@solidxai/core 0.1.13-beta.9 → 0.1.14-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9244 -0
- package/README.md +19 -0
- package/dist/commands/run-tests.command.d.ts +2 -0
- package/dist/commands/run-tests.command.d.ts.map +1 -1
- package/dist/commands/run-tests.command.js +20 -3
- package/dist/commands/run-tests.command.js.map +1 -1
- package/dist/config/cache.options.d.ts.map +1 -1
- package/dist/config/cache.options.js +2 -2
- package/dist/config/cache.options.js.map +1 -1
- package/dist/constants/error-messages.d.ts +7 -0
- package/dist/constants/error-messages.d.ts.map +1 -1
- package/dist/constants/error-messages.js +7 -0
- package/dist/constants/error-messages.js.map +1 -1
- package/dist/constants/media-file-types.d.ts +17 -0
- package/dist/constants/media-file-types.d.ts.map +1 -1
- package/dist/constants/media-file-types.js +129 -22
- package/dist/constants/media-file-types.js.map +1 -1
- package/dist/constants/success-messages.d.ts +3 -0
- package/dist/constants/success-messages.d.ts.map +1 -1
- package/dist/constants/success-messages.js +3 -0
- package/dist/constants/success-messages.js.map +1 -1
- package/dist/controllers/authentication.controller.d.ts +1 -1
- package/dist/controllers/authentication.controller.d.ts.map +1 -1
- package/dist/controllers/authentication.controller.js +4 -3
- package/dist/controllers/authentication.controller.js.map +1 -1
- package/dist/controllers/field-metadata.controller.d.ts +6 -2
- package/dist/controllers/field-metadata.controller.d.ts.map +1 -1
- package/dist/controllers/mpin-authentication.controller.d.ts +44 -0
- package/dist/controllers/mpin-authentication.controller.d.ts.map +1 -0
- package/dist/controllers/mpin-authentication.controller.js +102 -0
- package/dist/controllers/mpin-authentication.controller.js.map +1 -0
- package/dist/controllers/view-metadata.controller.d.ts +4 -0
- package/dist/controllers/view-metadata.controller.d.ts.map +1 -1
- package/dist/dtos/change-mpin.dto.d.ts +6 -0
- package/dist/dtos/change-mpin.dto.d.ts.map +1 -0
- package/dist/dtos/change-mpin.dto.js +39 -0
- package/dist/dtos/change-mpin.dto.js.map +1 -0
- package/dist/dtos/create-field-metadata.dto.d.ts +3 -6
- package/dist/dtos/create-field-metadata.dto.d.ts.map +1 -1
- package/dist/dtos/create-field-metadata.dto.js +15 -10
- package/dist/dtos/create-field-metadata.dto.js.map +1 -1
- package/dist/dtos/create-model-sequence.dto.d.ts +1 -1
- package/dist/dtos/create-model-sequence.dto.d.ts.map +1 -1
- package/dist/dtos/create-model-sequence.dto.js +1 -1
- package/dist/dtos/create-model-sequence.dto.js.map +1 -1
- package/dist/dtos/mpin-login.dto.d.ts +5 -0
- package/dist/dtos/mpin-login.dto.d.ts.map +1 -0
- package/dist/dtos/mpin-login.dto.js +33 -0
- package/dist/dtos/mpin-login.dto.js.map +1 -0
- package/dist/dtos/setup-mpin.dto.d.ts +7 -0
- package/dist/dtos/setup-mpin.dto.d.ts.map +1 -0
- package/dist/dtos/setup-mpin.dto.js +47 -0
- package/dist/dtos/setup-mpin.dto.js.map +1 -0
- package/dist/entities/dashboard-user-layout.entity.js +2 -2
- package/dist/entities/dashboard-user-layout.entity.js.map +1 -1
- package/dist/entities/field-metadata.entity.d.ts +1 -0
- package/dist/entities/field-metadata.entity.d.ts.map +1 -1
- package/dist/entities/field-metadata.entity.js +5 -1
- package/dist/entities/field-metadata.entity.js.map +1 -1
- package/dist/entities/user-device-credential.entity.d.ts +18 -0
- package/dist/entities/user-device-credential.entity.d.ts.map +1 -0
- package/dist/entities/user-device-credential.entity.js +91 -0
- package/dist/entities/user-device-credential.entity.js.map +1 -0
- package/dist/entities/user.entity.js +2 -2
- package/dist/entities/user.entity.js.map +1 -1
- package/dist/entities/view-metadata.entity.js.map +1 -1
- package/dist/entities/workflow-execution-artifact.entity.d.ts.map +1 -1
- package/dist/entities/workflow-execution-artifact.entity.js +4 -3
- package/dist/entities/workflow-execution-artifact.entity.js.map +1 -1
- package/dist/entities/workflow-execution-log.entity.d.ts.map +1 -1
- package/dist/entities/workflow-execution-log.entity.js +4 -3
- package/dist/entities/workflow-execution-log.entity.js.map +1 -1
- package/dist/entities/workflow-execution.entity.d.ts.map +1 -1
- package/dist/entities/workflow-execution.entity.js +3 -2
- package/dist/entities/workflow-execution.entity.js.map +1 -1
- package/dist/entities/workflow-secret.entity.d.ts.map +1 -1
- package/dist/entities/workflow-secret.entity.js +3 -2
- package/dist/entities/workflow-secret.entity.js.map +1 -1
- package/dist/entities/workflow-step-execution.entity.d.ts.map +1 -1
- package/dist/entities/workflow-step-execution.entity.js +3 -2
- package/dist/entities/workflow-step-execution.entity.js.map +1 -1
- package/dist/entities/workflow-trigger-execution.entity.d.ts.map +1 -1
- package/dist/entities/workflow-trigger-execution.entity.js +6 -5
- package/dist/entities/workflow-trigger-execution.entity.js.map +1 -1
- package/dist/filters/http-exception.filter.d.ts.map +1 -1
- package/dist/filters/http-exception.filter.js +5 -1
- package/dist/filters/http-exception.filter.js.map +1 -1
- package/dist/helpers/bootstrap.helper.d.ts +5 -2
- package/dist/helpers/bootstrap.helper.d.ts.map +1 -1
- package/dist/helpers/bootstrap.helper.js +7 -3
- package/dist/helpers/bootstrap.helper.js.map +1 -1
- package/dist/helpers/field-crud-managers/LongTextFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/LongTextFieldCrudManager.js +3 -2
- package/dist/helpers/field-crud-managers/LongTextFieldCrudManager.js.map +1 -1
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts +8 -0
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js +61 -76
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js.map +1 -1
- package/dist/helpers/field-crud-managers/ShortTextFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/ShortTextFieldCrudManager.js +3 -2
- package/dist/helpers/field-crud-managers/ShortTextFieldCrudManager.js.map +1 -1
- package/dist/helpers/field-crud-managers/textFieldCrudManagerUtils.d.ts +3 -0
- package/dist/helpers/field-crud-managers/textFieldCrudManagerUtils.d.ts.map +1 -0
- package/dist/helpers/field-crud-managers/textFieldCrudManagerUtils.js +17 -0
- package/dist/helpers/field-crud-managers/textFieldCrudManagerUtils.js.map +1 -0
- package/dist/helpers/file-download.helper.d.ts.map +1 -1
- package/dist/helpers/file-download.helper.js +6 -1
- package/dist/helpers/file-download.helper.js.map +1 -1
- package/dist/helpers/security.helper.d.ts +5 -1
- package/dist/helpers/security.helper.d.ts.map +1 -1
- package/dist/helpers/security.helper.js +15 -4
- package/dist/helpers/security.helper.js.map +1 -1
- package/dist/helpers/solid-core-error-codes-provider.service.d.ts.map +1 -1
- package/dist/helpers/solid-core-error-codes-provider.service.js +45 -0
- package/dist/helpers/solid-core-error-codes-provider.service.js.map +1 -1
- package/dist/helpers/solid-microservice-adapter.service.d.ts.map +1 -1
- package/dist/helpers/solid-microservice-adapter.service.js +1 -1
- package/dist/helpers/solid-microservice-adapter.service.js.map +1 -1
- package/dist/helpers/typeorm-db-helper.d.ts.map +1 -1
- package/dist/helpers/typeorm-db-helper.js +9 -0
- package/dist/helpers/typeorm-db-helper.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces/active-user-data.interface.d.ts +1 -0
- package/dist/interfaces/active-user-data.interface.d.ts.map +1 -1
- package/dist/interfaces/active-user-data.interface.js.map +1 -1
- package/dist/repository/user-device-credential.repository.d.ts +12 -0
- package/dist/repository/user-device-credential.repository.d.ts.map +1 -0
- package/dist/repository/user-device-credential.repository.js +34 -0
- package/dist/repository/user-device-credential.repository.js.map +1 -0
- package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.js +7 -3
- package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
- package/dist/seeders/seed-data/solid-core-metadata.json +168 -2
- package/dist/services/api-key.service.d.ts.map +1 -1
- package/dist/services/api-key.service.js +1 -1
- package/dist/services/api-key.service.js.map +1 -1
- package/dist/services/authentication.service.d.ts +5 -4
- package/dist/services/authentication.service.d.ts.map +1 -1
- package/dist/services/authentication.service.js +50 -19
- package/dist/services/authentication.service.js.map +1 -1
- package/dist/services/chatter-message.service.d.ts +5 -1
- package/dist/services/chatter-message.service.d.ts.map +1 -1
- package/dist/services/chatter-message.service.js +48 -13
- package/dist/services/chatter-message.service.js.map +1 -1
- package/dist/services/crud-helper.service.d.ts +1 -2
- package/dist/services/crud-helper.service.d.ts.map +1 -1
- package/dist/services/crud-helper.service.js +2 -16
- package/dist/services/crud-helper.service.js.map +1 -1
- package/dist/services/crud.service.d.ts.map +1 -1
- package/dist/services/crud.service.js +4 -2
- package/dist/services/crud.service.js.map +1 -1
- package/dist/services/draft-publish-helper.service.d.ts +1 -0
- package/dist/services/draft-publish-helper.service.d.ts.map +1 -1
- package/dist/services/draft-publish-helper.service.js +38 -4
- package/dist/services/draft-publish-helper.service.js.map +1 -1
- package/dist/services/field-metadata.service.d.ts +6 -2
- package/dist/services/field-metadata.service.d.ts.map +1 -1
- package/dist/services/field-metadata.service.js +5 -1
- package/dist/services/field-metadata.service.js.map +1 -1
- package/dist/services/media-storage.utils.d.ts +1 -0
- package/dist/services/media-storage.utils.d.ts.map +1 -1
- package/dist/services/media-storage.utils.js +12 -1
- package/dist/services/media-storage.utils.js.map +1 -1
- package/dist/services/media.service.d.ts.map +1 -1
- package/dist/services/media.service.js +1 -0
- package/dist/services/media.service.js.map +1 -1
- package/dist/services/module-metadata.service.d.ts.map +1 -1
- package/dist/services/module-metadata.service.js +9 -1
- package/dist/services/module-metadata.service.js.map +1 -1
- package/dist/services/mpin.service.d.ts +67 -0
- package/dist/services/mpin.service.d.ts.map +1 -0
- package/dist/services/mpin.service.js +282 -0
- package/dist/services/mpin.service.js.map +1 -0
- package/dist/services/refresh-token-ids-storage.service.d.ts +25 -6
- package/dist/services/refresh-token-ids-storage.service.d.ts.map +1 -1
- package/dist/services/refresh-token-ids-storage.service.js +80 -42
- package/dist/services/refresh-token-ids-storage.service.js.map +1 -1
- package/dist/services/setting.service.d.ts.map +1 -1
- package/dist/services/setting.service.js +6 -1
- package/dist/services/setting.service.js.map +1 -1
- package/dist/services/settings/default-settings-provider.service.d.ts +202 -6
- package/dist/services/settings/default-settings-provider.service.d.ts.map +1 -1
- package/dist/services/settings/default-settings-provider.service.js +114 -3
- package/dist/services/settings/default-settings-provider.service.js.map +1 -1
- package/dist/services/view-metadata.service.d.ts +4 -0
- package/dist/services/view-metadata.service.d.ts.map +1 -1
- package/dist/services/view-metadata.service.js +2 -0
- package/dist/services/view-metadata.service.js.map +1 -1
- package/dist/solid-core.module.d.ts +1 -3
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +14 -39
- package/dist/solid-core.module.js.map +1 -1
- package/dist/testing/reporter/console-reporter.d.ts +3 -0
- package/dist/testing/reporter/console-reporter.d.ts.map +1 -1
- package/dist/testing/reporter/console-reporter.js +2 -0
- package/dist/testing/reporter/console-reporter.js.map +1 -1
- package/dist/testing/reporter/progress-reporter.d.ts +64 -0
- package/dist/testing/reporter/progress-reporter.d.ts.map +1 -0
- package/dist/testing/reporter/progress-reporter.js +224 -0
- package/dist/testing/reporter/progress-reporter.js.map +1 -0
- package/dist/testing/reporter/reporter.types.d.ts +3 -0
- package/dist/testing/reporter/reporter.types.d.ts.map +1 -1
- package/dist/testing/reporter/reporter.types.js.map +1 -1
- package/dist/testing/runner/run-from-metadata.d.ts.map +1 -1
- package/dist/testing/runner/run-from-metadata.js +1 -0
- package/dist/testing/runner/run-from-metadata.js.map +1 -1
- package/dist/theme/theme-registry.d.ts +14 -0
- package/dist/theme/theme-registry.d.ts.map +1 -0
- package/dist/theme/theme-registry.js +147 -0
- package/dist/theme/theme-registry.js.map +1 -0
- package/package.json +2 -2
- package/src/commands/run-tests.command.ts +17 -3
- package/src/config/cache.options.ts +9 -1
- package/src/constants/error-messages.ts +14 -0
- package/src/constants/media-file-types.ts +182 -19
- package/src/constants/success-messages.ts +5 -0
- package/src/controllers/authentication.controller.ts +5 -2
- package/src/controllers/mpin-authentication.controller.ts +67 -0
- package/src/dtos/change-mpin.dto.ts +18 -0
- package/src/dtos/create-field-metadata.dto.ts +17 -9
- package/src/dtos/create-model-sequence.dto.ts +1 -1
- package/src/dtos/mpin-login.dto.ts +24 -0
- package/src/dtos/setup-mpin.dto.ts +51 -0
- package/src/entities/dashboard-user-layout.entity.ts +2 -2
- package/src/entities/field-metadata.entity.ts +3 -0
- package/src/entities/user-device-credential.entity.ts +130 -0
- package/src/entities/user.entity.ts +2 -2
- package/src/entities/view-metadata.entity.ts +2 -2
- package/src/entities/workflow-execution-artifact.entity.ts +4 -3
- package/src/entities/workflow-execution-log.entity.ts +4 -3
- package/src/entities/workflow-execution.entity.ts +3 -2
- package/src/entities/workflow-secret.entity.ts +3 -2
- package/src/entities/workflow-step-execution.entity.ts +3 -2
- package/src/entities/workflow-trigger-execution.entity.ts +6 -5
- package/src/filters/http-exception.filter.ts +11 -1
- package/src/helpers/bootstrap.helper.ts +43 -6
- package/src/helpers/field-crud-managers/LongTextFieldCrudManager.ts +3 -2
- package/src/helpers/field-crud-managers/MediaFieldCrudManager.ts +83 -96
- package/src/helpers/field-crud-managers/ShortTextFieldCrudManager.ts +3 -2
- package/src/helpers/field-crud-managers/textFieldCrudManagerUtils.ts +14 -0
- package/src/helpers/file-download.helper.ts +15 -1
- package/src/helpers/security.helper.ts +35 -8
- package/src/helpers/solid-core-error-codes-provider.service.ts +53 -0
- package/src/helpers/solid-microservice-adapter.service.ts +6 -1
- package/src/helpers/typeorm-db-helper.ts +12 -1
- package/src/index.ts +6 -0
- package/src/interfaces/active-user-data.interface.ts +9 -0
- package/src/repository/user-device-credential.repository.ts +17 -0
- package/src/seeders/module-metadata-seeder.service.ts +11 -3
- package/src/seeders/seed-data/solid-core-metadata.json +168 -2
- package/src/services/api-key.service.ts +13 -1
- package/src/services/authentication.service.ts +127 -36
- package/src/services/chatter-message.service.ts +78 -15
- package/src/services/crud-helper.service.ts +19 -16
- package/src/services/crud.service.ts +5 -2
- package/src/services/draft-publish-helper.service.ts +56 -4
- package/src/services/field-metadata.service.ts +6 -2
- package/src/services/media-storage.utils.ts +26 -1
- package/src/services/media.service.ts +1 -0
- package/src/services/module-metadata.service.ts +10 -1
- package/src/services/mpin.service.ts +447 -0
- package/src/services/refresh-token-ids-storage.service.ts +229 -90
- package/src/services/setting.service.ts +8 -1
- package/src/services/settings/default-settings-provider.service.ts +119 -3
- package/src/services/view-metadata.service.ts +4 -0
- package/src/solid-core.module.ts +26 -12
- package/src/testing/README.md +2 -1
- package/src/testing/reporter/console-reporter.ts +4 -0
- package/src/testing/reporter/progress-reporter.ts +251 -0
- package/src/testing/reporter/reporter.types.ts +3 -0
- package/src/testing/runner/run-from-metadata.ts +1 -0
- package/src/theme/theme-registry.ts +181 -0
- package/CLAUDE.md +0 -26
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.helper.js","sourceRoot":"","sources":["../../src/helpers/bootstrap.helper.ts"],"names":[],"mappings":"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","sourcesContent":["import { ClassSerializerInterceptor, ValidationPipe } from '@nestjs/common';\nimport { NestFactory, Reflector } from '@nestjs/core';\nimport { WsAdapter } from '@nestjs/platform-ws';\nimport { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';\nimport { NextFunction, Request, Response } from 'express';\nimport helmet from 'helmet';\nimport qs from 'qs';\nimport { existsSync } from 'fs';\nimport { resolve } from 'path';\nimport { WINSTON_MODULE_NEST_PROVIDER, WinstonModule } from 'nest-winston';\nimport { CommandFactory } from 'nest-commander';\nimport { createWinstonLoggerConfig } from '../winston.logger';\nimport { WrapResponseInterceptor } from '../interceptors/wrap-response.interceptor';\nimport { buildDefaultCorsOptions } from './cors.helper';\nimport { buildDefaultSecurityHeaderOptions, buildPermissionsPolicyHeader, PermissionsPolicyConfig } from './security.helper';\nimport { parseBooleanEnv } from './environment.helper';\n\n// ---- Shared process handlers ----\n\nfunction registerGlobalProcessHandlers() {\n process.on('unhandledRejection', (reason, promise) => {\n console.error('Unhandled Rejection at:', promise, 'reason:', reason);\n });\n\n process.on('uncaughtException', (err) => {\n console.error('Uncaught Exception thrown:', err);\n });\n\n // Suppress pg deprecation warning caused by TypeORM's internal query scheduling\n process.on('warning', (warning) => {\n if (warning.name === 'DeprecationWarning' && (warning.message.includes('client.query()') || warning.message.includes('punycode'))) {\n return;\n }\n console.warn(warning);\n });\n}\n\n// ---- HTTP server bootstrap ----\n\nexport interface SolidSwaggerOptions {\n title?: string;\n description?: string;\n version?: string;\n}\n\nexport interface SolidBootstrapOptions {\n /** Global API prefix. Defaults to 'api'. Set to '' to disable. */\n globalPrefix?: string;\n /** Swagger configuration. Set to false to disable Swagger entirely. */\n swagger?: SolidSwaggerOptions | false;\n /** Permissions-Policy header overrides (merged with defaults). */\n permissionsPolicyOverrides?: Partial<PermissionsPolicyConfig>;\n /** Show full NestJS init logs during bootstrap (route mapping, module deps, pollers). Defaults to false. */\n verboseBootstrap?: boolean;\n}\n\n/**\n * Bootstraps a SolidX NestJS HTTP application with sensible defaults:\n * security headers, CORS, Winston logger, ValidationPipe,\n * WrapResponseInterceptor, qs deep query parsing, Swagger, and the\n * pg BIGINT type parser.\n *\n * @example\n * // main.ts\n * bootstrapSolidApp(() => AppModule.forRoot(), {\n * swagger: { title: 'My API', description: 'My API description' },\n * });\n */\nexport async function bootstrapSolidApp(\n appModuleFactory: () => Promise<any>,\n options: SolidBootstrapOptions = {},\n): Promise<void> {\n registerGlobalProcessHandlers();\n\n const { globalPrefix = 'api', swagger = {}, permissionsPolicyOverrides = {}, verboseBootstrap = false } = options;\n\n const startTime = Date.now();\n const appModule = await appModuleFactory();\n const app = await NestFactory.create(appModule, {\n logger: WinstonModule.createLogger({ ...createWinstonLoggerConfig(), level: verboseBootstrap ? 'debug' : 'error' }),\n });\n\n const apiEnabled = parseBooleanEnv('API_ENABLED', true);\n\n if (!apiEnabled) {\n await app.init();\n app\n .get(WINSTON_MODULE_NEST_PROVIDER)\n .log('API server disabled via API_ENABLED=false. Skipping HTTP listen.', 'Bootstrap');\n return;\n }\n\n // Health check at root path\n const server = app.getHttpAdapter().getInstance();\n server.get('/', (_req, res) => res.status(200).send('SOLID OK'));\n\n // Security headers\n app.use(helmet(buildDefaultSecurityHeaderOptions()));\n\n // Nest's Swagger UI HTML injects inline styles; keep CSP strict elsewhere.\n const isSwaggerPath = (path: string) =>\n path === '/docs' ||\n path === '/docs/' ||\n path.startsWith('/docs/') ||\n path === '/docs-json' ||\n path === '/docs-yaml';\n\n app.use((req: Request, res: Response, next: NextFunction) => {\n if (isSwaggerPath(req.path)) {\n res.removeHeader('Content-Security-Policy');\n }\n next();\n });\n\n // Permissions-Policy header\n app.use((_req: Request, res: Response, next: NextFunction) => {\n res.setHeader('Permissions-Policy', buildPermissionsPolicyHeader(permissionsPolicyOverrides));\n next();\n });\n\n const port = process.env.PORT || 3000;\n\n if (globalPrefix) {\n app.setGlobalPrefix(globalPrefix);\n }\n\n // qs-based deep query parsing (dot notation, nested objects, arrays)\n app.use((req: Request, _res: Response, next: NextFunction) => {\n if (req.query) {\n req.query = qs.parse(req.url.split('?')[1], {\n allowDots: true,\n depth: 20,\n arrayLimit: 100,\n });\n }\n next();\n });\n\n // Global ValidationPipe\n app.useGlobalPipes(\n new ValidationPipe({\n transform: true,\n transformOptions: { enableImplicitConversion: true },\n }),\n );\n\n // Swagger\n if (swagger !== false) {\n const { title = process.env.SOLID_APP_NAME, description = process.env.SOLID_APP_DESCRIPTION, version = '1.0' } = swagger;\n const swaggerConfig = new DocumentBuilder()\n .setTitle(title)\n .setDescription(description)\n .setVersion(version)\n .setExternalDoc('Postman Collection', '/docs-json')\n .addBearerAuth(\n {\n description: 'Please enter token in following format: Bearer <JWT>',\n name: 'Authorization',\n bearerFormat: 'Bearer',\n scheme: 'Bearer',\n type: 'http',\n in: 'Header',\n },\n 'jwt',\n )\n .build();\n const document = SwaggerModule.createDocument(app, swaggerConfig);\n SwaggerModule.setup('/docs', app, document);\n }\n\n // Global interceptor\n app.useGlobalInterceptors(\n new ClassSerializerInterceptor(app.get(Reflector), {\n enableImplicitConversion: true, // optional but handy\n // groups: ['client'], // if you use groups\n }),\n new WrapResponseInterceptor()\n );\n\n // CORS\n app.enableCors(buildDefaultCorsOptions());\n\n // Fix pg returning BIGINT columns as strings\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const types = require('pg').types;\n types.setTypeParser(types.builtins.INT8, (val: string) => parseInt(val));\n\n app.useWebSocketAdapter(new WsAdapter(app));\n\n await app.listen(port);\n\n // Wire up Winston as the runtime logger only AFTER listen — this suppresses all\n // framework init noise (route mapping, module deps, onModuleInit) during boot.\n app.useLogger(app.get(WINSTON_MODULE_NEST_PROVIDER));\n\n const elapsed = ((Date.now() - startTime) / 1000).toFixed(2);\n process.stdout.write(`\\x1b[32mServer started on port ${port} in ${elapsed}s\\x1b[0m\\n`);\n}\n\n// ---- CLI bootstrap ----\n\n/**\n * Bootstraps a SolidX NestJS CLI application using nest-commander.\n * Handles verbose flag stripping, project root validation, and clean process exit.\n *\n * @example\n * // main-cli.ts\n * #!/usr/bin/env node\n * import { bootstrapSolidCli } from '@solidxai/core';\n * import { AppModule } from './app.module';\n *\n * bootstrapSolidCli(() => AppModule.forRoot());\n */\nexport async function bootstrapSolidCli(\n appModuleFactory: () => Promise<any>,\n): Promise<void> {\n registerGlobalProcessHandlers();\n\n process.on('exit', (code) => {\n if (code !== 0) {\n console.error(`Exiting with error status code: ${code}`);\n }\n });\n\n // Validate that cwd is a valid Solid API project\n const packageJsonPath = resolve(process.cwd(), 'package.json');\n if (!existsSync(packageJsonPath)) {\n console.error('Does not seem to be a valid solid-api project.');\n console.error('Exit reason: missing package.json in the current directory.');\n process.exit(1);\n }\n\n // Strip --verbose / -v before nest-commander processes argv\n const showLogs = process.argv.includes('--verbose') || process.argv.includes('-v');\n for (const flag of ['--verbose', '-v']) {\n const idx = process.argv.indexOf(flag);\n if (idx !== -1) process.argv.splice(idx, 1);\n }\n\n const appModule = await appModuleFactory();\n process.env.SOLID_CLI_RUNNING = 'true';\n\n // @ts-ignore\n const app = await CommandFactory.createWithoutRunning(appModule, {\n logger: showLogs ? ['debug', 'error', 'fatal', 'log', 'verbose', 'warn'] : false,\n });\n\n try {\n await CommandFactory.runApplication(app);\n } catch (e) {\n console.error('CLI exited abruptly due to an error:', e);\n process.exit(1);\n }\n\n process.exit(0);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"bootstrap.helper.js","sourceRoot":"","sources":["../../src/helpers/bootstrap.helper.ts"],"names":[],"mappings":"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","sourcesContent":["import { ClassSerializerInterceptor, ValidationPipe } from '@nestjs/common';\nimport { NestFactory, Reflector } from '@nestjs/core';\nimport { NestExpressApplication } from '@nestjs/platform-express';\nimport { WsAdapter } from '@nestjs/platform-ws';\nimport { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';\nimport { NextFunction, Request, Response } from 'express';\nimport helmet from 'helmet';\nimport qs from 'qs';\nimport { existsSync } from 'fs';\nimport { resolve } from 'path';\nimport { WINSTON_MODULE_NEST_PROVIDER, WinstonModule } from 'nest-winston';\nimport { CommandFactory } from 'nest-commander';\nimport { createWinstonLoggerConfig } from '../winston.logger';\nimport { WrapResponseInterceptor } from '../interceptors/wrap-response.interceptor';\nimport { buildDefaultCorsOptions } from './cors.helper';\nimport {\n buildDefaultSecurityHeaderOptions,\n buildPermissionsPolicyHeader,\n PermissionsPolicyConfig,\n SolidSecurityOptions,\n} from './security.helper';\nimport { parseBooleanEnv } from './environment.helper';\n\n// ---- Shared process handlers ----\n\nfunction registerGlobalProcessHandlers() {\n process.on('unhandledRejection', (reason, promise) => {\n console.error('Unhandled Rejection at:', promise, 'reason:', reason);\n });\n\n process.on('uncaughtException', (err) => {\n console.error('Uncaught Exception thrown:', err);\n });\n\n // Suppress pg deprecation warning caused by TypeORM's internal query scheduling\n process.on('warning', (warning) => {\n if (warning.name === 'DeprecationWarning' && (warning.message.includes('client.query()') || warning.message.includes('punycode'))) {\n return;\n }\n console.warn(warning);\n });\n}\n\n// ---- HTTP server bootstrap ----\n\nexport interface SolidSwaggerOptions {\n title?: string;\n description?: string;\n version?: string;\n}\n\nexport interface SolidBootstrapOptions {\n /** Global API prefix. Defaults to 'api'. Set to '' to disable. */\n globalPrefix?: string;\n /** Swagger configuration. Set to false to disable Swagger entirely. */\n swagger?: SolidSwaggerOptions | false;\n /** Permissions-Policy header overrides (merged with defaults). */\n permissionsPolicyOverrides?: Partial<PermissionsPolicyConfig>;\n /** Security header overrides, including iframe frame-ancestor allowlists. */\n security?: SolidSecurityOptions;\n /** Show full NestJS init logs during bootstrap (route mapping, module deps, pollers). Defaults to false. */\n verboseBootstrap?: boolean;\n /**\n * Max request body size for JSON and urlencoded payloads, as a `bytes`-compatible\n * string (e.g. '10mb', '512kb'). Defaults to '10mb'.\n *\n * Does NOT apply to multipart/form-data uploads: body-parser matches on Content-Type,\n * so multipart requests skip these parsers entirely and are handled by Multer. Raise\n * this only for large structured JSON (e.g. /bulk arrays), bearing in mind the parsed\n * object graph can retain several times the raw byte size.\n */\n bodyLimit?: string;\n}\n\n/**\n * Bootstraps a SolidX NestJS HTTP application with sensible defaults:\n * security headers, CORS, Winston logger, ValidationPipe,\n * WrapResponseInterceptor, qs deep query parsing, Swagger, and the\n * pg BIGINT type parser.\n *\n * @example\n * // main.ts\n * bootstrapSolidApp(() => AppModule.forRoot(), {\n * swagger: { title: 'My API', description: 'My API description' },\n * security: { frameAncestors: [\"'self'\", 'https://portal.example.com'] },\n * });\n */\nexport async function bootstrapSolidApp(\n appModuleFactory: () => Promise<any>,\n options: SolidBootstrapOptions = {},\n): Promise<NestExpressApplication> {\n registerGlobalProcessHandlers();\n\n const {\n globalPrefix = 'api',\n swagger = {},\n permissionsPolicyOverrides = {},\n security = {},\n verboseBootstrap = false,\n bodyLimit = '10mb',\n } = options;\n\n const startTime = Date.now();\n const appModule = await appModuleFactory();\n const app = await NestFactory.create<NestExpressApplication>(appModule, {\n // Nest's default parsers are registered during init() with a 100kb limit, ahead of\n // any module middleware. Disable them so the parsers below own the limit outright.\n bodyParser: false,\n logger: WinstonModule.createLogger({ ...createWinstonLoggerConfig(), level: verboseBootstrap ? 'debug' : 'error' }),\n });\n\n const apiEnabled = parseBooleanEnv('API_ENABLED', true);\n\n if (!apiEnabled) {\n await app.init();\n app\n .get(WINSTON_MODULE_NEST_PROVIDER)\n .log('API server disabled via API_ENABLED=false. Skipping HTTP listen.', 'Bootstrap');\n return app;\n }\n\n // Health check at root path\n const server = app.getHttpAdapter().getInstance();\n server.get('/', (_req, res) => res.status(200).send('SOLID OK'));\n\n // Security headers\n app.use(helmet(buildDefaultSecurityHeaderOptions(security)));\n\n // Nest's Swagger UI HTML injects inline styles; keep CSP strict elsewhere.\n const isSwaggerPath = (path: string) =>\n path === '/docs' ||\n path === '/docs/' ||\n path.startsWith('/docs/') ||\n path === '/docs-json' ||\n path === '/docs-yaml';\n\n app.use((req: Request, res: Response, next: NextFunction) => {\n if (isSwaggerPath(req.path)) {\n res.removeHeader('Content-Security-Policy');\n }\n next();\n });\n\n // Permissions-Policy header\n app.use((_req: Request, res: Response, next: NextFunction) => {\n res.setHeader('Permissions-Policy', buildPermissionsPolicyHeader(permissionsPolicyOverrides));\n next();\n });\n\n const port = process.env.PORT || 3000;\n\n if (globalPrefix) {\n app.setGlobalPrefix(globalPrefix);\n }\n\n // qs-based deep query parsing (dot notation, nested objects, arrays)\n app.use((req: Request, _res: Response, next: NextFunction) => {\n if (req.query) {\n req.query = qs.parse(req.url.split('?')[1], {\n allowDots: true,\n depth: 20,\n arrayLimit: 100,\n });\n }\n next();\n });\n\n // Body parsers — replaces Nest's default 100kb parsers (disabled via bodyParser: false).\n // Registered here so the middleware order Nest applied by default is preserved:\n // helmet -> CSP -> Permissions-Policy -> qs -> body parsers -> routes.\n app.useBodyParser('json', { limit: bodyLimit });\n app.useBodyParser('urlencoded', { limit: bodyLimit, extended: true });\n\n // Global ValidationPipe\n app.useGlobalPipes(\n new ValidationPipe({\n transform: true,\n transformOptions: { enableImplicitConversion: true },\n }),\n );\n\n // Swagger\n if (swagger !== false) {\n const { title = process.env.SOLID_APP_NAME, description = process.env.SOLID_APP_DESCRIPTION, version = '1.0' } = swagger;\n const swaggerConfig = new DocumentBuilder()\n .setTitle(title)\n .setDescription(description)\n .setVersion(version)\n .setExternalDoc('Postman Collection', '/docs-json')\n .addBearerAuth(\n {\n description: 'Please enter token in following format: Bearer <JWT>',\n name: 'Authorization',\n bearerFormat: 'Bearer',\n scheme: 'Bearer',\n type: 'http',\n in: 'Header',\n },\n 'jwt',\n )\n .build();\n const document = SwaggerModule.createDocument(app, swaggerConfig);\n SwaggerModule.setup('/docs', app, document);\n }\n\n // Global interceptor\n app.useGlobalInterceptors(\n new ClassSerializerInterceptor(app.get(Reflector), {\n enableImplicitConversion: true, // optional but handy\n // groups: ['client'], // if you use groups\n }),\n new WrapResponseInterceptor()\n );\n\n // CORS\n app.enableCors(buildDefaultCorsOptions());\n\n // Fix pg returning BIGINT columns as strings\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const types = require('pg').types;\n types.setTypeParser(types.builtins.INT8, (val: string) => parseInt(val));\n\n app.useWebSocketAdapter(new WsAdapter(app));\n\n await app.listen(port);\n\n // Wire up Winston as the runtime logger only AFTER listen — this suppresses all\n // framework init noise (route mapping, module deps, onModuleInit) during boot.\n app.useLogger(app.get(WINSTON_MODULE_NEST_PROVIDER));\n\n const elapsed = ((Date.now() - startTime) / 1000).toFixed(2);\n process.stdout.write(`\\x1b[32mServer started on port ${port} in ${elapsed}s\\x1b[0m\\n`);\n\n return app;\n}\n\n// ---- CLI bootstrap ----\n\n/**\n * Bootstraps a SolidX NestJS CLI application using nest-commander.\n * Handles verbose flag stripping, project root validation, and clean process exit.\n *\n * @example\n * // main-cli.ts\n * #!/usr/bin/env node\n * import { bootstrapSolidCli } from '@solidxai/core';\n * import { AppModule } from './app.module';\n *\n * bootstrapSolidCli(() => AppModule.forRoot());\n */\nexport async function bootstrapSolidCli(\n appModuleFactory: () => Promise<any>,\n): Promise<void> {\n registerGlobalProcessHandlers();\n\n process.on('exit', (code) => {\n if (code !== 0) {\n console.error(`Exiting with error status code: ${code}`);\n }\n });\n\n // Validate that cwd is a valid Solid API project\n const packageJsonPath = resolve(process.cwd(), 'package.json');\n if (!existsSync(packageJsonPath)) {\n console.error('Does not seem to be a valid solid-api project.');\n console.error('Exit reason: missing package.json in the current directory.');\n process.exit(1);\n }\n\n // Strip --verbose / -v before nest-commander processes argv\n const showLogs = process.argv.includes('--verbose') || process.argv.includes('-v');\n for (const flag of ['--verbose', '-v']) {\n const idx = process.argv.indexOf(flag);\n if (idx !== -1) process.argv.splice(idx, 1);\n }\n\n const appModule = await appModuleFactory();\n process.env.SOLID_CLI_RUNNING = 'true';\n\n // @ts-ignore\n const app = await CommandFactory.createWithoutRunning(appModule, {\n logger: showLogs ? ['debug', 'error', 'fatal', 'log', 'verbose', 'warn'] : false,\n });\n\n try {\n await CommandFactory.runApplication(app);\n } catch (e) {\n console.error('CLI exited abruptly due to an error:', e);\n process.exit(1);\n }\n\n process.exit(0);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LongTextFieldCrudManager.d.ts","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/LongTextFieldCrudManager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"LongTextFieldCrudManager.d.ts","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/LongTextFieldCrudManager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGnE,MAAM,WAAW,oBAAoB;IACjC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACxC,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;IACrC,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,wBAAyB,YAAW,gBAAgB;IAC7D,OAAO,CAAC,OAAO,CAAuB;gBAE1B,OAAO,EAAE,oBAAoB;IAIzC,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,eAAe,EAAE;IAKrC,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,sBAAsB;IAO9B,kBAAkB,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG;IAKjC,OAAO,CAAC,uBAAuB;IAG/B,OAAO,CAAC,sBAAsB;IAG9B,OAAO,CAAC,yBAAyB;CAGpC"}
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.LongTextFieldCrudManager = void 0;
|
|
4
4
|
const class_validator_1 = require("class-validator");
|
|
5
|
+
const textFieldCrudManagerUtils_1 = require("./textFieldCrudManagerUtils");
|
|
5
6
|
class LongTextFieldCrudManager {
|
|
6
7
|
constructor(options) {
|
|
7
8
|
this.options = options;
|
|
8
9
|
}
|
|
9
10
|
validate(dto) {
|
|
10
|
-
const fieldValue = dto[this.options.fieldName];
|
|
11
|
+
const fieldValue = (0, textFieldCrudManagerUtils_1.normalizeTextFieldValue)(dto[this.options.fieldName]);
|
|
11
12
|
return this.applyValidations(fieldValue);
|
|
12
13
|
}
|
|
13
14
|
applyValidations(fieldValue) {
|
|
@@ -25,7 +26,7 @@ class LongTextFieldCrudManager {
|
|
|
25
26
|
return errors;
|
|
26
27
|
}
|
|
27
28
|
transformForCreate(dto) {
|
|
28
|
-
return dto;
|
|
29
|
+
return (0, textFieldCrudManagerUtils_1.normalizeTextFieldInDto)(dto, this.options.fieldName);
|
|
29
30
|
}
|
|
30
31
|
isApplyStringValidation() {
|
|
31
32
|
return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LongTextFieldCrudManager.js","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/LongTextFieldCrudManager.ts"],"names":[],"mappings":";;;AAAA,qDAAyE;
|
|
1
|
+
{"version":3,"file":"LongTextFieldCrudManager.js","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/LongTextFieldCrudManager.ts"],"names":[],"mappings":";;;AAAA,qDAAyE;AAEzE,2EAA+F;AAQ/F,MAAa,wBAAwB;IAGjC,YAAY,OAA6B;QACrC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;IAED,QAAQ,CAAC,GAAQ;QACb,MAAM,UAAU,GAAQ,IAAA,mDAAuB,EAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;QAC7E,OAAO,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC7C,CAAC;IAEO,gBAAgB,CAAC,UAAe;QACpC,MAAM,MAAM,GAAsB,EAAE,CAAC;QACrC,IAAI,CAAC,yBAAyB,EAAE,IAAI,IAAA,yBAAO,EAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,UAAU,IAAI,CAAC,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CAAA,CAAC,CAAC,WAAW,CAAC;QAC7K,IAAI,IAAA,4BAAU,EAAC,UAAU,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAEO,sBAAsB,CAAC,UAAe;QAC1C,MAAM,MAAM,GAAsB,EAAE,CAAC;QACrC,IAAI,CAAC,uBAAuB,EAAE,IAAI,CAAC,IAAA,0BAAQ,EAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;QACvJ,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC,IAAA,yBAAO,EAAC,UAAU,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,gCAAgC,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;QACrM,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,kBAAkB,CAAC,GAAQ;QACvB,OAAO,IAAA,mDAAuB,EAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChE,CAAC;IAGO,uBAAuB;QAC3B,OAAO,IAAI,CAAC;IAChB,CAAC;IACO,sBAAsB;QAC1B,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,KAAK,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IACxI,CAAC;IACO,yBAAyB;QAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;IACjC,CAAC;CACJ;AA1CD,4DA0CC","sourcesContent":["import { isEmpty, isNotEmpty, isString, matches } from \"class-validator\";\nimport { FieldCrudManager, ValidationError } from \"src/interfaces\";\nimport { normalizeTextFieldInDto, normalizeTextFieldValue } from \"./textFieldCrudManagerUtils\";\n\nexport interface LongTextFieldOptions {\n regexPattern: string | undefined | null;\n required: boolean | undefined | null;\n fieldName: string;\n}\n\nexport class LongTextFieldCrudManager implements FieldCrudManager {\n private options: LongTextFieldOptions;\n\n constructor(options: LongTextFieldOptions) {\n this.options = options;\n }\n\n validate(dto: any): ValidationError[] {\n const fieldValue: any = normalizeTextFieldValue(dto[this.options.fieldName]);\n return this.applyValidations(fieldValue);\n }\n\n private applyValidations(fieldValue: any): ValidationError[] {\n const errors: ValidationError[] = [];\n this.isApplyRequiredValidation() && isEmpty(fieldValue) ? errors.push({ field: this.options.fieldName, error: `Field: ${this.options.fieldName} is required` }): \"no errors\";\n if (isNotEmpty(fieldValue)) {\n errors.push(...this.applyFormatValidations(fieldValue));\n }\n return errors;\n }\n\n private applyFormatValidations(fieldValue: any): ValidationError[] {\n const errors: ValidationError[] = [];\n this.isApplyStringValidation() && !isString(fieldValue) ? errors.push({ field: this.options.fieldName, error: 'Field is not a string' }) : \"no errors\";\n this.isApplyRegexValidation() && !matches(fieldValue, new RegExp(this.options.regexPattern)) ? errors.push({ field: this.options.fieldName, error: 'Field regex pattern is invalid' }) : \"no errors\";\n return errors;\n }\n\n transformForCreate(dto: any): any {\n return normalizeTextFieldInDto(dto, this.options.fieldName);\n }\n\n // Validation to be applied\n private isApplyStringValidation(): boolean {\n return true;\n }\n private isApplyRegexValidation(): boolean {\n return this.options.regexPattern !== null && this.options.regexPattern !== undefined && this.options.regexPattern.trim().length > 0;\n }\n private isApplyRequiredValidation(): boolean {\n return this.options.required;\n }\n}\n"]}
|
|
@@ -7,17 +7,25 @@ export interface MediaFieldOptions {
|
|
|
7
7
|
type: SolidMediaType;
|
|
8
8
|
required: boolean | undefined | null;
|
|
9
9
|
fieldName: string | undefined | null;
|
|
10
|
+
fieldLabel?: string | undefined | null;
|
|
10
11
|
mediaMaxSizeKb: number | undefined | null;
|
|
11
12
|
mediaTypes: string[];
|
|
13
|
+
mediaAllowedExtensions?: string[] | null;
|
|
12
14
|
isUpdate: boolean | undefined | null;
|
|
13
15
|
}
|
|
14
16
|
export declare class MediaFieldCrudManager implements FieldCrudManager {
|
|
15
17
|
private readonly options;
|
|
16
18
|
constructor(options: MediaFieldOptions);
|
|
19
|
+
private getFieldLabel;
|
|
17
20
|
private resolveMediaType;
|
|
18
21
|
validate(dto: any, files: Array<Express.Multer.File>): ValidationError[];
|
|
19
22
|
private applyValidations;
|
|
20
23
|
private validateDangerousFiles;
|
|
24
|
+
private validateCommon;
|
|
25
|
+
private validateRequired;
|
|
26
|
+
private validateSize;
|
|
27
|
+
private validateTypes;
|
|
28
|
+
private validateAllowedExtensions;
|
|
21
29
|
private validateMediaSingle;
|
|
22
30
|
private validateMediaMultiple;
|
|
23
31
|
transformForCreate(dto: any): any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MediaFieldCrudManager.d.ts","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/MediaFieldCrudManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGnE,oBAAY,cAAc;IACtB,WAAW,gBAAgB;IAC3B,aAAa,kBAAkB;CAClC;AAED,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;IACrC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACrC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAC1C,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;CACxC;
|
|
1
|
+
{"version":3,"file":"MediaFieldCrudManager.d.ts","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/MediaFieldCrudManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGnE,oBAAY,cAAc;IACtB,WAAW,gBAAgB;IAC3B,aAAa,kBAAkB;CAClC;AAED,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;IACrC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACvC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAC1C,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,sBAAsB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACzC,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;CACxC;AAID,qBAAa,qBAAsB,YAAW,gBAAgB;IAE9C,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,iBAAiB;IAGvD,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,gBAAgB;IA+BxB,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,eAAe,EAAE;IAKxE,OAAO,CAAC,gBAAgB;IAexB,OAAO,CAAC,sBAAsB;IAY9B,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,gBAAgB;IAWxB,OAAO,CAAC,YAAY;IAiBpB,OAAO,CAAC,aAAa;IAsBrB,OAAO,CAAC,yBAAyB;IAmBjC,OAAO,CAAC,mBAAmB;IAW3B,OAAO,CAAC,qBAAqB;IAI7B,kBAAkB,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG;CAKpC"}
|
|
@@ -7,88 +7,43 @@ var SolidMediaType;
|
|
|
7
7
|
SolidMediaType["mediaSingle"] = "mediaSingle";
|
|
8
8
|
SolidMediaType["mediaMultiple"] = "mediaMultiple";
|
|
9
9
|
})(SolidMediaType || (exports.SolidMediaType = SolidMediaType = {}));
|
|
10
|
-
const MIME_TO_MEDIA_TYPE = {
|
|
11
|
-
'image/png': 'image',
|
|
12
|
-
'image/jpeg': 'image',
|
|
13
|
-
'image/jpg': 'image',
|
|
14
|
-
'image/webp': 'image',
|
|
15
|
-
'image/gif': 'image',
|
|
16
|
-
'image/bmp': 'image',
|
|
17
|
-
'image/tiff': 'image',
|
|
18
|
-
'image/heic': 'image',
|
|
19
|
-
'image/heif': 'image',
|
|
20
|
-
'audio/mpeg': 'audio',
|
|
21
|
-
'audio/mp3': 'audio',
|
|
22
|
-
'audio/wav': 'audio',
|
|
23
|
-
'audio/x-wav': 'audio',
|
|
24
|
-
'audio/webm': 'audio',
|
|
25
|
-
'audio/ogg': 'audio',
|
|
26
|
-
'audio/aac': 'audio',
|
|
27
|
-
'audio/mp4': 'audio',
|
|
28
|
-
'audio/x-m4a': 'audio',
|
|
29
|
-
'audio/flac': 'audio',
|
|
30
|
-
'video/mp4': 'video',
|
|
31
|
-
'video/mpeg': 'video',
|
|
32
|
-
'video/webm': 'video',
|
|
33
|
-
'video/ogg': 'video',
|
|
34
|
-
'video/quicktime': 'video',
|
|
35
|
-
'video/x-msvideo': 'video',
|
|
36
|
-
'video/x-matroska': 'video',
|
|
37
|
-
'video/3gpp': 'video',
|
|
38
|
-
'video/3gpp2': 'video',
|
|
39
|
-
'application/pdf': 'pdf',
|
|
40
|
-
'text/plain': 'file',
|
|
41
|
-
'text/markdown': 'file',
|
|
42
|
-
'application/json': 'file',
|
|
43
|
-
'text/csv': 'file',
|
|
44
|
-
'application/msword': 'file',
|
|
45
|
-
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'file',
|
|
46
|
-
'application/vnd.ms-excel': 'file',
|
|
47
|
-
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'file',
|
|
48
|
-
'application/vnd.ms-powerpoint': 'file',
|
|
49
|
-
'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'file',
|
|
50
|
-
'application/zip': 'file',
|
|
51
|
-
'application/x-zip-compressed': 'file',
|
|
52
|
-
'application/x-rar-compressed': 'file',
|
|
53
|
-
'application/x-7z-compressed': 'file',
|
|
54
|
-
};
|
|
55
10
|
class MediaFieldCrudManager {
|
|
56
11
|
constructor(options) {
|
|
57
12
|
this.options = options;
|
|
58
13
|
}
|
|
14
|
+
getFieldLabel() {
|
|
15
|
+
return this.options.fieldLabel || this.options.fieldName || 'File';
|
|
16
|
+
}
|
|
59
17
|
resolveMediaType(file) {
|
|
60
18
|
if ((0, media_file_types_1.isDangerousMediaFile)(file)) {
|
|
61
19
|
return null;
|
|
62
20
|
}
|
|
63
21
|
const ext = (0, media_file_types_1.getLowercaseFileExtension)((0, media_file_types_1.getUploadedFileName)(file));
|
|
64
|
-
const
|
|
65
|
-
if (
|
|
66
|
-
return
|
|
22
|
+
const extType = ext ? media_file_types_1.EXT_TO_MEDIA_TYPE[ext] : undefined;
|
|
23
|
+
if (!extType) {
|
|
24
|
+
return null;
|
|
67
25
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return 'video';
|
|
74
|
-
if (ext && media_file_types_1.EXT_TO_MEDIA_TYPE[ext]) {
|
|
75
|
-
return media_file_types_1.EXT_TO_MEDIA_TYPE[ext];
|
|
26
|
+
const mt = (file.mimetype || '').toLowerCase().trim();
|
|
27
|
+
const mimeType = media_file_types_1.MIME_TO_MEDIA_TYPE[mt]
|
|
28
|
+
?? (mt.startsWith('image/') ? 'image' : mt.startsWith('audio/') ? 'audio' : mt.startsWith('video/') ? 'video' : undefined);
|
|
29
|
+
if (mimeType && mimeType !== extType) {
|
|
30
|
+
return null;
|
|
76
31
|
}
|
|
77
|
-
return
|
|
32
|
+
return extType;
|
|
78
33
|
}
|
|
79
34
|
validate(dto, files) {
|
|
80
35
|
const fieldFiles = files.filter(file => file.fieldname === this.options.fieldName);
|
|
81
36
|
return this.applyValidations(fieldFiles);
|
|
82
37
|
}
|
|
83
38
|
applyValidations(fieldFiles) {
|
|
84
|
-
const
|
|
39
|
+
const dangerousFileErrors = this.validateDangerousFiles(fieldFiles);
|
|
85
40
|
switch (this.options.type) {
|
|
86
41
|
case SolidMediaType.mediaSingle:
|
|
87
|
-
return [...
|
|
42
|
+
return [...dangerousFileErrors, ...this.validateMediaSingle(fieldFiles)];
|
|
88
43
|
case SolidMediaType.mediaMultiple:
|
|
89
|
-
return [...
|
|
44
|
+
return [...dangerousFileErrors, ...this.validateMediaMultiple(fieldFiles)];
|
|
90
45
|
default:
|
|
91
|
-
return
|
|
46
|
+
return dangerousFileErrors;
|
|
92
47
|
}
|
|
93
48
|
}
|
|
94
49
|
validateDangerousFiles(fieldFiles) {
|
|
@@ -96,24 +51,30 @@ class MediaFieldCrudManager {
|
|
|
96
51
|
.filter(fieldFile => (0, media_file_types_1.isDangerousMediaFile)(fieldFile))
|
|
97
52
|
.map(fieldFile => ({
|
|
98
53
|
field: this.options.fieldName,
|
|
99
|
-
error: `${this.
|
|
54
|
+
error: `${this.getFieldLabel()} file type not allowed. ` +
|
|
100
55
|
`${(0, media_file_types_1.getUploadedFileName)(fieldFile) || 'File'} is a potentially dangerous file type.`
|
|
101
56
|
}));
|
|
102
57
|
}
|
|
103
|
-
|
|
58
|
+
validateCommon(fieldFiles) {
|
|
59
|
+
return [
|
|
60
|
+
...this.validateRequired(fieldFiles),
|
|
61
|
+
...this.validateSize(fieldFiles),
|
|
62
|
+
...this.validateTypes(fieldFiles),
|
|
63
|
+
...this.validateAllowedExtensions(fieldFiles),
|
|
64
|
+
];
|
|
65
|
+
}
|
|
66
|
+
validateRequired(fieldFiles) {
|
|
104
67
|
const errors = [];
|
|
105
68
|
if (!this.options.isUpdate && this.options.required && fieldFiles.length === 0) {
|
|
106
69
|
errors.push({
|
|
107
70
|
field: this.options.fieldName,
|
|
108
|
-
error: `${this.
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
if (fieldFiles.length > 1) {
|
|
112
|
-
errors.push({
|
|
113
|
-
field: this.options.fieldName,
|
|
114
|
-
error: `${this.options.fieldName} must be a single file`
|
|
71
|
+
error: `${this.getFieldLabel()} is required`
|
|
115
72
|
});
|
|
116
73
|
}
|
|
74
|
+
return errors;
|
|
75
|
+
}
|
|
76
|
+
validateSize(fieldFiles) {
|
|
77
|
+
const errors = [];
|
|
117
78
|
if (this.options.mediaMaxSizeKb) {
|
|
118
79
|
for (let i = 0; i < fieldFiles.length; i++) {
|
|
119
80
|
const fieldFile = fieldFiles[i];
|
|
@@ -121,11 +82,15 @@ class MediaFieldCrudManager {
|
|
|
121
82
|
if (fieldFileSizeInBytes > this.options.mediaMaxSizeKb) {
|
|
122
83
|
errors.push({
|
|
123
84
|
field: this.options.fieldName,
|
|
124
|
-
error: `${this.
|
|
85
|
+
error: `${this.getFieldLabel()} with size ${fieldFileSizeInBytes} KB exceeds max size limit of ${this.options.mediaMaxSizeKb} KB`
|
|
125
86
|
});
|
|
126
87
|
}
|
|
127
88
|
}
|
|
128
89
|
}
|
|
90
|
+
return errors;
|
|
91
|
+
}
|
|
92
|
+
validateTypes(fieldFiles) {
|
|
93
|
+
const errors = [];
|
|
129
94
|
if (this.options.mediaTypes && this.options.mediaTypes.length > 0) {
|
|
130
95
|
const allowedFileTypes = this.options.mediaTypes;
|
|
131
96
|
for (let i = 0; i < fieldFiles.length; i++) {
|
|
@@ -134,7 +99,7 @@ class MediaFieldCrudManager {
|
|
|
134
99
|
if (!resolvedType || !allowedFileTypes.includes(resolvedType)) {
|
|
135
100
|
errors.push({
|
|
136
101
|
field: this.options.fieldName,
|
|
137
|
-
error: `${this.
|
|
102
|
+
error: `${this.getFieldLabel()} file type not allowed. ` +
|
|
138
103
|
`Allowed: ${allowedFileTypes.join(', ')}. ` +
|
|
139
104
|
`Received mimetype: ${fieldFile.mimetype}${resolvedType ? ` (mapped to ${resolvedType})` : ''}`
|
|
140
105
|
});
|
|
@@ -143,16 +108,36 @@ class MediaFieldCrudManager {
|
|
|
143
108
|
}
|
|
144
109
|
return errors;
|
|
145
110
|
}
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
if (!
|
|
111
|
+
validateAllowedExtensions(fieldFiles) {
|
|
112
|
+
const allowed = this.options.mediaAllowedExtensions;
|
|
113
|
+
if (!allowed || allowed.length === 0) {
|
|
114
|
+
return [];
|
|
115
|
+
}
|
|
116
|
+
const normalizedAllowed = new Set(allowed.map(ext => ext.toLowerCase().replace(/^\./, '')));
|
|
117
|
+
return fieldFiles
|
|
118
|
+
.filter(fieldFile => {
|
|
119
|
+
const ext = (0, media_file_types_1.getLowercaseFileExtension)((0, media_file_types_1.getUploadedFileName)(fieldFile));
|
|
120
|
+
return !ext || !normalizedAllowed.has(ext);
|
|
121
|
+
})
|
|
122
|
+
.map(fieldFile => ({
|
|
123
|
+
field: this.options.fieldName,
|
|
124
|
+
error: `${this.getFieldLabel()} file type not allowed. ` +
|
|
125
|
+
`Allowed extensions: ${[...normalizedAllowed].join(', ')}.`
|
|
126
|
+
}));
|
|
127
|
+
}
|
|
128
|
+
validateMediaSingle(fieldFiles) {
|
|
129
|
+
const errors = this.validateCommon(fieldFiles);
|
|
130
|
+
if (fieldFiles.length > 1) {
|
|
149
131
|
errors.push({
|
|
150
132
|
field: this.options.fieldName,
|
|
151
|
-
error: `${this.
|
|
133
|
+
error: `${this.getFieldLabel()} must be a single file`
|
|
152
134
|
});
|
|
153
135
|
}
|
|
154
136
|
return errors;
|
|
155
137
|
}
|
|
138
|
+
validateMediaMultiple(fieldFiles) {
|
|
139
|
+
return this.validateCommon(fieldFiles);
|
|
140
|
+
}
|
|
156
141
|
transformForCreate(dto) {
|
|
157
142
|
return dto;
|
|
158
143
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MediaFieldCrudManager.js","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/MediaFieldCrudManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { FieldCrudManager, ValidationError } from \"src/interfaces\";\nimport { EXT_TO_MEDIA_TYPE, getLowercaseFileExtension, getUploadedFileName, isDangerousMediaFile, MediaCategory } from \"src/constants/media-file-types\";\n\nexport enum SolidMediaType {\n mediaSingle = 'mediaSingle',\n mediaMultiple = 'mediaMultiple'\n}\n\nexport interface MediaFieldOptions {\n type: SolidMediaType;\n required: boolean | undefined | null;\n fieldName: string | undefined | null;\n mediaMaxSizeKb: number | undefined | null;\n mediaTypes: string[];\n isUpdate: boolean | undefined | null;\n}\n\ntype MediaType = MediaCategory;\n\nconst MIME_TO_MEDIA_TYPE: Record<string, MediaType> = {\n // Images\n 'image/png': 'image',\n 'image/jpeg': 'image',\n 'image/jpg': 'image',\n 'image/webp': 'image',\n 'image/gif': 'image',\n 'image/bmp': 'image',\n 'image/tiff': 'image',\n 'image/heic': 'image',\n 'image/heif': 'image',\n\n // Audio\n 'audio/mpeg': 'audio', // mp3\n 'audio/mp3': 'audio',\n 'audio/wav': 'audio',\n 'audio/x-wav': 'audio',\n 'audio/webm': 'audio',\n 'audio/ogg': 'audio',\n 'audio/aac': 'audio',\n 'audio/mp4': 'audio', // m4a often shows as audio/mp4\n 'audio/x-m4a': 'audio',\n 'audio/flac': 'audio',\n\n // Video\n 'video/mp4': 'video',\n 'video/mpeg': 'video',\n 'video/webm': 'video',\n 'video/ogg': 'video',\n 'video/quicktime': 'video', // mov\n 'video/x-msvideo': 'video', // avi\n 'video/x-matroska': 'video',// mkv\n 'video/3gpp': 'video',\n 'video/3gpp2': 'video',\n\n // Documents / files (treat as \"file\")\n 'application/pdf': 'pdf',\n 'text/plain': 'file',\n 'text/markdown': 'file',\n 'application/json': 'file',\n 'text/csv': 'file',\n\n // Office\n 'application/msword': 'file', // doc\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'file', // docx\n 'application/vnd.ms-excel': 'file', // xls\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'file', // xlsx\n 'application/vnd.ms-powerpoint': 'file', // ppt\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'file', // pptx,\n\n // Archives (optional)\n 'application/zip': 'file',\n 'application/x-zip-compressed': 'file',\n 'application/x-rar-compressed': 'file',\n 'application/x-7z-compressed': 'file',\n};\n\nexport class MediaFieldCrudManager implements FieldCrudManager {\n\n constructor(private readonly options: MediaFieldOptions) {\n }\n\n private resolveMediaType(file: Express.Multer.File): MediaType | null {\n // Belt-and-braces: dangerous files are already rejected outright by\n // validateDangerousFiles, but never let one resolve to a usable category.\n if (isDangerousMediaFile(file)) {\n return null;\n }\n\n const ext = getLowercaseFileExtension(getUploadedFileName(file));\n const mt = (file.mimetype || '').toLowerCase().trim();\n if (mt && MIME_TO_MEDIA_TYPE[mt]) {\n return MIME_TO_MEDIA_TYPE[mt];\n }\n\n // Some libs may send \"image/*\" etc. Treat broad families safely.\n if (mt.startsWith('image/')) return 'image';\n if (mt.startsWith('audio/')) return 'audio';\n if (mt.startsWith('video/')) return 'video';\n\n // Fallback to extension if provided (also covers generic/unrecognized\n // mimetypes such as application/octet-stream).\n if (ext && EXT_TO_MEDIA_TYPE[ext]) {\n return EXT_TO_MEDIA_TYPE[ext];\n }\n\n return null;\n }\n\n validate(dto: any, files: Array<Express.Multer.File>): ValidationError[] {\n const fieldFiles = files.filter(file => file.fieldname === this.options.fieldName);\n return this.applyValidations(fieldFiles);\n }\n\n private applyValidations(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n // Runs for every media field type and regardless of the admin-configured mediaTypes\n // allowlist - a dangerous upload is never acceptable, so this must not sit behind\n // the optional type checks below.\n const errors = this.validateDangerousFiles(fieldFiles);\n\n switch (this.options.type) {\n case SolidMediaType.mediaSingle:\n return [...errors, ...this.validateMediaSingle(fieldFiles)];\n case SolidMediaType.mediaMultiple:\n return [...errors, ...this.validateMediaMultiple(fieldFiles)];\n default:\n return errors;\n }\n }\n\n private validateDangerousFiles(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n return fieldFiles\n .filter(fieldFile => isDangerousMediaFile(fieldFile))\n .map(fieldFile => ({\n field: this.options.fieldName,\n error: `${this.options.fieldName} file type not allowed. ` +\n `${getUploadedFileName(fieldFile) || 'File'} is a potentially dangerous file type.`\n }));\n }\n\n private validateMediaSingle(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n const errors: ValidationError[] = [];\n if (!this.options.isUpdate && this.options.required && fieldFiles.length === 0) {\n errors.push({\n field: this.options.fieldName,\n error: `${this.options.fieldName} is required`\n });\n }\n if (fieldFiles.length > 1) {\n errors.push({\n field: this.options.fieldName,\n error: `${this.options.fieldName} must be a single file`\n });\n }\n // validate size\n if (this.options.mediaMaxSizeKb) {\n for (let i = 0; i < fieldFiles.length; i++) {\n const fieldFile = fieldFiles[i];\n const fieldFileSizeInBytes = Math.ceil(fieldFile.size / 1024);\n if (fieldFileSizeInBytes > this.options.mediaMaxSizeKb) {\n errors.push({\n field: this.options.fieldName,\n error: `${this.options.fieldName} with size ${fieldFileSizeInBytes} KB exceeds max size limit of ${this.options.mediaMaxSizeKb} KB`\n });\n }\n }\n }\n // validate type\n if (this.options.mediaTypes && this.options.mediaTypes.length > 0) {\n const allowedFileTypes = this.options.mediaTypes as MediaType[];\n\n for (let i = 0; i < fieldFiles.length; i++) {\n const fieldFile = fieldFiles[i];\n\n const resolvedType = this.resolveMediaType(fieldFile);\n if (!resolvedType || !allowedFileTypes.includes(resolvedType)) {\n errors.push({\n field: this.options.fieldName,\n error: `${this.options.fieldName} file type not allowed. ` +\n `Allowed: ${allowedFileTypes.join(', ')}. ` +\n `Received mimetype: ${fieldFile.mimetype}${resolvedType ? ` (mapped to ${resolvedType})` : ''}`\n });\n }\n }\n }\n\n return errors;\n }\n\n private validateMediaMultiple(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n const errors: ValidationError[] = [];\n if (!this.options.isUpdate && this.options.required && fieldFiles.length === 0) {\n errors.push({\n field: this.options.fieldName,\n error: `${this.options.fieldName} is required`\n });\n }\n return errors;\n }\n\n transformForCreate(dto: any): any {\n return dto;\n }\n\n // Validation to be applied\n}\n"]}
|
|
1
|
+
{"version":3,"file":"MediaFieldCrudManager.js","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/MediaFieldCrudManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { FieldCrudManager, ValidationError } from \"src/interfaces\";\nimport { EXT_TO_MEDIA_TYPE, getLowercaseFileExtension, getUploadedFileName, isDangerousMediaFile, MediaCategory, MIME_TO_MEDIA_TYPE } from \"src/constants/media-file-types\";\n\nexport enum SolidMediaType {\n mediaSingle = 'mediaSingle',\n mediaMultiple = 'mediaMultiple'\n}\n\nexport interface MediaFieldOptions {\n type: SolidMediaType;\n required: boolean | undefined | null;\n fieldName: string | undefined | null;\n fieldLabel?: string | undefined | null;\n mediaMaxSizeKb: number | undefined | null;\n mediaTypes: string[];\n mediaAllowedExtensions?: string[] | null;\n isUpdate: boolean | undefined | null;\n}\n\ntype MediaType = MediaCategory;\n\nexport class MediaFieldCrudManager implements FieldCrudManager {\n\n constructor(private readonly options: MediaFieldOptions) {\n }\n\n private getFieldLabel(): string {\n return this.options.fieldLabel || this.options.fieldName || 'File';\n }\n\n private resolveMediaType(file: Express.Multer.File): MediaType | null {\n // Belt-and-braces: dangerous files are already rejected outright by\n // validateDangerousFiles, but never let one resolve to a usable category.\n if (isDangerousMediaFile(file)) {\n return null;\n }\n\n // Extension is authoritative: a declared mimetype is fully attacker-controlled and\n // proved insufficient on its own (a .msi uploaded as image/png previously resolved to\n // 'image', since the mimetype match short-circuited before the extension was ever\n // checked). The extension must independently resolve to a known-safe category before\n // anything is accepted - not merely \"not on the denylist\".\n const ext = getLowercaseFileExtension(getUploadedFileName(file));\n const extType = ext ? EXT_TO_MEDIA_TYPE[ext] : undefined;\n if (!extType) {\n return null;\n }\n\n // The mimetype may only confirm or veto what the extension already established, never\n // grant a category on its own. A mimetype that doesn't resolve to anything (e.g.\n // application/octet-stream) has no opinion and is treated as agreeing.\n const mt = (file.mimetype || '').toLowerCase().trim();\n const mimeType = MIME_TO_MEDIA_TYPE[mt]\n ?? (mt.startsWith('image/') ? 'image' : mt.startsWith('audio/') ? 'audio' : mt.startsWith('video/') ? 'video' : undefined);\n if (mimeType && mimeType !== extType) {\n return null;\n }\n\n return extType;\n }\n\n validate(dto: any, files: Array<Express.Multer.File>): ValidationError[] {\n const fieldFiles = files.filter(file => file.fieldname === this.options.fieldName);\n return this.applyValidations(fieldFiles);\n }\n\n private applyValidations(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n // A dangerous upload is never acceptable, regardless of admin config, so this is the\n // only check that sits outside validateCommon() and can't be skipped either way below.\n const dangerousFileErrors = this.validateDangerousFiles(fieldFiles);\n\n switch (this.options.type) {\n case SolidMediaType.mediaSingle:\n return [...dangerousFileErrors, ...this.validateMediaSingle(fieldFiles)];\n case SolidMediaType.mediaMultiple:\n return [...dangerousFileErrors, ...this.validateMediaMultiple(fieldFiles)];\n default:\n return dangerousFileErrors;\n }\n }\n\n private validateDangerousFiles(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n return fieldFiles\n .filter(fieldFile => isDangerousMediaFile(fieldFile))\n .map(fieldFile => ({\n field: this.options.fieldName,\n error: `${this.getFieldLabel()} file type not allowed. ` +\n `${getUploadedFileName(fieldFile) || 'File'} is a potentially dangerous file type.`\n }));\n }\n\n // Every optional, admin-configured, per-field check - no-ops when its setting is unset -\n // shared between mediaSingle and mediaMultiple so neither can drift out of sync with it.\n private validateCommon(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n return [\n ...this.validateRequired(fieldFiles),\n ...this.validateSize(fieldFiles),\n ...this.validateTypes(fieldFiles),\n ...this.validateAllowedExtensions(fieldFiles),\n ];\n }\n\n private validateRequired(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n const errors: ValidationError[] = [];\n if (!this.options.isUpdate && this.options.required && fieldFiles.length === 0) {\n errors.push({\n field: this.options.fieldName,\n error: `${this.getFieldLabel()} is required`\n });\n }\n return errors;\n }\n\n private validateSize(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n const errors: ValidationError[] = [];\n if (this.options.mediaMaxSizeKb) {\n for (let i = 0; i < fieldFiles.length; i++) {\n const fieldFile = fieldFiles[i];\n const fieldFileSizeInBytes = Math.ceil(fieldFile.size / 1024);\n if (fieldFileSizeInBytes > this.options.mediaMaxSizeKb) {\n errors.push({\n field: this.options.fieldName,\n error: `${this.getFieldLabel()} with size ${fieldFileSizeInBytes} KB exceeds max size limit of ${this.options.mediaMaxSizeKb} KB`\n });\n }\n }\n }\n return errors;\n }\n\n private validateTypes(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n const errors: ValidationError[] = [];\n if (this.options.mediaTypes && this.options.mediaTypes.length > 0) {\n const allowedFileTypes = this.options.mediaTypes as MediaType[];\n\n for (let i = 0; i < fieldFiles.length; i++) {\n const fieldFile = fieldFiles[i];\n\n const resolvedType = this.resolveMediaType(fieldFile);\n if (!resolvedType || !allowedFileTypes.includes(resolvedType)) {\n errors.push({\n field: this.options.fieldName,\n error: `${this.getFieldLabel()} file type not allowed. ` +\n `Allowed: ${allowedFileTypes.join(', ')}. ` +\n `Received mimetype: ${fieldFile.mimetype}${resolvedType ? ` (mapped to ${resolvedType})` : ''}`\n });\n }\n }\n }\n return errors;\n }\n\n private validateAllowedExtensions(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n const allowed = this.options.mediaAllowedExtensions;\n if (!allowed || allowed.length === 0) {\n return [];\n }\n\n const normalizedAllowed = new Set(allowed.map(ext => ext.toLowerCase().replace(/^\\./, '')));\n return fieldFiles\n .filter(fieldFile => {\n const ext = getLowercaseFileExtension(getUploadedFileName(fieldFile));\n return !ext || !normalizedAllowed.has(ext);\n })\n .map(fieldFile => ({\n field: this.options.fieldName,\n error: `${this.getFieldLabel()} file type not allowed. ` +\n `Allowed extensions: ${[...normalizedAllowed].join(', ')}.`\n }));\n }\n\n private validateMediaSingle(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n const errors = this.validateCommon(fieldFiles);\n if (fieldFiles.length > 1) {\n errors.push({\n field: this.options.fieldName,\n error: `${this.getFieldLabel()} must be a single file`\n });\n }\n return errors;\n }\n\n private validateMediaMultiple(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n return this.validateCommon(fieldFiles);\n }\n\n transformForCreate(dto: any): any {\n return dto;\n }\n\n // Validation to be applied\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShortTextFieldCrudManager.d.ts","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/ShortTextFieldCrudManager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"ShortTextFieldCrudManager.d.ts","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/ShortTextFieldCrudManager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGnE,MAAM,WAAW,qBAAqB;IAClC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAClC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACxC,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;IACrC,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,yBAA0B,YAAW,gBAAgB;IAC9D,OAAO,CAAC,OAAO,CAAwB;gBAE3B,OAAO,EAAE,qBAAqB;IAI1C,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAG,MAAM,EAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,eAAe,EAAE;IAMzE,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,sBAAsB;IAQ9B,kBAAkB,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG;IAKjC,OAAO,CAAC,uBAAuB;IAG/B,OAAO,CAAC,uBAAuB;IAG/B,OAAO,CAAC,sBAAsB;IAG9B,OAAO,CAAC,yBAAyB;CAGpC"}
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ShortTextFieldCrudManager = void 0;
|
|
4
4
|
const class_validator_1 = require("class-validator");
|
|
5
|
+
const textFieldCrudManagerUtils_1 = require("./textFieldCrudManagerUtils");
|
|
5
6
|
class ShortTextFieldCrudManager {
|
|
6
7
|
constructor(options) {
|
|
7
8
|
this.options = options;
|
|
8
9
|
}
|
|
9
10
|
validate(dto, _files) {
|
|
10
|
-
const fieldValue = dto[this.options.fieldName];
|
|
11
|
+
const fieldValue = (0, textFieldCrudManagerUtils_1.normalizeTextFieldValue)(dto[this.options.fieldName]);
|
|
11
12
|
return this.applyValidations(fieldValue);
|
|
12
13
|
}
|
|
13
14
|
applyValidations(fieldValue) {
|
|
@@ -26,7 +27,7 @@ class ShortTextFieldCrudManager {
|
|
|
26
27
|
return errors;
|
|
27
28
|
}
|
|
28
29
|
transformForCreate(dto) {
|
|
29
|
-
return dto;
|
|
30
|
+
return (0, textFieldCrudManagerUtils_1.normalizeTextFieldInDto)(dto, this.options.fieldName);
|
|
30
31
|
}
|
|
31
32
|
isApplyStringValidation() {
|
|
32
33
|
return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShortTextFieldCrudManager.js","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/ShortTextFieldCrudManager.ts"],"names":[],"mappings":";;;AAAA,qDAAiF;
|
|
1
|
+
{"version":3,"file":"ShortTextFieldCrudManager.js","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/ShortTextFieldCrudManager.ts"],"names":[],"mappings":";;;AAAA,qDAAiF;AAEjF,2EAA+F;AAS/F,MAAa,yBAAyB;IAGlC,YAAY,OAA8B;QACtC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;IAED,QAAQ,CAAC,GAAQ,EAAG,MAAiC;QACjD,MAAM,UAAU,GAAQ,IAAA,mDAAuB,EAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;QAC7E,OAAO,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC7C,CAAC;IAGO,gBAAgB,CAAC,UAAe;QACpC,MAAM,MAAM,GAAsB,EAAE,CAAC;QACrC,IAAI,CAAC,yBAAyB,EAAE,IAAI,IAAA,yBAAO,EAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,UAAU,IAAI,CAAC,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CAAA,CAAC,CAAC,WAAW,CAAC;QAC7K,IAAI,IAAA,4BAAU,EAAC,UAAU,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAEO,sBAAsB,CAAC,UAAe;QAC1C,MAAM,MAAM,GAAsB,EAAE,CAAC;QACrC,IAAI,CAAC,uBAAuB,EAAE,IAAI,CAAC,IAAA,0BAAQ,EAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;QACvJ,IAAI,CAAC,uBAAuB,EAAE,IAAI,CAAC,IAAA,wBAAM,EAAC,UAAU,EAAE,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;QAC/K,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC,IAAA,yBAAO,EAAC,UAAU,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,gCAAgC,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;QACrM,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,kBAAkB,CAAC,GAAQ;QACvB,OAAO,IAAA,mDAAuB,EAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChE,CAAC;IAGO,uBAAuB;QAC3B,OAAO,IAAI,CAAC;IAChB,CAAC;IACO,uBAAuB;QAC3B,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACrC,CAAC;IACO,sBAAsB;QAC1B,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,KAAK,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IACxI,CAAC;IACO,yBAAyB;QAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;IACjC,CAAC;CACJ;AA/CD,8DA+CC","sourcesContent":["import { isEmpty, isNotEmpty, isString, length, matches } from \"class-validator\";\nimport { FieldCrudManager, ValidationError } from \"src/interfaces\";\nimport { normalizeTextFieldInDto, normalizeTextFieldValue } from \"./textFieldCrudManagerUtils\";\n\nexport interface ShortTextFieldOptions {\n length: number | undefined | null;\n regexPattern: string | undefined | null;\n required: boolean | undefined | null;\n fieldName: string;\n}\n\nexport class ShortTextFieldCrudManager implements FieldCrudManager {\n private options: ShortTextFieldOptions;\n\n constructor(options: ShortTextFieldOptions) {\n this.options = options;\n }\n\n validate(dto: any, _files:Array<Express.Multer.File>): ValidationError[] {\n const fieldValue: any = normalizeTextFieldValue(dto[this.options.fieldName]);\n return this.applyValidations(fieldValue);\n }\n\n\n private applyValidations(fieldValue: any): ValidationError[] {\n const errors: ValidationError[] = [];\n this.isApplyRequiredValidation() && isEmpty(fieldValue) ? errors.push({ field: this.options.fieldName, error: `Field: ${this.options.fieldName} is required` }): \"no errors\";\n if (isNotEmpty(fieldValue)) {\n errors.push(...this.applyFormatValidations(fieldValue));\n }\n return errors;\n }\n\n private applyFormatValidations(fieldValue: any): ValidationError[] {\n const errors: ValidationError[] = [];\n this.isApplyStringValidation() && !isString(fieldValue) ? errors.push({ field: this.options.fieldName, error: 'Field is not a string' }) : \"no errors\";\n this.isApplyLengthValidation() && !length(fieldValue, 1, this.options.length) ? errors.push({ field: this.options.fieldName, error: 'Field length is invalid' }) : \"no errors\"; //FIXME min length to be handled\n this.isApplyRegexValidation() && !matches(fieldValue, new RegExp(this.options.regexPattern)) ? errors.push({ field: this.options.fieldName, error: 'Field regex pattern is invalid' }) : \"no errors\";\n return errors;\n }\n\n transformForCreate(dto: any): any {\n return normalizeTextFieldInDto(dto, this.options.fieldName);\n }\n\n // Validation to be applied\n private isApplyStringValidation(): boolean {\n return true;\n }\n private isApplyLengthValidation(): boolean {\n return (this.options.length > 0);\n }\n private isApplyRegexValidation(): boolean {\n return this.options.regexPattern !== null && this.options.regexPattern !== undefined && this.options.regexPattern.trim().length > 0;\n }\n private isApplyRequiredValidation(): boolean {\n return this.options.required;\n }\n}"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textFieldCrudManagerUtils.d.ts","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/textFieldCrudManagerUtils.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,uBAAuB,GAAI,YAAY,GAAG,KAAG,GAEzD,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,KAAK,GAAG,EAAE,YAAY,MAAM,GAAG,IAAI,KAAG,GAO7E,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeTextFieldInDto = exports.normalizeTextFieldValue = void 0;
|
|
4
|
+
const class_validator_1 = require("class-validator");
|
|
5
|
+
const normalizeTextFieldValue = (fieldValue) => {
|
|
6
|
+
return (0, class_validator_1.isString)(fieldValue) ? fieldValue.trim() : fieldValue;
|
|
7
|
+
};
|
|
8
|
+
exports.normalizeTextFieldValue = normalizeTextFieldValue;
|
|
9
|
+
const normalizeTextFieldInDto = (dto, fieldName) => {
|
|
10
|
+
if (!fieldName || !Object.prototype.hasOwnProperty.call(dto, fieldName)) {
|
|
11
|
+
return dto;
|
|
12
|
+
}
|
|
13
|
+
dto[fieldName] = (0, exports.normalizeTextFieldValue)(dto[fieldName]);
|
|
14
|
+
return dto;
|
|
15
|
+
};
|
|
16
|
+
exports.normalizeTextFieldInDto = normalizeTextFieldInDto;
|
|
17
|
+
//# sourceMappingURL=textFieldCrudManagerUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textFieldCrudManagerUtils.js","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/textFieldCrudManagerUtils.ts"],"names":[],"mappings":";;;AAAA,qDAA2C;AAEpC,MAAM,uBAAuB,GAAG,CAAC,UAAe,EAAO,EAAE;IAC5D,OAAO,IAAA,0BAAQ,EAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC;AACjE,CAAC,CAAC;AAFW,QAAA,uBAAuB,2BAElC;AAEK,MAAM,uBAAuB,GAAG,CAAC,GAAQ,EAAE,SAAyB,EAAO,EAAE;IAChF,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,CAAC;QACtE,OAAO,GAAG,CAAC;IACf,CAAC;IAED,GAAG,CAAC,SAAS,CAAC,GAAG,IAAA,+BAAuB,EAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;IACzD,OAAO,GAAG,CAAC;AACf,CAAC,CAAC;AAPW,QAAA,uBAAuB,2BAOlC","sourcesContent":["import { isString } from \"class-validator\";\n\nexport const normalizeTextFieldValue = (fieldValue: any): any => {\n return isString(fieldValue) ? fieldValue.trim() : fieldValue;\n};\n\nexport const normalizeTextFieldInDto = (dto: any, fieldName?: string | null): any => {\n if (!fieldName || !Object.prototype.hasOwnProperty.call(dto, fieldName)) {\n return dto;\n }\n\n dto[fieldName] = normalizeTextFieldValue(dto[fieldName]);\n return dto;\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-download.helper.d.ts","sourceRoot":"","sources":["../../src/helpers/file-download.helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IAEjB,WAAW,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC;IAEtC,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;
|
|
1
|
+
{"version":3,"file":"file-download.helper.d.ts","sourceRoot":"","sources":["../../src/helpers/file-download.helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IAEjB,WAAW,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC;IAEtC,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;AAoBD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,yBAAyB,GAAG,IAAI,CAe9F"}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.setFileDownloadHeaders = setFileDownloadHeaders;
|
|
4
|
+
function buildContentDisposition(disposition, fileName) {
|
|
5
|
+
const name = (fileName || "file").replace(/[\r\n]/g, "");
|
|
6
|
+
const asciiFallback = name.replace(/[^\x20-\x7E]/g, "_").replace(/["\\]/g, "_") || "file";
|
|
7
|
+
return `${disposition}; filename="${asciiFallback}"; filename*=UTF-8''${encodeURIComponent(name)}`;
|
|
8
|
+
}
|
|
4
9
|
function setFileDownloadHeaders(res, options) {
|
|
5
10
|
const disposition = options.disposition ?? "attachment";
|
|
6
|
-
res.setHeader("Content-Disposition",
|
|
11
|
+
res.setHeader("Content-Disposition", buildContentDisposition(disposition, options.fileName));
|
|
7
12
|
res.setHeader("Content-Type", options.mimeType);
|
|
8
13
|
res.setHeader("Access-Control-Expose-Headers", "Content-Disposition, Content-Type");
|
|
9
14
|
res.setHeader("X-Content-Type-Options", "nosniff");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-download.helper.js","sourceRoot":"","sources":["../../src/helpers/file-download.helper.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"file-download.helper.js","sourceRoot":"","sources":["../../src/helpers/file-download.helper.ts"],"names":[],"mappings":";;AA6BA,wDAeC;AA1BD,SAAS,uBAAuB,CAAC,WAAoC,EAAE,QAAgB;IACrF,MAAM,IAAI,GAAG,CAAC,QAAQ,IAAI,MAAM,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACzD,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC;IAE1F,OAAO,GAAG,WAAW,eAAe,aAAa,uBAAuB,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;AACrG,CAAC;AAMD,SAAgB,sBAAsB,CAAC,GAAa,EAAE,OAAkC;IACtF,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,YAAY,CAAC;IAExD,GAAG,CAAC,SAAS,CAAC,qBAAqB,EAAE,uBAAuB,CAAC,WAAW,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC7F,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChD,GAAG,CAAC,SAAS,CAAC,+BAA+B,EAAE,mCAAmC,CAAC,CAAC;IAKpF,GAAG,CAAC,SAAS,CAAC,wBAAwB,EAAE,SAAS,CAAC,CAAC;IAEnD,IAAI,OAAO,CAAC,yBAAyB,EAAE,CAAC;QACtC,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,cAAc,CAAC,CAAC;IAChE,CAAC;AACH,CAAC","sourcesContent":["import type { Response } from \"express\";\n\nexport interface FileDownloadHeaderOptions {\n fileName: string;\n mimeType: string;\n /** Defaults to 'attachment'; only pass 'inline' for types known safe to render. */\n disposition?: \"inline\" | \"attachment\";\n /** Opt in for assets loaded cross-origin by the UI (e.g. media served to :3000). */\n crossOriginResourcePolicy?: boolean;\n}\n\n/**\n * Builds an RFC 6266 Content-Disposition value. The file name is attacker-controlled (it comes\n * from the uploaded originalFileName), so it can't be interpolated raw: a quote would close the\n * quoted-string early and let the rest of the name forge further header parameters. The ASCII\n * fallback is stripped to a safe subset and the real name is carried in the RFC 5987\n * `filename*` parameter, which is also what preserves non-ASCII names correctly.\n */\nfunction buildContentDisposition(disposition: \"inline\" | \"attachment\", fileName: string): string {\n const name = (fileName || \"file\").replace(/[\\r\\n]/g, \"\");\n const asciiFallback = name.replace(/[^\\x20-\\x7E]/g, \"_\").replace(/[\"\\\\]/g, \"_\") || \"file\";\n\n return `${disposition}; filename=\"${asciiFallback}\"; filename*=UTF-8''${encodeURIComponent(name)}`;\n}\n\n/**\n * Single place that stamps the response headers for every streamed file download, so the\n * security headers can't be applied to one endpoint and forgotten on the next.\n */\nexport function setFileDownloadHeaders(res: Response, options: FileDownloadHeaderOptions): void {\n const disposition = options.disposition ?? \"attachment\";\n\n res.setHeader(\"Content-Disposition\", buildContentDisposition(disposition, options.fileName));\n res.setHeader(\"Content-Type\", options.mimeType);\n res.setHeader(\"Access-Control-Expose-Headers\", \"Content-Disposition, Content-Type\");\n\n // Prevent the browser from ever content-sniffing a served file into something more\n // dangerous than its declared Content-Type (e.g. rendering a mislabeled upload as HTML\n // and executing embedded script).\n res.setHeader(\"X-Content-Type-Options\", \"nosniff\");\n\n if (options.crossOriginResourcePolicy) {\n res.setHeader(\"Cross-Origin-Resource-Policy\", \"cross-origin\");\n }\n}\n"]}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { HelmetOptions } from "helmet";
|
|
2
|
-
export
|
|
2
|
+
export interface SolidSecurityOptions {
|
|
3
|
+
frameAncestors?: string[];
|
|
4
|
+
}
|
|
5
|
+
export declare const DEFAULT_FRAME_ANCESTORS: string[];
|
|
6
|
+
export declare function buildDefaultSecurityHeaderOptions(options?: SolidSecurityOptions): Readonly<HelmetOptions>;
|
|
3
7
|
type Source = "self" | "none" | string;
|
|
4
8
|
type DirectiveConfig = "self" | "none" | Source[];
|
|
5
9
|
export type PermissionsPolicyConfig = Record<string, DirectiveConfig>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security.helper.d.ts","sourceRoot":"","sources":["../../src/helpers/security.helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"security.helper.d.ts","sourceRoot":"","sources":["../../src/helpers/security.helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAGvC,MAAM,WAAW,oBAAoB;IAKnC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,eAAO,MAAM,uBAAuB,UAQnC,CAAC;AASF,wBAAgB,iCAAiC,CAC/C,OAAO,GAAE,oBAAyB,GACjC,QAAQ,CAAC,aAAa,CAAC,CA+CzB;AAID,KAAK,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AACvC,KAAK,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;AAClD,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;AAEtE,eAAO,MAAM,0BAA0B,EAAE,uBAaxC,CAAC;AAEF,wBAAgB,4BAA4B,CAC1C,SAAS,GAAE,OAAO,CAAC,uBAAuB,CAAM,GAC/C,MAAM,CAKR;AAeD,eAAO,MAAM,qBAAqB,iFAC8C,CAAC;AAEjF,wBAAgB,sBAAsB,KAElC,MAAM,OAAO,SAAS,EAAE,OAAO,EAC/B,MAAM,OAAO,SAAS,EAAE,QAAQ,EAChC,MAAM,OAAO,SAAS,EAAE,YAAY,UAKvC"}
|