@venizia/ignis 0.4.7-1 → 0.4.7-2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/base/applications/base.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,KAAK,EACV,mBAAmB,EAEnB,cAAc,EACd,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAWhC,OAAO,EAAE,kBAAkB,EAA0B,MAAM,gBAAgB,CAAC;AAG5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAgC/D,8BAAsB,eAAgB,SAAQ,iBAAkB,YAAW,gBAAgB;IACzF,SAAS,CAAC,eAAe,CAAC,EAAE,cAAc,CAAC;IAC3C,SAAS,CAAC,mBAAmB,CAAC,EAAE,oBAAoB,CAAC;IAErD,SAAS,CAAC,aAAa,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM;IAKtD,6IAA6I;IAC9H,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAuDnD,eAAe,IAAI,cAAc,CAAC,oBAAoB,CAAC;IAIjD,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IA0ErC,4KAA4K;cAC5J,oBAAoB,CAAC,IAAI,EAAE;QACzC,QAAQ,EAAE,cAAc,CAAC;QACzB,YAAY,EAAE,oBAAoB,CAAC;QACnC,eAAe,EAAE,MAAM,EAAE,CAAC;QAC1B,MAAM,EAAE,OAAO,CAAC;KACjB,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBjB,SAAS,CAAC,mBAAmB,CAAC,IAAI,EAAE;QAClC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/B,KAAK,EAAE,mBAAmB,CAAC;KAC5B,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAY1B,gMAAgM;IAChM,SAAS,CAAC,+BAA+B,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,mBAAmB,CAAA;KAAE,GAAG,OAAO;IAQlF,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB3C,MAAM,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;IAiBtD;;;;OAIG;IACH,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE;IAgClD,kGAAkG;cAC/E,oBAAoB,IAAI,kBAAkB;IAO7D,gKAAgK;cACvI,0BAA0B;IA4BnD,8MAA8M;IAC9M,SAAS,CAAC,YAAY;IAmDtB;;;OAGG;IACY,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;cAIvB,eAAe,IAAI,iBAAiB,EAAE;IAyCzD;;;OAGG;IACH,SAAS,CAAC,0BAA0B,IAAI,IAAI;CAK7C"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/base/applications/base.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,KAAK,EACV,mBAAmB,EAEnB,cAAc,EACd,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAWhC,OAAO,EAAE,kBAAkB,EAA0B,MAAM,gBAAgB,CAAC;AAI5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAgC/D,8BAAsB,eAAgB,SAAQ,iBAAkB,YAAW,gBAAgB;IACzF,SAAS,CAAC,eAAe,CAAC,EAAE,cAAc,CAAC;IAC3C,SAAS,CAAC,mBAAmB,CAAC,EAAE,oBAAoB,CAAC;IAErD,SAAS,CAAC,aAAa,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM;IAKtD,6IAA6I;IAC9H,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAuDnD,eAAe,IAAI,cAAc,CAAC,oBAAoB,CAAC;IAIjD,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IA0ErC,4KAA4K;cAC5J,oBAAoB,CAAC,IAAI,EAAE;QACzC,QAAQ,EAAE,cAAc,CAAC;QACzB,YAAY,EAAE,oBAAoB,CAAC;QACnC,eAAe,EAAE,MAAM,EAAE,CAAC;QAC1B,MAAM,EAAE,OAAO,CAAC;KACjB,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBjB,SAAS,CAAC,mBAAmB,CAAC,IAAI,EAAE;QAClC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/B,KAAK,EAAE,mBAAmB,CAAC;KAC5B,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAY1B,gMAAgM;IAChM,SAAS,CAAC,+BAA+B,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,mBAAmB,CAAA;KAAE,GAAG,OAAO;IAQlF,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB3C,MAAM,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;IAiBtD;;;;OAIG;IACH,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE;IAgClD,kGAAkG;cAC/E,oBAAoB,IAAI,kBAAkB;IAO7D,gKAAgK;cACvI,0BAA0B;IA4BnD,8MAA8M;IAC9M,SAAS,CAAC,YAAY;IAmDtB;;;OAGG;IACY,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;cAKvB,eAAe,IAAI,iBAAiB,EAAE;IAyCzD;;;OAGG;IACH,SAAS,CAAC,0BAA0B,IAAI,IAAI;CAK7C"}
@@ -11,6 +11,7 @@ import { applicationEnvironment, SecretsHelperFactory, PerformanceUtility, Envir
11
11
  import { contextStorage, tryGetContext } from 'hono/context-storage';
12
12
  import { AppErrorMiddleware, EmojiFaviconMiddleware } from '../middlewares/index.js';
13
13
  import { serveStatic } from 'hono/bun';
14
+ import { ServerLoggerStartup } from './common/index.js';
14
15
  import { ServerBootSteps } from './boot-steps.js';
15
16
  import { ServerApplication } from './server.js';
16
17
  /** Maps a secret bundle to env names: the explicit `keys` mapping when present, otherwise every bundle key under `prefix`. */
@@ -109,9 +110,12 @@ export class BaseApplication extends ServerApplication {
109
110
  }
110
111
  logger.warn('Secret provider failed; falling back to system-envs | env: %s | error: %s', env, error);
111
112
  if (provider) {
112
- await provider
113
- .shutdown()
114
- .catch((shutdownError) => logger.error('Failed to shut down partially-built provider during fallback | error: %s', shutdownError));
113
+ try {
114
+ await provider.shutdown();
115
+ }
116
+ catch (shutdownError) {
117
+ logger.error('Failed to shut down partially-built provider during fallback | error: %s', shutdownError);
118
+ }
115
119
  }
116
120
  const result2 = await SecretsHelperFactory.create({
117
121
  provider: SecretProviders.SYSTEM_ENVS,
@@ -292,6 +296,7 @@ export class BaseApplication extends ServerApplication {
292
296
  * `getBootSequence()`/`runBootSequence()` throws here before any socket binds.
293
297
  */
294
298
  async initialize() {
299
+ await ServerLoggerStartup.selectDefault();
295
300
  await this.runBootSequence({ steps: this.getBootSequence() });
296
301
  }
297
302
  getBootSequence() {
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../../src/base/applications/base.ts"],"names":[],"mappings":"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","sourcesContent":["import { ScopeFilterUtility } from '@venizia/ignis-connectors';\nimport { ControllerTransports } from '@venizia/ignis-kernel';\nimport { BindingNamespaces, CoreBindings } from '@venizia/ignis-kernel';\nimport { EnvironmentKeys } from '@/common/environments';\nimport { RequestTrackerComponent } from '@/components';\nimport { GrpcComponent } from '@/components/controller/grpc';\nimport {\n BindingScopes,\n BindingValueTypes,\n BootSequence,\n MetadataRegistry,\n RequestContextRegistry,\n} from '@venizia/ignis-kernel';\nimport type { ILogger } from '@venizia/ignis-helpers/core';\nimport type { ValueOrPromise } from '@venizia/ignis-helpers/common';\nimport type {\n ISecretHydrateEntry,\n ISecretRotatable,\n ISecretsHelper,\n ISecretsRegistration,\n} from '@venizia/ignis-helpers';\nimport { ParseUtility, getError } from '@venizia/ignis-helpers/core';\nimport { HTTP, ObjectUtility } from '@venizia/ignis-helpers/common';\nimport {\n applicationEnvironment,\n SecretsHelperFactory,\n PerformanceUtility,\n Environment,\n SecretProviders,\n} from '@venizia/ignis-helpers';\nimport { contextStorage, tryGetContext } from 'hono/context-storage';\nimport { AppErrorMiddleware, EmojiFaviconMiddleware } from '../middlewares';\nimport { serveStatic } from 'hono/bun';\nimport { ServerBootSteps } from './boot-steps';\nimport { ServerApplication } from './server';\nimport type { IRestApplication } from '@venizia/ignis-kernel';\nimport type { IBootSequenceStep } from '@venizia/ignis-kernel';\n\n/** Maps a secret bundle to env names: the explicit `keys` mapping when present, otherwise every bundle key under `prefix`. */\nconst selectSecretEnvKeys = (opts: {\n bundle: Record<string, string>;\n entry: ISecretHydrateEntry;\n}): Record<string, string> => {\n const { bundle, entry } = opts;\n const merged: Record<string, string> = {};\n\n if (!entry.keys) {\n const bundleEntries = Object.entries(bundle);\n for (const [rawKey, value] of bundleEntries) {\n merged[`${entry.prefix ?? ''}${rawKey}`] = value;\n }\n\n return merged;\n }\n\n const entryKeysEntries = Object.entries(entry.keys);\n for (const [rawKey, envKey] of entryKeysEntries) {\n const value = bundle[rawKey];\n if (value === undefined) {\n continue;\n }\n\n merged[envKey] = value;\n }\n\n return merged;\n};\n\nexport abstract class BaseApplication extends ServerApplication implements IRestApplication {\n protected secretsProvider?: ISecretsHelper;\n protected secretsRegistration?: ISecretsRegistration;\n\n protected normalizePath(...segments: string[]): string {\n const joined = segments.join('/').replace(/\\/+/g, '/').replace(/\\/$/, '');\n return joined || '/';\n }\n\n /** Adds the gRPC branch the kernel cannot own: `GrpcComponent` needs `AbstractGrpcController`, core-only code that reaches `node:module`. */\n override async registerControllers(): Promise<void> {\n await super.registerControllers();\n\n await PerformanceUtility.executeWithMeasure({\n logger: this.logger,\n description: 'Register application gRPC controllers',\n scope: this.registerControllers.name,\n task: async () => {\n const transports = this.configs.transports ?? [ControllerTransports.REST];\n\n for (const transport of transports) {\n if (transport === ControllerTransports.REST) {\n continue;\n }\n\n if (transport !== ControllerTransports.GRPC) {\n throw getError({\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n message: `[registerControllers] Unsupported transport: '${transport}'`,\n });\n }\n\n const grpcComponent = new GrpcComponent(this);\n await grpcComponent.configure();\n }\n\n // Warn if gRPC controllers exist but gRPC transport is not enabled\n if (transports.includes(ControllerTransports.GRPC)) {\n return;\n }\n\n const allBindings = this.findByTag({ tag: BindingNamespaces.CONTROLLER });\n for (const binding of allBindings) {\n const target = binding.getBindingMeta({ type: BindingValueTypes.CLASS });\n if (!target) {\n continue;\n }\n\n const metadata = MetadataRegistry.getInstance().getControllerMetadata({ target });\n if (metadata?.transport !== ControllerTransports.GRPC) {\n continue;\n }\n\n this.logger\n .for(this.registerControllers.name)\n .error(\n 'gRPC controller \"%s\" discovered but gRPC transport is not enabled. Add \"%s\" to transports config.',\n binding.key,\n ControllerTransports.GRPC,\n );\n }\n },\n });\n }\n\n registerSecrets(): ValueOrPromise<ISecretsRegistration> {\n return { provider: SecretProviders.SYSTEM_ENVS };\n }\n\n async hydrateSecrets(): Promise<void> {\n const logger = this.logger.for(this.hydrateSecrets.name);\n const registration = await this.registerSecrets();\n\n let provider: ISecretsHelper | undefined;\n const emptyHydrations: string[] = [];\n try {\n const result = await SecretsHelperFactory.create({ ...registration, identifier: 'app' });\n provider = result;\n await provider.configure();\n\n await this.hydrateSecretEntries({ provider, registration, emptyHydrations, logger });\n\n const registrationLease = registration.lease ?? [];\n for (const entry of registrationLease) {\n await provider.lease({ path: entry.path, key: entry.key });\n }\n } catch (error) {\n const env = Environment.current;\n if (!Environment.DEVELOPMENT_ENVS.has(env.toLowerCase())) {\n throw getError({\n message: `[hydrateSecrets] Secret provider failed in non-development environment | env: ${env}`,\n });\n }\n logger.warn(\n 'Secret provider failed; falling back to system-envs | env: %s | error: %s',\n env,\n error,\n );\n\n if (provider) {\n await provider\n .shutdown()\n .catch((shutdownError) =>\n logger.error(\n 'Failed to shut down partially-built provider during fallback | error: %s',\n shutdownError,\n ),\n );\n }\n const result2 = await SecretsHelperFactory.create({\n provider: SecretProviders.SYSTEM_ENVS,\n identifier: 'app',\n });\n provider = result2;\n }\n\n if (!provider) {\n throw getError({ message: '[hydrateSecrets] No secrets provider resolved' });\n }\n\n if (emptyHydrations.length > 0) {\n const env = Environment.current;\n if (!Environment.DEVELOPMENT_ENVS.has(env.toLowerCase())) {\n throw getError({\n message: `[hydrateSecrets] Hydrate entries resolved to an empty secret bundle in non-development environment | env: ${env} | paths: ${emptyHydrations.join(', ')}`,\n });\n }\n logger.warn(\n 'Hydrate entries resolved to an empty secret bundle; continuing in development | env: %s | paths: %s',\n env,\n emptyHydrations.join(', '),\n );\n }\n\n this.bind<ISecretsHelper>({ key: CoreBindings.APPLICATION_CONFIG })\n .toProvider(() => provider)\n .setScope(BindingScopes.SINGLETON);\n\n this.registerPostStopHook({ identifier: 'secrets.shutdown', hook: () => provider.shutdown() });\n this.secretsProvider = provider;\n this.secretsRegistration = registration;\n }\n\n /** Applies each hydrate entry in declaration order; paths that resolve empty while declaring an expectation are collected in `emptyHydrations` rather than failing here. */\n protected async hydrateSecretEntries(opts: {\n provider: ISecretsHelper;\n registration: ISecretsRegistration;\n emptyHydrations: string[];\n logger: ILogger;\n }): Promise<void> {\n const { provider, registration, emptyHydrations, logger } = opts;\n\n const registrationHydrate = registration.hydrate ?? [];\n for (const entry of registrationHydrate) {\n const bundle = await provider.getBundle({ path: entry.path });\n const merged = this.mergeSecretsIntoEnv({ bundle, entry });\n if (Object.keys(merged).length > 0) {\n continue;\n }\n\n if (this.hydrateEntryDeclaresExpectation({ entry })) {\n emptyHydrations.push(entry.path);\n continue;\n }\n\n logger.warn(\n 'Hydrate entry resolved to an empty bundle and declares no expected keys | path: %s',\n entry.path,\n );\n }\n }\n\n protected mergeSecretsIntoEnv(opts: {\n bundle: Record<string, string>;\n entry: ISecretHydrateEntry;\n }): Record<string, string> {\n const { bundle, entry } = opts;\n const merged = selectSecretEnvKeys({ bundle, entry });\n\n const mergedEntries = Object.entries(merged);\n for (const [key, value] of mergedEntries) {\n process.env[key] = value;\n }\n applicationEnvironment.merge({ envs: merged });\n return merged;\n }\n\n /** A hydrate entry declares an expectation only via explicit `keys` or a non-empty `prefix`; such an entry resolving to zero env values is a misconfiguration boot must not silently absorb. */\n protected hydrateEntryDeclaresExpectation(opts: { entry: ISecretHydrateEntry }): boolean {\n const { entry } = opts;\n if (entry.keys && Object.keys(entry.keys).length > 0) {\n return true;\n }\n return typeof entry.prefix === 'string' && entry.prefix.length > 0;\n }\n\n async wireSecretRotatables(): Promise<void> {\n const logger = this.logger.for(this.wireSecretRotatables.name);\n const provider = this.secretsProvider;\n const registration = this.secretsRegistration;\n if (!provider || !registration?.lease?.length) {\n return;\n }\n for (const entry of registration.lease) {\n const instance = this.get<ISecretRotatable>({ key: entry.key, isOptional: true });\n if (instance && typeof instance.onSecretRotated === 'function') {\n provider.registerRotatable({ key: entry.key, target: instance });\n logger.info('Wired rotatable | key: %s', entry.key);\n continue;\n }\n logger.debug('Lease key has no rotatable consumer | key: %s', entry.key);\n }\n }\n\n static(opts: { restPath?: string; folderPath: string }) {\n const { restPath = '*', folderPath } = opts;\n const server = this.getServer();\n\n server.use(restPath, serveStatic({ root: folderPath }));\n\n this.logger\n .for(this.static.name)\n .debug(\n 'Registered static files | runtime: %s | path: %s | folder: %s',\n this.runtime,\n restPath,\n folderPath,\n );\n return this;\n }\n\n /**\n * Every value is read HERE, not destructured at module load: an application that loads its\n * `.env` in its own entrypoint does so after this module is imported, and a module-load snapshot\n * would print the defaults for a host that configured everything correctly.\n */\n protected printStartUpInfo(opts: { scope: string }) {\n const { scope } = opts;\n const read = (key: string, fallback: string): string =>\n ParseUtility.blankToUndefined({ input: process.env[key] }) ?? fallback;\n const divider = '------------------------------------------------------------------------';\n\n this.logger.for(scope).info(divider);\n this.logger\n .for(scope)\n .info(\n 'Starting application... | Name: %s | Env: %s | Runtime: %s',\n read(EnvironmentKeys.APP_ENV_APPLICATION_NAME, 'PNT'),\n Environment.ambient,\n this.runtime,\n );\n this.logger\n .for(scope)\n .info(\n 'AllowEmptyEnv: %s | Prefix: %s',\n read('ALLOW_EMPTY_ENV_VALUE', 'true'),\n read('APPLICATION_ENV_PREFIX', 'APP_ENV'),\n );\n this.logger.for(scope).info('RunMode: %s', process.env.RUN_MODE);\n this.logger\n .for(scope)\n .info('Timezone: %s', read(EnvironmentKeys.APP_ENV_APPLICATION_TIMEZONE, 'Asia/Ho_Chi_Minh'));\n this.logger\n .for(scope)\n .info('LogPath: %s', read(EnvironmentKeys.APP_ENV_LOGGER_FOLDER_PATH, './'));\n this.logger.for(scope).info(divider);\n }\n\n /** Swaps in the `ErrorPrettier`-backed formatter - `node:util`, so the kernel cannot build it. */\n protected override buildErrorMiddleware(): AppErrorMiddleware {\n return new AppErrorMiddleware({\n logger: this.logger,\n rootKey: this.configs.error?.rootKey ?? undefined,\n });\n }\n\n /** Adds what only a listening server has, on top of the kernel's three - which stay in `RestApplication` so a browser Worker answers with the same envelope. */\n protected override async registerDefaultMiddlewares() {\n await PerformanceUtility.executeWithMeasure({\n logger: this.logger,\n scope: this.registerDefaultMiddlewares.name,\n description: 'Register default application server handler',\n task: async () => {\n const server = this.getServer();\n\n await super.registerDefaultMiddlewares();\n\n // Always installed, not only under `asyncContext.enable`: `tryGetContext()` answers \"no context\"\n // without a store, and a `contextStorage()` the application registered itself stays visible to\n // the enrichers. Inside a method body because every package declares `sideEffects: false`.\n RequestContextRegistry.setResolver({ resolver: () => tryGetContext() });\n\n if (this.configs.asyncContext?.enable) {\n server.use(contextStorage());\n }\n\n // Request-body parsing and the access log; the request id it reads is already installed\n // above (also works around the Bun + Hono body-parsing bug: https://github.com/honojs/middleware/issues/81).\n this.component(RequestTrackerComponent);\n\n server.use(EmojiFaviconMiddleware.create({ icon: this.configs.favicon ?? '🔥' }));\n },\n });\n }\n\n /** Lives here rather than on `AbstractApplication` - `applicationEnvironment` reads `process.env` at module load, so a kernel-pure ancestor cannot carry it; this is the layer that already depends on it. */\n protected validateEnvs() {\n const t = performance.now();\n const envKeys = applicationEnvironment.keys();\n\n // Permissive by DEFAULT: a name a host leaves empty is the host's business, and an empty value\n // already falls back to `defaultValue` at read time, so refusing to boot over one fights the\n // reader rather than helping it. Set ALLOW_EMPTY_ENV_VALUE to `false` or `0` to turn the check\n // on. Read once rather than per key, and a blank value reads as unset - the same rule every\n // other env read follows.\n const configured = ParseUtility.blankToUndefined({ input: process.env.ALLOW_EMPTY_ENV_VALUE });\n const allowsEmpty = configured === undefined || ParseUtility.toBoolean({ input: configured });\n\n this.logger\n .for(this.initialize.name)\n .info(\n 'Envs: %s | START Validating application environments | Empty values: %s',\n envKeys.length,\n allowsEmpty ? 'ALLOWED (default)' : 'REJECTED',\n );\n\n if (allowsEmpty) {\n this.logger\n .for(this.validateEnvs.name)\n .info(\n 'Envs: %s | SKIPPED - set ALLOW_EMPTY_ENV_VALUE=false to reject empty values',\n envKeys.length,\n );\n return;\n }\n\n for (const argKey of envKeys) {\n const argValue = applicationEnvironment.get<string | number>(argKey);\n\n if (!ObjectUtility.isEmpty({ value: argValue })) {\n continue;\n }\n\n throw getError({\n message: `[validateEnvs] Invalid Application Environment! Key: ${argKey} | Value: ${argValue}`,\n });\n }\n\n this.logger\n .for(this.validateEnvs.name)\n .info(\n 'Envs: %s | DONE Validating application environments | Took: %s (ms)',\n envKeys.length,\n performance.now() - t,\n );\n }\n\n /**\n * Version tripwire, body identical to `RestApplication.initialize()`: a stale kernel without\n * `getBootSequence()`/`runBootSequence()` throws here before any socket binds.\n */\n override async initialize(): Promise<void> {\n await this.runBootSequence({ steps: this.getBootSequence() });\n }\n\n protected override getBootSequence(): IBootSequenceStep[] {\n const steps: IBootSequenceStep[] = [\n {\n name: ServerBootSteps.PRINT_START_UP_INFO,\n run: () => this.printStartUpInfo({ scope: this.initialize.name }),\n },\n { name: ServerBootSteps.VALIDATE_ENVS, run: () => this.validateEnvs() },\n {\n name: ServerBootSteps.REGISTER_DEFAULT_MIDDLEWARES,\n run: () => this.registerDefaultMiddlewares(),\n },\n ...super.getBootSequence(),\n ];\n\n const withHydrate = BootSequence.insertAfter({\n steps,\n target: ServerBootSteps.PRE_CONFIGURE,\n step: { name: ServerBootSteps.HYDRATE_SECRETS, run: () => this.hydrateSecrets() },\n });\n\n // Components can contribute datasources, so wire rotatables only after the contributed sweep -\n // a lease key pointing at a component-contributed datasource would otherwise resolve to nothing.\n const withRotatables = BootSequence.insertAfter({\n steps: withHydrate,\n target: ServerBootSteps.REGISTER_CONTRIBUTED_DATA_SOURCES,\n step: {\n name: ServerBootSteps.WIRE_SECRET_ROTATABLES,\n run: () => this.wireSecretRotatables(),\n },\n });\n\n return [\n ...withRotatables,\n // Last, so a model registered by a component is covered too.\n {\n name: ServerBootSteps.VALIDATE_SCOPE_FILTER_SUPPORT,\n run: () => this.validateScopeFilterSupport(),\n },\n ];\n }\n\n /**\n * Refuses to start when a model's `settings.access` cannot take effect. Both failures are\n * silent at runtime and opposite: a search-backed model returns too many rows, a context-less one none.\n */\n protected validateScopeFilterSupport(): void {\n ScopeFilterUtility.assertScopeFilterSupported({\n asyncContextEnabled: this.configs.asyncContext?.enable ?? false,\n });\n }\n}\n"]}
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../../src/base/applications/base.ts"],"names":[],"mappings":"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","sourcesContent":["import { ScopeFilterUtility } from '@venizia/ignis-connectors';\nimport { ControllerTransports } from '@venizia/ignis-kernel';\nimport { BindingNamespaces, CoreBindings } from '@venizia/ignis-kernel';\nimport { EnvironmentKeys } from '@/common/environments';\nimport { RequestTrackerComponent } from '@/components';\nimport { GrpcComponent } from '@/components/controller/grpc';\nimport {\n BindingScopes,\n BindingValueTypes,\n BootSequence,\n MetadataRegistry,\n RequestContextRegistry,\n} from '@venizia/ignis-kernel';\nimport type { ILogger } from '@venizia/ignis-helpers/core';\nimport type { ValueOrPromise } from '@venizia/ignis-helpers/common';\nimport type {\n ISecretHydrateEntry,\n ISecretRotatable,\n ISecretsHelper,\n ISecretsRegistration,\n} from '@venizia/ignis-helpers';\nimport { ParseUtility, getError } from '@venizia/ignis-helpers/core';\nimport { HTTP, ObjectUtility } from '@venizia/ignis-helpers/common';\nimport {\n applicationEnvironment,\n SecretsHelperFactory,\n PerformanceUtility,\n Environment,\n SecretProviders,\n} from '@venizia/ignis-helpers';\nimport { contextStorage, tryGetContext } from 'hono/context-storage';\nimport { AppErrorMiddleware, EmojiFaviconMiddleware } from '../middlewares';\nimport { serveStatic } from 'hono/bun';\nimport { ServerLoggerStartup } from './common';\nimport { ServerBootSteps } from './boot-steps';\nimport { ServerApplication } from './server';\nimport type { IRestApplication } from '@venizia/ignis-kernel';\nimport type { IBootSequenceStep } from '@venizia/ignis-kernel';\n\n/** Maps a secret bundle to env names: the explicit `keys` mapping when present, otherwise every bundle key under `prefix`. */\nconst selectSecretEnvKeys = (opts: {\n bundle: Record<string, string>;\n entry: ISecretHydrateEntry;\n}): Record<string, string> => {\n const { bundle, entry } = opts;\n const merged: Record<string, string> = {};\n\n if (!entry.keys) {\n const bundleEntries = Object.entries(bundle);\n for (const [rawKey, value] of bundleEntries) {\n merged[`${entry.prefix ?? ''}${rawKey}`] = value;\n }\n\n return merged;\n }\n\n const entryKeysEntries = Object.entries(entry.keys);\n for (const [rawKey, envKey] of entryKeysEntries) {\n const value = bundle[rawKey];\n if (value === undefined) {\n continue;\n }\n\n merged[envKey] = value;\n }\n\n return merged;\n};\n\nexport abstract class BaseApplication extends ServerApplication implements IRestApplication {\n protected secretsProvider?: ISecretsHelper;\n protected secretsRegistration?: ISecretsRegistration;\n\n protected normalizePath(...segments: string[]): string {\n const joined = segments.join('/').replace(/\\/+/g, '/').replace(/\\/$/, '');\n return joined || '/';\n }\n\n /** Adds the gRPC branch the kernel cannot own: `GrpcComponent` needs `AbstractGrpcController`, core-only code that reaches `node:module`. */\n override async registerControllers(): Promise<void> {\n await super.registerControllers();\n\n await PerformanceUtility.executeWithMeasure({\n logger: this.logger,\n description: 'Register application gRPC controllers',\n scope: this.registerControllers.name,\n task: async () => {\n const transports = this.configs.transports ?? [ControllerTransports.REST];\n\n for (const transport of transports) {\n if (transport === ControllerTransports.REST) {\n continue;\n }\n\n if (transport !== ControllerTransports.GRPC) {\n throw getError({\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n message: `[registerControllers] Unsupported transport: '${transport}'`,\n });\n }\n\n const grpcComponent = new GrpcComponent(this);\n await grpcComponent.configure();\n }\n\n // Warn if gRPC controllers exist but gRPC transport is not enabled\n if (transports.includes(ControllerTransports.GRPC)) {\n return;\n }\n\n const allBindings = this.findByTag({ tag: BindingNamespaces.CONTROLLER });\n for (const binding of allBindings) {\n const target = binding.getBindingMeta({ type: BindingValueTypes.CLASS });\n if (!target) {\n continue;\n }\n\n const metadata = MetadataRegistry.getInstance().getControllerMetadata({ target });\n if (metadata?.transport !== ControllerTransports.GRPC) {\n continue;\n }\n\n this.logger\n .for(this.registerControllers.name)\n .error(\n 'gRPC controller \"%s\" discovered but gRPC transport is not enabled. Add \"%s\" to transports config.',\n binding.key,\n ControllerTransports.GRPC,\n );\n }\n },\n });\n }\n\n registerSecrets(): ValueOrPromise<ISecretsRegistration> {\n return { provider: SecretProviders.SYSTEM_ENVS };\n }\n\n async hydrateSecrets(): Promise<void> {\n const logger = this.logger.for(this.hydrateSecrets.name);\n const registration = await this.registerSecrets();\n\n let provider: ISecretsHelper | undefined;\n const emptyHydrations: string[] = [];\n try {\n const result = await SecretsHelperFactory.create({ ...registration, identifier: 'app' });\n provider = result;\n await provider.configure();\n\n await this.hydrateSecretEntries({ provider, registration, emptyHydrations, logger });\n\n const registrationLease = registration.lease ?? [];\n for (const entry of registrationLease) {\n await provider.lease({ path: entry.path, key: entry.key });\n }\n } catch (error) {\n const env = Environment.current;\n if (!Environment.DEVELOPMENT_ENVS.has(env.toLowerCase())) {\n throw getError({\n message: `[hydrateSecrets] Secret provider failed in non-development environment | env: ${env}`,\n });\n }\n logger.warn(\n 'Secret provider failed; falling back to system-envs | env: %s | error: %s',\n env,\n error,\n );\n\n if (provider) {\n try {\n await provider.shutdown();\n } catch (shutdownError) {\n logger.error(\n 'Failed to shut down partially-built provider during fallback | error: %s',\n shutdownError,\n );\n }\n }\n const result2 = await SecretsHelperFactory.create({\n provider: SecretProviders.SYSTEM_ENVS,\n identifier: 'app',\n });\n provider = result2;\n }\n\n if (!provider) {\n throw getError({ message: '[hydrateSecrets] No secrets provider resolved' });\n }\n\n if (emptyHydrations.length > 0) {\n const env = Environment.current;\n if (!Environment.DEVELOPMENT_ENVS.has(env.toLowerCase())) {\n throw getError({\n message: `[hydrateSecrets] Hydrate entries resolved to an empty secret bundle in non-development environment | env: ${env} | paths: ${emptyHydrations.join(', ')}`,\n });\n }\n logger.warn(\n 'Hydrate entries resolved to an empty secret bundle; continuing in development | env: %s | paths: %s',\n env,\n emptyHydrations.join(', '),\n );\n }\n\n this.bind<ISecretsHelper>({ key: CoreBindings.APPLICATION_CONFIG })\n .toProvider(() => provider)\n .setScope(BindingScopes.SINGLETON);\n\n this.registerPostStopHook({ identifier: 'secrets.shutdown', hook: () => provider.shutdown() });\n this.secretsProvider = provider;\n this.secretsRegistration = registration;\n }\n\n /** Applies each hydrate entry in declaration order; paths that resolve empty while declaring an expectation are collected in `emptyHydrations` rather than failing here. */\n protected async hydrateSecretEntries(opts: {\n provider: ISecretsHelper;\n registration: ISecretsRegistration;\n emptyHydrations: string[];\n logger: ILogger;\n }): Promise<void> {\n const { provider, registration, emptyHydrations, logger } = opts;\n\n const registrationHydrate = registration.hydrate ?? [];\n for (const entry of registrationHydrate) {\n const bundle = await provider.getBundle({ path: entry.path });\n const merged = this.mergeSecretsIntoEnv({ bundle, entry });\n if (Object.keys(merged).length > 0) {\n continue;\n }\n\n if (this.hydrateEntryDeclaresExpectation({ entry })) {\n emptyHydrations.push(entry.path);\n continue;\n }\n\n logger.warn(\n 'Hydrate entry resolved to an empty bundle and declares no expected keys | path: %s',\n entry.path,\n );\n }\n }\n\n protected mergeSecretsIntoEnv(opts: {\n bundle: Record<string, string>;\n entry: ISecretHydrateEntry;\n }): Record<string, string> {\n const { bundle, entry } = opts;\n const merged = selectSecretEnvKeys({ bundle, entry });\n\n const mergedEntries = Object.entries(merged);\n for (const [key, value] of mergedEntries) {\n process.env[key] = value;\n }\n applicationEnvironment.merge({ envs: merged });\n return merged;\n }\n\n /** A hydrate entry declares an expectation only via explicit `keys` or a non-empty `prefix`; such an entry resolving to zero env values is a misconfiguration boot must not silently absorb. */\n protected hydrateEntryDeclaresExpectation(opts: { entry: ISecretHydrateEntry }): boolean {\n const { entry } = opts;\n if (entry.keys && Object.keys(entry.keys).length > 0) {\n return true;\n }\n return typeof entry.prefix === 'string' && entry.prefix.length > 0;\n }\n\n async wireSecretRotatables(): Promise<void> {\n const logger = this.logger.for(this.wireSecretRotatables.name);\n const provider = this.secretsProvider;\n const registration = this.secretsRegistration;\n if (!provider || !registration?.lease?.length) {\n return;\n }\n for (const entry of registration.lease) {\n const instance = this.get<ISecretRotatable>({ key: entry.key, isOptional: true });\n if (instance && typeof instance.onSecretRotated === 'function') {\n provider.registerRotatable({ key: entry.key, target: instance });\n logger.info('Wired rotatable | key: %s', entry.key);\n continue;\n }\n logger.debug('Lease key has no rotatable consumer | key: %s', entry.key);\n }\n }\n\n static(opts: { restPath?: string; folderPath: string }) {\n const { restPath = '*', folderPath } = opts;\n const server = this.getServer();\n\n server.use(restPath, serveStatic({ root: folderPath }));\n\n this.logger\n .for(this.static.name)\n .debug(\n 'Registered static files | runtime: %s | path: %s | folder: %s',\n this.runtime,\n restPath,\n folderPath,\n );\n return this;\n }\n\n /**\n * Every value is read HERE, not destructured at module load: an application that loads its\n * `.env` in its own entrypoint does so after this module is imported, and a module-load snapshot\n * would print the defaults for a host that configured everything correctly.\n */\n protected printStartUpInfo(opts: { scope: string }) {\n const { scope } = opts;\n const read = (key: string, fallback: string): string =>\n ParseUtility.blankToUndefined({ input: process.env[key] }) ?? fallback;\n const divider = '------------------------------------------------------------------------';\n\n this.logger.for(scope).info(divider);\n this.logger\n .for(scope)\n .info(\n 'Starting application... | Name: %s | Env: %s | Runtime: %s',\n read(EnvironmentKeys.APP_ENV_APPLICATION_NAME, 'PNT'),\n Environment.ambient,\n this.runtime,\n );\n this.logger\n .for(scope)\n .info(\n 'AllowEmptyEnv: %s | Prefix: %s',\n read('ALLOW_EMPTY_ENV_VALUE', 'true'),\n read('APPLICATION_ENV_PREFIX', 'APP_ENV'),\n );\n this.logger.for(scope).info('RunMode: %s', process.env.RUN_MODE);\n this.logger\n .for(scope)\n .info('Timezone: %s', read(EnvironmentKeys.APP_ENV_APPLICATION_TIMEZONE, 'Asia/Ho_Chi_Minh'));\n this.logger\n .for(scope)\n .info('LogPath: %s', read(EnvironmentKeys.APP_ENV_LOGGER_FOLDER_PATH, './'));\n this.logger.for(scope).info(divider);\n }\n\n /** Swaps in the `ErrorPrettier`-backed formatter - `node:util`, so the kernel cannot build it. */\n protected override buildErrorMiddleware(): AppErrorMiddleware {\n return new AppErrorMiddleware({\n logger: this.logger,\n rootKey: this.configs.error?.rootKey ?? undefined,\n });\n }\n\n /** Adds what only a listening server has, on top of the kernel's three - which stay in `RestApplication` so a browser Worker answers with the same envelope. */\n protected override async registerDefaultMiddlewares() {\n await PerformanceUtility.executeWithMeasure({\n logger: this.logger,\n scope: this.registerDefaultMiddlewares.name,\n description: 'Register default application server handler',\n task: async () => {\n const server = this.getServer();\n\n await super.registerDefaultMiddlewares();\n\n // Always installed, not only under `asyncContext.enable`: `tryGetContext()` answers \"no context\"\n // without a store, and a `contextStorage()` the application registered itself stays visible to\n // the enrichers. Inside a method body because every package declares `sideEffects: false`.\n RequestContextRegistry.setResolver({ resolver: () => tryGetContext() });\n\n if (this.configs.asyncContext?.enable) {\n server.use(contextStorage());\n }\n\n // Request-body parsing and the access log; the request id it reads is already installed\n // above (also works around the Bun + Hono body-parsing bug: https://github.com/honojs/middleware/issues/81).\n this.component(RequestTrackerComponent);\n\n server.use(EmojiFaviconMiddleware.create({ icon: this.configs.favicon ?? '🔥' }));\n },\n });\n }\n\n /** Lives here rather than on `AbstractApplication` - `applicationEnvironment` reads `process.env` at module load, so a kernel-pure ancestor cannot carry it; this is the layer that already depends on it. */\n protected validateEnvs() {\n const t = performance.now();\n const envKeys = applicationEnvironment.keys();\n\n // Permissive by DEFAULT: a name a host leaves empty is the host's business, and an empty value\n // already falls back to `defaultValue` at read time, so refusing to boot over one fights the\n // reader rather than helping it. Set ALLOW_EMPTY_ENV_VALUE to `false` or `0` to turn the check\n // on. Read once rather than per key, and a blank value reads as unset - the same rule every\n // other env read follows.\n const configured = ParseUtility.blankToUndefined({ input: process.env.ALLOW_EMPTY_ENV_VALUE });\n const allowsEmpty = configured === undefined || ParseUtility.toBoolean({ input: configured });\n\n this.logger\n .for(this.initialize.name)\n .info(\n 'Envs: %s | START Validating application environments | Empty values: %s',\n envKeys.length,\n allowsEmpty ? 'ALLOWED (default)' : 'REJECTED',\n );\n\n if (allowsEmpty) {\n this.logger\n .for(this.validateEnvs.name)\n .info(\n 'Envs: %s | SKIPPED - set ALLOW_EMPTY_ENV_VALUE=false to reject empty values',\n envKeys.length,\n );\n return;\n }\n\n for (const argKey of envKeys) {\n const argValue = applicationEnvironment.get<string | number>(argKey);\n\n if (!ObjectUtility.isEmpty({ value: argValue })) {\n continue;\n }\n\n throw getError({\n message: `[validateEnvs] Invalid Application Environment! Key: ${argKey} | Value: ${argValue}`,\n });\n }\n\n this.logger\n .for(this.validateEnvs.name)\n .info(\n 'Envs: %s | DONE Validating application environments | Took: %s (ms)',\n envKeys.length,\n performance.now() - t,\n );\n }\n\n /**\n * Version tripwire, body identical to `RestApplication.initialize()`: a stale kernel without\n * `getBootSequence()`/`runBootSequence()` throws here before any socket binds.\n */\n override async initialize(): Promise<void> {\n await ServerLoggerStartup.selectDefault();\n await this.runBootSequence({ steps: this.getBootSequence() });\n }\n\n protected override getBootSequence(): IBootSequenceStep[] {\n const steps: IBootSequenceStep[] = [\n {\n name: ServerBootSteps.PRINT_START_UP_INFO,\n run: () => this.printStartUpInfo({ scope: this.initialize.name }),\n },\n { name: ServerBootSteps.VALIDATE_ENVS, run: () => this.validateEnvs() },\n {\n name: ServerBootSteps.REGISTER_DEFAULT_MIDDLEWARES,\n run: () => this.registerDefaultMiddlewares(),\n },\n ...super.getBootSequence(),\n ];\n\n const withHydrate = BootSequence.insertAfter({\n steps,\n target: ServerBootSteps.PRE_CONFIGURE,\n step: { name: ServerBootSteps.HYDRATE_SECRETS, run: () => this.hydrateSecrets() },\n });\n\n // Components can contribute datasources, so wire rotatables only after the contributed sweep -\n // a lease key pointing at a component-contributed datasource would otherwise resolve to nothing.\n const withRotatables = BootSequence.insertAfter({\n steps: withHydrate,\n target: ServerBootSteps.REGISTER_CONTRIBUTED_DATA_SOURCES,\n step: {\n name: ServerBootSteps.WIRE_SECRET_ROTATABLES,\n run: () => this.wireSecretRotatables(),\n },\n });\n\n return [\n ...withRotatables,\n // Last, so a model registered by a component is covered too.\n {\n name: ServerBootSteps.VALIDATE_SCOPE_FILTER_SUPPORT,\n run: () => this.validateScopeFilterSupport(),\n },\n ];\n }\n\n /**\n * Refuses to start when a model's `settings.access` cannot take effect. Both failures are\n * silent at runtime and opposite: a search-backed model returns too many rows, a context-less one none.\n */\n protected validateScopeFilterSupport(): void {\n ScopeFilterUtility.assertScopeFilterSupported({\n asyncContextEnabled: this.configs.asyncContext?.enable ?? false,\n });\n }\n}\n"]}
@@ -1,2 +1,3 @@
1
1
  export * from './types.js';
2
+ export * from './logger-startup.js';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/base/applications/common/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/base/applications/common/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,kBAAkB,CAAC"}
@@ -1,2 +1,3 @@
1
1
  export * from './types.js';
2
+ export * from './logger-startup.js';
2
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/base/applications/common/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC","sourcesContent":["export * from './types';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/base/applications/common/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,kBAAkB,CAAC","sourcesContent":["export * from './types';\nexport * from './logger-startup';\n"]}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * What the server does about logging at startup: an application that chose a provider (`LoggerFactory.use`) keeps it;
3
+ * one that did not gets Winston, the server's logger, when it is installed. Without Winston (an optional peer of the
4
+ * helpers) the console stays, which is the default provider everywhere. Any other failure to load Winston (a broken
5
+ * install, a version mismatch) is reported once on the console: the application must not log to the console in
6
+ * production without a word.
7
+ */
8
+ export declare class ServerLoggerStartup {
9
+ static selectDefault(): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=logger-startup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger-startup.d.ts","sourceRoot":"","sources":["../../../../../src/base/applications/common/logger-startup.ts"],"names":[],"mappings":"AAKA;;;;;;GAMG;AACH,qBAAa,mBAAmB;WACjB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CAoB5C"}
@@ -0,0 +1,29 @@
1
+ import { LoggerFactory } from '@venizia/ignis-helpers/core';
2
+ /** What a failed `import()` reports when the package is simply not installed. */
3
+ const MODULE_NOT_FOUND_CODES = new Set(['ERR_MODULE_NOT_FOUND', 'MODULE_NOT_FOUND']);
4
+ /**
5
+ * What the server does about logging at startup: an application that chose a provider (`LoggerFactory.use`) keeps it;
6
+ * one that did not gets Winston, the server's logger, when it is installed. Without Winston (an optional peer of the
7
+ * helpers) the console stays, which is the default provider everywhere. Any other failure to load Winston (a broken
8
+ * install, a version mismatch) is reported once on the console: the application must not log to the console in
9
+ * production without a word.
10
+ */
11
+ export class ServerLoggerStartup {
12
+ static async selectDefault() {
13
+ if (LoggerFactory.isChosen()) {
14
+ return;
15
+ }
16
+ try {
17
+ const { WinstonLogger } = await import('@venizia/ignis-helpers/winston');
18
+ LoggerFactory.useUnlessChosen({ provider: WinstonLogger });
19
+ }
20
+ catch (error) {
21
+ const code = error?.code;
22
+ if (code !== undefined && MODULE_NOT_FOUND_CODES.has(code)) {
23
+ return;
24
+ }
25
+ console.warn(`[ServerLoggerStartup] Winston could not be loaded, so the console stays the logger | cause: ${error instanceof Error ? error.message : String(error)}`);
26
+ }
27
+ }
28
+ }
29
+ //# sourceMappingURL=logger-startup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger-startup.js","sourceRoot":"","sources":["../../../../../src/base/applications/common/logger-startup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,iFAAiF;AACjF,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC,CAAC,sBAAsB,EAAE,kBAAkB,CAAC,CAAC,CAAC;AAErF;;;;;;GAMG;AACH,MAAM,OAAO,mBAAmB;IAC9B,MAAM,CAAC,KAAK,CAAC,aAAa;QACxB,IAAI,aAAa,CAAC,QAAQ,EAAE,EAAE,CAAC;YAC7B,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,gCAAgC,CAAC,CAAC;YACzE,aAAa,CAAC,eAAe,CAAC,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC,CAAC;QAC7D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,GAAI,KAAkC,EAAE,IAAI,CAAC;YAEvD,IAAI,IAAI,KAAK,SAAS,IAAI,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC3D,OAAO;YACT,CAAC;YAED,OAAO,CAAC,IAAI,CACV,+FAA+F,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACxJ,CAAC;QACJ,CAAC;IACH,CAAC;CACF","sourcesContent":["import { LoggerFactory } from '@venizia/ignis-helpers/core';\n\n/** What a failed `import()` reports when the package is simply not installed. */\nconst MODULE_NOT_FOUND_CODES = new Set(['ERR_MODULE_NOT_FOUND', 'MODULE_NOT_FOUND']);\n\n/**\n * What the server does about logging at startup: an application that chose a provider (`LoggerFactory.use`) keeps it;\n * one that did not gets Winston, the server's logger, when it is installed. Without Winston (an optional peer of the\n * helpers) the console stays, which is the default provider everywhere. Any other failure to load Winston (a broken\n * install, a version mismatch) is reported once on the console: the application must not log to the console in\n * production without a word.\n */\nexport class ServerLoggerStartup {\n static async selectDefault(): Promise<void> {\n if (LoggerFactory.isChosen()) {\n return;\n }\n\n try {\n const { WinstonLogger } = await import('@venizia/ignis-helpers/winston');\n LoggerFactory.useUnlessChosen({ provider: WinstonLogger });\n } catch (error) {\n const code = (error as { code?: string } | null)?.code;\n\n if (code !== undefined && MODULE_NOT_FOUND_CODES.has(code)) {\n return;\n }\n\n console.warn(\n `[ServerLoggerStartup] Winston could not be loaded, so the console stays the logger | cause: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"attachment.utility.d.ts","sourceRoot":"","sources":["../../../../../src/components/mail/utilities/attachment.utility.ts"],"names":[],"mappings":"AAMA,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AA2J7D,qBAAa,qBAAqB;IAChC;;;;;OAKG;WACU,WAAW,CAAC,IAAI,EAAE;QAC7B,UAAU,EAAE,eAAe,CAAC;QAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,MAAM,CAAC;IAsCnB;;;;OAIG;WACU,OAAO,CAAC,IAAI,EAAE;QACzB,WAAW,EAAE,eAAe,EAAE,CAAC;QAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IA4C9B;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;QAAE,WAAW,CAAC,EAAE,eAAe,EAAE,CAAA;KAAE,GAAG,IAAI;CA2BhE"}
1
+ {"version":3,"file":"attachment.utility.d.ts","sourceRoot":"","sources":["../../../../../src/components/mail/utilities/attachment.utility.ts"],"names":[],"mappings":"AAMA,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AA+J7D,qBAAa,qBAAqB;IAChC;;;;;OAKG;WACU,WAAW,CAAC,IAAI,EAAE;QAC7B,UAAU,EAAE,eAAe,CAAC;QAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,MAAM,CAAC;IAsCnB;;;;OAIG;WACU,OAAO,CAAC,IAAI,EAAE;QACzB,WAAW,EAAE,eAAe,EAAE,CAAC;QAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IA4C9B;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;QAAE,WAAW,CAAC,EAAE,eAAe,EAAE,CAAA;KAAE,GAAG,IAAI;CA2BhE"}
@@ -91,9 +91,14 @@ const readConfinedFile = async (opts) => {
91
91
  });
92
92
  }
93
93
  const filePath = await resolveConfinedPath({ path, attachmentRoot });
94
- const handle = await open(filePath, OPEN_FLAGS).catch((error) => {
94
+ let handle;
95
+ try {
96
+ const opened = await open(filePath, OPEN_FLAGS);
97
+ handle = opened;
98
+ }
99
+ catch (error) {
95
100
  throw buildPathRefusedError({ reason: PATH_OUTSIDE_REASON, cause: error });
96
- });
101
+ }
97
102
  try {
98
103
  const stats = await handle.stat();
99
104
  if (!stats.isFile()) {
@@ -1 +1 @@
1
- {"version":3,"file":"attachment.utility.js","sourceRoot":"","sources":["../../../../../src/components/mail/utilities/attachment.utility.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAwB,MAAM,WAAW,CAAC;AAE7D,MAAM,MAAM,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC;AAE5D,0FAA0F;AAC1F,+EAA+E;AAC/E,MAAM,UAAU,GAAG,SAAS,CAAC,QAAQ,GAAG,CAAC,SAAS,CAAC,UAAU,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC;AAElG,yFAAyF;AACzF,MAAM,mBAAmB,GACvB,qGAAqG,CAAC;AAIxG,MAAM,qBAAqB,GAAG,CAAC,IAAyC,EAAE,EAAE;IAC1E,OAAO,QAAQ,CAAC;QACd,KAAK,EAAE,UAAU,CAAC,uBAAuB;QACzC,OAAO,EAAE,kCAAkC,IAAI,CAAC,MAAM,EAAE;QACxD,KAAK,EAAE,IAAI,CAAC,KAAK;KAClB,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,IAA0B,EAAE,EAAE;IACxD,OAAO,QAAQ,CAAC;QACd,KAAK,EAAE,UAAU,CAAC,oBAAoB;QACtC,OAAO,EAAE,iDAAiD,IAAI,CAAC,QAAQ,iGAAiG;KACzK,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,IAAkE,EAAE,EAAE;IAC/F,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAEjD,IAAI,QAAQ,KAAK,SAAS,IAAI,SAAS,GAAG,UAAU,IAAI,QAAQ,EAAE,CAAC;QACjE,OAAO;IACT,CAAC;IAED,MAAM,kBAAkB,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;AACzC,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,KAAc,EAA8B,EAAE;IACxE,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,CAAC,aAAa,IAAI,KAAK,CAAC;AACtF,CAAC,CAAC;AAEF,MAAM,QAAQ,GAAG,CAAC,KAA0B,EAAU,EAAE;IACtD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC3B,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;AACpE,CAAC,CAAC;AAEF,6FAA6F;AAC7F,MAAM,WAAW,GAAG,KAAK,EAAE,IAI1B,EAAmB,EAAE;IACpB,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAC7C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC/B,WAAW,IAAI,MAAM,CAAC,UAAU,CAAC;QAEjC,mFAAmF;QACnF,iBAAiB,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QACpE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAC5C,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,mBAAmB,GAAG,KAAK,EAAE,IAGlC,EAAmB,EAAE;IACpB,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;IAEtC,IAAI,QAAgB,CAAC;IACrB,IAAI,QAAgB,CAAC;IAErB,mGAAmG;IACnG,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACjC,QAAQ,CAAC,cAAc,CAAC;YACxB,QAAQ,CAAC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;SACxC,CAAC,CAAC;QACH,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,qBAAqB,CAAC,EAAE,MAAM,EAAE,mBAAmB,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC9C,MAAM,SAAS,GACb,QAAQ,KAAK,EAAE,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,CAAC,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC;IAElG,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,qBAAqB,CAAC,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,KAAK,EAAE,IAK/B,EAAmB,EAAE;IACpB,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAE3D,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,qBAAqB,CAAC;YAC1B,MAAM,EACJ,4IAA4I;SAC/I,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;IACrE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QAC9D,MAAM,qBAAqB,CAAC,EAAE,MAAM,EAAE,mBAAmB,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QAElC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACpB,MAAM,qBAAqB,CAAC,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC,CAAC;QAC/D,CAAC;QAED,qFAAqF;QACrF,iBAAiB,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEnE,2FAA2F;QAC3F,qBAAqB;QACrB,MAAM,MAAM,GAAG,MAAM,CAAC,gBAAgB,CAAC;YACrC,SAAS,EAAE,KAAK;YAChB,GAAG,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,GAAG,SAAS;SAC9D,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QAClE,OAAO,MAAM,CAAC;IAChB,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,OAAO,qBAAqB;IAChC;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,IAKxB;QACC,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,SAAS,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC;QACrE,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC;QAE/B,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YAC9C,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAChC,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,IAAI,OAAO,CAAC;gBAChD,iBAAiB,CAAC;oBAChB,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC;oBAChD,SAAS;oBACT,QAAQ;iBACT,CAAC,CAAC;gBACH,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YACxC,CAAC;YAED,IAAI,OAAO,YAAY,UAAU,EAAE,CAAC;gBAClC,iBAAiB,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAC3E,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC3B,CAAC;YAED,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC;gBACjC,MAAM,QAAQ,CAAC;oBACb,KAAK,EAAE,UAAU,CAAC,qBAAqB;oBACvC,OAAO,EACL,mGAAmG;iBACtG,CAAC,CAAC;YACL,CAAC;YAED,OAAO,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,UAAU,CAAC,IAAI,KAAK,SAAS,IAAI,UAAU,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YAC9D,OAAO,gBAAgB,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC1F,CAAC;QAED,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAIpB;QACC,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;QACvD,MAAM,QAAQ,GAAsB,EAAE,CAAC;QACvC,IAAI,SAAS,GAAG,CAAC,CAAC;QAElB,6EAA6E;QAC7E,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACrC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,UAAU,CAAC;YAEnE,qFAAqF;YACrF,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI,CAAC,EAAE,CAAC;gBACjF,MAAM,qBAAqB,CAAC;oBAC1B,MAAM,EACJ,kFAAkF;iBACrF,CAAC,CAAC;YACL,CAAC;YAED,MAAM,KAAK,GAAG,MAAM,qBAAqB,CAAC,WAAW,CAAC;gBACpD,UAAU,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE;gBACvC,cAAc;gBACd,QAAQ;gBACR,SAAS;aACV,CAAC,CAAC;YAEH,SAAS,IAAI,KAAK,CAAC,UAAU,CAAC;YAE9B,MAAM,cAAc,GAClB,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,IAAI,CAAC,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC;YAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAChF,MAAM,WAAW,GACf,IAAI,CAAC,WAAW;gBAChB,CAAC,cAAc,IAAI,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAEpF,QAAQ,CAAC,IAAI,CAAC;gBACZ,GAAG,IAAI;gBACP,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;gBAC/C,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;gBACrD,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,IAAyC;QACtD,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,WAAW,IAAI,EAAE,EAAE,CAAC;YAChD,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC;YAE/B,IAAI,OAAO,YAAY,cAAc,EAAE,CAAC;gBACtC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;oBACpB,OAAO,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;wBAC/B,MAAM,CAAC,IAAI,CACT,4EAA4E,EAC5E,KAAK,CACN,CAAC;oBACJ,CAAC,CAAC,CAAC;gBACL,CAAC;gBAED,SAAS;YACX,CAAC;YAED,IACE,OAAO,OAAO,KAAK,QAAQ;gBAC3B,OAAO,KAAK,IAAI;gBAChB,SAAS,IAAI,OAAO;gBACpB,OAAO,OAAO,CAAC,OAAO,KAAK,UAAU,EACrC,CAAC;gBACD,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC;CACF","sourcesContent":["import { constants } from 'node:fs';\nimport { open, realpath } from 'node:fs/promises';\nimport { basename, isAbsolute, relative, resolve, sep } from 'node:path';\nimport { ContentTypeTable } from '@venizia/ignis-helpers/common';\nimport { getError } from '@venizia/ignis-helpers/core';\nimport { LoggerFactory } from '@venizia/ignis-helpers';\nimport { MailErrors, type IMailAttachment } from '../common';\n\nconst logger = LoggerFactory.getLogger(['MailAttachments']);\n\n// O_NONBLOCK: opening a FIFO must not wait for a writer; the fstat check then refuses it.\n// Windows has neither flag; there the realpath containment check stands alone.\nconst OPEN_FLAGS = constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0);\n\n// One reason for missing, directory, unreadable and escaping paths: no existence oracle.\nconst PATH_OUTSIDE_REASON =\n 'attachment.path must name a readable file inside attachmentRoot | pass the bytes as content instead';\n\ntype TAttachmentStream = AsyncIterable<Uint8Array | string>;\n\nconst buildPathRefusedError = (opts: { reason: string; cause?: unknown }) => {\n return getError({\n error: MailErrors.ATTACHMENT_PATH_REFUSED,\n message: `Mail attachment path refused | ${opts.reason}`,\n cause: opts.cause,\n });\n};\n\nconst buildTooLargeError = (opts: { maxBytes: number }) => {\n return getError({\n error: MailErrors.ATTACHMENT_TOO_LARGE,\n message: `Mail attachments are over maxAttachmentBytes (${opts.maxBytes} bytes per message) | raise maxAttachmentBytes on the mail options, or send smaller attachments`,\n });\n};\n\nconst assertWithinLimit = (opts: { byteLength: number; usedBytes: number; maxBytes?: number }) => {\n const { byteLength, usedBytes, maxBytes } = opts;\n\n if (maxBytes === undefined || usedBytes + byteLength <= maxBytes) {\n return;\n }\n\n throw buildTooLargeError({ maxBytes });\n};\n\nconst isAttachmentStream = (value: unknown): value is TAttachmentStream => {\n return typeof value === 'object' && value !== null && Symbol.asyncIterator in value;\n};\n\nconst toBuffer = (chunk: Uint8Array | string): Buffer => {\n if (typeof chunk === 'string') {\n return Buffer.from(chunk);\n }\n\n return Buffer.isBuffer(chunk)\n ? chunk\n : Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength);\n};\n\n/** Throwing out of `for await` destroys a Node Readable and cancels a web ReadableStream. */\nconst drainStream = async (opts: {\n stream: TAttachmentStream;\n usedBytes: number;\n maxBytes?: number;\n}): Promise<Buffer> => {\n const { stream, usedBytes, maxBytes } = opts;\n const chunks: Buffer[] = [];\n let streamBytes = 0;\n\n for await (const chunk of stream) {\n const buffer = toBuffer(chunk);\n streamBytes += buffer.byteLength;\n\n // Per chunk: a stream has no length up front, and the rest must never be buffered.\n assertWithinLimit({ byteLength: streamBytes, usedBytes, maxBytes });\n chunks.push(buffer);\n }\n\n return Buffer.concat(chunks, streamBytes);\n};\n\n/**\n * Both sides go through realpath, so neither `..` nor a symlink can leave the root. Not closed: a\n * directory inside the root swapped for a symlink between this check and `open` - that takes write\n * access inside the root, so keep the root writable only by what the application trusts.\n */\nconst resolveConfinedPath = async (opts: {\n path: string;\n attachmentRoot: string;\n}): Promise<string> => {\n const { path, attachmentRoot } = opts;\n\n let rootPath: string;\n let filePath: string;\n\n // `resolve` throws synchronously on a non-string `path` from an untyped caller; it lands here too.\n try {\n const resolved = await Promise.all([\n realpath(attachmentRoot),\n realpath(resolve(attachmentRoot, path)),\n ]);\n [rootPath, filePath] = resolved;\n } catch (error) {\n throw buildPathRefusedError({ reason: PATH_OUTSIDE_REASON, cause: error });\n }\n\n const relation = relative(rootPath, filePath);\n const isOutside =\n relation === '' || relation === '..' || relation.startsWith(`..${sep}`) || isAbsolute(relation);\n\n if (isOutside) {\n throw buildPathRefusedError({ reason: PATH_OUTSIDE_REASON });\n }\n\n return filePath;\n};\n\nconst readConfinedFile = async (opts: {\n path: string;\n usedBytes: number;\n attachmentRoot?: string;\n maxBytes?: number;\n}): Promise<Buffer> => {\n const { path, usedBytes, attachmentRoot, maxBytes } = opts;\n\n if (!attachmentRoot) {\n throw buildPathRefusedError({\n reason:\n 'attachment.path is read only under attachmentRoot, which is not set | set attachmentRoot on the mail options, or pass the bytes as content',\n });\n }\n\n const filePath = await resolveConfinedPath({ path, attachmentRoot });\n const handle = await open(filePath, OPEN_FLAGS).catch((error) => {\n throw buildPathRefusedError({ reason: PATH_OUTSIDE_REASON, cause: error });\n });\n\n try {\n const stats = await handle.stat();\n\n if (!stats.isFile()) {\n throw buildPathRefusedError({ reason: PATH_OUTSIDE_REASON });\n }\n\n // Sized before reading, so a file known to be oversized is never opened for reading.\n assertWithinLimit({ byteLength: stats.size, usedBytes, maxBytes });\n\n // Counted while read, and read no further than one byte past the budget: the file may have\n // grown since fstat.\n const stream = handle.createReadStream({\n autoClose: false,\n end: maxBytes === undefined ? Infinity : maxBytes - usedBytes,\n });\n\n const result = await drainStream({ stream, usedBytes, maxBytes });\n return result;\n } finally {\n await handle.close();\n }\n};\n\nexport class MailAttachmentUtility {\n /**\n * Reads one attachment's bytes. A string `content` is raw text unless `encoding` says otherwise\n * (nodemailer's convention); `null` counts as absent. A `path` is read only inside\n * `attachmentRoot` and refused without one. `maxBytes` caps the whole message; `usedBytes` is what\n * earlier attachments already took.\n */\n static async readContent(opts: {\n attachment: IMailAttachment;\n attachmentRoot?: string;\n maxBytes?: number;\n usedBytes?: number;\n }): Promise<Buffer> {\n const { attachment, attachmentRoot, maxBytes, usedBytes = 0 } = opts;\n const { content } = attachment;\n\n if (content !== undefined && content !== null) {\n if (typeof content === 'string') {\n const encoding = attachment.encoding ?? 'utf-8';\n assertWithinLimit({\n byteLength: Buffer.byteLength(content, encoding),\n usedBytes,\n maxBytes,\n });\n return Buffer.from(content, encoding);\n }\n\n if (content instanceof Uint8Array) {\n assertWithinLimit({ byteLength: content.byteLength, usedBytes, maxBytes });\n return toBuffer(content);\n }\n\n if (!isAttachmentStream(content)) {\n throw getError({\n error: MailErrors.INVALID_CONFIGURATION,\n message:\n 'Invalid mail attachment | attachment.content must be a Buffer, a Uint8Array, a string or a stream',\n });\n }\n\n return drainStream({ stream: content, usedBytes, maxBytes });\n }\n\n if (attachment.path !== undefined && attachment.path !== null) {\n return readConfinedFile({ path: attachment.path, usedBytes, attachmentRoot, maxBytes });\n }\n\n return Buffer.alloc(0);\n }\n\n /**\n * Turns every attachment into `content` bytes and drops `path`, so no transport is ever handed a\n * file or URL to read on its own. `maxBytes` is shared by all attachments of the message. An\n * attachment read from `path` keeps the file's name and, when none is given, its content type.\n */\n static async resolve(opts: {\n attachments: IMailAttachment[];\n attachmentRoot?: string;\n maxBytes?: number;\n }): Promise<IMailAttachment[]> {\n const { attachments, attachmentRoot, maxBytes } = opts;\n const resolved: IMailAttachment[] = [];\n let usedBytes = 0;\n\n // Sequential on purpose: each read spends the budget the previous ones left.\n for (const attachment of attachments) {\n const { path, href, raw, content, encoding, ...rest } = attachment;\n\n // nodemailer reads both on its own - `href` fetches a URL, `raw` can carry a `path`.\n if ((href !== undefined && href !== null) || (raw !== undefined && raw !== null)) {\n throw buildPathRefusedError({\n reason:\n 'attachment.href and attachment.raw are not supported | pass the bytes as content',\n });\n }\n\n const bytes = await MailAttachmentUtility.readContent({\n attachment: { content, encoding, path },\n attachmentRoot,\n maxBytes,\n usedBytes,\n });\n\n usedBytes += bytes.byteLength;\n\n const isReadFromPath =\n (content === undefined || content === null) && typeof path === 'string';\n const filename = rest.filename ?? (isReadFromPath ? basename(path) : undefined);\n const contentType =\n rest.contentType ??\n (isReadFromPath && filename ? ContentTypeTable.resolve({ filename }) : undefined);\n\n resolved.push({\n ...rest,\n ...(filename === undefined ? {} : { filename }),\n ...(contentType === undefined ? {} : { contentType }),\n content: bytes,\n });\n }\n\n return resolved;\n }\n\n /**\n * Releases every attachment stream of a refused send, read or not, so none keeps a descriptor\n * open. A drained stream is already closed; releasing it again is harmless.\n */\n static release(opts: { attachments?: IMailAttachment[] }): void {\n for (const attachment of opts.attachments ?? []) {\n const { content } = attachment;\n\n if (content instanceof ReadableStream) {\n if (!content.locked) {\n content.cancel().catch((error) => {\n logger.warn(\n '[MailAttachmentUtility.release] Cancelling a web stream failed | error: %s',\n error,\n );\n });\n }\n\n continue;\n }\n\n if (\n typeof content === 'object' &&\n content !== null &&\n 'destroy' in content &&\n typeof content.destroy === 'function'\n ) {\n content.destroy();\n }\n }\n }\n}\n"]}
1
+ {"version":3,"file":"attachment.utility.js","sourceRoot":"","sources":["../../../../../src/components/mail/utilities/attachment.utility.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAmB,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAwB,MAAM,WAAW,CAAC;AAE7D,MAAM,MAAM,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC;AAE5D,0FAA0F;AAC1F,+EAA+E;AAC/E,MAAM,UAAU,GAAG,SAAS,CAAC,QAAQ,GAAG,CAAC,SAAS,CAAC,UAAU,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC;AAElG,yFAAyF;AACzF,MAAM,mBAAmB,GACvB,qGAAqG,CAAC;AAIxG,MAAM,qBAAqB,GAAG,CAAC,IAAyC,EAAE,EAAE;IAC1E,OAAO,QAAQ,CAAC;QACd,KAAK,EAAE,UAAU,CAAC,uBAAuB;QACzC,OAAO,EAAE,kCAAkC,IAAI,CAAC,MAAM,EAAE;QACxD,KAAK,EAAE,IAAI,CAAC,KAAK;KAClB,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,IAA0B,EAAE,EAAE;IACxD,OAAO,QAAQ,CAAC;QACd,KAAK,EAAE,UAAU,CAAC,oBAAoB;QACtC,OAAO,EAAE,iDAAiD,IAAI,CAAC,QAAQ,iGAAiG;KACzK,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,IAAkE,EAAE,EAAE;IAC/F,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAEjD,IAAI,QAAQ,KAAK,SAAS,IAAI,SAAS,GAAG,UAAU,IAAI,QAAQ,EAAE,CAAC;QACjE,OAAO;IACT,CAAC;IAED,MAAM,kBAAkB,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;AACzC,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,KAAc,EAA8B,EAAE;IACxE,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,CAAC,aAAa,IAAI,KAAK,CAAC;AACtF,CAAC,CAAC;AAEF,MAAM,QAAQ,GAAG,CAAC,KAA0B,EAAU,EAAE;IACtD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC3B,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;AACpE,CAAC,CAAC;AAEF,6FAA6F;AAC7F,MAAM,WAAW,GAAG,KAAK,EAAE,IAI1B,EAAmB,EAAE;IACpB,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAC7C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC/B,WAAW,IAAI,MAAM,CAAC,UAAU,CAAC;QAEjC,mFAAmF;QACnF,iBAAiB,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QACpE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAC5C,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,mBAAmB,GAAG,KAAK,EAAE,IAGlC,EAAmB,EAAE;IACpB,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;IAEtC,IAAI,QAAgB,CAAC;IACrB,IAAI,QAAgB,CAAC;IAErB,mGAAmG;IACnG,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACjC,QAAQ,CAAC,cAAc,CAAC;YACxB,QAAQ,CAAC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;SACxC,CAAC,CAAC;QACH,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,qBAAqB,CAAC,EAAE,MAAM,EAAE,mBAAmB,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC9C,MAAM,SAAS,GACb,QAAQ,KAAK,EAAE,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,CAAC,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC;IAElG,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,qBAAqB,CAAC,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,KAAK,EAAE,IAK/B,EAAmB,EAAE;IACpB,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAE3D,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,qBAAqB,CAAC;YAC1B,MAAM,EACJ,4IAA4I;SAC/I,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;IACrE,IAAI,MAAkB,CAAC;IACvB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAChD,MAAM,GAAG,MAAM,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,qBAAqB,CAAC,EAAE,MAAM,EAAE,mBAAmB,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QAElC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACpB,MAAM,qBAAqB,CAAC,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC,CAAC;QAC/D,CAAC;QAED,qFAAqF;QACrF,iBAAiB,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEnE,2FAA2F;QAC3F,qBAAqB;QACrB,MAAM,MAAM,GAAG,MAAM,CAAC,gBAAgB,CAAC;YACrC,SAAS,EAAE,KAAK;YAChB,GAAG,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,GAAG,SAAS;SAC9D,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QAClE,OAAO,MAAM,CAAC;IAChB,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,OAAO,qBAAqB;IAChC;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,IAKxB;QACC,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,SAAS,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC;QACrE,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC;QAE/B,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YAC9C,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAChC,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,IAAI,OAAO,CAAC;gBAChD,iBAAiB,CAAC;oBAChB,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC;oBAChD,SAAS;oBACT,QAAQ;iBACT,CAAC,CAAC;gBACH,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YACxC,CAAC;YAED,IAAI,OAAO,YAAY,UAAU,EAAE,CAAC;gBAClC,iBAAiB,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAC3E,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC3B,CAAC;YAED,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC;gBACjC,MAAM,QAAQ,CAAC;oBACb,KAAK,EAAE,UAAU,CAAC,qBAAqB;oBACvC,OAAO,EACL,mGAAmG;iBACtG,CAAC,CAAC;YACL,CAAC;YAED,OAAO,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,UAAU,CAAC,IAAI,KAAK,SAAS,IAAI,UAAU,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YAC9D,OAAO,gBAAgB,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC1F,CAAC;QAED,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAIpB;QACC,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;QACvD,MAAM,QAAQ,GAAsB,EAAE,CAAC;QACvC,IAAI,SAAS,GAAG,CAAC,CAAC;QAElB,6EAA6E;QAC7E,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACrC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,UAAU,CAAC;YAEnE,qFAAqF;YACrF,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI,CAAC,EAAE,CAAC;gBACjF,MAAM,qBAAqB,CAAC;oBAC1B,MAAM,EACJ,kFAAkF;iBACrF,CAAC,CAAC;YACL,CAAC;YAED,MAAM,KAAK,GAAG,MAAM,qBAAqB,CAAC,WAAW,CAAC;gBACpD,UAAU,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE;gBACvC,cAAc;gBACd,QAAQ;gBACR,SAAS;aACV,CAAC,CAAC;YAEH,SAAS,IAAI,KAAK,CAAC,UAAU,CAAC;YAE9B,MAAM,cAAc,GAClB,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,IAAI,CAAC,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC;YAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAChF,MAAM,WAAW,GACf,IAAI,CAAC,WAAW;gBAChB,CAAC,cAAc,IAAI,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAEpF,QAAQ,CAAC,IAAI,CAAC;gBACZ,GAAG,IAAI;gBACP,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;gBAC/C,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;gBACrD,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,IAAyC;QACtD,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,WAAW,IAAI,EAAE,EAAE,CAAC;YAChD,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC;YAE/B,IAAI,OAAO,YAAY,cAAc,EAAE,CAAC;gBACtC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;oBACpB,OAAO,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;wBAC/B,MAAM,CAAC,IAAI,CACT,4EAA4E,EAC5E,KAAK,CACN,CAAC;oBACJ,CAAC,CAAC,CAAC;gBACL,CAAC;gBAED,SAAS;YACX,CAAC;YAED,IACE,OAAO,OAAO,KAAK,QAAQ;gBAC3B,OAAO,KAAK,IAAI;gBAChB,SAAS,IAAI,OAAO;gBACpB,OAAO,OAAO,CAAC,OAAO,KAAK,UAAU,EACrC,CAAC;gBACD,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC;CACF","sourcesContent":["import { constants } from 'node:fs';\nimport { open, realpath, type FileHandle } from 'node:fs/promises';\nimport { basename, isAbsolute, relative, resolve, sep } from 'node:path';\nimport { ContentTypeTable } from '@venizia/ignis-helpers/common';\nimport { getError } from '@venizia/ignis-helpers/core';\nimport { LoggerFactory } from '@venizia/ignis-helpers';\nimport { MailErrors, type IMailAttachment } from '../common';\n\nconst logger = LoggerFactory.getLogger(['MailAttachments']);\n\n// O_NONBLOCK: opening a FIFO must not wait for a writer; the fstat check then refuses it.\n// Windows has neither flag; there the realpath containment check stands alone.\nconst OPEN_FLAGS = constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0);\n\n// One reason for missing, directory, unreadable and escaping paths: no existence oracle.\nconst PATH_OUTSIDE_REASON =\n 'attachment.path must name a readable file inside attachmentRoot | pass the bytes as content instead';\n\ntype TAttachmentStream = AsyncIterable<Uint8Array | string>;\n\nconst buildPathRefusedError = (opts: { reason: string; cause?: unknown }) => {\n return getError({\n error: MailErrors.ATTACHMENT_PATH_REFUSED,\n message: `Mail attachment path refused | ${opts.reason}`,\n cause: opts.cause,\n });\n};\n\nconst buildTooLargeError = (opts: { maxBytes: number }) => {\n return getError({\n error: MailErrors.ATTACHMENT_TOO_LARGE,\n message: `Mail attachments are over maxAttachmentBytes (${opts.maxBytes} bytes per message) | raise maxAttachmentBytes on the mail options, or send smaller attachments`,\n });\n};\n\nconst assertWithinLimit = (opts: { byteLength: number; usedBytes: number; maxBytes?: number }) => {\n const { byteLength, usedBytes, maxBytes } = opts;\n\n if (maxBytes === undefined || usedBytes + byteLength <= maxBytes) {\n return;\n }\n\n throw buildTooLargeError({ maxBytes });\n};\n\nconst isAttachmentStream = (value: unknown): value is TAttachmentStream => {\n return typeof value === 'object' && value !== null && Symbol.asyncIterator in value;\n};\n\nconst toBuffer = (chunk: Uint8Array | string): Buffer => {\n if (typeof chunk === 'string') {\n return Buffer.from(chunk);\n }\n\n return Buffer.isBuffer(chunk)\n ? chunk\n : Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength);\n};\n\n/** Throwing out of `for await` destroys a Node Readable and cancels a web ReadableStream. */\nconst drainStream = async (opts: {\n stream: TAttachmentStream;\n usedBytes: number;\n maxBytes?: number;\n}): Promise<Buffer> => {\n const { stream, usedBytes, maxBytes } = opts;\n const chunks: Buffer[] = [];\n let streamBytes = 0;\n\n for await (const chunk of stream) {\n const buffer = toBuffer(chunk);\n streamBytes += buffer.byteLength;\n\n // Per chunk: a stream has no length up front, and the rest must never be buffered.\n assertWithinLimit({ byteLength: streamBytes, usedBytes, maxBytes });\n chunks.push(buffer);\n }\n\n return Buffer.concat(chunks, streamBytes);\n};\n\n/**\n * Both sides go through realpath, so neither `..` nor a symlink can leave the root. Not closed: a\n * directory inside the root swapped for a symlink between this check and `open` - that takes write\n * access inside the root, so keep the root writable only by what the application trusts.\n */\nconst resolveConfinedPath = async (opts: {\n path: string;\n attachmentRoot: string;\n}): Promise<string> => {\n const { path, attachmentRoot } = opts;\n\n let rootPath: string;\n let filePath: string;\n\n // `resolve` throws synchronously on a non-string `path` from an untyped caller; it lands here too.\n try {\n const resolved = await Promise.all([\n realpath(attachmentRoot),\n realpath(resolve(attachmentRoot, path)),\n ]);\n [rootPath, filePath] = resolved;\n } catch (error) {\n throw buildPathRefusedError({ reason: PATH_OUTSIDE_REASON, cause: error });\n }\n\n const relation = relative(rootPath, filePath);\n const isOutside =\n relation === '' || relation === '..' || relation.startsWith(`..${sep}`) || isAbsolute(relation);\n\n if (isOutside) {\n throw buildPathRefusedError({ reason: PATH_OUTSIDE_REASON });\n }\n\n return filePath;\n};\n\nconst readConfinedFile = async (opts: {\n path: string;\n usedBytes: number;\n attachmentRoot?: string;\n maxBytes?: number;\n}): Promise<Buffer> => {\n const { path, usedBytes, attachmentRoot, maxBytes } = opts;\n\n if (!attachmentRoot) {\n throw buildPathRefusedError({\n reason:\n 'attachment.path is read only under attachmentRoot, which is not set | set attachmentRoot on the mail options, or pass the bytes as content',\n });\n }\n\n const filePath = await resolveConfinedPath({ path, attachmentRoot });\n let handle: FileHandle;\n try {\n const opened = await open(filePath, OPEN_FLAGS);\n handle = opened;\n } catch (error) {\n throw buildPathRefusedError({ reason: PATH_OUTSIDE_REASON, cause: error });\n }\n\n try {\n const stats = await handle.stat();\n\n if (!stats.isFile()) {\n throw buildPathRefusedError({ reason: PATH_OUTSIDE_REASON });\n }\n\n // Sized before reading, so a file known to be oversized is never opened for reading.\n assertWithinLimit({ byteLength: stats.size, usedBytes, maxBytes });\n\n // Counted while read, and read no further than one byte past the budget: the file may have\n // grown since fstat.\n const stream = handle.createReadStream({\n autoClose: false,\n end: maxBytes === undefined ? Infinity : maxBytes - usedBytes,\n });\n\n const result = await drainStream({ stream, usedBytes, maxBytes });\n return result;\n } finally {\n await handle.close();\n }\n};\n\nexport class MailAttachmentUtility {\n /**\n * Reads one attachment's bytes. A string `content` is raw text unless `encoding` says otherwise\n * (nodemailer's convention); `null` counts as absent. A `path` is read only inside\n * `attachmentRoot` and refused without one. `maxBytes` caps the whole message; `usedBytes` is what\n * earlier attachments already took.\n */\n static async readContent(opts: {\n attachment: IMailAttachment;\n attachmentRoot?: string;\n maxBytes?: number;\n usedBytes?: number;\n }): Promise<Buffer> {\n const { attachment, attachmentRoot, maxBytes, usedBytes = 0 } = opts;\n const { content } = attachment;\n\n if (content !== undefined && content !== null) {\n if (typeof content === 'string') {\n const encoding = attachment.encoding ?? 'utf-8';\n assertWithinLimit({\n byteLength: Buffer.byteLength(content, encoding),\n usedBytes,\n maxBytes,\n });\n return Buffer.from(content, encoding);\n }\n\n if (content instanceof Uint8Array) {\n assertWithinLimit({ byteLength: content.byteLength, usedBytes, maxBytes });\n return toBuffer(content);\n }\n\n if (!isAttachmentStream(content)) {\n throw getError({\n error: MailErrors.INVALID_CONFIGURATION,\n message:\n 'Invalid mail attachment | attachment.content must be a Buffer, a Uint8Array, a string or a stream',\n });\n }\n\n return drainStream({ stream: content, usedBytes, maxBytes });\n }\n\n if (attachment.path !== undefined && attachment.path !== null) {\n return readConfinedFile({ path: attachment.path, usedBytes, attachmentRoot, maxBytes });\n }\n\n return Buffer.alloc(0);\n }\n\n /**\n * Turns every attachment into `content` bytes and drops `path`, so no transport is ever handed a\n * file or URL to read on its own. `maxBytes` is shared by all attachments of the message. An\n * attachment read from `path` keeps the file's name and, when none is given, its content type.\n */\n static async resolve(opts: {\n attachments: IMailAttachment[];\n attachmentRoot?: string;\n maxBytes?: number;\n }): Promise<IMailAttachment[]> {\n const { attachments, attachmentRoot, maxBytes } = opts;\n const resolved: IMailAttachment[] = [];\n let usedBytes = 0;\n\n // Sequential on purpose: each read spends the budget the previous ones left.\n for (const attachment of attachments) {\n const { path, href, raw, content, encoding, ...rest } = attachment;\n\n // nodemailer reads both on its own - `href` fetches a URL, `raw` can carry a `path`.\n if ((href !== undefined && href !== null) || (raw !== undefined && raw !== null)) {\n throw buildPathRefusedError({\n reason:\n 'attachment.href and attachment.raw are not supported | pass the bytes as content',\n });\n }\n\n const bytes = await MailAttachmentUtility.readContent({\n attachment: { content, encoding, path },\n attachmentRoot,\n maxBytes,\n usedBytes,\n });\n\n usedBytes += bytes.byteLength;\n\n const isReadFromPath =\n (content === undefined || content === null) && typeof path === 'string';\n const filename = rest.filename ?? (isReadFromPath ? basename(path) : undefined);\n const contentType =\n rest.contentType ??\n (isReadFromPath && filename ? ContentTypeTable.resolve({ filename }) : undefined);\n\n resolved.push({\n ...rest,\n ...(filename === undefined ? {} : { filename }),\n ...(contentType === undefined ? {} : { contentType }),\n content: bytes,\n });\n }\n\n return resolved;\n }\n\n /**\n * Releases every attachment stream of a refused send, read or not, so none keeps a descriptor\n * open. A drained stream is already closed; releasing it again is harmless.\n */\n static release(opts: { attachments?: IMailAttachment[] }): void {\n for (const attachment of opts.attachments ?? []) {\n const { content } = attachment;\n\n if (content instanceof ReadableStream) {\n if (!content.locked) {\n content.cancel().catch((error) => {\n logger.warn(\n '[MailAttachmentUtility.release] Cancelling a web stream failed | error: %s',\n error,\n );\n });\n }\n\n continue;\n }\n\n if (\n typeof content === 'object' &&\n content !== null &&\n 'destroy' in content &&\n typeof content.destroy === 'function'\n ) {\n content.destroy();\n }\n }\n }\n}\n"]}
@@ -783,13 +783,14 @@ export class AssetControllerFactory extends BaseHelper {
783
783
  // The copy IS the commit; removing the temporary object is cleanup. A failure here
784
784
  // leaves one object for the lifecycle rule, and failing the request would tell the
785
785
  // caller their upload did not work when it did.
786
- await helper
787
- .removeObject({ bucket: bucketRef, object: pendingObject })
788
- .catch((error) => {
786
+ try {
787
+ await helper.removeObject({ bucket: bucketRef, object: pendingObject });
788
+ }
789
+ catch (error) {
789
790
  this.logger
790
791
  .for('UPLOAD_COMMIT')
791
792
  .warn('Committed, but the pending object remains | key: %s | error: %s', pendingObject.key, error);
792
- });
793
+ }
793
794
  const link = AssetControllerFactory.buildObjectLink({
794
795
  basePath: normalizedBasePath,
795
796
  bucket: bucketRef,
@@ -1 +1 @@
1
- {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../../../../src/components/static-asset/controller/factory.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseRestController, type TRouteContext } from '@/base/controllers';\nimport { controller as controllerDecorator } from '@/base/metadata';\nimport {\n BaseStorageHelper,\n RequestUtility,\n StorageUtility,\n type IObjectLocation,\n type IObjectMetadata,\n type IObjectRef,\n type IStorageHelper,\n type IUploadFile,\n type IPostPolicy,\n type IUploadResult,\n type TUploadNaming,\n} from '@venizia/ignis-helpers';\nimport { HTTP, ResolverUtility, type ValueOrPromise } from '@venizia/ignis-helpers/common';\nimport type { AnyType, TValueOrAsyncResolver } from '@venizia/ignis-helpers/common';\nimport { BaseHelper, getError, UuidHelper } from '@venizia/ignis-helpers/core';\nimport { type Env } from 'hono';\nimport { readFileSync, rmSync } from 'node:fs';\nimport {\n RENDERABLE_CONTENT_TYPES,\n StaticAssetErrors,\n type TBucketParams,\n type TDefineExtraRoutes,\n type TListQuery,\n type TMetaLinkConfig,\n DEFAULT_PENDING_PREFIX,\n META_LINK_CREATE_FAILED,\n type TObjectParams,\n type TUploadPolicyRequest,\n type TObjectNameResolver,\n type TStaticAssetExtraOptions,\n type TStaticAssetsComponentOptions,\n type TStaticAssetStorageType,\n type TUploadQuery,\n WHITELIST_HEADERS,\n} from '../common';\nimport { AssetCommitToken, MetaLinkRecreateActions } from '../common';\nimport { AssetDefinitionBuilder } from './base.definition';\nimport { AssetKeyScope } from './key-scope';\nimport { AssetMetaLink } from './meta-link';\nimport { AssetRouteOptions } from './route-options';\n\nexport interface IAssetControllerOptions {\n controller: TStaticAssetsComponentOptions[string]['controller'];\n storage: TStaticAssetStorageType;\n helper: IStorageHelper;\n useMetaLink?: boolean;\n /** The table is erased at this seam on purpose. The public option types carry the real `Schema` and check it; inside the controller every read and write is on MetaLink COLUMNS, and threading a table type nobody here constrains through 700 lines of handler buys nothing. */\n metaLink?: TMetaLinkConfig<AnyType>;\n options?: TStaticAssetExtraOptions;\n\n /** Decides the stored object name of each uploaded file. Absent leaves the storage helper's own naming untouched. */\n resolveObjectName?: TObjectNameResolver;\n\n /** Registers the application's own routes on the generated controller, after every built-in one. */\n /** Registers the application's own routes BEFORE every built-in one, so a literal path wins over the catch-all `rawObjectPath` produces. */\n defineRoutesBefore?: TDefineExtraRoutes;\n defineExtraRoutes?: TDefineExtraRoutes;\n}\n\n/** Hono ALREADY percent-decodes path params - a second decodeURIComponent throws on `report_100%.pdf` and turns `a%2Fb.png` into a DIFFERENT object; `isValidName`/`isValidPath` still run on this value, so traversal is still rejected. */\n/** The upload labels, read off the multipart form. Every value arrives as text, so `sequence` is the one that needs converting. */\n/** One list: the reader below and the stale-caller warning must agree. */\nconst UPLOAD_LABEL_NAMES = [\n 'principalType',\n 'principalId',\n 'variant',\n 'sequence',\n 'folderPath',\n] as const;\n\n/** The body of `AssetControllerFactory.findLabelsInQuery`, callable from the helpers above the class. */\nconst listLabelsInQuery = (opts: {\n query: Record<string, string>;\n names?: ReadonlyArray<(typeof UPLOAD_LABEL_NAMES)[number]>;\n}): string[] => (opts.names ?? UPLOAD_LABEL_NAMES).filter((name) => opts.query[name] !== undefined);\n\n/** Refused before the body is read: a route that ignored them would store an unlabelled row. */\nconst refuseLabelsInQuery = (opts: {\n query: Record<string, string>;\n names?: ReadonlyArray<(typeof UPLOAD_LABEL_NAMES)[number]>;\n reason?: string;\n}): void => {\n const names = listLabelsInQuery(opts);\n if (names.length > 0) {\n throw getError({\n error: StaticAssetErrors.LABELS_IN_QUERY,\n message: `${opts.reason ?? 'Upload labels belong in the request body, not the query'} | names: ${names.join(', ')}`,\n });\n }\n};\n\n/** The commit body carries four of the five: the object key - and so `folderPath` - was fixed when the policy was issued. */\nconst COMMIT_LABEL_NAMES = UPLOAD_LABEL_NAMES.filter((name) => name !== 'folderPath');\n\n// A multipart form hands strings; a JSON commit body may hand `sequence` as a number.\nconst readUploadLabels = (opts: {\n fields: Partial<Record<(typeof UPLOAD_LABEL_NAMES)[number], string | number>>;\n}): TUploadQuery => {\n const { fields } = opts;\n const read = (name: (typeof UPLOAD_LABEL_NAMES)[number]) => {\n const value = fields[name];\n return value === undefined || value === '' ? undefined : String(value);\n };\n\n const sequence = read('sequence');\n\n return {\n principalType: read('principalType'),\n principalId: read('principalId'),\n variant: read('variant'),\n sequence: sequence === undefined ? undefined : Number(sequence),\n folderPath: read('folderPath'),\n };\n};\n\nconst readObjectName: (rawObjectName: string) => string = (rawObjectName) => rawObjectName;\n\n/** Encodes an object path into a SINGLE url segment: `{objectName}` matches one segment only, so `/` must be percent-encoded too (Hono decodes it back before the handler reads the param). */\nconst encodeObjectPath: (objectPath: string) => string = (objectPath) => {\n return encodeURIComponent(objectPath);\n};\n\n/** The bucket one request works on: a configured value wins - called on every request, so an application may read an environment variable lazily - else the path param, which is only registered when there is no configured bucket. */\nconst resolveBucket = async (opts: {\n configured?: TValueOrAsyncResolver<string>;\n param?: string;\n}): Promise<string> => {\n const { configured, param } = opts;\n\n if (configured === undefined) {\n return param ?? '';\n }\n\n return ResolverUtility.resolveValueAsync({ value: configured });\n};\n\n/** Mirrors `BaseStorageHelper.normalizeObjectName`, which is protected: `resolveObjectName` is offered the very name the helper would otherwise have written. */\nconst defaultObjectName: (opts: { file: TUploadNaming }) => string = ({ file }) => {\n const { originalName, folderPath } = file;\n const normalizedFileName = originalName.toLowerCase().replace(/ /g, '_');\n\n if (!folderPath) {\n return normalizedFileName;\n }\n\n return `${folderPath.toLowerCase().replace(/ /g, '_')}/${normalizedFileName}`;\n};\n\n/**\n * Reads one `Range` header. Only a single byte range is honoured - multipart ranges need a multipart\n * body no browser asks for here. An unsatisfiable or malformed range returns `null`, and the caller\n * serves the whole object, which is what RFC 9110 allows.\n */\nconst readByteRange = (opts: {\n header: string | undefined;\n size: number;\n}): { start: number; end: number } | null => {\n const { header, size } = opts;\n\n if (!header || size <= 0) {\n return null;\n }\n\n const match = /^bytes=(\\d*)-(\\d*)$/.exec(header.trim());\n if (!match) {\n return null;\n }\n\n const [, rawStart, rawEnd] = match;\n\n // `bytes=-500` means the LAST 500 bytes, not \"from 0 to 500\".\n if (!rawStart) {\n const suffixLength = Number(rawEnd);\n if (!Number.isInteger(suffixLength) || suffixLength <= 0) {\n return null;\n }\n\n return { start: Math.max(size - suffixLength, 0), end: size - 1 };\n }\n\n const start = Number(rawStart);\n const end = rawEnd ? Number(rawEnd) : size - 1;\n\n if (!Number.isInteger(start) || !Number.isInteger(end) || start > end || start >= size) {\n return null;\n }\n\n return { start, end: Math.min(end, size - 1) };\n};\n\n/** Sets whitelisted metadata headers on the response context. `content-type` is not among them. */\nconst applyMetadataHeaders: (opts: {\n ctx: TRouteContext<Env>;\n metadata: IObjectMetadata;\n}) => void = ({ ctx, metadata }) => {\n Object.entries(metadata).forEach(([key, value]) => {\n if (!WHITELIST_HEADERS.includes(key.toLowerCase() as (typeof WHITELIST_HEADERS)[number])) {\n return;\n }\n ctx.header(key.toLowerCase(), String(value).replace(/[\\r\\n]/g, ''));\n });\n};\n\nexport class AssetControllerFactory extends BaseHelper {\n constructor() {\n super({ scope: AssetControllerFactory.name });\n }\n\n /** Names any label a caller put in the query - where the upload routes refuse it. */\n static findLabelsInQuery(opts: {\n query: Record<string, string>;\n names?: ReadonlyArray<(typeof UPLOAD_LABEL_NAMES)[number]>;\n }): string[] {\n return listLabelsInQuery(opts);\n }\n\n /** The URL of one object, in the shape its controller serves: no `/buckets/<name>` with a configured bucket, and a raw path with `rawObjectPath`. */\n static buildObjectLink(\n opts: IObjectLocation & {\n basePath: string;\n hasConfiguredBucket?: boolean;\n rawObjectPath?: boolean;\n },\n ): string {\n const { basePath, bucket, object } = opts;\n const { hasConfiguredBucket = false, rawObjectPath = false } = opts;\n\n const bucketSegment = hasConfiguredBucket ? '' : `/buckets/${bucket.name}`;\n const objectSegment = rawObjectPath ? object.key : encodeObjectPath(object.key);\n\n return `${basePath}${bucketSegment}/objects/${objectSegment}`;\n }\n\n /**\n * The served type comes from the object NAME, never the backend or the uploader: a renderable type on\n * the API origin is stored XSS. Public so a hand-written route makes the same decision - the\n * backend's own content-type is dropped by `WHITELIST_HEADERS`.\n */\n static resolveServedContentType(opts: { helper: IStorageHelper; object: IObjectRef }): {\n contentType: string;\n isRenderable: boolean;\n } {\n const { helper, object } = opts;\n const candidate = helper\n .getMimeType({ filename: object.key })\n .toLowerCase()\n .split(';')[0]\n .trim();\n\n if (!RENDERABLE_CONTENT_TYPES.has(candidate)) {\n return { contentType: HTTP.HeaderValues.APPLICATION_OCTET_STREAM, isRenderable: false };\n }\n\n return { contentType: candidate, isRenderable: true };\n }\n\n static defineAssetController(opts: IAssetControllerOptions) {\n const { controller, helper, options, useMetaLink, metaLink, storage } = opts;\n const { resolveObjectName, defineRoutesBefore, defineExtraRoutes } = opts;\n const { directUpload } = controller;\n const { name, basePath, routes, isStrict = true, bucket, rawObjectPath = false } = controller;\n const maxFolderDepth = options?.maxFolderDepth ?? BaseStorageHelper.DEFAULT_MAX_FOLDER_DEPTH;\n const maxBytes = options?.maxBytes;\n\n const hasConfiguredBucket = bucket !== undefined;\n\n // With the bucket in the URL, the bucket routes stay unscoped and the scope spans every bucket.\n if (controller.keyPrefix !== undefined && !hasConfiguredBucket) {\n throw getError({\n message: `[${name}] keyPrefix needs controller.bucket | a bucket in the URL is a bucket the caller chooses, and the bucket routes cannot be scoped`,\n });\n }\n\n const scope =\n controller.keyPrefix === undefined\n ? undefined\n : AssetKeyScope.normalizePrefix({ keyPrefix: controller.keyPrefix, helper, scope: name });\n const keyPrefix = scope?.keyPrefix;\n // `maxFolderDepth` counts the caller's folders; the scope's own are configuration, not input.\n const objectKeyMaxDepth = maxFolderDepth + (scope?.depth ?? 0);\n // The component's own name under a scope: the original name must stay one segment, as without one.\n const isScopedDefaultNaming =\n keyPrefix !== undefined && !resolveObjectName && !options?.normalizeNameFn;\n const definitions = AssetDefinitionBuilder.build({ hasConfiguredBucket, rawObjectPath });\n\n // The mount path may be declared with or without a leading slash; a link must carry exactly one.\n const normalizedBasePath = basePath.startsWith('/') ? basePath : `/${basePath}`;\n\n /** Only when the URL shape deviates: with neither option the storage helper's own link is left untouched. */\n const shapedLinkFn =\n hasConfiguredBucket || rawObjectPath\n ? (linkOptions: IObjectLocation) =>\n AssetControllerFactory.buildObjectLink({\n basePath: normalizedBasePath,\n bucket: linkOptions.bucket,\n object: linkOptions.object,\n hasConfiguredBucket,\n rawObjectPath,\n })\n : undefined;\n const normalizeLinkFn = options?.normalizeLinkFn ?? shapedLinkFn;\n\n @controllerDecorator({ path: basePath })\n class GeneratedStaticAssetController extends BaseRestController {\n constructor() {\n super({\n scope: name,\n path: basePath,\n isStrict,\n });\n }\n\n /** Clears the multipart spool files written by `parseMultipartBody({ storage: 'disk' })`. */\n removeSpoolFiles(spoolOptions: { paths: string[] }): void {\n for (const filePath of spoolOptions.paths) {\n try {\n rmSync(filePath, { force: true });\n } catch (error) {\n this.logger\n .for('UPLOAD')\n .error('Failed to remove spool file | path: %s | Error: %s', filePath, error);\n }\n }\n }\n\n override binding(): ValueOrPromise<void> {\n // First, so a literal path can win over the built-in catch-all `rawObjectPath` registers.\n defineRoutesBefore?.({ controller: this, helper, basePath: normalizedBasePath });\n\n // A single-bucket application has no reason to expose bucket creation or deletion, so the\n // four bucket-management routes are not registered once `bucket` is configured.\n if (!hasConfiguredBucket) {\n const getBucketsRoute = AssetRouteOptions.readOverride({ route: routes?.getBuckets });\n if (getBucketsRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.GET_BUCKETS, ...getBucketsRoute.override },\n }).to({\n handler: async (ctx) => {\n const buckets = await helper.getBuckets();\n return ctx.json(buckets, HTTP.ResultCodes.RS_2.Ok);\n },\n });\n }\n\n const getBucketByNameRoute = AssetRouteOptions.readOverride({\n route: routes?.getBucketByName,\n });\n if (getBucketByNameRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.GET_BUCKET_BY_NAME, ...getBucketByNameRoute.override },\n }).to({\n handler: async (ctx) => {\n const params = ctx.req.valid<TBucketParams>('param');\n const bucketName = await resolveBucket({\n configured: bucket,\n param: params.bucketName,\n });\n\n if (!helper.isValidBucketName({ bucket: { name: bucketName } })) {\n throw getError({ error: StaticAssetErrors.BUCKET_NAME_INVALID });\n }\n\n const found = await helper.getBucket({ bucket: { name: bucketName } });\n return ctx.json(found, HTTP.ResultCodes.RS_2.Ok);\n },\n });\n }\n\n const createBucketRoute = AssetRouteOptions.readOverride({ route: routes?.createBucket });\n if (createBucketRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.CREATE_BUCKET, ...createBucketRoute.override },\n }).to({\n handler: async (ctx) => {\n const params = ctx.req.valid<TBucketParams>('param');\n const bucketName = await resolveBucket({\n configured: bucket,\n param: params.bucketName,\n });\n\n if (!helper.isValidBucketName({ bucket: { name: bucketName } })) {\n throw getError({ error: StaticAssetErrors.BUCKET_NAME_INVALID });\n }\n\n const createdBucket = await helper.createBucket({ bucket: { name: bucketName } });\n return ctx.json(createdBucket, HTTP.ResultCodes.RS_2.Ok);\n },\n });\n }\n\n const deleteBucketRoute = AssetRouteOptions.readOverride({ route: routes?.deleteBucket });\n if (deleteBucketRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.DELETE_BUCKET, ...deleteBucketRoute.override },\n }).to({\n handler: async (ctx) => {\n const params = ctx.req.valid<TBucketParams>('param');\n const bucketName = await resolveBucket({\n configured: bucket,\n param: params.bucketName,\n });\n\n if (!helper.isValidBucketName({ bucket: { name: bucketName } })) {\n throw getError({ error: StaticAssetErrors.BUCKET_NAME_INVALID });\n }\n\n const isRemovedBucket = await helper.removeBucket({\n bucket: { name: bucketName },\n });\n return ctx.json({ isDeleted: isRemovedBucket }, HTTP.ResultCodes.RS_2.Ok);\n },\n });\n }\n }\n\n const getObjectByNameRoute = AssetRouteOptions.readOverride({\n route: routes?.getObjectByName,\n });\n if (getObjectByNameRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.GET_OBJECT_BY_NAME, ...getObjectByNameRoute.override },\n }).to({\n handler: async (ctx) => {\n const params = ctx.req.valid<TObjectParams>('param');\n const bucketName = await resolveBucket({\n configured: bucket,\n param: params.bucketName,\n });\n const objectName = readObjectName(params.objectName);\n\n if (!helper.isValidBucketName({ bucket: { name: bucketName } })) {\n throw getError({ error: StaticAssetErrors.BUCKET_NAME_INVALID });\n }\n\n if (\n !helper.isValidObjectKey({\n object: { key: objectName },\n maxDepth: objectKeyMaxDepth,\n })\n ) {\n throw getError({ error: StaticAssetErrors.OBJECT_NAME_INVALID });\n }\n\n // Before any storage call: a key outside the scope must not even be probed.\n AssetKeyScope.assertInScope({ key: objectName, keyPrefix });\n\n const fileStat = await helper.getStat({\n bucket: { name: bucketName },\n object: { key: objectName },\n });\n const { size, metadata } = fileStat;\n applyMetadataHeaders({ ctx, metadata });\n\n const served = AssetControllerFactory.resolveServedContentType({\n helper,\n object: { key: objectName },\n });\n ctx.header(HTTP.Headers.CONTENT_TYPE, served.contentType);\n ctx.header('x-content-type-options', 'nosniff');\n // Sandboxed even when renderable, so an unforeseen renderable type cannot reach this origin.\n ctx.header(HTTP.Headers.CONTENT_SECURITY_POLICY, 'sandbox');\n // Advertised unconditionally: a player only offers seeking once it sees this.\n ctx.header('accept-ranges', 'bytes');\n\n // A type outside the allow-list downloads instead of rendering; that is the XSS boundary.\n if (!served.isRenderable) {\n const inlineName = objectName.split('/').pop() ?? objectName;\n ctx.header(\n HTTP.Headers.CONTENT_DISPOSITION,\n RequestUtility.buildContentDispositionHeader({\n filename: inlineName,\n type: 'attachment',\n }),\n );\n }\n\n const range = readByteRange({ header: ctx.req.header('range'), size });\n\n if (range) {\n ctx.header(HTTP.Headers.CONTENT_LENGTH, String(range.end - range.start + 1));\n ctx.header(HTTP.Headers.CONTENT_RANGE, `bytes ${range.start}-${range.end}/${size}`);\n } else {\n ctx.header(HTTP.Headers.CONTENT_LENGTH, size.toString());\n }\n\n // The web stream is what a Response body wants, so no Node Readable sits in between.\n const stream = await helper.getObjectStream({\n bucket: { name: bucketName },\n object: { key: objectName },\n ...(range ? { range } : {}),\n });\n\n return new Response(stream, {\n headers: ctx.res.headers,\n status: range ? HTTP.ResultCodes.RS_2.PartialContent : HTTP.ResultCodes.RS_2.Ok,\n });\n },\n });\n }\n\n const downloadObjectByNameRoute = AssetRouteOptions.readOverride({\n route: routes?.downloadObjectByName,\n });\n if (downloadObjectByNameRoute.isEnabled) {\n this.bindRoute({\n configs: {\n ...definitions.DOWNLOAD_OBJECT_BY_NAME,\n ...downloadObjectByNameRoute.override,\n },\n }).to({\n handler: async (ctx) => {\n const params = ctx.req.valid<TObjectParams>('param');\n const bucketName = await resolveBucket({\n configured: bucket,\n param: params.bucketName,\n });\n const objectName = readObjectName(params.objectName);\n\n if (!helper.isValidBucketName({ bucket: { name: bucketName } })) {\n throw getError({ error: StaticAssetErrors.BUCKET_NAME_INVALID });\n }\n\n if (\n !helper.isValidObjectKey({\n object: { key: objectName },\n maxDepth: objectKeyMaxDepth,\n })\n ) {\n throw getError({ error: StaticAssetErrors.OBJECT_NAME_INVALID });\n }\n\n // Before any storage call: a key outside the scope must not even be probed.\n AssetKeyScope.assertInScope({ key: objectName, keyPrefix });\n\n const fileStat = await helper.getStat({\n bucket: { name: bucketName },\n object: { key: objectName },\n });\n const { size, metadata } = fileStat;\n applyMetadataHeaders({ ctx, metadata });\n\n // Download always attaches, so the served type only has to be honest, never renderable.\n const served = AssetControllerFactory.resolveServedContentType({\n helper,\n object: { key: objectName },\n });\n ctx.header(HTTP.Headers.CONTENT_TYPE, served.contentType);\n ctx.header(HTTP.Headers.CONTENT_LENGTH, size.toString());\n\n const fileName = objectName.split('/').pop() ?? objectName;\n ctx.header(\n HTTP.Headers.CONTENT_DISPOSITION,\n RequestUtility.buildContentDispositionHeader({\n filename: fileName,\n type: 'attachment',\n }),\n );\n ctx.header('x-content-type-options', 'nosniff');\n ctx.header(HTTP.Headers.CONTENT_SECURITY_POLICY, 'sandbox');\n\n const stream = await helper.getObjectStream({\n bucket: { name: bucketName },\n object: { key: objectName },\n });\n return new Response(stream, {\n headers: ctx.res.headers,\n status: HTTP.ResultCodes.RS_2.Ok,\n });\n },\n });\n }\n\n const uploadRoute = AssetRouteOptions.readOverride({ route: routes?.upload });\n if (uploadRoute.isEnabled) {\n const uploadMiddleware =\n maxBytes === undefined\n ? uploadRoute.override.middleware\n : AssetRouteOptions.appendLengthGuard({\n middleware: uploadRoute.override.middleware,\n maxBytes,\n });\n\n this.bindRoute({\n configs: {\n ...definitions.UPLOAD,\n ...uploadRoute.override,\n middleware: uploadMiddleware,\n },\n }).to({\n handler: async (ctx) => {\n // A configured bucket drops `params` from this route entirely, so it is read only when it exists.\n const bucketParam = hasConfiguredBucket\n ? undefined\n : ctx.req.valid<TBucketParams>('param').bucketName;\n const bucketName = await resolveBucket({ configured: bucket, param: bucketParam });\n\n if (!helper.isValidBucketName({ bucket: { name: bucketName } })) {\n throw getError({ error: StaticAssetErrors.BUCKET_NAME_INVALID });\n }\n\n const validateFolderPath = (folderPath: string) => {\n const normalizedFolder = folderPath.replace(/^\\/+|\\/+$/g, '');\n if (!normalizedFolder) {\n throw getError({ error: StaticAssetErrors.FOLDER_PATH_INVALID });\n }\n // maxFolderDepth excludes the filename, so it is compared directly against segment count.\n const folderSegments = normalizedFolder.split('/');\n if (folderSegments.length > maxFolderDepth) {\n throw getError({\n error: StaticAssetErrors.FOLDER_DEPTH_EXCEEDED,\n message: `Folder path exceeds max depth of ${maxFolderDepth}`,\n });\n }\n const invalidSegmentIndex = folderSegments.findIndex(\n (segment) => !helper.isValidSegment({ segment }),\n );\n if (invalidSegmentIndex !== -1) {\n throw getError({\n error: StaticAssetErrors.FOLDER_SEGMENT_INVALID,\n message: `Invalid folder path segment: ${folderSegments[invalidSegmentIndex]}`,\n });\n }\n };\n\n refuseLabelsInQuery({ query: ctx.req.query() });\n\n const { files: filesArray, fields } = await RequestUtility.parseMultipartBody({\n context: ctx,\n storage: options?.parseMultipartBody?.storage,\n uploadDir: options?.parseMultipartBody?.uploadDir,\n });\n\n // Labels travel with the payload, not the URL, so the folder check waits for the parse.\n const query = readUploadLabels({ fields });\n\n const folderPath = query.folderPath;\n if (folderPath) {\n validateFolderPath(folderPath);\n }\n\n const spoolPaths = filesArray\n .map((file) => file.path)\n .filter((filePath): filePath is string => Boolean(filePath));\n\n let uploaded: IUploadResult[];\n try {\n // `storage: 'disk'` spools the payload to `uploadDir` and returns `path` instead of `buffer`; the storage helpers only ever write `buffer`, so it must be read back.\n const modifiedFiles: IUploadFile[] = filesArray.map((file) => {\n const buffer = file.buffer ?? (file.path ? readFileSync(file.path) : undefined);\n\n if (!buffer?.length) {\n throw getError({\n error: StaticAssetErrors.FILE_EMPTY,\n message: `Empty file content | name: ${file.originalname}`,\n });\n }\n\n // Authoritative: `buffer.length`, not the client-declared `size`.\n if (maxBytes !== undefined && buffer.length > maxBytes) {\n throw getError({\n error: StaticAssetErrors.UPLOAD_TOO_LARGE,\n message: `File ${file.originalname} of ${buffer.length} bytes exceeds the maximum of ${maxBytes}`,\n });\n }\n\n return {\n originalName: file.originalname,\n mimetype: file.mimetype,\n buffer,\n size: file.size,\n encoding: file.encoding,\n folderPath: folderPath ?? undefined,\n };\n });\n\n // Built per request: the hook is offered the bucket, which only the route knows. With\n // neither hook nor scope, `normalizeNameFn` stays exactly as configured. Under a scope,\n // the component's own default is placed inside it; an application hook's key is\n // checked, never rewritten, because the application may record that key elsewhere.\n const normalizeNameFn =\n resolveObjectName || keyPrefix !== undefined\n ? (naming: { file: TUploadNaming }) => {\n if (\n isScopedDefaultNaming &&\n !helper.isValidSegment({ segment: naming.file.originalName })\n ) {\n throw getError({ message: '[upload] Invalid original file name' });\n }\n\n const defaultKey = options?.normalizeNameFn\n ? options.normalizeNameFn(naming)\n : `${keyPrefix ?? ''}${defaultObjectName(naming)}`;\n\n const key = resolveObjectName\n ? resolveObjectName({\n bucket: { name: bucketName },\n file: naming.file,\n defaultKey,\n })\n : defaultKey;\n\n if (!AssetKeyScope.isInScope({ key, keyPrefix })) {\n throw getError({\n error: StaticAssetErrors.OBJECT_KEY_OUT_OF_SCOPE,\n message: `Object key is outside the key prefix of this controller | key: ${key} | keyPrefix: ${keyPrefix}`,\n });\n }\n\n return key;\n }\n : options?.normalizeNameFn;\n\n const result = await helper.upload({\n bucket: { name: bucketName },\n files: modifiedFiles,\n normalizeNameFn,\n normalizeLinkFn,\n // Without this the helper re-validates against its own hard default of 2, so an app configured for a deeper tree spools the body and only then fails inside the helper.\n maxFolderDepth: objectKeyMaxDepth,\n });\n uploaded = result;\n } finally {\n this.removeSpoolFiles({ paths: spoolPaths });\n }\n\n if (!useMetaLink || !metaLink) {\n return ctx.json(uploaded, HTTP.ResultCodes.RS_2.Ok);\n }\n\n const results: IUploadResult[] = [];\n for (const uploadResult of uploaded) {\n try {\n const fileStat = await helper.getStat({\n bucket: uploadResult.bucket,\n object: uploadResult.object,\n });\n\n const createdMetaLink = await AssetMetaLink.createRow({\n metaLink,\n helper,\n storage,\n uploadResult,\n fileStat,\n query,\n });\n\n results.push({ ...uploadResult, metaLink: { data: createdMetaLink } });\n } catch (error) {\n this.logger\n .for('UPLOAD')\n .error(\n 'Failed to create MetaLink | objectName: %s | Error: %s',\n uploadResult.object.key,\n error,\n );\n results.push({\n ...uploadResult,\n // A CODE, never the driver text. This handler returns 200, so it bypasses the\n // error middleware and `database.handler` - the two places that strip\n // `detail`/`table`/`constraint` - and shipped raw constraint names to the client.\n // The real error is already logged in full immediately above.\n metaLink: { error: META_LINK_CREATE_FAILED },\n });\n }\n }\n return ctx.json(results, HTTP.ResultCodes.RS_2.Ok);\n },\n });\n }\n\n const deleteObjectRoute = AssetRouteOptions.readOverride({ route: routes?.deleteObject });\n if (deleteObjectRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.DELETE_OBJECT, ...deleteObjectRoute.override },\n }).to({\n handler: async (ctx) => {\n const params = ctx.req.valid<TObjectParams>('param');\n const bucketName = await resolveBucket({\n configured: bucket,\n param: params.bucketName,\n });\n const objectName = readObjectName(params.objectName);\n\n if (!helper.isValidBucketName({ bucket: { name: bucketName } })) {\n throw getError({ error: StaticAssetErrors.BUCKET_NAME_INVALID });\n }\n\n if (\n !helper.isValidObjectKey({\n object: { key: objectName },\n maxDepth: objectKeyMaxDepth,\n })\n ) {\n throw getError({ error: StaticAssetErrors.OBJECT_NAME_INVALID });\n }\n\n // Before any storage call: a key outside the scope must not even be probed.\n AssetKeyScope.assertInScope({ key: objectName, keyPrefix });\n\n // Deliberately idempotent: S3 answers 200 for a key that was never there, and consumers\n // already depend on it. `disk` throws instead, so the two are reconciled here, not below.\n try {\n await helper.removeObject({\n bucket: { name: bucketName },\n object: { key: objectName },\n });\n } catch (error) {\n if (!StorageUtility.isNotFoundError({ error })) {\n throw error;\n }\n }\n\n if (!useMetaLink || !metaLink) {\n return ctx.json({ success: true }, HTTP.ResultCodes.RS_2.Ok);\n }\n\n const deleteRepository = await ResolverUtility.resolveValueAsync({\n value: metaLink.repository,\n });\n deleteRepository\n .deleteAll({\n where: {\n bucketName,\n objectName,\n },\n })\n .then(() => {\n this.logger\n .for('DELETE_OBJECT')\n .info('Successfully to delete MetaLink for %s/%s', bucketName, objectName);\n })\n .catch((error) => {\n this.logger\n .for('DELETE_OBJECT')\n .error(\n 'Failed to delete MetaLink | bucket: %s | objectName: %s | Error: %s',\n bucketName,\n objectName,\n error,\n );\n });\n\n return ctx.json({ success: true }, HTTP.ResultCodes.RS_2.Ok);\n },\n });\n }\n\n const listObjectsRoute = AssetRouteOptions.readOverride({ route: routes?.listObjects });\n if (listObjectsRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.LIST_OBJECTS, ...listObjectsRoute.override },\n }).to({\n handler: async (ctx) => {\n // A configured bucket drops `params` from this route entirely, so it is read only when it exists.\n const bucketParam = hasConfiguredBucket\n ? undefined\n : ctx.req.valid<TBucketParams>('param').bucketName;\n const bucketName = await resolveBucket({ configured: bucket, param: bucketParam });\n const { prefix, recursive, maxKeys } = ctx.req.valid<TListQuery>('query');\n\n if (!helper.isValidBucketName({ bucket: { name: bucketName } })) {\n throw getError({ error: StaticAssetErrors.BUCKET_NAME_INVALID });\n }\n\n // A NaN or 0 maxKeys is silently treated as \"unlimited\" by the storage backends, so an unparsable value must be rejected instead of forwarded.\n let resolvedMaxKeys: number | undefined;\n if (maxKeys !== undefined) {\n resolvedMaxKeys = Number(maxKeys);\n\n if (!Number.isInteger(resolvedMaxKeys) || resolvedMaxKeys < 1) {\n throw getError({\n error: StaticAssetErrors.MAX_KEYS_INVALID,\n message: `Invalid maxKeys | Expected a positive integer | value: ${maxKeys}`,\n });\n }\n }\n\n const scoped = AssetKeyScope.resolveListPrefix({ prefix, keyPrefix });\n if (scoped.isOutOfScope) {\n return ctx.json([], HTTP.ResultCodes.RS_2.Ok);\n }\n\n const objects = await helper.listObjects({\n bucket: { name: bucketName },\n prefix: scoped.prefix,\n useRecursive: recursive === 'true',\n maxKeys: resolvedMaxKeys,\n });\n\n return ctx.json(objects, HTTP.ResultCodes.RS_2.Ok);\n },\n });\n }\n\n if (directUpload) {\n if (!hasConfiguredBucket) {\n throw getError({\n message: `[${name}] directUpload needs controller.bucket | a policy names one bucket, and a bucket in the URL is a bucket the caller chooses`,\n });\n }\n\n const pendingPrefix = directUpload.pendingPrefix ?? DEFAULT_PENDING_PREFIX;\n // The scope rides inside the pending key, so the commit, which strips `pendingPrefix`, lands inside it.\n const policyKeyPrefix = `${pendingPrefix}${keyPrefix ?? ''}`;\n\n const uploadPolicyRoute = AssetRouteOptions.readOverride({ route: routes?.uploadPolicy });\n if (uploadPolicyRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.UPLOAD_POLICY, ...uploadPolicyRoute.override },\n }).to({\n handler: async (ctx) => {\n const result = await directUpload.authorize({ context: ctx });\n if (!result) {\n throw getError({ error: StaticAssetErrors.UPLOAD_NOT_AUTHORIZED });\n }\n\n const { files } = ctx.req.valid<TUploadPolicyRequest>('json');\n const bucketName = await resolveBucket({ configured: bucket });\n\n const policies: Array<IPostPolicy & { objectName: string; commitToken: string }> =\n [];\n for (const file of files) {\n if (file.size !== undefined && file.size > directUpload.maxBytes) {\n throw getError({\n error: StaticAssetErrors.UPLOAD_TOO_LARGE,\n message: `File '${file.fileName}' is ${file.size} bytes, over the ${directUpload.maxBytes} the policy allows`,\n });\n }\n\n // Generated, never taken from the caller: a key the caller picks is a key the caller\n // can collide with, and the pending object is the one thing a policy authorizes.\n const objectName = `${policyKeyPrefix}${UuidHelper.getInstance().v4()}/${file.fileName}`;\n const policy = await helper.presignPost({\n bucket: { name: bucketName },\n keyPrefix: policyKeyPrefix,\n maxBytes: directUpload.maxBytes,\n contentType: file.contentType,\n expiresIn: directUpload.expiresIn,\n });\n\n policies.push({\n ...policy,\n objectName,\n commitToken: AssetCommitToken.build({\n payload: {\n bucket: bucketName,\n key: objectName,\n expiresAt: new Date(policy.expiresAt).getTime(),\n },\n secretKey: directUpload.secretKey,\n }),\n });\n }\n\n return ctx.json(policies, HTTP.ResultCodes.RS_2.Ok);\n },\n });\n }\n\n const uploadCommitRoute = AssetRouteOptions.readOverride({ route: routes?.uploadCommit });\n if (uploadCommitRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.UPLOAD_COMMIT, ...uploadCommitRoute.override },\n }).to({\n handler: async (ctx) => {\n const commitQuery = ctx.req.query();\n refuseLabelsInQuery({ query: commitQuery, names: COMMIT_LABEL_NAMES });\n refuseLabelsInQuery({\n query: commitQuery,\n names: ['folderPath'],\n reason:\n 'folderPath was decided when the upload policy was issued; the commit route cannot move the object',\n });\n\n const { commitToken, ...labels } = ctx.req.valid<\n { commitToken: string } & TUploadQuery\n >('json');\n\n // Verified BEFORE any storage call. That is what keeps this route from being a name\n // prober: a forged token fails without a round trip, so timing says nothing.\n const payload = AssetCommitToken.read({\n token: commitToken,\n secretKey: directUpload.secretKey,\n });\n\n // Labels, not authorization - the token deliberately carries no business fields, so\n // they travel beside it rather than inside it.\n const query = readUploadLabels({ fields: labels });\n\n const bucketRef = { name: payload.bucket };\n const pendingObject = { key: payload.key };\n const object = { key: payload.key.slice(pendingPrefix.length) };\n\n // A token another controller signed with the same secret must not land outside this scope.\n AssetKeyScope.assertInScope({ key: object.key, keyPrefix });\n\n // Before the copy, so a hook that throws leaves the object under the pending prefix\n // for a lifecycle rule, rather than stranding it at the final key.\n await directUpload.onCommit?.({ bucket: bucketRef, pendingObject, object });\n\n await helper.copyObject({\n bucket: bucketRef,\n source: pendingObject,\n destination: object,\n });\n // The copy IS the commit; removing the temporary object is cleanup. A failure here\n // leaves one object for the lifecycle rule, and failing the request would tell the\n // caller their upload did not work when it did.\n await helper\n .removeObject({ bucket: bucketRef, object: pendingObject })\n .catch((error) => {\n this.logger\n .for('UPLOAD_COMMIT')\n .warn(\n 'Committed, but the pending object remains | key: %s | error: %s',\n pendingObject.key,\n error,\n );\n });\n\n const link = AssetControllerFactory.buildObjectLink({\n basePath: normalizedBasePath,\n bucket: bucketRef,\n object,\n hasConfiguredBucket,\n rawObjectPath,\n });\n\n // The two paths have to agree: without this a client reading `metaLink` off the\n // response renders an empty state with no error - the failure nobody reports.\n let metaLinkResult: IUploadResult['metaLink'];\n if (useMetaLink && metaLink) {\n try {\n const fileStat = await helper.getStat({ bucket: bucketRef, object });\n const data = await AssetMetaLink.createRow({\n metaLink,\n helper,\n storage,\n uploadResult: AssetMetaLink.buildStoredUploadResult({\n helper,\n bucket: bucketRef,\n object,\n link,\n fileStat,\n }),\n fileStat,\n query,\n });\n\n metaLinkResult = { data };\n } catch (error) {\n // The object IS committed by now. A 500 would send the caller back with a token\n // whose source no longer exists, so this rides the body as a code, like UPLOAD.\n this.logger\n .for('UPLOAD_COMMIT')\n .error(\n 'Failed to create MetaLink | objectName: %s | Error: %s',\n object.key,\n error,\n );\n metaLinkResult = { error: META_LINK_CREATE_FAILED };\n }\n }\n\n return ctx.json(\n {\n bucket: bucketRef,\n object,\n link,\n ...(metaLinkResult === undefined ? {} : { metaLink: metaLinkResult }),\n },\n HTTP.ResultCodes.RS_2.Ok,\n );\n },\n });\n }\n }\n\n if (useMetaLink && metaLink) {\n const recreateMetaLinkRoute = AssetRouteOptions.readOverride({\n route: routes?.recreateMetaLink,\n });\n if (recreateMetaLinkRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.RECREATE_METALINK, ...recreateMetaLinkRoute.override },\n }).to({\n handler: async (ctx) => {\n // This route takes no labels anywhere: one in the query would land an unlabelled row.\n refuseLabelsInQuery({\n query: ctx.req.query(),\n reason:\n 'This route recreates a MetaLink for an existing object and takes no labels',\n });\n\n const params = ctx.req.valid<TObjectParams>('param');\n const bucketName = await resolveBucket({\n configured: bucket,\n param: params.bucketName,\n });\n const objectName = readObjectName(params.objectName);\n\n if (!helper.isValidBucketName({ bucket: { name: bucketName } })) {\n throw getError({ error: StaticAssetErrors.BUCKET_NAME_INVALID });\n }\n\n if (\n !helper.isValidObjectKey({\n object: { key: objectName },\n maxDepth: objectKeyMaxDepth,\n })\n ) {\n throw getError({ error: StaticAssetErrors.OBJECT_NAME_INVALID });\n }\n\n // Before any storage call: a key outside the scope must not even be probed.\n AssetKeyScope.assertInScope({ key: objectName, keyPrefix });\n\n const bucketRef = { name: bucketName };\n const object = { key: objectName };\n const fileStat = await helper.getStat({ bucket: bucketRef, object });\n\n const link = options?.normalizeLinkFn\n ? options.normalizeLinkFn({ bucket: bucketRef, object })\n : AssetControllerFactory.buildObjectLink({\n basePath: normalizedBasePath,\n bucket: bucketRef,\n object,\n hasConfiguredBucket,\n rawObjectPath,\n });\n\n const refreshed = await AssetMetaLink.refreshRows({\n metaLink,\n helper,\n bucket: bucketRef,\n object,\n link,\n fileStat,\n });\n\n if (refreshed.count > 0) {\n return ctx.json(\n {\n success: true,\n action: MetaLinkRecreateActions.REFRESHED,\n count: refreshed.count,\n metaLink: refreshed.data[0],\n metaLinks: refreshed.data,\n },\n HTTP.ResultCodes.RS_2.Ok,\n );\n }\n\n // Not atomic with the refresh above: two concurrent calls may both create, which the\n // table allows - rows per pair are deliberately not unique.\n const created = await AssetMetaLink.createRow({\n metaLink,\n helper,\n storage,\n uploadResult: AssetMetaLink.buildStoredUploadResult({\n helper,\n bucket: bucketRef,\n object,\n link,\n fileStat,\n }),\n fileStat,\n query: {},\n });\n\n return ctx.json(\n {\n success: true,\n action: MetaLinkRecreateActions.CREATED,\n count: 1,\n metaLink: created,\n metaLinks: [created],\n },\n HTTP.ResultCodes.RS_2.Ok,\n );\n },\n });\n }\n }\n\n // Last, so a built-in route always wins a path collision with an application's own.\n defineExtraRoutes?.({ controller: this, helper, basePath: normalizedBasePath });\n }\n }\n\n Object.defineProperty(GeneratedStaticAssetController, 'name', {\n value: name,\n configurable: true,\n });\n return GeneratedStaticAssetController;\n }\n}\n"]}
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../../../../src/components/static-asset/controller/factory.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseRestController, type TRouteContext } from '@/base/controllers';\nimport { controller as controllerDecorator } from '@/base/metadata';\nimport {\n BaseStorageHelper,\n RequestUtility,\n StorageUtility,\n type IObjectLocation,\n type IObjectMetadata,\n type IObjectRef,\n type IStorageHelper,\n type IUploadFile,\n type IPostPolicy,\n type IUploadResult,\n type TUploadNaming,\n} from '@venizia/ignis-helpers';\nimport { HTTP, ResolverUtility, type ValueOrPromise } from '@venizia/ignis-helpers/common';\nimport type { AnyType, TValueOrAsyncResolver } from '@venizia/ignis-helpers/common';\nimport { BaseHelper, getError, UuidHelper } from '@venizia/ignis-helpers/core';\nimport { type Env } from 'hono';\nimport { readFileSync, rmSync } from 'node:fs';\nimport {\n RENDERABLE_CONTENT_TYPES,\n StaticAssetErrors,\n type TBucketParams,\n type TDefineExtraRoutes,\n type TListQuery,\n type TMetaLinkConfig,\n DEFAULT_PENDING_PREFIX,\n META_LINK_CREATE_FAILED,\n type TObjectParams,\n type TUploadPolicyRequest,\n type TObjectNameResolver,\n type TStaticAssetExtraOptions,\n type TStaticAssetsComponentOptions,\n type TStaticAssetStorageType,\n type TUploadQuery,\n WHITELIST_HEADERS,\n} from '../common';\nimport { AssetCommitToken, MetaLinkRecreateActions } from '../common';\nimport { AssetDefinitionBuilder } from './base.definition';\nimport { AssetKeyScope } from './key-scope';\nimport { AssetMetaLink } from './meta-link';\nimport { AssetRouteOptions } from './route-options';\n\nexport interface IAssetControllerOptions {\n controller: TStaticAssetsComponentOptions[string]['controller'];\n storage: TStaticAssetStorageType;\n helper: IStorageHelper;\n useMetaLink?: boolean;\n /** The table is erased at this seam on purpose. The public option types carry the real `Schema` and check it; inside the controller every read and write is on MetaLink COLUMNS, and threading a table type nobody here constrains through 700 lines of handler buys nothing. */\n metaLink?: TMetaLinkConfig<AnyType>;\n options?: TStaticAssetExtraOptions;\n\n /** Decides the stored object name of each uploaded file. Absent leaves the storage helper's own naming untouched. */\n resolveObjectName?: TObjectNameResolver;\n\n /** Registers the application's own routes on the generated controller, after every built-in one. */\n /** Registers the application's own routes BEFORE every built-in one, so a literal path wins over the catch-all `rawObjectPath` produces. */\n defineRoutesBefore?: TDefineExtraRoutes;\n defineExtraRoutes?: TDefineExtraRoutes;\n}\n\n/** Hono ALREADY percent-decodes path params - a second decodeURIComponent throws on `report_100%.pdf` and turns `a%2Fb.png` into a DIFFERENT object; `isValidName`/`isValidPath` still run on this value, so traversal is still rejected. */\n/** The upload labels, read off the multipart form. Every value arrives as text, so `sequence` is the one that needs converting. */\n/** One list: the reader below and the stale-caller warning must agree. */\nconst UPLOAD_LABEL_NAMES = [\n 'principalType',\n 'principalId',\n 'variant',\n 'sequence',\n 'folderPath',\n] as const;\n\n/** The body of `AssetControllerFactory.findLabelsInQuery`, callable from the helpers above the class. */\nconst listLabelsInQuery = (opts: {\n query: Record<string, string>;\n names?: ReadonlyArray<(typeof UPLOAD_LABEL_NAMES)[number]>;\n}): string[] => (opts.names ?? UPLOAD_LABEL_NAMES).filter((name) => opts.query[name] !== undefined);\n\n/** Refused before the body is read: a route that ignored them would store an unlabelled row. */\nconst refuseLabelsInQuery = (opts: {\n query: Record<string, string>;\n names?: ReadonlyArray<(typeof UPLOAD_LABEL_NAMES)[number]>;\n reason?: string;\n}): void => {\n const names = listLabelsInQuery(opts);\n if (names.length > 0) {\n throw getError({\n error: StaticAssetErrors.LABELS_IN_QUERY,\n message: `${opts.reason ?? 'Upload labels belong in the request body, not the query'} | names: ${names.join(', ')}`,\n });\n }\n};\n\n/** The commit body carries four of the five: the object key - and so `folderPath` - was fixed when the policy was issued. */\nconst COMMIT_LABEL_NAMES = UPLOAD_LABEL_NAMES.filter((name) => name !== 'folderPath');\n\n// A multipart form hands strings; a JSON commit body may hand `sequence` as a number.\nconst readUploadLabels = (opts: {\n fields: Partial<Record<(typeof UPLOAD_LABEL_NAMES)[number], string | number>>;\n}): TUploadQuery => {\n const { fields } = opts;\n const read = (name: (typeof UPLOAD_LABEL_NAMES)[number]) => {\n const value = fields[name];\n return value === undefined || value === '' ? undefined : String(value);\n };\n\n const sequence = read('sequence');\n\n return {\n principalType: read('principalType'),\n principalId: read('principalId'),\n variant: read('variant'),\n sequence: sequence === undefined ? undefined : Number(sequence),\n folderPath: read('folderPath'),\n };\n};\n\nconst readObjectName: (rawObjectName: string) => string = (rawObjectName) => rawObjectName;\n\n/** Encodes an object path into a SINGLE url segment: `{objectName}` matches one segment only, so `/` must be percent-encoded too (Hono decodes it back before the handler reads the param). */\nconst encodeObjectPath: (objectPath: string) => string = (objectPath) => {\n return encodeURIComponent(objectPath);\n};\n\n/** The bucket one request works on: a configured value wins - called on every request, so an application may read an environment variable lazily - else the path param, which is only registered when there is no configured bucket. */\nconst resolveBucket = async (opts: {\n configured?: TValueOrAsyncResolver<string>;\n param?: string;\n}): Promise<string> => {\n const { configured, param } = opts;\n\n if (configured === undefined) {\n return param ?? '';\n }\n\n return ResolverUtility.resolveValueAsync({ value: configured });\n};\n\n/** Mirrors `BaseStorageHelper.normalizeObjectName`, which is protected: `resolveObjectName` is offered the very name the helper would otherwise have written. */\nconst defaultObjectName: (opts: { file: TUploadNaming }) => string = ({ file }) => {\n const { originalName, folderPath } = file;\n const normalizedFileName = originalName.toLowerCase().replace(/ /g, '_');\n\n if (!folderPath) {\n return normalizedFileName;\n }\n\n return `${folderPath.toLowerCase().replace(/ /g, '_')}/${normalizedFileName}`;\n};\n\n/**\n * Reads one `Range` header. Only a single byte range is honoured - multipart ranges need a multipart\n * body no browser asks for here. An unsatisfiable or malformed range returns `null`, and the caller\n * serves the whole object, which is what RFC 9110 allows.\n */\nconst readByteRange = (opts: {\n header: string | undefined;\n size: number;\n}): { start: number; end: number } | null => {\n const { header, size } = opts;\n\n if (!header || size <= 0) {\n return null;\n }\n\n const match = /^bytes=(\\d*)-(\\d*)$/.exec(header.trim());\n if (!match) {\n return null;\n }\n\n const [, rawStart, rawEnd] = match;\n\n // `bytes=-500` means the LAST 500 bytes, not \"from 0 to 500\".\n if (!rawStart) {\n const suffixLength = Number(rawEnd);\n if (!Number.isInteger(suffixLength) || suffixLength <= 0) {\n return null;\n }\n\n return { start: Math.max(size - suffixLength, 0), end: size - 1 };\n }\n\n const start = Number(rawStart);\n const end = rawEnd ? Number(rawEnd) : size - 1;\n\n if (!Number.isInteger(start) || !Number.isInteger(end) || start > end || start >= size) {\n return null;\n }\n\n return { start, end: Math.min(end, size - 1) };\n};\n\n/** Sets whitelisted metadata headers on the response context. `content-type` is not among them. */\nconst applyMetadataHeaders: (opts: {\n ctx: TRouteContext<Env>;\n metadata: IObjectMetadata;\n}) => void = ({ ctx, metadata }) => {\n Object.entries(metadata).forEach(([key, value]) => {\n if (!WHITELIST_HEADERS.includes(key.toLowerCase() as (typeof WHITELIST_HEADERS)[number])) {\n return;\n }\n ctx.header(key.toLowerCase(), String(value).replace(/[\\r\\n]/g, ''));\n });\n};\n\nexport class AssetControllerFactory extends BaseHelper {\n constructor() {\n super({ scope: AssetControllerFactory.name });\n }\n\n /** Names any label a caller put in the query - where the upload routes refuse it. */\n static findLabelsInQuery(opts: {\n query: Record<string, string>;\n names?: ReadonlyArray<(typeof UPLOAD_LABEL_NAMES)[number]>;\n }): string[] {\n return listLabelsInQuery(opts);\n }\n\n /** The URL of one object, in the shape its controller serves: no `/buckets/<name>` with a configured bucket, and a raw path with `rawObjectPath`. */\n static buildObjectLink(\n opts: IObjectLocation & {\n basePath: string;\n hasConfiguredBucket?: boolean;\n rawObjectPath?: boolean;\n },\n ): string {\n const { basePath, bucket, object } = opts;\n const { hasConfiguredBucket = false, rawObjectPath = false } = opts;\n\n const bucketSegment = hasConfiguredBucket ? '' : `/buckets/${bucket.name}`;\n const objectSegment = rawObjectPath ? object.key : encodeObjectPath(object.key);\n\n return `${basePath}${bucketSegment}/objects/${objectSegment}`;\n }\n\n /**\n * The served type comes from the object NAME, never the backend or the uploader: a renderable type on\n * the API origin is stored XSS. Public so a hand-written route makes the same decision - the\n * backend's own content-type is dropped by `WHITELIST_HEADERS`.\n */\n static resolveServedContentType(opts: { helper: IStorageHelper; object: IObjectRef }): {\n contentType: string;\n isRenderable: boolean;\n } {\n const { helper, object } = opts;\n const candidate = helper\n .getMimeType({ filename: object.key })\n .toLowerCase()\n .split(';')[0]\n .trim();\n\n if (!RENDERABLE_CONTENT_TYPES.has(candidate)) {\n return { contentType: HTTP.HeaderValues.APPLICATION_OCTET_STREAM, isRenderable: false };\n }\n\n return { contentType: candidate, isRenderable: true };\n }\n\n static defineAssetController(opts: IAssetControllerOptions) {\n const { controller, helper, options, useMetaLink, metaLink, storage } = opts;\n const { resolveObjectName, defineRoutesBefore, defineExtraRoutes } = opts;\n const { directUpload } = controller;\n const { name, basePath, routes, isStrict = true, bucket, rawObjectPath = false } = controller;\n const maxFolderDepth = options?.maxFolderDepth ?? BaseStorageHelper.DEFAULT_MAX_FOLDER_DEPTH;\n const maxBytes = options?.maxBytes;\n\n const hasConfiguredBucket = bucket !== undefined;\n\n // With the bucket in the URL, the bucket routes stay unscoped and the scope spans every bucket.\n if (controller.keyPrefix !== undefined && !hasConfiguredBucket) {\n throw getError({\n message: `[${name}] keyPrefix needs controller.bucket | a bucket in the URL is a bucket the caller chooses, and the bucket routes cannot be scoped`,\n });\n }\n\n const scope =\n controller.keyPrefix === undefined\n ? undefined\n : AssetKeyScope.normalizePrefix({ keyPrefix: controller.keyPrefix, helper, scope: name });\n const keyPrefix = scope?.keyPrefix;\n // `maxFolderDepth` counts the caller's folders; the scope's own are configuration, not input.\n const objectKeyMaxDepth = maxFolderDepth + (scope?.depth ?? 0);\n // The component's own name under a scope: the original name must stay one segment, as without one.\n const isScopedDefaultNaming =\n keyPrefix !== undefined && !resolveObjectName && !options?.normalizeNameFn;\n const definitions = AssetDefinitionBuilder.build({ hasConfiguredBucket, rawObjectPath });\n\n // The mount path may be declared with or without a leading slash; a link must carry exactly one.\n const normalizedBasePath = basePath.startsWith('/') ? basePath : `/${basePath}`;\n\n /** Only when the URL shape deviates: with neither option the storage helper's own link is left untouched. */\n const shapedLinkFn =\n hasConfiguredBucket || rawObjectPath\n ? (linkOptions: IObjectLocation) =>\n AssetControllerFactory.buildObjectLink({\n basePath: normalizedBasePath,\n bucket: linkOptions.bucket,\n object: linkOptions.object,\n hasConfiguredBucket,\n rawObjectPath,\n })\n : undefined;\n const normalizeLinkFn = options?.normalizeLinkFn ?? shapedLinkFn;\n\n @controllerDecorator({ path: basePath })\n class GeneratedStaticAssetController extends BaseRestController {\n constructor() {\n super({\n scope: name,\n path: basePath,\n isStrict,\n });\n }\n\n /** Clears the multipart spool files written by `parseMultipartBody({ storage: 'disk' })`. */\n removeSpoolFiles(spoolOptions: { paths: string[] }): void {\n for (const filePath of spoolOptions.paths) {\n try {\n rmSync(filePath, { force: true });\n } catch (error) {\n this.logger\n .for('UPLOAD')\n .error('Failed to remove spool file | path: %s | Error: %s', filePath, error);\n }\n }\n }\n\n override binding(): ValueOrPromise<void> {\n // First, so a literal path can win over the built-in catch-all `rawObjectPath` registers.\n defineRoutesBefore?.({ controller: this, helper, basePath: normalizedBasePath });\n\n // A single-bucket application has no reason to expose bucket creation or deletion, so the\n // four bucket-management routes are not registered once `bucket` is configured.\n if (!hasConfiguredBucket) {\n const getBucketsRoute = AssetRouteOptions.readOverride({ route: routes?.getBuckets });\n if (getBucketsRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.GET_BUCKETS, ...getBucketsRoute.override },\n }).to({\n handler: async (ctx) => {\n const buckets = await helper.getBuckets();\n return ctx.json(buckets, HTTP.ResultCodes.RS_2.Ok);\n },\n });\n }\n\n const getBucketByNameRoute = AssetRouteOptions.readOverride({\n route: routes?.getBucketByName,\n });\n if (getBucketByNameRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.GET_BUCKET_BY_NAME, ...getBucketByNameRoute.override },\n }).to({\n handler: async (ctx) => {\n const params = ctx.req.valid<TBucketParams>('param');\n const bucketName = await resolveBucket({\n configured: bucket,\n param: params.bucketName,\n });\n\n if (!helper.isValidBucketName({ bucket: { name: bucketName } })) {\n throw getError({ error: StaticAssetErrors.BUCKET_NAME_INVALID });\n }\n\n const found = await helper.getBucket({ bucket: { name: bucketName } });\n return ctx.json(found, HTTP.ResultCodes.RS_2.Ok);\n },\n });\n }\n\n const createBucketRoute = AssetRouteOptions.readOverride({ route: routes?.createBucket });\n if (createBucketRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.CREATE_BUCKET, ...createBucketRoute.override },\n }).to({\n handler: async (ctx) => {\n const params = ctx.req.valid<TBucketParams>('param');\n const bucketName = await resolveBucket({\n configured: bucket,\n param: params.bucketName,\n });\n\n if (!helper.isValidBucketName({ bucket: { name: bucketName } })) {\n throw getError({ error: StaticAssetErrors.BUCKET_NAME_INVALID });\n }\n\n const createdBucket = await helper.createBucket({ bucket: { name: bucketName } });\n return ctx.json(createdBucket, HTTP.ResultCodes.RS_2.Ok);\n },\n });\n }\n\n const deleteBucketRoute = AssetRouteOptions.readOverride({ route: routes?.deleteBucket });\n if (deleteBucketRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.DELETE_BUCKET, ...deleteBucketRoute.override },\n }).to({\n handler: async (ctx) => {\n const params = ctx.req.valid<TBucketParams>('param');\n const bucketName = await resolveBucket({\n configured: bucket,\n param: params.bucketName,\n });\n\n if (!helper.isValidBucketName({ bucket: { name: bucketName } })) {\n throw getError({ error: StaticAssetErrors.BUCKET_NAME_INVALID });\n }\n\n const isRemovedBucket = await helper.removeBucket({\n bucket: { name: bucketName },\n });\n return ctx.json({ isDeleted: isRemovedBucket }, HTTP.ResultCodes.RS_2.Ok);\n },\n });\n }\n }\n\n const getObjectByNameRoute = AssetRouteOptions.readOverride({\n route: routes?.getObjectByName,\n });\n if (getObjectByNameRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.GET_OBJECT_BY_NAME, ...getObjectByNameRoute.override },\n }).to({\n handler: async (ctx) => {\n const params = ctx.req.valid<TObjectParams>('param');\n const bucketName = await resolveBucket({\n configured: bucket,\n param: params.bucketName,\n });\n const objectName = readObjectName(params.objectName);\n\n if (!helper.isValidBucketName({ bucket: { name: bucketName } })) {\n throw getError({ error: StaticAssetErrors.BUCKET_NAME_INVALID });\n }\n\n if (\n !helper.isValidObjectKey({\n object: { key: objectName },\n maxDepth: objectKeyMaxDepth,\n })\n ) {\n throw getError({ error: StaticAssetErrors.OBJECT_NAME_INVALID });\n }\n\n // Before any storage call: a key outside the scope must not even be probed.\n AssetKeyScope.assertInScope({ key: objectName, keyPrefix });\n\n const fileStat = await helper.getStat({\n bucket: { name: bucketName },\n object: { key: objectName },\n });\n const { size, metadata } = fileStat;\n applyMetadataHeaders({ ctx, metadata });\n\n const served = AssetControllerFactory.resolveServedContentType({\n helper,\n object: { key: objectName },\n });\n ctx.header(HTTP.Headers.CONTENT_TYPE, served.contentType);\n ctx.header('x-content-type-options', 'nosniff');\n // Sandboxed even when renderable, so an unforeseen renderable type cannot reach this origin.\n ctx.header(HTTP.Headers.CONTENT_SECURITY_POLICY, 'sandbox');\n // Advertised unconditionally: a player only offers seeking once it sees this.\n ctx.header('accept-ranges', 'bytes');\n\n // A type outside the allow-list downloads instead of rendering; that is the XSS boundary.\n if (!served.isRenderable) {\n const inlineName = objectName.split('/').pop() ?? objectName;\n ctx.header(\n HTTP.Headers.CONTENT_DISPOSITION,\n RequestUtility.buildContentDispositionHeader({\n filename: inlineName,\n type: 'attachment',\n }),\n );\n }\n\n const range = readByteRange({ header: ctx.req.header('range'), size });\n\n if (range) {\n ctx.header(HTTP.Headers.CONTENT_LENGTH, String(range.end - range.start + 1));\n ctx.header(HTTP.Headers.CONTENT_RANGE, `bytes ${range.start}-${range.end}/${size}`);\n } else {\n ctx.header(HTTP.Headers.CONTENT_LENGTH, size.toString());\n }\n\n // The web stream is what a Response body wants, so no Node Readable sits in between.\n const stream = await helper.getObjectStream({\n bucket: { name: bucketName },\n object: { key: objectName },\n ...(range ? { range } : {}),\n });\n\n return new Response(stream, {\n headers: ctx.res.headers,\n status: range ? HTTP.ResultCodes.RS_2.PartialContent : HTTP.ResultCodes.RS_2.Ok,\n });\n },\n });\n }\n\n const downloadObjectByNameRoute = AssetRouteOptions.readOverride({\n route: routes?.downloadObjectByName,\n });\n if (downloadObjectByNameRoute.isEnabled) {\n this.bindRoute({\n configs: {\n ...definitions.DOWNLOAD_OBJECT_BY_NAME,\n ...downloadObjectByNameRoute.override,\n },\n }).to({\n handler: async (ctx) => {\n const params = ctx.req.valid<TObjectParams>('param');\n const bucketName = await resolveBucket({\n configured: bucket,\n param: params.bucketName,\n });\n const objectName = readObjectName(params.objectName);\n\n if (!helper.isValidBucketName({ bucket: { name: bucketName } })) {\n throw getError({ error: StaticAssetErrors.BUCKET_NAME_INVALID });\n }\n\n if (\n !helper.isValidObjectKey({\n object: { key: objectName },\n maxDepth: objectKeyMaxDepth,\n })\n ) {\n throw getError({ error: StaticAssetErrors.OBJECT_NAME_INVALID });\n }\n\n // Before any storage call: a key outside the scope must not even be probed.\n AssetKeyScope.assertInScope({ key: objectName, keyPrefix });\n\n const fileStat = await helper.getStat({\n bucket: { name: bucketName },\n object: { key: objectName },\n });\n const { size, metadata } = fileStat;\n applyMetadataHeaders({ ctx, metadata });\n\n // Download always attaches, so the served type only has to be honest, never renderable.\n const served = AssetControllerFactory.resolveServedContentType({\n helper,\n object: { key: objectName },\n });\n ctx.header(HTTP.Headers.CONTENT_TYPE, served.contentType);\n ctx.header(HTTP.Headers.CONTENT_LENGTH, size.toString());\n\n const fileName = objectName.split('/').pop() ?? objectName;\n ctx.header(\n HTTP.Headers.CONTENT_DISPOSITION,\n RequestUtility.buildContentDispositionHeader({\n filename: fileName,\n type: 'attachment',\n }),\n );\n ctx.header('x-content-type-options', 'nosniff');\n ctx.header(HTTP.Headers.CONTENT_SECURITY_POLICY, 'sandbox');\n\n const stream = await helper.getObjectStream({\n bucket: { name: bucketName },\n object: { key: objectName },\n });\n return new Response(stream, {\n headers: ctx.res.headers,\n status: HTTP.ResultCodes.RS_2.Ok,\n });\n },\n });\n }\n\n const uploadRoute = AssetRouteOptions.readOverride({ route: routes?.upload });\n if (uploadRoute.isEnabled) {\n const uploadMiddleware =\n maxBytes === undefined\n ? uploadRoute.override.middleware\n : AssetRouteOptions.appendLengthGuard({\n middleware: uploadRoute.override.middleware,\n maxBytes,\n });\n\n this.bindRoute({\n configs: {\n ...definitions.UPLOAD,\n ...uploadRoute.override,\n middleware: uploadMiddleware,\n },\n }).to({\n handler: async (ctx) => {\n // A configured bucket drops `params` from this route entirely, so it is read only when it exists.\n const bucketParam = hasConfiguredBucket\n ? undefined\n : ctx.req.valid<TBucketParams>('param').bucketName;\n const bucketName = await resolveBucket({ configured: bucket, param: bucketParam });\n\n if (!helper.isValidBucketName({ bucket: { name: bucketName } })) {\n throw getError({ error: StaticAssetErrors.BUCKET_NAME_INVALID });\n }\n\n const validateFolderPath = (folderPath: string) => {\n const normalizedFolder = folderPath.replace(/^\\/+|\\/+$/g, '');\n if (!normalizedFolder) {\n throw getError({ error: StaticAssetErrors.FOLDER_PATH_INVALID });\n }\n // maxFolderDepth excludes the filename, so it is compared directly against segment count.\n const folderSegments = normalizedFolder.split('/');\n if (folderSegments.length > maxFolderDepth) {\n throw getError({\n error: StaticAssetErrors.FOLDER_DEPTH_EXCEEDED,\n message: `Folder path exceeds max depth of ${maxFolderDepth}`,\n });\n }\n const invalidSegmentIndex = folderSegments.findIndex(\n (segment) => !helper.isValidSegment({ segment }),\n );\n if (invalidSegmentIndex !== -1) {\n throw getError({\n error: StaticAssetErrors.FOLDER_SEGMENT_INVALID,\n message: `Invalid folder path segment: ${folderSegments[invalidSegmentIndex]}`,\n });\n }\n };\n\n refuseLabelsInQuery({ query: ctx.req.query() });\n\n const { files: filesArray, fields } = await RequestUtility.parseMultipartBody({\n context: ctx,\n storage: options?.parseMultipartBody?.storage,\n uploadDir: options?.parseMultipartBody?.uploadDir,\n });\n\n // Labels travel with the payload, not the URL, so the folder check waits for the parse.\n const query = readUploadLabels({ fields });\n\n const folderPath = query.folderPath;\n if (folderPath) {\n validateFolderPath(folderPath);\n }\n\n const spoolPaths = filesArray\n .map((file) => file.path)\n .filter((filePath): filePath is string => Boolean(filePath));\n\n let uploaded: IUploadResult[];\n try {\n // `storage: 'disk'` spools the payload to `uploadDir` and returns `path` instead of `buffer`; the storage helpers only ever write `buffer`, so it must be read back.\n const modifiedFiles: IUploadFile[] = filesArray.map((file) => {\n const buffer = file.buffer ?? (file.path ? readFileSync(file.path) : undefined);\n\n if (!buffer?.length) {\n throw getError({\n error: StaticAssetErrors.FILE_EMPTY,\n message: `Empty file content | name: ${file.originalname}`,\n });\n }\n\n // Authoritative: `buffer.length`, not the client-declared `size`.\n if (maxBytes !== undefined && buffer.length > maxBytes) {\n throw getError({\n error: StaticAssetErrors.UPLOAD_TOO_LARGE,\n message: `File ${file.originalname} of ${buffer.length} bytes exceeds the maximum of ${maxBytes}`,\n });\n }\n\n return {\n originalName: file.originalname,\n mimetype: file.mimetype,\n buffer,\n size: file.size,\n encoding: file.encoding,\n folderPath: folderPath ?? undefined,\n };\n });\n\n // Built per request: the hook is offered the bucket, which only the route knows. With\n // neither hook nor scope, `normalizeNameFn` stays exactly as configured. Under a scope,\n // the component's own default is placed inside it; an application hook's key is\n // checked, never rewritten, because the application may record that key elsewhere.\n const normalizeNameFn =\n resolveObjectName || keyPrefix !== undefined\n ? (naming: { file: TUploadNaming }) => {\n if (\n isScopedDefaultNaming &&\n !helper.isValidSegment({ segment: naming.file.originalName })\n ) {\n throw getError({ message: '[upload] Invalid original file name' });\n }\n\n const defaultKey = options?.normalizeNameFn\n ? options.normalizeNameFn(naming)\n : `${keyPrefix ?? ''}${defaultObjectName(naming)}`;\n\n const key = resolveObjectName\n ? resolveObjectName({\n bucket: { name: bucketName },\n file: naming.file,\n defaultKey,\n })\n : defaultKey;\n\n if (!AssetKeyScope.isInScope({ key, keyPrefix })) {\n throw getError({\n error: StaticAssetErrors.OBJECT_KEY_OUT_OF_SCOPE,\n message: `Object key is outside the key prefix of this controller | key: ${key} | keyPrefix: ${keyPrefix}`,\n });\n }\n\n return key;\n }\n : options?.normalizeNameFn;\n\n const result = await helper.upload({\n bucket: { name: bucketName },\n files: modifiedFiles,\n normalizeNameFn,\n normalizeLinkFn,\n // Without this the helper re-validates against its own hard default of 2, so an app configured for a deeper tree spools the body and only then fails inside the helper.\n maxFolderDepth: objectKeyMaxDepth,\n });\n uploaded = result;\n } finally {\n this.removeSpoolFiles({ paths: spoolPaths });\n }\n\n if (!useMetaLink || !metaLink) {\n return ctx.json(uploaded, HTTP.ResultCodes.RS_2.Ok);\n }\n\n const results: IUploadResult[] = [];\n for (const uploadResult of uploaded) {\n try {\n const fileStat = await helper.getStat({\n bucket: uploadResult.bucket,\n object: uploadResult.object,\n });\n\n const createdMetaLink = await AssetMetaLink.createRow({\n metaLink,\n helper,\n storage,\n uploadResult,\n fileStat,\n query,\n });\n\n results.push({ ...uploadResult, metaLink: { data: createdMetaLink } });\n } catch (error) {\n this.logger\n .for('UPLOAD')\n .error(\n 'Failed to create MetaLink | objectName: %s | Error: %s',\n uploadResult.object.key,\n error,\n );\n results.push({\n ...uploadResult,\n // A CODE, never the driver text. This handler returns 200, so it bypasses the\n // error middleware and `database.handler` - the two places that strip\n // `detail`/`table`/`constraint` - and shipped raw constraint names to the client.\n // The real error is already logged in full immediately above.\n metaLink: { error: META_LINK_CREATE_FAILED },\n });\n }\n }\n return ctx.json(results, HTTP.ResultCodes.RS_2.Ok);\n },\n });\n }\n\n const deleteObjectRoute = AssetRouteOptions.readOverride({ route: routes?.deleteObject });\n if (deleteObjectRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.DELETE_OBJECT, ...deleteObjectRoute.override },\n }).to({\n handler: async (ctx) => {\n const params = ctx.req.valid<TObjectParams>('param');\n const bucketName = await resolveBucket({\n configured: bucket,\n param: params.bucketName,\n });\n const objectName = readObjectName(params.objectName);\n\n if (!helper.isValidBucketName({ bucket: { name: bucketName } })) {\n throw getError({ error: StaticAssetErrors.BUCKET_NAME_INVALID });\n }\n\n if (\n !helper.isValidObjectKey({\n object: { key: objectName },\n maxDepth: objectKeyMaxDepth,\n })\n ) {\n throw getError({ error: StaticAssetErrors.OBJECT_NAME_INVALID });\n }\n\n // Before any storage call: a key outside the scope must not even be probed.\n AssetKeyScope.assertInScope({ key: objectName, keyPrefix });\n\n // Deliberately idempotent: S3 answers 200 for a key that was never there, and consumers\n // already depend on it. `disk` throws instead, so the two are reconciled here, not below.\n try {\n await helper.removeObject({\n bucket: { name: bucketName },\n object: { key: objectName },\n });\n } catch (error) {\n if (!StorageUtility.isNotFoundError({ error })) {\n throw error;\n }\n }\n\n if (!useMetaLink || !metaLink) {\n return ctx.json({ success: true }, HTTP.ResultCodes.RS_2.Ok);\n }\n\n const deleteRepository = await ResolverUtility.resolveValueAsync({\n value: metaLink.repository,\n });\n deleteRepository\n .deleteAll({\n where: {\n bucketName,\n objectName,\n },\n })\n .then(() => {\n this.logger\n .for('DELETE_OBJECT')\n .info('Successfully to delete MetaLink for %s/%s', bucketName, objectName);\n })\n .catch((error) => {\n this.logger\n .for('DELETE_OBJECT')\n .error(\n 'Failed to delete MetaLink | bucket: %s | objectName: %s | Error: %s',\n bucketName,\n objectName,\n error,\n );\n });\n\n return ctx.json({ success: true }, HTTP.ResultCodes.RS_2.Ok);\n },\n });\n }\n\n const listObjectsRoute = AssetRouteOptions.readOverride({ route: routes?.listObjects });\n if (listObjectsRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.LIST_OBJECTS, ...listObjectsRoute.override },\n }).to({\n handler: async (ctx) => {\n // A configured bucket drops `params` from this route entirely, so it is read only when it exists.\n const bucketParam = hasConfiguredBucket\n ? undefined\n : ctx.req.valid<TBucketParams>('param').bucketName;\n const bucketName = await resolveBucket({ configured: bucket, param: bucketParam });\n const { prefix, recursive, maxKeys } = ctx.req.valid<TListQuery>('query');\n\n if (!helper.isValidBucketName({ bucket: { name: bucketName } })) {\n throw getError({ error: StaticAssetErrors.BUCKET_NAME_INVALID });\n }\n\n // A NaN or 0 maxKeys is silently treated as \"unlimited\" by the storage backends, so an unparsable value must be rejected instead of forwarded.\n let resolvedMaxKeys: number | undefined;\n if (maxKeys !== undefined) {\n resolvedMaxKeys = Number(maxKeys);\n\n if (!Number.isInteger(resolvedMaxKeys) || resolvedMaxKeys < 1) {\n throw getError({\n error: StaticAssetErrors.MAX_KEYS_INVALID,\n message: `Invalid maxKeys | Expected a positive integer | value: ${maxKeys}`,\n });\n }\n }\n\n const scoped = AssetKeyScope.resolveListPrefix({ prefix, keyPrefix });\n if (scoped.isOutOfScope) {\n return ctx.json([], HTTP.ResultCodes.RS_2.Ok);\n }\n\n const objects = await helper.listObjects({\n bucket: { name: bucketName },\n prefix: scoped.prefix,\n useRecursive: recursive === 'true',\n maxKeys: resolvedMaxKeys,\n });\n\n return ctx.json(objects, HTTP.ResultCodes.RS_2.Ok);\n },\n });\n }\n\n if (directUpload) {\n if (!hasConfiguredBucket) {\n throw getError({\n message: `[${name}] directUpload needs controller.bucket | a policy names one bucket, and a bucket in the URL is a bucket the caller chooses`,\n });\n }\n\n const pendingPrefix = directUpload.pendingPrefix ?? DEFAULT_PENDING_PREFIX;\n // The scope rides inside the pending key, so the commit, which strips `pendingPrefix`, lands inside it.\n const policyKeyPrefix = `${pendingPrefix}${keyPrefix ?? ''}`;\n\n const uploadPolicyRoute = AssetRouteOptions.readOverride({ route: routes?.uploadPolicy });\n if (uploadPolicyRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.UPLOAD_POLICY, ...uploadPolicyRoute.override },\n }).to({\n handler: async (ctx) => {\n const result = await directUpload.authorize({ context: ctx });\n if (!result) {\n throw getError({ error: StaticAssetErrors.UPLOAD_NOT_AUTHORIZED });\n }\n\n const { files } = ctx.req.valid<TUploadPolicyRequest>('json');\n const bucketName = await resolveBucket({ configured: bucket });\n\n const policies: Array<IPostPolicy & { objectName: string; commitToken: string }> =\n [];\n for (const file of files) {\n if (file.size !== undefined && file.size > directUpload.maxBytes) {\n throw getError({\n error: StaticAssetErrors.UPLOAD_TOO_LARGE,\n message: `File '${file.fileName}' is ${file.size} bytes, over the ${directUpload.maxBytes} the policy allows`,\n });\n }\n\n // Generated, never taken from the caller: a key the caller picks is a key the caller\n // can collide with, and the pending object is the one thing a policy authorizes.\n const objectName = `${policyKeyPrefix}${UuidHelper.getInstance().v4()}/${file.fileName}`;\n const policy = await helper.presignPost({\n bucket: { name: bucketName },\n keyPrefix: policyKeyPrefix,\n maxBytes: directUpload.maxBytes,\n contentType: file.contentType,\n expiresIn: directUpload.expiresIn,\n });\n\n policies.push({\n ...policy,\n objectName,\n commitToken: AssetCommitToken.build({\n payload: {\n bucket: bucketName,\n key: objectName,\n expiresAt: new Date(policy.expiresAt).getTime(),\n },\n secretKey: directUpload.secretKey,\n }),\n });\n }\n\n return ctx.json(policies, HTTP.ResultCodes.RS_2.Ok);\n },\n });\n }\n\n const uploadCommitRoute = AssetRouteOptions.readOverride({ route: routes?.uploadCommit });\n if (uploadCommitRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.UPLOAD_COMMIT, ...uploadCommitRoute.override },\n }).to({\n handler: async (ctx) => {\n const commitQuery = ctx.req.query();\n refuseLabelsInQuery({ query: commitQuery, names: COMMIT_LABEL_NAMES });\n refuseLabelsInQuery({\n query: commitQuery,\n names: ['folderPath'],\n reason:\n 'folderPath was decided when the upload policy was issued; the commit route cannot move the object',\n });\n\n const { commitToken, ...labels } = ctx.req.valid<\n { commitToken: string } & TUploadQuery\n >('json');\n\n // Verified BEFORE any storage call. That is what keeps this route from being a name\n // prober: a forged token fails without a round trip, so timing says nothing.\n const payload = AssetCommitToken.read({\n token: commitToken,\n secretKey: directUpload.secretKey,\n });\n\n // Labels, not authorization - the token deliberately carries no business fields, so\n // they travel beside it rather than inside it.\n const query = readUploadLabels({ fields: labels });\n\n const bucketRef = { name: payload.bucket };\n const pendingObject = { key: payload.key };\n const object = { key: payload.key.slice(pendingPrefix.length) };\n\n // A token another controller signed with the same secret must not land outside this scope.\n AssetKeyScope.assertInScope({ key: object.key, keyPrefix });\n\n // Before the copy, so a hook that throws leaves the object under the pending prefix\n // for a lifecycle rule, rather than stranding it at the final key.\n await directUpload.onCommit?.({ bucket: bucketRef, pendingObject, object });\n\n await helper.copyObject({\n bucket: bucketRef,\n source: pendingObject,\n destination: object,\n });\n // The copy IS the commit; removing the temporary object is cleanup. A failure here\n // leaves one object for the lifecycle rule, and failing the request would tell the\n // caller their upload did not work when it did.\n try {\n await helper.removeObject({ bucket: bucketRef, object: pendingObject });\n } catch (error) {\n this.logger\n .for('UPLOAD_COMMIT')\n .warn(\n 'Committed, but the pending object remains | key: %s | error: %s',\n pendingObject.key,\n error,\n );\n }\n\n const link = AssetControllerFactory.buildObjectLink({\n basePath: normalizedBasePath,\n bucket: bucketRef,\n object,\n hasConfiguredBucket,\n rawObjectPath,\n });\n\n // The two paths have to agree: without this a client reading `metaLink` off the\n // response renders an empty state with no error - the failure nobody reports.\n let metaLinkResult: IUploadResult['metaLink'];\n if (useMetaLink && metaLink) {\n try {\n const fileStat = await helper.getStat({ bucket: bucketRef, object });\n const data = await AssetMetaLink.createRow({\n metaLink,\n helper,\n storage,\n uploadResult: AssetMetaLink.buildStoredUploadResult({\n helper,\n bucket: bucketRef,\n object,\n link,\n fileStat,\n }),\n fileStat,\n query,\n });\n\n metaLinkResult = { data };\n } catch (error) {\n // The object IS committed by now. A 500 would send the caller back with a token\n // whose source no longer exists, so this rides the body as a code, like UPLOAD.\n this.logger\n .for('UPLOAD_COMMIT')\n .error(\n 'Failed to create MetaLink | objectName: %s | Error: %s',\n object.key,\n error,\n );\n metaLinkResult = { error: META_LINK_CREATE_FAILED };\n }\n }\n\n return ctx.json(\n {\n bucket: bucketRef,\n object,\n link,\n ...(metaLinkResult === undefined ? {} : { metaLink: metaLinkResult }),\n },\n HTTP.ResultCodes.RS_2.Ok,\n );\n },\n });\n }\n }\n\n if (useMetaLink && metaLink) {\n const recreateMetaLinkRoute = AssetRouteOptions.readOverride({\n route: routes?.recreateMetaLink,\n });\n if (recreateMetaLinkRoute.isEnabled) {\n this.bindRoute({\n configs: { ...definitions.RECREATE_METALINK, ...recreateMetaLinkRoute.override },\n }).to({\n handler: async (ctx) => {\n // This route takes no labels anywhere: one in the query would land an unlabelled row.\n refuseLabelsInQuery({\n query: ctx.req.query(),\n reason:\n 'This route recreates a MetaLink for an existing object and takes no labels',\n });\n\n const params = ctx.req.valid<TObjectParams>('param');\n const bucketName = await resolveBucket({\n configured: bucket,\n param: params.bucketName,\n });\n const objectName = readObjectName(params.objectName);\n\n if (!helper.isValidBucketName({ bucket: { name: bucketName } })) {\n throw getError({ error: StaticAssetErrors.BUCKET_NAME_INVALID });\n }\n\n if (\n !helper.isValidObjectKey({\n object: { key: objectName },\n maxDepth: objectKeyMaxDepth,\n })\n ) {\n throw getError({ error: StaticAssetErrors.OBJECT_NAME_INVALID });\n }\n\n // Before any storage call: a key outside the scope must not even be probed.\n AssetKeyScope.assertInScope({ key: objectName, keyPrefix });\n\n const bucketRef = { name: bucketName };\n const object = { key: objectName };\n const fileStat = await helper.getStat({ bucket: bucketRef, object });\n\n const link = options?.normalizeLinkFn\n ? options.normalizeLinkFn({ bucket: bucketRef, object })\n : AssetControllerFactory.buildObjectLink({\n basePath: normalizedBasePath,\n bucket: bucketRef,\n object,\n hasConfiguredBucket,\n rawObjectPath,\n });\n\n const refreshed = await AssetMetaLink.refreshRows({\n metaLink,\n helper,\n bucket: bucketRef,\n object,\n link,\n fileStat,\n });\n\n if (refreshed.count > 0) {\n return ctx.json(\n {\n success: true,\n action: MetaLinkRecreateActions.REFRESHED,\n count: refreshed.count,\n metaLink: refreshed.data[0],\n metaLinks: refreshed.data,\n },\n HTTP.ResultCodes.RS_2.Ok,\n );\n }\n\n // Not atomic with the refresh above: two concurrent calls may both create, which the\n // table allows - rows per pair are deliberately not unique.\n const created = await AssetMetaLink.createRow({\n metaLink,\n helper,\n storage,\n uploadResult: AssetMetaLink.buildStoredUploadResult({\n helper,\n bucket: bucketRef,\n object,\n link,\n fileStat,\n }),\n fileStat,\n query: {},\n });\n\n return ctx.json(\n {\n success: true,\n action: MetaLinkRecreateActions.CREATED,\n count: 1,\n metaLink: created,\n metaLinks: [created],\n },\n HTTP.ResultCodes.RS_2.Ok,\n );\n },\n });\n }\n }\n\n // Last, so a built-in route always wins a path collision with an application's own.\n defineExtraRoutes?.({ controller: this, helper, basePath: normalizedBasePath });\n }\n }\n\n Object.defineProperty(GeneratedStaticAssetController, 'name', {\n value: name,\n configurable: true,\n });\n return GeneratedStaticAssetController;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"network.utility.d.ts","sourceRoot":"","sources":["../../../src/utilities/network.utility.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAGpC,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAqD;IACnF,8FAA8F;IAC9F,OAAO,CAAC,MAAM,CAAC,sBAAsB,CAAS;IAE9C,qEAAqE;IACrE,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI;CAiBtD"}
1
+ {"version":3,"file":"network.utility.d.ts","sourceRoot":"","sources":["../../../src/utilities/network.utility.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAGpC,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAA8C;IAC5E,8FAA8F;IAC9F,OAAO,CAAC,MAAM,CAAC,sBAAsB,CAAS;IAE9C,qEAAqE;IACrE,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI;CAiBtD"}
@@ -1,7 +1,7 @@
1
- import { ApplicationLogger, ErrorPrettier } from '@venizia/ignis-helpers';
1
+ import { ErrorPrettier, LoggerFactory } from '@venizia/ignis-helpers';
2
2
  import { getConnInfo } from 'hono/bun';
3
3
  export class NetworkUtility {
4
- static { this.logger = ApplicationLogger.get({ scope: 'getIncomingIp' }); }
4
+ static { this.logger = LoggerFactory.getLogger(['getIncomingIp']); }
5
5
  /** Latches the warning: an absent conninfo peer fails identically for every later request. */
6
6
  static { this.hasReportedUnavailable = false; }
7
7
  /** Reads the incoming IP from Bun's connection info (`hono/bun`). */
@@ -1 +1 @@
1
- {"version":3,"file":"network.utility.js","sourceRoot":"","sources":["../../../src/utilities/network.utility.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE1E,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,MAAM,OAAO,cAAc;aACD,WAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;IACnF,8FAA8F;aAC/E,2BAAsB,GAAG,KAAK,CAAC;IAE9C,qEAAqE;IACrE,MAAM,CAAC,aAAa,CAAC,OAAgB;QACnC,IAAI,CAAC;YACH,OAAO,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,IAAI,IAAI,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,cAAc,CAAC,sBAAsB,EAAE,CAAC;gBAC1C,OAAO,IAAI,CAAC;YACd,CAAC;YAED,cAAc,CAAC,sBAAsB,GAAG,IAAI,CAAC;YAC7C,cAAc,CAAC,MAAM,CAAC,IAAI,CACxB,qFAAqF,EACrF,aAAa,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAChC,CAAC;YAEF,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC","sourcesContent":["import { ApplicationLogger, ErrorPrettier } from '@venizia/ignis-helpers';\nimport type { Context } from 'hono';\nimport { getConnInfo } from 'hono/bun';\n\nexport class NetworkUtility {\n private static readonly logger = ApplicationLogger.get({ scope: 'getIncomingIp' });\n /** Latches the warning: an absent conninfo peer fails identically for every later request. */\n private static hasReportedUnavailable = false;\n\n /** Reads the incoming IP from Bun's connection info (`hono/bun`). */\n static getIncomingIp(context: Context): string | null {\n try {\n return getConnInfo(context)?.remote?.address ?? null;\n } catch (error) {\n if (NetworkUtility.hasReportedUnavailable) {\n return null;\n }\n\n NetworkUtility.hasReportedUnavailable = true;\n NetworkUtility.logger.warn(\n '[getIncomingIp] Connection info unavailable - reporting null for every request | %s',\n ErrorPrettier.format({ error }),\n );\n\n return null;\n }\n }\n}\n"]}
1
+ {"version":3,"file":"network.utility.js","sourceRoot":"","sources":["../../../src/utilities/network.utility.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEtE,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,MAAM,OAAO,cAAc;aACD,WAAM,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;IAC5E,8FAA8F;aAC/E,2BAAsB,GAAG,KAAK,CAAC;IAE9C,qEAAqE;IACrE,MAAM,CAAC,aAAa,CAAC,OAAgB;QACnC,IAAI,CAAC;YACH,OAAO,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,IAAI,IAAI,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,cAAc,CAAC,sBAAsB,EAAE,CAAC;gBAC1C,OAAO,IAAI,CAAC;YACd,CAAC;YAED,cAAc,CAAC,sBAAsB,GAAG,IAAI,CAAC;YAC7C,cAAc,CAAC,MAAM,CAAC,IAAI,CACxB,qFAAqF,EACrF,aAAa,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAChC,CAAC;YAEF,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC","sourcesContent":["import { ErrorPrettier, LoggerFactory } from '@venizia/ignis-helpers';\nimport type { Context } from 'hono';\nimport { getConnInfo } from 'hono/bun';\n\nexport class NetworkUtility {\n private static readonly logger = LoggerFactory.getLogger(['getIncomingIp']);\n /** Latches the warning: an absent conninfo peer fails identically for every later request. */\n private static hasReportedUnavailable = false;\n\n /** Reads the incoming IP from Bun's connection info (`hono/bun`). */\n static getIncomingIp(context: Context): string | null {\n try {\n return getConnInfo(context)?.remote?.address ?? null;\n } catch (error) {\n if (NetworkUtility.hasReportedUnavailable) {\n return null;\n }\n\n NetworkUtility.hasReportedUnavailable = true;\n NetworkUtility.logger.warn(\n '[getIncomingIp] Connection info unavailable - reporting null for every request | %s',\n ErrorPrettier.format({ error }),\n );\n\n return null;\n }\n }\n}\n"]}
@@ -14,9 +14,9 @@
14
14
  "dependencies": {
15
15
  "@hono/zod-openapi": "^1.6.3",
16
16
  "@scalar/hono-api-reference": "^0.12.13",
17
- "@venizia/ignis": "0.4.7-1",
18
- "@venizia/ignis-boot": "0.4.7-1",
19
- "@venizia/ignis-helpers": "0.4.7-1",
17
+ "@venizia/ignis": "0.4.7-2",
18
+ "@venizia/ignis-boot": "0.4.7-2",
19
+ "@venizia/ignis-helpers": "0.4.7-2",
20
20
  "hono": "^4.13.13",
21
21
  "winston": "^3.19.0",
22
22
  "winston-daily-rotate-file": "^5.0.0",
@@ -24,7 +24,7 @@
24
24
  },
25
25
  "devDependencies": {
26
26
  "@types/bun": "^1.4.3",
27
- "@venizia/dev-configs": "0.4.7-1",
27
+ "@venizia/dev-configs": "0.4.7-2",
28
28
  "eslint": "^10.13.0",
29
29
  "oxlint": "1.89.0",
30
30
  "oxlint-tsgolint": "7.0.2004",
@@ -4,15 +4,15 @@
4
4
  "dependencies": {},
5
5
  "devDependencies": {
6
6
  "@types/bun": "^1.4.3",
7
- "@venizia/dev-configs": "0.4.7-1",
8
- "@venizia/ignis": "0.4.7-1",
7
+ "@venizia/dev-configs": "0.4.7-2",
8
+ "@venizia/ignis": "0.4.7-2",
9
9
  "eslint": "^10.13.0",
10
10
  "oxlint": "1.89.0",
11
11
  "oxlint-tsgolint": "7.0.2004",
12
12
  "typescript": "^6.0.3"
13
13
  },
14
14
  "peerDependencies": {
15
- "@venizia/ignis": "0.4.7-1"
15
+ "@venizia/ignis": "0.4.7-2"
16
16
  },
17
17
  "scripts": {
18
18
  "typecheck": "bun check",
@@ -4,7 +4,7 @@
4
4
  "dependencies": {},
5
5
  "devDependencies": {
6
6
  "@types/bun": "^1.4.3",
7
- "@venizia/dev-configs": "0.4.7-1",
7
+ "@venizia/dev-configs": "0.4.7-2",
8
8
  "eslint": "^10.13.0",
9
9
  "oxlint": "1.89.0",
10
10
  "oxlint-tsgolint": "7.0.2004",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@venizia/ignis",
3
- "version": "0.4.7-1",
3
+ "version": "0.4.7-2",
4
4
  "description": "TypeScript server framework with decorator-based DI, the repository pattern and a component system, on Hono. Features auto-generated OpenAPI docs, Drizzle ORM type-safe SQL, JWT/Basic authentication, Casbin authorization, convention-based bootstrapping, and pluggable components for health checks, Swagger UI, mail, Socket.IO, and static assets. Built for Bun and Node.js.",
5
5
  "keywords": [
6
6
  "access-control",
@@ -186,11 +186,11 @@
186
186
  "force-update": "sh ../../scripts/build/force-update.sh"
187
187
  },
188
188
  "dependencies": {
189
- "@venizia/ignis-connectors": "0.4.7-1",
189
+ "@venizia/ignis-connectors": "0.4.7-2",
190
190
  "@venizia/ignis-filter": "0.4.6-1",
191
- "@venizia/ignis-helpers": "0.4.7-1",
191
+ "@venizia/ignis-helpers": "0.4.7-2",
192
192
  "@venizia/ignis-inversion": "0.4.6-1",
193
- "@venizia/ignis-kernel": "0.4.7-1",
193
+ "@venizia/ignis-kernel": "0.4.7-2",
194
194
  "reflect-metadata": "^0.2.2"
195
195
  },
196
196
  "devDependencies": {
@@ -203,8 +203,8 @@
203
203
  "@types/bun": "^1.4.3",
204
204
  "@types/nodemailer": "^8.0.2",
205
205
  "@types/pg": "^8.23.1",
206
- "@venizia/dev-configs": "0.4.7-1",
207
- "@venizia/ignis-boot": "0.4.7-1",
206
+ "@venizia/dev-configs": "0.4.7-2",
207
+ "@venizia/ignis-boot": "0.4.7-2",
208
208
  "casbin": "^5.51.1",
209
209
  "eslint": "^10.13.0",
210
210
  "meilisearch": "^0.62.0",