@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.
- package/api/server/api-request-token.provider.d.ts +5 -3
- package/api/server/api-request-token.provider.js +12 -4
- package/api/server/gateway.d.ts +1 -9
- package/api/server/gateway.js +67 -36
- package/api/types.d.ts +5 -1
- package/application/application.d.ts +2 -0
- package/application/application.js +3 -1
- package/application/providers.d.ts +1 -1
- package/application/providers.js +1 -1
- package/audit/audit.model.d.ts +106 -6
- package/audit/audit.model.js +156 -13
- package/audit/auditor.d.ts +115 -30
- package/audit/auditor.js +160 -19
- package/audit/drizzle/0000_bored_stick.sql +26 -0
- package/audit/drizzle/meta/0000_snapshot.json +195 -0
- package/audit/drizzle/meta/_journal.json +13 -0
- package/audit/drizzle.config.d.ts +2 -0
- package/audit/drizzle.config.js +11 -0
- package/audit/index.d.ts +3 -1
- package/audit/index.js +3 -1
- package/audit/module.d.ts +22 -0
- package/audit/module.js +33 -0
- package/audit/schemas.d.ts +6 -0
- package/audit/schemas.js +8 -0
- package/audit/types.d.ts +2 -1
- package/audit/types.js +2 -1
- package/authentication/models/authentication-credentials.model.js +1 -2
- package/authentication/models/authentication-session.model.d.ts +2 -2
- package/authentication/models/authentication-session.model.js +3 -5
- package/authentication/models/index.d.ts +0 -1
- package/authentication/models/index.js +0 -1
- package/authentication/server/authentication-api-request-token.provider.d.ts +2 -2
- package/authentication/server/authentication-api-request-token.provider.js +8 -5
- package/authentication/server/authentication.api-controller.d.ts +8 -8
- package/authentication/server/authentication.api-controller.js +16 -16
- package/authentication/server/authentication.audit.d.ts +34 -0
- package/authentication/server/authentication.audit.js +1 -0
- package/authentication/server/authentication.service.d.ts +19 -10
- package/authentication/server/authentication.service.js +158 -43
- package/authentication/server/drizzle.config.js +1 -1
- package/authentication/server/index.d.ts +1 -0
- package/authentication/server/index.js +1 -0
- package/authentication/server/module.d.ts +1 -1
- package/authentication/{models → server}/schemas.d.ts +2 -3
- package/authentication/{models → server}/schemas.js +2 -3
- package/constants.d.ts +1 -0
- package/constants.js +1 -0
- package/document-management/api/document-management.api.d.ts +74 -74
- package/document-management/models/document-assignment-scope.model.d.ts +1 -2
- package/document-management/models/document-assignment-scope.model.js +4 -6
- package/document-management/models/document-assignment-task.model.d.ts +1 -2
- package/document-management/models/document-assignment-task.model.js +3 -5
- package/document-management/models/document-category.model.d.ts +1 -2
- package/document-management/models/document-category.model.js +3 -4
- package/document-management/models/document-collection-assignment.model.d.ts +1 -2
- package/document-management/models/document-collection-assignment.model.js +5 -7
- package/document-management/models/document-collection.model.d.ts +1 -2
- package/document-management/models/document-collection.model.js +3 -4
- package/document-management/models/document-management-table.d.ts +1 -1
- package/document-management/models/document-management-table.js +1 -1
- package/document-management/models/document-property-value.model.d.ts +1 -2
- package/document-management/models/document-property-value.model.js +5 -8
- package/document-management/models/document-property.model.d.ts +1 -2
- package/document-management/models/document-property.model.js +2 -3
- package/document-management/models/document-request-collection-assignment.model.d.ts +1 -2
- package/document-management/models/document-request-collection-assignment.model.js +4 -6
- package/document-management/models/document-request-template.d.ts +1 -2
- package/document-management/models/document-request-template.js +4 -6
- package/document-management/models/document-request.model.d.ts +1 -1
- package/document-management/models/document-request.model.js +4 -5
- package/document-management/models/document-requests-template.d.ts +1 -1
- package/document-management/models/document-requests-template.js +2 -3
- package/document-management/models/document-tag-assignment.model.d.ts +1 -2
- package/document-management/models/document-tag-assignment.model.js +4 -6
- package/document-management/models/document-tag.model.d.ts +1 -1
- package/document-management/models/document-tag.model.js +2 -3
- package/document-management/models/document-type-property.model.d.ts +1 -2
- package/document-management/models/document-type-property.model.js +4 -6
- package/document-management/models/document-type-validation.model.d.ts +1 -2
- package/document-management/models/document-type-validation.model.js +4 -6
- package/document-management/models/document-type.model.d.ts +1 -2
- package/document-management/models/document-type.model.js +3 -5
- package/document-management/models/document-validation-definition.model.d.ts +1 -2
- package/document-management/models/document-validation-definition.model.js +3 -4
- package/document-management/models/document-validation-execution-related-document.model.d.ts +1 -2
- package/document-management/models/document-validation-execution-related-document.model.js +4 -6
- package/document-management/models/document-validation-execution.model.d.ts +1 -2
- package/document-management/models/document-validation-execution.model.js +6 -8
- package/document-management/models/document-workflow.model.d.ts +1 -2
- package/document-management/models/document-workflow.model.js +5 -7
- package/document-management/models/document.model.d.ts +1 -2
- package/document-management/models/document.model.js +5 -7
- package/document-management/server/api/document-management.api.js +1 -1
- package/document-management/server/module.d.ts +1 -1
- package/document-management/server/module.js +1 -1
- package/document-management/server/schemas.d.ts +1 -1
- package/document-management/server/schemas.js +1 -1
- package/document-management/server/services/document-category-type.service.d.ts +2 -2
- package/document-management/server/services/document-category-type.service.js +1 -2
- package/document-management/server/services/document-collection.service.d.ts +1 -1
- package/document-management/server/services/document-collection.service.js +1 -2
- package/document-management/server/services/document-management.service.js +6 -6
- package/document-management/server/services/document-property.service.d.ts +1 -1
- package/document-management/server/services/document-property.service.js +1 -2
- package/document-management/server/services/document-validation.service.js +2 -2
- package/document-management/server/services/document-workflow.service.d.ts +2 -2
- package/document-management/server/services/document-workflow.service.js +1 -2
- package/document-management/server/services/document.service.d.ts +1 -1
- package/document-management/server/services/document.service.js +1 -2
- package/document-management/server/services/singleton.js +1 -1
- package/document-management/service-models/document.service-model.d.ts +62 -62
- package/document-management/service-models/document.service-model.js +1 -1
- package/document-management/service-models/enriched/enriched-document-management-data.view.js +1 -1
- package/document-management/service-models/enriched/enriched-document.view.d.ts +1 -1
- package/examples/api/authentication.js +2 -2
- package/examples/api/basic-overview.js +2 -2
- package/examples/api/custom-authentication.js +2 -2
- package/examples/api/streaming.js +2 -2
- package/examples/browser/basic.js +2 -2
- package/examples/document-management/main.js +2 -2
- package/examples/http/client.js +2 -2
- package/examples/mail/basic.js +2 -2
- package/examples/pdf/basic.js +2 -2
- package/examples/template/basic.js +2 -2
- package/http/server/http-server-request.d.ts +3 -3
- package/key-value-store/postgres/key-value-store.service.js +1 -2
- package/key-value-store/postgres/models/key-value.model.d.ts +1 -2
- package/key-value-store/postgres/models/key-value.model.js +2 -4
- package/key-value-store/postgres/models/schemas.d.ts +1 -1
- package/key-value-store/postgres/models/schemas.js +1 -1
- package/lock/postgres/lock.js +1 -1
- package/lock/postgres/models/lock.model.d.ts +1 -2
- package/lock/postgres/models/lock.model.js +3 -5
- package/lock/postgres/models/schemas.d.ts +1 -1
- package/lock/postgres/models/schemas.js +1 -1
- package/lock/postgres/provider.js +1 -2
- package/mail/models/mail-log.model.d.ts +1 -1
- package/mail/models/mail-log.model.js +4 -5
- package/mail/models/schemas.d.ts +1 -1
- package/mail/models/schemas.js +1 -1
- package/openid-connect/oidc-state.model.d.ts +1 -1
- package/openid-connect/oidc-state.model.js +2 -3
- package/openid-connect/oidc.service.js +1 -1
- package/orm/data-types/bytea.js +1 -1
- package/orm/data-types/numeric-date.js +1 -1
- package/orm/decorators.d.ts +65 -72
- package/orm/decorators.js +42 -40
- package/orm/entity.d.ts +7 -1
- package/orm/entity.js +25 -11
- package/orm/index.d.ts +2 -1
- package/orm/index.js +2 -1
- package/orm/schemas/json.d.ts +1 -1
- package/orm/schemas/json.js +1 -1
- package/orm/schemas/numeric-date.d.ts +1 -1
- package/orm/schemas/numeric-date.js +1 -1
- package/orm/schemas/timestamp.d.ts +1 -1
- package/orm/schemas/timestamp.js +1 -1
- package/orm/schemas/uuid.d.ts +2 -2
- package/orm/schemas/uuid.js +1 -1
- package/orm/server/drizzle/schema-converter.ts +408 -0
- package/orm/server/repository.d.ts +1 -1
- package/orm/server/repository.js +12 -9
- package/orm/sqls.d.ts +1 -1
- package/orm/sqls.js +1 -1
- package/orm/types.d.ts +2 -6
- package/orm/types.js +1 -4
- package/package.json +15 -24
- package/queue/postgres/job.model.d.ts +3 -3
- package/queue/postgres/job.model.js +5 -6
- package/queue/postgres/queue.js +2 -2
- package/queue/postgres/schemas.d.ts +1 -1
- package/queue/postgres/schemas.js +1 -1
- package/supports.d.ts +1 -0
- package/supports.js +2 -1
- package/types/types.d.ts +12 -1
- package/utils/object/object.d.ts +3 -1
- package/utils/object/object.js +7 -1
- package/orm/server/drizzle/index.js +0 -1
- package/orm/server/drizzle/schema-converter.d.ts +0 -15
- package/orm/server/drizzle/schema-converter.js +0 -300
- /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
|
-
|
|
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
|
-
|
|
8
|
+
tryGetToken<T extends Token>(_requestData: ApiRequestData): T | null | Promise<T | null>;
|
|
7
9
|
}
|
|
8
10
|
export declare class MockApiRequestTokenProvider extends ApiRequestTokenProvider {
|
|
9
|
-
|
|
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
|
-
|
|
12
|
-
throw new Error('No
|
|
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
|
-
|
|
28
|
+
tryGetToken(_requestData) {
|
|
21
29
|
return {};
|
|
22
30
|
}
|
|
23
31
|
};
|
|
24
32
|
MockApiRequestTokenProvider = __decorate([
|
|
25
|
-
Singleton(
|
|
33
|
+
Singleton()
|
|
26
34
|
], MockApiRequestTokenProvider);
|
|
27
35
|
export { MockApiRequestTokenProvider };
|
package/api/server/gateway.d.ts
CHANGED
|
@@ -50,15 +50,7 @@ export type ApiMetadata = {
|
|
|
50
50
|
patternResult: URLPatternResult;
|
|
51
51
|
};
|
|
52
52
|
export declare class ApiGateway implements Resolvable<ApiGatewayOptions> {
|
|
53
|
-
private
|
|
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;
|
package/api/server/gateway.js
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
|
65
|
-
this
|
|
66
|
-
this
|
|
67
|
-
this
|
|
68
|
-
this
|
|
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
|
|
78
|
+
this.#middlewares.push(middleware);
|
|
73
79
|
this.updateMiddleware();
|
|
74
80
|
}
|
|
75
81
|
supressErrors(...errorTypes) {
|
|
76
82
|
for (const type of errorTypes) {
|
|
77
|
-
this
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
159
|
-
this
|
|
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
|
|
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
|
-
|
|
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 =
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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;
|
package/application/providers.js
CHANGED
|
@@ -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
|
|
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 };
|
package/audit/audit.model.d.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
78
|
+
/**
|
|
79
|
+
* The type of the actor.
|
|
80
|
+
*/
|
|
11
81
|
actorType: ActorType;
|
|
12
|
-
|
|
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
|
-
|
|
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
|
}
|