@tstdl/base 0.93.1 → 0.93.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.
Files changed (181) hide show
  1. package/api/server/api-request-token.provider.d.ts +5 -3
  2. package/api/server/api-request-token.provider.js +12 -4
  3. package/api/server/gateway.d.ts +1 -9
  4. package/api/server/gateway.js +67 -36
  5. package/api/types.d.ts +5 -1
  6. package/application/application.d.ts +2 -0
  7. package/application/application.js +3 -1
  8. package/application/providers.d.ts +1 -1
  9. package/application/providers.js +1 -1
  10. package/audit/audit.model.d.ts +106 -6
  11. package/audit/audit.model.js +156 -13
  12. package/audit/auditor.d.ts +115 -30
  13. package/audit/auditor.js +160 -19
  14. package/audit/drizzle/0000_bored_stick.sql +26 -0
  15. package/audit/drizzle/meta/0000_snapshot.json +195 -0
  16. package/audit/drizzle/meta/_journal.json +13 -0
  17. package/audit/drizzle.config.d.ts +2 -0
  18. package/audit/drizzle.config.js +11 -0
  19. package/audit/index.d.ts +3 -1
  20. package/audit/index.js +3 -1
  21. package/audit/module.d.ts +22 -0
  22. package/audit/module.js +33 -0
  23. package/audit/schemas.d.ts +6 -0
  24. package/audit/schemas.js +8 -0
  25. package/audit/types.d.ts +2 -1
  26. package/audit/types.js +2 -1
  27. package/authentication/models/authentication-credentials.model.js +1 -2
  28. package/authentication/models/authentication-session.model.d.ts +2 -2
  29. package/authentication/models/authentication-session.model.js +3 -5
  30. package/authentication/models/index.d.ts +0 -1
  31. package/authentication/models/index.js +0 -1
  32. package/authentication/server/authentication-api-request-token.provider.d.ts +2 -2
  33. package/authentication/server/authentication-api-request-token.provider.js +8 -5
  34. package/authentication/server/authentication.api-controller.d.ts +8 -8
  35. package/authentication/server/authentication.api-controller.js +16 -16
  36. package/authentication/server/authentication.audit.d.ts +34 -0
  37. package/authentication/server/authentication.audit.js +1 -0
  38. package/authentication/server/authentication.service.d.ts +19 -10
  39. package/authentication/server/authentication.service.js +158 -43
  40. package/authentication/server/drizzle.config.js +1 -1
  41. package/authentication/server/index.d.ts +1 -0
  42. package/authentication/server/index.js +1 -0
  43. package/authentication/server/module.d.ts +1 -1
  44. package/authentication/{models → server}/schemas.d.ts +2 -3
  45. package/authentication/{models → server}/schemas.js +2 -3
  46. package/constants.d.ts +1 -0
  47. package/constants.js +1 -0
  48. package/document-management/api/document-management.api.d.ts +74 -74
  49. package/document-management/models/document-assignment-scope.model.d.ts +1 -2
  50. package/document-management/models/document-assignment-scope.model.js +4 -6
  51. package/document-management/models/document-assignment-task.model.d.ts +1 -2
  52. package/document-management/models/document-assignment-task.model.js +3 -5
  53. package/document-management/models/document-category.model.d.ts +1 -2
  54. package/document-management/models/document-category.model.js +3 -4
  55. package/document-management/models/document-collection-assignment.model.d.ts +1 -2
  56. package/document-management/models/document-collection-assignment.model.js +5 -7
  57. package/document-management/models/document-collection.model.d.ts +1 -2
  58. package/document-management/models/document-collection.model.js +3 -4
  59. package/document-management/models/document-management-table.d.ts +1 -1
  60. package/document-management/models/document-management-table.js +1 -1
  61. package/document-management/models/document-property-value.model.d.ts +1 -2
  62. package/document-management/models/document-property-value.model.js +5 -8
  63. package/document-management/models/document-property.model.d.ts +1 -2
  64. package/document-management/models/document-property.model.js +2 -3
  65. package/document-management/models/document-request-collection-assignment.model.d.ts +1 -2
  66. package/document-management/models/document-request-collection-assignment.model.js +4 -6
  67. package/document-management/models/document-request-template.d.ts +1 -2
  68. package/document-management/models/document-request-template.js +4 -6
  69. package/document-management/models/document-request.model.d.ts +1 -1
  70. package/document-management/models/document-request.model.js +4 -5
  71. package/document-management/models/document-requests-template.d.ts +1 -1
  72. package/document-management/models/document-requests-template.js +2 -3
  73. package/document-management/models/document-tag-assignment.model.d.ts +1 -2
  74. package/document-management/models/document-tag-assignment.model.js +4 -6
  75. package/document-management/models/document-tag.model.d.ts +1 -1
  76. package/document-management/models/document-tag.model.js +2 -3
  77. package/document-management/models/document-type-property.model.d.ts +1 -2
  78. package/document-management/models/document-type-property.model.js +4 -6
  79. package/document-management/models/document-type-validation.model.d.ts +1 -2
  80. package/document-management/models/document-type-validation.model.js +4 -6
  81. package/document-management/models/document-type.model.d.ts +1 -2
  82. package/document-management/models/document-type.model.js +3 -5
  83. package/document-management/models/document-validation-definition.model.d.ts +1 -2
  84. package/document-management/models/document-validation-definition.model.js +3 -4
  85. package/document-management/models/document-validation-execution-related-document.model.d.ts +1 -2
  86. package/document-management/models/document-validation-execution-related-document.model.js +4 -6
  87. package/document-management/models/document-validation-execution.model.d.ts +1 -2
  88. package/document-management/models/document-validation-execution.model.js +6 -8
  89. package/document-management/models/document-workflow.model.d.ts +1 -2
  90. package/document-management/models/document-workflow.model.js +5 -7
  91. package/document-management/models/document.model.d.ts +1 -2
  92. package/document-management/models/document.model.js +5 -7
  93. package/document-management/server/api/document-management.api.js +1 -1
  94. package/document-management/server/module.d.ts +1 -1
  95. package/document-management/server/module.js +1 -1
  96. package/document-management/server/schemas.d.ts +1 -1
  97. package/document-management/server/schemas.js +1 -1
  98. package/document-management/server/services/document-category-type.service.d.ts +2 -2
  99. package/document-management/server/services/document-category-type.service.js +1 -2
  100. package/document-management/server/services/document-collection.service.d.ts +1 -1
  101. package/document-management/server/services/document-collection.service.js +1 -2
  102. package/document-management/server/services/document-management.service.js +6 -6
  103. package/document-management/server/services/document-property.service.d.ts +1 -1
  104. package/document-management/server/services/document-property.service.js +1 -2
  105. package/document-management/server/services/document-validation.service.js +2 -2
  106. package/document-management/server/services/document-workflow.service.d.ts +2 -2
  107. package/document-management/server/services/document-workflow.service.js +1 -2
  108. package/document-management/server/services/document.service.d.ts +1 -1
  109. package/document-management/server/services/document.service.js +1 -2
  110. package/document-management/server/services/singleton.js +1 -1
  111. package/document-management/service-models/document.service-model.d.ts +62 -62
  112. package/document-management/service-models/document.service-model.js +1 -1
  113. package/document-management/service-models/enriched/enriched-document-management-data.view.js +1 -1
  114. package/document-management/service-models/enriched/enriched-document.view.d.ts +1 -1
  115. package/examples/api/authentication.js +2 -2
  116. package/examples/api/basic-overview.js +2 -2
  117. package/examples/api/custom-authentication.js +2 -2
  118. package/examples/api/streaming.js +2 -2
  119. package/examples/browser/basic.js +2 -2
  120. package/examples/document-management/main.js +2 -2
  121. package/examples/http/client.js +2 -2
  122. package/examples/mail/basic.js +2 -2
  123. package/examples/pdf/basic.js +2 -2
  124. package/examples/template/basic.js +2 -2
  125. package/http/server/http-server-request.d.ts +3 -3
  126. package/key-value-store/postgres/key-value-store.service.js +1 -2
  127. package/key-value-store/postgres/models/key-value.model.d.ts +1 -2
  128. package/key-value-store/postgres/models/key-value.model.js +2 -4
  129. package/key-value-store/postgres/models/schemas.d.ts +1 -1
  130. package/key-value-store/postgres/models/schemas.js +1 -1
  131. package/lock/postgres/lock.js +1 -1
  132. package/lock/postgres/models/lock.model.d.ts +1 -2
  133. package/lock/postgres/models/lock.model.js +3 -5
  134. package/lock/postgres/models/schemas.d.ts +1 -1
  135. package/lock/postgres/models/schemas.js +1 -1
  136. package/lock/postgres/provider.js +1 -2
  137. package/mail/models/mail-log.model.d.ts +1 -1
  138. package/mail/models/mail-log.model.js +4 -5
  139. package/mail/models/schemas.d.ts +1 -1
  140. package/mail/models/schemas.js +1 -1
  141. package/openid-connect/oidc-state.model.d.ts +1 -1
  142. package/openid-connect/oidc-state.model.js +2 -3
  143. package/openid-connect/oidc.service.js +1 -1
  144. package/orm/data-types/bytea.js +1 -1
  145. package/orm/data-types/numeric-date.js +1 -1
  146. package/orm/decorators.d.ts +65 -72
  147. package/orm/decorators.js +42 -40
  148. package/orm/entity.d.ts +7 -1
  149. package/orm/entity.js +25 -11
  150. package/orm/index.d.ts +2 -1
  151. package/orm/index.js +2 -1
  152. package/orm/schemas/json.d.ts +1 -1
  153. package/orm/schemas/json.js +1 -1
  154. package/orm/schemas/numeric-date.d.ts +1 -1
  155. package/orm/schemas/numeric-date.js +1 -1
  156. package/orm/schemas/timestamp.d.ts +1 -1
  157. package/orm/schemas/timestamp.js +1 -1
  158. package/orm/schemas/uuid.d.ts +2 -2
  159. package/orm/schemas/uuid.js +1 -1
  160. package/orm/server/drizzle/schema-converter.ts +408 -0
  161. package/orm/server/repository.d.ts +1 -1
  162. package/orm/server/repository.js +12 -9
  163. package/orm/sqls.d.ts +1 -1
  164. package/orm/sqls.js +1 -1
  165. package/orm/types.d.ts +2 -6
  166. package/orm/types.js +1 -4
  167. package/package.json +15 -24
  168. package/queue/postgres/job.model.d.ts +3 -3
  169. package/queue/postgres/job.model.js +5 -6
  170. package/queue/postgres/queue.js +2 -2
  171. package/queue/postgres/schemas.d.ts +1 -1
  172. package/queue/postgres/schemas.js +1 -1
  173. package/supports.d.ts +1 -0
  174. package/supports.js +2 -1
  175. package/types/types.d.ts +12 -1
  176. package/utils/object/object.d.ts +3 -1
  177. package/utils/object/object.js +7 -1
  178. package/orm/server/drizzle/index.js +0 -1
  179. package/orm/server/drizzle/schema-converter.d.ts +0 -15
  180. package/orm/server/drizzle/schema-converter.js +0 -300
  181. /package/orm/server/drizzle/{index.d.ts → index.ts} +0 -0
