@nage-api/core 1.0.0-beta.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.
Files changed (81) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +141 -0
  3. package/dist/bootstrap/bootstrap.d.ts +48 -0
  4. package/dist/bootstrap/bootstrap.js +255 -0
  5. package/dist/bootstrap/drain.d.ts +48 -0
  6. package/dist/bootstrap/drain.js +113 -0
  7. package/dist/bootstrap/lifecycle.d.ts +30 -0
  8. package/dist/bootstrap/lifecycle.js +64 -0
  9. package/dist/bootstrap/process-guards.d.ts +42 -0
  10. package/dist/bootstrap/process-guards.js +103 -0
  11. package/dist/bootstrap/query-parser.d.ts +34 -0
  12. package/dist/bootstrap/query-parser.js +37 -0
  13. package/dist/bootstrap/shutdown.d.ts +55 -0
  14. package/dist/bootstrap/shutdown.js +182 -0
  15. package/dist/constants.d.ts +32 -0
  16. package/dist/constants.js +48 -0
  17. package/dist/context/active-context.d.ts +23 -0
  18. package/dist/context/active-context.js +34 -0
  19. package/dist/context/request-context.middleware.d.ts +31 -0
  20. package/dist/context/request-context.middleware.js +95 -0
  21. package/dist/context/request-context.service.d.ts +29 -0
  22. package/dist/context/request-context.service.js +67 -0
  23. package/dist/decorators/owner.decorator.d.ts +18 -0
  24. package/dist/decorators/owner.decorator.js +31 -0
  25. package/dist/decorators/public.decorator.d.ts +13 -0
  26. package/dist/decorators/public.decorator.js +23 -0
  27. package/dist/decorators/version.decorators.d.ts +34 -0
  28. package/dist/decorators/version.decorators.js +40 -0
  29. package/dist/errors/catalog.d.ts +149 -0
  30. package/dist/errors/catalog.js +289 -0
  31. package/dist/errors/index.d.ts +3 -0
  32. package/dist/errors/index.js +22 -0
  33. package/dist/errors/nage.error.d.ts +43 -0
  34. package/dist/errors/nage.error.js +45 -0
  35. package/dist/guards/api-version.guard.d.ts +20 -0
  36. package/dist/guards/api-version.guard.js +73 -0
  37. package/dist/http/all-exceptions.filter.d.ts +25 -0
  38. package/dist/http/all-exceptions.filter.js +256 -0
  39. package/dist/http/envelope.d.ts +25 -0
  40. package/dist/http/envelope.js +44 -0
  41. package/dist/http/no-envelope.decorator.d.ts +11 -0
  42. package/dist/http/no-envelope.decorator.js +16 -0
  43. package/dist/http/request-timeout.decorators.d.ts +23 -0
  44. package/dist/http/request-timeout.decorators.js +29 -0
  45. package/dist/http/request-timeout.interceptor.d.ts +28 -0
  46. package/dist/http/request-timeout.interceptor.js +75 -0
  47. package/dist/http/response.interceptor.d.ts +19 -0
  48. package/dist/http/response.interceptor.js +73 -0
  49. package/dist/index.d.ts +38 -0
  50. package/dist/index.js +135 -0
  51. package/dist/job/job.factory.d.ts +29 -0
  52. package/dist/job/job.factory.js +50 -0
  53. package/dist/logging/json.logger.d.ts +23 -0
  54. package/dist/logging/json.logger.js +136 -0
  55. package/dist/logging/nest-logger.adapter.d.ts +20 -0
  56. package/dist/logging/nest-logger.adapter.js +46 -0
  57. package/dist/module/core.module.d.ts +40 -0
  58. package/dist/module/core.module.js +112 -0
  59. package/dist/security/audit.d.ts +42 -0
  60. package/dist/security/audit.js +399 -0
  61. package/dist/security/index.d.ts +15 -0
  62. package/dist/security/index.js +50 -0
  63. package/dist/security/legacy-scan.d.ts +24 -0
  64. package/dist/security/legacy-scan.js +98 -0
  65. package/dist/security/random.d.ts +40 -0
  66. package/dist/security/random.js +87 -0
  67. package/dist/security/rate-limit.decorators.d.ts +24 -0
  68. package/dist/security/rate-limit.decorators.js +25 -0
  69. package/dist/security/rate-limit.guard.d.ts +44 -0
  70. package/dist/security/rate-limit.guard.js +130 -0
  71. package/dist/security/rate-limit.store.d.ts +30 -0
  72. package/dist/security/rate-limit.store.js +63 -0
  73. package/dist/security/redaction.d.ts +54 -0
  74. package/dist/security/redaction.js +146 -0
  75. package/dist/security/tls.d.ts +29 -0
  76. package/dist/security/tls.js +48 -0
  77. package/dist/tokens.d.ts +60 -0
  78. package/dist/tokens.js +89 -0
  79. package/dist/version.d.ts +5 -0
  80. package/dist/version.js +8 -0
  81. package/package.json +77 -0
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ /**
3
+ * The single global response interceptor (PLAN.md §16.1).
4
+ *
5
+ * Controllers `return data`. This wraps it. Nothing in application code touches
6
+ * `res` — the `@Res()` escape hatch used by 18 legacy controllers bypassed the
7
+ * interceptor pipeline entirely and is what made the envelope inconsistent.
8
+ */
9
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
10
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
11
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
12
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
13
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
14
+ };
15
+ var __metadata = (this && this.__metadata) || function (k, v) {
16
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
17
+ };
18
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
19
+ return function (target, key) { decorator(target, key, paramIndex); }
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.ResponseInterceptor = void 0;
23
+ const common_1 = require("@nestjs/common");
24
+ const core_1 = require("@nestjs/core");
25
+ const operators_1 = require("rxjs/operators");
26
+ const constants_js_1 = require("../constants.js");
27
+ const request_context_service_js_1 = require("../context/request-context.service.js");
28
+ const envelope_js_1 = require("./envelope.js");
29
+ let ResponseInterceptor = class ResponseInterceptor {
30
+ reflector;
31
+ context;
32
+ constructor(reflector, context) {
33
+ this.reflector = reflector;
34
+ this.context = context;
35
+ }
36
+ intercept(context, next) {
37
+ // Only HTTP responses carry the envelope; websocket and microservice
38
+ // payloads have their own contracts.
39
+ if (context.getType() !== 'http')
40
+ return next.handle();
41
+ const noEnvelope = this.reflector.getAllAndOverride(constants_js_1.METADATA_KEYS.noEnvelope, [context.getHandler(), context.getClass()]);
42
+ if (noEnvelope === true)
43
+ return next.handle();
44
+ return next.handle().pipe((0, operators_1.map)((data) => this.#wrap(data)));
45
+ }
46
+ #wrap(data) {
47
+ const requestContext = this.context.get();
48
+ const requestId = requestContext?.requestId ?? 'unknown';
49
+ const version = requestContext?.apiVersion;
50
+ if ((0, envelope_js_1.isPaginated)(data)) {
51
+ return (0, envelope_js_1.successEnvelope)(data.records, {
52
+ requestId,
53
+ pagination: data.pagination,
54
+ ...(version === undefined ? {} : { version }),
55
+ });
56
+ }
57
+ // A handler that returns nothing (204, or a delete) still gets a body-shaped
58
+ // envelope with `data: null`, so clients can parse one shape unconditionally.
59
+ return (0, envelope_js_1.successEnvelope)(data === undefined ? null : data, {
60
+ requestId,
61
+ ...(version === undefined ? {} : { version }),
62
+ });
63
+ }
64
+ };
65
+ exports.ResponseInterceptor = ResponseInterceptor;
66
+ exports.ResponseInterceptor = ResponseInterceptor = __decorate([
67
+ (0, common_1.Injectable)(),
68
+ __param(0, (0, common_1.Inject)(core_1.Reflector)),
69
+ __param(1, (0, common_1.Inject)(request_context_service_js_1.RequestContextService)),
70
+ __metadata("design:paramtypes", [core_1.Reflector,
71
+ request_context_service_js_1.RequestContextService])
72
+ ], ResponseInterceptor);
73
+ //# sourceMappingURL=response.interceptor.js.map
@@ -0,0 +1,38 @@
1
+ /**
2
+ * `@nage-api/core` — the small mandatory layer every application depends on
3
+ * (PLAN.md §7.2).
4
+ *
5
+ * Core depends on `@nage-api/contracts` and on nothing else: never on a feature
6
+ * package, never on a project entity. That direction is what the legacy
7
+ * `src/core` inverted, and it is enforced in CI.
8
+ */
9
+ export type * from '@nage-api/contracts';
10
+ export { NAGE_CORE_VERSION, NAGE_MIN_NODE_VERSION } from './version.js';
11
+ export { DEFAULT_REDACTED_FIELDS, DEFAULT_REQUEST_TIMEOUT_MS, API_VERSION_HEADER, CORRELATION_ID_HEADER, DEFAULT_API_VERSION, METADATA_KEYS, REQUEST_ID_HEADER, REQUEST_ID_PATTERN, } from './constants.js';
12
+ export { createToken, keyValueStoreToken, repositoryToken, NAGE_CONFIG, NAGE_LIFECYCLE, NAGE_LOGGER, NAGE_RATE_LIMIT_STORE, NAGE_REQUEST_CONTEXT, NAGE_UNIT_OF_WORK, type Token, } from './tokens.js';
13
+ export { getActiveContext, runWithContext, setContextValue, type MutableRequestContext, } from './context/active-context.js';
14
+ export { RequestContextService } from './context/request-context.service.js';
15
+ export { RequestContextMiddleware, parseApiVersion, resolveRequestId, } from './context/request-context.middleware.js';
16
+ export * from './errors/index.js';
17
+ export { buildMeta, errorEnvelope, isPaginated, successEnvelope, type EnvelopeMetaInput, } from './http/envelope.js';
18
+ export { NoEnvelope } from './http/no-envelope.decorator.js';
19
+ export { ResponseInterceptor } from './http/response.interceptor.js';
20
+ export { AllExceptionsFilter } from './http/all-exceptions.filter.js';
21
+ export { RequestTimeoutInterceptor } from './http/request-timeout.interceptor.js';
22
+ export { RequestTimeout, SkipRequestTimeout } from './http/request-timeout.decorators.js';
23
+ export { Public, isPublicRoute } from './decorators/public.decorator.js';
24
+ export { Owner, OptionalOwner } from './decorators/owner.decorator.js';
25
+ export { BetweenVersions, ForVersion, FromVersion, TillVersion, versionSatisfies, type VersionRule, } from './decorators/version.decorators.js';
26
+ export { ApiVersionGuard } from './guards/api-version.guard.js';
27
+ export { createJob, emptyPage, paginate, type CreateJobInput } from './job/job.factory.js';
28
+ export { JsonLogger } from './logging/json.logger.js';
29
+ export { NestLoggerAdapter } from './logging/nest-logger.adapter.js';
30
+ export * from './security/index.js';
31
+ export { NageCoreModule, buildValidationPipe, type NageCoreModuleOptions, } from './module/core.module.js';
32
+ export { bootstrap, createApplication, resolveCorsOptions, type ApplicationModule, type BootstrapOptions, } from './bootstrap/bootstrap.js';
33
+ export { enableQueryDsl } from './bootstrap/query-parser.js';
34
+ export { LifecycleState, processLifecycle, type LifecyclePhase } from './bootstrap/lifecycle.js';
35
+ export { RequestDrain, requestDrainFor, registerRequestDrain, type DrainMiddleware, type DrainResponseLike, type RequestDrainOptions, } from './bootstrap/drain.js';
36
+ export { installShutdown, shutdownHandleFor, registerShutdownHandle, type ClosableApplication, type ShutdownHandle, type ShutdownOptions, } from './bootstrap/shutdown.js';
37
+ export { installProcessGuards, type DisposeProcessGuards, type FatalKind, type ProcessGuardOptions, } from './bootstrap/process-guards.js';
38
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js ADDED
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ /**
3
+ * `@nage-api/core` — the small mandatory layer every application depends on
4
+ * (PLAN.md §7.2).
5
+ *
6
+ * Core depends on `@nage-api/contracts` and on nothing else: never on a feature
7
+ * package, never on a project entity. That direction is what the legacy
8
+ * `src/core` inverted, and it is enforced in CI.
9
+ */
10
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ var desc = Object.getOwnPropertyDescriptor(m, k);
13
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
+ desc = { enumerable: true, get: function() { return m[k]; } };
15
+ }
16
+ Object.defineProperty(o, k2, desc);
17
+ }) : (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ o[k2] = m[k];
20
+ }));
21
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
22
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.JsonLogger = exports.paginate = exports.emptyPage = exports.createJob = exports.ApiVersionGuard = exports.versionSatisfies = exports.TillVersion = exports.FromVersion = exports.ForVersion = exports.BetweenVersions = exports.OptionalOwner = exports.Owner = exports.isPublicRoute = exports.Public = exports.SkipRequestTimeout = exports.RequestTimeout = exports.RequestTimeoutInterceptor = exports.AllExceptionsFilter = exports.ResponseInterceptor = exports.NoEnvelope = exports.successEnvelope = exports.isPaginated = exports.errorEnvelope = exports.buildMeta = exports.resolveRequestId = exports.parseApiVersion = exports.RequestContextMiddleware = exports.RequestContextService = exports.setContextValue = exports.runWithContext = exports.getActiveContext = exports.NAGE_UNIT_OF_WORK = exports.NAGE_REQUEST_CONTEXT = exports.NAGE_RATE_LIMIT_STORE = exports.NAGE_LOGGER = exports.NAGE_LIFECYCLE = exports.NAGE_CONFIG = exports.repositoryToken = exports.keyValueStoreToken = exports.createToken = exports.REQUEST_ID_PATTERN = exports.REQUEST_ID_HEADER = exports.METADATA_KEYS = exports.DEFAULT_API_VERSION = exports.CORRELATION_ID_HEADER = exports.API_VERSION_HEADER = exports.DEFAULT_REQUEST_TIMEOUT_MS = exports.DEFAULT_REDACTED_FIELDS = exports.NAGE_MIN_NODE_VERSION = exports.NAGE_CORE_VERSION = void 0;
26
+ exports.installProcessGuards = exports.registerShutdownHandle = exports.shutdownHandleFor = exports.installShutdown = exports.registerRequestDrain = exports.requestDrainFor = exports.RequestDrain = exports.processLifecycle = exports.LifecycleState = exports.enableQueryDsl = exports.resolveCorsOptions = exports.createApplication = exports.bootstrap = exports.buildValidationPipe = exports.NageCoreModule = exports.NestLoggerAdapter = void 0;
27
+ var version_js_1 = require("./version.js");
28
+ Object.defineProperty(exports, "NAGE_CORE_VERSION", { enumerable: true, get: function () { return version_js_1.NAGE_CORE_VERSION; } });
29
+ Object.defineProperty(exports, "NAGE_MIN_NODE_VERSION", { enumerable: true, get: function () { return version_js_1.NAGE_MIN_NODE_VERSION; } });
30
+ // Configuration surface consumed by bootstrap; the types themselves live in
31
+ // @nage-api/contracts and are re-exported above. @nage-api/config produces a value.
32
+ var constants_js_1 = require("./constants.js");
33
+ Object.defineProperty(exports, "DEFAULT_REDACTED_FIELDS", { enumerable: true, get: function () { return constants_js_1.DEFAULT_REDACTED_FIELDS; } });
34
+ Object.defineProperty(exports, "DEFAULT_REQUEST_TIMEOUT_MS", { enumerable: true, get: function () { return constants_js_1.DEFAULT_REQUEST_TIMEOUT_MS; } });
35
+ Object.defineProperty(exports, "API_VERSION_HEADER", { enumerable: true, get: function () { return constants_js_1.API_VERSION_HEADER; } });
36
+ Object.defineProperty(exports, "CORRELATION_ID_HEADER", { enumerable: true, get: function () { return constants_js_1.CORRELATION_ID_HEADER; } });
37
+ Object.defineProperty(exports, "DEFAULT_API_VERSION", { enumerable: true, get: function () { return constants_js_1.DEFAULT_API_VERSION; } });
38
+ Object.defineProperty(exports, "METADATA_KEYS", { enumerable: true, get: function () { return constants_js_1.METADATA_KEYS; } });
39
+ Object.defineProperty(exports, "REQUEST_ID_HEADER", { enumerable: true, get: function () { return constants_js_1.REQUEST_ID_HEADER; } });
40
+ Object.defineProperty(exports, "REQUEST_ID_PATTERN", { enumerable: true, get: function () { return constants_js_1.REQUEST_ID_PATTERN; } });
41
+ // DI tokens — how feature packages collaborate without importing each other.
42
+ var tokens_js_1 = require("./tokens.js");
43
+ Object.defineProperty(exports, "createToken", { enumerable: true, get: function () { return tokens_js_1.createToken; } });
44
+ Object.defineProperty(exports, "keyValueStoreToken", { enumerable: true, get: function () { return tokens_js_1.keyValueStoreToken; } });
45
+ Object.defineProperty(exports, "repositoryToken", { enumerable: true, get: function () { return tokens_js_1.repositoryToken; } });
46
+ Object.defineProperty(exports, "NAGE_CONFIG", { enumerable: true, get: function () { return tokens_js_1.NAGE_CONFIG; } });
47
+ Object.defineProperty(exports, "NAGE_LIFECYCLE", { enumerable: true, get: function () { return tokens_js_1.NAGE_LIFECYCLE; } });
48
+ Object.defineProperty(exports, "NAGE_LOGGER", { enumerable: true, get: function () { return tokens_js_1.NAGE_LOGGER; } });
49
+ Object.defineProperty(exports, "NAGE_RATE_LIMIT_STORE", { enumerable: true, get: function () { return tokens_js_1.NAGE_RATE_LIMIT_STORE; } });
50
+ Object.defineProperty(exports, "NAGE_REQUEST_CONTEXT", { enumerable: true, get: function () { return tokens_js_1.NAGE_REQUEST_CONTEXT; } });
51
+ Object.defineProperty(exports, "NAGE_UNIT_OF_WORK", { enumerable: true, get: function () { return tokens_js_1.NAGE_UNIT_OF_WORK; } });
52
+ // Request context (CLS).
53
+ var active_context_js_1 = require("./context/active-context.js");
54
+ Object.defineProperty(exports, "getActiveContext", { enumerable: true, get: function () { return active_context_js_1.getActiveContext; } });
55
+ Object.defineProperty(exports, "runWithContext", { enumerable: true, get: function () { return active_context_js_1.runWithContext; } });
56
+ Object.defineProperty(exports, "setContextValue", { enumerable: true, get: function () { return active_context_js_1.setContextValue; } });
57
+ var request_context_service_js_1 = require("./context/request-context.service.js");
58
+ Object.defineProperty(exports, "RequestContextService", { enumerable: true, get: function () { return request_context_service_js_1.RequestContextService; } });
59
+ var request_context_middleware_js_1 = require("./context/request-context.middleware.js");
60
+ Object.defineProperty(exports, "RequestContextMiddleware", { enumerable: true, get: function () { return request_context_middleware_js_1.RequestContextMiddleware; } });
61
+ Object.defineProperty(exports, "parseApiVersion", { enumerable: true, get: function () { return request_context_middleware_js_1.parseApiVersion; } });
62
+ Object.defineProperty(exports, "resolveRequestId", { enumerable: true, get: function () { return request_context_middleware_js_1.resolveRequestId; } });
63
+ // Typed error catalog.
64
+ __exportStar(require("./errors/index.js"), exports);
65
+ // Response envelope, interceptor and exception filter.
66
+ var envelope_js_1 = require("./http/envelope.js");
67
+ Object.defineProperty(exports, "buildMeta", { enumerable: true, get: function () { return envelope_js_1.buildMeta; } });
68
+ Object.defineProperty(exports, "errorEnvelope", { enumerable: true, get: function () { return envelope_js_1.errorEnvelope; } });
69
+ Object.defineProperty(exports, "isPaginated", { enumerable: true, get: function () { return envelope_js_1.isPaginated; } });
70
+ Object.defineProperty(exports, "successEnvelope", { enumerable: true, get: function () { return envelope_js_1.successEnvelope; } });
71
+ var no_envelope_decorator_js_1 = require("./http/no-envelope.decorator.js");
72
+ Object.defineProperty(exports, "NoEnvelope", { enumerable: true, get: function () { return no_envelope_decorator_js_1.NoEnvelope; } });
73
+ var response_interceptor_js_1 = require("./http/response.interceptor.js");
74
+ Object.defineProperty(exports, "ResponseInterceptor", { enumerable: true, get: function () { return response_interceptor_js_1.ResponseInterceptor; } });
75
+ var all_exceptions_filter_js_1 = require("./http/all-exceptions.filter.js");
76
+ Object.defineProperty(exports, "AllExceptionsFilter", { enumerable: true, get: function () { return all_exceptions_filter_js_1.AllExceptionsFilter; } });
77
+ // Request timeout (§21): on by default, per-route overrides for the routes whose
78
+ // duration is the caller's business.
79
+ var request_timeout_interceptor_js_1 = require("./http/request-timeout.interceptor.js");
80
+ Object.defineProperty(exports, "RequestTimeoutInterceptor", { enumerable: true, get: function () { return request_timeout_interceptor_js_1.RequestTimeoutInterceptor; } });
81
+ var request_timeout_decorators_js_1 = require("./http/request-timeout.decorators.js");
82
+ Object.defineProperty(exports, "RequestTimeout", { enumerable: true, get: function () { return request_timeout_decorators_js_1.RequestTimeout; } });
83
+ Object.defineProperty(exports, "SkipRequestTimeout", { enumerable: true, get: function () { return request_timeout_decorators_js_1.SkipRequestTimeout; } });
84
+ // Base decorators and guards.
85
+ var public_decorator_js_1 = require("./decorators/public.decorator.js");
86
+ Object.defineProperty(exports, "Public", { enumerable: true, get: function () { return public_decorator_js_1.Public; } });
87
+ Object.defineProperty(exports, "isPublicRoute", { enumerable: true, get: function () { return public_decorator_js_1.isPublicRoute; } });
88
+ var owner_decorator_js_1 = require("./decorators/owner.decorator.js");
89
+ Object.defineProperty(exports, "Owner", { enumerable: true, get: function () { return owner_decorator_js_1.Owner; } });
90
+ Object.defineProperty(exports, "OptionalOwner", { enumerable: true, get: function () { return owner_decorator_js_1.OptionalOwner; } });
91
+ var version_decorators_js_1 = require("./decorators/version.decorators.js");
92
+ Object.defineProperty(exports, "BetweenVersions", { enumerable: true, get: function () { return version_decorators_js_1.BetweenVersions; } });
93
+ Object.defineProperty(exports, "ForVersion", { enumerable: true, get: function () { return version_decorators_js_1.ForVersion; } });
94
+ Object.defineProperty(exports, "FromVersion", { enumerable: true, get: function () { return version_decorators_js_1.FromVersion; } });
95
+ Object.defineProperty(exports, "TillVersion", { enumerable: true, get: function () { return version_decorators_js_1.TillVersion; } });
96
+ Object.defineProperty(exports, "versionSatisfies", { enumerable: true, get: function () { return version_decorators_js_1.versionSatisfies; } });
97
+ var api_version_guard_js_1 = require("./guards/api-version.guard.js");
98
+ Object.defineProperty(exports, "ApiVersionGuard", { enumerable: true, get: function () { return api_version_guard_js_1.ApiVersionGuard; } });
99
+ // Job / pagination helpers.
100
+ var job_factory_js_1 = require("./job/job.factory.js");
101
+ Object.defineProperty(exports, "createJob", { enumerable: true, get: function () { return job_factory_js_1.createJob; } });
102
+ Object.defineProperty(exports, "emptyPage", { enumerable: true, get: function () { return job_factory_js_1.emptyPage; } });
103
+ Object.defineProperty(exports, "paginate", { enumerable: true, get: function () { return job_factory_js_1.paginate; } });
104
+ // Logging.
105
+ var json_logger_js_1 = require("./logging/json.logger.js");
106
+ Object.defineProperty(exports, "JsonLogger", { enumerable: true, get: function () { return json_logger_js_1.JsonLogger; } });
107
+ var nest_logger_adapter_js_1 = require("./logging/nest-logger.adapter.js");
108
+ Object.defineProperty(exports, "NestLoggerAdapter", { enumerable: true, get: function () { return nest_logger_adapter_js_1.NestLoggerAdapter; } });
109
+ // Security baseline (§12): CSPRNG, redaction, TLS policy, throttling, audit.
110
+ __exportStar(require("./security/index.js"), exports);
111
+ // Module and bootstrap.
112
+ var core_module_js_1 = require("./module/core.module.js");
113
+ Object.defineProperty(exports, "NageCoreModule", { enumerable: true, get: function () { return core_module_js_1.NageCoreModule; } });
114
+ Object.defineProperty(exports, "buildValidationPipe", { enumerable: true, get: function () { return core_module_js_1.buildValidationPipe; } });
115
+ var bootstrap_js_1 = require("./bootstrap/bootstrap.js");
116
+ Object.defineProperty(exports, "bootstrap", { enumerable: true, get: function () { return bootstrap_js_1.bootstrap; } });
117
+ Object.defineProperty(exports, "createApplication", { enumerable: true, get: function () { return bootstrap_js_1.createApplication; } });
118
+ Object.defineProperty(exports, "resolveCorsOptions", { enumerable: true, get: function () { return bootstrap_js_1.resolveCorsOptions; } });
119
+ var query_parser_js_1 = require("./bootstrap/query-parser.js");
120
+ Object.defineProperty(exports, "enableQueryDsl", { enumerable: true, get: function () { return query_parser_js_1.enableQueryDsl; } });
121
+ // Production lifecycle (§21): ordered drain, readiness phase, fatal-error policy.
122
+ var lifecycle_js_1 = require("./bootstrap/lifecycle.js");
123
+ Object.defineProperty(exports, "LifecycleState", { enumerable: true, get: function () { return lifecycle_js_1.LifecycleState; } });
124
+ Object.defineProperty(exports, "processLifecycle", { enumerable: true, get: function () { return lifecycle_js_1.processLifecycle; } });
125
+ var drain_js_1 = require("./bootstrap/drain.js");
126
+ Object.defineProperty(exports, "RequestDrain", { enumerable: true, get: function () { return drain_js_1.RequestDrain; } });
127
+ Object.defineProperty(exports, "requestDrainFor", { enumerable: true, get: function () { return drain_js_1.requestDrainFor; } });
128
+ Object.defineProperty(exports, "registerRequestDrain", { enumerable: true, get: function () { return drain_js_1.registerRequestDrain; } });
129
+ var shutdown_js_1 = require("./bootstrap/shutdown.js");
130
+ Object.defineProperty(exports, "installShutdown", { enumerable: true, get: function () { return shutdown_js_1.installShutdown; } });
131
+ Object.defineProperty(exports, "shutdownHandleFor", { enumerable: true, get: function () { return shutdown_js_1.shutdownHandleFor; } });
132
+ Object.defineProperty(exports, "registerShutdownHandle", { enumerable: true, get: function () { return shutdown_js_1.registerShutdownHandle; } });
133
+ var process_guards_js_1 = require("./bootstrap/process-guards.js");
134
+ Object.defineProperty(exports, "installProcessGuards", { enumerable: true, get: function () { return process_guards_js_1.installProcessGuards; } });
135
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Runtime helpers for the `Job` / `Paginated` contracts (PLAN.md §13, §14.1).
3
+ *
4
+ * The `Job` work unit and its lifecycle hooks are the legacy framework's best
5
+ * idea; what undercut them was `body: any` / `records: any[]`. `@nage-api/data`
6
+ * (Phase 5) builds every job through these helpers so a job is typed against its
7
+ * entity from the moment it is created.
8
+ */
9
+ import type { DeepPartial, Job, JobAction, Paginated, PaginationMeta, RequestContext, UnknownRecord } from '@nage-api/contracts';
10
+ export interface CreateJobInput<TEntity, TBody, TParams extends UnknownRecord> {
11
+ readonly action: JobAction;
12
+ readonly params?: TParams;
13
+ readonly query?: Job<TEntity, TBody, TParams>['query'];
14
+ readonly body?: TBody;
15
+ readonly id?: Job<TEntity, TBody, TParams>['id'];
16
+ readonly deleteMode?: Job<TEntity, TBody, TParams>['deleteMode'];
17
+ /** Defaults to the ambient request context. */
18
+ readonly context?: RequestContext;
19
+ }
20
+ /**
21
+ * Build a job, defaulting the owner and context from the active request — the
22
+ * reason audit columns and ownership scoping need no plumbing at call sites.
23
+ */
24
+ export declare function createJob<TEntity, TBody = DeepPartial<TEntity>, TParams extends UnknownRecord = UnknownRecord>(input: CreateJobInput<TEntity, TBody, TParams>): Job<TEntity, TBody, TParams>;
25
+ /** Assemble the standard page shape returned by every repository. */
26
+ export declare function paginate<TEntity>(records: readonly TEntity[], pagination: PaginationMeta): Paginated<TEntity>;
27
+ /** An empty page — the correct answer for a filtered query with no matches. */
28
+ export declare function emptyPage<TEntity>(offset?: number, limit?: number): Paginated<TEntity>;
29
+ //# sourceMappingURL=job.factory.d.ts.map
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ /**
3
+ * Runtime helpers for the `Job` / `Paginated` contracts (PLAN.md §13, §14.1).
4
+ *
5
+ * The `Job` work unit and its lifecycle hooks are the legacy framework's best
6
+ * idea; what undercut them was `body: any` / `records: any[]`. `@nage-api/data`
7
+ * (Phase 5) builds every job through these helpers so a job is typed against its
8
+ * entity from the moment it is created.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.createJob = createJob;
12
+ exports.paginate = paginate;
13
+ exports.emptyPage = emptyPage;
14
+ const active_context_js_1 = require("../context/active-context.js");
15
+ const catalog_js_1 = require("../errors/catalog.js");
16
+ /**
17
+ * Build a job, defaulting the owner and context from the active request — the
18
+ * reason audit columns and ownership scoping need no plumbing at call sites.
19
+ */
20
+ function createJob(input) {
21
+ const context = input.context ?? (0, active_context_js_1.getActiveContext)();
22
+ if (context === undefined) {
23
+ throw new catalog_js_1.InternalError({
24
+ detail: 'A job needs a request context',
25
+ meta: {
26
+ action: input.action,
27
+ hint: 'Create the job inside a request, or pass `context` explicitly for background work.',
28
+ },
29
+ });
30
+ }
31
+ return {
32
+ action: input.action,
33
+ params: input.params ?? {},
34
+ query: input.query ?? {},
35
+ body: input.body ?? {},
36
+ context,
37
+ ...(input.id === undefined ? {} : { id: input.id }),
38
+ ...(context.user === undefined ? {} : { owner: context.user }),
39
+ ...(input.deleteMode === undefined ? {} : { deleteMode: input.deleteMode }),
40
+ };
41
+ }
42
+ /** Assemble the standard page shape returned by every repository. */
43
+ function paginate(records, pagination) {
44
+ return { records, pagination };
45
+ }
46
+ /** An empty page — the correct answer for a filtered query with no matches. */
47
+ function emptyPage(offset = 0, limit = 0) {
48
+ return { records: [], pagination: { offset, limit, count: 0 } };
49
+ }
50
+ //# sourceMappingURL=job.factory.js.map
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Minimal structured logger (PLAN.md §18).
3
+ *
4
+ * Newline-delimited JSON to stdout, with the correlation id pulled from the
5
+ * ambient context so no caller has to remember to pass it, and configured
6
+ * fields redacted before anything is written. `@nage-api/observability` (Phase 8)
7
+ * replaces this with pino behind the same `LoggerPort` — nothing else changes.
8
+ */
9
+ import type { LogFields, LoggerPort, NageCoreConfig } from '@nage-api/contracts';
10
+ import { RequestContextService } from '../context/request-context.service.js';
11
+ export declare class JsonLogger implements LoggerPort {
12
+ #private;
13
+ private readonly context?;
14
+ constructor(context?: RequestContextService | undefined, config?: NageCoreConfig);
15
+ trace(message: string, fields?: LogFields): void;
16
+ debug(message: string, fields?: LogFields): void;
17
+ info(message: string, fields?: LogFields): void;
18
+ warn(message: string, fields?: LogFields): void;
19
+ error(message: string, fields?: LogFields): void;
20
+ fatal(message: string, fields?: LogFields): void;
21
+ child(bindings: LogFields): LoggerPort;
22
+ }
23
+ //# sourceMappingURL=json.logger.d.ts.map
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ /**
3
+ * Minimal structured logger (PLAN.md §18).
4
+ *
5
+ * Newline-delimited JSON to stdout, with the correlation id pulled from the
6
+ * ambient context so no caller has to remember to pass it, and configured
7
+ * fields redacted before anything is written. `@nage-api/observability` (Phase 8)
8
+ * replaces this with pino behind the same `LoggerPort` — nothing else changes.
9
+ */
10
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
11
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
12
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
13
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
14
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
15
+ };
16
+ var __metadata = (this && this.__metadata) || function (k, v) {
17
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
18
+ };
19
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
20
+ return function (target, key) { decorator(target, key, paramIndex); }
21
+ };
22
+ var JsonLogger_1;
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.JsonLogger = void 0;
25
+ const common_1 = require("@nestjs/common");
26
+ const request_context_service_js_1 = require("../context/request-context.service.js");
27
+ const redaction_js_1 = require("../security/redaction.js");
28
+ const tokens_js_1 = require("../tokens.js");
29
+ const LEVEL_ORDER = {
30
+ trace: 10,
31
+ debug: 20,
32
+ info: 30,
33
+ warn: 40,
34
+ error: 50,
35
+ fatal: 60,
36
+ };
37
+ let JsonLogger = JsonLogger_1 = class JsonLogger {
38
+ context;
39
+ #minimum;
40
+ #redacted;
41
+ #json;
42
+ #config;
43
+ /** Set only via `child()`; not a constructor parameter, which Nest would try to inject. */
44
+ #bindings = {};
45
+ constructor(context, config) {
46
+ this.context = context;
47
+ this.#minimum = LEVEL_ORDER[config?.logging?.level ?? 'info'];
48
+ this.#redacted = (0, redaction_js_1.redactionSet)(config?.logging?.redact ?? []);
49
+ this.#json = config?.logging?.json ?? config?.app.environment !== 'development';
50
+ this.#config = config;
51
+ }
52
+ trace(message, fields) {
53
+ this.#write('trace', message, fields);
54
+ }
55
+ debug(message, fields) {
56
+ this.#write('debug', message, fields);
57
+ }
58
+ info(message, fields) {
59
+ this.#write('info', message, fields);
60
+ }
61
+ warn(message, fields) {
62
+ this.#write('warn', message, fields);
63
+ }
64
+ error(message, fields) {
65
+ this.#write('error', message, fields);
66
+ }
67
+ fatal(message, fields) {
68
+ this.#write('fatal', message, fields);
69
+ }
70
+ child(bindings) {
71
+ const logger = new JsonLogger_1(this.context, this.#config);
72
+ logger.#bindings = { ...this.#bindings, ...bindings };
73
+ return logger;
74
+ }
75
+ #write(level, message, fields = {}) {
76
+ if (LEVEL_ORDER[level] < this.#minimum)
77
+ return;
78
+ const context = this.context?.get();
79
+ const scrubbed = (0, redaction_js_1.redact)(fields, this.#redacted);
80
+ const entry = {
81
+ level,
82
+ time: new Date().toISOString(),
83
+ message,
84
+ ...this.#bindings,
85
+ ...(context === undefined
86
+ ? {}
87
+ : {
88
+ requestId: context.requestId,
89
+ ...(context.user === undefined ? {} : { userId: context.user.id }),
90
+ ...(context.tenantId === undefined ? {} : { tenantId: context.tenantId }),
91
+ }),
92
+ ...scrubbed,
93
+ };
94
+ // The pretty line gets the *scrubbed* fields, not the originals. It used to
95
+ // print `fields`, so `logging.json: false` — the documented setting for
96
+ // human-readable output, and the default outside production — wrote
97
+ // passwords and bearer tokens in clear.
98
+ const fallback = { level, time: entry.time, message };
99
+ const line = this.#json
100
+ ? safeStringify(entry, fallback)
101
+ : `${entry.time} ${level.toUpperCase().padEnd(5)} ${message} ${safeStringify(scrubbed, {})}`;
102
+ // Written directly rather than through console so the stream stays a single
103
+ // newline-delimited JSON document, exactly as a log shipper expects.
104
+ const stream = LEVEL_ORDER[level] >= LEVEL_ORDER.error ? process.stderr : process.stdout;
105
+ stream.write(`${line}\n`);
106
+ }
107
+ };
108
+ exports.JsonLogger = JsonLogger;
109
+ exports.JsonLogger = JsonLogger = JsonLogger_1 = __decorate([
110
+ (0, common_1.Injectable)(),
111
+ __param(0, (0, common_1.Optional)()),
112
+ __param(0, (0, common_1.Inject)(request_context_service_js_1.RequestContextService)),
113
+ __param(1, (0, common_1.Optional)()),
114
+ __param(1, (0, common_1.Inject)(tokens_js_1.NAGE_CONFIG)),
115
+ __metadata("design:paramtypes", [request_context_service_js_1.RequestContextService, Object])
116
+ ], JsonLogger);
117
+ /**
118
+ * A log call must never be the thing that fails a request.
119
+ *
120
+ * `redact` already replaces cycles, but a field can still carry a getter that
121
+ * throws or a `toJSON` that does, and `JSON.stringify` propagates both. The
122
+ * fallback keeps the level, time and message — what an operator needs in order
123
+ * to find the request — and records why the fields are missing.
124
+ */
125
+ function safeStringify(entry, fallback) {
126
+ try {
127
+ return JSON.stringify(entry);
128
+ }
129
+ catch (error) {
130
+ return JSON.stringify({
131
+ ...fallback,
132
+ fieldsError: error instanceof Error ? error.message : String(error),
133
+ });
134
+ }
135
+ }
136
+ //# sourceMappingURL=json.logger.js.map
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Bridges Nest's internal `LoggerService` onto our `LoggerPort` (PLAN.md §18).
3
+ *
4
+ * Without this, a process emits two log formats: Nest's coloured boot lines and
5
+ * the framework's JSON. One structured stream is the whole point — a log shipper
6
+ * should never have to parse two grammars from one stdout.
7
+ */
8
+ import type { LoggerService } from '@nestjs/common';
9
+ import type { LoggerPort } from '@nage-api/contracts';
10
+ export declare class NestLoggerAdapter implements LoggerService {
11
+ private readonly logger;
12
+ constructor(logger: LoggerPort);
13
+ log(message: unknown, ...optional: unknown[]): void;
14
+ error(message: unknown, ...optional: unknown[]): void;
15
+ warn(message: unknown, ...optional: unknown[]): void;
16
+ debug(message: unknown, ...optional: unknown[]): void;
17
+ verbose(message: unknown, ...optional: unknown[]): void;
18
+ fatal(message: unknown, ...optional: unknown[]): void;
19
+ }
20
+ //# sourceMappingURL=nest-logger.adapter.d.ts.map
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ /**
3
+ * Bridges Nest's internal `LoggerService` onto our `LoggerPort` (PLAN.md §18).
4
+ *
5
+ * Without this, a process emits two log formats: Nest's coloured boot lines and
6
+ * the framework's JSON. One structured stream is the whole point — a log shipper
7
+ * should never have to parse two grammars from one stdout.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.NestLoggerAdapter = void 0;
11
+ function fields(context, extra = {}) {
12
+ return typeof context === 'string' ? { context, ...extra } : extra;
13
+ }
14
+ function messageOf(message) {
15
+ return typeof message === 'string' ? message : JSON.stringify(message);
16
+ }
17
+ class NestLoggerAdapter {
18
+ logger;
19
+ constructor(logger) {
20
+ this.logger = logger;
21
+ }
22
+ log(message, ...optional) {
23
+ this.logger.info(messageOf(message), fields(optional[0]));
24
+ }
25
+ error(message, ...optional) {
26
+ const [trace, context] = optional;
27
+ this.logger.error(messageOf(message), {
28
+ ...fields(context ?? trace),
29
+ ...(typeof trace === 'string' ? { stack: trace } : {}),
30
+ });
31
+ }
32
+ warn(message, ...optional) {
33
+ this.logger.warn(messageOf(message), fields(optional[0]));
34
+ }
35
+ debug(message, ...optional) {
36
+ this.logger.debug(messageOf(message), fields(optional[0]));
37
+ }
38
+ verbose(message, ...optional) {
39
+ this.logger.trace(messageOf(message), fields(optional[0]));
40
+ }
41
+ fatal(message, ...optional) {
42
+ this.logger.fatal(messageOf(message), fields(optional[0]));
43
+ }
44
+ }
45
+ exports.NestLoggerAdapter = NestLoggerAdapter;
46
+ //# sourceMappingURL=nest-logger.adapter.js.map
@@ -0,0 +1,40 @@
1
+ /**
2
+ * `NageCoreModule.forRoot(config)` — the one module every application imports
3
+ * (PLAN.md §7.3).
4
+ *
5
+ * Registering the interceptor, filter and guard as providers (rather than
6
+ * `app.useGlobal*`) keeps them inside the DI container, so they can inject the
7
+ * context and the logger, and so tests get the same wiring as production.
8
+ */
9
+ import { ValidationPipe, type DynamicModule, type MiddlewareConsumer, type NestModule } from '@nestjs/common';
10
+ import type { NageCoreConfig, RateLimitStore } from '@nage-api/contracts';
11
+ /**
12
+ * Validation defaults (§16.2). `forbidNonWhitelisted` means an unexpected
13
+ * property is an error rather than something silently dropped — a mass-assignment
14
+ * guard, not a style preference.
15
+ */
16
+ export declare function buildValidationPipe(config: NageCoreConfig): ValidationPipe;
17
+ /**
18
+ * Wiring that is a decision rather than configuration, so it does not belong in
19
+ * `NageCoreConfig` — a `NageCoreConfig` is data, loadable from a file or an
20
+ * environment, and a store is an object with a connection.
21
+ */
22
+ export interface NageCoreModuleOptions {
23
+ /**
24
+ * Counter store behind the global throttle (§12). Defaults to
25
+ * `MemoryRateLimitStore`, which counts **per process** — so with the default,
26
+ * a limit of N across M instances is really N×M. A multi-instance deployment
27
+ * passes a shared implementation here.
28
+ *
29
+ * Supplying it from the application module instead does not work and is worth
30
+ * saying explicitly: `forRoot` binds `NAGE_RATE_LIMIT_STORE` inside this
31
+ * module, and `RateLimitGuard` resolves it from this module's injector, so an
32
+ * app-level provider for the same token is simply not the one the guard sees.
33
+ */
34
+ readonly rateLimitStore?: RateLimitStore;
35
+ }
36
+ export declare class NageCoreModule implements NestModule {
37
+ static forRoot(config: NageCoreConfig, options?: NageCoreModuleOptions): DynamicModule;
38
+ configure(consumer: MiddlewareConsumer): void;
39
+ }
40
+ //# sourceMappingURL=core.module.d.ts.map