@composed-di/core 0.5.2-alpha → 0.6.0-alpha
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/dist/errors.d.ts +0 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +4 -4
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +1 -1
- package/dist/serviceFactory.d.ts.map +1 -1
- package/dist/serviceFactory.js.map +1 -1
- package/dist/serviceKey.d.ts +6 -0
- package/dist/serviceKey.d.ts.map +1 -1
- package/dist/serviceKey.js.map +1 -1
- package/dist/serviceModule.d.ts +1 -11
- package/dist/serviceModule.d.ts.map +1 -1
- package/dist/serviceModule.js +3 -146
- package/dist/serviceModule.js.map +1 -1
- package/dist/serviceScope.d.ts.map +1 -1
- package/dist/serviceScope.js.map +1 -1
- package/dist/serviceSelector.d.ts.map +1 -1
- package/dist/serviceSelector.js.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js.map +1 -1
- package/package.json +17 -17
- package/src/errors.ts +2 -10
- package/src/index.ts +7 -9
- package/src/serviceFactory.ts +33 -33
- package/src/serviceKey.ts +11 -4
- package/src/serviceModule.ts +53 -217
- package/src/serviceScope.ts +2 -2
- package/src/serviceSelector.ts +4 -4
- package/src/utils.ts +103 -103
- package/dist/redactingEventListener.d.ts +0 -57
- package/dist/redactingEventListener.d.ts.map +0 -1
- package/dist/redactingEventListener.js +0 -89
- package/dist/redactingEventListener.js.map +0 -1
- package/dist/serviceEventListener.d.ts +0 -133
- package/dist/serviceEventListener.d.ts.map +0 -1
- package/dist/serviceEventListener.js +0 -3
- package/dist/serviceEventListener.js.map +0 -1
- package/dist/serviceModuleListener.d.ts +0 -133
- package/dist/serviceModuleListener.d.ts.map +0 -1
- package/dist/serviceModuleListener.js +0 -3
- package/dist/serviceModuleListener.js.map +0 -1
- package/src/redactingEventListener.ts +0 -132
- package/src/serviceModuleListener.ts +0 -139
package/src/utils.ts
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
import { ServiceModule } from './serviceModule'
|
|
2
|
-
import { ServiceKey } from './serviceKey'
|
|
1
|
+
import { ServiceModule } from './serviceModule'
|
|
2
|
+
import { ServiceKey } from './serviceKey'
|
|
3
3
|
|
|
4
4
|
export interface DotGraphOptions {
|
|
5
5
|
/** Graph direction: 'TB' (top-bottom), 'LR' (left-right), 'BT' (bottom-top), 'RL' (right-left) */
|
|
6
|
-
direction?: 'TB' | 'LR' | 'BT' | 'RL'
|
|
6
|
+
direction?: 'TB' | 'LR' | 'BT' | 'RL'
|
|
7
7
|
/** Title for the graph */
|
|
8
|
-
title?: string
|
|
8
|
+
title?: string
|
|
9
9
|
/** Show nodes with no dependencies in a different color */
|
|
10
|
-
highlightLeaves?: boolean
|
|
10
|
+
highlightLeaves?: boolean
|
|
11
11
|
/** Show nodes with no dependents in a different color */
|
|
12
|
-
highlightRoots?: boolean
|
|
12
|
+
highlightRoots?: boolean
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export interface MermaidGraphOptions {
|
|
16
16
|
/** Graph direction: 'TB' (top-bottom), 'LR' (left-right), 'BT' (bottom-top), 'RL' (right-left) */
|
|
17
|
-
direction?: 'TB' | 'LR' | 'BT' | 'RL'
|
|
17
|
+
direction?: 'TB' | 'LR' | 'BT' | 'RL'
|
|
18
18
|
/** Show nodes with no dependencies in a different color */
|
|
19
|
-
highlightLeaves?: boolean
|
|
19
|
+
highlightLeaves?: boolean
|
|
20
20
|
/** Show nodes with no dependents in a different color */
|
|
21
|
-
highlightRoots?: boolean
|
|
21
|
+
highlightRoots?: boolean
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Escapes special characters in strings for DOT notation
|
|
26
26
|
*/
|
|
27
27
|
function escapeDotString(str: string): string {
|
|
28
|
-
return str.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n')
|
|
28
|
+
return str.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n')
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* Escapes special characters in strings for Mermaid notation
|
|
33
33
|
*/
|
|
34
34
|
function escapeMermaidString(str: string): string {
|
|
35
|
-
return str.replace(/"/g, '#quot;')
|
|
35
|
+
return str.replace(/"/g, '#quot;')
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
/**
|
|
@@ -56,98 +56,98 @@ export function createDotGraph(
|
|
|
56
56
|
highlightRoots: true,
|
|
57
57
|
},
|
|
58
58
|
): string {
|
|
59
|
-
const factories = module.factories
|
|
60
|
-
const lines: string[] = []
|
|
59
|
+
const factories = module.factories
|
|
60
|
+
const lines: string[] = []
|
|
61
61
|
|
|
62
62
|
// Start the digraph
|
|
63
|
-
lines.push('digraph ServiceDependencies {')
|
|
64
|
-
lines.push(` label="${title}";`)
|
|
65
|
-
lines.push(' labelloc="t";')
|
|
66
|
-
lines.push(' fontsize=16;')
|
|
67
|
-
lines.push(` rankdir=${direction};`)
|
|
68
|
-
lines.push('')
|
|
63
|
+
lines.push('digraph ServiceDependencies {')
|
|
64
|
+
lines.push(` label="${title}";`)
|
|
65
|
+
lines.push(' labelloc="t";')
|
|
66
|
+
lines.push(' fontsize=16;')
|
|
67
|
+
lines.push(` rankdir=${direction};`)
|
|
68
|
+
lines.push('')
|
|
69
69
|
|
|
70
70
|
// Default node styling
|
|
71
|
-
lines.push(' node [')
|
|
72
|
-
lines.push(' shape=box,')
|
|
73
|
-
lines.push(' style="rounded,filled",')
|
|
74
|
-
lines.push(' fillcolor="#e1f5ff",')
|
|
75
|
-
lines.push(' color="#0288d1",')
|
|
76
|
-
lines.push(' fontname="Arial",')
|
|
77
|
-
lines.push(' fontsize=12')
|
|
78
|
-
lines.push(' ];')
|
|
79
|
-
lines.push('')
|
|
71
|
+
lines.push(' node [')
|
|
72
|
+
lines.push(' shape=box,')
|
|
73
|
+
lines.push(' style="rounded,filled",')
|
|
74
|
+
lines.push(' fillcolor="#e1f5ff",')
|
|
75
|
+
lines.push(' color="#0288d1",')
|
|
76
|
+
lines.push(' fontname="Arial",')
|
|
77
|
+
lines.push(' fontsize=12')
|
|
78
|
+
lines.push(' ];')
|
|
79
|
+
lines.push('')
|
|
80
80
|
|
|
81
81
|
// Default edge styling
|
|
82
|
-
lines.push(' edge [')
|
|
83
|
-
lines.push(' color="#666666",')
|
|
84
|
-
lines.push(' arrowsize=0.8')
|
|
85
|
-
lines.push(' ];')
|
|
86
|
-
lines.push('')
|
|
82
|
+
lines.push(' edge [')
|
|
83
|
+
lines.push(' color="#666666",')
|
|
84
|
+
lines.push(' arrowsize=0.8')
|
|
85
|
+
lines.push(' ];')
|
|
86
|
+
lines.push('')
|
|
87
87
|
|
|
88
88
|
// Build dependency maps to identify leaves and roots
|
|
89
|
-
const hasDependencies = new Set<string>()
|
|
90
|
-
const hasDependents = new Set<string>()
|
|
89
|
+
const hasDependencies = new Set<string>()
|
|
90
|
+
const hasDependents = new Set<string>()
|
|
91
91
|
|
|
92
92
|
factories.forEach((factory) => {
|
|
93
|
-
const serviceName = factory.provides.name
|
|
93
|
+
const serviceName = factory.provides.name
|
|
94
94
|
|
|
95
95
|
if (factory.dependsOn.length > 0) {
|
|
96
|
-
hasDependencies.add(serviceName)
|
|
96
|
+
hasDependencies.add(serviceName)
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
factory.dependsOn.forEach((dependency: ServiceKey<unknown>) => {
|
|
100
|
-
hasDependents.add(dependency.name)
|
|
101
|
-
})
|
|
102
|
-
})
|
|
100
|
+
hasDependents.add(dependency.name)
|
|
101
|
+
})
|
|
102
|
+
})
|
|
103
103
|
|
|
104
104
|
// Define nodes with special styling for leaves and roots
|
|
105
|
-
const nodeIds = new Map<string, string>()
|
|
106
|
-
let nodeCounter = 0
|
|
105
|
+
const nodeIds = new Map<string, string>()
|
|
106
|
+
let nodeCounter = 0
|
|
107
107
|
|
|
108
108
|
factories.forEach((factory) => {
|
|
109
|
-
const serviceName = factory.provides.name
|
|
110
|
-
const nodeId = `node${nodeCounter++}
|
|
111
|
-
nodeIds.set(serviceName, nodeId)
|
|
109
|
+
const serviceName = factory.provides.name
|
|
110
|
+
const nodeId = `node${nodeCounter++}`
|
|
111
|
+
nodeIds.set(serviceName, nodeId)
|
|
112
112
|
|
|
113
|
-
const isLeaf = !hasDependencies.has(serviceName)
|
|
114
|
-
const isRoot = !hasDependents.has(serviceName)
|
|
113
|
+
const isLeaf = !hasDependencies.has(serviceName)
|
|
114
|
+
const isRoot = !hasDependents.has(serviceName)
|
|
115
115
|
|
|
116
|
-
let nodeStyle = ''
|
|
116
|
+
let nodeStyle = ''
|
|
117
117
|
|
|
118
118
|
if (highlightLeaves && isLeaf) {
|
|
119
|
-
nodeStyle = ' [fillcolor="#c8e6c9", color="#388e3c"]'
|
|
119
|
+
nodeStyle = ' [fillcolor="#c8e6c9", color="#388e3c"]'
|
|
120
120
|
} else if (highlightRoots && isRoot) {
|
|
121
|
-
nodeStyle = ' [fillcolor="#ffccbc", color="#d84315"]'
|
|
121
|
+
nodeStyle = ' [fillcolor="#ffccbc", color="#d84315"]'
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
lines.push(
|
|
125
125
|
` ${nodeId} [label="${escapeDotString(serviceName)}"]${nodeStyle};`,
|
|
126
|
-
)
|
|
127
|
-
})
|
|
126
|
+
)
|
|
127
|
+
})
|
|
128
128
|
|
|
129
|
-
lines.push('')
|
|
129
|
+
lines.push('')
|
|
130
130
|
|
|
131
131
|
// Define edges (dependencies)
|
|
132
132
|
factories.forEach((factory) => {
|
|
133
|
-
const serviceName = factory.provides.name
|
|
134
|
-
const serviceNodeId = nodeIds.get(serviceName)
|
|
133
|
+
const serviceName = factory.provides.name
|
|
134
|
+
const serviceNodeId = nodeIds.get(serviceName)!
|
|
135
135
|
|
|
136
136
|
factory.dependsOn.forEach((dependency: ServiceKey<unknown>) => {
|
|
137
|
-
const depName = dependency.name
|
|
138
|
-
const depNodeId = nodeIds.get(depName)
|
|
137
|
+
const depName = dependency.name
|
|
138
|
+
const depNodeId = nodeIds.get(depName)
|
|
139
139
|
|
|
140
140
|
if (depNodeId) {
|
|
141
141
|
// Arrow points from dependent to dependency (what needs it -> what provides it)
|
|
142
|
-
lines.push(` ${serviceNodeId} -> ${depNodeId};`)
|
|
142
|
+
lines.push(` ${serviceNodeId} -> ${depNodeId};`)
|
|
143
143
|
}
|
|
144
|
-
})
|
|
145
|
-
})
|
|
144
|
+
})
|
|
145
|
+
})
|
|
146
146
|
|
|
147
147
|
// Close the digraph
|
|
148
|
-
lines.push('}')
|
|
148
|
+
lines.push('}')
|
|
149
149
|
|
|
150
|
-
return lines.join('\n')
|
|
150
|
+
return lines.join('\n')
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
/**
|
|
@@ -161,9 +161,9 @@ export function printDotGraph(
|
|
|
161
161
|
module: ServiceModule,
|
|
162
162
|
options?: DotGraphOptions,
|
|
163
163
|
): void {
|
|
164
|
-
console.log(createDotGraph(module, options))
|
|
165
|
-
console.log('\n\nCopy the DOT output above and paste it into:')
|
|
166
|
-
console.log('https://dreampuf.github.io/GraphvizOnline/')
|
|
164
|
+
console.log(createDotGraph(module, options))
|
|
165
|
+
console.log('\n\nCopy the DOT output above and paste it into:')
|
|
166
|
+
console.log('https://dreampuf.github.io/GraphvizOnline/')
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
/**
|
|
@@ -185,79 +185,79 @@ export function createMermaidGraph(
|
|
|
185
185
|
highlightRoots: true,
|
|
186
186
|
},
|
|
187
187
|
): string {
|
|
188
|
-
const factories = module.factories
|
|
189
|
-
const lines: string[] = []
|
|
188
|
+
const factories = module.factories
|
|
189
|
+
const lines: string[] = []
|
|
190
190
|
|
|
191
191
|
// Start the flowchart
|
|
192
|
-
lines.push(`flowchart ${direction}`)
|
|
192
|
+
lines.push(`flowchart ${direction}`)
|
|
193
193
|
|
|
194
194
|
// Build dependency maps to identify leaves and roots
|
|
195
|
-
const hasDependencies = new Set<string>()
|
|
196
|
-
const hasDependents = new Set<string>()
|
|
195
|
+
const hasDependencies = new Set<string>()
|
|
196
|
+
const hasDependents = new Set<string>()
|
|
197
197
|
|
|
198
198
|
factories.forEach((factory) => {
|
|
199
|
-
const serviceName = factory.provides.name
|
|
199
|
+
const serviceName = factory.provides.name
|
|
200
200
|
|
|
201
201
|
if (factory.dependsOn.length > 0) {
|
|
202
|
-
hasDependencies.add(serviceName)
|
|
202
|
+
hasDependencies.add(serviceName)
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
factory.dependsOn.forEach((dependency) => {
|
|
206
|
-
hasDependents.add(dependency.name)
|
|
207
|
-
})
|
|
208
|
-
})
|
|
206
|
+
hasDependents.add(dependency.name)
|
|
207
|
+
})
|
|
208
|
+
})
|
|
209
209
|
|
|
210
210
|
// Define nodes with special styling for leaves and roots
|
|
211
|
-
const nodeIds = new Map<string, string>()
|
|
212
|
-
let nodeCounter = 0
|
|
211
|
+
const nodeIds = new Map<string, string>()
|
|
212
|
+
let nodeCounter = 0
|
|
213
213
|
|
|
214
214
|
factories.forEach((factory) => {
|
|
215
|
-
const serviceName = factory.provides.name
|
|
216
|
-
const nodeId = `node${nodeCounter++}
|
|
217
|
-
nodeIds.set(serviceName, nodeId)
|
|
215
|
+
const serviceName = factory.provides.name
|
|
216
|
+
const nodeId = `node${nodeCounter++}`
|
|
217
|
+
nodeIds.set(serviceName, nodeId)
|
|
218
218
|
|
|
219
|
-
lines.push(` ${nodeId}["${escapeMermaidString(serviceName)}"]`)
|
|
220
|
-
})
|
|
219
|
+
lines.push(` ${nodeId}["${escapeMermaidString(serviceName)}"]`)
|
|
220
|
+
})
|
|
221
221
|
|
|
222
|
-
lines.push('')
|
|
222
|
+
lines.push('')
|
|
223
223
|
|
|
224
224
|
// Define edges (dependencies)
|
|
225
225
|
factories.forEach((factory) => {
|
|
226
|
-
const serviceName = factory.provides.name
|
|
227
|
-
const serviceNodeId = nodeIds.get(serviceName)
|
|
226
|
+
const serviceName = factory.provides.name
|
|
227
|
+
const serviceNodeId = nodeIds.get(serviceName)!
|
|
228
228
|
|
|
229
229
|
factory.dependsOn.forEach((dependency) => {
|
|
230
|
-
const depName = dependency.name
|
|
231
|
-
const depNodeId = nodeIds.get(depName)
|
|
230
|
+
const depName = dependency.name
|
|
231
|
+
const depNodeId = nodeIds.get(depName)
|
|
232
232
|
|
|
233
233
|
if (depNodeId) {
|
|
234
234
|
// Arrow points from dependent to dependency (what needs it -> what provides it)
|
|
235
|
-
lines.push(` ${serviceNodeId} --> ${depNodeId}`)
|
|
235
|
+
lines.push(` ${serviceNodeId} --> ${depNodeId}`)
|
|
236
236
|
}
|
|
237
|
-
})
|
|
238
|
-
})
|
|
237
|
+
})
|
|
238
|
+
})
|
|
239
239
|
|
|
240
|
-
lines.push('')
|
|
240
|
+
lines.push('')
|
|
241
241
|
|
|
242
242
|
// Apply styling
|
|
243
243
|
factories.forEach((factory) => {
|
|
244
|
-
const serviceName = factory.provides.name
|
|
245
|
-
const serviceNodeId = nodeIds.get(serviceName)
|
|
244
|
+
const serviceName = factory.provides.name
|
|
245
|
+
const serviceNodeId = nodeIds.get(serviceName)!
|
|
246
246
|
|
|
247
|
-
const isLeaf = !hasDependencies.has(serviceName)
|
|
248
|
-
const isRoot = !hasDependents.has(serviceName)
|
|
247
|
+
const isLeaf = !hasDependencies.has(serviceName)
|
|
248
|
+
const isRoot = !hasDependents.has(serviceName)
|
|
249
249
|
|
|
250
250
|
if (highlightLeaves && isLeaf) {
|
|
251
|
-
lines.push(` style ${serviceNodeId} fill:#c8e6c9,stroke:#388e3c`)
|
|
251
|
+
lines.push(` style ${serviceNodeId} fill:#c8e6c9,stroke:#388e3c`)
|
|
252
252
|
} else if (highlightRoots && isRoot) {
|
|
253
|
-
lines.push(` style ${serviceNodeId} fill:#ffccbc,stroke:#d84315`)
|
|
253
|
+
lines.push(` style ${serviceNodeId} fill:#ffccbc,stroke:#d84315`)
|
|
254
254
|
} else {
|
|
255
255
|
// Default style
|
|
256
|
-
lines.push(` style ${serviceNodeId} fill:#e1f5ff,stroke:#0288d1`)
|
|
256
|
+
lines.push(` style ${serviceNodeId} fill:#e1f5ff,stroke:#0288d1`)
|
|
257
257
|
}
|
|
258
|
-
})
|
|
258
|
+
})
|
|
259
259
|
|
|
260
|
-
return lines.join('\n')
|
|
260
|
+
return lines.join('\n')
|
|
261
261
|
}
|
|
262
262
|
|
|
263
263
|
/**
|
|
@@ -271,7 +271,7 @@ export function printMermaidGraph(
|
|
|
271
271
|
module: ServiceModule,
|
|
272
272
|
options?: MermaidGraphOptions,
|
|
273
273
|
): void {
|
|
274
|
-
console.log(createMermaidGraph(module, options))
|
|
275
|
-
console.log('\n\nCopy the Mermaid output above and paste it into:')
|
|
276
|
-
console.log('https://mermaid.live/')
|
|
274
|
+
console.log(createMermaidGraph(module, options))
|
|
275
|
+
console.log('\n\nCopy the Mermaid output above and paste it into:')
|
|
276
|
+
console.log('https://mermaid.live/')
|
|
277
277
|
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import type { DisposeContext, EventSpan, InitializeContext, MethodCallContext, ServiceModuleListener } from './serviceModuleListener';
|
|
2
|
-
import type { ServiceKey } from './serviceKey';
|
|
3
|
-
/**
|
|
4
|
-
* The placeholder that replaces redacted values in event contexts and
|
|
5
|
-
* outcomes.
|
|
6
|
-
*/
|
|
7
|
-
export declare const REDACTED_VALUE = "[redacted]";
|
|
8
|
-
/**
|
|
9
|
-
* Marks a service — or specific properties of it — as sensitive, so the
|
|
10
|
-
* values flowing through its events are replaced with {@link REDACTED_VALUE}.
|
|
11
|
-
*/
|
|
12
|
-
export interface RedactionRule<T> {
|
|
13
|
-
/**
|
|
14
|
-
* The service key whose values must be redacted. Matched by key
|
|
15
|
-
* identity, like everywhere else in the container.
|
|
16
|
-
*/
|
|
17
|
-
key: ServiceKey<T>;
|
|
18
|
-
/**
|
|
19
|
-
* Property names to redact. Optional: when omitted, ALL properties of
|
|
20
|
-
* the service are redacted, along with its initialize result (the
|
|
21
|
-
* service instance itself may carry credentials or config).
|
|
22
|
-
*/
|
|
23
|
-
properties?: Extract<keyof T, string>[];
|
|
24
|
-
}
|
|
25
|
-
export declare function redactionRule<T>(key: ServiceKey<T>, properties?: Extract<keyof T, string>[]): RedactionRule<T>;
|
|
26
|
-
/**
|
|
27
|
-
* A ServiceEventListener decorator that redacts sensitive values before
|
|
28
|
-
* they reach the wrapped listener. Works with any implementation via
|
|
29
|
-
* delegation: arguments in MethodCallContext and success values in
|
|
30
|
-
* EventOutcome are replaced with {@link REDACTED_VALUE}, so the delegate
|
|
31
|
-
* never sees the sensitive data — whatever it captures or exports is
|
|
32
|
-
* already scrubbed.
|
|
33
|
-
*
|
|
34
|
-
* Failure outcomes are passed through unchanged so error reporting keeps
|
|
35
|
-
* working; keep secrets out of error messages at the throwing site.
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* ```ts
|
|
39
|
-
* const listener = new RedactingEventListener(
|
|
40
|
-
* new OTELEventListener({ captureArguments: true, captureResults: true }),
|
|
41
|
-
* [
|
|
42
|
-
* { key: SecretClientKey }, // whole service is sensitive
|
|
43
|
-
* { key: VaultKey, properties: ['getSecret'] }, // only these calls
|
|
44
|
-
* ],
|
|
45
|
-
* );
|
|
46
|
-
* ```
|
|
47
|
-
*/
|
|
48
|
-
export declare class RedactingEventListener implements ServiceModuleListener {
|
|
49
|
-
private readonly delegate;
|
|
50
|
-
private readonly rules;
|
|
51
|
-
constructor(delegate: ServiceModuleListener, rules: readonly RedactionRule<any>[]);
|
|
52
|
-
onInitialize(context: InitializeContext): EventSpan | void;
|
|
53
|
-
onDispose(context: DisposeContext): EventSpan | void;
|
|
54
|
-
onMethodCall(context: MethodCallContext): EventSpan | void;
|
|
55
|
-
private isRedacted;
|
|
56
|
-
}
|
|
57
|
-
//# sourceMappingURL=redactingEventListener.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"redactingEventListener.d.ts","sourceRoot":"","sources":["../src/redactingEventListener.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EAEd,SAAS,EACT,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C;;;GAGG;AACH,eAAO,MAAM,cAAc,eAAe,CAAC;AAE3C;;;GAGG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B;;;OAGG;IACH,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IAEnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC;CACzC;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,EAAE,GAAG,aAAa,CAAC,CAAC,CAAC,CAE9G;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,sBAAuB,YAAW,qBAAqB;IAEhE,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBADL,QAAQ,EAAE,qBAAqB,EAC/B,KAAK,EAAE,SAAS,aAAa,CAAC,GAAG,CAAC,EAAE;IAGvD,YAAY,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,GAAG,IAAI;IAU1D,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,GAAG,IAAI;IAKpD,YAAY,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,GAAG,IAAI;IAc1D,OAAO,CAAC,UAAU;CAYnB"}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RedactingEventListener = exports.REDACTED_VALUE = void 0;
|
|
4
|
-
exports.redactionRule = redactionRule;
|
|
5
|
-
/**
|
|
6
|
-
* The placeholder that replaces redacted values in event contexts and
|
|
7
|
-
* outcomes.
|
|
8
|
-
*/
|
|
9
|
-
exports.REDACTED_VALUE = '[redacted]';
|
|
10
|
-
function redactionRule(key, properties) {
|
|
11
|
-
return { key, properties };
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* A ServiceEventListener decorator that redacts sensitive values before
|
|
15
|
-
* they reach the wrapped listener. Works with any implementation via
|
|
16
|
-
* delegation: arguments in MethodCallContext and success values in
|
|
17
|
-
* EventOutcome are replaced with {@link REDACTED_VALUE}, so the delegate
|
|
18
|
-
* never sees the sensitive data — whatever it captures or exports is
|
|
19
|
-
* already scrubbed.
|
|
20
|
-
*
|
|
21
|
-
* Failure outcomes are passed through unchanged so error reporting keeps
|
|
22
|
-
* working; keep secrets out of error messages at the throwing site.
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
|
-
* ```ts
|
|
26
|
-
* const listener = new RedactingEventListener(
|
|
27
|
-
* new OTELEventListener({ captureArguments: true, captureResults: true }),
|
|
28
|
-
* [
|
|
29
|
-
* { key: SecretClientKey }, // whole service is sensitive
|
|
30
|
-
* { key: VaultKey, properties: ['getSecret'] }, // only these calls
|
|
31
|
-
* ],
|
|
32
|
-
* );
|
|
33
|
-
* ```
|
|
34
|
-
*/
|
|
35
|
-
class RedactingEventListener {
|
|
36
|
-
constructor(delegate, rules) {
|
|
37
|
-
this.delegate = delegate;
|
|
38
|
-
this.rules = rules;
|
|
39
|
-
}
|
|
40
|
-
onInitialize(context) {
|
|
41
|
-
var _a, _b;
|
|
42
|
-
// The initialize result is the service instance itself, so it is
|
|
43
|
-
// redacted only when the whole service is sensitive — a rule without
|
|
44
|
-
// `properties`.
|
|
45
|
-
return redactSpan((_b = (_a = this.delegate).onInitialize) === null || _b === void 0 ? void 0 : _b.call(_a, context), this.isRedacted(context.key));
|
|
46
|
-
}
|
|
47
|
-
onDispose(context) {
|
|
48
|
-
var _a, _b;
|
|
49
|
-
// Dispose carries no arguments and no result value; nothing to redact.
|
|
50
|
-
return (_b = (_a = this.delegate).onDispose) === null || _b === void 0 ? void 0 : _b.call(_a, context);
|
|
51
|
-
}
|
|
52
|
-
onMethodCall(context) {
|
|
53
|
-
var _a, _b;
|
|
54
|
-
const redacted = this.isRedacted(context.key, context.functionName);
|
|
55
|
-
const span = (_b = (_a = this.delegate).onMethodCall) === null || _b === void 0 ? void 0 : _b.call(_a, redacted
|
|
56
|
-
? // Replace each argument rather than the whole array, so the
|
|
57
|
-
Object.assign(Object.assign({}, context), { args: context.args.map(() => exports.REDACTED_VALUE) }) : context);
|
|
58
|
-
return redactSpan(span, redacted);
|
|
59
|
-
}
|
|
60
|
-
// 1. Si expiro el dbr `EXPIRED` el cron debe mandar a `FACE_MISMATCH`?
|
|
61
|
-
// 2. Si hubo un matchLevel intermediario el cron debe mandar a `FACE_MISMATCH`? (Probablemente no)
|
|
62
|
-
isRedacted(key, propertyName) {
|
|
63
|
-
return this.rules.some((rule) => {
|
|
64
|
-
var _a;
|
|
65
|
-
return rule.key === key &&
|
|
66
|
-
// A rule without `properties` redacts everything on the key,
|
|
67
|
-
// including initialize — where no property name is passed —
|
|
68
|
-
// while a rule with `properties` matches only those calls.
|
|
69
|
-
(rule.properties === undefined ||
|
|
70
|
-
(propertyName !== undefined &&
|
|
71
|
-
((_a = rule.properties) === null || _a === void 0 ? void 0 : _a.includes(propertyName))));
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
exports.RedactingEventListener = RedactingEventListener;
|
|
76
|
-
/**
|
|
77
|
-
* Wraps the delegate's EventSpan so success values are redacted before
|
|
78
|
-
* `end` sees them. `run` (and any future fields) pass through untouched.
|
|
79
|
-
*/
|
|
80
|
-
function redactSpan(span, redacted) {
|
|
81
|
-
if (!redacted || !(span === null || span === void 0 ? void 0 : span.end)) {
|
|
82
|
-
return span;
|
|
83
|
-
}
|
|
84
|
-
const end = span.end.bind(span);
|
|
85
|
-
return Object.assign(Object.assign({}, span), { end: (outcome) => end(outcome.type === 'success'
|
|
86
|
-
? { type: 'success', value: exports.REDACTED_VALUE }
|
|
87
|
-
: outcome) });
|
|
88
|
-
}
|
|
89
|
-
//# sourceMappingURL=redactingEventListener.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"redactingEventListener.js","sourceRoot":"","sources":["../src/redactingEventListener.ts"],"names":[],"mappings":";;;AAmCA,sCAEC;AA3BD;;;GAGG;AACU,QAAA,cAAc,GAAG,YAAY,CAAC;AAqB3C,SAAgB,aAAa,CAAI,GAAkB,EAAE,UAAuC;IAC1F,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC;AAC7B,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAa,sBAAsB;IACjC,YACmB,QAA+B,EAC/B,KAAoC;QADpC,aAAQ,GAAR,QAAQ,CAAuB;QAC/B,UAAK,GAAL,KAAK,CAA+B;IACpD,CAAC;IAEJ,YAAY,CAAC,OAA0B;;QACrC,iEAAiE;QACjE,qEAAqE;QACrE,gBAAgB;QAChB,OAAO,UAAU,CACf,MAAA,MAAA,IAAI,CAAC,QAAQ,EAAC,YAAY,mDAAG,OAAO,CAAC,EACrC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAC7B,CAAC;IACJ,CAAC;IAED,SAAS,CAAC,OAAuB;;QAC/B,uEAAuE;QACvE,OAAO,MAAA,MAAA,IAAI,CAAC,QAAQ,EAAC,SAAS,mDAAG,OAAO,CAAC,CAAC;IAC5C,CAAC;IAED,YAAY,CAAC,OAA0B;;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;QACpE,MAAM,IAAI,GAAG,MAAA,MAAA,IAAI,CAAC,QAAQ,EAAC,YAAY,mDACrC,QAAQ;YACN,CAAC,CAAC,4DAA4D;6CAEvD,OAAO,KAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,sBAAc,CAAC,IAC5D,CAAC,CAAC,OAAO,CACZ,CAAC;QACF,OAAO,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED,uEAAuE;IACvE,mGAAmG;IAC3F,UAAU,CAAC,GAAoB,EAAE,YAAqB;QAC5D,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CACpB,CAAC,IAAI,EAAE,EAAE;;YACP,OAAA,IAAI,CAAC,GAAG,KAAK,GAAG;gBAChB,6DAA6D;gBAC7D,4DAA4D;gBAC5D,2DAA2D;gBAC3D,CAAC,IAAI,CAAC,UAAU,KAAK,SAAS;oBAC5B,CAAC,YAAY,KAAK,SAAS;yBACzB,MAAA,IAAI,CAAC,UAAU,0CAAE,QAAQ,CAAC,YAAY,CAAC,CAAA,CAAC,CAAC,CAAA;SAAA,CAChD,CAAC;IACJ,CAAC;CACF;AA/CD,wDA+CC;AAED;;;GAGG;AACH,SAAS,UAAU,CACjB,IAAsB,EACtB,QAAiB;IAEjB,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,GAAG,CAAA,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChC,uCACK,IAAI,KACP,GAAG,EAAE,CAAC,OAAqB,EAAE,EAAE,CAC7B,GAAG,CACD,OAAO,CAAC,IAAI,KAAK,SAAS;YACxB,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,sBAAc,EAAE;YAC5C,CAAC,CAAC,OAAO,CACZ,IACH;AACJ,CAAC"}
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import type { ServiceKey } from './serviceKey';
|
|
2
|
-
/**
|
|
3
|
-
* A handle representing a single in-flight operation (initialization,
|
|
4
|
-
* disposal, or method call), returned by a ServiceEventListener when the
|
|
5
|
-
* operation starts.
|
|
6
|
-
*
|
|
7
|
-
* `end` is invoked exactly once when the operation finishes, so
|
|
8
|
-
* implementations can close over per-call state (a start time, a span
|
|
9
|
-
* handle, a correlation id) without any bookkeeping to pair concurrent
|
|
10
|
-
* start/finish events.
|
|
11
|
-
*/
|
|
12
|
-
export interface EventSpan {
|
|
13
|
-
/**
|
|
14
|
-
* Optional wrapper around the operation itself. When present, the module
|
|
15
|
-
* invokes the operation as `run(() => operation())`, so the listener can
|
|
16
|
-
* establish ambient state that the operation body and its async
|
|
17
|
-
* continuations inherit — this is what lets spans of nested service
|
|
18
|
-
* calls form a parent-child hierarchy.
|
|
19
|
-
*
|
|
20
|
-
* Implementations must invoke `fn` exactly once, synchronously, and
|
|
21
|
-
* return its result unchanged (for async operations, the promise itself).
|
|
22
|
-
* `end` is still delivered separately when the operation finishes.
|
|
23
|
-
*
|
|
24
|
-
* @param fn - A thunk that performs the operation.
|
|
25
|
-
* @return The value returned by `fn`.
|
|
26
|
-
*/
|
|
27
|
-
run?<T>(fn: () => T): T;
|
|
28
|
-
/**
|
|
29
|
-
* Invoked exactly once when the operation finishes, whether it succeeded
|
|
30
|
-
* or failed. For methods that return a promise, this fires when the
|
|
31
|
-
* promise settles, not when the method returns. On failure, the error is
|
|
32
|
-
* rethrown to the caller after this is invoked.
|
|
33
|
-
*
|
|
34
|
-
* Whether to retain or log the outcome is the implementation's choice;
|
|
35
|
-
* values are passed by reference, so implementations must not mutate them.
|
|
36
|
-
*
|
|
37
|
-
* @param outcome - How the operation finished, and its value or error.
|
|
38
|
-
* @return void
|
|
39
|
-
*/
|
|
40
|
-
end?(outcome: EventOutcome): void;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* How an operation finished, delivered to EventSpan.end: `success` carries
|
|
44
|
-
* the value produced by the operation (the return or resolved value for
|
|
45
|
-
* method calls, the service instance for initialize, undefined for
|
|
46
|
-
* dispose); `failure` carries the error that was thrown or rejected.
|
|
47
|
-
*/
|
|
48
|
-
export type EventOutcome = {
|
|
49
|
-
type: 'success';
|
|
50
|
-
value: unknown;
|
|
51
|
-
} | {
|
|
52
|
-
type: 'failure';
|
|
53
|
-
error: unknown;
|
|
54
|
-
};
|
|
55
|
-
/**
|
|
56
|
-
* Context of a service initialization, delivered to onInitialize.
|
|
57
|
-
* Future fields are added here rather than as extra parameters.
|
|
58
|
-
*/
|
|
59
|
-
export interface InitializeContext {
|
|
60
|
-
/**
|
|
61
|
-
* The unique identifier of the service that is being initialized.
|
|
62
|
-
*/
|
|
63
|
-
key: ServiceKey<unknown>;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Context of a service disposal, delivered to onDispose.
|
|
67
|
-
* Future fields are added here rather than as extra parameters.
|
|
68
|
-
*/
|
|
69
|
-
export interface DisposeContext {
|
|
70
|
-
/**
|
|
71
|
-
* The unique identifier of the service that is being disposed.
|
|
72
|
-
*/
|
|
73
|
-
key: ServiceKey<unknown>;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Context of a method invocation, delivered to onMethodCall.
|
|
77
|
-
* Future fields are added here rather than as extra parameters.
|
|
78
|
-
*/
|
|
79
|
-
export interface MethodCallContext {
|
|
80
|
-
/**
|
|
81
|
-
* The unique identifier of the service the method belongs to.
|
|
82
|
-
*/
|
|
83
|
-
key: ServiceKey<unknown>;
|
|
84
|
-
/**
|
|
85
|
-
* The name of the class implementing the service (the instance's
|
|
86
|
-
* constructor name), which may differ from `key.name`. Undefined for
|
|
87
|
-
* services that are not instances of a named class, such as plain
|
|
88
|
-
* object literals.
|
|
89
|
-
*/
|
|
90
|
-
className?: string;
|
|
91
|
-
/**
|
|
92
|
-
* The name of the method that is being called.
|
|
93
|
-
*/
|
|
94
|
-
functionName: string;
|
|
95
|
-
/**
|
|
96
|
-
* The arguments the method was invoked with, passed by reference;
|
|
97
|
-
* implementations must not mutate them.
|
|
98
|
-
*/
|
|
99
|
-
args: readonly unknown[];
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Interface for listening to service events. Implement this interface to
|
|
103
|
-
* observe lifecycle events and method calls of services in a module.
|
|
104
|
-
*
|
|
105
|
-
* Each method is invoked when the corresponding operation starts and may
|
|
106
|
-
* return an EventSpan that is notified when that operation finishes.
|
|
107
|
-
* Returning nothing opts out of completion tracking for that call.
|
|
108
|
-
*/
|
|
109
|
-
export interface ServiceEventListener {
|
|
110
|
-
/**
|
|
111
|
-
* Invoked at the start of the initialization process for a specific service.
|
|
112
|
-
*
|
|
113
|
-
* @param context - Context of the initialization, including the service key.
|
|
114
|
-
* @return An EventSpan notified when initialization finishes, or void.
|
|
115
|
-
*/
|
|
116
|
-
onInitialize?(context: InitializeContext): EventSpan | void;
|
|
117
|
-
/**
|
|
118
|
-
* Invoked when the disposal process for a service starts.
|
|
119
|
-
*
|
|
120
|
-
* @param context - Context of the disposal, including the service key.
|
|
121
|
-
* @return An EventSpan notified when disposal finishes, or void.
|
|
122
|
-
*/
|
|
123
|
-
onDispose?(context: DisposeContext): EventSpan | void;
|
|
124
|
-
/**
|
|
125
|
-
* Invoked when a method call starts on a service instance.
|
|
126
|
-
*
|
|
127
|
-
* @param context - Context of the invocation, including the service key,
|
|
128
|
-
* the method name, and its arguments.
|
|
129
|
-
* @return An EventSpan notified when the call finishes, or void.
|
|
130
|
-
*/
|
|
131
|
-
onMethodCall?(context: MethodCallContext): EventSpan | void;
|
|
132
|
-
}
|
|
133
|
-
//# sourceMappingURL=serviceEventListener.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"serviceEventListener.d.ts","sourceRoot":"","sources":["../src/serviceEventListener.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C;;;;;;;;;GASG;AACH,MAAM,WAAW,SAAS;IACxB;;;;;;;;;;;;;OAaG;IACH,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAExB;;;;;;;;;;;OAWG;IACH,GAAG,CAAC,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;CACnC;AAED;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GACtB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAE5E;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,GAAG,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,GAAG,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,GAAG,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IAEzB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,IAAI,EAAE,SAAS,OAAO,EAAE,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,YAAY,CAAC,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,GAAG,IAAI,CAAC;IAE5D;;;;;OAKG;IACH,SAAS,CAAC,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,GAAG,IAAI,CAAC;IAEtD;;;;;;OAMG;IACH,YAAY,CAAC,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,GAAG,IAAI,CAAC;CAC7D"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"serviceEventListener.js","sourceRoot":"","sources":["../src/serviceEventListener.ts"],"names":[],"mappings":""}
|