@shin1ohno/sage 0.10.0 → 0.11.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/dist/cli/mcp-handler.d.ts.map +1 -1
- package/dist/cli/mcp-handler.js +213 -6
- package/dist/cli/mcp-handler.js.map +1 -1
- package/dist/cli/signal-handler.d.ts +23 -0
- package/dist/cli/signal-handler.d.ts.map +1 -0
- package/dist/cli/signal-handler.js +51 -0
- package/dist/cli/signal-handler.js.map +1 -0
- package/dist/config/config-differ.d.ts +21 -0
- package/dist/config/config-differ.d.ts.map +1 -0
- package/dist/config/config-differ.js +194 -0
- package/dist/config/config-differ.js.map +1 -0
- package/dist/config/config-reload-service.d.ts +84 -0
- package/dist/config/config-reload-service.d.ts.map +1 -0
- package/dist/config/config-reload-service.js +234 -0
- package/dist/config/config-reload-service.js.map +1 -0
- package/dist/config/config-watcher.d.ts +78 -0
- package/dist/config/config-watcher.d.ts.map +1 -0
- package/dist/config/config-watcher.js +244 -0
- package/dist/config/config-watcher.js.map +1 -0
- package/dist/config/hot-reload-config.d.ts +16 -0
- package/dist/config/hot-reload-config.d.ts.map +1 -0
- package/dist/config/hot-reload-config.js +61 -0
- package/dist/config/hot-reload-config.js.map +1 -0
- package/dist/index.js +58 -0
- package/dist/index.js.map +1 -1
- package/dist/services/reloadable/calendar-source-manager-adapter.d.ts +45 -0
- package/dist/services/reloadable/calendar-source-manager-adapter.d.ts.map +1 -0
- package/dist/services/reloadable/calendar-source-manager-adapter.js +106 -0
- package/dist/services/reloadable/calendar-source-manager-adapter.js.map +1 -0
- package/dist/services/reloadable/index.d.ts +46 -0
- package/dist/services/reloadable/index.d.ts.map +1 -0
- package/dist/services/reloadable/index.js +88 -0
- package/dist/services/reloadable/index.js.map +1 -0
- package/dist/services/reloadable/notion-service-adapter.d.ts +45 -0
- package/dist/services/reloadable/notion-service-adapter.d.ts.map +1 -0
- package/dist/services/reloadable/notion-service-adapter.js +86 -0
- package/dist/services/reloadable/notion-service-adapter.js.map +1 -0
- package/dist/services/reloadable/priority-engine-adapter.d.ts +73 -0
- package/dist/services/reloadable/priority-engine-adapter.d.ts.map +1 -0
- package/dist/services/reloadable/priority-engine-adapter.js +105 -0
- package/dist/services/reloadable/priority-engine-adapter.js.map +1 -0
- package/dist/services/reloadable/reminder-manager-adapter.d.ts +45 -0
- package/dist/services/reloadable/reminder-manager-adapter.d.ts.map +1 -0
- package/dist/services/reloadable/reminder-manager-adapter.js +80 -0
- package/dist/services/reloadable/reminder-manager-adapter.js.map +1 -0
- package/dist/services/reloadable/todo-list-manager-adapter.d.ts +45 -0
- package/dist/services/reloadable/todo-list-manager-adapter.d.ts.map +1 -0
- package/dist/services/reloadable/todo-list-manager-adapter.js +80 -0
- package/dist/services/reloadable/todo-list-manager-adapter.js.map +1 -0
- package/dist/services/reloadable/working-cadence-adapter.d.ts +52 -0
- package/dist/services/reloadable/working-cadence-adapter.d.ts.map +1 -0
- package/dist/services/reloadable/working-cadence-adapter.js +77 -0
- package/dist/services/reloadable/working-cadence-adapter.js.map +1 -0
- package/dist/services/service-registry.d.ts +85 -0
- package/dist/services/service-registry.d.ts.map +1 -0
- package/dist/services/service-registry.js +166 -0
- package/dist/services/service-registry.js.map +1 -0
- package/dist/tools/config/index.d.ts +9 -0
- package/dist/tools/config/index.d.ts.map +1 -0
- package/dist/tools/config/index.js +8 -0
- package/dist/tools/config/index.js.map +1 -0
- package/dist/tools/config/reload-handler.d.ts +35 -0
- package/dist/tools/config/reload-handler.d.ts.map +1 -0
- package/dist/tools/config/reload-handler.js +63 -0
- package/dist/tools/config/reload-handler.js.map +1 -0
- package/dist/tools/integrations/handlers.d.ts +2 -0
- package/dist/tools/integrations/handlers.d.ts.map +1 -1
- package/dist/tools/integrations/handlers.js.map +1 -1
- package/dist/tools/setup/handlers.d.ts +2 -0
- package/dist/tools/setup/handlers.d.ts.map +1 -1
- package/dist/tools/setup/handlers.js +14 -0
- package/dist/tools/setup/handlers.js.map +1 -1
- package/dist/types/hot-reload.d.ts +131 -0
- package/dist/types/hot-reload.d.ts.map +1 -0
- package/dist/types/hot-reload.js +5 -0
- package/dist/types/hot-reload.js.map +1 -0
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration differ utility
|
|
3
|
+
* Provides deep comparison functionality for UserConfig objects
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Top-level sections in UserConfig that can be compared
|
|
7
|
+
*/
|
|
8
|
+
const CONFIG_SECTIONS = [
|
|
9
|
+
'user',
|
|
10
|
+
'calendar',
|
|
11
|
+
'priorityRules',
|
|
12
|
+
'estimation',
|
|
13
|
+
'reminders',
|
|
14
|
+
'team',
|
|
15
|
+
'integrations',
|
|
16
|
+
'preferences',
|
|
17
|
+
];
|
|
18
|
+
/**
|
|
19
|
+
* Check if two values are deeply equal
|
|
20
|
+
* @param a - First value
|
|
21
|
+
* @param b - Second value
|
|
22
|
+
* @returns true if values are deeply equal
|
|
23
|
+
*/
|
|
24
|
+
function deepEqual(a, b) {
|
|
25
|
+
// Handle primitive types and null/undefined
|
|
26
|
+
if (a === b) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
// Handle null/undefined cases
|
|
30
|
+
if (a === null || b === null || a === undefined || b === undefined) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
// Handle different types
|
|
34
|
+
if (typeof a !== typeof b) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
// Handle arrays
|
|
38
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
39
|
+
if (a.length !== b.length) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
return a.every((item, index) => deepEqual(item, b[index]));
|
|
43
|
+
}
|
|
44
|
+
// Handle objects
|
|
45
|
+
if (typeof a === 'object' && typeof b === 'object') {
|
|
46
|
+
const aObj = a;
|
|
47
|
+
const bObj = b;
|
|
48
|
+
const aKeys = Object.keys(aObj);
|
|
49
|
+
const bKeys = Object.keys(bObj);
|
|
50
|
+
// Check if both objects have the same number of keys
|
|
51
|
+
if (aKeys.length !== bKeys.length) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
// Check if all keys in a exist in b with equal values
|
|
55
|
+
return aKeys.every((key) => {
|
|
56
|
+
if (!Object.prototype.hasOwnProperty.call(bObj, key)) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return deepEqual(aObj[key], bObj[key]);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
// Primitive values that are not equal
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get all keys from an object recursively with dot notation
|
|
67
|
+
* @param obj - Object to get keys from
|
|
68
|
+
* @param prefix - Prefix for nested keys
|
|
69
|
+
* @returns Array of dot-notation key paths
|
|
70
|
+
*/
|
|
71
|
+
function getDeepKeys(obj, prefix = '') {
|
|
72
|
+
if (obj === null || obj === undefined || typeof obj !== 'object' || Array.isArray(obj)) {
|
|
73
|
+
return prefix ? [prefix] : [];
|
|
74
|
+
}
|
|
75
|
+
const objRecord = obj;
|
|
76
|
+
const keys = [];
|
|
77
|
+
for (const key of Object.keys(objRecord)) {
|
|
78
|
+
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
79
|
+
const value = objRecord[key];
|
|
80
|
+
if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
|
|
81
|
+
keys.push(...getDeepKeys(value, fullKey));
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
keys.push(fullKey);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return keys;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Get a value from an object using dot notation path
|
|
91
|
+
* @param obj - Object to get value from
|
|
92
|
+
* @param path - Dot notation path
|
|
93
|
+
* @returns Value at path or undefined
|
|
94
|
+
*/
|
|
95
|
+
function getValueByPath(obj, path) {
|
|
96
|
+
if (obj === null || obj === undefined || typeof obj !== 'object') {
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
const parts = path.split('.');
|
|
100
|
+
let current = obj;
|
|
101
|
+
for (const part of parts) {
|
|
102
|
+
if (current === null || current === undefined || typeof current !== 'object') {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
current = current[part];
|
|
106
|
+
}
|
|
107
|
+
return current;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Compare two UserConfig objects and return the differences
|
|
111
|
+
* @param oldConfig - Previous configuration
|
|
112
|
+
* @param newConfig - New configuration
|
|
113
|
+
* @returns ConfigDiff describing all differences
|
|
114
|
+
*/
|
|
115
|
+
export function diffConfig(oldConfig, newConfig) {
|
|
116
|
+
const changedSections = [];
|
|
117
|
+
const addedKeys = {};
|
|
118
|
+
const removedKeys = [];
|
|
119
|
+
const modifiedKeys = {};
|
|
120
|
+
// Compare each top-level section
|
|
121
|
+
for (const section of CONFIG_SECTIONS) {
|
|
122
|
+
const oldSection = oldConfig[section];
|
|
123
|
+
const newSection = newConfig[section];
|
|
124
|
+
if (!deepEqual(oldSection, newSection)) {
|
|
125
|
+
changedSections.push(section);
|
|
126
|
+
// Get detailed changes within this section
|
|
127
|
+
const oldKeys = getDeepKeys(oldSection, section);
|
|
128
|
+
const newKeys = getDeepKeys(newSection, section);
|
|
129
|
+
const oldKeySet = new Set(oldKeys);
|
|
130
|
+
const newKeySet = new Set(newKeys);
|
|
131
|
+
// Find added keys
|
|
132
|
+
for (const key of newKeys) {
|
|
133
|
+
if (!oldKeySet.has(key)) {
|
|
134
|
+
addedKeys[key] = getValueByPath(newConfig, key);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// Find removed keys
|
|
138
|
+
for (const key of oldKeys) {
|
|
139
|
+
if (!newKeySet.has(key)) {
|
|
140
|
+
removedKeys.push(key);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Find modified keys (keys that exist in both but have different values)
|
|
144
|
+
for (const key of oldKeys) {
|
|
145
|
+
if (newKeySet.has(key)) {
|
|
146
|
+
const oldValue = getValueByPath(oldConfig, key);
|
|
147
|
+
const newValue = getValueByPath(newConfig, key);
|
|
148
|
+
if (!deepEqual(oldValue, newValue)) {
|
|
149
|
+
modifiedKeys[key] = { old: oldValue, new: newValue };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// Also check metadata fields that might have changed
|
|
156
|
+
if (oldConfig.version !== newConfig.version) {
|
|
157
|
+
modifiedKeys['version'] = { old: oldConfig.version, new: newConfig.version };
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
changedSections,
|
|
161
|
+
addedKeys,
|
|
162
|
+
removedKeys,
|
|
163
|
+
modifiedKeys,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Check if the config diff contains significant changes that warrant service re-initialization
|
|
168
|
+
* Changes to metadata fields (version, createdAt, lastUpdated) are not considered significant
|
|
169
|
+
* @param diff - ConfigDiff to evaluate
|
|
170
|
+
* @returns true if there are significant changes
|
|
171
|
+
*/
|
|
172
|
+
export function hasSignificantChanges(diff) {
|
|
173
|
+
// If there are changed sections, that's significant
|
|
174
|
+
if (diff.changedSections.length > 0) {
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
// If there are added or removed keys (excluding metadata), that's significant
|
|
178
|
+
const metadataKeys = ['version', 'createdAt', 'lastUpdated'];
|
|
179
|
+
const significantAddedKeys = Object.keys(diff.addedKeys).filter((key) => !metadataKeys.includes(key));
|
|
180
|
+
if (significantAddedKeys.length > 0) {
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
const significantRemovedKeys = diff.removedKeys.filter((key) => !metadataKeys.includes(key));
|
|
184
|
+
if (significantRemovedKeys.length > 0) {
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
// If there are modified keys (excluding metadata), that's significant
|
|
188
|
+
const significantModifiedKeys = Object.keys(diff.modifiedKeys).filter((key) => !metadataKeys.includes(key));
|
|
189
|
+
if (significantModifiedKeys.length > 0) {
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=config-differ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-differ.js","sourceRoot":"","sources":["../../src/config/config-differ.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;GAEG;AACH,MAAM,eAAe,GAAG;IACtB,MAAM;IACN,UAAU;IACV,eAAe;IACf,YAAY;IACZ,WAAW;IACX,MAAM;IACN,cAAc;IACd,aAAa;CACL,CAAC;AAEX;;;;;GAKG;AACH,SAAS,SAAS,CAAC,CAAU,EAAE,CAAU;IACvC,4CAA4C;IAC5C,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IAED,8BAA8B;IAC9B,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;QACnE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,yBAAyB;IACzB,IAAI,OAAO,CAAC,KAAK,OAAO,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,gBAAgB;IAChB,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;YAC1B,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED,iBAAiB;IACjB,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QACnD,MAAM,IAAI,GAAG,CAA4B,CAAC;QAC1C,MAAM,IAAI,GAAG,CAA4B,CAAC;QAE1C,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEhC,qDAAqD;QACrD,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC;YAClC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,sDAAsD;QACtD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACzB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;gBACrD,OAAO,KAAK,CAAC;YACf,CAAC;YACD,OAAO,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;IACL,CAAC;IAED,sCAAsC;IACtC,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,SAAS,WAAW,CAAC,GAAY,EAAE,MAAM,GAAG,EAAE;IAC5C,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvF,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAChC,CAAC;IAED,MAAM,SAAS,GAAG,GAA8B,CAAC;IACjD,MAAM,IAAI,GAAa,EAAE,CAAC;IAE1B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;QAClD,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;QAE7B,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzE,IAAI,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;QAC5C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,SAAS,cAAc,CAAC,GAAY,EAAE,IAAY;IAChD,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACjE,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,OAAO,GAAY,GAAG,CAAC;IAE3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC7E,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,GAAI,OAAmC,CAAC,IAAI,CAAC,CAAC;IACvD,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,SAAqB,EAAE,SAAqB;IACrE,MAAM,eAAe,GAAa,EAAE,CAAC;IACrC,MAAM,SAAS,GAA4B,EAAE,CAAC;IAC9C,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,MAAM,YAAY,GAAmD,EAAE,CAAC;IAExE,iCAAiC;IACjC,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;QACtC,MAAM,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAEtC,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,CAAC;YACvC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAE9B,2CAA2C;YAC3C,MAAM,OAAO,GAAG,WAAW,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACjD,MAAM,OAAO,GAAG,WAAW,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YAEjD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;YACnC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;YAEnC,kBAAkB;YAClB,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;gBAC1B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBACxB,SAAS,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;gBAClD,CAAC;YACH,CAAC;YAED,oBAAoB;YACpB,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;gBAC1B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBACxB,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC;YAED,yEAAyE;YACzE,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;gBAC1B,IAAI,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBACvB,MAAM,QAAQ,GAAG,cAAc,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;oBAChD,MAAM,QAAQ,GAAG,cAAc,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;oBAEhD,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;wBACnC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;oBACvD,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,qDAAqD;IACrD,IAAI,SAAS,CAAC,OAAO,KAAK,SAAS,CAAC,OAAO,EAAE,CAAC;QAC5C,YAAY,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,CAAC,OAAO,EAAE,GAAG,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC;IAC/E,CAAC;IAED,OAAO;QACL,eAAe;QACf,SAAS;QACT,WAAW;QACX,YAAY;KACb,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAgB;IACpD,oDAAoD;IACpD,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,8EAA8E;IAC9E,MAAM,YAAY,GAAG,CAAC,SAAS,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;IAE7D,MAAM,oBAAoB,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAC7D,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CACrC,CAAC;IACF,IAAI,oBAAoB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,sBAAsB,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7F,IAAI,sBAAsB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,sEAAsE;IACtE,MAAM,uBAAuB,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,CACnE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CACrC,CAAC;IACF,IAAI,uBAAuB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Reload Service
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates configuration hot-reload functionality.
|
|
5
|
+
* Subscribes to ConfigWatcher events and coordinates service
|
|
6
|
+
* re-initialization through ServiceRegistry.
|
|
7
|
+
*/
|
|
8
|
+
import type { ReloadResult, ConfigReloadServiceOptions, ConfigWatcher } from '../types/hot-reload.js';
|
|
9
|
+
import type { UserConfig } from '../types/config.js';
|
|
10
|
+
import type { ServiceRegistry } from '../services/service-registry.js';
|
|
11
|
+
/**
|
|
12
|
+
* ConfigReloadService manages automatic configuration reloading
|
|
13
|
+
*
|
|
14
|
+
* Subscribes to file change events from ConfigWatcher, validates
|
|
15
|
+
* new configuration, calculates differences, and coordinates
|
|
16
|
+
* service re-initialization through ServiceRegistry.
|
|
17
|
+
*/
|
|
18
|
+
export declare class ConfigReloadService {
|
|
19
|
+
private readonly watcher;
|
|
20
|
+
private readonly serviceRegistry;
|
|
21
|
+
private readonly enableAutoReload;
|
|
22
|
+
private readonly onReloadCallback?;
|
|
23
|
+
private currentConfig;
|
|
24
|
+
private lastReloadResult;
|
|
25
|
+
private isReloading;
|
|
26
|
+
private pendingReload;
|
|
27
|
+
private changeHandler;
|
|
28
|
+
/**
|
|
29
|
+
* Create a new ConfigReloadService
|
|
30
|
+
*
|
|
31
|
+
* @param watcher - ConfigWatcher instance to subscribe to
|
|
32
|
+
* @param serviceRegistry - ServiceRegistry for coordinating service re-initialization
|
|
33
|
+
* @param options - Optional configuration options
|
|
34
|
+
*/
|
|
35
|
+
constructor(watcher: ConfigWatcher, serviceRegistry: ServiceRegistry, options?: ConfigReloadServiceOptions);
|
|
36
|
+
/**
|
|
37
|
+
* Start the reload service
|
|
38
|
+
*
|
|
39
|
+
* Loads initial configuration and subscribes to watcher events
|
|
40
|
+
* if auto-reload is enabled.
|
|
41
|
+
*/
|
|
42
|
+
start(): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Stop the reload service
|
|
45
|
+
*
|
|
46
|
+
* Unsubscribes from watcher events and stops the watcher.
|
|
47
|
+
*/
|
|
48
|
+
stop(): void;
|
|
49
|
+
/**
|
|
50
|
+
* Check if auto-reload is enabled
|
|
51
|
+
*/
|
|
52
|
+
isAutoReloadEnabled(): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Get the result of the last reload operation
|
|
55
|
+
*/
|
|
56
|
+
getLastReloadResult(): ReloadResult | null;
|
|
57
|
+
/**
|
|
58
|
+
* Get the current configuration
|
|
59
|
+
*/
|
|
60
|
+
getCurrentConfig(): UserConfig | null;
|
|
61
|
+
/**
|
|
62
|
+
* Reload configuration manually or in response to file changes
|
|
63
|
+
*
|
|
64
|
+
* Implements reload lock mechanism to prevent concurrent reloads.
|
|
65
|
+
* If a reload is already in progress, queues the request and returns
|
|
66
|
+
* the same promise.
|
|
67
|
+
*
|
|
68
|
+
* @returns ReloadResult with details about the reload operation
|
|
69
|
+
*/
|
|
70
|
+
reload(): Promise<ReloadResult>;
|
|
71
|
+
/**
|
|
72
|
+
* Perform the actual reload operation
|
|
73
|
+
*/
|
|
74
|
+
private performReload;
|
|
75
|
+
/**
|
|
76
|
+
* Handle config file change events from watcher
|
|
77
|
+
*/
|
|
78
|
+
private handleConfigChange;
|
|
79
|
+
/**
|
|
80
|
+
* Invoke the onReload callback if configured
|
|
81
|
+
*/
|
|
82
|
+
private invokeCallback;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=config-reload-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-reload-service.d.ts","sourceRoot":"","sources":["../../src/config/config-reload-service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,0BAA0B,EAC1B,aAAa,EACd,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAKvE;;;;;;GAMG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAClD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAU;IAC3C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAiC;IAEnE,OAAO,CAAC,aAAa,CAA2B;IAChD,OAAO,CAAC,gBAAgB,CAA6B;IACrD,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,aAAa,CAAsC;IAC3D,OAAO,CAAC,aAAa,CAAyC;IAE9D;;;;;;OAMG;gBAED,OAAO,EAAE,aAAa,EACtB,eAAe,EAAE,eAAe,EAChC,OAAO,GAAE,0BAA+B;IAa1C;;;;;OAKG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB5B;;;;OAIG;IACH,IAAI,IAAI,IAAI;IAeZ;;OAEG;IACH,mBAAmB,IAAI,OAAO;IAI9B;;OAEG;IACH,mBAAmB,IAAI,YAAY,GAAG,IAAI;IAI1C;;OAEG;IACH,gBAAgB,IAAI,UAAU,GAAG,IAAI;IAIrC;;;;;;;;OAQG;IACG,MAAM,IAAI,OAAO,CAAC,YAAY,CAAC;IA0BrC;;OAEG;YACW,aAAa;IAoG3B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;OAEG;IACH,OAAO,CAAC,cAAc;CAYvB"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Reload Service
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates configuration hot-reload functionality.
|
|
5
|
+
* Subscribes to ConfigWatcher events and coordinates service
|
|
6
|
+
* re-initialization through ServiceRegistry.
|
|
7
|
+
*/
|
|
8
|
+
import { ConfigLoader } from './loader.js';
|
|
9
|
+
import { diffConfig, hasSignificantChanges } from './config-differ.js';
|
|
10
|
+
import { createLogger } from '../utils/logger.js';
|
|
11
|
+
const logger = createLogger('config-reload-service');
|
|
12
|
+
/**
|
|
13
|
+
* ConfigReloadService manages automatic configuration reloading
|
|
14
|
+
*
|
|
15
|
+
* Subscribes to file change events from ConfigWatcher, validates
|
|
16
|
+
* new configuration, calculates differences, and coordinates
|
|
17
|
+
* service re-initialization through ServiceRegistry.
|
|
18
|
+
*/
|
|
19
|
+
export class ConfigReloadService {
|
|
20
|
+
watcher;
|
|
21
|
+
serviceRegistry;
|
|
22
|
+
enableAutoReload;
|
|
23
|
+
onReloadCallback;
|
|
24
|
+
currentConfig = null;
|
|
25
|
+
lastReloadResult = null;
|
|
26
|
+
isReloading = false;
|
|
27
|
+
pendingReload = null;
|
|
28
|
+
changeHandler = null;
|
|
29
|
+
/**
|
|
30
|
+
* Create a new ConfigReloadService
|
|
31
|
+
*
|
|
32
|
+
* @param watcher - ConfigWatcher instance to subscribe to
|
|
33
|
+
* @param serviceRegistry - ServiceRegistry for coordinating service re-initialization
|
|
34
|
+
* @param options - Optional configuration options
|
|
35
|
+
*/
|
|
36
|
+
constructor(watcher, serviceRegistry, options = {}) {
|
|
37
|
+
this.watcher = watcher;
|
|
38
|
+
this.serviceRegistry = serviceRegistry;
|
|
39
|
+
this.enableAutoReload = options.enableAutoReload ?? true;
|
|
40
|
+
this.onReloadCallback = options.onReload;
|
|
41
|
+
logger.debug({ enableAutoReload: this.enableAutoReload }, 'ConfigReloadService initialized');
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Start the reload service
|
|
45
|
+
*
|
|
46
|
+
* Loads initial configuration and subscribes to watcher events
|
|
47
|
+
* if auto-reload is enabled.
|
|
48
|
+
*/
|
|
49
|
+
async start() {
|
|
50
|
+
logger.info('Starting ConfigReloadService');
|
|
51
|
+
// Load initial configuration
|
|
52
|
+
try {
|
|
53
|
+
this.currentConfig = await ConfigLoader.load();
|
|
54
|
+
logger.debug('Initial configuration loaded');
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
logger.error({ err: error }, 'Failed to load initial configuration');
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
// Subscribe to watcher events if auto-reload is enabled
|
|
61
|
+
if (this.enableAutoReload) {
|
|
62
|
+
this.changeHandler = this.handleConfigChange.bind(this);
|
|
63
|
+
this.watcher.on('change', this.changeHandler);
|
|
64
|
+
logger.info('Subscribed to config watcher change events');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Stop the reload service
|
|
69
|
+
*
|
|
70
|
+
* Unsubscribes from watcher events and stops the watcher.
|
|
71
|
+
*/
|
|
72
|
+
stop() {
|
|
73
|
+
logger.info('Stopping ConfigReloadService');
|
|
74
|
+
// Unsubscribe from watcher events
|
|
75
|
+
if (this.changeHandler) {
|
|
76
|
+
this.watcher.off('change', this.changeHandler);
|
|
77
|
+
this.changeHandler = null;
|
|
78
|
+
logger.debug('Unsubscribed from config watcher change events');
|
|
79
|
+
}
|
|
80
|
+
// Stop the watcher
|
|
81
|
+
this.watcher.stop();
|
|
82
|
+
logger.info('ConfigReloadService stopped');
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Check if auto-reload is enabled
|
|
86
|
+
*/
|
|
87
|
+
isAutoReloadEnabled() {
|
|
88
|
+
return this.enableAutoReload;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Get the result of the last reload operation
|
|
92
|
+
*/
|
|
93
|
+
getLastReloadResult() {
|
|
94
|
+
return this.lastReloadResult;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Get the current configuration
|
|
98
|
+
*/
|
|
99
|
+
getCurrentConfig() {
|
|
100
|
+
return this.currentConfig;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Reload configuration manually or in response to file changes
|
|
104
|
+
*
|
|
105
|
+
* Implements reload lock mechanism to prevent concurrent reloads.
|
|
106
|
+
* If a reload is already in progress, queues the request and returns
|
|
107
|
+
* the same promise.
|
|
108
|
+
*
|
|
109
|
+
* @returns ReloadResult with details about the reload operation
|
|
110
|
+
*/
|
|
111
|
+
async reload() {
|
|
112
|
+
// If already reloading, queue and return pending promise
|
|
113
|
+
if (this.isReloading && this.pendingReload) {
|
|
114
|
+
logger.debug('Reload already in progress, queueing request');
|
|
115
|
+
return this.pendingReload;
|
|
116
|
+
}
|
|
117
|
+
// Set reload lock
|
|
118
|
+
this.isReloading = true;
|
|
119
|
+
logger.info('Starting configuration reload');
|
|
120
|
+
const startTime = Date.now();
|
|
121
|
+
// Create and store the pending reload promise
|
|
122
|
+
this.pendingReload = this.performReload(startTime);
|
|
123
|
+
try {
|
|
124
|
+
const result = await this.pendingReload;
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
finally {
|
|
128
|
+
// Release reload lock
|
|
129
|
+
this.isReloading = false;
|
|
130
|
+
this.pendingReload = null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Perform the actual reload operation
|
|
135
|
+
*/
|
|
136
|
+
async performReload(startTime) {
|
|
137
|
+
try {
|
|
138
|
+
// Load new configuration
|
|
139
|
+
logger.debug('Loading new configuration from disk');
|
|
140
|
+
const newConfig = await ConfigLoader.load();
|
|
141
|
+
// Calculate diff if we have a previous config
|
|
142
|
+
let changedSections = [];
|
|
143
|
+
if (this.currentConfig) {
|
|
144
|
+
const diff = diffConfig(this.currentConfig, newConfig);
|
|
145
|
+
logger.debug({
|
|
146
|
+
changedSections: diff.changedSections,
|
|
147
|
+
addedKeys: Object.keys(diff.addedKeys).length,
|
|
148
|
+
removedKeys: diff.removedKeys.length,
|
|
149
|
+
modifiedKeys: Object.keys(diff.modifiedKeys).length,
|
|
150
|
+
}, 'Configuration diff calculated');
|
|
151
|
+
// Check if there are significant changes
|
|
152
|
+
if (!hasSignificantChanges(diff)) {
|
|
153
|
+
logger.info('No significant configuration changes detected');
|
|
154
|
+
const result = {
|
|
155
|
+
success: true,
|
|
156
|
+
changedSections: [],
|
|
157
|
+
reinitializedServices: [],
|
|
158
|
+
timestamp: new Date().toISOString(),
|
|
159
|
+
durationMs: Date.now() - startTime,
|
|
160
|
+
};
|
|
161
|
+
this.lastReloadResult = result;
|
|
162
|
+
this.invokeCallback(result);
|
|
163
|
+
return result;
|
|
164
|
+
}
|
|
165
|
+
changedSections = diff.changedSections;
|
|
166
|
+
}
|
|
167
|
+
// Re-initialize affected services
|
|
168
|
+
logger.info({ changedSections }, 'Re-initializing services for changed sections');
|
|
169
|
+
const affectedServices = this.serviceRegistry.getServicesForSections(changedSections);
|
|
170
|
+
const reinitializedServices = affectedServices.map((s) => s.name);
|
|
171
|
+
await this.serviceRegistry.reinitializeForSections(changedSections, newConfig);
|
|
172
|
+
// Update current config
|
|
173
|
+
this.currentConfig = newConfig;
|
|
174
|
+
const durationMs = Date.now() - startTime;
|
|
175
|
+
logger.info({
|
|
176
|
+
changedSections,
|
|
177
|
+
reinitializedServices,
|
|
178
|
+
durationMs,
|
|
179
|
+
}, 'Configuration reload completed successfully');
|
|
180
|
+
const result = {
|
|
181
|
+
success: true,
|
|
182
|
+
changedSections,
|
|
183
|
+
reinitializedServices,
|
|
184
|
+
timestamp: new Date().toISOString(),
|
|
185
|
+
durationMs,
|
|
186
|
+
};
|
|
187
|
+
this.lastReloadResult = result;
|
|
188
|
+
this.invokeCallback(result);
|
|
189
|
+
return result;
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
const durationMs = Date.now() - startTime;
|
|
193
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
194
|
+
logger.error({
|
|
195
|
+
err: error,
|
|
196
|
+
durationMs,
|
|
197
|
+
}, 'Configuration reload failed');
|
|
198
|
+
const result = {
|
|
199
|
+
success: false,
|
|
200
|
+
changedSections: [],
|
|
201
|
+
reinitializedServices: [],
|
|
202
|
+
error: errorMessage,
|
|
203
|
+
timestamp: new Date().toISOString(),
|
|
204
|
+
durationMs,
|
|
205
|
+
};
|
|
206
|
+
this.lastReloadResult = result;
|
|
207
|
+
this.invokeCallback(result);
|
|
208
|
+
return result;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Handle config file change events from watcher
|
|
213
|
+
*/
|
|
214
|
+
handleConfigChange(path) {
|
|
215
|
+
logger.info({ path }, 'Config file change detected, triggering reload');
|
|
216
|
+
this.reload().catch((error) => {
|
|
217
|
+
logger.error({ err: error, path }, 'Failed to reload configuration after file change');
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Invoke the onReload callback if configured
|
|
222
|
+
*/
|
|
223
|
+
invokeCallback(result) {
|
|
224
|
+
if (this.onReloadCallback) {
|
|
225
|
+
try {
|
|
226
|
+
this.onReloadCallback(result);
|
|
227
|
+
}
|
|
228
|
+
catch (error) {
|
|
229
|
+
logger.error({ err: error }, 'Error in onReload callback');
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=config-reload-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-reload-service.js","sourceRoot":"","sources":["../../src/config/config-reload-service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEvE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,MAAM,GAAG,YAAY,CAAC,uBAAuB,CAAC,CAAC;AAErD;;;;;;GAMG;AACH,MAAM,OAAO,mBAAmB;IACb,OAAO,CAAgB;IACvB,eAAe,CAAkB;IACjC,gBAAgB,CAAU;IAC1B,gBAAgB,CAAkC;IAE3D,aAAa,GAAsB,IAAI,CAAC;IACxC,gBAAgB,GAAwB,IAAI,CAAC;IAC7C,WAAW,GAAY,KAAK,CAAC;IAC7B,aAAa,GAAiC,IAAI,CAAC;IACnD,aAAa,GAAoC,IAAI,CAAC;IAE9D;;;;;;OAMG;IACH,YACE,OAAsB,EACtB,eAAgC,EAChC,UAAsC,EAAE;QAExC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;QACvC,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,IAAI,CAAC;QACzD,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;QAEzC,MAAM,CAAC,KAAK,CACV,EAAE,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,EAC3C,iCAAiC,CAClC,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,KAAK;QACT,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAE5C,6BAA6B;QAC7B,IAAI,CAAC;YACH,IAAI,CAAC,aAAa,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,CAAC;YAC/C,MAAM,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAC/C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CACV,EAAE,GAAG,EAAE,KAAK,EAAE,EACd,sCAAsC,CACvC,CAAC;YACF,MAAM,KAAK,CAAC;QACd,CAAC;QAED,wDAAwD;QACxD,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxD,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;YAC9C,MAAM,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,IAAI;QACF,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAE5C,kCAAkC;QAClC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;YAC/C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;YAC1B,MAAM,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACjE,CAAC;QAED,mBAAmB;QACnB,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACpB,MAAM,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACH,mBAAmB;QACjB,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,mBAAmB;QACjB,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,gBAAgB;QACd,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,MAAM;QACV,yDAAyD;QACzD,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YAC3C,MAAM,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAC7D,OAAO,IAAI,CAAC,aAAa,CAAC;QAC5B,CAAC;QAED,kBAAkB;QAClB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,MAAM,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;QAE7C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,8CAA8C;QAC9C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QAEnD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC;YACxC,OAAO,MAAM,CAAC;QAChB,CAAC;gBAAS,CAAC;YACT,sBAAsB;YACtB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;YACzB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC5B,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,aAAa,CAAC,SAAiB;QAC3C,IAAI,CAAC;YACH,yBAAyB;YACzB,MAAM,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;YACpD,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,CAAC;YAE5C,8CAA8C;YAC9C,IAAI,eAAe,GAAa,EAAE,CAAC;YACnC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;gBACvB,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;gBACvD,MAAM,CAAC,KAAK,CACV;oBACE,eAAe,EAAE,IAAI,CAAC,eAAe;oBACrC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM;oBAC7C,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,MAAM;oBACpC,YAAY,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM;iBACpD,EACD,+BAA+B,CAChC,CAAC;gBAEF,yCAAyC;gBACzC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,CAAC;oBACjC,MAAM,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;oBAC7D,MAAM,MAAM,GAAiB;wBAC3B,OAAO,EAAE,IAAI;wBACb,eAAe,EAAE,EAAE;wBACnB,qBAAqB,EAAE,EAAE;wBACzB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;wBACnC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;qBACnC,CAAC;oBACF,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC;oBAC/B,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;oBAC5B,OAAO,MAAM,CAAC;gBAChB,CAAC;gBAED,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC;YACzC,CAAC;YAED,kCAAkC;YAClC,MAAM,CAAC,IAAI,CACT,EAAE,eAAe,EAAE,EACnB,+CAA+C,CAChD,CAAC;YAEF,MAAM,gBAAgB,GAAG,IAAI,CAAC,eAAe,CAAC,sBAAsB,CAAC,eAAe,CAAC,CAAC;YACtF,MAAM,qBAAqB,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAElE,MAAM,IAAI,CAAC,eAAe,CAAC,uBAAuB,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;YAE/E,wBAAwB;YACxB,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;YAE/B,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAC1C,MAAM,CAAC,IAAI,CACT;gBACE,eAAe;gBACf,qBAAqB;gBACrB,UAAU;aACX,EACD,6CAA6C,CAC9C,CAAC;YAEF,MAAM,MAAM,GAAiB;gBAC3B,OAAO,EAAE,IAAI;gBACb,eAAe;gBACf,qBAAqB;gBACrB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,UAAU;aACX,CAAC;YAEF,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC;YAC/B,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;YAC5B,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAC1C,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAE5E,MAAM,CAAC,KAAK,CACV;gBACE,GAAG,EAAE,KAAK;gBACV,UAAU;aACX,EACD,6BAA6B,CAC9B,CAAC;YAEF,MAAM,MAAM,GAAiB;gBAC3B,OAAO,EAAE,KAAK;gBACd,eAAe,EAAE,EAAE;gBACnB,qBAAqB,EAAE,EAAE;gBACzB,KAAK,EAAE,YAAY;gBACnB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,UAAU;aACX,CAAC;YAEF,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC;YAC/B,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;YAC5B,OAAO,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IAED;;OAEG;IACK,kBAAkB,CAAC,IAAY;QACrC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,gDAAgD,CAAC,CAAC;QACxE,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YAC5B,MAAM,CAAC,KAAK,CACV,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EACpB,kDAAkD,CACnD,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,MAAoB;QACzC,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,IAAI,CAAC;gBACH,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;YAChC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CACV,EAAE,GAAG,EAAE,KAAK,EAAE,EACd,4BAA4B,CAC7B,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration File Watcher
|
|
3
|
+
* Watches user config and remote config files for changes
|
|
4
|
+
* and emits events with debouncing support.
|
|
5
|
+
*/
|
|
6
|
+
import { EventEmitter } from 'events';
|
|
7
|
+
import type { ConfigWatcherOptions, ConfigWatcherEvents } from '../types/hot-reload.js';
|
|
8
|
+
/**
|
|
9
|
+
* ConfigWatcher watches configuration files for changes
|
|
10
|
+
* and emits debounced 'change' events.
|
|
11
|
+
*/
|
|
12
|
+
export declare class ConfigWatcher extends EventEmitter {
|
|
13
|
+
private readonly debounceMs;
|
|
14
|
+
private readonly configPaths;
|
|
15
|
+
private watchers;
|
|
16
|
+
private debounceTimers;
|
|
17
|
+
private watching;
|
|
18
|
+
constructor(options?: ConfigWatcherOptions);
|
|
19
|
+
/**
|
|
20
|
+
* Start watching all configuration files
|
|
21
|
+
*/
|
|
22
|
+
start(): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Stop watching all configuration files
|
|
25
|
+
*/
|
|
26
|
+
stop(): void;
|
|
27
|
+
/**
|
|
28
|
+
* Check if the watcher is currently active
|
|
29
|
+
*/
|
|
30
|
+
isWatching(): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Get the list of watched paths
|
|
33
|
+
*/
|
|
34
|
+
getWatchedPaths(): string[];
|
|
35
|
+
/**
|
|
36
|
+
* Watch a single file for changes
|
|
37
|
+
*/
|
|
38
|
+
private watchFile;
|
|
39
|
+
/**
|
|
40
|
+
* Watch for file creation when the file doesn't exist
|
|
41
|
+
*/
|
|
42
|
+
private watchForFileCreation;
|
|
43
|
+
/**
|
|
44
|
+
* Handle file change events
|
|
45
|
+
*/
|
|
46
|
+
private handleFileChange;
|
|
47
|
+
/**
|
|
48
|
+
* Handle potential file deletion
|
|
49
|
+
*/
|
|
50
|
+
private handlePotentialDeletion;
|
|
51
|
+
/**
|
|
52
|
+
* Emit debounced change event
|
|
53
|
+
*/
|
|
54
|
+
private emitDebouncedChange;
|
|
55
|
+
/**
|
|
56
|
+
* Handle watch errors
|
|
57
|
+
*/
|
|
58
|
+
private handleWatchError;
|
|
59
|
+
/**
|
|
60
|
+
* Check if a file exists
|
|
61
|
+
*/
|
|
62
|
+
private fileExists;
|
|
63
|
+
/**
|
|
64
|
+
* Get parent directory of a file path
|
|
65
|
+
*/
|
|
66
|
+
private getParentDirectory;
|
|
67
|
+
/**
|
|
68
|
+
* Get file name from a file path
|
|
69
|
+
*/
|
|
70
|
+
private getFileName;
|
|
71
|
+
/**
|
|
72
|
+
* Type-safe event emitter methods
|
|
73
|
+
*/
|
|
74
|
+
on<K extends keyof ConfigWatcherEvents>(event: K, listener: ConfigWatcherEvents[K]): this;
|
|
75
|
+
off<K extends keyof ConfigWatcherEvents>(event: K, listener: ConfigWatcherEvents[K]): this;
|
|
76
|
+
emit<K extends keyof ConfigWatcherEvents>(event: K, ...args: Parameters<ConfigWatcherEvents[K]>): boolean;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=config-watcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-watcher.d.ts","sourceRoot":"","sources":["../../src/config/config-watcher.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAYxF;;;GAGG;AACH,qBAAa,aAAc,SAAQ,YAAY;IAC7C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAW;IACvC,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,cAAc,CAA0C;IAChE,OAAO,CAAC,QAAQ,CAAkB;gBAEtB,OAAO,GAAE,oBAAyB;IAW9C;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAe5B;;OAEG;IACH,IAAI,IAAI,IAAI;IAwBZ;;OAEG;IACH,UAAU,IAAI,OAAO;IAIrB;;OAEG;IACH,eAAe,IAAI,MAAM,EAAE;IAI3B;;OAEG;YACW,SAAS;IA0BvB;;OAEG;YACW,oBAAoB;IAsClC;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAaxB;;OAEG;YACW,uBAAuB;IAoBrC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAiB3B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAKxB;;OAEG;YACW,UAAU;IASxB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAK1B;;OAEG;IACH,OAAO,CAAC,WAAW;IAKnB;;OAEG;IACM,EAAE,CAAC,CAAC,SAAS,MAAM,mBAAmB,EAC7C,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAC/B,IAAI;IAIE,GAAG,CAAC,CAAC,SAAS,MAAM,mBAAmB,EAC9C,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAC/B,IAAI;IAIE,IAAI,CAAC,CAAC,SAAS,MAAM,mBAAmB,EAC/C,KAAK,EAAE,CAAC,EACR,GAAG,IAAI,EAAE,UAAU,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,GAC1C,OAAO;CAGX"}
|