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
+
+
+
+
+
+
+
\ 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==}