@defai.digital/config-domain 13.0.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/LICENSE +214 -0
- package/dist/aggregate.d.ts +110 -0
- package/dist/aggregate.d.ts.map +1 -0
- package/dist/aggregate.js +297 -0
- package/dist/aggregate.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/migrator.d.ts +93 -0
- package/dist/migrator.d.ts.map +1 -0
- package/dist/migrator.js +263 -0
- package/dist/migrator.js.map +1 -0
- package/dist/operations.d.ts +47 -0
- package/dist/operations.d.ts.map +1 -0
- package/dist/operations.js +260 -0
- package/dist/operations.js.map +1 -0
- package/dist/ports/detection.d.ts +61 -0
- package/dist/ports/detection.d.ts.map +1 -0
- package/dist/ports/detection.js +60 -0
- package/dist/ports/detection.js.map +1 -0
- package/dist/repository.d.ts +100 -0
- package/dist/repository.d.ts.map +1 -0
- package/dist/repository.js +135 -0
- package/dist/repository.js.map +1 -0
- package/dist/resolver.d.ts +92 -0
- package/dist/resolver.d.ts.map +1 -0
- package/dist/resolver.js +94 -0
- package/dist/resolver.js.map +1 -0
- package/dist/store.d.ts +85 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +247 -0
- package/dist/store.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Operations
|
|
3
|
+
*
|
|
4
|
+
* Pure functions for config manipulation (immutable operations).
|
|
5
|
+
*/
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Path Operations
|
|
8
|
+
// ============================================================================
|
|
9
|
+
/**
|
|
10
|
+
* Parses a config path into segments
|
|
11
|
+
* @example parsePath('providers.0.providerId') => ['providers', '0', 'providerId']
|
|
12
|
+
*/
|
|
13
|
+
export function parsePath(path) {
|
|
14
|
+
if (path === '') {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
return path.split('.');
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Gets a value from config by path
|
|
21
|
+
* @example getValue(config, 'providers.0.providerId') => 'claude'
|
|
22
|
+
*/
|
|
23
|
+
export function getValue(config, path) {
|
|
24
|
+
const segments = parsePath(path);
|
|
25
|
+
let current = config;
|
|
26
|
+
for (const segment of segments) {
|
|
27
|
+
if (current === null || current === undefined) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
if (typeof current !== 'object') {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
// Handle array access with numeric index
|
|
34
|
+
if (Array.isArray(current)) {
|
|
35
|
+
const index = parseInt(segment, 10);
|
|
36
|
+
if (Number.isNaN(index)) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
current = current[index];
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
current = current[segment];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return current;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Sets a value in config by path (immutable)
|
|
49
|
+
* @example setValue(config, 'logLevel', 'debug') => new config with updated logLevel
|
|
50
|
+
*/
|
|
51
|
+
export function setValue(config, path, value) {
|
|
52
|
+
const segments = parsePath(path);
|
|
53
|
+
if (segments.length === 0) {
|
|
54
|
+
throw new Error('Path cannot be empty');
|
|
55
|
+
}
|
|
56
|
+
return setNestedValue(config, segments, value);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Recursively sets a nested value (immutable)
|
|
60
|
+
*/
|
|
61
|
+
function setNestedValue(obj, segments, value) {
|
|
62
|
+
if (segments.length === 0) {
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
65
|
+
const first = segments[0];
|
|
66
|
+
const rest = segments.slice(1);
|
|
67
|
+
if (first === undefined) {
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
if (Array.isArray(obj)) {
|
|
71
|
+
const index = parseInt(first, 10);
|
|
72
|
+
if (Number.isNaN(index)) {
|
|
73
|
+
throw new Error(`Invalid array index: ${first}`);
|
|
74
|
+
}
|
|
75
|
+
const newArray = [...obj];
|
|
76
|
+
newArray[index] = setNestedValue(obj[index], rest, value);
|
|
77
|
+
return newArray;
|
|
78
|
+
}
|
|
79
|
+
if (typeof obj === 'object' && obj !== null) {
|
|
80
|
+
const record = obj;
|
|
81
|
+
return {
|
|
82
|
+
...record,
|
|
83
|
+
[first]: setNestedValue(record[first], rest, value),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
// Create new object if current value is not an object
|
|
87
|
+
return {
|
|
88
|
+
[first]: setNestedValue(undefined, rest, value),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Removes a value from config by path (immutable)
|
|
93
|
+
*/
|
|
94
|
+
export function removeValue(config, path) {
|
|
95
|
+
const segments = parsePath(path);
|
|
96
|
+
if (segments.length === 0) {
|
|
97
|
+
throw new Error('Path cannot be empty');
|
|
98
|
+
}
|
|
99
|
+
return removeNestedValue(config, segments);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Recursively removes a nested value (immutable)
|
|
103
|
+
*/
|
|
104
|
+
function removeNestedValue(obj, segments) {
|
|
105
|
+
if (segments.length === 0) {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
const first = segments[0];
|
|
109
|
+
const rest = segments.slice(1);
|
|
110
|
+
if (first === undefined) {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
if (Array.isArray(obj)) {
|
|
114
|
+
const index = parseInt(first, 10);
|
|
115
|
+
if (Number.isNaN(index) || index < 0 || index >= obj.length) {
|
|
116
|
+
return obj;
|
|
117
|
+
}
|
|
118
|
+
if (rest.length === 0) {
|
|
119
|
+
// Remove element from array
|
|
120
|
+
return [...obj.slice(0, index), ...obj.slice(index + 1)];
|
|
121
|
+
}
|
|
122
|
+
// Recurse into array element
|
|
123
|
+
const newArray = [...obj];
|
|
124
|
+
newArray[index] = removeNestedValue(obj[index], rest);
|
|
125
|
+
return newArray;
|
|
126
|
+
}
|
|
127
|
+
if (typeof obj === 'object' && obj !== null) {
|
|
128
|
+
const record = obj;
|
|
129
|
+
if (rest.length === 0) {
|
|
130
|
+
// Remove key from object
|
|
131
|
+
const result = {};
|
|
132
|
+
for (const key of Object.keys(record)) {
|
|
133
|
+
if (key !== first) {
|
|
134
|
+
result[key] = record[key];
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return result;
|
|
138
|
+
}
|
|
139
|
+
// Recurse into nested object
|
|
140
|
+
return {
|
|
141
|
+
...record,
|
|
142
|
+
[first]: removeNestedValue(record[first], rest),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return obj;
|
|
146
|
+
}
|
|
147
|
+
// ============================================================================
|
|
148
|
+
// Config Merging
|
|
149
|
+
// ============================================================================
|
|
150
|
+
/**
|
|
151
|
+
* Deep merges two configs (immutable)
|
|
152
|
+
* Override values take precedence
|
|
153
|
+
*/
|
|
154
|
+
export function mergeConfigs(base, override) {
|
|
155
|
+
return deepMerge(base, override);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Deep merges two objects
|
|
159
|
+
*/
|
|
160
|
+
function deepMerge(base, override) {
|
|
161
|
+
const result = { ...base };
|
|
162
|
+
for (const key of Object.keys(override)) {
|
|
163
|
+
const overrideValue = override[key];
|
|
164
|
+
const baseValue = base[key];
|
|
165
|
+
if (overrideValue === undefined) {
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (typeof overrideValue === 'object' &&
|
|
169
|
+
overrideValue !== null &&
|
|
170
|
+
!Array.isArray(overrideValue) &&
|
|
171
|
+
typeof baseValue === 'object' &&
|
|
172
|
+
baseValue !== null &&
|
|
173
|
+
!Array.isArray(baseValue)) {
|
|
174
|
+
result[key] = deepMerge(baseValue, overrideValue);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
result[key] = overrideValue;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return result;
|
|
181
|
+
}
|
|
182
|
+
// ============================================================================
|
|
183
|
+
// Config Comparison
|
|
184
|
+
// ============================================================================
|
|
185
|
+
/**
|
|
186
|
+
* Compares two configs and returns the differences
|
|
187
|
+
*/
|
|
188
|
+
export function diffConfigs(oldConfig, newConfig) {
|
|
189
|
+
const diffs = [];
|
|
190
|
+
function compare(oldObj, newObj, currentPath) {
|
|
191
|
+
// Handle primitives and nulls
|
|
192
|
+
if (oldObj === newObj ||
|
|
193
|
+
typeof oldObj !== 'object' ||
|
|
194
|
+
typeof newObj !== 'object' ||
|
|
195
|
+
oldObj === null ||
|
|
196
|
+
newObj === null) {
|
|
197
|
+
if (oldObj !== newObj) {
|
|
198
|
+
diffs.push({ path: currentPath, oldValue: oldObj, newValue: newObj });
|
|
199
|
+
}
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
// Handle arrays
|
|
203
|
+
if (Array.isArray(oldObj) && Array.isArray(newObj)) {
|
|
204
|
+
const maxLength = Math.max(oldObj.length, newObj.length);
|
|
205
|
+
for (let i = 0; i < maxLength; i++) {
|
|
206
|
+
compare(oldObj[i], newObj[i], currentPath !== '' ? `${currentPath}.${i}` : String(i));
|
|
207
|
+
}
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
// Handle objects
|
|
211
|
+
const oldRecord = oldObj;
|
|
212
|
+
const newRecord = newObj;
|
|
213
|
+
const allKeys = new Set([...Object.keys(oldRecord), ...Object.keys(newRecord)]);
|
|
214
|
+
for (const key of allKeys) {
|
|
215
|
+
compare(oldRecord[key], newRecord[key], currentPath !== '' ? `${currentPath}.${key}` : key);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
compare(oldConfig, newConfig, '');
|
|
219
|
+
return diffs;
|
|
220
|
+
}
|
|
221
|
+
// ============================================================================
|
|
222
|
+
// Validation Helpers
|
|
223
|
+
// ============================================================================
|
|
224
|
+
/**
|
|
225
|
+
* Checks if a path exists in the config
|
|
226
|
+
*/
|
|
227
|
+
export function hasPath(config, path) {
|
|
228
|
+
return getValue(config, path) !== undefined;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Gets all paths in a config (flattened)
|
|
232
|
+
*/
|
|
233
|
+
export function getAllPaths(config) {
|
|
234
|
+
const paths = [];
|
|
235
|
+
function traverse(obj, currentPath) {
|
|
236
|
+
if (obj === null || obj === undefined) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
if (Array.isArray(obj)) {
|
|
240
|
+
paths.push(currentPath);
|
|
241
|
+
obj.forEach((item, index) => {
|
|
242
|
+
traverse(item, currentPath !== '' ? `${currentPath}.${index}` : String(index));
|
|
243
|
+
});
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (typeof obj === 'object') {
|
|
247
|
+
if (currentPath !== '') {
|
|
248
|
+
paths.push(currentPath);
|
|
249
|
+
}
|
|
250
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
251
|
+
traverse(value, currentPath !== '' ? `${currentPath}.${key}` : key);
|
|
252
|
+
}
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
paths.push(currentPath);
|
|
256
|
+
}
|
|
257
|
+
traverse(config, '');
|
|
258
|
+
return paths;
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../src/operations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Detection Port
|
|
3
|
+
*
|
|
4
|
+
* Interface for provider detection adapters (hexagonal architecture).
|
|
5
|
+
* The actual implementation belongs in the adapter layer.
|
|
6
|
+
*
|
|
7
|
+
* Invariants:
|
|
8
|
+
* - INV-CFG-ADP-002: Detection times out after 5s
|
|
9
|
+
* - INV-CFG-ADP-003: No network calls during detection
|
|
10
|
+
*/
|
|
11
|
+
import type { ProviderId, ProviderDetectionResult, ProviderDetectionSummary } from '@defai.digital/contracts';
|
|
12
|
+
/**
|
|
13
|
+
* Provider detection port (interface for adapters)
|
|
14
|
+
*
|
|
15
|
+
* This port defines the interface that detection adapters must implement.
|
|
16
|
+
* The domain depends on this interface, not on concrete implementations.
|
|
17
|
+
*/
|
|
18
|
+
export interface ProviderDetectionPort {
|
|
19
|
+
/**
|
|
20
|
+
* Detects a single provider
|
|
21
|
+
*/
|
|
22
|
+
detectProvider(providerId: ProviderId): Promise<ProviderDetectionResult>;
|
|
23
|
+
/**
|
|
24
|
+
* Detects all known providers
|
|
25
|
+
*/
|
|
26
|
+
detectAllProviders(): Promise<ProviderDetectionSummary>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Detection options
|
|
30
|
+
*/
|
|
31
|
+
export interface DetectionOptions {
|
|
32
|
+
/**
|
|
33
|
+
* Timeout in milliseconds (default: 5000)
|
|
34
|
+
*/
|
|
35
|
+
timeout?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Providers to detect (default: all)
|
|
38
|
+
*/
|
|
39
|
+
providers?: ProviderId[];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Null detection adapter that returns no providers
|
|
43
|
+
* Used as a fallback when no adapter is configured
|
|
44
|
+
*
|
|
45
|
+
* Note: AutomatosX does NOT check authentication.
|
|
46
|
+
* All CLIs handle their own auth internally.
|
|
47
|
+
*/
|
|
48
|
+
export declare const nullDetectionAdapter: ProviderDetectionPort;
|
|
49
|
+
/**
|
|
50
|
+
* Sets the provider detection adapter
|
|
51
|
+
*/
|
|
52
|
+
export declare function setDetectionAdapter(adapter: ProviderDetectionPort): void;
|
|
53
|
+
/**
|
|
54
|
+
* Gets the current provider detection adapter
|
|
55
|
+
*/
|
|
56
|
+
export declare function getDetectionAdapter(): ProviderDetectionPort;
|
|
57
|
+
/**
|
|
58
|
+
* Resets to the null adapter
|
|
59
|
+
*/
|
|
60
|
+
export declare function resetDetectionAdapter(): void;
|
|
61
|
+
//# sourceMappingURL=detection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detection.d.ts","sourceRoot":"","sources":["../../src/ports/detection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,0BAA0B,CAAC;AAMlC;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,cAAc,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAEzE;;OAEG;IACH,kBAAkB,IAAI,OAAO,CAAC,wBAAwB,CAAC,CAAC;CACzD;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,SAAS,CAAC,EAAE,UAAU,EAAE,CAAC;CAC1B;AAMD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,EAAE,qBAiBlC,CAAC;AAQF;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAExE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,qBAAqB,CAE3D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Detection Port
|
|
3
|
+
*
|
|
4
|
+
* Interface for provider detection adapters (hexagonal architecture).
|
|
5
|
+
* The actual implementation belongs in the adapter layer.
|
|
6
|
+
*
|
|
7
|
+
* Invariants:
|
|
8
|
+
* - INV-CFG-ADP-002: Detection times out after 5s
|
|
9
|
+
* - INV-CFG-ADP-003: No network calls during detection
|
|
10
|
+
*/
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Null Detection Adapter
|
|
13
|
+
// ============================================================================
|
|
14
|
+
/**
|
|
15
|
+
* Null detection adapter that returns no providers
|
|
16
|
+
* Used as a fallback when no adapter is configured
|
|
17
|
+
*
|
|
18
|
+
* Note: AutomatosX does NOT check authentication.
|
|
19
|
+
* All CLIs handle their own auth internally.
|
|
20
|
+
*/
|
|
21
|
+
export const nullDetectionAdapter = {
|
|
22
|
+
async detectProvider(providerId) {
|
|
23
|
+
return {
|
|
24
|
+
providerId,
|
|
25
|
+
detected: false,
|
|
26
|
+
command: providerId, // Use providerId as fallback command name
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
async detectAllProviders() {
|
|
30
|
+
return {
|
|
31
|
+
timestamp: new Date().toISOString(),
|
|
32
|
+
totalProviders: 0,
|
|
33
|
+
detectedCount: 0,
|
|
34
|
+
results: [],
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
// ============================================================================
|
|
39
|
+
// Detection Adapter Registry
|
|
40
|
+
// ============================================================================
|
|
41
|
+
let currentAdapter = nullDetectionAdapter;
|
|
42
|
+
/**
|
|
43
|
+
* Sets the provider detection adapter
|
|
44
|
+
*/
|
|
45
|
+
export function setDetectionAdapter(adapter) {
|
|
46
|
+
currentAdapter = adapter;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Gets the current provider detection adapter
|
|
50
|
+
*/
|
|
51
|
+
export function getDetectionAdapter() {
|
|
52
|
+
return currentAdapter;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Resets to the null adapter
|
|
56
|
+
*/
|
|
57
|
+
export function resetDetectionAdapter() {
|
|
58
|
+
currentAdapter = nullDetectionAdapter;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=detection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detection.js","sourceRoot":"","sources":["../../src/ports/detection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA6CH,+EAA+E;AAC/E,yBAAyB;AACzB,+EAA+E;AAE/E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAA0B;IACzD,KAAK,CAAC,cAAc,CAAC,UAAsB;QACzC,OAAO;YACL,UAAU;YACV,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,UAAU,EAAE,0CAA0C;SAChE,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,OAAO;YACL,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,cAAc,EAAE,CAAC;YACjB,aAAa,EAAE,CAAC;YAChB,OAAO,EAAE,EAAE;SACZ,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,+EAA+E;AAC/E,6BAA6B;AAC7B,+EAA+E;AAE/E,IAAI,cAAc,GAA0B,oBAAoB,CAAC;AAEjE;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAA8B;IAChE,cAAc,GAAG,OAAO,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,cAAc,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB;IACnC,cAAc,GAAG,oBAAoB,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Repository
|
|
3
|
+
*
|
|
4
|
+
* Persistence layer for config aggregate following repository pattern.
|
|
5
|
+
*
|
|
6
|
+
* Invariants:
|
|
7
|
+
* - INV-CFG-GOV-001: All changes emit events (audit trail)
|
|
8
|
+
*/
|
|
9
|
+
import type { ConfigEvent } from '@defai.digital/contracts';
|
|
10
|
+
import { ConfigAggregate } from './aggregate.js';
|
|
11
|
+
import { type ConfigStore } from './store.js';
|
|
12
|
+
/**
|
|
13
|
+
* Event store interface for config events
|
|
14
|
+
*/
|
|
15
|
+
export interface ConfigEventStore {
|
|
16
|
+
/**
|
|
17
|
+
* Appends events for a scope
|
|
18
|
+
*/
|
|
19
|
+
append(scope: 'global' | 'local', events: ConfigEvent[]): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Gets all events for a scope
|
|
22
|
+
*/
|
|
23
|
+
getEvents(scope: 'global' | 'local'): Promise<ConfigEvent[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Gets events since a specific version
|
|
26
|
+
*/
|
|
27
|
+
getEventsSince(scope: 'global' | 'local', version: number): Promise<ConfigEvent[]>;
|
|
28
|
+
/**
|
|
29
|
+
* Clears all events for a scope
|
|
30
|
+
*/
|
|
31
|
+
clear(scope: 'global' | 'local'): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* In-memory event store implementation
|
|
35
|
+
* Suitable for development and testing
|
|
36
|
+
*/
|
|
37
|
+
export declare class InMemoryConfigEventStore implements ConfigEventStore {
|
|
38
|
+
private events;
|
|
39
|
+
append(scope: 'global' | 'local', events: ConfigEvent[]): Promise<void>;
|
|
40
|
+
getEvents(scope: 'global' | 'local'): Promise<ConfigEvent[]>;
|
|
41
|
+
getEventsSince(scope: 'global' | 'local', version: number): Promise<ConfigEvent[]>;
|
|
42
|
+
clear(scope: 'global' | 'local'): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Config repository interface (follows Repository pattern)
|
|
46
|
+
*/
|
|
47
|
+
export interface ConfigRepository {
|
|
48
|
+
/**
|
|
49
|
+
* Loads config aggregate from store
|
|
50
|
+
*/
|
|
51
|
+
load(scope: 'global' | 'local'): Promise<ConfigAggregate>;
|
|
52
|
+
/**
|
|
53
|
+
* Saves config aggregate (commits events and persists config)
|
|
54
|
+
*/
|
|
55
|
+
save(aggregate: ConfigAggregate): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Gets event history
|
|
58
|
+
*/
|
|
59
|
+
getEvents(scope: 'global' | 'local', options?: {
|
|
60
|
+
limit?: number;
|
|
61
|
+
since?: number;
|
|
62
|
+
}): Promise<ConfigEvent[]>;
|
|
63
|
+
/**
|
|
64
|
+
* Checks if config exists
|
|
65
|
+
*/
|
|
66
|
+
exists(scope: 'global' | 'local'): Promise<boolean>;
|
|
67
|
+
/**
|
|
68
|
+
* Deletes config
|
|
69
|
+
*/
|
|
70
|
+
delete(scope: 'global' | 'local'): Promise<boolean>;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Repository options
|
|
74
|
+
*/
|
|
75
|
+
export interface ConfigRepositoryOptions {
|
|
76
|
+
eventStore?: ConfigEventStore;
|
|
77
|
+
configStore?: ConfigStore;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Creates a file-based config repository
|
|
81
|
+
*
|
|
82
|
+
* This implementation:
|
|
83
|
+
* - Persists config to JSON files (via ConfigStore)
|
|
84
|
+
* - Stores events in memory (optionally in an event store)
|
|
85
|
+
* - Loads config from file and creates aggregate from it
|
|
86
|
+
*/
|
|
87
|
+
export declare function createConfigRepository(options?: ConfigRepositoryOptions): ConfigRepository;
|
|
88
|
+
/**
|
|
89
|
+
* Gets or creates a shared repository instance
|
|
90
|
+
*/
|
|
91
|
+
export declare function getConfigRepository(): ConfigRepository;
|
|
92
|
+
/**
|
|
93
|
+
* Sets the shared repository instance (useful for testing)
|
|
94
|
+
*/
|
|
95
|
+
export declare function setConfigRepository(repository: ConfigRepository): void;
|
|
96
|
+
/**
|
|
97
|
+
* Resets the shared repository instance
|
|
98
|
+
*/
|
|
99
|
+
export declare function resetConfigRepository(): void;
|
|
100
|
+
//# sourceMappingURL=repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAoD,MAAM,gBAAgB,CAAC;AACnG,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAMjE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExE;;OAEG;IACH,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAE7D;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAEnF;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD;AAMD;;;GAGG;AACH,qBAAa,wBAAyB,YAAW,gBAAgB;IAC/D,OAAO,CAAC,MAAM,CAAoC;IAE5C,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvE,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAI5D,cAAc,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAKlF,KAAK,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAGtD;AAMD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,IAAI,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAE1D;;OAEG;IACH,IAAI,CAAC,SAAS,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhD;;OAEG;IACH,SAAS,CACP,KAAK,EAAE,QAAQ,GAAG,OAAO,EACzB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3C,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAE1B;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpD;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACrD;AAMD;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,GAAE,uBAA4B,GACpC,gBAAgB,CAoFlB;AAQD;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,gBAAgB,CAKtD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,gBAAgB,GAAG,IAAI,CAEtE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Repository
|
|
3
|
+
*
|
|
4
|
+
* Persistence layer for config aggregate following repository pattern.
|
|
5
|
+
*
|
|
6
|
+
* Invariants:
|
|
7
|
+
* - INV-CFG-GOV-001: All changes emit events (audit trail)
|
|
8
|
+
*/
|
|
9
|
+
import { createConfigAggregate, createAggregateFromConfig } from './aggregate.js';
|
|
10
|
+
import { createConfigStore } from './store.js';
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// In-Memory Event Store
|
|
13
|
+
// ============================================================================
|
|
14
|
+
/**
|
|
15
|
+
* In-memory event store implementation
|
|
16
|
+
* Suitable for development and testing
|
|
17
|
+
*/
|
|
18
|
+
export class InMemoryConfigEventStore {
|
|
19
|
+
events = new Map();
|
|
20
|
+
async append(scope, events) {
|
|
21
|
+
const existing = this.events.get(scope) ?? [];
|
|
22
|
+
this.events.set(scope, [...existing, ...events]);
|
|
23
|
+
}
|
|
24
|
+
async getEvents(scope) {
|
|
25
|
+
return [...(this.events.get(scope) ?? [])];
|
|
26
|
+
}
|
|
27
|
+
async getEventsSince(scope, version) {
|
|
28
|
+
const events = this.events.get(scope) ?? [];
|
|
29
|
+
return events.filter((e) => e.version > version);
|
|
30
|
+
}
|
|
31
|
+
async clear(scope) {
|
|
32
|
+
this.events.delete(scope);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Creates a file-based config repository
|
|
37
|
+
*
|
|
38
|
+
* This implementation:
|
|
39
|
+
* - Persists config to JSON files (via ConfigStore)
|
|
40
|
+
* - Stores events in memory (optionally in an event store)
|
|
41
|
+
* - Loads config from file and creates aggregate from it
|
|
42
|
+
*/
|
|
43
|
+
export function createConfigRepository(options = {}) {
|
|
44
|
+
const eventStore = options.eventStore ?? new InMemoryConfigEventStore();
|
|
45
|
+
const configStore = options.configStore ?? createConfigStore();
|
|
46
|
+
return {
|
|
47
|
+
async load(scope) {
|
|
48
|
+
// Load events from event store
|
|
49
|
+
const events = await eventStore.getEvents(scope);
|
|
50
|
+
// If we have events, rehydrate from them
|
|
51
|
+
if (events.length > 0) {
|
|
52
|
+
return createConfigAggregate(scope, events);
|
|
53
|
+
}
|
|
54
|
+
// Otherwise, try to load from file (for migration from non-event-sourced)
|
|
55
|
+
const config = await configStore.read(scope);
|
|
56
|
+
if (config !== undefined) {
|
|
57
|
+
// Create synthetic "created" event from existing config
|
|
58
|
+
const correlationId = crypto.randomUUID();
|
|
59
|
+
const aggregate = createAggregateFromConfig(scope, config, correlationId);
|
|
60
|
+
// Store the initial event
|
|
61
|
+
await eventStore.append(scope, aggregate.getUncommittedEvents());
|
|
62
|
+
aggregate.markEventsCommitted();
|
|
63
|
+
return aggregate;
|
|
64
|
+
}
|
|
65
|
+
// No config exists - return empty aggregate
|
|
66
|
+
return createConfigAggregate(scope, []);
|
|
67
|
+
},
|
|
68
|
+
async save(aggregate) {
|
|
69
|
+
const uncommittedEvents = aggregate.getUncommittedEvents();
|
|
70
|
+
const state = aggregate.getState();
|
|
71
|
+
if (uncommittedEvents.length === 0) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
// Append events to event store
|
|
75
|
+
await eventStore.append(state.scope, uncommittedEvents);
|
|
76
|
+
// Persist current config to file
|
|
77
|
+
const config = aggregate.getConfig();
|
|
78
|
+
if (config !== undefined && state.status === 'valid') {
|
|
79
|
+
await configStore.write(config, state.scope);
|
|
80
|
+
}
|
|
81
|
+
else if (state.status === 'uninitialized') {
|
|
82
|
+
// Config was deleted/reset
|
|
83
|
+
await configStore.delete(state.scope);
|
|
84
|
+
}
|
|
85
|
+
// Mark events as committed
|
|
86
|
+
aggregate.markEventsCommitted();
|
|
87
|
+
},
|
|
88
|
+
async getEvents(scope, options) {
|
|
89
|
+
let events;
|
|
90
|
+
if (options?.since !== undefined) {
|
|
91
|
+
events = await eventStore.getEventsSince(scope, options.since);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
events = await eventStore.getEvents(scope);
|
|
95
|
+
}
|
|
96
|
+
if (options?.limit !== undefined && options.limit > 0) {
|
|
97
|
+
return events.slice(-options.limit);
|
|
98
|
+
}
|
|
99
|
+
return events;
|
|
100
|
+
},
|
|
101
|
+
async exists(scope) {
|
|
102
|
+
return configStore.exists(scope);
|
|
103
|
+
},
|
|
104
|
+
async delete(scope) {
|
|
105
|
+
await eventStore.clear(scope);
|
|
106
|
+
return configStore.delete(scope);
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
// ============================================================================
|
|
111
|
+
// Shared Repository Instance
|
|
112
|
+
// ============================================================================
|
|
113
|
+
let sharedRepository;
|
|
114
|
+
/**
|
|
115
|
+
* Gets or creates a shared repository instance
|
|
116
|
+
*/
|
|
117
|
+
export function getConfigRepository() {
|
|
118
|
+
if (sharedRepository === undefined) {
|
|
119
|
+
sharedRepository = createConfigRepository();
|
|
120
|
+
}
|
|
121
|
+
return sharedRepository;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Sets the shared repository instance (useful for testing)
|
|
125
|
+
*/
|
|
126
|
+
export function setConfigRepository(repository) {
|
|
127
|
+
sharedRepository = repository;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Resets the shared repository instance
|
|
131
|
+
*/
|
|
132
|
+
export function resetConfigRepository() {
|
|
133
|
+
sharedRepository = undefined;
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repository.js","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"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"}
|