@tstdl/base 0.93.0 → 0.93.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,5 @@
1
1
  import { CancellationSignal } from '../cancellation/token.js';
2
2
  import { type ProvidersItem } from '../injector/injector.js';
3
- import type { Resolvable, resolveArgumentType } from '../injector/interfaces.js';
4
- import type { LoggerArgument } from '../logger/index.js';
5
3
  import { Module } from '../module/index.js';
6
4
  import type { OneOrMany, Type } from '../types/index.js';
7
5
  export type InitializerFn = () => void | Promise<void>;
@@ -9,10 +7,8 @@ export type DestructorFn = () => void | Promise<void>;
9
7
  export declare const APPLICATION_MODULE: import("../injector/token.js").InjectionToken<Module, never>;
10
8
  export declare const APPLICATION_INITIALIZER: import("../injector/token.js").InjectionToken<InitializerFn, never>;
11
9
  export declare const APPLICATION_DESTRUCTOR: import("../injector/token.js").InjectionToken<DestructorFn, never>;
12
- export type ApplicationArgument = LoggerArgument;
13
- export declare class Application implements Resolvable<ApplicationArgument> {
10
+ export declare class Application {
14
11
  #private;
15
- readonly [resolveArgumentType]: string;
16
12
  static create(name: string, providers?: OneOrMany<ProvidersItem>[]): Application;
17
13
  static run(name: string, providers?: OneOrMany<ProvidersItem>[]): Application;
18
14
  get shutdownSignal(): CancellationSignal;
@@ -7,7 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  var Application_1;
8
8
  import { CancellationSignal, CancellationToken } from '../cancellation/token.js';
9
9
  import { Singleton } from '../injector/decorators.js';
10
- import { inject, injectAll, injectArgument, runInInjectionContext } from '../injector/inject.js';
10
+ import { inject, injectAll, runInInjectionContext } from '../injector/inject.js';
11
11
  import { Injector } from '../injector/injector.js';
12
12
  import { injectionToken } from '../injector/token.js';
13
13
  import { Logger } from '../logger/index.js';
@@ -19,8 +19,9 @@ 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
23
  let Application = Application_1 = class Application {
23
- #name = injectArgument(this);
24
+ #name = inject(APPLICATION_NAME);
24
25
  #injector = inject(Injector);
25
26
  #logger = inject(Logger, this.#name);
26
27
  #moduleTypesAndInstances = new Set(injectAll(APPLICATION_MODULE, undefined, { optional: true }));
@@ -28,10 +29,11 @@ let Application = Application_1 = class Application {
28
29
  #shutdownToken = inject(CancellationSignal, undefined, { optional: true })?.createChild() ?? new CancellationToken();
29
30
  static create(name, providers = []) {
30
31
  const injector = new Injector(`${name}Injector`);
32
+ injector.register(APPLICATION_NAME, { useValue: name });
31
33
  for (const providersItem of providers.flat()) {
32
34
  injector.register(providersItem.provide, providersItem, { multi: providersItem.multi });
33
35
  }
34
- return injector.resolve(Application_1, name);
36
+ return injector.resolve(Application_1);
35
37
  }
36
38
  static run(name, providers = []) {
37
39
  const app = Application_1.create(name, providers);
@@ -1,15 +1,110 @@
1
- import { EntityWithoutMetadata, Json, Timestamp, Uuid } from '../orm/index.js';
1
+ import { Embedded, EntityWithoutMetadata, Json, Timestamp, 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 IP address of the client.
10
+ * @example '192.168.1.100'
11
+ */
12
+ ipAddress: string | null;
13
+ /**
14
+ * The user agent string of the client.
15
+ * @example 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...'
16
+ */
17
+ userAgent: string | null;
18
+ /**
19
+ * The session ID associated with the request, if any.
20
+ */
21
+ sessionId: Uuid | null;
22
+ }
23
+ /**
24
+ * Represents the state of data before and after a change.
25
+ */
26
+ export declare class ChangeDetails {
27
+ /**
28
+ * The state of the data before the change occurred.
29
+ */
30
+ before: Json<unknown> | null;
31
+ /**
32
+ * The state of the data after the change occurred.
33
+ */
34
+ after: Json<unknown> | null;
35
+ }
36
+ /**
37
+ * Represents a single audit event record in the database.
38
+ * This entity captures who did what, when, and to what, along with other contextual information.
39
+ *
40
+ * @template Details The type of the `details` JSON object, allowing for custom, action-specific data.
41
+ */
42
+ export declare class AuditEvent<Details extends UndefinableJsonObject = UndefinableJsonObject> extends EntityWithoutMetadata {
43
+ /**
44
+ * The timestamp when the event occurred.
45
+ */
4
46
  timestamp: Timestamp;
5
- correlationId?: Uuid;
47
+ /**
48
+ * The ID of the tenant in which the event occurred. Can be null for system-level events.
49
+ */
50
+ tenantId: Uuid | null;
51
+ /**
52
+ * A unique identifier to correlate multiple related audit events.
53
+ */
54
+ correlationId: Uuid | null;
55
+ /**
56
+ * The module or feature area where the event originated, in dot-separated format.
57
+ * @example 'user.authentication'
58
+ */
6
59
  module: string;
60
+ /**
61
+ * The specific action that was performed.
62
+ * @example 'login'
63
+ */
7
64
  action: string;
65
+ /**
66
+ * The outcome of the action.
67
+ */
8
68
  outcome: AuditOutcome;
69
+ /**
70
+ * The severity level of the event.
71
+ */
9
72
  severity: AuditSeverity;
10
- actorId: string;
73
+ /**
74
+ * The unique identifier of the actor who performed the action.
75
+ */
76
+ actorId: Uuid;
77
+ /**
78
+ * The type of the actor.
79
+ */
11
80
  actorType: ActorType;
12
- targetId: string;
81
+ /**
82
+ * The unique identifier of the user who is impersonating the actor, if applicable.
83
+ */
84
+ impersonatorId: Uuid | null;
85
+ /**
86
+ * The type of the impersonator, if applicable.
87
+ */
88
+ impersonatorType: ActorType | null;
89
+ /**
90
+ * The unique identifier of the primary resource or entity that was the target of the action.
91
+ */
92
+ targetId: Uuid;
93
+ /**
94
+ * The type of the target entity.
95
+ * @example 'User'
96
+ */
13
97
  targetType: string;
14
- details?: Json<unknown>;
98
+ /**
99
+ * Network-related details for the request that triggered the event.
100
+ */
101
+ network: Embedded<RequestDetails> | null;
102
+ /**
103
+ * Details about data changes.
104
+ */
105
+ changes: Embedded<ChangeDetails> | null;
106
+ /**
107
+ * A flexible JSON object for storing additional, action-specific details.
108
+ */
109
+ details: Json<Details> | null;
15
110
  }
@@ -7,20 +7,134 @@ 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
- import { EntityWithoutMetadata, Json, Table, Timestamp, Uuid } from '../orm/index.js';
10
+ import { Embedded, EntityWithoutMetadata, Json, Table, Timestamp, Uuid } from '../orm/index.js';
11
11
  import { Enumeration, StringProperty } from '../schema/index.js';
12
12
  import { ActorType, AuditOutcome, AuditSeverity } from './types.js';
13
+ /**
14
+ * Represents the network details of the request that triggered the audit event.
15
+ */
16
+ export class RequestDetails {
17
+ /**
18
+ * The IP address of the client.
19
+ * @example '192.168.1.100'
20
+ */
21
+ ipAddress;
22
+ /**
23
+ * The user agent string of the client.
24
+ * @example 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...'
25
+ */
26
+ userAgent;
27
+ /**
28
+ * The session ID associated with the request, if any.
29
+ */
30
+ sessionId;
31
+ }
32
+ __decorate([
33
+ StringProperty({ nullable: true }),
34
+ __metadata("design:type", Object)
35
+ ], RequestDetails.prototype, "ipAddress", void 0);
36
+ __decorate([
37
+ StringProperty({ nullable: true }),
38
+ __metadata("design:type", Object)
39
+ ], RequestDetails.prototype, "userAgent", void 0);
40
+ __decorate([
41
+ Uuid({ nullable: true }),
42
+ __metadata("design:type", Object)
43
+ ], RequestDetails.prototype, "sessionId", void 0);
44
+ /**
45
+ * Represents the state of data before and after a change.
46
+ */
47
+ export class ChangeDetails {
48
+ /**
49
+ * The state of the data before the change occurred.
50
+ */
51
+ before;
52
+ /**
53
+ * The state of the data after the change occurred.
54
+ */
55
+ after;
56
+ }
57
+ __decorate([
58
+ Json({ nullable: true }),
59
+ __metadata("design:type", Object)
60
+ ], ChangeDetails.prototype, "before", void 0);
61
+ __decorate([
62
+ Json({ nullable: true }),
63
+ __metadata("design:type", Object)
64
+ ], ChangeDetails.prototype, "after", void 0);
65
+ /**
66
+ * Represents a single audit event record in the database.
67
+ * This entity captures who did what, when, and to what, along with other contextual information.
68
+ *
69
+ * @template Details The type of the `details` JSON object, allowing for custom, action-specific data.
70
+ */
13
71
  let AuditEvent = class AuditEvent extends EntityWithoutMetadata {
72
+ /**
73
+ * The timestamp when the event occurred.
74
+ */
14
75
  timestamp;
76
+ /**
77
+ * The ID of the tenant in which the event occurred. Can be null for system-level events.
78
+ */
79
+ tenantId;
80
+ /**
81
+ * A unique identifier to correlate multiple related audit events.
82
+ */
15
83
  correlationId;
84
+ /**
85
+ * The module or feature area where the event originated, in dot-separated format.
86
+ * @example 'user.authentication'
87
+ */
16
88
  module;
89
+ /**
90
+ * The specific action that was performed.
91
+ * @example 'login'
92
+ */
17
93
  action;
94
+ /**
95
+ * The outcome of the action.
96
+ */
18
97
  outcome;
98
+ /**
99
+ * The severity level of the event.
100
+ */
19
101
  severity;
102
+ /**
103
+ * The unique identifier of the actor who performed the action.
104
+ */
20
105
  actorId;
106
+ /**
107
+ * The type of the actor.
108
+ */
21
109
  actorType;
110
+ /**
111
+ * The unique identifier of the user who is impersonating the actor, if applicable.
112
+ */
113
+ impersonatorId;
114
+ /**
115
+ * The type of the impersonator, if applicable.
116
+ */
117
+ impersonatorType;
118
+ /**
119
+ * The unique identifier of the primary resource or entity that was the target of the action.
120
+ */
22
121
  targetId;
122
+ /**
123
+ * The type of the target entity.
124
+ * @example 'User'
125
+ */
23
126
  targetType;
127
+ /**
128
+ * Network-related details for the request that triggered the event.
129
+ */
130
+ network;
131
+ /**
132
+ * Details about data changes.
133
+ */
134
+ changes;
135
+ /**
136
+ * A flexible JSON object for storing additional, action-specific details.
137
+ */
24
138
  details;
25
139
  };
26
140
  __decorate([
@@ -29,7 +143,11 @@ __decorate([
29
143
  ], AuditEvent.prototype, "timestamp", void 0);
30
144
  __decorate([
31
145
  Uuid({ nullable: true }),
32
- __metadata("design:type", String)
146
+ __metadata("design:type", Object)
147
+ ], AuditEvent.prototype, "tenantId", void 0);
148
+ __decorate([
149
+ Uuid({ nullable: true }),
150
+ __metadata("design:type", Object)
33
151
  ], AuditEvent.prototype, "correlationId", void 0);
34
152
  __decorate([
35
153
  StringProperty(),
@@ -48,7 +166,7 @@ __decorate([
48
166
  __metadata("design:type", String)
49
167
  ], AuditEvent.prototype, "severity", void 0);
50
168
  __decorate([
51
- StringProperty(),
169
+ Uuid(),
52
170
  __metadata("design:type", String)
53
171
  ], AuditEvent.prototype, "actorId", void 0);
54
172
  __decorate([
@@ -56,13 +174,29 @@ __decorate([
56
174
  __metadata("design:type", String)
57
175
  ], AuditEvent.prototype, "actorType", void 0);
58
176
  __decorate([
59
- StringProperty(),
177
+ Uuid({ nullable: true }),
178
+ __metadata("design:type", Object)
179
+ ], AuditEvent.prototype, "impersonatorId", void 0);
180
+ __decorate([
181
+ Enumeration(ActorType, { nullable: true }),
182
+ __metadata("design:type", Object)
183
+ ], AuditEvent.prototype, "impersonatorType", void 0);
184
+ __decorate([
185
+ Uuid(),
60
186
  __metadata("design:type", String)
61
187
  ], AuditEvent.prototype, "targetId", void 0);
62
188
  __decorate([
63
189
  StringProperty(),
64
190
  __metadata("design:type", String)
65
191
  ], AuditEvent.prototype, "targetType", void 0);
192
+ __decorate([
193
+ Embedded(RequestDetails),
194
+ __metadata("design:type", Object)
195
+ ], AuditEvent.prototype, "network", void 0);
196
+ __decorate([
197
+ Embedded(ChangeDetails),
198
+ __metadata("design:type", Object)
199
+ ], AuditEvent.prototype, "changes", void 0);
66
200
  __decorate([
67
201
  Json({ nullable: true }),
68
202
  __metadata("design:type", Object)
@@ -1,42 +1,118 @@
1
1
  import { type Resolvable, type resolveArgumentType } from '../injector/index.js';
2
- import type { UndefinableJsonObject } from '../types/index.js';
3
- import type { ActorType } from './types.js';
4
- import { AuditOutcome, AuditSeverity } from './types.js';
5
- export type AuditPayload = Partial<{
6
- correlationId?: string;
7
- outcome?: AuditOutcome;
8
- severity?: AuditSeverity;
9
- actorId?: string;
10
- actorType?: ActorType;
11
- targetId?: string;
12
- targetType?: string;
13
- details?: UndefinableJsonObject;
2
+ import type { TypedOmit, UndefinableJsonObject } from '../types/index.js';
3
+ import { AuditEvent } from './audit.model.js';
4
+ export type AuditPayload = Partial<TypedOmit<AuditEvent, 'id' | 'timestamp' | 'module' | 'action' | 'details'> & {
5
+ details: UndefinableJsonObject;
14
6
  }>;
15
7
  export type AuditorArgument = string | string[] | {
8
+ /**
9
+ * The module or path of modules for the auditor.
10
+ */
16
11
  module?: string | string[];
12
+ /**
13
+ * Default context to apply to all events logged by this auditor instance.
14
+ */
17
15
  context?: Partial<AuditPayload>;
18
16
  };
19
- export declare class Auditor implements Resolvable<AuditorArgument> {
17
+ type AuditEvents = Record<string, UndefinableJsonObject>;
18
+ /**
19
+ * A service for logging audit events.
20
+ * It provides a structured way to record activities within the system.
21
+ * The Auditor can be forked to create sub-auditors for different modules or enriched with contextual data.
22
+ *
23
+ * @template Events A record mapping event action names to their specific `details` payload types.
24
+ */
25
+ export declare class Auditor<Events extends AuditEvents = AuditEvents> implements Resolvable<AuditorArgument> {
20
26
  #private;
27
+ /**
28
+ * The module path for this auditor instance.
29
+ */
21
30
  readonly module: string[];
22
- readonly context: Partial<Partial<{
23
- correlationId?: string;
24
- outcome?: AuditOutcome;
25
- severity?: AuditSeverity;
26
- actorId?: string;
27
- actorType?: ActorType;
28
- targetId?: string;
29
- targetType?: string;
30
- details?: UndefinableJsonObject;
31
+ /**
32
+ * The context that is automatically merged into every event logged by this auditor.
33
+ */
34
+ readonly context: Partial<Partial<TypedOmit<AuditEvent<UndefinableJsonObject>, "module" | "timestamp" | "id" | "details" | "action"> & {
35
+ details: UndefinableJsonObject;
31
36
  }>>;
37
+ /**
38
+ * A dot-separated string representation of the module path.
39
+ * @example ['user', 'authentication'] becomes 'user.authentication'
40
+ */
32
41
  get moduleString(): string;
33
42
  readonly [resolveArgumentType]: AuditorArgument;
34
- fork(subModule: string | string[]): Auditor;
35
- with(context: Partial<AuditPayload>): Auditor;
36
- withCorrelation(): Auditor;
37
- log(action: string, data?: AuditPayload): Promise<void>;
38
- info(action: string, data: AuditPayload): Promise<void>;
39
- warn(action: string, data: AuditPayload): Promise<void>;
40
- error(action: string, data: AuditPayload): Promise<void>;
41
- critical(action: string, data: AuditPayload): Promise<void>;
43
+ /**
44
+ * Creates a new `Auditor` instance for a submodule.
45
+ * The new auditor inherits the context of its parent and appends the submodule to its module path.
46
+ *
47
+ * @param subModule The name of the submodule or a path of submodules.
48
+ * @returns A new `Auditor` instance for the specified submodule.
49
+ * @template T The event map of the new Auditor instance.
50
+ */
51
+ fork<T extends AuditEvents = Events>(subModule: string | string[]): Auditor<T>;
52
+ /**
53
+ * Creates a new `Auditor` instance with additional context.
54
+ * The new context is merged with the existing context.
55
+ *
56
+ * @param context The additional context to apply.
57
+ * @returns A new `Auditor` instance with the merged context.
58
+ * @template T The event map of the new Auditor instance.
59
+ */
60
+ with<T extends AuditEvents = Events>(context: Partial<AuditPayload>): Auditor<T>;
61
+ /**
62
+ * Creates a new `Auditor` instance with a correlation ID in its context.
63
+ * If a correlation ID already exists in the context, it is preserved. Otherwise, a new UUID is generated.
64
+ *
65
+ * @returns A new `Auditor` instance with a correlation ID.
66
+ */
67
+ withCorrelation(): Auditor<Events>;
68
+ /**
69
+ * Logs a generic audit event.
70
+ *
71
+ * @param action The name of the action being logged. Must be a key of the `Events` type.
72
+ * @param data The payload containing details about the event.
73
+ */
74
+ log<E extends Extract<keyof Events, string>>(action: E, data?: AuditPayload & {
75
+ details: Events[E];
76
+ }): Promise<void>;
77
+ /**
78
+ * Logs an informational event.
79
+ * Automatically sets severity to `Info` and defaults outcome to `Success`.
80
+ *
81
+ * @param action The name of the action being logged.
82
+ * @param data The payload containing details about the event.
83
+ */
84
+ info<E extends Extract<keyof Events, string>>(action: E, data: AuditPayload & {
85
+ details: Events[E];
86
+ }): Promise<void>;
87
+ /**
88
+ * Logs a warning event.
89
+ * Automatically sets severity to `Warn` and defaults outcome to `Failure`.
90
+ *
91
+ * @param action The name of the action being logged.
92
+ * @param data The payload containing details about the event.
93
+ */
94
+ warn<E extends Extract<keyof Events, string>>(action: E, data: AuditPayload & {
95
+ details: Events[E];
96
+ }): Promise<void>;
97
+ /**
98
+ * Logs an error event.
99
+ * Automatically sets severity to `Error` and defaults outcome to `Failure`.
100
+ *
101
+ * @param action The name of the action being logged.
102
+ * @param data The payload containing details about the event.
103
+ */
104
+ error<E extends Extract<keyof Events, string>>(action: E, data: AuditPayload & {
105
+ details: Events[E];
106
+ }): Promise<void>;
107
+ /**
108
+ * Logs a critical event.
109
+ * Automatically sets severity to `Critical` and defaults outcome to `Failure`.
110
+ *
111
+ * @param action The name of the action being logged.
112
+ * @param data The payload containing details about the event.
113
+ */
114
+ critical<E extends Extract<keyof Events, string>>(action: E, data: AuditPayload & {
115
+ details: Events[E];
116
+ }): Promise<void>;
42
117
  }
118
+ export {};
package/audit/auditor.js CHANGED
@@ -19,46 +19,103 @@ import { assertDefinedPass, isArray, isNotArray, isObject, isString } from '../u
19
19
  import { AuditEvent } from './audit.model.js';
20
20
  import { AuditOutcome, AuditSeverity } from './types.js';
21
21
  const { runInAuditorCreationContext, getCurrentAuditorCreationContext, isInAuditorCreationContext } = createContextProvider('AuditorCreation');
22
+ /**
23
+ * A service for logging audit events.
24
+ * It provides a structured way to record activities within the system.
25
+ * The Auditor can be forked to create sub-auditors for different modules or enriched with contextual data.
26
+ *
27
+ * @template Events A record mapping event action names to their specific `details` payload types.
28
+ */
22
29
  let Auditor = Auditor_1 = class Auditor {
23
30
  #repository = injectRepository(AuditEvent);
24
31
  #argument = isInAuditorCreationContext() ? injectArgument(this, { optional: true }) : undefined;
25
32
  #creationContext = getCurrentAuditorCreationContext();
33
+ /**
34
+ * The module path for this auditor instance.
35
+ */
26
36
  module = this.#creationContext?.module ?? moduleFromArgument(this.#argument);
37
+ /**
38
+ * The context that is automatically merged into every event logged by this auditor.
39
+ */
27
40
  context = this.#creationContext?.context ?? ((isObject(this.#argument) && isNotArray(this.#argument)) ? (this.#argument.context ?? {}) : {});
41
+ /**
42
+ * A dot-separated string representation of the module path.
43
+ * @example ['user', 'authentication'] becomes 'user.authentication'
44
+ */
28
45
  get moduleString() {
29
46
  return this.module.join('.');
30
47
  }
48
+ /**
49
+ * Creates a new `Auditor` instance for a submodule.
50
+ * The new auditor inherits the context of its parent and appends the submodule to its module path.
51
+ *
52
+ * @param subModule The name of the submodule or a path of submodules.
53
+ * @returns A new `Auditor` instance for the specified submodule.
54
+ * @template T The event map of the new Auditor instance.
55
+ */
31
56
  fork(subModule) {
32
57
  return runInAuditorCreationContext({
33
58
  module: [...this.module, ...toArray(subModule)],
34
59
  context: this.context,
35
60
  }, () => new Auditor_1());
36
61
  }
62
+ /**
63
+ * Creates a new `Auditor` instance with additional context.
64
+ * The new context is merged with the existing context.
65
+ *
66
+ * @param context The additional context to apply.
67
+ * @returns A new `Auditor` instance with the merged context.
68
+ * @template T The event map of the new Auditor instance.
69
+ */
37
70
  with(context) {
38
71
  return runInAuditorCreationContext({
39
72
  module: this.module,
40
73
  context: { ...this.context, ...context, details: { ...this.context.details, ...context.details } },
41
74
  }, () => new Auditor_1());
42
75
  }
76
+ /**
77
+ * Creates a new `Auditor` instance with a correlation ID in its context.
78
+ * If a correlation ID already exists in the context, it is preserved. Otherwise, a new UUID is generated.
79
+ *
80
+ * @returns A new `Auditor` instance with a correlation ID.
81
+ */
43
82
  withCorrelation() {
44
83
  return this.with({ correlationId: this.context.correlationId ?? crypto.randomUUID() });
45
84
  }
85
+ /**
86
+ * Logs a generic audit event.
87
+ *
88
+ * @param action The name of the action being logged. Must be a key of the `Events` type.
89
+ * @param data The payload containing details about the event.
90
+ */
46
91
  async log(action, data) {
47
92
  const mergedData = { ...this.context, ...data, details: filterUndefinedFromRecord({ ...this.context.details, ...data?.details }) };
48
93
  await this.#repository.insert({
49
94
  timestamp: TRANSACTION_TIMESTAMP,
50
- correlationId: mergedData.correlationId,
95
+ tenantId: mergedData.tenantId ?? null,
96
+ correlationId: mergedData.correlationId ?? null,
51
97
  module: this.moduleString,
52
98
  action: action,
53
99
  outcome: assertDefinedPass(mergedData.outcome, 'Audit outcome is required'),
54
100
  severity: assertDefinedPass(mergedData.severity, 'Audit severity is required'),
55
101
  actorId: assertDefinedPass(mergedData.actorId, 'Audit actorId is required'),
56
102
  actorType: assertDefinedPass(mergedData.actorType, 'Audit actorType is required'),
103
+ impersonatorId: mergedData.impersonatorId ?? null,
104
+ impersonatorType: mergedData.impersonatorType ?? null,
57
105
  targetId: assertDefinedPass(mergedData.targetId, 'Audit targetId is required'),
58
106
  targetType: assertDefinedPass(mergedData.targetType, 'Audit targetType is required'),
59
- details: (objectKeys(mergedData.details).length > 0) ? mergedData.details : undefined,
107
+ network: mergedData.network ?? null,
108
+ changes: mergedData.changes ?? null,
109
+ details: (objectKeys(mergedData.details).length > 0) ? mergedData.details : null,
60
110
  });
61
111
  }
112
+ /**
113
+ * Logs an informational event.
114
+ * Automatically sets severity to `Info` and defaults outcome to `Success`.
115
+ *
116
+ * @param action The name of the action being logged.
117
+ * @param data The payload containing details about the event.
118
+ */
62
119
  async info(action, data) {
63
120
  await this.log(action, {
64
121
  ...data,
@@ -66,6 +123,13 @@ let Auditor = Auditor_1 = class Auditor {
66
123
  outcome: data.outcome ?? AuditOutcome.Success,
67
124
  });
68
125
  }
126
+ /**
127
+ * Logs a warning event.
128
+ * Automatically sets severity to `Warn` and defaults outcome to `Failure`.
129
+ *
130
+ * @param action The name of the action being logged.
131
+ * @param data The payload containing details about the event.
132
+ */
69
133
  async warn(action, data) {
70
134
  await this.log(action, {
71
135
  ...data,
@@ -73,6 +137,13 @@ let Auditor = Auditor_1 = class Auditor {
73
137
  outcome: data.outcome ?? AuditOutcome.Failure,
74
138
  });
75
139
  }
140
+ /**
141
+ * Logs an error event.
142
+ * Automatically sets severity to `Error` and defaults outcome to `Failure`.
143
+ *
144
+ * @param action The name of the action being logged.
145
+ * @param data The payload containing details about the event.
146
+ */
76
147
  async error(action, data) {
77
148
  await this.log(action, {
78
149
  ...data,
@@ -80,6 +151,13 @@ let Auditor = Auditor_1 = class Auditor {
80
151
  outcome: data.outcome ?? AuditOutcome.Failure,
81
152
  });
82
153
  }
154
+ /**
155
+ * Logs a critical event.
156
+ * Automatically sets severity to `Critical` and defaults outcome to `Failure`.
157
+ *
158
+ * @param action The name of the action being logged.
159
+ * @param data The payload containing details about the event.
160
+ */
83
161
  async critical(action, data) {
84
162
  await this.log(action, {
85
163
  ...data,
@@ -0,0 +1,25 @@
1
+ CREATE TYPE "audit"."actor_type" AS ENUM('user', 'system', 'api-key');--> statement-breakpoint
2
+ CREATE TYPE "audit"."audit_outcome" AS ENUM('pending', 'success', 'cancelled', 'failure', 'denied');--> statement-breakpoint
3
+ CREATE TYPE "audit"."audit_severity" AS ENUM('info', 'warn', 'error', 'critical');--> statement-breakpoint
4
+ CREATE TABLE "audit"."event" (
5
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
6
+ "timestamp" timestamp with time zone NOT NULL,
7
+ "tenant_id" uuid,
8
+ "correlation_id" uuid,
9
+ "module" text NOT NULL,
10
+ "action" text NOT NULL,
11
+ "outcome" "audit"."audit_outcome" NOT NULL,
12
+ "severity" "audit"."audit_severity" NOT NULL,
13
+ "actor_id" uuid NOT NULL,
14
+ "actor_type" "audit"."actor_type" NOT NULL,
15
+ "impersonator_id" uuid,
16
+ "impersonator_type" "audit"."actor_type",
17
+ "target_id" uuid NOT NULL,
18
+ "target_type" text NOT NULL,
19
+ "network_ip_address" text,
20
+ "network_user_agent" text,
21
+ "network_session_id" uuid,
22
+ "changes_before" jsonb,
23
+ "changes_after" jsonb,
24
+ "details" jsonb
25
+ );