@@ -1,10 +1,12 @@
1
+ import type { Token } from '../../authentication/index.js';
1
2
  import type { ApiRequestData } from '../types.js';
2
3
  export declare abstract class ApiRequestTokenProvider {
3
- abstract getToken<T>(requestData: ApiRequestData): T | Promise<T>;
4
+ getToken<T extends Token>(data: ApiRequestData): Promise<T>;
5
+ abstract tryGetToken<T extends Token>(requestData: ApiRequestData): T | null | Promise<T | null>;
4
6
  }
5
7
  export declare class NoopApiRequestTokenProvider extends ApiRequestTokenProvider {
6
- getToken<T>(): T;
8
+ tryGetToken<T extends Token>(_requestData: ApiRequestData): T | null | Promise<T | null>;
7
9
  }
8
10
  export declare class MockApiRequestTokenProvider extends ApiRequestTokenProvider {
9
- getToken<T>(): T;
11
+ tryGetToken<T extends Token>(_requestData: ApiRequestData): T | null | Promise<T | null>;
10
12
  }
@@ -5,11 +5,19 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { Singleton } from '../../injector/decorators.js';
8
+ import { isNull } from '../../utils/type-guards.js';
8
9
  export class ApiRequestTokenProvider {
10
+ async getToken(data) {
11
+ const token = await this.tryGetToken(data);
12
+ if (isNull(token)) {
13
+ throw new Error('No token available for request');
14
+ }
15
+ return token;
16
+ }
9
17
  }
