diff --git a/apps/sample/src/assets/wallet-verification.hbs b/apps/sample/src/assets/wallet-verification.hbs new file mode 100644 index 0000000..44b0bee --- /dev/null +++ b/apps/sample/src/assets/wallet-verification.hbs @@ -0,0 +1,16 @@ + + + + + + + Wallet Verification + + + +
+

Hi {{name}},

+
+ + + \ No newline at end of file diff --git a/libs/extensions/src/mailer/adapters/ejs.adapter.ts b/libs/extensions/src/mailer/adapters/ejs.adapter.ts new file mode 100644 index 0000000..cb92235 --- /dev/null +++ b/libs/extensions/src/mailer/adapters/ejs.adapter.ts @@ -0,0 +1,78 @@ +import { inline } from '@css-inline/css-inline'; +import { + AsyncTemplateFunction, + ClientFunction, + TemplateFunction, + compile, +} from 'ejs'; +import * as fs from 'fs'; +import { get } from 'lodash'; +import * as path from 'path'; +import { + MailerOptions, + TemplateAdapter, + TemplateAdapterConfig, +} from '../../../../sdk/src/interfaces'; + +export class EjsAdapter implements TemplateAdapter { + private precompiledTemplates: { + [name: string]: TemplateFunction | AsyncTemplateFunction | ClientFunction; + } = {}; + private config: TemplateAdapterConfig = { + inlineCssOptions: {}, + inlineCssEnabled: true, + }; + + constructor(config?: TemplateAdapterConfig) { + Object.assign(this.config, config); + } + + public compile(mail: any, callback: any, mailerOptions: MailerOptions): void { + const { context, template } = mail.data; + const templateBaseDir = get(mailerOptions, 'template.dir', ''); + const templateExt = path.extname(template) || '.ejs'; + let templateName = path.basename(template, path.extname(template)); + const templateDir = path.isAbsolute(template) + ? path.dirname(template) + : path.join(templateBaseDir, path.dirname(template)); + const templatePath = path.join( + templateDir, + `${templateName}${templateExt}`, + ); + templateName = path + .relative(templateBaseDir, templatePath) + .replace(templateExt, ''); + + if (!this.precompiledTemplates[templateName]) { + try { + const template = fs.readFileSync(templatePath, 'utf8'); + this.precompiledTemplates[templateName] = compile(template, { + ...get(mailerOptions, 'template.ejs', {}), + filename: templatePath, + }); + } catch (error) { + return callback(error); + } + } + const rendered = this.precompiledTemplates[templateName](context); + + const render = (html: string) => { + if (this.config.inlineCssEnabled) { + try { + mail.data.html = inline(html, this.config.inlineCssOptions); + } catch (error) { + return callback(error); + } + } else { + mail.data.html = html; + } + return callback(); + }; + + if (typeof rendered === 'string') { + render(rendered); + } else { + rendered.then(render); + } + } +} diff --git a/libs/extensions/src/mailer/adapters/handlebars.adapter.ts b/libs/extensions/src/mailer/adapters/handlebars.adapter.ts new file mode 100644 index 0000000..2ca021d --- /dev/null +++ b/libs/extensions/src/mailer/adapters/handlebars.adapter.ts @@ -0,0 +1,117 @@ +import { inline } from '@css-inline/css-inline'; +import * as fs from 'fs'; +import * as glob from 'glob'; +import * as handlebars from 'handlebars'; +import { HelperDeclareSpec } from 'handlebars'; +import { get } from 'lodash'; +import * as path from 'path'; +import { + MailerOptions, + TemplateAdapter, + TemplateAdapterConfig, +} from '../../../../sdk/src/interfaces'; + +export class HandlebarsAdapter implements TemplateAdapter { + private precompiledTemplates: { + [name: string]: handlebars.TemplateDelegate; + } = {}; + + private config: TemplateAdapterConfig = { + inlineCssOptions: {}, + inlineCssEnabled: true, + }; + + constructor(helpers?: HelperDeclareSpec, config?: TemplateAdapterConfig) { + handlebars.registerHelper('concat', (...args) => { + args.pop; + return args.join(''); + }); + handlebars.registerHelper(helpers || {}); + Object.assign(this.config, config); + } + + public compile(mail: any, callback: any, mailerOptions: MailerOptions): void { + const precompile = (template: any, callback: any, options: any) => { + const templateBaseDir = get(options, 'dir', ''); + const templateExt = path.extname(template) || '.hbs'; + let templateName = path.basename(template, path.extname(template)); + const templateDir = path.isAbsolute(template) + ? path.dirname(template) + : path.join(templateBaseDir, path.dirname(template)); + const templatePath = path.join(templateDir, templateName + templateExt); + templateName = path + .relative(templateBaseDir, templatePath) + .replace(templateExt, ''); + if (!this.precompiledTemplates[templateName]) { + try { + const template = fs.readFileSync(templatePath, 'utf8'); + this.precompiledTemplates[templateName] = handlebars.compile( + template, + get(options, 'options', {}), + ); + } catch (error) { + return callback(error); + } + } + + return { + templateExt, + templateName, + templateDir, + templatePath, + }; + }; + const { templateName } = precompile( + mail.data.template, + callback, + mailerOptions.template, + ); + + const runtimeOptions = get(mailerOptions, 'options', { + partials: false, + data: {}, + }); + + if (runtimeOptions.partials) { + const partialPath = path + .join(runtimeOptions.partials.dir, '**', '*.hbs') + .replace(/\\/g, '/'); + const files = glob.sync(partialPath); + + files.forEach((file) => { + const { templateName, templatePath } = precompile( + file, + () => {}, + runtimeOptions.partials, + ); + const templateDir = path.relative( + runtimeOptions.partials.dir, + path.dirname(templatePath), + ); + handlebars.registerPartial( + path.join(templateDir, templateName), + fs.readFileSync(templatePath, 'utf8'), + ); + }); + } + + const rendered = this.precompiledTemplates[templateName]( + mail.data.context, + { + ...runtimeOptions, + partials: this.precompiledTemplates, + }, + ); + + if (this.config.inlineCssEnabled) { + try { + mail.data.html = inline(rendered, this.config.inlineCssOptions); + } catch (error) { + callback(error); + } + } else { + mail.data.html = rendered; + } + return callback(); + } +} diff --git a/libs/extensions/src/mailer/adapters/index.ts b/libs/extensions/src/mailer/adapters/index.ts new file mode 100644 index 0000000..2b16fbb --- /dev/null +++ b/libs/extensions/src/mailer/adapters/index.ts @@ -0,0 +1,2 @@ +export * from './ejs.adapter'; +export * from './handlebars.adapter'; diff --git a/libs/extensions/src/mailer/index.ts b/libs/extensions/src/mailer/index.ts new file mode 100644 index 0000000..e9ccf48 --- /dev/null +++ b/libs/extensions/src/mailer/index.ts @@ -0,0 +1,5 @@ +export * from './adapters'; +export * from './mailer-core.module'; +export * from './mailer-transport.factory'; +export * from './mailer.module'; +export * from './mailer.service'; diff --git a/libs/extensions/src/mailer/mailer-core.module.ts b/libs/extensions/src/mailer/mailer-core.module.ts new file mode 100644 index 0000000..4bdc65a --- /dev/null +++ b/libs/extensions/src/mailer/mailer-core.module.ts @@ -0,0 +1,77 @@ +import { + DynamicModule, + Global, + Module, + Provider, + ValueProvider, +} from '@nestjs/common'; +import { MAILER_OPTIONS } from '../../../sdk/src/constants'; +import { + MailerAsyncOptions, + MailerOptions, + MailerOptionsFactory, +} from '../../../sdk/src/interfaces'; +import { MailerService } from './mailer.service'; + +@Global() +@Module({}) +export class MailerCoreModule { + public static forRoot(options: MailerOptions): DynamicModule { + const MailerOptionsProvider: ValueProvider = { + provide: MAILER_OPTIONS, + useValue: options, + }; + + return { + module: MailerCoreModule, + providers: [MailerOptionsProvider, MailerService], + exports: [MailerService], + }; + } + + public static forRootAsync(options: MailerAsyncOptions): DynamicModule { + const providers: Provider[] = this.createAsyncProviders(options); + return { + module: MailerCoreModule, + providers: [ + ...providers, + MailerService, + ...(options.extraProviders || []), + ], + imports: options.imports, + exports: [MailerService], + }; + } + + private static createAsyncProviders(options: MailerAsyncOptions): Provider[] { + const providers: Provider[] = [this.createAsyncOptionsProvider(options)]; + + if (options.useClass) { + providers.push({ + provide: options.useClass, + useClass: options.useClass, + }); + } + return providers; + } + + public static createAsyncOptionsProvider( + options: MailerAsyncOptions, + ): Provider { + if (options.useFactory) { + return { + provide: MAILER_OPTIONS, + useFactory: options.useFactory, + inject: options.inject || [], + }; + } + + return { + provide: MAILER_OPTIONS, + useFactory: async (optionsFactory: MailerOptionsFactory) => { + return optionsFactory.createMailerOptions(); + }, + inject: [options?.useExisting! || options?.useClass!], + }; + } +} diff --git a/libs/extensions/src/mailer/mailer-transport.factory.ts b/libs/extensions/src/mailer/mailer-transport.factory.ts new file mode 100644 index 0000000..7f022f7 --- /dev/null +++ b/libs/extensions/src/mailer/mailer-transport.factory.ts @@ -0,0 +1,21 @@ +import { Inject } from '@nestjs/common'; +import { MAILER_OPTIONS } from '@rumsan/sdk/constants'; +import { createTransport } from 'nodemailer'; +import { + MailerTransportFactory as IMailerTransportFactory, + MailerOptions, +} from '../../../sdk/src/interfaces'; +import { TransportType } from '../../../sdk/src/types'; + +export class MailerTransportFactory implements IMailerTransportFactory { + constructor( + @Inject(MAILER_OPTIONS) private readonly options: MailerOptions, + ) {} + + public createTransport(opts?: TransportType): any { + return createTransport( + opts || this.options.transport, + this.options.defaults, + ); + } +} diff --git a/libs/extensions/src/mailer/mailer.module.ts b/libs/extensions/src/mailer/mailer.module.ts new file mode 100644 index 0000000..97c2ca9 --- /dev/null +++ b/libs/extensions/src/mailer/mailer.module.ts @@ -0,0 +1,19 @@ +import { DynamicModule, Module } from '@nestjs/common'; +import { MailerAsyncOptions, MailerOptions } from '../../../sdk/src/interfaces'; +import { MailerCoreModule } from './mailer-core.module'; +@Module({}) +export class MailerModule { + public static forRoot(options?: MailerOptions): DynamicModule { + return { + module: MailerModule, + imports: [MailerCoreModule.forRoot(options!)], + }; + } + + public static forRootAsync(options: MailerAsyncOptions): DynamicModule { + return { + module: MailerModule, + imports: [MailerCoreModule.forRootAsync(options)], + }; + } +} diff --git a/libs/extensions/src/mailer/mailer.service.ts b/libs/extensions/src/mailer/mailer.service.ts new file mode 100644 index 0000000..97a1ae0 --- /dev/null +++ b/libs/extensions/src/mailer/mailer.service.ts @@ -0,0 +1,156 @@ +import { Inject, Injectable, Logger, Optional } from '@nestjs/common'; +import { defaultsDeep, get } from 'lodash'; +import { SentMessageInfo, Transporter } from 'nodemailer'; +import * as smtpTransport from 'nodemailer/lib/smtp-transport'; +import { + MAILER_OPTIONS, + MAILER_TRANSPORT_FACTORY, +} from '../../../sdk/src/constants'; +import { + MailerTransportFactory as IMailerTransportFactory, + ISendMailOptions, + MailerOptions, + TemplateAdapter, +} from '../../../sdk/src/interfaces'; +import { MailerTransportFactory } from './mailer-transport.factory'; +import previewEmail = require('preview-email'); + +@Injectable() +export class MailerService { + private transporter!: Transporter; + private transporters = new Map(); + private templateAdapter: any; + private initTemplateAdapter( + templateAdapter: TemplateAdapter, + transporter: Transporter, + ): void { + if (templateAdapter) { + transporter.use('compile', (mail, callback) => { + if (mail.data.html) { + return callback(); + } + return templateAdapter.compile(mail, callback, this.mailerOptions); + }); + + if (this.mailerOptions.preview) { + transporter.use('stream', (mail, callback) => { + return previewEmail(mail.data, this.mailerOptions.preview) + .then(() => callback()) + .catch(callback); + }); + } + } + } + + private readonly mailerLogger = new Logger(MailerService?.name); + + constructor( + @Inject(MAILER_OPTIONS) private readonly mailerOptions: MailerOptions, + @Optional() + @Inject(MAILER_TRANSPORT_FACTORY) + private readonly transportFactory: IMailerTransportFactory, + ) { + if (!transportFactory) { + this.transportFactory = new MailerTransportFactory(mailerOptions); + } + + if ( + (!mailerOptions.transport || + Object.keys(mailerOptions.transport).length <= 0) && + !mailerOptions.transports + ) { + throw new Error( + 'Make sure to provide a nodemailer transport configuration object, connection url or a transport plugin instance.', + ); + } + + this.templateAdapter = get(this.mailerOptions, 'template.adapter'); + if (this.mailerOptions.preview) { + const defaults = { open: { wait: false } }; + this.mailerOptions.preview = + typeof this.mailerOptions.preview === 'boolean' + ? defaults + : defaultsDeep(this.mailerOptions.preview, defaults); + } + + if (mailerOptions.transports) { + Object.keys(mailerOptions.transports).forEach((name) => { + const transporter = this.transportFactory.createTransport( + this.mailerOptions.transports![name], + ); + this.transporters.set(name, transporter); + this.verifyTransporter(transporter, name); + }); + } + + if (mailerOptions.transport) { + this.transporter = this.transportFactory.createTransport(); + this.verifyTransporter(this.transporter); + this.initTemplateAdapter(this.templateAdapter, this.transporter); + } + } + + private verifyTransporter(transporter: Transporter, name?: string): void { + const transportName = name ? ` '${name}'` : ''; + transporter + .verify() + .then(() => + this.mailerLogger.log(`Transporter ${transportName} is ready`), + ) + .catch((error) => + this.mailerLogger.error( + `Error occurred while verifying the transporter${transportName}: ${error.message}`, + ), + ); + } + + public async verifyAllTransporters() { + const transporters = [...this.transporters.values(), this.transporter]; + const transportersVerified = await Promise.all( + transporters.map((transporter) => + transporter.verify().catch(() => false), + ), + ); + return transportersVerified.every((verified: any) => verified); + } + + public async sendMail( + sendMailOptions: ISendMailOptions, + ): Promise { + if (sendMailOptions.transporterName) { + if ( + this.transporters && + this.transporters.get(sendMailOptions.transporterName) + ) { + return await this.transporters + .get(sendMailOptions.transporterName)! + .sendMail(sendMailOptions); + } else { + throw new ReferenceError( + `Transporters object doesn't have ${sendMailOptions.transporterName} key`, + ); + } + } else { + if (this.transporter) { + return await this.transporter.sendMail(sendMailOptions); + } else { + throw new ReferenceError(`Transporter object is not defined`); + } + } + } + + addTransport( + transporterName: string, + config: string | smtpTransport | smtpTransport.Options, + ): string { + this.transporters.set( + transporterName, + this.transportFactory.createTransport(config), + ); + this.initTemplateAdapter( + this.templateAdapter, + this.transporters.get(transporterName)!, + ); + return transporterName; + } +} diff --git a/libs/extensions/src/settings/settings.controller.ts b/libs/extensions/src/settings/settings.controller.ts index 9f2c83c..dc15e2a 100644 --- a/libs/extensions/src/settings/settings.controller.ts +++ b/libs/extensions/src/settings/settings.controller.ts @@ -6,7 +6,7 @@ import { SettingsService } from './settings.service'; @Controller('settings') @ApiTags('Settings') export class SettingsController { - constructor(private readonly settingsService: SettingsService) { } + constructor(private readonly settingsService: SettingsService) {} @Get('') listPublic() { diff --git a/libs/extensions/src/settings/settings.service.spec.ts b/libs/extensions/src/settings/settings.service.spec.ts index 9f5bca4..92494b1 100644 --- a/libs/extensions/src/settings/settings.service.spec.ts +++ b/libs/extensions/src/settings/settings.service.spec.ts @@ -1,63 +1,102 @@ import { SettingsService } from './settings.service'; describe('SettingsService', () => { - let service: SettingsService; - let prismaMock: any; - - beforeEach(() => { - prismaMock = { - setting: { - findMany: jest.fn(), - findUnique: jest.fn(), - }, - }; - service = new SettingsService(prismaMock); - }); + let service: SettingsService; + let prismaMock: any; - it('should return public settings', async () => { - const mockSettings = [ - { name: 'SMTP', value: { "HOST": "smtp.gmail.com", "PORT": 465, "SECURE": true, "PASSWORD": "test", "USERNAME": "test" }, isPrivate: false }, - { name: 'SMTP1', value: { "HOST": "smtp.gmail.com", "PORT": 465, "SECURE": true, "PASSWORD": "test", "USERNAME": "test" }, isPrivate: false }, - ]; + beforeEach(() => { + prismaMock = { + setting: { + findMany: jest.fn(), + findUnique: jest.fn(), + }, + }; + service = new SettingsService(prismaMock); + }); - prismaMock.setting.findMany.mockResolvedValue(mockSettings); + it('should return public settings', async () => { + const mockSettings = [ + { + name: 'SMTP', + value: { + HOST: 'smtp.gmail.com', + PORT: 465, + SECURE: true, + PASSWORD: 'test', + USERNAME: 'test', + }, + isPrivate: false, + }, + { + name: 'SMTP1', + value: { + HOST: 'smtp.gmail.com', + PORT: 465, + SECURE: true, + PASSWORD: 'test', + USERNAME: 'test', + }, + isPrivate: false, + }, + ]; - const result = await service.listPublic(); - console.log(result) + prismaMock.setting.findMany.mockResolvedValue(mockSettings); - expect(result).toEqual({ - SMTP: { "HOST": "smtp.gmail.com", "PORT": 465, "SECURE": true, "PASSWORD": "test", "USERNAME": "test" }, - SMTP1: { "HOST": "smtp.gmail.com", "PORT": 465, "SECURE": true, "PASSWORD": "test", "USERNAME": "test" }, - }); - expect(prismaMock.setting.findMany).toHaveBeenCalledWith({ - where: { isPrivate: false }, - }); - }); + const result = await service.listPublic(); + console.log(result); + expect(result).toEqual({ + SMTP: { + HOST: 'smtp.gmail.com', + PORT: 465, + SECURE: true, + PASSWORD: 'test', + USERNAME: 'test', + }, + SMTP1: { + HOST: 'smtp.gmail.com', + PORT: 465, + SECURE: true, + PASSWORD: 'test', + USERNAME: 'test', + }, + }); + expect(prismaMock.setting.findMany).toHaveBeenCalledWith({ + where: { isPrivate: false }, + }); + }); - it('should return a public setting by name', async () => { - const mockSetting = { name: 'SMTP', value: { "HOST": "smtp.gmail.com", "PORT": 465, "SECURE": true, "PASSWORD": "test", "USERNAME": "test" }, isPrivate: false }; + it('should return a public setting by name', async () => { + const mockSetting = { + name: 'SMTP', + value: { + HOST: 'smtp.gmail.com', + PORT: 465, + SECURE: true, + PASSWORD: 'test', + USERNAME: 'test', + }, + isPrivate: false, + }; - prismaMock.setting.findUnique.mockResolvedValue(mockSetting); + prismaMock.setting.findUnique.mockResolvedValue(mockSetting); - const result = await service.getPublic('SMTP'); + const result = await service.getPublic('SMTP'); - expect(result).toEqual(mockSetting); - expect(prismaMock.setting.findUnique).toHaveBeenCalledWith({ - where: { name: 'SMTP', isPrivate: false }, - }); + expect(result).toEqual(mockSetting); + expect(prismaMock.setting.findUnique).toHaveBeenCalledWith({ + where: { name: 'SMTP', isPrivate: false }, }); + }); - it('should throw an error if a public setting is not found', async () => { - prismaMock.setting.findUnique.mockResolvedValue(null); - - + it('should throw an error if a public setting is not found', async () => { + prismaMock.setting.findUnique.mockResolvedValue(null); - await expect(service.getPublic('NONEXISTENT')).rejects.toThrow( - "Public setting 'NONEXISTENT' not found" - ); - expect(prismaMock.setting.findUnique).toHaveBeenCalledWith({ - where: { name: 'NONEXISTENT', isPrivate: false }, - }); + await expect(service.getPublic('NONEXISTENT')).rejects.toThrow( + "Public setting 'NONEXISTENT' not found", + ); + expect(prismaMock.setting.findUnique).toHaveBeenCalledWith({ + where: { name: 'NONEXISTENT', isPrivate: false }, }); -}); \ No newline at end of file + }); +}); diff --git a/libs/extensions/src/settings/settings.service.ts b/libs/extensions/src/settings/settings.service.ts index 5b31bfb..7932633 100644 --- a/libs/extensions/src/settings/settings.service.ts +++ b/libs/extensions/src/settings/settings.service.ts @@ -52,7 +52,7 @@ type PrismaClientType = Omit< @Injectable() export class SettingsService { private static data: any = {}; - constructor(private prisma: PrismaService) { } + constructor(private prisma: PrismaService) {} public static get(path: string) { const keys = path.split('.'); diff --git a/libs/sdk/src/constants/index.ts b/libs/sdk/src/constants/index.ts index 3e588b8..eb4fcec 100755 --- a/libs/sdk/src/constants/index.ts +++ b/libs/sdk/src/constants/index.ts @@ -1,3 +1,6 @@ export const CONSTANTS = { CLIENT_TOKEN_LIFETIME: 600, }; + +export const MAILER_OPTIONS = 'MAILER_OPTIONS'; +export const MAILER_TRANSPORT_FACTORY = 'MAILER_TRANSPORT_FACTORY'; diff --git a/libs/sdk/src/interfaces/index.ts b/libs/sdk/src/interfaces/index.ts new file mode 100644 index 0000000..ecd4faf --- /dev/null +++ b/libs/sdk/src/interfaces/index.ts @@ -0,0 +1,7 @@ +export * from './mailer-async-options.interface'; +export * from './mailer-options-factory.interface'; +export * from './mailer-options.interface'; +export * from './mailer-transport-factory.interface'; +export * from './send-mail-options.interface'; +export * from './template-adapter-config.interface'; +export * from './template-adapter.interface'; diff --git a/libs/sdk/src/interfaces/mailer-async-options.interface.ts b/libs/sdk/src/interfaces/mailer-async-options.interface.ts new file mode 100644 index 0000000..5390b74 --- /dev/null +++ b/libs/sdk/src/interfaces/mailer-async-options.interface.ts @@ -0,0 +1,11 @@ +import { ModuleMetadata, Provider, Type } from '@nestjs/common/interfaces'; +import { MailerOptionsFactory } from './mailer-options-factory.interface'; +import { MailerOptions } from './mailer-options.interface'; + +export interface MailerAsyncOptions extends Pick { + inject?: any[]; + useClass?: Type; + useExisting?: Type; + useFactory?: (...args: any[]) => Promise | MailerOptions; + extraProviders?: Provider[]; +} diff --git a/libs/sdk/src/interfaces/mailer-options-factory.interface.ts b/libs/sdk/src/interfaces/mailer-options-factory.interface.ts new file mode 100644 index 0000000..02e658f --- /dev/null +++ b/libs/sdk/src/interfaces/mailer-options-factory.interface.ts @@ -0,0 +1,5 @@ +import { MailerOptions } from './mailer-options.interface'; + +export interface MailerOptionsFactory { + createMailerOptions(): Promise | MailerOptions; +} diff --git a/libs/sdk/src/interfaces/mailer-options.interface.ts b/libs/sdk/src/interfaces/mailer-options.interface.ts new file mode 100644 index 0000000..19668ff --- /dev/null +++ b/libs/sdk/src/interfaces/mailer-options.interface.ts @@ -0,0 +1,21 @@ +import * as SMTPTransport from 'nodemailer/lib/smtp-transport'; +import { Options, TransportType } from '../types'; +import { TemplateAdapter } from './template-adapter.interface'; + +export interface MailerOptions { + defaults?: Options; + transport?: TransportType; + transports?: { + [name: string]: SMTPTransport | SMTPTransport.Options | string; + }; + template?: { + dir?: string; + adapter?: TemplateAdapter; + options?: { [name: string]: any }; + }; + options?: { [name: string]: any }; + preview?: Partial<{ + dir: string; + open: boolean | { wait: boolean; app: string | string[] }; + }>; +} diff --git a/libs/sdk/src/interfaces/mailer-transport-factory.interface.ts b/libs/sdk/src/interfaces/mailer-transport-factory.interface.ts new file mode 100644 index 0000000..3374623 --- /dev/null +++ b/libs/sdk/src/interfaces/mailer-transport-factory.interface.ts @@ -0,0 +1,6 @@ +import * as Mail from 'nodemailer/lib/mailer'; +import { TransportType } from '../types'; + +export interface MailerTransportFactory { + createTransport(opts?: TransportType): Mail; +} diff --git a/libs/sdk/src/interfaces/send-mail-options.interface.ts b/libs/sdk/src/interfaces/send-mail-options.interface.ts new file mode 100644 index 0000000..5c7a078 --- /dev/null +++ b/libs/sdk/src/interfaces/send-mail-options.interface.ts @@ -0,0 +1,41 @@ +import { SendMailOptions } from 'nodemailer'; +import * as DKIM from 'nodemailer/lib/dkim'; +import { Attachment } from 'nodemailer/lib/mailer'; +import { TextEncoding } from '../types'; + +export interface Address { + name: string; + address: string; +} + +export interface AttachmentLikeObject { + path: string; +} + +export interface ISendMailOptions extends SendMailOptions { + to?: string | Address | Array; + cc?: string | Address | Array; + bcc?: string | Address | Array; + replyTo?: string | Address | Array; + inReplyTo?: string | Address; + from?: string | Address; + subject?: string; + text?: string | Buffer | AttachmentLikeObject; + html?: string | Buffer; + sender?: string | Address; + raw?: string | Buffer; + textEncoding?: TextEncoding; + encoding?: string; + references?: string | string[]; + date?: Date | string; + headers?: { + [key: string]: string | string[] | { prepared: boolean; value: string }; + }; + context?: { + [name: string]: any; + }; + transporterName?: string; + template?: string; + attachments?: Attachment[]; + dkim?: DKIM.Options; +} diff --git a/libs/sdk/src/interfaces/template-adapter-config.interface.ts b/libs/sdk/src/interfaces/template-adapter-config.interface.ts new file mode 100644 index 0000000..c746569 --- /dev/null +++ b/libs/sdk/src/interfaces/template-adapter-config.interface.ts @@ -0,0 +1,5 @@ +import { Options } from '@css-inline/css-inline'; +export interface TemplateAdapterConfig { + inlineCssOptions?: Options; + inlineCssEnabled?: boolean; +} diff --git a/libs/sdk/src/interfaces/template-adapter.interface.ts b/libs/sdk/src/interfaces/template-adapter.interface.ts new file mode 100644 index 0000000..5083577 --- /dev/null +++ b/libs/sdk/src/interfaces/template-adapter.interface.ts @@ -0,0 +1,10 @@ +/** Interfaces **/ +import { MailerOptions } from './mailer-options.interface'; + +export interface TemplateAdapter { + compile( + mail: any, + callback: (err?: any, body?: string) => any, + options: MailerOptions, + ): void; +} diff --git a/libs/sdk/src/types/index.ts b/libs/sdk/src/types/index.ts index 248c201..50872ec 100755 --- a/libs/sdk/src/types/index.ts +++ b/libs/sdk/src/types/index.ts @@ -3,6 +3,7 @@ export * from './challenge.types'; export * from './controllerFunction.types'; export * from './error.types'; export * from './loginResponse.types'; +export * from './mailer.types'; export * from './otp.types'; export * from './pagination.types'; export * from './permission.types'; diff --git a/libs/sdk/src/types/mailer.types.ts b/libs/sdk/src/types/mailer.types.ts new file mode 100644 index 0000000..3b54e2b --- /dev/null +++ b/libs/sdk/src/types/mailer.types.ts @@ -0,0 +1,33 @@ +import { Transport, TransportOptions } from 'nodemailer'; +import * as JSONTransport from 'nodemailer/lib/json-transport'; +import * as SendmailTransport from 'nodemailer/lib/sendmail-transport'; +import * as SESTransport from 'nodemailer/lib/ses-transport'; +import * as SMTPPool from 'nodemailer/lib/smtp-pool'; +import * as SMTPTransport from 'nodemailer/lib/smtp-transport'; +import * as StreamTransport from 'nodemailer/lib/stream-transport'; + +export type Options = + | SMTPTransport.Options + | SMTPPool.Options + | SendmailTransport.Options + | StreamTransport.Options + | JSONTransport.Options + | SESTransport.Options + | TransportOptions; + +export type TransportType = + | Options + | SMTPTransport + | SMTPPool + | SendmailTransport + | StreamTransport + | JSONTransport + | SESTransport + | Transport + | string; + +export type TextEncoding = 'quoted-printable' | 'base64'; + +export type Headers = + | { [key: string]: string | string[] | { prepared: boolean; value: string } } + | Array<{ key: string; value: string }>; diff --git a/libs/user/src/lib/auths/strategy/jwt.strategy.ts b/libs/user/src/lib/auths/strategy/jwt.strategy.ts index 982bc45..237209a 100755 --- a/libs/user/src/lib/auths/strategy/jwt.strategy.ts +++ b/libs/user/src/lib/auths/strategy/jwt.strategy.ts @@ -7,7 +7,10 @@ import { getSecret } from '../../utils/config.utils'; @Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { - constructor(config: ConfigService, private prisma: PrismaService) { + constructor( + config: ConfigService, + private prisma: PrismaService, + ) { // Extrac Bearer Token from Authorization header request super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), diff --git a/package.json b/package.json index 1c5a6af..12088e5 100755 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "private": true, "dependencies": { "@casl/ability": "^6.5.0", + "@css-inline/css-inline": "^0.13.1", "@nestjs/common": "^10.3.3", "@nestjs/config": "^3.2.0", "@nestjs/core": "^10.3.3", @@ -36,10 +37,13 @@ "axios": "^1.6.7", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", + "ejs": "^3.1.9", + "handlebars": "^4.7.8", "ioredis": "^5.3.2", "nest-winston": "^1.9.4", "nodemailer": "^6.9.9", "passport-jwt": "^4.0.1", + "preview-email": "^3.0.19", "react": "^18.2.0", "reflect-metadata": "^0.2.1", "rxjs": "^7.8.1", @@ -66,9 +70,13 @@ "@svgr/webpack": "^8.1.0", "@swc-node/register": "~1.8.0", "@swc/core": "~1.4.2", + "@types/ejs": "^3.1.5", + "@types/glob": "^8.1.0", "@types/jest": "^29.5.12", "@types/node": "20.11.19", + "@types/nodemailer": "^6.4.14", "@types/passport-jwt": "^4.0.1", + "@types/preview-email": "^3.0.4", "@types/react": "^18.2.60", "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^7.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d43f6b6..e6d780d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ dependencies: '@casl/ability': specifier: ^6.5.0 version: 6.7.0 + '@css-inline/css-inline': + specifier: ^0.13.1 + version: 0.13.1 '@nestjs/common': specifier: ^10.3.3 version: 10.3.3(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.1)(rxjs@7.8.1) @@ -56,6 +59,12 @@ dependencies: class-validator: specifier: ^0.14.1 version: 0.14.1 + ejs: + specifier: ^3.1.9 + version: 3.1.9 + handlebars: + specifier: ^4.7.8 + version: 4.7.8 ioredis: specifier: ^5.3.2 version: 5.3.2 @@ -68,6 +77,9 @@ dependencies: passport-jwt: specifier: ^4.0.1 version: 4.0.1 + preview-email: + specifier: ^3.0.19 + version: 3.0.19 react: specifier: ^18.2.0 version: 18.2.0 @@ -142,15 +154,27 @@ devDependencies: '@swc/core': specifier: ~1.4.2 version: 1.4.5 + '@types/ejs': + specifier: ^3.1.5 + version: 3.1.5 + '@types/glob': + specifier: ^8.1.0 + version: 8.1.0 '@types/jest': specifier: ^29.5.12 version: 29.5.12 '@types/node': specifier: 20.11.19 version: 20.11.19 + '@types/nodemailer': + specifier: ^6.4.14 + version: 6.4.14 '@types/passport-jwt': specifier: ^4.0.1 version: 4.0.1 + '@types/preview-email': + specifier: ^3.0.4 + version: 3.0.4 '@types/react': specifier: ^18.2.60 version: 18.2.64 @@ -515,12 +539,10 @@ packages: /@babel/helper-string-parser@7.23.4: resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} engines: {node: '>=6.9.0'} - dev: true /@babel/helper-validator-identifier@7.22.20: resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} engines: {node: '>=6.9.0'} - dev: true /@babel/helper-validator-option@7.23.5: resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} @@ -562,7 +584,6 @@ packages: hasBin: true dependencies: '@babel/types': 7.24.0 - dev: true /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.23.3(@babel/core@7.24.0): resolution: {integrity: sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==} @@ -1619,7 +1640,6 @@ packages: '@babel/helper-string-parser': 7.23.4 '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 - dev: true /@bcoe/v8-coverage@0.2.3: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} @@ -1643,6 +1663,112 @@ packages: '@jridgewell/trace-mapping': 0.3.9 dev: true + /@css-inline/css-inline-android-arm-eabi@0.13.1: + resolution: {integrity: sha512-IpELOLMh6PIec6/2V9wtaIyWmoed7v5H3XA3N91sMdNqxX7B9FIiEEIBeg9lq+6f1rQWaC7/iC7gp0Ep5QChRA==} + engines: {node: '>= 10'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@css-inline/css-inline-android-arm64@0.13.1: + resolution: {integrity: sha512-fmcYqIXKm9r1DLVY64gMi09fKz+u3lt49u+093S1l+u0ES77IfImlbPWJxqtbUIZG7CELj5jcbfdgK9H8Z0ohg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@css-inline/css-inline-darwin-arm64@0.13.1: + resolution: {integrity: sha512-2+2S7Qr1klU1rWQK5/Ru6XNyRvzXdjqCSM5FBdtT/mfKGCKQKAuh17kg9FNm4OOnCv5D8sNO24CZdeo0+xYL6A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@css-inline/css-inline-darwin-x64@0.13.1: + resolution: {integrity: sha512-P078CMwyDLb7um3i5jkULsOQj0b9P0E5RVXjxQLoxQFromJpGABbwHdOD8xExo5f+jnCgK7AaVH4EPPj2UT5TQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@css-inline/css-inline-linux-arm-gnueabihf@0.13.1: + resolution: {integrity: sha512-Mcxqz0Xg+yStGR0ZMiRZ4NnINcsEXwMt1C5GXNaFbp/cj7jIrfsZ9TSqCzD38yd2v3L44i1EP1wtV3GthI66Tw==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@css-inline/css-inline-linux-arm64-gnu@0.13.1: + resolution: {integrity: sha512-s42N8BUJKX+LSdjlJkRQdxE+0OrjW8fB6gnWbXs3omGPHQEi8mYRlfv0LDHWffEE9A5YagK34S6vycJIk4R1Qw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@css-inline/css-inline-linux-arm64-musl@0.13.1: + resolution: {integrity: sha512-y/WJ68ZQmSp2PRKL1MNYVxTn0wVsBDiKsWxmObl9AvgXR508Cj0334/EWfGseGc6nd3wa7pnnPnJ6exZZ1avSw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@css-inline/css-inline-linux-x64-gnu@0.13.1: + resolution: {integrity: sha512-cozfGHUYfrq0sxp0GVNxkqkOCHnl0oBsCi8PmWaKSnLfo/rpVe9KzTOpo6loU9svAaxOm3injhyImvre6Zu0ig==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@css-inline/css-inline-linux-x64-musl@0.13.1: + resolution: {integrity: sha512-RFwWrFIKRJsU6YsXQyLsjirn/6sNezMiBzr9UoMwmLQYC/Ia9dXzJZtWwB0KThpnCiHDUR+fTEj2GrmUleRoVw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@css-inline/css-inline-win32-x64-msvc@0.13.1: + resolution: {integrity: sha512-+LxH/kkDYWOcyJsutBM/0jFxiF/lYhrG1mu1K1/85p2Bc9Aldd/dGBmGu7GSNQwGsKYZLWsIeNNdehT7YfOj5A==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@css-inline/css-inline@0.13.1: + resolution: {integrity: sha512-X/apnCEVKPujmTdXOL0lWM74ac9+QRZnM2BmoV4Wt06DTy61wSr6LEJEbPX4BnFxRChfm6KnbZcAUqifBZFFRw==} + engines: {node: '>= 10'} + optionalDependencies: + '@css-inline/css-inline-android-arm-eabi': 0.13.1 + '@css-inline/css-inline-android-arm64': 0.13.1 + '@css-inline/css-inline-darwin-arm64': 0.13.1 + '@css-inline/css-inline-darwin-x64': 0.13.1 + '@css-inline/css-inline-linux-arm-gnueabihf': 0.13.1 + '@css-inline/css-inline-linux-arm64-gnu': 0.13.1 + '@css-inline/css-inline-linux-arm64-musl': 0.13.1 + '@css-inline/css-inline-linux-x64-gnu': 0.13.1 + '@css-inline/css-inline-linux-x64-musl': 0.13.1 + '@css-inline/css-inline-win32-x64-msvc': 0.13.1 + dev: false + /@cypress/request@3.0.1: resolution: {integrity: sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==} engines: {node: '>= 6'} @@ -3330,6 +3456,13 @@ packages: '@scure/base': 1.1.5 dev: false + /@selderee/plugin-htmlparser2@0.11.0: + resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==} + dependencies: + domhandler: 5.0.3 + selderee: 0.11.0 + dev: false + /@sinclair/typebox@0.27.8: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: true @@ -3752,6 +3885,10 @@ packages: '@types/node': 20.11.19 dev: true + /@types/ejs@3.1.5: + resolution: {integrity: sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==} + dev: true + /@types/eslint-scope@3.7.7: resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} dependencies: @@ -3788,6 +3925,13 @@ packages: '@types/serve-static': 1.15.5 dev: true + /@types/glob@8.1.0: + resolution: {integrity: sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==} + dependencies: + '@types/minimatch': 5.1.2 + '@types/node': 20.11.19 + dev: true + /@types/graceful-fs@4.1.9: resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} dependencies: @@ -3847,6 +3991,13 @@ packages: resolution: {integrity: sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==} dev: true + /@types/mailparser@3.4.4: + resolution: {integrity: sha512-C6Znp2QVS25JqtuPyxj38Qh+QoFcLycdxsvcc6IZCGekhaMBzbdTXzwGzhGoYb3TfKu8IRCNV0sV1o3Od97cEQ==} + dependencies: + '@types/node': 20.11.19 + iconv-lite: 0.6.3 + dev: true + /@types/mime@1.3.5: resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} dev: true @@ -3855,6 +4006,10 @@ packages: resolution: {integrity: sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw==} dev: true + /@types/minimatch@5.1.2: + resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + dev: true + /@types/node-forge@1.3.11: resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} dependencies: @@ -3866,6 +4021,12 @@ packages: dependencies: undici-types: 5.26.5 + /@types/nodemailer@6.4.14: + resolution: {integrity: sha512-fUWthHO9k9DSdPCSPRqcu6TWhYyxTBg382vlNIttSe9M7XfsT06y0f24KHXtbnijPGGRIcVvdKHTNikOI6qiHA==} + dependencies: + '@types/node': 20.11.19 + dev: true + /@types/parse-json@4.0.2: resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} dev: true @@ -3890,6 +4051,14 @@ packages: '@types/express': 4.17.21 dev: true + /@types/preview-email@3.0.4: + resolution: {integrity: sha512-7FT5bPnb7siEPzv9f1lgww306QVieNnXEBdNJi+Jq5MtB5iIKM/bAdki8CZTbCRY3WvUeaNLKgvEGKA07NXFuQ==} + dependencies: + '@types/mailparser': 3.4.4 + '@types/node': 20.11.19 + '@types/nodemailer': 6.4.14 + dev: true + /@types/prop-types@15.7.11: resolution: {integrity: sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==} @@ -4592,6 +4761,12 @@ packages: engines: {node: '>=0.4.0'} dev: true + /acorn@7.4.1: + resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: false + /acorn@8.11.3: resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} engines: {node: '>=0.4.0'} @@ -4656,6 +4831,14 @@ packages: require-from-string: 2.0.2 uri-js: 4.4.1 + /alce@1.2.0: + resolution: {integrity: sha512-XppPf2S42nO2WhvKzlwzlfcApcXHzjlod30pKmcWjRgLOtqoe5DMuqdiYoM6AgyXksc6A6pV4v1L/WW217e57w==} + engines: {node: '>=0.8.0'} + dependencies: + esprima: 1.2.5 + estraverse: 1.9.3 + dev: false + /ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} @@ -4747,12 +4930,20 @@ packages: engines: {node: '>=12'} dev: true + /asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + dev: false + /asn1@0.2.6: resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} dependencies: safer-buffer: 2.1.2 dev: true + /assert-never@1.2.1: + resolution: {integrity: sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==} + dev: false + /assert-plus@1.0.0: resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} engines: {node: '>=0.8'} @@ -4971,9 +5162,15 @@ packages: babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.0) dev: true + /babel-walk@3.0.0-canary-5: + resolution: {integrity: sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==} + engines: {node: '>= 10.0.0'} + dependencies: + '@babel/types': 7.24.0 + dev: false + /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -5063,13 +5260,11 @@ packages: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - dev: true /brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} dependencies: balanced-match: 1.0.2 - dev: true /braces@3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} @@ -5198,6 +5393,14 @@ packages: supports-color: 5.5.0 dev: true + /chalk@3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: false + /chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -5210,6 +5413,12 @@ packages: engines: {node: '>=10'} dev: true + /character-parser@2.2.0: + resolution: {integrity: sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==} + dependencies: + is-regex: 1.1.4 + dev: false + /chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -5233,7 +5442,6 @@ packages: /ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} - dev: true /cjs-module-lexer@1.2.3: resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==} @@ -5409,7 +5617,6 @@ packages: /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true /concat-stream@1.6.2: resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} @@ -5432,6 +5639,13 @@ packages: /consola@2.15.3: resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} + /constantinople@4.0.1: + resolution: {integrity: sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==} + dependencies: + '@babel/parser': 7.24.0 + '@babel/types': 7.24.0 + dev: false + /content-disposition@0.5.4: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} engines: {node: '>= 0.6'} @@ -5573,6 +5787,17 @@ packages: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} dev: true + /cross-spawn@6.0.5: + resolution: {integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==} + engines: {node: '>=4.8'} + dependencies: + nice-try: 1.0.5 + path-key: 2.0.1 + semver: 5.7.2 + shebang-command: 1.2.0 + which: 1.3.1 + dev: false + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -5796,6 +6021,11 @@ packages: optional: true dev: true + /deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + dev: false + /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true @@ -5803,7 +6033,6 @@ packages: /deepmerge@4.3.1: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} - dev: true /default-gateway@6.0.3: resolution: {integrity: sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==} @@ -5852,10 +6081,14 @@ packages: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + /detect-indent@6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + dev: false + /detect-newline@3.1.0: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} - dev: true /detect-node@2.1.0: resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} @@ -5888,6 +6121,14 @@ packages: path-type: 4.0.0 dev: true + /display-notification@2.0.0: + resolution: {integrity: sha512-TdmtlAcdqy1NU+j7zlkDdMnCL878zriLaBmoD9quOoq1ySSSGv03l0hXK5CvIFZlIfFI/hizqdQuW+Num7xuhw==} + engines: {node: '>=4'} + dependencies: + escape-string-applescript: 1.0.0 + run-applescript: 3.2.0 + dev: false + /dns-packet@5.6.1: resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} engines: {node: '>=6'} @@ -5902,24 +6143,25 @@ packages: esutils: 2.0.3 dev: true + /doctypes@1.1.0: + resolution: {integrity: sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==} + dev: false + /dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} dependencies: domelementtype: 2.3.0 domhandler: 5.0.3 entities: 4.5.0 - dev: true /domelementtype@2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - dev: true /domhandler@5.0.3: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} dependencies: domelementtype: 2.3.0 - dev: true /domutils@3.1.0: resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} @@ -5927,7 +6169,6 @@ packages: dom-serializer: 2.0.0 domelementtype: 2.3.0 domhandler: 5.0.3 - dev: true /dot-case@3.0.4: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} @@ -5984,7 +6225,6 @@ packages: hasBin: true dependencies: jake: 10.8.7 - dev: true /electron-to-chromium@1.4.695: resolution: {integrity: sha512-eMijZmeqPtm774pCZIOrfUHMs/7ls++W1sLhxwqgu8KQ8E2WmMtzwyqOMt0XXUJ3HTIPfuwlfwF+I5cwnfItBA==} @@ -6012,6 +6252,11 @@ packages: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} + /encoding-japanese@2.0.0: + resolution: {integrity: sha512-++P0RhebUC8MJAwJOsT93dT+5oc5oPImp1HubZpAuCZ5kTLnhuuBhKHj2jJeO/Gj93idPBWmIuQ9QWMe5rX3pQ==} + engines: {node: '>=8.10.0'} + dev: false + /end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} dependencies: @@ -6036,7 +6281,6 @@ packages: /entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} - dev: true /envinfo@7.11.0: resolution: {integrity: sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==} @@ -6118,6 +6362,11 @@ packages: /escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + /escape-string-applescript@1.0.0: + resolution: {integrity: sha512-4/hFwoYaC6TkpDn9A3pTC52zQPArFeXuIfhUtCGYdauTzXVP9H3BDr3oO/QzQehMpLDC7srvYgfwvImPFGfvBA==} + engines: {node: '>=0.10.0'} + dev: false + /escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} @@ -6219,6 +6468,12 @@ packages: eslint-visitor-keys: 3.4.3 dev: true + /esprima@1.2.5: + resolution: {integrity: sha512-S9VbPDU0adFErpDai3qDkjq8+G05ONtKzcyNrPKg/ZKa+tf879nX2KexNU95b31UoTJjRLInNBHHHjFPoCd7lQ==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: false + /esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} engines: {node: '>=4'} @@ -6239,6 +6494,11 @@ packages: estraverse: 5.3.0 dev: true + /estraverse@1.9.3: + resolution: {integrity: sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==} + engines: {node: '>=0.10.0'} + dev: false + /estraverse@4.3.0: resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} engines: {node: '>=4.0'} @@ -6274,6 +6534,19 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} + /execa@0.10.0: + resolution: {integrity: sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==} + engines: {node: '>=4'} + dependencies: + cross-spawn: 6.0.5 + get-stream: 3.0.0 + is-stream: 1.1.0 + npm-run-path: 2.0.2 + p-finally: 1.0.0 + signal-exit: 3.0.7 + strip-eof: 1.0.0 + dev: false + /execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -6386,6 +6659,10 @@ packages: - supports-color dev: true + /extend-object@1.0.0: + resolution: {integrity: sha512-0dHDIXC7y7LDmCh/lp1oYkmv73K25AMugQI07r8eFopkW6f7Ufn1q+ETMsJjnV9Am14SlElkqy3O92r6xEaxPw==} + dev: false + /extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} dev: true @@ -6532,7 +6809,6 @@ packages: resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} dependencies: minimatch: 5.1.6 - dev: true /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} @@ -6596,6 +6872,18 @@ packages: path-exists: 5.0.0 dev: true + /fixpack@4.0.0: + resolution: {integrity: sha512-5SM1+H2CcuJ3gGEwTiVo/+nd/hYpNj9Ch3iMDOQ58ndY+VGQ2QdvaUTkd3otjZvYnd/8LF/HkJ5cx7PBq0orCQ==} + hasBin: true + dependencies: + alce: 1.2.0 + chalk: 3.0.0 + detect-indent: 6.1.0 + detect-newline: 3.1.0 + extend-object: 1.0.0 + rc: 1.2.8 + dev: false + /flat-cache@3.2.0: resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} engines: {node: ^10.12.0 || >=12.0.0} @@ -6753,6 +7041,16 @@ packages: engines: {node: '>=8.0.0'} dev: true + /get-port@5.1.1: + resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==} + engines: {node: '>=8'} + dev: false + + /get-stream@3.0.0: + resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==} + engines: {node: '>=4'} + dev: false + /get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -6867,7 +7165,6 @@ packages: wordwrap: 1.0.0 optionalDependencies: uglify-js: 3.17.4 - dev: true /harmony-reflect@1.6.2: resolution: {integrity: sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==} @@ -6900,12 +7197,24 @@ packages: resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} engines: {node: '>= 0.4'} + /has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: false + /hasown@2.0.1: resolution: {integrity: sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==} engines: {node: '>= 0.4'} dependencies: function-bind: 1.1.2 + /he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + dev: false + /hosted-git-info@7.0.1: resolution: {integrity: sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==} engines: {node: ^16.14.0 || >=18.0.0} @@ -6930,6 +7239,26 @@ packages: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} dev: true + /html-to-text@9.0.5: + resolution: {integrity: sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==} + engines: {node: '>=14'} + dependencies: + '@selderee/plugin-htmlparser2': 0.11.0 + deepmerge: 4.3.1 + dom-serializer: 2.0.0 + htmlparser2: 8.0.2 + selderee: 0.11.0 + dev: false + + /htmlparser2@8.0.2: + resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.1.0 + entities: 4.5.0 + dev: false + /http-deceiver@1.2.7: resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==} dev: true @@ -7031,7 +7360,6 @@ packages: engines: {node: '>=0.10.0'} dependencies: safer-buffer: 2.1.2 - dev: true /icss-utils@5.1.0(postcss@8.4.35): resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} @@ -7105,6 +7433,10 @@ packages: /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + /ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: false + /ioredis@5.3.2: resolution: {integrity: sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==} engines: {node: '>=12.22.0'} @@ -7149,13 +7481,18 @@ packages: resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} dependencies: hasown: 2.0.1 - dev: true /is-docker@2.2.1: resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} engines: {node: '>=8'} hasBin: true - dev: true + + /is-expression@4.0.0: + resolution: {integrity: sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==} + dependencies: + acorn: 7.4.1 + object-assign: 4.1.1 + dev: false /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} @@ -7201,7 +7538,19 @@ packages: /is-promise@2.2.2: resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} - dev: true + + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: false + + /is-stream@1.1.0: + resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} + engines: {node: '>=0.10.0'} + dev: false /is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} @@ -7225,14 +7574,12 @@ packages: engines: {node: '>=8'} dependencies: is-docker: 2.2.1 - dev: true /isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true /isows@1.0.3(ws@8.13.0): resolution: {integrity: sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg==} @@ -7318,7 +7665,6 @@ packages: chalk: 4.1.2 filelist: 1.0.4 minimatch: 3.1.2 - dev: true /jest-changed-files@29.7.0: resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} @@ -7740,6 +8086,10 @@ packages: - ts-node dev: true + /js-stringify@1.0.2: + resolution: {integrity: sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==} + dev: false + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -7867,6 +8217,13 @@ packages: verror: 1.10.0 dev: true + /jstransformer@1.0.0: + resolution: {integrity: sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==} + dependencies: + is-promise: 2.2.2 + promise: 7.3.1 + dev: false + /jwa@1.4.1: resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} dependencies: @@ -7919,6 +8276,10 @@ packages: shell-quote: 1.8.1 dev: true + /leac@0.6.0: + resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==} + dev: false + /less-loader@11.1.0(less@4.1.3)(webpack@5.90.3): resolution: {integrity: sha512-C+uDBV7kS7W5fJlUjq5mPBeBVhYpTIm5gB09APT9o3n/ILeaXVsiSFTbZpTJCJwQ/Crczfn3DmfQFwxYusWFug==} engines: {node: '>= 14.15.0'} @@ -7962,9 +8323,43 @@ packages: type-check: 0.4.0 dev: true + /libbase64@1.2.1: + resolution: {integrity: sha512-l+nePcPbIG1fNlqMzrh68MLkX/gTxk/+vdvAb388Ssi7UuUN31MI44w4Yf33mM3Cm4xDfw48mdf3rkdHszLNew==} + dev: false + + /libbase64@1.3.0: + resolution: {integrity: sha512-GgOXd0Eo6phYgh0DJtjQ2tO8dc0IVINtZJeARPeiIJqge+HdsWSuaDTe8ztQ7j/cONByDZ3zeB325AHiv5O0dg==} + dev: false + + /libmime@5.2.0: + resolution: {integrity: sha512-X2U5Wx0YmK0rXFbk67ASMeqYIkZ6E5vY7pNWRKtnNzqjvdYYG8xtPDpCnuUEnPU9vlgNev+JoSrcaKSUaNvfsw==} + dependencies: + encoding-japanese: 2.0.0 + iconv-lite: 0.6.3 + libbase64: 1.2.1 + libqp: 2.0.1 + dev: false + + /libmime@5.3.4: + resolution: {integrity: sha512-TsqPdercr6DHrnoQx1F0nS2Y4yPT+fWuOjEP2rqzvV77hMYWomTe/rpm0u9JORQ/FavEXybAGcBJsQbLr9+hjA==} + dependencies: + encoding-japanese: 2.0.0 + iconv-lite: 0.6.3 + libbase64: 1.3.0 + libqp: 2.1.0 + dev: false + /libphonenumber-js@1.10.57: resolution: {integrity: sha512-OjsEd9y4LgcX+Ig09SbxWqcGESxliDDFNVepFhB9KEsQZTrnk3UdEU+cO0sW1APvLprHstQpS23OQpZ3bwxy6Q==} + /libqp@2.0.1: + resolution: {integrity: sha512-Ka0eC5LkF3IPNQHJmYBWljJsw0UvM6j+QdKRbWyCdTmYwvIDE6a7bCm0UkTAL/K+3KXK5qXT/ClcInU01OpdLg==} + dev: false + + /libqp@2.1.0: + resolution: {integrity: sha512-O6O6/fsG5jiUVbvdgT7YX3xY3uIadR6wEZ7+vy9u7PKHAlSEB6blvC1o5pHBjgsi95Uo0aiBBdkyFecj6jtb7A==} + dev: false + /license-webpack-plugin@4.0.2(webpack@5.90.3): resolution: {integrity: sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==} peerDependencies: @@ -7972,6 +8367,8 @@ packages: peerDependenciesMeta: webpack: optional: true + webpack-sources: + optional: true dependencies: webpack: 5.90.3(@swc/core@1.4.5)(esbuild@0.20.1) webpack-sources: 3.2.3 @@ -7999,6 +8396,12 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: true + /linkify-it@5.0.0: + resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + dependencies: + uc.micro: 2.1.0 + dev: false + /loader-runner@4.3.0: resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} engines: {node: '>=6.11.5'} @@ -8170,6 +8573,29 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true + /mailparser@3.6.9: + resolution: {integrity: sha512-1fIDZlgN1NnuzmTSEUxkaViquXYkw5NbQehVc+kz55QRy98QgLdTtRSKv289Jy4NrCiDchRx6zAijB4HrPsvkA==} + dependencies: + encoding-japanese: 2.0.0 + he: 1.2.0 + html-to-text: 9.0.5 + iconv-lite: 0.6.3 + libmime: 5.3.4 + linkify-it: 5.0.0 + mailsplit: 5.4.0 + nodemailer: 6.9.11 + punycode: 2.3.1 + tlds: 1.250.0 + dev: false + + /mailsplit@5.4.0: + resolution: {integrity: sha512-wnYxX5D5qymGIPYLwnp6h8n1+6P6vz/MJn5AzGjZ8pwICWssL+CCQjWBIToOVHASmATot4ktvlLo6CyLfOXWYA==} + dependencies: + libbase64: 1.2.1 + libmime: 5.2.0 + libqp: 2.0.1 + dev: false + /make-dir@2.1.0: resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} engines: {node: '>=6'} @@ -8290,14 +8716,12 @@ packages: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: brace-expansion: 1.1.11 - dev: true /minimatch@5.1.6: resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} engines: {node: '>=10'} dependencies: brace-expansion: 2.0.1 - dev: true /minimatch@7.4.6: resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==} @@ -8408,7 +8832,6 @@ packages: /neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: true /nest-winston@1.9.4(@nestjs/common@10.3.3)(winston@3.12.0): resolution: {integrity: sha512-ilEmHuuYSAI6aMNR120fLBl42EdY13QI9WRggHdEizt9M7qZlmXJwpbemVWKW/tqRmULjSx/otKNQ3GMQbfoUQ==} @@ -8421,6 +8844,10 @@ packages: winston: 3.12.0 dev: false + /nice-try@1.0.5: + resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} + dev: false + /no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} dependencies: @@ -8497,6 +8924,13 @@ packages: validate-npm-package-name: 5.0.0 dev: true + /npm-run-path@2.0.2: + resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} + engines: {node: '>=4'} + dependencies: + path-key: 2.0.1 + dev: false + /npm-run-path@4.0.1: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} @@ -8628,6 +9062,14 @@ packages: mimic-fn: 2.1.0 dev: true + /open@7.4.2: + resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==} + engines: {node: '>=8'} + dependencies: + is-docker: 2.2.1 + is-wsl: 2.2.0 + dev: false + /open@8.4.2: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} @@ -8678,6 +9120,18 @@ packages: wcwidth: 1.0.1 dev: true + /p-event@4.2.0: + resolution: {integrity: sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==} + engines: {node: '>=8'} + dependencies: + p-timeout: 3.2.0 + dev: false + + /p-finally@1.0.0: + resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} + engines: {node: '>=4'} + dev: false + /p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -8728,11 +9182,25 @@ packages: retry: 0.13.1 dev: true + /p-timeout@3.2.0: + resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} + engines: {node: '>=8'} + dependencies: + p-finally: 1.0.0 + dev: false + /p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} dev: true + /p-wait-for@3.2.0: + resolution: {integrity: sha512-wpgERjNkLrBiFmkMEjuZJEWKKDrNfHCKA1OhyN1wg1FrLkULbviEy6py1AyJUgZ72YWFbZ38FIpnqvVqAlDUwA==} + engines: {node: '>=8'} + dependencies: + p-timeout: 3.2.0 + dev: false + /packet-reader@1.0.0: resolution: {integrity: sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==} dev: true @@ -8763,6 +9231,13 @@ packages: resolution: {integrity: sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==} dev: true + /parseley@0.12.1: + resolution: {integrity: sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==} + dependencies: + leac: 0.6.0 + peberminta: 0.9.0 + dev: false + /parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -8803,6 +9278,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /path-key@2.0.1: + resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} + engines: {node: '>=4'} + dev: false + /path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -8810,7 +9290,6 @@ packages: /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true /path-to-regexp@0.1.7: resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} @@ -8831,6 +9310,10 @@ packages: resolution: {integrity: sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==} dev: false + /peberminta@0.9.0: + resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==} + dev: false + /performance-now@2.1.0: resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} dev: true @@ -9445,6 +9928,23 @@ packages: react-is: 18.2.0 dev: true + /preview-email@3.0.19: + resolution: {integrity: sha512-DBS3Nir18YtKc8loYCCOGitmiaQ0vTdahPoiXxwNweJDpmVZo+w3tppufOhoK0m8skpRxT56llYLs3VrORnmNQ==} + engines: {node: '>=14'} + dependencies: + ci-info: 3.9.0 + display-notification: 2.0.0 + fixpack: 4.0.0 + get-port: 5.1.1 + mailparser: 3.6.9 + nodemailer: 6.9.11 + open: 7.4.2 + p-event: 4.2.0 + p-wait-for: 3.2.0 + pug: 3.0.2 + uuid: 9.0.1 + dev: false + /prisma@5.10.2: resolution: {integrity: sha512-hqb/JMz9/kymRE25pMWCxkdyhbnIWrq+h7S6WysJpdnCvhstbJSNP/S6mScEcqiB8Qv2F+0R3yG+osRaWqZacQ==} engines: {node: '>=16.13'} @@ -9477,6 +9977,12 @@ packages: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} + /promise@7.3.1: + resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==} + dependencies: + asap: 2.0.6 + dev: false + /prompts@2.4.2: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} @@ -9509,6 +10015,97 @@ packages: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} dev: true + /pug-attrs@3.0.0: + resolution: {integrity: sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==} + dependencies: + constantinople: 4.0.1 + js-stringify: 1.0.2 + pug-runtime: 3.0.1 + dev: false + + /pug-code-gen@3.0.2: + resolution: {integrity: sha512-nJMhW16MbiGRiyR4miDTQMRWDgKplnHyeLvioEJYbk1RsPI3FuA3saEP8uwnTb2nTJEKBU90NFVWJBk4OU5qyg==} + dependencies: + constantinople: 4.0.1 + doctypes: 1.1.0 + js-stringify: 1.0.2 + pug-attrs: 3.0.0 + pug-error: 2.0.0 + pug-runtime: 3.0.1 + void-elements: 3.1.0 + with: 7.0.2 + dev: false + + /pug-error@2.0.0: + resolution: {integrity: sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ==} + dev: false + + /pug-filters@4.0.0: + resolution: {integrity: sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==} + dependencies: + constantinople: 4.0.1 + jstransformer: 1.0.0 + pug-error: 2.0.0 + pug-walk: 2.0.0 + resolve: 1.22.8 + dev: false + + /pug-lexer@5.0.1: + resolution: {integrity: sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==} + dependencies: + character-parser: 2.2.0 + is-expression: 4.0.0 + pug-error: 2.0.0 + dev: false + + /pug-linker@4.0.0: + resolution: {integrity: sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==} + dependencies: + pug-error: 2.0.0 + pug-walk: 2.0.0 + dev: false + + /pug-load@3.0.0: + resolution: {integrity: sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==} + dependencies: + object-assign: 4.1.1 + pug-walk: 2.0.0 + dev: false + + /pug-parser@6.0.0: + resolution: {integrity: sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==} + dependencies: + pug-error: 2.0.0 + token-stream: 1.0.0 + dev: false + + /pug-runtime@3.0.1: + resolution: {integrity: sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==} + dev: false + + /pug-strip-comments@2.0.0: + resolution: {integrity: sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==} + dependencies: + pug-error: 2.0.0 + dev: false + + /pug-walk@2.0.0: + resolution: {integrity: sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==} + dev: false + + /pug@3.0.2: + resolution: {integrity: sha512-bp0I/hiK1D1vChHh6EfDxtndHji55XP/ZJKwsRqrz6lRia6ZC2OZbdAymlxdVFwd1L70ebrVJw4/eZ79skrIaw==} + dependencies: + pug-code-gen: 3.0.2 + pug-filters: 4.0.0 + pug-lexer: 5.0.1 + pug-linker: 4.0.0 + pug-load: 3.0.0 + pug-parser: 6.0.0 + pug-runtime: 3.0.1 + pug-strip-comments: 2.0.0 + dev: false + /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -9569,6 +10166,16 @@ packages: iconv-lite: 0.4.24 unpipe: 1.0.0 + /rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + dev: false + /react-is@18.2.0: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} dev: true @@ -9742,7 +10349,6 @@ packages: is-core-module: 2.13.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - dev: true /restore-cursor@3.1.0: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} @@ -9784,6 +10390,13 @@ packages: glob: 7.2.3 dev: true + /run-applescript@3.2.0: + resolution: {integrity: sha512-Ep0RsvAjnRcBX1p5vogbaBdAGu/8j/ewpvGqnQYunnLd9SM0vWcPJewPKNnWFggf0hF0pwIgwV5XK7qQ7UZ8Qg==} + engines: {node: '>=4'} + dependencies: + execa: 0.10.0 + dev: false + /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: @@ -9882,6 +10495,12 @@ packages: resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} dev: false + /selderee@0.11.0: + resolution: {integrity: sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==} + dependencies: + parseley: 0.12.1 + dev: false + /select-hose@2.0.0: resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} dev: true @@ -9898,8 +10517,6 @@ packages: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true requiresBuild: true - dev: true - optional: true /semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} @@ -9994,6 +10611,13 @@ packages: /setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + /shebang-command@1.2.0: + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} + engines: {node: '>=0.10.0'} + dependencies: + shebang-regex: 1.0.0 + dev: false + /shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -10001,6 +10625,11 @@ packages: shebang-regex: 3.0.0 dev: true + /shebang-regex@1.0.0: + resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} + engines: {node: '>=0.10.0'} + dev: false + /shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} @@ -10021,7 +10650,6 @@ packages: /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true /simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} @@ -10117,7 +10745,6 @@ packages: /source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - dev: true /source-map@0.7.4: resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} @@ -10259,11 +10886,21 @@ packages: engines: {node: '>=8'} dev: true + /strip-eof@1.0.0: + resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} + engines: {node: '>=0.10.0'} + dev: false + /strip-final-newline@2.0.0: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} dev: true + /strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + dev: false + /strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -10348,7 +10985,6 @@ packages: /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - dev: true /svg-parser@2.0.4: resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} @@ -10462,6 +11098,11 @@ packages: resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} dev: true + /tlds@1.250.0: + resolution: {integrity: sha512-rWsBfFCWKrjM/o2Q1TTUeYQv6tHSd/umUutDjVs6taTuEgRDIreVYIBgWRWW4ot7jp6n0UVUuxhTLWBtUmPu/w==} + hasBin: true + dev: false + /tmp@0.2.3: resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} engines: {node: '>=14.14'} @@ -10474,7 +11115,6 @@ packages: /to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} - dev: true /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} @@ -10492,6 +11132,10 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} + /token-stream@1.0.0: + resolution: {integrity: sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==} + dev: false + /toposort@2.0.2: resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==} dev: true @@ -10719,12 +11363,15 @@ packages: engines: {node: '>=14.17'} hasBin: true + /uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + dev: false + /uglify-js@3.17.4: resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} engines: {node: '>=0.8.0'} hasBin: true requiresBuild: true - dev: true optional: true /uid@2.0.2: @@ -10980,6 +11627,11 @@ packages: - zod dev: false + /void-elements@3.1.0: + resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} + engines: {node: '>=0.10.0'} + dev: false + /walker@1.0.8: resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} dependencies: @@ -11158,6 +11810,13 @@ packages: tr46: 0.0.3 webidl-conversions: 3.0.1 + /which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: false + /which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -11192,9 +11851,18 @@ packages: winston-transport: 4.7.0 dev: false + /with@7.0.2: + resolution: {integrity: sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==} + engines: {node: '>= 10.0.0'} + dependencies: + '@babel/parser': 7.24.0 + '@babel/types': 7.24.0 + assert-never: 1.2.1 + babel-walk: 3.0.0-canary-5 + dev: false + /wordwrap@1.0.0: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - dev: true /wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}