@nest-toolbox/typeorm-audit-log 1.8.1
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/LICENSE +21 -0
- package/README.md +283 -0
- package/dist/audit-context.d.ts +67 -0
- package/dist/audit-context.js +96 -0
- package/dist/audit-context.js.map +1 -0
- package/dist/audit-context.middleware.d.ts +76 -0
- package/dist/audit-context.middleware.js +91 -0
- package/dist/audit-context.middleware.js.map +1 -0
- package/dist/audit-log.entity.d.ts +56 -0
- package/dist/audit-log.entity.js +89 -0
- package/dist/audit-log.entity.js.map +1 -0
- package/dist/audit-log.module.d.ts +56 -0
- package/dist/audit-log.module.js +130 -0
- package/dist/audit-log.module.js.map +1 -0
- package/dist/audit-log.service.d.ts +43 -0
- package/dist/audit-log.service.js +177 -0
- package/dist/audit-log.service.js.map +1 -0
- package/dist/audit-log.subscriber.d.ts +66 -0
- package/dist/audit-log.subscriber.js +135 -0
- package/dist/audit-log.subscriber.js.map +1 -0
- package/dist/constants.d.ts +32 -0
- package/dist/constants.js +49 -0
- package/dist/constants.js.map +1 -0
- package/dist/decorators.d.ts +109 -0
- package/dist/decorators.js +161 -0
- package/dist/decorators.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/dist/types.d.ts +161 -0
- package/dist/types.js +16 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/diff.d.ts +16 -0
- package/dist/utils/diff.js +142 -0
- package/dist/utils/diff.js.map +1 -0
- package/dist/utils/mask.d.ts +15 -0
- package/dist/utils/mask.js +69 -0
- package/dist/utils/mask.js.map +1 -0
- package/package.json +63 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for @nest-toolbox/typeorm-audit-log
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Audit action types
|
|
6
|
+
*/
|
|
7
|
+
export declare enum AuditAction {
|
|
8
|
+
CREATE = "CREATE",
|
|
9
|
+
UPDATE = "UPDATE",
|
|
10
|
+
DELETE = "DELETE"
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Represents a single field change in an audit log
|
|
14
|
+
*/
|
|
15
|
+
export interface AuditDiff {
|
|
16
|
+
field: string;
|
|
17
|
+
oldValue: any;
|
|
18
|
+
newValue: any;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Context data captured for audit logging
|
|
22
|
+
*/
|
|
23
|
+
export interface AuditContextData {
|
|
24
|
+
userId?: string;
|
|
25
|
+
userName?: string;
|
|
26
|
+
ip?: string;
|
|
27
|
+
userAgent?: string;
|
|
28
|
+
metadata?: Record<string, any>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Options for @Auditable() decorator
|
|
32
|
+
*/
|
|
33
|
+
export interface AuditableOptions {
|
|
34
|
+
/**
|
|
35
|
+
* Custom entity name (defaults to class name)
|
|
36
|
+
*/
|
|
37
|
+
entityName?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Fields to exclude from audit logging for this entity
|
|
40
|
+
*/
|
|
41
|
+
excludeFields?: string[];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Options for @AuditMask() decorator
|
|
45
|
+
*/
|
|
46
|
+
export interface AuditMaskOptions {
|
|
47
|
+
/**
|
|
48
|
+
* Custom mask function. Defaults to masking middle characters.
|
|
49
|
+
* @param value - The original value
|
|
50
|
+
* @returns The masked value
|
|
51
|
+
*/
|
|
52
|
+
maskFn?: (value: any) => string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Parameters for logging an audit entry
|
|
56
|
+
*/
|
|
57
|
+
export interface LogParams {
|
|
58
|
+
action: AuditAction;
|
|
59
|
+
entity: any;
|
|
60
|
+
entityName: string;
|
|
61
|
+
entityId: string;
|
|
62
|
+
oldValues?: any;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Options for finding audit logs by user
|
|
66
|
+
*/
|
|
67
|
+
export interface FindByUserOptions {
|
|
68
|
+
since?: Date;
|
|
69
|
+
until?: Date;
|
|
70
|
+
entityName?: string;
|
|
71
|
+
action?: AuditAction;
|
|
72
|
+
limit?: number;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Options for finding audit logs by entity
|
|
76
|
+
*/
|
|
77
|
+
export interface FindByEntityOptions {
|
|
78
|
+
since?: Date;
|
|
79
|
+
until?: Date;
|
|
80
|
+
action?: AuditAction;
|
|
81
|
+
limit?: number;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Options for finding all audit logs
|
|
85
|
+
*/
|
|
86
|
+
export interface FindAllOptions {
|
|
87
|
+
since?: Date;
|
|
88
|
+
until?: Date;
|
|
89
|
+
entityName?: string;
|
|
90
|
+
entityId?: string;
|
|
91
|
+
userId?: string;
|
|
92
|
+
action?: AuditAction;
|
|
93
|
+
page?: number;
|
|
94
|
+
limit?: number;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Paginated result for audit log queries
|
|
98
|
+
*/
|
|
99
|
+
export interface PaginatedResult<T> {
|
|
100
|
+
items: T[];
|
|
101
|
+
total: number;
|
|
102
|
+
page: number;
|
|
103
|
+
limit: number;
|
|
104
|
+
totalPages: number;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Module configuration options
|
|
108
|
+
*/
|
|
109
|
+
export interface AuditLogModuleOptions {
|
|
110
|
+
/**
|
|
111
|
+
* Storage type for audit logs
|
|
112
|
+
* @default 'database'
|
|
113
|
+
*/
|
|
114
|
+
storage?: 'database' | 'file' | 'webhook';
|
|
115
|
+
/**
|
|
116
|
+
* Custom table name for audit logs
|
|
117
|
+
* @default 'audit_logs'
|
|
118
|
+
*/
|
|
119
|
+
tableName?: string;
|
|
120
|
+
/**
|
|
121
|
+
* Number of days to retain audit logs (0 = forever)
|
|
122
|
+
* @default 0
|
|
123
|
+
*/
|
|
124
|
+
retentionDays?: number;
|
|
125
|
+
/**
|
|
126
|
+
* Fields to globally exclude from all audit logs
|
|
127
|
+
*/
|
|
128
|
+
excludeFields?: string[];
|
|
129
|
+
/**
|
|
130
|
+
* Entity names to exclude from auditing
|
|
131
|
+
*/
|
|
132
|
+
excludeEntities?: string[];
|
|
133
|
+
/**
|
|
134
|
+
* Webhook URL for webhook storage type
|
|
135
|
+
*/
|
|
136
|
+
webhookUrl?: string;
|
|
137
|
+
/**
|
|
138
|
+
* File path for file storage type
|
|
139
|
+
*/
|
|
140
|
+
filePath?: string;
|
|
141
|
+
/**
|
|
142
|
+
* Don't block on audit log writes
|
|
143
|
+
* @default false
|
|
144
|
+
*/
|
|
145
|
+
async?: boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Batch size for bulk writes
|
|
148
|
+
* @default 1
|
|
149
|
+
*/
|
|
150
|
+
batchSize?: number;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Async module options for forRootAsync
|
|
154
|
+
*/
|
|
155
|
+
export interface AuditLogModuleAsyncOptions {
|
|
156
|
+
imports?: any[];
|
|
157
|
+
useFactory?: (...args: any[]) => Promise<AuditLogModuleOptions> | AuditLogModuleOptions;
|
|
158
|
+
inject?: any[];
|
|
159
|
+
useClass?: any;
|
|
160
|
+
useExisting?: any;
|
|
161
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Types for @nest-toolbox/typeorm-audit-log
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.AuditAction = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Audit action types
|
|
9
|
+
*/
|
|
10
|
+
var AuditAction;
|
|
11
|
+
(function (AuditAction) {
|
|
12
|
+
AuditAction["CREATE"] = "CREATE";
|
|
13
|
+
AuditAction["UPDATE"] = "UPDATE";
|
|
14
|
+
AuditAction["DELETE"] = "DELETE";
|
|
15
|
+
})(AuditAction || (exports.AuditAction = AuditAction = {}));
|
|
16
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH;;GAEG;AACH,IAAY,WAIX;AAJD,WAAY,WAAW;IACrB,gCAAiB,CAAA;IACjB,gCAAiB,CAAA;IACjB,gCAAiB,CAAA;AACnB,CAAC,EAJW,WAAW,2BAAX,WAAW,QAItB"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AuditDiff } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Calculate the difference between two objects using deep-diff.
|
|
4
|
+
* Returns an array of field changes suitable for audit logging.
|
|
5
|
+
*
|
|
6
|
+
* @param oldValues - The original object state
|
|
7
|
+
* @param newValues - The new object state
|
|
8
|
+
* @param excludeFields - Fields to exclude from diff calculation
|
|
9
|
+
* @returns Array of AuditDiff entries, or null if no changes
|
|
10
|
+
*/
|
|
11
|
+
export declare function calculateDiff(oldValues: any, newValues: any, excludeFields?: string[]): AuditDiff[] | null;
|
|
12
|
+
/**
|
|
13
|
+
* Simple diff calculation for cases where deep-diff is not needed.
|
|
14
|
+
* Only compares top-level primitive values.
|
|
15
|
+
*/
|
|
16
|
+
export declare function calculateSimpleDiff(oldValues: any, newValues: any, excludeFields?: string[]): AuditDiff[] | null;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calculateDiff = calculateDiff;
|
|
4
|
+
exports.calculateSimpleDiff = calculateSimpleDiff;
|
|
5
|
+
const deep_diff_1 = require("deep-diff");
|
|
6
|
+
/**
|
|
7
|
+
* Calculate the difference between two objects using deep-diff.
|
|
8
|
+
* Returns an array of field changes suitable for audit logging.
|
|
9
|
+
*
|
|
10
|
+
* @param oldValues - The original object state
|
|
11
|
+
* @param newValues - The new object state
|
|
12
|
+
* @param excludeFields - Fields to exclude from diff calculation
|
|
13
|
+
* @returns Array of AuditDiff entries, or null if no changes
|
|
14
|
+
*/
|
|
15
|
+
function calculateDiff(
|
|
16
|
+
// biome-ignore lint/suspicious/noExplicitAny: values can be any type
|
|
17
|
+
oldValues,
|
|
18
|
+
// biome-ignore lint/suspicious/noExplicitAny: values can be any type
|
|
19
|
+
newValues, excludeFields = []) {
|
|
20
|
+
var _a, _b, _c, _d, _e;
|
|
21
|
+
if (!oldValues || !newValues) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const differences = (0, deep_diff_1.diff)(oldValues, newValues);
|
|
25
|
+
if (!differences || differences.length === 0) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const result = [];
|
|
29
|
+
for (const d of differences) {
|
|
30
|
+
// Get the field path (e.g., 'address.city' for nested objects)
|
|
31
|
+
const fieldPath = (_b = (_a = d.path) === null || _a === void 0 ? void 0 : _a.join('.')) !== null && _b !== void 0 ? _b : '';
|
|
32
|
+
// Skip internal TypeORM properties
|
|
33
|
+
if (fieldPath.startsWith('_')) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
// Skip excluded fields
|
|
37
|
+
const rootField = (_e = (_d = (_c = d.path) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.toString()) !== null && _e !== void 0 ? _e : '';
|
|
38
|
+
if (excludeFields.includes(rootField) || excludeFields.includes(fieldPath)) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
// Handle different types of changes
|
|
42
|
+
switch (d.kind) {
|
|
43
|
+
case 'N': // New property
|
|
44
|
+
result.push({
|
|
45
|
+
field: fieldPath,
|
|
46
|
+
oldValue: undefined,
|
|
47
|
+
newValue: d.rhs,
|
|
48
|
+
});
|
|
49
|
+
break;
|
|
50
|
+
case 'D': // Deleted property
|
|
51
|
+
result.push({
|
|
52
|
+
field: fieldPath,
|
|
53
|
+
oldValue: d.lhs,
|
|
54
|
+
newValue: undefined,
|
|
55
|
+
});
|
|
56
|
+
break;
|
|
57
|
+
case 'E': // Edited property
|
|
58
|
+
result.push({
|
|
59
|
+
field: fieldPath,
|
|
60
|
+
oldValue: d.lhs,
|
|
61
|
+
newValue: d.rhs,
|
|
62
|
+
});
|
|
63
|
+
break;
|
|
64
|
+
case 'A': // Array change
|
|
65
|
+
// For arrays, we track the whole array change at the root level
|
|
66
|
+
// rather than individual index changes for simplicity
|
|
67
|
+
if (d.path && d.path.length > 0) {
|
|
68
|
+
const arrayField = d.path.slice(0, -1).join('.');
|
|
69
|
+
// Check if we already have this array in results
|
|
70
|
+
if (!result.some((r) => r.field === arrayField)) {
|
|
71
|
+
result.push({
|
|
72
|
+
field: arrayField || rootField,
|
|
73
|
+
oldValue: getNestedValue(oldValues, d.path.slice(0, -1)),
|
|
74
|
+
newValue: getNestedValue(newValues, d.path.slice(0, -1)),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return result.length > 0 ? result : null;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Get a nested value from an object using a path array.
|
|
85
|
+
*/
|
|
86
|
+
// biome-ignore lint/suspicious/noExplicitAny: utility function for any object
|
|
87
|
+
function getNestedValue(obj, path) {
|
|
88
|
+
let current = obj;
|
|
89
|
+
for (const key of path) {
|
|
90
|
+
if (current === null || current === undefined) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
current = current[key];
|
|
94
|
+
}
|
|
95
|
+
return current;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Simple diff calculation for cases where deep-diff is not needed.
|
|
99
|
+
* Only compares top-level primitive values.
|
|
100
|
+
*/
|
|
101
|
+
function calculateSimpleDiff(
|
|
102
|
+
// biome-ignore lint/suspicious/noExplicitAny: values can be any type
|
|
103
|
+
oldValues,
|
|
104
|
+
// biome-ignore lint/suspicious/noExplicitAny: values can be any type
|
|
105
|
+
newValues, excludeFields = []) {
|
|
106
|
+
if (!oldValues || !newValues) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
const diff = [];
|
|
110
|
+
const allKeys = new Set([...Object.keys(oldValues), ...Object.keys(newValues)]);
|
|
111
|
+
for (const key of allKeys) {
|
|
112
|
+
// Skip internal TypeORM properties
|
|
113
|
+
if (key.startsWith('_')) {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
// Skip excluded fields
|
|
117
|
+
if (excludeFields.includes(key)) {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const oldVal = oldValues[key];
|
|
121
|
+
const newVal = newValues[key];
|
|
122
|
+
// Skip complex objects (use calculateDiff for those)
|
|
123
|
+
if (typeof oldVal === 'object' && oldVal !== null && !(oldVal instanceof Date)) {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (typeof newVal === 'object' && newVal !== null && !(newVal instanceof Date)) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
// Compare values (handle Date objects)
|
|
130
|
+
const oldCompare = oldVal instanceof Date ? oldVal.getTime() : oldVal;
|
|
131
|
+
const newCompare = newVal instanceof Date ? newVal.getTime() : newVal;
|
|
132
|
+
if (oldCompare !== newCompare) {
|
|
133
|
+
diff.push({
|
|
134
|
+
field: key,
|
|
135
|
+
oldValue: oldVal,
|
|
136
|
+
newValue: newVal,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return diff.length > 0 ? diff : null;
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/utils/diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Apply masking and field exclusions to entity values.
|
|
3
|
+
* Uses @AuditIgnore and @AuditMask decorators from the entity class.
|
|
4
|
+
*
|
|
5
|
+
* @param values - The entity values to process
|
|
6
|
+
* @param entityClass - The entity class constructor (for reading decorators)
|
|
7
|
+
* @param globalExcludeFields - Additional fields to exclude globally
|
|
8
|
+
* @returns Processed values with ignored fields removed and masked fields masked
|
|
9
|
+
*/
|
|
10
|
+
export declare function applyMaskAndExclusions(values: any, entityClass: Function | null, globalExcludeFields?: string[]): Record<string, unknown> | null;
|
|
11
|
+
/**
|
|
12
|
+
* Get the list of all fields that should be excluded from audit logging.
|
|
13
|
+
* Combines @AuditIgnore decorator fields with global exclusions.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getAllExcludedFields(entityClass: Function | null, globalExcludeFields?: string[]): string[];
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.applyMaskAndExclusions = applyMaskAndExclusions;
|
|
4
|
+
exports.getAllExcludedFields = getAllExcludedFields;
|
|
5
|
+
const decorators_1 = require("../decorators");
|
|
6
|
+
/**
|
|
7
|
+
* Apply masking and field exclusions to entity values.
|
|
8
|
+
* Uses @AuditIgnore and @AuditMask decorators from the entity class.
|
|
9
|
+
*
|
|
10
|
+
* @param values - The entity values to process
|
|
11
|
+
* @param entityClass - The entity class constructor (for reading decorators)
|
|
12
|
+
* @param globalExcludeFields - Additional fields to exclude globally
|
|
13
|
+
* @returns Processed values with ignored fields removed and masked fields masked
|
|
14
|
+
*/
|
|
15
|
+
function applyMaskAndExclusions(
|
|
16
|
+
// biome-ignore lint/suspicious/noExplicitAny: entity values can be any type
|
|
17
|
+
values,
|
|
18
|
+
// biome-ignore lint/complexity/noBannedTypes: ClassDecorator requires Function type
|
|
19
|
+
entityClass, globalExcludeFields = []) {
|
|
20
|
+
if (!values) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const result = {};
|
|
24
|
+
// Get ignored fields from decorator
|
|
25
|
+
const ignoredFields = entityClass ? (0, decorators_1.getIgnoredFields)(entityClass) : [];
|
|
26
|
+
for (const [key, value] of Object.entries(values)) {
|
|
27
|
+
// Skip internal TypeORM properties
|
|
28
|
+
if (key.startsWith('_')) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
// Skip globally excluded fields
|
|
32
|
+
if (globalExcludeFields.includes(key)) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
// Skip fields marked with @AuditIgnore
|
|
36
|
+
if (ignoredFields.includes(key)) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
// Skip functions
|
|
40
|
+
if (typeof value === 'function') {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
// Skip complex objects (relations) - just store primitives
|
|
44
|
+
if (typeof value === 'object' && value !== null && !(value instanceof Date)) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
// Check if field should be masked
|
|
48
|
+
const maskFn = entityClass ? (0, decorators_1.getFieldMaskFn)(entityClass, key) : undefined;
|
|
49
|
+
if (maskFn && value !== null && value !== undefined) {
|
|
50
|
+
result[key] = maskFn(value);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
result[key] = value;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return Object.keys(result).length > 0 ? result : null;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get the list of all fields that should be excluded from audit logging.
|
|
60
|
+
* Combines @AuditIgnore decorator fields with global exclusions.
|
|
61
|
+
*/
|
|
62
|
+
function getAllExcludedFields(
|
|
63
|
+
// biome-ignore lint/complexity/noBannedTypes: ClassDecorator requires Function type
|
|
64
|
+
entityClass, globalExcludeFields = []) {
|
|
65
|
+
const ignoredFields = entityClass ? (0, decorators_1.getIgnoredFields)(entityClass) : [];
|
|
66
|
+
const combined = new Set([...globalExcludeFields, ...ignoredFields.map(String)]);
|
|
67
|
+
return Array.from(combined);
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=mask.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mask.js","sourceRoot":"","sources":["../../src/utils/mask.ts"],"names":[],"mappings":";;AAWA,wDAoDC;AAMD,oDAQC;AA7ED,8CAAiE;AAEjE;;;;;;;;GAQG;AACH,SAAgB,sBAAsB;AACpC,4EAA4E;AAC5E,MAAW;AACX,oFAAoF;AACpF,WAA4B,EAC5B,sBAAgC,EAAE;IAElC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAA4B,EAAE,CAAC;IAE3C,oCAAoC;IACpC,MAAM,aAAa,GAAG,WAAW,CAAC,CAAC,CAAC,IAAA,6BAAgB,EAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAEvE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,mCAAmC;QACnC,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,SAAS;QACX,CAAC;QAED,gCAAgC;QAChC,IAAI,mBAAmB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACtC,SAAS;QACX,CAAC;QAED,uCAAuC;QACvC,IAAI,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAChC,SAAS;QACX,CAAC;QAED,iBAAiB;QACjB,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;YAChC,SAAS;QACX,CAAC;QAED,2DAA2D;QAC3D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,CAAC,KAAK,YAAY,IAAI,CAAC,EAAE,CAAC;YAC5E,SAAS;QACX,CAAC;QAED,kCAAkC;QAClC,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,IAAA,2BAAc,EAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1E,IAAI,MAAM,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACpD,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACxD,CAAC;AAED;;;GAGG;AACH,SAAgB,oBAAoB;AAClC,oFAAoF;AACpF,WAA4B,EAC5B,sBAAgC,EAAE;IAElC,MAAM,aAAa,GAAG,WAAW,CAAC,CAAC,CAAC,IAAA,6BAAgB,EAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACvE,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,mBAAmB,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACjF,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC9B,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nest-toolbox/typeorm-audit-log",
|
|
3
|
+
"description": "Automatic audit logging for TypeORM entities with user attribution and diff tracking",
|
|
4
|
+
"version": "1.8.1",
|
|
5
|
+
"author": "bogdanlupu <lupu60@gmail.com>",
|
|
6
|
+
"homepage": "https://github.com/lupu60/nestjs-toolbox/tree/master/packages/typeorm-audit-log#readme",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"typeorm",
|
|
10
|
+
"audit-log",
|
|
11
|
+
"audit-trail",
|
|
12
|
+
"nestjs",
|
|
13
|
+
"orm",
|
|
14
|
+
"compliance",
|
|
15
|
+
"toolbox"
|
|
16
|
+
],
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/lupu60/nestjs-toolbox.git"
|
|
20
|
+
},
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/lupu60/nestjs-toolbox/issues"
|
|
23
|
+
},
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"registry": "https://registry.npmjs.org/",
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"main": "dist/index",
|
|
29
|
+
"types": "dist/index",
|
|
30
|
+
"files": [
|
|
31
|
+
"dist"
|
|
32
|
+
],
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=19 <=22",
|
|
35
|
+
"npm": "<=11"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "npm run clean && npm run compile",
|
|
39
|
+
"clean": "rimraf -rf ./dist",
|
|
40
|
+
"cleanup": "rimraf -rf dist coverage",
|
|
41
|
+
"compile": "tsc -p tsconfig.build.json",
|
|
42
|
+
"lint": "biome check src",
|
|
43
|
+
"test": "vitest run --config ../../vitest.config.ts",
|
|
44
|
+
"prepublishOnly": "npm run build"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"deep-diff": "^1.0.2",
|
|
48
|
+
"reflect-metadata": "0.2.2",
|
|
49
|
+
"typeorm": "0.3.26"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/deep-diff": "^1.0.5",
|
|
53
|
+
"@types/node": "24.0.3",
|
|
54
|
+
"rimraf": "6.0.1",
|
|
55
|
+
"typescript": "5.9.3"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"@nestjs/common": "^10.0.0",
|
|
59
|
+
"@nestjs/core": "^10.0.0",
|
|
60
|
+
"@nestjs/typeorm": "^10.0.0",
|
|
61
|
+
"typeorm": "^0.3.0"
|
|
62
|
+
}
|
|
63
|
+
}
|