10
18
  let NoopApiRequestTokenProvider = class NoopApiRequestTokenProvider extends ApiRequestTokenProvider {
11
- getToken() {
12
- throw new Error('No RequestTokenProvider registered');
19
+ tryGetToken(_requestData) {
20
+ throw new Error('No RequestInfoProvider registered');
13
21
  }
14
22
  };
15
23
  NoopApiRequestTokenProvider = __decorate([
@@ -17,11 +25,11 @@ NoopApiRequestTokenProvider = __decorate([
17
25
  ], NoopApiRequestTokenProvider);
18
26
  export { NoopApiRequestTokenProvider };
19
27
  let MockApiRequestTokenProvider = class MockApiRequestTokenProvider extends ApiRequestTokenProvider {
20
- getToken() {
28
+ tryGetToken(_requestData) {
21
29
  return {};
22
30
  }
23
31
  };
24
32
  MockApiRequestTokenProvider = __decorate([
25
- Singleton({ alias: ApiRequestTokenProvider })
33
+ Singleton()
26
34
  ], MockApiRequestTokenProvider);
27
35
  export { MockApiRequestTokenProvider };
@@ -50,15 +50,7 @@ export type ApiMetadata = {
50
50
  patternResult: URLPatternResult;
51
51
  };
52
52
  export declare class ApiGateway implements Resolvable<ApiGatewayOptions> {
53
- private readonly requestTokenProvider;
54
- private readonly logger;
55
- private readonly prefix;
56
- private readonly apis;
57
- private readonly middlewares;
58
- private readonly supressedErrors;
59
- private readonly catchErrorMiddleware;
60
- private readonly options;
61
- private composedMiddleware;
53
+ #private;
62
54
  readonly [resolveArgumentType]: ApiGatewayOptions;
63
55
  constructor();
64
56
  addMiddleware(middleware: ApiGatewayMiddleware): void;
@@ -7,13 +7,18 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  var __metadata = (this && this.__metadata) || function (k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  };
10
+ var _a;
10
11
  var ApiGateway_1;
12
+ import { match } from 'ts-pattern';
11
13
  import 'urlpattern-polyfill';
14
+ import { Auditor } from '../../audit/auditor.js';
15
+ import { ActorType } from '../../audit/types.js';
16
+ import { NIL_UUID } from '../../constants.js';
12
17
  import { BadRequestError } from '../../errors/bad-request.error.js';
13
18
  import { NotFoundError } from '../../errors/not-found.error.js';
14
19
  import { NotImplementedError } from '../../errors/not-implemented.error.js';
15
20
  import { HttpServerResponse } from '../../http/server/index.js';
16
- import { Singleton, inject, injectArgument, resolveArgumentType } from '../../injector/index.js';
21
+ import { inject, injectArgument, resolveArgumentType, Singleton } from '../../injector/index.js';
17
22
  import { Logger } from '../../logger/index.js';
18
23
  import { Schema } from '../../schema/index.js';
19
24
  import { DataStreamSource } from '../../sse/data-stream-source.js';
@@ -23,7 +28,7 @@ import { toArray } from '../../utils/array/array.js';
23
28
  import { composeAsyncMiddleware } from '../../utils/middleware.js';
24
29
  import { mapObjectValues } from '../../utils/object/object.js';
25
30
  import { deferThrow } from '../../utils/throw.js';
26
- import { isArray, isBlob, isDefined, isNull, isNullOrUndefined, isObject, isReadableStream, isUint8Array, isUndefined } from '../../utils/type-guards.js';
31
+ import { isArray, isBlob, isDefined, isNotNull, isNotNullOrUndefined, isNull, isNullOrUndefined, isObject, isReadableStream, isUint8Array, isUndefined } from '../../utils/type-guards.js';
27
32
  import { mebibyte } from '../../utils/units.js';
28
33
  import { normalizedApiDefinitionEndpointsEntries } from '../types.js';
29
34
  import { getFullApiEndpointResource } from '../utils.js';
@@ -51,42 +56,43 @@ export class ApiGatewayOptions {
51
56
  defaultMaxBytes;
52
57
  }
53
58
  let ApiGateway = ApiGateway_1 = class ApiGateway {
54
- requestTokenProvider = inject(ApiRequestTokenProvider);
55
- logger = inject(Logger, ApiGateway_1.name);
56
- prefix;
57
- apis;
58
- middlewares;
59
- supressedErrors;
60
- catchErrorMiddleware;
61
- options = injectArgument(this, { optional: true }) ?? {};
62
- composedMiddleware;
59
+ #requestTokenProvider = inject(ApiRequestTokenProvider);
60
+ #auditor = inject(Auditor, 'Api');
61
+ #logger = inject(Logger, ApiGateway_1.name);
62
+ #prefix;
63
+ #apis;
64
+ #middlewares;
65
+ #supressedErrors;
66
+ #catchErrorMiddleware;
67
+ #options = injectArgument(this, { optional: true }) ?? {};
68
+ #composedMiddleware;
63
69
  constructor() {
64
- this.prefix = isNull(this.options.prefix) ? null : (this.options.prefix ?? 'api');
65
- this.apis = new Map();
66
- this.middlewares = this.options.middlewares ?? [];
67
- this.supressedErrors = new Set(this.options.supressedErrors);
68
- this.catchErrorMiddleware = getCatchErrorMiddleware(this.supressedErrors, this.logger);
70
+ this.#prefix = isNull(this.#options.prefix) ? null : (this.#options.prefix ?? 'api');
71
+ this.#apis = new Map();
72
+ this.#middlewares = this.#options.middlewares ?? [];
73
+ this.#supressedErrors = new Set(this.#options.supressedErrors);
74
+ this.#catchErrorMiddleware = getCatchErrorMiddleware(this.#supressedErrors, this.#logger);
69
75
  this.updateMiddleware();
70
76
  }
71
77
  addMiddleware(middleware) {
72
- this.middlewares.push(middleware);
78
+ this.#middlewares.push(middleware);
73
79
  this.updateMiddleware();
74
80
  }
75
81
  supressErrors(...errorTypes) {
76
82
  for (const type of errorTypes) {
77
- this.supressedErrors.add(type);
83
+ this.#supressedErrors.add(type);
78
84
  }
79
85
  }
80
86
  registerApi(definition, implementation) {
81
87
  for (const [name, endpointDefinition] of normalizedApiDefinitionEndpointsEntries(definition.endpoints)) {
82
88
  const versionArray = isUndefined(endpointDefinition.version) ? [1] : toArray(endpointDefinition.version);
83
89
  for (const version of versionArray) {
84
- const resource = getFullApiEndpointResource({ api: definition, endpoint: endpointDefinition, defaultPrefix: this.prefix, explicitVersion: version });
90
+ const resource = getFullApiEndpointResource({ api: definition, endpoint: endpointDefinition, defaultPrefix: this.#prefix, explicitVersion: version });
85
91
  const methods = isArray(endpointDefinition.method) ? endpointDefinition.method : [endpointDefinition.method ?? 'GET'];
86
92
  if (methods.length == 0) {
87
93
  throw new Error(`No method provided for resource ${resource}.`);
88
94
  }
89
- let resourceApis = this.apis.get(resource);
95
+ let resourceApis = this.#apis.get(resource);
90
96
  if (isUndefined(resourceApis)) {
91
97
  resourceApis = {
92
98
  resource,
@@ -103,7 +109,7 @@ let ApiGateway = ApiGateway_1 = class ApiGateway {
103
109
  }),
104
110
  endpoints: new Map(),
105
111
  };
106
- this.apis.set(resource, resourceApis);
112
+ this.#apis.set(resource, resourceApis);
107
113
  }
108
114
  const endpointImplementation = implementation[name]?.bind(implementation) ?? deferThrow(() => new NotImplementedError(`Endpoint ${name} for resource ${resource} not implemented.`));
109
115
  for (const method of methods) {
@@ -119,13 +125,13 @@ let ApiGateway = ApiGateway_1 = class ApiGateway {
119
125
  const { api, patternResult } = this.getApiMetadata(request.url);
120
126
  const endpoint = api.endpoints.get(request.method);
121
127
  const context = { api, resourcePatternResult: patternResult, endpoint, request, response };
122
- await this.composedMiddleware(context);
128
+ await this.#composedMiddleware(context);
123
129
  responded = true;
124
130
  await respond(context.response);
125
131
  }
126
132
  catch (error) {
127
133
  try {
128
- handleApiError(error, response, this.supressedErrors, this.logger);
134
+ handleApiError(error, response, this.#supressedErrors, this.#logger);
129
135
  if (responded) {
130
136
  await close();
131
137
  }
@@ -134,7 +140,7 @@ let ApiGateway = ApiGateway_1 = class ApiGateway {
134
140
  await respond(response);
135
141
  }
136
142
  catch (errorRespondError) {
137
- this.logger.error(errorRespondError);
143
+ this.#logger.error(errorRespondError);
138
144
  await close();
139
145
  }
140
146
  }
@@ -145,7 +151,7 @@ let ApiGateway = ApiGateway_1 = class ApiGateway {
145
151
  getApiMetadata(resource) {
146
152
  const urlWithoutPort = new URL(resource);
147
153
  urlWithoutPort.port = '';
148
- for (const api of this.apis.values()) {
154
+ for (const api of this.#apis.values()) {
149
155
  const result = api.pattern.exec(urlWithoutPort);
150
156
  if (isNullOrUndefined(result)) {
151
157
  continue;
@@ -155,11 +161,11 @@ let ApiGateway = ApiGateway_1 = class ApiGateway {
155
161
  throw new NotFoundError(`Resource ${resource.pathname} not available.`);
156
162
  }
157
163
  updateMiddleware() {
158
- const middlewares = [responseTimeMiddleware, contentTypeMiddleware, this.catchErrorMiddleware, corsMiddleware(this.options.cors), allowedMethodsMiddleware, ...this.middlewares, async (context, next) => this.endpointMiddleware(context, next)];
159
- this.composedMiddleware = composeAsyncMiddleware(middlewares);
164
+ const middlewares = [responseTimeMiddleware, contentTypeMiddleware, this.#catchErrorMiddleware, corsMiddleware(this.#options.cors), allowedMethodsMiddleware, ...this.#middlewares, async (context, next) => await this.endpointMiddleware(context, next)];
165
+ this.#composedMiddleware = composeAsyncMiddleware(middlewares);
160
166
  }
161
167
  async endpointMiddleware(context, next) {
162
- const readBodyOptions = { maxBytes: context.endpoint.definition.maxBytes ?? this.options.defaultMaxBytes ?? defaultMaxBytes };
168
+ const readBodyOptions = { maxBytes: context.endpoint.definition.maxBytes ?? this.#options.defaultMaxBytes ?? defaultMaxBytes };
163
169
  const body = isDefined(context.endpoint.definition.body)
164
170
  ? await getBody(context.request, readBodyOptions, context.endpoint.definition.body)
165
171
  : undefined;
@@ -174,24 +180,49 @@ let ApiGateway = ApiGateway_1 = class ApiGateway {
174
180
  const validatedParameters = isDefined(context.endpoint.definition.parameters)
175
181
  ? Schema.parse(context.endpoint.definition.parameters, parameters)
176
182
  : parameters;
183
+ const requestTokenProvider = this.#requestTokenProvider;
184
+ const auditor = this.#auditor;
177
185
  const requestContext = {
178
186
  parameters: validatedParameters,
179
187
  body,
180
188
  request: context.request,
181
- getToken: async () => this.requestTokenProvider.getToken(requestContext),
189
+ async tryGetToken() {
190
+ return await requestTokenProvider.tryGetToken(requestContext);
191
+ },
192
+ async getToken() {
193
+ return await requestTokenProvider.getToken(requestContext);
194
+ },
195
+ async getAuditor() {
196
+ const token = await this.tryGetToken();
197
+ return auditor.fork(context.api.resource)
198
+ .withCorrelation()
199
+ .with({
200
+ actorType: isNotNull(token) ? ActorType.User : ActorType.Anonymous,
201
+ actor: token?.payload.subject ?? NIL_UUID,
202
+ impersonatorType: isNotNullOrUndefined(token?.payload.impersonator) ? ActorType.User : null,
203
+ impersonator: token?.payload.impersonator ?? null,
204
+ network: {
205
+ path: context.request.url.pathname,
206
+ ipAddress: context.request.ip,
207
+ userAgent: context.request.headers.tryGetSingle('User-Agent') ?? null,
208
+ sessionId: token?.payload.sessionId ?? null,
209
+ },
210
+ });
211
+ },
182
212
  };
183
213
  const result = await context.endpoint.implementation(requestContext);
184
214
  if (result instanceof HttpServerResponse) {
185
215
  context.response.update(result);
186
216
  }
187
217
  else {
188
- context.response.body = isUint8Array(result) ? { buffer: result }
189
- : isBlob(result) ? { stream: result.stream() }
190
- : isReadableStream(result) ? { stream: result }
191
- : (result instanceof ServerSentEventsSource) ? { events: result }
192
- : (context.endpoint.definition.result == DataStream) ? { events: DataStreamSource.fromIterable(result).eventSource }
193
- : (context.endpoint.definition.result == String) ? { text: result }
194
- : { json: result };
218
+ context.response.body = match(result)
219
+ .when(isUint8Array, (buffer) => ({ buffer }))
220
+ .when(isBlob, (value) => ({ stream: value.stream() }))
221
+ .when((isReadableStream), (stream) => ({ stream }))
222
+ .when((value) => value instanceof ServerSentEventsSource, (events) => ({ events }))
223
+ .when(() => (context.endpoint.definition.result == DataStream), (value) => ({ events: DataStreamSource.fromIterable(value).eventSource }))
224
+ .when(() => (context.endpoint.definition.result == String), (text) => ({ text: text }))
225
+ .otherwise((json) => ({ json }));
195
226
  }
196
227
  await next();
197
228
  }
package/api/types.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import type { Observable } from 'rxjs';
2
+ import type { Auditor } from '../audit/index.js';
3
+ import type { Token } from '../authentication/index.js';
2
4
  import type { HttpServerRequest, HttpServerResponse } from '../http/server/index.js';
3
5
  import type { HttpMethod } from '../http/types.js';
4
6
  import type { SchemaOutput, SchemaTestable } from '../schema/index.js';
@@ -106,7 +108,9 @@ export type ApiRequestData<T extends ApiDefinition = ApiDefinition, K extends Ap
106
108
  request: HttpServerRequest;
107
109
  };
108
110
  export type ApiRequestContext<T extends ApiDefinition = ApiDefinition, K extends ApiEndpointKeys<T> = ApiEndpointKeys<T>> = ApiRequestData<T, K> & {
109
- getToken<Token>(): Promise<Token>;
111
+ tryGetToken<T extends Token>(): Promise<T | null>;
112
+ getToken<T extends Token>(): Promise<T>;
113
+ getAuditor(): Promise<Auditor>;
110
114
  };
111
115
  export type ApiEndpointServerImplementation<T extends ApiDefinition = ApiDefinition, K extends ApiEndpointKeys<T> = ApiEndpointKeys<T>> = (context: ApiRequestContext<T, K>) => ApiServerResult<T, K> | Promise<ApiServerResult<T, K>>;
112
116
  export type ApiEndpointClientImplementation<T extends ApiDefinition = ApiDefinition, K extends ApiEndpointKeys<T> = ApiEndpointKeys<T>> = ApiClientBody<T, K> extends never ? ApiParameters<T, K> extends never ? () => Promise<ApiClientResult<T, K>> : (parameters: ApiParameters<T, K>) => Promise<ApiClientResult<T, K>> : (parameters: ApiParameters<T, K> extends never ? undefined | Record<never, never> : ApiParameters<T, K>, body: ApiClientBody<T, K>) => Promise<ApiClientResult<T, K>>;
@@ -7,6 +7,8 @@ export type DestructorFn = () => void | Promise<void>;
7
7
  export declare const APPLICATION_MODULE: import("../injector/token.js").InjectionToken<Module, never>;
8
8
  export declare const APPLICATION_INITIALIZER: import("../injector/token.js").InjectionToken<InitializerFn, never>;
9
9
  export declare const APPLICATION_DESTRUCTOR: import("../injector/token.js").InjectionToken<DestructorFn, never>;
10
+ export declare const APPLICATION_INSTANCE_ID: import("../injector/token.js").InjectionToken<string, never>;
11
+ export declare const APPLICATION_NAME: import("../injector/token.js").InjectionToken<string, never>;
10
12
  export declare class Application {
11
13
  #private;
12
14
  static create(name: string, providers?: OneOrMany<ProvidersItem>[]): Application;
@@ -19,7 +19,8 @@ import { isDefined, isFunction } from '../utils/type-guards.js';
19
19
  export const APPLICATION_MODULE = injectionToken('ApplicationModule');
20
20
  export const APPLICATION_INITIALIZER = injectionToken('ApplicationInitializer');
21
21
  export const APPLICATION_DESTRUCTOR = injectionToken('ApplicationDestructor');
22
- const APPLICATION_NAME = injectionToken('ApplicationName');
22
+ export const APPLICATION_INSTANCE_ID = injectionToken('ApplicationInstanceId');
23
+ export const APPLICATION_NAME = injectionToken('ApplicationName');
23
24
  let Application = Application_1 = class Application {
24
25
  #name = inject(APPLICATION_NAME);
25
26
  #injector = inject(Injector);
@@ -29,6 +30,7 @@ let Application = Application_1 = class Application {
29
30
  #shutdownToken = inject(CancellationSignal, undefined, { optional: true })?.createChild() ?? new CancellationToken();
30
31
  static create(name, providers = []) {
31
32
  const injector = new Injector(`${name}Injector`);
33
+ injector.register(APPLICATION_INSTANCE_ID, { useValue: crypto.randomUUID() });
32
34
  injector.register(APPLICATION_NAME, { useValue: name });
33
35
  for (const providersItem of providers.flat()) {
34
36
  injector.register(providersItem.provide, providersItem, { multi: providersItem.multi });
@@ -3,7 +3,7 @@ import { type ProvidersItem } from '../injector/index.js';
3
3
  import { Module, type FunctionModuleFunction } from '../module/index.js';
4
4
  import type { OneOrMany, Type } from '../types/index.js';
5
5
  import { type DestructorFn, type InitializerFn } from './application.js';
6
- export declare function provideModules(...functionsAndModules: OneOrMany<FunctionModuleFunction | Type<Module>>[]): ProvidersItem[];
6
+ export declare function provideModule(...functionsAndModules: OneOrMany<FunctionModuleFunction | Type<Module>>[]): ProvidersItem[];
7
7
  export declare function provideInitializer(fn: InitializerFn): ProvidersItem;
8
8
  export declare function provideDestructor(fn: DestructorFn): ProvidersItem;
9
9
  export declare function provideShutdownSignal(signal: CancellationSignal): ProvidersItem;
@@ -7,7 +7,7 @@ import { typeExtends } from '../utils/type/index.js';
7
7
  import { Application, APPLICATION_DESTRUCTOR, APPLICATION_INITIALIZER, APPLICATION_MODULE } from './application.js';
8
8
  const quitSignals = ['SIGTERM', 'SIGINT', 'SIGHUP', 'SIGBREAK'];
9
9
  const quitEvents = ['uncaughtException', 'unhandledRejection', 'rejectionHandled'];
10
- export function provideModules(...functionsAndModules) {
10
+ export function provideModule(...functionsAndModules) {
11
11
  return functionsAndModules.flat().map((fnOrModule) => {
12
12
  if (typeExtends(fnOrModule, Module)) {
13
13
  return { provide: APPLICATION_MODULE, useValue: fnOrModule, multi: true };
@@ -1,15 +1,115 @@
1
- import { EntityWithoutMetadata, Json, Timestamp, Uuid } from '../orm/index.js';
1
+ import { type Embedded, EntityWithoutMetadata, type Json, type Timestamp, type Uuid } from '../orm/index.js';
2
+ import type { UndefinableJsonObject } from '../types/index.js';
2
3
  import { ActorType, AuditOutcome, AuditSeverity } from './types.js';
3
- export declare class AuditEvent extends EntityWithoutMetadata {
4
+ /**
5
+ * Represents the network details of the request that triggered the audit event.
6
+ */
7
+ export declare class RequestDetails {
8
+ /**
9
+ * The path of the request.
10
+ * @example '/api/v1/users/xyz'
11
+ */
12
+ path: string | null;
13
+ /**
14
+ * The IP address of the client.
15
+ * @example '192.168.1.100'
16
+ */
17
+ ipAddress: string | null;
18
+ /**
19
+ * The user agent string of the client.
20
+ * @example 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...'
21
+ */
22
+ userAgent: string | null;
23
+ /**
24
+ * The session ID associated with the request, if any.
25
+ */
26
+ sessionId: Uuid | null;
27
+ }
28
+ /**
29
+ * Represents the state of data before and after a change.
30
+ */
31
+ export declare class ChangeDetails {
32
+ /**
33
+ * The state of the data before the change occurred.
34
+ */
35
+ before: Json<unknown> | null;
36
+ /**
37
+ * The state of the data after the change occurred.
38
+ */
39
+ after: Json<unknown> | null;
40
+ }
41
+ /**
42
+ * Represents a single audit event record in the database.
43
+ * This entity captures who did what, when, and to what, along with other contextual information.
44
+ *
45
+ * @template Details The type of the `details` JSON object, allowing for custom, action-specific data.
46
+ */
47
+ export declare class AuditEvent<Details extends UndefinableJsonObject = UndefinableJsonObject> extends EntityWithoutMetadata {
48
+ /**
49
+ * The timestamp when the event occurred.
50
+ */
4
51
  timestamp: Timestamp;
5
- correlationId?: Uuid;
52
+ /**
53
+ * The ID of the tenant in which the event occurred. Can be null for system-level events.
54
+ */
55
+ tenantId: Uuid | null;
56
+ /**
57
+ * A unique identifier to correlate multiple related audit events.
58
+ */
59
+ correlationId: Uuid | null;
60
+ /**
61
+ * The module or feature area where the event originated, in dot-separated format.
62
+ * @example 'user.authentication'
63
+ */
6
64
  module: string;
65
+ /**
66
+ * The specific action that was performed.
67
+ * @example 'login'
68
+ */
7
69
  action: string;
70
+ /**
71
+ * The outcome of the action.
72
+ */
8
73
  outcome: AuditOutcome;
74
+ /**
75
+ * The severity level of the event.
76
+ */
9
77
  severity: AuditSeverity;
10
- actorId: string;
78
+ /**
79
+ * The type of the actor.
80
+ */
11
81
  actorType: ActorType;
12
- targetId: string;
82
+ /**
83
+ * The (if possible unique) identifier of the actor who performed the action.
84
+ */
85
+ actor: string | null;
86
+ /**
87
+ * The type of the impersonator, if applicable.
88
+ */
89
+ impersonatorType: ActorType | null;
90
+ /**
91
+ * The (if possible unique) identifier of the user who is impersonating the actor, if applicable.
92
+ */
93
+ impersonator: string | null;
94
+ /**
95
+ * The type of the target entity.
96
+ * @example 'User'
97
+ */
13
98
  targetType: string;
14
- details?: Json<unknown>;
99
+ /**
100
+ * The unique identifier of the primary resource or entity that was the target of the action.
101
+ */
102
+ targetId: Uuid;
103
+ /**
104
+ * Network-related details for the request that triggered the event.
105
+ */
106
+ network: Embedded<RequestDetails> | null;
107
+ /**
108
+ * Details about data changes.
109
+ */
110
+ changes: Embedded<ChangeDetails> | null;
111
+ /**
112
+ * A flexible JSON object for storing additional, action-specific details.
113
+ */
114
+ details: Json<Details> | null;
15
115
  }