@venizia/ignis-kernel 0.4.7-1 → 0.4.7-3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/base/controllers/factory/crud/persistable.d.ts.map +1 -1
- package/dist/esm/base/controllers/factory/crud/persistable.js +9 -1
- package/dist/esm/base/controllers/factory/crud/persistable.js.map +1 -1
- package/dist/esm/base/middlewares/app-error/app-error.middleware.d.ts.map +1 -1
- package/dist/esm/base/middlewares/app-error/app-error.middleware.js +1 -0
- package/dist/esm/base/middlewares/app-error/app-error.middleware.js.map +1 -1
- package/dist/esm/base/repositories/common/response-reader.d.ts.map +1 -1
- package/dist/esm/base/repositories/common/response-reader.js +10 -1
- package/dist/esm/base/repositories/common/response-reader.js.map +1 -1
- package/dist/esm/helpers/inversion/container.d.ts +1 -1
- package/dist/esm/helpers/inversion/container.d.ts.map +1 -1
- package/dist/esm/helpers/inversion/container.js +1 -1
- package/dist/esm/helpers/inversion/container.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistable.d.ts","sourceRoot":"","sources":["../../../../../../src/base/controllers/factory/crud/persistable.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAGlF,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC3F,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAGpD,mGAAmG;AACnG,8BAAsB,yBAAyB,CAC7C,OAAO,SAAS,cAAc,CAAC,gBAAgB,CAAC,GAAG,cAAc,CAAC,gBAAgB,CAAC,EACnF,QAAQ,SAAS,GAAG,GAAG,GAAG,EAC1B,WAAW,SAAS,MAAM,GAAG,EAAE,EAC/B,QAAQ,SAAS,MAAM,GAAG,GAAG,EAC7B,mBAAmB,SAAS,MAAM,GAAG,EAAE,EACvC,WAAW,SAAS,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,EACvD,cAAc,SAAS,MAAM,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAC7D,SAAQ,sBAAsB,CAC9B,OAAO,EACP,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,mBAAmB,EACnB,WAAW,EACX,cAAc,CACf;IACC,aAAa;IACP,MAAM,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAA;KAAE;IAoBvD;;;OAGG;IACH,oBAAoB,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAYjE,iBAAiB;IACX,UAAU,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAA;KAAE;IAsB3D,cAAc;IACR,QAAQ,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAA;KAAE;IAoCzD,kBAAkB;IACZ,UAAU,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAA;KAAE;IAoB3D,eAAe;IACT,QAAQ,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAA;KAAE;
|
|
1
|
+
{"version":3,"file":"persistable.d.ts","sourceRoot":"","sources":["../../../../../../src/base/controllers/factory/crud/persistable.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAGlF,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC3F,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAGpD,mGAAmG;AACnG,8BAAsB,yBAAyB,CAC7C,OAAO,SAAS,cAAc,CAAC,gBAAgB,CAAC,GAAG,cAAc,CAAC,gBAAgB,CAAC,EACnF,QAAQ,SAAS,GAAG,GAAG,GAAG,EAC1B,WAAW,SAAS,MAAM,GAAG,EAAE,EAC/B,QAAQ,SAAS,MAAM,GAAG,GAAG,EAC7B,mBAAmB,SAAS,MAAM,GAAG,EAAE,EACvC,WAAW,SAAS,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,EACvD,cAAc,SAAS,MAAM,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAC7D,SAAQ,sBAAsB,CAC9B,OAAO,EACP,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,mBAAmB,EACnB,WAAW,EACX,cAAc,CACf;IACC,aAAa;IACP,MAAM,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAA;KAAE;IAoBvD;;;OAGG;IACH,oBAAoB,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAYjE,iBAAiB;IACX,UAAU,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAA;KAAE;IAsB3D,cAAc;IACR,QAAQ,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAA;KAAE;IAoCzD,kBAAkB;IACZ,UAAU,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAA;KAAE;IAoB3D,eAAe;IACT,QAAQ,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAA;KAAE;CAuC1D"}
|
|
@@ -113,7 +113,15 @@ export class PersistableCrudController extends ReadableCrudController {
|
|
|
113
113
|
const { where: queryWhere } = context.req.valid('query');
|
|
114
114
|
// Read, never validated: a declared body schema would gate the media type and answer 400 to a
|
|
115
115
|
// client that sends a content-type and no body. A body that is not JSON is simply not a `where`.
|
|
116
|
-
|
|
116
|
+
let body;
|
|
117
|
+
try {
|
|
118
|
+
const result = await context.req.json();
|
|
119
|
+
body = result;
|
|
120
|
+
// eslint-disable-next-line venizia/no-silent-catch -- a body that is not JSON is not a `where`; the bulk delete then relies on the query alone and nothing else is lost
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
body = undefined;
|
|
124
|
+
}
|
|
117
125
|
const resolved = this.resolveBulkWhere({
|
|
118
126
|
context,
|
|
119
127
|
where: { fromQuery: queryWhere, fromBody: body?.where },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistable.js","sourceRoot":"","sources":["../../../../../../src/base/controllers/factory/crud/persistable.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IdType } from '@/base/models';\nimport type { AbstractEntity } from '@/base/models/base';\nimport { RequestErrors } from '@/base/middlewares/common/errors';\nimport type { TWhere } from '@venizia/ignis-filter';\nimport type { TAnyObjectSchema } from '@/base/controllers/common/schema-builders';\nimport { HTTP } from '@venizia/ignis-helpers/common';\nimport { getError } from '@venizia/ignis-helpers/core';\nimport type { Env, Schema } from 'hono';\nimport type { TEntityDataObject, TEntityPersistObject, TRouteContext } from '../../common';\nimport { ReadableCrudController } from './readable';\nimport { ResponseFormats } from '../../common';\n\n/** Write tier: create / updateById / updateBy / deleteById / deleteBy. Inherits the read verbs. */\nexport abstract class PersistableCrudController<\n TEntity extends AbstractEntity<TAnyObjectSchema> = AbstractEntity<TAnyObjectSchema>,\n RouteEnv extends Env = Env,\n RouteSchema extends Schema = {},\n BasePath extends string = '/',\n ConfigurableOptions extends object = {},\n TDataObject extends object = TEntityDataObject<TEntity>,\n TPersistObject extends object = TEntityPersistObject<TEntity>,\n> extends ReadableCrudController<\n TEntity,\n RouteEnv,\n RouteSchema,\n BasePath,\n ConfigurableOptions,\n TDataObject,\n TPersistObject\n> {\n /** POST / */\n async create(opts: { context: TRouteContext<RouteEnv> }) {\n const { context } = opts;\n const data = context.req.valid<TPersistObject>('json');\n\n const rs = await this.measure({\n scope: 'create',\n args: data,\n task: async () => {\n const payload = await this.repository.create({ data });\n return this.respond<TDataObject>({\n context,\n format: ResponseFormats.OBJECT,\n payload,\n });\n },\n });\n\n return context.json(rs, HTTP.ResultCodes.RS_2.Created);\n }\n\n /**\n * 400 when the validated body leaves no field to write - `{}`, or only keys the body schema drops.\n * The repository would otherwise fail with a 500.\n */\n assertNonEmptyUpdate(opts: { scope: string; data: object }): void {\n const { scope, data } = opts;\n\n if (Object.keys(data).length === 0) {\n throw getError({\n error: RequestErrors.NOTHING_TO_UPDATE,\n message: `[${scope}] Nothing to update | The body has no field this route writes`,\n logLevel: 'warn',\n });\n }\n }\n\n /** PATCH /:id */\n async updateById(opts: { context: TRouteContext<RouteEnv> }) {\n const { context } = opts;\n const { id } = context.req.valid<{ id: IdType }>('param');\n const data = context.req.valid<Partial<TPersistObject>>('json');\n this.assertNonEmptyUpdate({ scope: 'updateById', data });\n\n const rs = await this.measure({\n scope: 'updateById',\n args: { id, data },\n task: async () => {\n const payload = await this.repository.updateById({ id, data });\n return this.respond<TDataObject>({\n context,\n format: ResponseFormats.OBJECT,\n payload,\n });\n },\n });\n\n return context.json(rs, HTTP.ResultCodes.RS_2.Ok);\n }\n\n /** PATCH / */\n async updateBy(opts: { context: TRouteContext<RouteEnv> }) {\n const { context } = opts;\n const { where: queryWhere } = context.req.valid<{ where?: TWhere<TDataObject> }>('query');\n const { where: bodyWhere } = context.req.valid<{ where?: TWhere<TDataObject> }>('json');\n // A COPY: `where` selects rows and is never written, and hono hands the same validated object to\n // an override that calls this through `super`.\n const data: Partial<TPersistObject> = { ...context.req.valid<Partial<TPersistObject>>('json') };\n Reflect.deleteProperty(data, 'where');\n this.assertNonEmptyUpdate({ scope: 'updateBy', data });\n\n const resolved = this.resolveBulkWhere({\n context,\n where: { fromQuery: queryWhere, fromBody: bodyWhere },\n });\n if (resolved.error !== undefined) {\n return resolved.error;\n }\n\n const { where } = resolved;\n\n const rs = await this.measure({\n scope: 'updateBy',\n args: { where, data },\n task: async () => {\n const payload = await this.repository.updateBy({ where, data });\n return this.respond<Array<TDataObject>>({\n context,\n format: ResponseFormats.ARRAY,\n payload,\n });\n },\n });\n\n return context.json(rs, HTTP.ResultCodes.RS_2.Ok);\n }\n\n /** DELETE /:id */\n async deleteById(opts: { context: TRouteContext<RouteEnv> }) {\n const { context } = opts;\n const { id } = context.req.valid<{ id: IdType }>('param');\n\n const rs = await this.measure({\n scope: 'deleteById',\n args: { id },\n task: async () => {\n const payload = await this.repository.deleteById({ id });\n return this.respond<TDataObject>({\n context,\n format: ResponseFormats.OBJECT,\n payload,\n });\n },\n });\n\n return context.json(rs, HTTP.ResultCodes.RS_2.Ok);\n }\n\n /** DELETE / */\n async deleteBy(opts: { context: TRouteContext<RouteEnv> }) {\n const { context } = opts;\n const { where: queryWhere } = context.req.valid<{ where?: TWhere<TDataObject> }>('query');\n // Read, never validated: a declared body schema would gate the media type and answer 400 to a\n // client that sends a content-type and no body. A body that is not JSON is simply not a `where`.\n const body = await context.req.json<{ where?: TWhere<TDataObject> }>().catch(() => undefined);\n\n const resolved = this.resolveBulkWhere({\n context,\n where: { fromQuery: queryWhere, fromBody: body?.where },\n });\n if (resolved.error !== undefined) {\n return resolved.error;\n }\n\n const { where } = resolved;\n\n const rs = await this.measure({\n scope: 'deleteBy',\n args: { where },\n task: async () => {\n const payload = await this.repository.deleteBy({ where });\n return this.respond<Array<TDataObject>>({\n context,\n format: ResponseFormats.ARRAY,\n payload,\n });\n },\n });\n\n return context.json(rs, HTTP.ResultCodes.RS_2.Ok);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"persistable.js","sourceRoot":"","sources":["../../../../../../src/base/controllers/factory/crud/persistable.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IdType } from '@/base/models';\nimport type { AbstractEntity } from '@/base/models/base';\nimport { RequestErrors } from '@/base/middlewares/common/errors';\nimport type { TWhere } from '@venizia/ignis-filter';\nimport type { TAnyObjectSchema } from '@/base/controllers/common/schema-builders';\nimport { HTTP } from '@venizia/ignis-helpers/common';\nimport { getError } from '@venizia/ignis-helpers/core';\nimport type { Env, Schema } from 'hono';\nimport type { TEntityDataObject, TEntityPersistObject, TRouteContext } from '../../common';\nimport { ReadableCrudController } from './readable';\nimport { ResponseFormats } from '../../common';\n\n/** Write tier: create / updateById / updateBy / deleteById / deleteBy. Inherits the read verbs. */\nexport abstract class PersistableCrudController<\n TEntity extends AbstractEntity<TAnyObjectSchema> = AbstractEntity<TAnyObjectSchema>,\n RouteEnv extends Env = Env,\n RouteSchema extends Schema = {},\n BasePath extends string = '/',\n ConfigurableOptions extends object = {},\n TDataObject extends object = TEntityDataObject<TEntity>,\n TPersistObject extends object = TEntityPersistObject<TEntity>,\n> extends ReadableCrudController<\n TEntity,\n RouteEnv,\n RouteSchema,\n BasePath,\n ConfigurableOptions,\n TDataObject,\n TPersistObject\n> {\n /** POST / */\n async create(opts: { context: TRouteContext<RouteEnv> }) {\n const { context } = opts;\n const data = context.req.valid<TPersistObject>('json');\n\n const rs = await this.measure({\n scope: 'create',\n args: data,\n task: async () => {\n const payload = await this.repository.create({ data });\n return this.respond<TDataObject>({\n context,\n format: ResponseFormats.OBJECT,\n payload,\n });\n },\n });\n\n return context.json(rs, HTTP.ResultCodes.RS_2.Created);\n }\n\n /**\n * 400 when the validated body leaves no field to write - `{}`, or only keys the body schema drops.\n * The repository would otherwise fail with a 500.\n */\n assertNonEmptyUpdate(opts: { scope: string; data: object }): void {\n const { scope, data } = opts;\n\n if (Object.keys(data).length === 0) {\n throw getError({\n error: RequestErrors.NOTHING_TO_UPDATE,\n message: `[${scope}] Nothing to update | The body has no field this route writes`,\n logLevel: 'warn',\n });\n }\n }\n\n /** PATCH /:id */\n async updateById(opts: { context: TRouteContext<RouteEnv> }) {\n const { context } = opts;\n const { id } = context.req.valid<{ id: IdType }>('param');\n const data = context.req.valid<Partial<TPersistObject>>('json');\n this.assertNonEmptyUpdate({ scope: 'updateById', data });\n\n const rs = await this.measure({\n scope: 'updateById',\n args: { id, data },\n task: async () => {\n const payload = await this.repository.updateById({ id, data });\n return this.respond<TDataObject>({\n context,\n format: ResponseFormats.OBJECT,\n payload,\n });\n },\n });\n\n return context.json(rs, HTTP.ResultCodes.RS_2.Ok);\n }\n\n /** PATCH / */\n async updateBy(opts: { context: TRouteContext<RouteEnv> }) {\n const { context } = opts;\n const { where: queryWhere } = context.req.valid<{ where?: TWhere<TDataObject> }>('query');\n const { where: bodyWhere } = context.req.valid<{ where?: TWhere<TDataObject> }>('json');\n // A COPY: `where` selects rows and is never written, and hono hands the same validated object to\n // an override that calls this through `super`.\n const data: Partial<TPersistObject> = { ...context.req.valid<Partial<TPersistObject>>('json') };\n Reflect.deleteProperty(data, 'where');\n this.assertNonEmptyUpdate({ scope: 'updateBy', data });\n\n const resolved = this.resolveBulkWhere({\n context,\n where: { fromQuery: queryWhere, fromBody: bodyWhere },\n });\n if (resolved.error !== undefined) {\n return resolved.error;\n }\n\n const { where } = resolved;\n\n const rs = await this.measure({\n scope: 'updateBy',\n args: { where, data },\n task: async () => {\n const payload = await this.repository.updateBy({ where, data });\n return this.respond<Array<TDataObject>>({\n context,\n format: ResponseFormats.ARRAY,\n payload,\n });\n },\n });\n\n return context.json(rs, HTTP.ResultCodes.RS_2.Ok);\n }\n\n /** DELETE /:id */\n async deleteById(opts: { context: TRouteContext<RouteEnv> }) {\n const { context } = opts;\n const { id } = context.req.valid<{ id: IdType }>('param');\n\n const rs = await this.measure({\n scope: 'deleteById',\n args: { id },\n task: async () => {\n const payload = await this.repository.deleteById({ id });\n return this.respond<TDataObject>({\n context,\n format: ResponseFormats.OBJECT,\n payload,\n });\n },\n });\n\n return context.json(rs, HTTP.ResultCodes.RS_2.Ok);\n }\n\n /** DELETE / */\n async deleteBy(opts: { context: TRouteContext<RouteEnv> }) {\n const { context } = opts;\n const { where: queryWhere } = context.req.valid<{ where?: TWhere<TDataObject> }>('query');\n // Read, never validated: a declared body schema would gate the media type and answer 400 to a\n // client that sends a content-type and no body. A body that is not JSON is simply not a `where`.\n let body;\n try {\n const result = await context.req.json<{ where?: TWhere<TDataObject> }>();\n body = result;\n // eslint-disable-next-line venizia/no-silent-catch -- a body that is not JSON is not a `where`; the bulk delete then relies on the query alone and nothing else is lost\n } catch {\n body = undefined;\n }\n\n const resolved = this.resolveBulkWhere({\n context,\n where: { fromQuery: queryWhere, fromBody: body?.where },\n });\n if (resolved.error !== undefined) {\n return resolved.error;\n }\n\n const { where } = resolved;\n\n const rs = await this.measure({\n scope: 'deleteBy',\n args: { where },\n task: async () => {\n const payload = await this.repository.deleteBy({ where });\n return this.respond<Array<TDataObject>>({\n context,\n format: ResponseFormats.ARRAY,\n payload,\n });\n },\n });\n\n return context.json(rs, HTTP.ResultCodes.RS_2.Ok);\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-error.middleware.d.ts","sourceRoot":"","sources":["../../../../../src/base/middlewares/app-error/app-error.middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAa,MAAM,6BAA6B,CAAC;AAEtE,OAAO,EACL,UAAU,EAKX,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,KAAK,EAAE,YAAY,EAAqB,MAAM,YAAY,CAAC;AAiBlE,2JAA2J;AAC3J,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE;IACtC,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,KAAK,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"app-error.middleware.d.ts","sourceRoot":"","sources":["../../../../../src/base/middlewares/app-error/app-error.middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAa,MAAM,6BAA6B,CAAC;AAEtE,OAAO,EACL,UAAU,EAKX,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,KAAK,EAAE,YAAY,EAAqB,MAAM,YAAY,CAAC;AAiBlE,2JAA2J;AAC3J,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE;IACtC,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,KAAK,MAAM,CAAC;AA+Cb;;;;;;;;;GASG;AACH,qBAAa,sBAAuB,SAAQ,UAAW,YAAW,SAAS,CAAC,YAAY,CAAC;IACvF,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,sBAAsB,CAAS;IACvC,OAAO,CAAC,qBAAqB,CAAS;IAEtC;;;;;;;;OAQG;IACH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAA2B;IAExD,uIAAuI;IACvI,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAqB;gBAE9C,IAAI,CAAC,EAAE;QACjB,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,sBAAsB,CAAC,EAAE,MAAM,CAAC;QAChC,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAC/B,WAAW,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;QACvC,WAAW,CAAC,EAAE,kBAAkB,CAAC;KAClC;IAgBD,+FAA+F;IAC/F,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE;QAC1B,KAAK,EAAE,OAAO,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAChC,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,GAAG,MAAM;IAIV;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAuCzB,OAAO,CAAC,WAAW;IAInB,+DAA+D;IAC/D,OAAO,CAAC,YAAY;IAgCpB,OAAO,CAAC,QAAQ;IAkBhB,wJAAwJ;IACxJ,OAAO,CAAC,qBAAqB;IAc7B,4GAA4G;IAC5G,OAAO,CAAC,qBAAqB;IAU7B,oGAAoG;IACpG,OAAO,CAAC,KAAK;IAsBb,OAAO,CAAC,OAAO;IA+Cf,mGAAmG;IACnG,OAAO,CAAC,eAAe;IAUvB,wGAAwG;IACxG,OAAO,CAAC,QAAQ;IAgChB,qIAAqI;IACrI,OAAO,CAAC,aAAa;IA6BrB,KAAK,IAAI,YAAY;CAkDtB"}
|
|
@@ -36,6 +36,7 @@ const renderValue = (opts) => {
|
|
|
36
36
|
try {
|
|
37
37
|
const rendered = JSON.stringify(safe, (_key, entry) => typeof entry === 'bigint' ? entry.toString() : entry);
|
|
38
38
|
return rendered ?? String(value);
|
|
39
|
+
// eslint-disable-next-line venizia/no-silent-catch -- the marker returned below is the report; the only thing lost is the unrenderable value's text in the log line
|
|
39
40
|
}
|
|
40
41
|
catch {
|
|
41
42
|
// Not a swallowed failure: this marker IS the report, and it lands in the log line the caller
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-error.middleware.js","sourceRoot":"","sources":["../../../../../src/base/middlewares/app-error/app-error.middleware.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,SAAS,EACT,WAAW,EACX,eAAe,GAChB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAIpE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EACL,qBAAqB,EACrB,6BAA6B,EAC7B,gCAAgC,GACjC,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,8BAA8B,GAAG,uBAAuB,CAAC;AAE/D,2JAA2J;AAC3J,MAAM,gCAAgC,GAAG,CAAC,CAAC;AAC3C,MAAM,+BAA+B,GAAG,EAAE,CAAC;AAc3C;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,GAAG,CAAC,IAAwB,EAAU,EAAE;IACvD,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;IAEvB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,IAAI,GAAG,aAAa,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAEjD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,6FAA6F;QAC7F,8EAA8E;QAC9E,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,KAAc,EAAE,EAAE,CAC7D,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CACrD,CAAC;YAEF,OAAO,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,8FAA8F;YAC9F,eAAe;YACf,OAAO,gBAAgB,CAAC;QAC1B,CAAC;IACH,CAAC;AACH,CAAC,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,OAAO,sBAAuB,SAAQ,UAAU;IAmBpD,YAAY,IAOX;QACC,yFAAyF;QACzF,mEAAmE;QACnE,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAElC,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,OAAO,CAAC;QAC7B,IAAI,CAAC,sBAAsB,GAAG,IAAI,EAAE,sBAAsB,IAAI,gCAAgC,CAAC;QAC/F,IAAI,CAAC,qBAAqB,GAAG,IAAI,EAAE,qBAAqB,IAAI,+BAA+B,CAAC;QAC5F,IAAI,CAAC,WAAW,GAAG,IAAI,EAAE,WAAW,CAAC;QACrC,IAAI,CAAC,mBAAmB,GAAG,IAAI,EAAE,WAAW,CAAC;QAE7C,IAAI,IAAI,EAAE,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,+FAA+F;IACrF,WAAW,CAAC,IAMrB;QACC,OAAO,CAAC,IAAI,CAAC,mBAAmB,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAChF,CAAC;IAED;;;;;;OAMG;IACK,iBAAiB,CAAC,IAMzB;QACC,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;QAChF,MAAM,MAAM,GAAG,KAA0C,CAAC;QAC1D,MAAM,KAAK,GAAkB,EAAE,CAAC;QAEhC,IAAI,OAAO,MAAM,EAAE,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrC,KAAK,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACrC,CAAC;QAED,KAAK,CAAC,IAAI,CACR,YAAY,OAAO,MAAM,EAAE,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CACnG,CAAC;QAEF,IAAI,WAAW,EAAE,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC,SAAS,WAAW,EAAE,CAAC,CAAC;QACrC,CAAC;QAED,IAAI,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3C,KAAK,CAAC,IAAI,CAAC,UAAU,WAAW,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACxD,CAAC;QAED,IAAI,YAAY,IAAI,OAAO,MAAM,EAAE,KAAK,KAAK,QAAQ,EAAE,CAAC;YACtD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;YAC7F,MAAM,MAAM,GAAG,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;YAEvF,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,KAAK,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrD,CAAC;IAEO,WAAW,CAAC,OAAe;QACjC,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;IAC9D,CAAC;IAED,+DAA+D;IACvD,YAAY,CAAC,IAA6D;QAChF,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;QAC3C,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAExE,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,8FAA8F;YAC9F,6FAA6F;YAC7F,4DAA4D;YAC5D,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACrB,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,6EAA6E,EAC7E,SAAS,EACT,GAAG,EACH,OAAO,CAAC,GAAG,CAAC,IAAI,EAChB,OAAO,CAAC,GAAG,CAAC,MAAM,EAClB,OAAO,CAAC,GAAG,CAAC,GAAG,EACf,IAAI,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,CAAC,CAC5B,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,qHAAqH,EACrH,SAAS,EACT,OAAO,CAAC,GAAG,CAAC,IAAI,CACjB,CAAC;YACJ,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;IACnE,CAAC;IAEO,QAAQ,CAAC,IAAuD;QACtE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QAEhC,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;YAC1B,OAAO,qBAAqB,CAAC,eAAe,CAAC;QAC/C,CAAC;QAED,IAAI,oBAAoB,CAAC,wBAAwB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;YAC7D,OAAO,qBAAqB,CAAC,kBAAkB,CAAC;QAClD,CAAC;QAED,IAAI,YAAY,IAAI,KAAK,IAAI,IAAI,CAAC,qBAAqB,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,SAAS,EAAE,CAAC;YACjF,OAAO,qBAAqB,CAAC,WAAW,CAAC;QAC3C,CAAC;QAED,OAAO,qBAAqB,CAAC,UAAU,CAAC;IAC1C,CAAC;IAED,wJAAwJ;IAChJ,qBAAqB,CAAC,IAAwB;QACpD,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;QAEvB,IAAI,CAAC,CAAC,aAAa,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC1F,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,aAAa,GACjB,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU;YAChD,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,mBAAmB,CAAC;QAE3D,OAAO,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAClD,CAAC;IAED,4GAA4G;IACpG,qBAAqB,CAAC,IAAwB;QACpD,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;QAEvB,IAAI,YAAY,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;YAClE,OAAO,KAAK,CAAC,UAAU,CAAC;QAC1B,CAAC;QAED,OAAO,IAAI,CAAC,qBAAqB,CAAC,EAAE,KAAK,EAAE,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,mBAAmB,CAAC;IAC5F,CAAC;IAED,oGAAoG;IAC5F,KAAK,CAAC,IAMb;QACC,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;QAE/D,qGAAqG;QACrG,MAAM,IAAI,GACR,WAAW;YACX,WAAW,CAAC,OAAO,CAAC,aAAa,IAAI,KAAK,CAAC,CAAC,CAAE,KAAK,CAAC,WAAsB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAE1F,MAAM,UAAU,GACd,YAAY,IAAI,KAAK;YACnB,CAAC,CAAE,KAAK,CAAC,UAAsD;YAC/D,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;QAExC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;IACnD,CAAC;IAEO,OAAO,CAAC,IAA+C;QAC7D,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;QACrC,MAAM,OAAO,GAAG,oBAAoB,CAAC,qBAAqB,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;QACpF,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAE/C,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,qBAAqB,CAAC,eAAe,CAAC,CAAC,CAAC;gBAC3C,OAAO,IAAI,CAAC,KAAK,CAAC;oBAChB,KAAK;oBACL,IAAI;oBACJ,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU;oBAC5C,yFAAyF;oBACzF,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,8BAA8B;iBAC3D,CAAC,CAAC;YACL,CAAC;YAED,KAAK,qBAAqB,CAAC,kBAAkB,CAAC,CAAC,CAAC;gBAC9C,OAAO,IAAI,CAAC,KAAK,CAAC;oBAChB,KAAK;oBACL,IAAI;oBACJ,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ;oBAC1C,OAAO,EAAE,gCAAgC;oBACzC,WAAW,EAAE,6BAA6B;iBAC3C,CAAC,CAAC;YACL,CAAC;YAED,KAAK,qBAAqB,CAAC,WAAW,CAAC,CAAC,CAAC;gBACvC,OAAO,IAAI,CAAC,KAAK,CAAC;oBAChB,KAAK;oBACL,IAAI;oBACJ,UAAU,EAAE,IAAI,CAAC,qBAAqB,CAAC,EAAE,KAAK,EAAE,CAAC;oBACjD,OAAO,EAAE,KAAK,CAAC,OAAO;iBACvB,CAAC,CAAC;YACL,CAAC;YAED,OAAO,CAAC,CAAC,CAAC;gBACR,OAAO,IAAI,CAAC,KAAK,CAAC;oBAChB,KAAK;oBACL,IAAI,EAAE,qBAAqB,CAAC,UAAU;oBACtC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,mBAAmB;oBACrD,mFAAmF;oBACnF,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO;iBACvE,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,mGAAmG;IAC3F,eAAe,CAAC,IAAwB;QAC9C,MAAM,SAAS,GAAI,IAAI,CAAC,KAAgC,CAAC,QAAQ,CAAC;QAElE,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YAClE,OAAO,SAAsB,CAAC;QAChC,CAAC;QAED,OAAO,SAAS,CAAC,KAAK,CAAC;IACzB,CAAC;IAED,wGAAwG;IAChG,QAAQ,CAAC,IAOhB;QACC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;QAE1E,IAAI,CAAC,MAAM,CAAC,GAAG,CACb,IAAI,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,CAAC,EAC/B,qCAAqC,EACrC,SAAS,EACT,UAAU,EACV,OAAO,CAAC,GAAG,CAAC,MAAM,EAClB,OAAO,CAAC,GAAG,CAAC,GAAG,EACf,IAAI,CAAC,WAAW,CAAC;YACf,KAAK;YACL,sFAAsF;YACtF,WAAW,EAAE,WAAW,KAAK,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW;YAC1E,KAAK,EAAE,OAAO,IAAI,KAAK,CAAC,CAAC,CAAE,KAAK,CAAC,KAAiC,CAAC,CAAC,CAAC,SAAS;YAC9E,YAAY,EAAE,IAAI;YAClB,qGAAqG;YACrG,cAAc,EACZ,IAAI,KAAK,qBAAqB,CAAC,UAAU;gBACvC,CAAC,CAAC,IAAI,CAAC,qBAAqB;gBAC5B,CAAC,CAAC,IAAI,CAAC,sBAAsB;SAClC,CAAC,CACH,CAAC;IACJ,CAAC;IAED,qIAAqI;IAC7H,aAAa,CAAC,IAIrB;QACC,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;QAEnD,IAAI,QAAQ,CAAC,IAAI,KAAK,qBAAqB,CAAC,WAAW,EAAE,CAAC;YACxD,OAAO,QAAQ,CAAC,OAAO,CAAC;QAC1B,CAAC;QAED,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,eAAe,CAAC,MAAM,CAAC;YAC/C,IAAI,EAAE,QAAQ,CAAC,OAAO;YACtB,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,IAAI;SAC/B,CAAC,CAAC;QAEH,uGAAuG;QACvG,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACxC,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,4DAA4D,EAC5D,SAAS,EACT,QAAQ,CAAC,UAAU,CAAC,IAAI,EACxB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CACnB,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK;QACH,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YAC9B,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YAEtE,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC9B,MAAM,EAAE,GAAG,eAAe,CAAC,cAAc,CAAC;oBACxC,YAAY;oBACZ,SAAS;oBACT,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG;oBACpB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI;oBACtB,KAAK;iBACN,CAAC,CAAC;gBAEH,IAAI,CAAC,QAAQ,CAAC;oBACZ,KAAK;oBACL,OAAO;oBACP,SAAS;oBACT,UAAU,EAAE,EAAE,CAAC,UAAU;oBACzB,WAAW,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI;iBACzC,CAAC,CAAC;gBAEH,OAAO,OAAO,CAAC,IAAI,CACjB,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,QAAQ,CAAC,EAC7B,EAAE,CAAC,UAAgD,CACpD,CAAC;YACJ,CAAC;YAED,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;YACvD,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC;YAElD,IAAI,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAE7F,MAAM,EAAE,GAAG;gBACT,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC;gBAClE,UAAU;gBACV,UAAU;gBACV,SAAS;gBACT,KAAK,EAAE,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS;gBAClD,OAAO,EAAE;oBACP,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG;oBACpB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI;oBACtB,KAAK,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;oBAC9C,KAAK,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;iBAC/C;aACF,CAAC;YAEF,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,UAAgD,CAAC,CAAC;QAC9F,CAAC,CAAC;IACJ,CAAC;CACF","sourcesContent":["import type { ILogger, TLogLevel } from '@venizia/ignis-helpers/core';\nimport type { TNullable } from '@venizia/ignis-helpers/common';\nimport {\n BaseHelper,\n EnvironmentNames,\n LogLevels,\n MessageCode,\n MessageTemplate,\n} from '@venizia/ignis-helpers/core';\nimport { HTTP, RedactUtility } from '@venizia/ignis-helpers/common';\nimport type { IProvider } from '@venizia/ignis-inversion';\nimport type { Context } from 'hono';\nimport type { ErrorHandler, HTTPResponseError } from 'hono/types';\nimport { REQUEST_ID_KEY } from '../common';\nimport { DatabaseErrorHandler } from './database.handler';\nimport {\n ApplicationErrorTypes,\n DATABASE_RETRYABLE_ERROR_CODE,\n DATABASE_RETRYABLE_ERROR_MESSAGE,\n} from './definition';\nimport type { IResolvedApplicationError, TApplicationErrorType } from './common';\nimport { ZodErrorHandler } from './zod.handler';\n\nconst DEFAULT_INTERNAL_ERROR_MESSAGE = 'Internal Server Error';\n\n/** An intentional error's throw site is still worth naming; its caller chain is framework plumbing, so it gets a smaller budget than an unexpected one. */\nconst DEFAULT_INTENTIONAL_STACK_FRAMES = 5;\nconst DEFAULT_UNEXPECTED_STACK_FRAMES = 10;\n\n/** How a thrown error is rendered into the log line. Must never throw - a throw inside the error handler turns a handled failure into an unhandled one. */\nexport type TErrorLogFormatter = (opts: {\n error: unknown;\n messageCode?: string;\n extra?: Record<string, unknown>;\n includeStack?: boolean;\n maxStackFrames?: number;\n}) => string;\n\ntype TThrown = Error | HTTPResponseError;\ntype TDatabaseClientError = ReturnType<typeof DatabaseErrorHandler.isDatabaseClientError>;\n\n/**\n * Renders a value into one log-safe fragment.\n *\n * Redaction is not optional here. This runs on `extra`, which is whatever a throw site chose to\n * attach - `getError({ extra: { apiKey } })` is a shape applications write - and in a Worker this\n * fragment lands in the browser console. `toJsonSafe` masks secret-shaped keys; a hand-rolled\n * `JSON.stringify` does not, and the server path has always redacted.\n *\n * The BigInt replacer stays: `toJsonSafe` leaves BigInt intact and `JSON.stringify` refuses it, so\n * without this a single BigInt would collapse the whole fragment to the marker below. Anything else\n * it refuses yields that marker rather than a throw - this is the last-resort error handler, where a\n * throw turns a handled failure into an unhandled one.\n */\nconst renderValue = (opts: { value: unknown }): string => {\n const { value } = opts;\n\n if (typeof value === 'string') {\n return value;\n }\n\n const safe = RedactUtility.toJsonSafe({ value });\n\n try {\n return JSON.stringify(safe) ?? String(value);\n } catch {\n // A replacer is 6x the cost of plain stringify and deopts every key, so it is installed only\n // once BigInt has actually thrown - the case it exists for, and the rare one.\n try {\n const rendered = JSON.stringify(safe, (_key, entry: unknown) =>\n typeof entry === 'bigint' ? entry.toString() : entry,\n );\n\n return rendered ?? String(value);\n } catch {\n // Not a swallowed failure: this marker IS the report, and it lands in the log line the caller\n // is building.\n return '[unrenderable]';\n }\n }\n};\n\n/**\n * Hono `onError`: ZodError -> 422, DB client error -> 400, retryable conflict -> 409, `getError` ->\n * its own status, else 500. Browser-pure: the two reads that need a host - the ambient environment\n * name and the error formatter - are constructor OPTIONS, not methods to subclass.\n *\n * They were hooks once, and three subclasses existed to answer them and nothing else. A class seam\n * is also unreachable from application code, so the browser example had to fake the environment with\n * a Hono middleware assigning `context.env`. `@venizia/ignis`'s `AppErrorMiddleware` now just\n * supplies `process.env.NODE_ENV` and `ErrorPrettier` as options.\n */\nexport class BaseAppErrorMiddleware extends BaseHelper implements IProvider<ErrorHandler> {\n private rootKey: TNullable<string>;\n private intentionalStackFrames: number;\n private unexpectedStackFrames: number;\n\n /**\n * How this host reads its ambient environment name, and the ONE option that says whether it has\n * one at all: absent means it does not (a browser), so an unresolved name is by design; present\n * but returning `undefined` means a host that should have one is misconfigured. Either way\n * {@link isProduction} fails closed.\n *\n * A function, not a string: `process.env.NODE_ENV` has to be read per request, since a test - and\n * a `--env-file` reload - can change it after the middleware is built.\n */\n private readonly environment?: () => string | undefined;\n\n /** Replaces {@link renderErrorForLog} - `@venizia/ignis` passes `ErrorPrettier`, which reaches `node:util` and so cannot live here. */\n private readonly formatErrorOverride?: TErrorLogFormatter;\n\n constructor(opts?: {\n logger?: ILogger;\n rootKey?: string;\n intentionalStackFrames?: number;\n unexpectedStackFrames?: number;\n environment?: () => string | undefined;\n formatError?: TErrorLogFormatter;\n }) {\n // `new.target`, not a literal: a subclass logs under its own name, so `@venizia/ignis`'s\n // `AppErrorMiddleware` keeps the scope it has always logged under.\n super({ scope: new.target.name });\n\n this.rootKey = opts?.rootKey;\n this.intentionalStackFrames = opts?.intentionalStackFrames ?? DEFAULT_INTENTIONAL_STACK_FRAMES;\n this.unexpectedStackFrames = opts?.unexpectedStackFrames ?? DEFAULT_UNEXPECTED_STACK_FRAMES;\n this.environment = opts?.environment;\n this.formatErrorOverride = opts?.formatError;\n\n if (opts?.logger) {\n this.logger = opts.logger;\n }\n }\n\n /** Renders a thrown error for the log, through the `formatError` option when one was given. */\n protected formatError(opts: {\n error: unknown;\n messageCode?: string;\n extra?: Record<string, unknown>;\n includeStack?: boolean;\n maxStackFrames?: number;\n }): string {\n return (this.formatErrorOverride ?? ((o) => this.renderErrorForLog(o)))(opts);\n }\n\n /**\n * The default log rendering: pure and deliberately small, so the whole middleware stays\n * browser-pure.\n *\n * Must never throw, cycles included: a throw inside the error handler turns a handled failure\n * into an unhandled one.\n */\n private renderErrorForLog(opts: {\n error: unknown;\n messageCode?: string;\n extra?: Record<string, unknown>;\n includeStack?: boolean;\n maxStackFrames?: number;\n }): string {\n const { error, messageCode, extra, includeStack = true, maxStackFrames } = opts;\n const thrown = error as Partial<Error> | null | undefined;\n const lines: Array<string> = [];\n\n if (typeof thrown?.name === 'string') {\n lines.push(`name: ${thrown.name}`);\n }\n\n lines.push(\n `message: ${typeof thrown?.message === 'string' ? thrown.message : renderValue({ value: error })}`,\n );\n\n if (messageCode) {\n lines.push(`code: ${messageCode}`);\n }\n\n if (extra && Object.keys(extra).length > 0) {\n lines.push(`extra: ${renderValue({ value: extra })}`);\n }\n\n if (includeStack && typeof thrown?.stack === 'string') {\n const frames = thrown.stack.split('\\n').filter((line) => line.trimStart().startsWith('at '));\n const capped = maxStackFrames === undefined ? frames : frames.slice(0, maxStackFrames);\n\n if (capped.length > 0) {\n lines.push(`stack:\\n${capped.join('\\n')}`);\n }\n }\n\n return lines.map((line) => `- ${line}`).join('\\n');\n }\n\n private withRootKey(payload: object) {\n return this.rootKey ? { [this.rootKey]: payload } : payload;\n }\n\n /** Fail-closed: an unset or unrecognized env is production. */\n private isProduction(opts: { context: Context; error: TThrown; requestId: string }): boolean {\n const { context, error, requestId } = opts;\n const env = [context.env?.NODE_ENV, this.environment?.()].find(Boolean);\n\n if (!env) {\n // Only a host that HAS an ambient environment can be misconfigured about it. In a browser the\n // absence is by design, and shouting it at error level on every request buries the error the\n // reader is actually looking at. Both paths still sanitize.\n if (this.environment) {\n this.logger.error(\n '[%s] INVALID ENV IDENTIFIER | env: %s | path: %s | method: %s | url: %s\\n%s',\n requestId,\n env,\n context.req.path,\n context.req.method,\n context.req.url,\n this.formatError({ error }),\n );\n } else {\n this.logger.debug(\n '[%s] No ambient environment - sanitizing as production | path: %s | set NODE_ENV on the Hono env binding to opt out',\n requestId,\n context.req.path,\n );\n }\n\n return true;\n }\n\n return !EnvironmentNames.DEVELOPMENT_ENVS.has(env.toLowerCase());\n }\n\n private classify(opts: { error: TThrown; dbError: TDatabaseClientError }): TApplicationErrorType {\n const { error, dbError } = opts;\n\n if (dbError.isClientError) {\n return ApplicationErrorTypes.DATABASE_CLIENT;\n }\n\n if (DatabaseErrorHandler.isRetryableDatabaseError({ error })) {\n return ApplicationErrorTypes.DATABASE_RETRYABLE;\n }\n\n if ('statusCode' in error || this.readClientErrorStatus({ error }) !== undefined) {\n return ApplicationErrorTypes.INTENTIONAL;\n }\n\n return ApplicationErrorTypes.UNEXPECTED;\n }\n\n /** Hono's `HTTPException` carries `status`, not `statusCode`. Only a 4xx is the caller's fault; a 5xx stays unexpected, so its message is sanitized. */\n private readClientErrorStatus(opts: { error: TThrown }): number | undefined {\n const { error } = opts;\n\n if (!('getResponse' in error) || !('status' in error) || typeof error.status !== 'number') {\n return undefined;\n }\n\n const isClientError =\n error.status >= HTTP.ResultCodes.RS_4.BadRequest &&\n error.status < HTTP.ResultCodes.RS_5.InternalServerError;\n\n return isClientError ? error.status : undefined;\n }\n\n /** `getError` sets `statusCode`, and it wins when a foreign error carries both. Neither usable is a 500. */\n private readIntentionalStatus(opts: { error: TThrown }): number {\n const { error } = opts;\n\n if ('statusCode' in error && typeof error.statusCode === 'number') {\n return error.statusCode;\n }\n\n return this.readClientErrorStatus({ error }) ?? HTTP.ResultCodes.RS_5.InternalServerError;\n }\n\n /** An ApplicationError's `normalized` is authoritative - a `transform` may have reworded `text`. */\n private build(opts: {\n error: TThrown;\n statusCode: number;\n message: string;\n type: TApplicationErrorType;\n messageCode?: string;\n }): IResolvedApplicationError {\n const { error, statusCode, message, type, messageCode } = opts;\n\n // Fallback for a FOREIGN error that sets its own code; an ApplicationError reports via `normalized`.\n const code =\n messageCode ??\n MessageCode.resolve('messageCode' in error ? (error.messageCode as string) : undefined);\n\n const normalized =\n 'normalized' in error\n ? (error.normalized as IResolvedApplicationError['normalized'])\n : { text: message, code, args: {} };\n\n return { statusCode, message, normalized, type };\n }\n\n private resolve(opts: { error: TThrown; isProduction: boolean }): IResolvedApplicationError {\n const { error, isProduction } = opts;\n const dbError = DatabaseErrorHandler.isDatabaseClientError({ error, isProduction });\n const type = this.classify({ error, dbError });\n\n switch (type) {\n case ApplicationErrorTypes.DATABASE_CLIENT: {\n return this.build({\n error,\n type,\n statusCode: HTTP.ResultCodes.RS_4.BadRequest,\n // The fallback is unreachable today; it keeps the driver's raw text from ever surfacing.\n message: dbError.message ?? DEFAULT_INTERNAL_ERROR_MESSAGE,\n });\n }\n\n case ApplicationErrorTypes.DATABASE_RETRYABLE: {\n return this.build({\n error,\n type,\n statusCode: HTTP.ResultCodes.RS_4.Conflict,\n message: DATABASE_RETRYABLE_ERROR_MESSAGE,\n messageCode: DATABASE_RETRYABLE_ERROR_CODE,\n });\n }\n\n case ApplicationErrorTypes.INTENTIONAL: {\n return this.build({\n error,\n type,\n statusCode: this.readIntentionalStatus({ error }),\n message: error.message,\n });\n }\n\n default: {\n return this.build({\n error,\n type: ApplicationErrorTypes.UNEXPECTED,\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n // Never leak a raw message - it may carry SQL, schema names or connection details.\n message: isProduction ? DEFAULT_INTERNAL_ERROR_MESSAGE : error.message,\n });\n }\n }\n }\n\n /** A throw site may set `logLevel` via `getError`; anything unset or malformed logs at `error`. */\n private resolveLogLevel(opts: { error: TThrown }): TLogLevel {\n const candidate = (opts.error as { logLevel?: unknown }).logLevel;\n\n if (typeof candidate === 'string' && LogLevels.isValid(candidate)) {\n return candidate as TLogLevel;\n }\n\n return LogLevels.ERROR;\n }\n\n /** The one place a thrown error reaches the log - called once the status is known, so it carries it. */\n private logError(opts: {\n error: TThrown;\n context: Context;\n requestId: string;\n statusCode: number;\n messageCode: string;\n type?: TApplicationErrorType;\n }) {\n const { error, context, requestId, statusCode, messageCode, type } = opts;\n\n this.logger.log(\n this.resolveLogLevel({ error }),\n '[%s] REQUEST ERROR | %s | %s %s\\n%s',\n requestId,\n statusCode,\n context.req.method,\n context.req.url,\n this.formatError({\n error,\n // The default code means \"no code\" - logging it on every error would be a noise line.\n messageCode: messageCode === MessageCode.DEFAULT ? undefined : messageCode,\n extra: 'extra' in error ? (error.extra as Record<string, unknown>) : undefined,\n includeStack: true,\n // An intentional error still needs its throw site; it just does not need the caller chain behind it.\n maxStackFrames:\n type === ApplicationErrorTypes.UNEXPECTED\n ? this.unexpectedStackFrames\n : this.intentionalStackFrames,\n }),\n );\n }\n\n /** Only an intentional error's message is a catalog template; every other branch writes its own text, so it passes through as is. */\n private renderMessage(opts: {\n resolved: IResolvedApplicationError;\n isProduction: boolean;\n requestId: string;\n }): string {\n const { resolved, isProduction, requestId } = opts;\n\n if (resolved.type !== ApplicationErrorTypes.INTENTIONAL) {\n return resolved.message;\n }\n\n const { text, missing } = MessageTemplate.render({\n text: resolved.message,\n args: resolved.normalized.args,\n });\n\n // Production stays silent and renders what it can; anywhere else a missing arg is a throw site to fix.\n if (missing.length > 0 && !isProduction) {\n this.logger.warn(\n '[%s] MESSAGE PLACEHOLDER WITHOUT ARG | code: %s | keys: %s',\n requestId,\n resolved.normalized.code,\n missing.join(', '),\n );\n }\n\n return text;\n }\n\n value(): ErrorHandler {\n return async (error, context) => {\n const requestId = context.get(REQUEST_ID_KEY);\n const isProduction = this.isProduction({ context, error, requestId });\n\n if (error.name === 'ZodError') {\n const rs = ZodErrorHandler.formatZodError({\n isProduction,\n requestId,\n url: context.req.url,\n path: context.req.path,\n error,\n });\n\n this.logError({\n error,\n context,\n requestId,\n statusCode: rs.statusCode,\n messageCode: rs.response.normalized.code,\n });\n\n return context.json(\n this.withRootKey(rs.response),\n rs.statusCode as Parameters<typeof context.json>[1],\n );\n }\n\n const resolved = this.resolve({ error, isProduction });\n const { statusCode, normalized, type } = resolved;\n\n this.logError({ error, context, requestId, statusCode, messageCode: normalized.code, type });\n\n const rs = {\n message: this.renderMessage({ resolved, isProduction, requestId }),\n statusCode,\n normalized,\n requestId,\n extra: 'extra' in error ? error?.extra : undefined,\n details: {\n url: context.req.url,\n path: context.req.path,\n stack: !isProduction ? error.stack : undefined,\n cause: !isProduction ? error.cause : undefined,\n },\n };\n\n return context.json(this.withRootKey(rs), statusCode as Parameters<typeof context.json>[1]);\n };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"app-error.middleware.js","sourceRoot":"","sources":["../../../../../src/base/middlewares/app-error/app-error.middleware.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ILogger, TLogLevel } from '@venizia/ignis-helpers/core';\nimport type { TNullable } from '@venizia/ignis-helpers/common';\nimport {\n BaseHelper,\n EnvironmentNames,\n LogLevels,\n MessageCode,\n MessageTemplate,\n} from '@venizia/ignis-helpers/core';\nimport { HTTP, RedactUtility } from '@venizia/ignis-helpers/common';\nimport type { IProvider } from '@venizia/ignis-inversion';\nimport type { Context } from 'hono';\nimport type { ErrorHandler, HTTPResponseError } from 'hono/types';\nimport { REQUEST_ID_KEY } from '../common';\nimport { DatabaseErrorHandler } from './database.handler';\nimport {\n ApplicationErrorTypes,\n DATABASE_RETRYABLE_ERROR_CODE,\n DATABASE_RETRYABLE_ERROR_MESSAGE,\n} from './definition';\nimport type { IResolvedApplicationError, TApplicationErrorType } from './common';\nimport { ZodErrorHandler } from './zod.handler';\n\nconst DEFAULT_INTERNAL_ERROR_MESSAGE = 'Internal Server Error';\n\n/** An intentional error's throw site is still worth naming; its caller chain is framework plumbing, so it gets a smaller budget than an unexpected one. */\nconst DEFAULT_INTENTIONAL_STACK_FRAMES = 5;\nconst DEFAULT_UNEXPECTED_STACK_FRAMES = 10;\n\n/** How a thrown error is rendered into the log line. Must never throw - a throw inside the error handler turns a handled failure into an unhandled one. */\nexport type TErrorLogFormatter = (opts: {\n error: unknown;\n messageCode?: string;\n extra?: Record<string, unknown>;\n includeStack?: boolean;\n maxStackFrames?: number;\n}) => string;\n\ntype TThrown = Error | HTTPResponseError;\ntype TDatabaseClientError = ReturnType<typeof DatabaseErrorHandler.isDatabaseClientError>;\n\n/**\n * Renders a value into one log-safe fragment.\n *\n * Redaction is not optional here. This runs on `extra`, which is whatever a throw site chose to\n * attach - `getError({ extra: { apiKey } })` is a shape applications write - and in a Worker this\n * fragment lands in the browser console. `toJsonSafe` masks secret-shaped keys; a hand-rolled\n * `JSON.stringify` does not, and the server path has always redacted.\n *\n * The BigInt replacer stays: `toJsonSafe` leaves BigInt intact and `JSON.stringify` refuses it, so\n * without this a single BigInt would collapse the whole fragment to the marker below. Anything else\n * it refuses yields that marker rather than a throw - this is the last-resort error handler, where a\n * throw turns a handled failure into an unhandled one.\n */\nconst renderValue = (opts: { value: unknown }): string => {\n const { value } = opts;\n\n if (typeof value === 'string') {\n return value;\n }\n\n const safe = RedactUtility.toJsonSafe({ value });\n\n try {\n return JSON.stringify(safe) ?? String(value);\n } catch {\n // A replacer is 6x the cost of plain stringify and deopts every key, so it is installed only\n // once BigInt has actually thrown - the case it exists for, and the rare one.\n try {\n const rendered = JSON.stringify(safe, (_key, entry: unknown) =>\n typeof entry === 'bigint' ? entry.toString() : entry,\n );\n\n return rendered ?? String(value);\n // eslint-disable-next-line venizia/no-silent-catch -- the marker returned below is the report; the only thing lost is the unrenderable value's text in the log line\n } catch {\n // Not a swallowed failure: this marker IS the report, and it lands in the log line the caller\n // is building.\n return '[unrenderable]';\n }\n }\n};\n\n/**\n * Hono `onError`: ZodError -> 422, DB client error -> 400, retryable conflict -> 409, `getError` ->\n * its own status, else 500. Browser-pure: the two reads that need a host - the ambient environment\n * name and the error formatter - are constructor OPTIONS, not methods to subclass.\n *\n * They were hooks once, and three subclasses existed to answer them and nothing else. A class seam\n * is also unreachable from application code, so the browser example had to fake the environment with\n * a Hono middleware assigning `context.env`. `@venizia/ignis`'s `AppErrorMiddleware` now just\n * supplies `process.env.NODE_ENV` and `ErrorPrettier` as options.\n */\nexport class BaseAppErrorMiddleware extends BaseHelper implements IProvider<ErrorHandler> {\n private rootKey: TNullable<string>;\n private intentionalStackFrames: number;\n private unexpectedStackFrames: number;\n\n /**\n * How this host reads its ambient environment name, and the ONE option that says whether it has\n * one at all: absent means it does not (a browser), so an unresolved name is by design; present\n * but returning `undefined` means a host that should have one is misconfigured. Either way\n * {@link isProduction} fails closed.\n *\n * A function, not a string: `process.env.NODE_ENV` has to be read per request, since a test - and\n * a `--env-file` reload - can change it after the middleware is built.\n */\n private readonly environment?: () => string | undefined;\n\n /** Replaces {@link renderErrorForLog} - `@venizia/ignis` passes `ErrorPrettier`, which reaches `node:util` and so cannot live here. */\n private readonly formatErrorOverride?: TErrorLogFormatter;\n\n constructor(opts?: {\n logger?: ILogger;\n rootKey?: string;\n intentionalStackFrames?: number;\n unexpectedStackFrames?: number;\n environment?: () => string | undefined;\n formatError?: TErrorLogFormatter;\n }) {\n // `new.target`, not a literal: a subclass logs under its own name, so `@venizia/ignis`'s\n // `AppErrorMiddleware` keeps the scope it has always logged under.\n super({ scope: new.target.name });\n\n this.rootKey = opts?.rootKey;\n this.intentionalStackFrames = opts?.intentionalStackFrames ?? DEFAULT_INTENTIONAL_STACK_FRAMES;\n this.unexpectedStackFrames = opts?.unexpectedStackFrames ?? DEFAULT_UNEXPECTED_STACK_FRAMES;\n this.environment = opts?.environment;\n this.formatErrorOverride = opts?.formatError;\n\n if (opts?.logger) {\n this.logger = opts.logger;\n }\n }\n\n /** Renders a thrown error for the log, through the `formatError` option when one was given. */\n protected formatError(opts: {\n error: unknown;\n messageCode?: string;\n extra?: Record<string, unknown>;\n includeStack?: boolean;\n maxStackFrames?: number;\n }): string {\n return (this.formatErrorOverride ?? ((o) => this.renderErrorForLog(o)))(opts);\n }\n\n /**\n * The default log rendering: pure and deliberately small, so the whole middleware stays\n * browser-pure.\n *\n * Must never throw, cycles included: a throw inside the error handler turns a handled failure\n * into an unhandled one.\n */\n private renderErrorForLog(opts: {\n error: unknown;\n messageCode?: string;\n extra?: Record<string, unknown>;\n includeStack?: boolean;\n maxStackFrames?: number;\n }): string {\n const { error, messageCode, extra, includeStack = true, maxStackFrames } = opts;\n const thrown = error as Partial<Error> | null | undefined;\n const lines: Array<string> = [];\n\n if (typeof thrown?.name === 'string') {\n lines.push(`name: ${thrown.name}`);\n }\n\n lines.push(\n `message: ${typeof thrown?.message === 'string' ? thrown.message : renderValue({ value: error })}`,\n );\n\n if (messageCode) {\n lines.push(`code: ${messageCode}`);\n }\n\n if (extra && Object.keys(extra).length > 0) {\n lines.push(`extra: ${renderValue({ value: extra })}`);\n }\n\n if (includeStack && typeof thrown?.stack === 'string') {\n const frames = thrown.stack.split('\\n').filter((line) => line.trimStart().startsWith('at '));\n const capped = maxStackFrames === undefined ? frames : frames.slice(0, maxStackFrames);\n\n if (capped.length > 0) {\n lines.push(`stack:\\n${capped.join('\\n')}`);\n }\n }\n\n return lines.map((line) => `- ${line}`).join('\\n');\n }\n\n private withRootKey(payload: object) {\n return this.rootKey ? { [this.rootKey]: payload } : payload;\n }\n\n /** Fail-closed: an unset or unrecognized env is production. */\n private isProduction(opts: { context: Context; error: TThrown; requestId: string }): boolean {\n const { context, error, requestId } = opts;\n const env = [context.env?.NODE_ENV, this.environment?.()].find(Boolean);\n\n if (!env) {\n // Only a host that HAS an ambient environment can be misconfigured about it. In a browser the\n // absence is by design, and shouting it at error level on every request buries the error the\n // reader is actually looking at. Both paths still sanitize.\n if (this.environment) {\n this.logger.error(\n '[%s] INVALID ENV IDENTIFIER | env: %s | path: %s | method: %s | url: %s\\n%s',\n requestId,\n env,\n context.req.path,\n context.req.method,\n context.req.url,\n this.formatError({ error }),\n );\n } else {\n this.logger.debug(\n '[%s] No ambient environment - sanitizing as production | path: %s | set NODE_ENV on the Hono env binding to opt out',\n requestId,\n context.req.path,\n );\n }\n\n return true;\n }\n\n return !EnvironmentNames.DEVELOPMENT_ENVS.has(env.toLowerCase());\n }\n\n private classify(opts: { error: TThrown; dbError: TDatabaseClientError }): TApplicationErrorType {\n const { error, dbError } = opts;\n\n if (dbError.isClientError) {\n return ApplicationErrorTypes.DATABASE_CLIENT;\n }\n\n if (DatabaseErrorHandler.isRetryableDatabaseError({ error })) {\n return ApplicationErrorTypes.DATABASE_RETRYABLE;\n }\n\n if ('statusCode' in error || this.readClientErrorStatus({ error }) !== undefined) {\n return ApplicationErrorTypes.INTENTIONAL;\n }\n\n return ApplicationErrorTypes.UNEXPECTED;\n }\n\n /** Hono's `HTTPException` carries `status`, not `statusCode`. Only a 4xx is the caller's fault; a 5xx stays unexpected, so its message is sanitized. */\n private readClientErrorStatus(opts: { error: TThrown }): number | undefined {\n const { error } = opts;\n\n if (!('getResponse' in error) || !('status' in error) || typeof error.status !== 'number') {\n return undefined;\n }\n\n const isClientError =\n error.status >= HTTP.ResultCodes.RS_4.BadRequest &&\n error.status < HTTP.ResultCodes.RS_5.InternalServerError;\n\n return isClientError ? error.status : undefined;\n }\n\n /** `getError` sets `statusCode`, and it wins when a foreign error carries both. Neither usable is a 500. */\n private readIntentionalStatus(opts: { error: TThrown }): number {\n const { error } = opts;\n\n if ('statusCode' in error && typeof error.statusCode === 'number') {\n return error.statusCode;\n }\n\n return this.readClientErrorStatus({ error }) ?? HTTP.ResultCodes.RS_5.InternalServerError;\n }\n\n /** An ApplicationError's `normalized` is authoritative - a `transform` may have reworded `text`. */\n private build(opts: {\n error: TThrown;\n statusCode: number;\n message: string;\n type: TApplicationErrorType;\n messageCode?: string;\n }): IResolvedApplicationError {\n const { error, statusCode, message, type, messageCode } = opts;\n\n // Fallback for a FOREIGN error that sets its own code; an ApplicationError reports via `normalized`.\n const code =\n messageCode ??\n MessageCode.resolve('messageCode' in error ? (error.messageCode as string) : undefined);\n\n const normalized =\n 'normalized' in error\n ? (error.normalized as IResolvedApplicationError['normalized'])\n : { text: message, code, args: {} };\n\n return { statusCode, message, normalized, type };\n }\n\n private resolve(opts: { error: TThrown; isProduction: boolean }): IResolvedApplicationError {\n const { error, isProduction } = opts;\n const dbError = DatabaseErrorHandler.isDatabaseClientError({ error, isProduction });\n const type = this.classify({ error, dbError });\n\n switch (type) {\n case ApplicationErrorTypes.DATABASE_CLIENT: {\n return this.build({\n error,\n type,\n statusCode: HTTP.ResultCodes.RS_4.BadRequest,\n // The fallback is unreachable today; it keeps the driver's raw text from ever surfacing.\n message: dbError.message ?? DEFAULT_INTERNAL_ERROR_MESSAGE,\n });\n }\n\n case ApplicationErrorTypes.DATABASE_RETRYABLE: {\n return this.build({\n error,\n type,\n statusCode: HTTP.ResultCodes.RS_4.Conflict,\n message: DATABASE_RETRYABLE_ERROR_MESSAGE,\n messageCode: DATABASE_RETRYABLE_ERROR_CODE,\n });\n }\n\n case ApplicationErrorTypes.INTENTIONAL: {\n return this.build({\n error,\n type,\n statusCode: this.readIntentionalStatus({ error }),\n message: error.message,\n });\n }\n\n default: {\n return this.build({\n error,\n type: ApplicationErrorTypes.UNEXPECTED,\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n // Never leak a raw message - it may carry SQL, schema names or connection details.\n message: isProduction ? DEFAULT_INTERNAL_ERROR_MESSAGE : error.message,\n });\n }\n }\n }\n\n /** A throw site may set `logLevel` via `getError`; anything unset or malformed logs at `error`. */\n private resolveLogLevel(opts: { error: TThrown }): TLogLevel {\n const candidate = (opts.error as { logLevel?: unknown }).logLevel;\n\n if (typeof candidate === 'string' && LogLevels.isValid(candidate)) {\n return candidate as TLogLevel;\n }\n\n return LogLevels.ERROR;\n }\n\n /** The one place a thrown error reaches the log - called once the status is known, so it carries it. */\n private logError(opts: {\n error: TThrown;\n context: Context;\n requestId: string;\n statusCode: number;\n messageCode: string;\n type?: TApplicationErrorType;\n }) {\n const { error, context, requestId, statusCode, messageCode, type } = opts;\n\n this.logger.log(\n this.resolveLogLevel({ error }),\n '[%s] REQUEST ERROR | %s | %s %s\\n%s',\n requestId,\n statusCode,\n context.req.method,\n context.req.url,\n this.formatError({\n error,\n // The default code means \"no code\" - logging it on every error would be a noise line.\n messageCode: messageCode === MessageCode.DEFAULT ? undefined : messageCode,\n extra: 'extra' in error ? (error.extra as Record<string, unknown>) : undefined,\n includeStack: true,\n // An intentional error still needs its throw site; it just does not need the caller chain behind it.\n maxStackFrames:\n type === ApplicationErrorTypes.UNEXPECTED\n ? this.unexpectedStackFrames\n : this.intentionalStackFrames,\n }),\n );\n }\n\n /** Only an intentional error's message is a catalog template; every other branch writes its own text, so it passes through as is. */\n private renderMessage(opts: {\n resolved: IResolvedApplicationError;\n isProduction: boolean;\n requestId: string;\n }): string {\n const { resolved, isProduction, requestId } = opts;\n\n if (resolved.type !== ApplicationErrorTypes.INTENTIONAL) {\n return resolved.message;\n }\n\n const { text, missing } = MessageTemplate.render({\n text: resolved.message,\n args: resolved.normalized.args,\n });\n\n // Production stays silent and renders what it can; anywhere else a missing arg is a throw site to fix.\n if (missing.length > 0 && !isProduction) {\n this.logger.warn(\n '[%s] MESSAGE PLACEHOLDER WITHOUT ARG | code: %s | keys: %s',\n requestId,\n resolved.normalized.code,\n missing.join(', '),\n );\n }\n\n return text;\n }\n\n value(): ErrorHandler {\n return async (error, context) => {\n const requestId = context.get(REQUEST_ID_KEY);\n const isProduction = this.isProduction({ context, error, requestId });\n\n if (error.name === 'ZodError') {\n const rs = ZodErrorHandler.formatZodError({\n isProduction,\n requestId,\n url: context.req.url,\n path: context.req.path,\n error,\n });\n\n this.logError({\n error,\n context,\n requestId,\n statusCode: rs.statusCode,\n messageCode: rs.response.normalized.code,\n });\n\n return context.json(\n this.withRootKey(rs.response),\n rs.statusCode as Parameters<typeof context.json>[1],\n );\n }\n\n const resolved = this.resolve({ error, isProduction });\n const { statusCode, normalized, type } = resolved;\n\n this.logError({ error, context, requestId, statusCode, messageCode: normalized.code, type });\n\n const rs = {\n message: this.renderMessage({ resolved, isProduction, requestId }),\n statusCode,\n normalized,\n requestId,\n extra: 'extra' in error ? error?.extra : undefined,\n details: {\n url: context.req.url,\n path: context.req.path,\n stack: !isProduction ? error.stack : undefined,\n cause: !isProduction ? error.cause : undefined,\n },\n };\n\n return context.json(this.withRootKey(rs), statusCode as Parameters<typeof context.json>[1]);\n };\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response-reader.d.ts","sourceRoot":"","sources":["../../../../../src/base/repositories/common/response-reader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAErF;;;GAGG;AACH,qBAAa,kBAAkB;IAC7B,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAMtE,oEAAoE;IACpE,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS;IAIjD;;;;OAIG;IACH,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE;QAC7B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACxB,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS;IAoBhD;;;;;;;;OAQG;IACH,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,eAAe;IA4BpF,kHAAkH;WACrG,SAAS,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"response-reader.d.ts","sourceRoot":"","sources":["../../../../../src/base/repositories/common/response-reader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAErF;;;GAGG;AACH,qBAAa,kBAAkB;IAC7B,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAMtE,oEAAoE;IACpE,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS;IAIjD;;;;OAIG;IACH,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE;QAC7B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACxB,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS;IAoBhD;;;;;;;;OAQG;IACH,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,eAAe;IA4BpF,kHAAkH;WACrG,SAAS,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,eAAe,CAAC;IAqBhG;;;;;;;;OAQG;WACU,kBAAkB,CAAC,IAAI,EAAE;QACpC,QAAQ,EAAE,QAAQ,CAAC;QACnB,gFAAgF;QAChF,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA4B7B;;;;;OAKG;IACH,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;KAAE,GAAG;QACxE,IAAI,EAAE,OAAO,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACjC;CAeF"}
|
|
@@ -66,10 +66,19 @@ export class HttpResponseReader {
|
|
|
66
66
|
}
|
|
67
67
|
/** A failed response's envelope. A body that is not JSON yields `{}`, and the status alone still describes it. */
|
|
68
68
|
static async readError(opts) {
|
|
69
|
-
|
|
69
|
+
let text;
|
|
70
|
+
try {
|
|
71
|
+
const result = await opts.response.text();
|
|
72
|
+
text = result;
|
|
73
|
+
// eslint-disable-next-line venizia/no-silent-catch -- an unreadable body is read as no text; the status alone still describes the failure
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
text = '';
|
|
77
|
+
}
|
|
70
78
|
let body;
|
|
71
79
|
try {
|
|
72
80
|
body = text ? JSON.parse(text) : undefined;
|
|
81
|
+
// eslint-disable-next-line venizia/no-silent-catch -- a body that is not JSON yields `{}`; the status alone still describes the failure
|
|
73
82
|
}
|
|
74
83
|
catch {
|
|
75
84
|
return {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response-reader.js","sourceRoot":"","sources":["../../../../../src/base/repositories/common/response-reader.ts"],"names":[],"mappings":"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","sourcesContent":["import { HTTP } from '@venizia/ignis-helpers/common';\nimport { getError } from '@venizia/ignis-helpers/core';\nimport type { ApplicationError, TResponsedError } from '@venizia/ignis-helpers/core';\n\n/**\n * What an IGNIS server answers - `Content-Range`, the error envelope - read once, here, for every\n * client of that server: the http connector, and a client that reads it without the connector.\n */\nexport class HttpResponseReader {\n static isPlainObject(value: unknown): value is Record<string, unknown> {\n return (\n !!value && typeof value === 'object' && Object.getPrototypeOf(value) === Object.prototype\n );\n }\n\n /** An empty string reads as absent, so a fallback still applies. */\n static toText(value: unknown): string | undefined {\n return typeof value === 'string' && value !== '' ? value : undefined;\n }\n\n /**\n * A `Content-Range` header as the IGNIS server writes it: `records 0-24/137` -> skip 0, total 137;\n * an empty page, `records *\\/137` -> total 137. Anything else, including an absent header or an\n * unknown total, is `undefined`.\n */\n static parseContentRange(opts: {\n header?: string | null;\n }): { skip?: number; total: number } | undefined {\n const { header } = opts;\n\n if (!header) {\n return undefined;\n }\n\n const range = header.match(/(\\d+)\\s*-\\s*(\\d+)\\s*\\/\\s*(\\d+)/);\n if (range) {\n return { skip: Number(range[1]), total: Number(range[3]) };\n }\n\n const unsatisfied = header.match(/\\*\\s*\\/\\s*(\\d+)/);\n if (unsatisfied) {\n return { total: Number(unsatisfied[1]) };\n }\n\n return undefined;\n }\n\n /**\n * The IGNIS error envelope - `{ message, statusCode, normalized: { text, code, args }, requestId,\n * extra, details }` - read off a parsed response body. A server configured with `error.rootKey`\n * wraps it under that key; pass the same `rootKey` to unwrap it. A body without that key, or with a\n * non-object under it (a proxy's `{ error: 'Bad Gateway' }`), is read as it stands.\n *\n * A body that is not a plain object yields `{}`; any other body yields its known fields, each\n * `undefined` when absent or mistyped. An empty string reads as absent.\n */\n static readErrorEnvelope(opts: { body: unknown; rootKey?: string }): TResponsedError {\n const { body, rootKey } = opts;\n\n const wrapped = rootKey && HttpResponseReader.isPlainObject(body) ? body[rootKey] : undefined;\n const envelope = HttpResponseReader.isPlainObject(wrapped) ? wrapped : body;\n\n if (!HttpResponseReader.isPlainObject(envelope)) {\n return {};\n }\n\n const { message, statusCode, normalized, requestId, extra, details } = envelope;\n const normalizedRecord = HttpResponseReader.isPlainObject(normalized) ? normalized : {};\n const { text, code, args } = normalizedRecord;\n\n return {\n message: HttpResponseReader.toText(message),\n statusCode: typeof statusCode === 'number' ? statusCode : undefined,\n normalized: {\n text: HttpResponseReader.toText(text),\n code: HttpResponseReader.toText(code),\n args: HttpResponseReader.isPlainObject(args) ? { ...args } : undefined,\n },\n requestId: HttpResponseReader.toText(requestId),\n extra: HttpResponseReader.isPlainObject(extra) ? { ...extra } : undefined,\n details: HttpResponseReader.isPlainObject(details) ? { ...details } : undefined,\n };\n }\n\n /** A failed response's envelope. A body that is not JSON yields `{}`, and the status alone still describes it. */\n static async readError(opts: { response: Response; rootKey?: string }): Promise<TResponsedError> {\n const text = await opts.response.text().catch(() => '');\n\n let body: unknown;\n try {\n body = text ? JSON.parse(text) : undefined;\n } catch {\n return {};\n }\n\n return HttpResponseReader.readErrorEnvelope({ body, rootKey: opts.rootKey });\n }\n\n /**\n * A failed response as the error the server threw: its status, code, args and text, and its\n * `extra` with the `requestId` added. `message` is `context` plus the server's text, for logs;\n * `normalized.text` stays the server's, for display - `HTTP <status>` when the server sent none.\n * `cause` is the server's `details.cause` - a 422's per-field issues, `{ path, message, code }`.\n *\n * `requestId` names the request this client made. A relaying server's `extra` carries the id of\n * the request it made upstream: it joins `upstreamRequestIds`, nearest first, at every hop.\n */\n static async toApplicationError(opts: {\n response: Response;\n /** Where it failed, for logs - e.g. `[HttpDataSource][read] 404 | /tickets`. */\n context: string;\n rootKey?: string;\n }): Promise<ApplicationError> {\n const { response, context, rootKey } = opts;\n const server = await HttpResponseReader.readError({ response, rootKey });\n const serverText = server.normalized?.text ?? server.message;\n const displayText = serverText ?? `HTTP ${response.status}`;\n\n const extra: Record<string, unknown> = { ...server.extra };\n if (server.requestId) {\n const upstreamRequestId = extra.requestId;\n extra.requestId = server.requestId;\n\n if (upstreamRequestId !== undefined && upstreamRequestId !== server.requestId) {\n const known = Array.isArray(extra.upstreamRequestIds) ? extra.upstreamRequestIds : [];\n extra.upstreamRequestIds = [upstreamRequestId, ...known];\n }\n }\n\n return getError({\n statusCode: response.status,\n message: serverText ? `${context} | ${serverText}` : context,\n messageCode: server.normalized?.code,\n messageArgs: server.normalized?.args,\n extra: Object.keys(extra).length > 0 ? extra : undefined,\n cause: server.details?.cause,\n transform: ({ message }) => ({ ...message, text: displayText }),\n });\n }\n\n /**\n * A body the server marked with `x-response-extra` carries `extra` beside its rows. `body` is what\n * the route answers without extras: the `{ count, data }` envelope when the count was asked for in\n * the body, the rows otherwise. Any other body is returned as it stands - an unmarked object is\n * never unwrapped, so a row that has `data` and `extra` columns of its own is never misread.\n */\n static readExtra(opts: { body: unknown; headers: Pick<Headers, 'has'> }): {\n body: unknown;\n extra?: Record<string, unknown>;\n } {\n const { body, headers } = opts;\n const isMarked = headers.has(HTTP.Headers.RESPONSE_EXTRA);\n\n if (\n !isMarked ||\n !HttpResponseReader.isPlainObject(body) ||\n !HttpResponseReader.isPlainObject(body.extra)\n ) {\n return { body };\n }\n\n const { extra, ...envelope } = body;\n return { body: 'count' in envelope ? envelope : envelope.data, extra: { ...extra } };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"response-reader.js","sourceRoot":"","sources":["../../../../../src/base/repositories/common/response-reader.ts"],"names":[],"mappings":"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","sourcesContent":["import { HTTP } from '@venizia/ignis-helpers/common';\nimport { getError } from '@venizia/ignis-helpers/core';\nimport type { ApplicationError, TResponsedError } from '@venizia/ignis-helpers/core';\n\n/**\n * What an IGNIS server answers - `Content-Range`, the error envelope - read once, here, for every\n * client of that server: the http connector, and a client that reads it without the connector.\n */\nexport class HttpResponseReader {\n static isPlainObject(value: unknown): value is Record<string, unknown> {\n return (\n !!value && typeof value === 'object' && Object.getPrototypeOf(value) === Object.prototype\n );\n }\n\n /** An empty string reads as absent, so a fallback still applies. */\n static toText(value: unknown): string | undefined {\n return typeof value === 'string' && value !== '' ? value : undefined;\n }\n\n /**\n * A `Content-Range` header as the IGNIS server writes it: `records 0-24/137` -> skip 0, total 137;\n * an empty page, `records *\\/137` -> total 137. Anything else, including an absent header or an\n * unknown total, is `undefined`.\n */\n static parseContentRange(opts: {\n header?: string | null;\n }): { skip?: number; total: number } | undefined {\n const { header } = opts;\n\n if (!header) {\n return undefined;\n }\n\n const range = header.match(/(\\d+)\\s*-\\s*(\\d+)\\s*\\/\\s*(\\d+)/);\n if (range) {\n return { skip: Number(range[1]), total: Number(range[3]) };\n }\n\n const unsatisfied = header.match(/\\*\\s*\\/\\s*(\\d+)/);\n if (unsatisfied) {\n return { total: Number(unsatisfied[1]) };\n }\n\n return undefined;\n }\n\n /**\n * The IGNIS error envelope - `{ message, statusCode, normalized: { text, code, args }, requestId,\n * extra, details }` - read off a parsed response body. A server configured with `error.rootKey`\n * wraps it under that key; pass the same `rootKey` to unwrap it. A body without that key, or with a\n * non-object under it (a proxy's `{ error: 'Bad Gateway' }`), is read as it stands.\n *\n * A body that is not a plain object yields `{}`; any other body yields its known fields, each\n * `undefined` when absent or mistyped. An empty string reads as absent.\n */\n static readErrorEnvelope(opts: { body: unknown; rootKey?: string }): TResponsedError {\n const { body, rootKey } = opts;\n\n const wrapped = rootKey && HttpResponseReader.isPlainObject(body) ? body[rootKey] : undefined;\n const envelope = HttpResponseReader.isPlainObject(wrapped) ? wrapped : body;\n\n if (!HttpResponseReader.isPlainObject(envelope)) {\n return {};\n }\n\n const { message, statusCode, normalized, requestId, extra, details } = envelope;\n const normalizedRecord = HttpResponseReader.isPlainObject(normalized) ? normalized : {};\n const { text, code, args } = normalizedRecord;\n\n return {\n message: HttpResponseReader.toText(message),\n statusCode: typeof statusCode === 'number' ? statusCode : undefined,\n normalized: {\n text: HttpResponseReader.toText(text),\n code: HttpResponseReader.toText(code),\n args: HttpResponseReader.isPlainObject(args) ? { ...args } : undefined,\n },\n requestId: HttpResponseReader.toText(requestId),\n extra: HttpResponseReader.isPlainObject(extra) ? { ...extra } : undefined,\n details: HttpResponseReader.isPlainObject(details) ? { ...details } : undefined,\n };\n }\n\n /** A failed response's envelope. A body that is not JSON yields `{}`, and the status alone still describes it. */\n static async readError(opts: { response: Response; rootKey?: string }): Promise<TResponsedError> {\n let text;\n try {\n const result = await opts.response.text();\n text = result;\n // eslint-disable-next-line venizia/no-silent-catch -- an unreadable body is read as no text; the status alone still describes the failure\n } catch {\n text = '';\n }\n\n let body: unknown;\n try {\n body = text ? JSON.parse(text) : undefined;\n // eslint-disable-next-line venizia/no-silent-catch -- a body that is not JSON yields `{}`; the status alone still describes the failure\n } catch {\n return {};\n }\n\n return HttpResponseReader.readErrorEnvelope({ body, rootKey: opts.rootKey });\n }\n\n /**\n * A failed response as the error the server threw: its status, code, args and text, and its\n * `extra` with the `requestId` added. `message` is `context` plus the server's text, for logs;\n * `normalized.text` stays the server's, for display - `HTTP <status>` when the server sent none.\n * `cause` is the server's `details.cause` - a 422's per-field issues, `{ path, message, code }`.\n *\n * `requestId` names the request this client made. A relaying server's `extra` carries the id of\n * the request it made upstream: it joins `upstreamRequestIds`, nearest first, at every hop.\n */\n static async toApplicationError(opts: {\n response: Response;\n /** Where it failed, for logs - e.g. `[HttpDataSource][read] 404 | /tickets`. */\n context: string;\n rootKey?: string;\n }): Promise<ApplicationError> {\n const { response, context, rootKey } = opts;\n const server = await HttpResponseReader.readError({ response, rootKey });\n const serverText = server.normalized?.text ?? server.message;\n const displayText = serverText ?? `HTTP ${response.status}`;\n\n const extra: Record<string, unknown> = { ...server.extra };\n if (server.requestId) {\n const upstreamRequestId = extra.requestId;\n extra.requestId = server.requestId;\n\n if (upstreamRequestId !== undefined && upstreamRequestId !== server.requestId) {\n const known = Array.isArray(extra.upstreamRequestIds) ? extra.upstreamRequestIds : [];\n extra.upstreamRequestIds = [upstreamRequestId, ...known];\n }\n }\n\n return getError({\n statusCode: response.status,\n message: serverText ? `${context} | ${serverText}` : context,\n messageCode: server.normalized?.code,\n messageArgs: server.normalized?.args,\n extra: Object.keys(extra).length > 0 ? extra : undefined,\n cause: server.details?.cause,\n transform: ({ message }) => ({ ...message, text: displayText }),\n });\n }\n\n /**\n * A body the server marked with `x-response-extra` carries `extra` beside its rows. `body` is what\n * the route answers without extras: the `{ count, data }` envelope when the count was asked for in\n * the body, the rows otherwise. Any other body is returned as it stands - an unmarked object is\n * never unwrapped, so a row that has `data` and `extra` columns of its own is never misread.\n */\n static readExtra(opts: { body: unknown; headers: Pick<Headers, 'has'> }): {\n body: unknown;\n extra?: Record<string, unknown>;\n } {\n const { body, headers } = opts;\n const isMarked = headers.has(HTTP.Headers.RESPONSE_EXTRA);\n\n if (\n !isMarked ||\n !HttpResponseReader.isPlainObject(body) ||\n !HttpResponseReader.isPlainObject(body.extra)\n ) {\n return { body };\n }\n\n const { extra, ...envelope } = body;\n return { body: 'count' in envelope ? envelope : envelope.data, extra: { ...extra } };\n }\n}\n"]}
|
|
@@ -3,7 +3,7 @@ import type { MetadataRegistry as _MetadataRegistry } from '@venizia/ignis-inver
|
|
|
3
3
|
import { Container as DIContainer } from '@venizia/ignis-inversion';
|
|
4
4
|
export declare class Container extends DIContainer {
|
|
5
5
|
logger: ILogger;
|
|
6
|
-
/** Resolved through `BaseHelper
|
|
6
|
+
/** Resolved through `BaseHelper`, which asks `LoggerFactory` (browser-pure, the console by default). A server host gets the provider the application chose, or Winston when it chose none. */
|
|
7
7
|
constructor(opts?: {
|
|
8
8
|
scope: string;
|
|
9
9
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../../../src/helpers/inversion/container.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,KAAK,EAAE,gBAAgB,IAAI,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACtF,OAAO,EAAE,SAAS,IAAI,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGpE,qBAAa,SAAU,SAAQ,WAAW;IACxC,MAAM,EAAE,OAAO,CAAC;IAEhB,
|
|
1
|
+
{"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../../../src/helpers/inversion/container.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,KAAK,EAAE,gBAAgB,IAAI,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACtF,OAAO,EAAE,SAAS,IAAI,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGpE,qBAAa,SAAU,SAAQ,WAAW;IACxC,MAAM,EAAE,OAAO,CAAC;IAEhB,8LAA8L;gBAClL,IAAI,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE;IAK3B,mBAAmB,IAAI,iBAAiB;CAGlD"}
|
|
@@ -2,7 +2,7 @@ import { BaseHelper } from '@venizia/ignis-helpers/core';
|
|
|
2
2
|
import { Container as DIContainer } from '@venizia/ignis-inversion';
|
|
3
3
|
import { MetadataRegistry } from './registry.js';
|
|
4
4
|
export class Container extends DIContainer {
|
|
5
|
-
/** Resolved through `BaseHelper
|
|
5
|
+
/** Resolved through `BaseHelper`, which asks `LoggerFactory` (browser-pure, the console by default). A server host gets the provider the application chose, or Winston when it chose none. */
|
|
6
6
|
constructor(opts) {
|
|
7
7
|
super({ scope: opts?.scope ?? Container.name });
|
|
8
8
|
this.logger = new BaseHelper({ scope: opts?.scope ?? Container.name }).getLogger();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container.js","sourceRoot":"","sources":["../../../../src/helpers/inversion/container.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAEzD,OAAO,EAAE,SAAS,IAAI,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,OAAO,SAAU,SAAQ,WAAW;IAGxC,
|
|
1
|
+
{"version":3,"file":"container.js","sourceRoot":"","sources":["../../../../src/helpers/inversion/container.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAEzD,OAAO,EAAE,SAAS,IAAI,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,OAAO,SAAU,SAAQ,WAAW;IAGxC,8LAA8L;IAC9L,YAAY,IAAwB;QAClC,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC,MAAM,GAAG,IAAI,UAAU,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC;IACrF,CAAC;IAEQ,mBAAmB;QAC1B,OAAO,gBAAgB,CAAC,WAAW,EAAE,CAAC;IACxC,CAAC;CACF","sourcesContent":["import type { ILogger } from '@venizia/ignis-helpers/core';\nimport { BaseHelper } from '@venizia/ignis-helpers/core';\nimport type { MetadataRegistry as _MetadataRegistry } from '@venizia/ignis-inversion';\nimport { Container as DIContainer } from '@venizia/ignis-inversion';\nimport { MetadataRegistry } from './registry';\n\nexport class Container extends DIContainer {\n logger: ILogger;\n\n /** Resolved through `BaseHelper`, which asks `LoggerFactory` (browser-pure, the console by default). A server host gets the provider the application chose, or Winston when it chose none. */\n constructor(opts?: { scope: string }) {\n super({ scope: opts?.scope ?? Container.name });\n this.logger = new BaseHelper({ scope: opts?.scope ?? Container.name }).getLogger();\n }\n\n override getMetadataRegistry(): _MetadataRegistry {\n return MetadataRegistry.getInstance();\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@venizia/ignis-kernel",
|
|
3
|
-
"version": "0.4.7-
|
|
3
|
+
"version": "0.4.7-3",
|
|
4
4
|
"description": "Browser-pure kernel of the IGNIS framework: dependency injection, lifecycle, REST controllers, repository and datasource abstractions, and the authentication and authorization seams. No node builtin and no server-only peer, so the same kernel serves a Bun server and a browser Worker.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"authentication",
|
|
@@ -69,13 +69,13 @@
|
|
|
69
69
|
},
|
|
70
70
|
"dependencies": {
|
|
71
71
|
"@venizia/ignis-filter": "0.4.6-1",
|
|
72
|
-
"@venizia/ignis-helpers": "0.4.7-
|
|
72
|
+
"@venizia/ignis-helpers": "0.4.7-3",
|
|
73
73
|
"@venizia/ignis-inversion": "0.4.6-1",
|
|
74
74
|
"reflect-metadata": "^0.2.2"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
77
|
"@types/bun": "^1.4.3",
|
|
78
|
-
"@venizia/dev-configs": "0.4.7-
|
|
78
|
+
"@venizia/dev-configs": "0.4.7-3",
|
|
79
79
|
"casbin": "^5.51.1",
|
|
80
80
|
"eslint": "^10.13.0",
|
|
81
81
|
"oxlint": "1.89.0",
|