@devilsdev/rag-pipeline-utils 2.2.1 → 2.3.0
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/README.md +244 -11
- package/contracts/contract-schema.json +189 -0
- package/dist/index.cjs +19 -0
- package/dist/index.mjs +15 -1
- package/package.json +3 -2
- package/src/cli/commands/wizard.js +627 -0
- package/src/cli/input-sanitization-middleware.js +356 -0
- package/src/cli/templates/development.template.json +64 -0
- package/src/cli/templates/minimal.template.json +33 -0
- package/src/cli/templates/production.template.json +104 -0
- package/src/cli/templates/testing.template.json +45 -0
- package/src/config/connection-pool-config.json +259 -0
- package/src/config/memory-optimization.js +414 -0
- package/src/config/redaction-patterns.json +150 -0
- package/src/config/sanitization-rules.json +323 -0
- package/src/core/plugin-registry.js +266 -20
- package/src/dag/core/error-context.js +391 -0
- package/src/dag/core/execution-scheduler.js +350 -0
- package/src/dag/core/topology-validation.js +415 -0
- package/src/dag/dag-engine.js +26 -424
- package/src/dev/README.md +126 -0
- package/src/dev/dev-server.js +356 -0
- package/src/dev/examples/hot-reload-usage.js +355 -0
- package/src/dev/hot-reload.js +807 -0
- package/src/enterprise/sso-integration.js +67 -25
- package/src/index.js +19 -0
- package/src/observability/event-logger.js +62 -2
- package/src/plugins/optimized-openai-embedder.js +169 -0
- package/src/security/jwt-config.js +431 -0
- package/src/security/jwt-validator.js +701 -0
- package/src/utils/api-client-pool-integration.js +436 -0
- package/src/utils/batch-processor.js +710 -0
- package/src/utils/connection-pool.js +605 -0
- package/src/utils/contract-validator.js +460 -0
- package/src/utils/error-formatter.js +603 -0
- package/src/utils/examples/error-formatter-usage.js +351 -0
- package/src/utils/input-sanitizer.js +967 -0
- package/src/utils/memory-monitor.js +800 -0
- package/src/utils/secure-logger-config.js +352 -0
- package/src/utils/secure-logger.js +576 -0
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Development Server with Hot Reload Support
|
|
5
|
+
*
|
|
6
|
+
* Provides a development server with integrated hot reloading
|
|
7
|
+
* for rapid plugin and configuration development.
|
|
8
|
+
*
|
|
9
|
+
* Features:
|
|
10
|
+
* - Automatic hot reloading of plugins and configuration
|
|
11
|
+
* - Live feedback on reload status
|
|
12
|
+
* - Error notifications
|
|
13
|
+
* - Statistics dashboard
|
|
14
|
+
* - WebSocket support for real-time updates (optional)
|
|
15
|
+
*
|
|
16
|
+
* @module dev/dev-server
|
|
17
|
+
* @since 2.4.0
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const { EventEmitter } = require('events');
|
|
21
|
+
const { createHotReloadManager } = require('./hot-reload');
|
|
22
|
+
const logger = require('../utils/logger');
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Development Server
|
|
26
|
+
*
|
|
27
|
+
* Integrates hot reloading with a development workflow
|
|
28
|
+
*/
|
|
29
|
+
class DevServer extends EventEmitter {
|
|
30
|
+
constructor(options = {}) {
|
|
31
|
+
super();
|
|
32
|
+
|
|
33
|
+
this.options = {
|
|
34
|
+
port: options.port || 3000,
|
|
35
|
+
host: options.host || 'localhost',
|
|
36
|
+
watchPaths: options.watchPaths || ['./src/plugins', './src/mocks'],
|
|
37
|
+
configPath: options.configPath || '.ragrc.json',
|
|
38
|
+
verbose: options.verbose !== false,
|
|
39
|
+
autoReload: options.autoReload !== false,
|
|
40
|
+
notifyOnReload: options.notifyOnReload !== false,
|
|
41
|
+
pluginRegistry: options.pluginRegistry || null,
|
|
42
|
+
pipeline: options.pipeline || null,
|
|
43
|
+
...options,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Create hot reload manager
|
|
47
|
+
this.hotReload = createHotReloadManager({
|
|
48
|
+
enabled: this.options.autoReload,
|
|
49
|
+
watchPaths: this.options.watchPaths,
|
|
50
|
+
configPath: this.options.configPath,
|
|
51
|
+
verbose: this.options.verbose,
|
|
52
|
+
pluginRegistry: this.options.pluginRegistry,
|
|
53
|
+
preserveState: true,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
this.isRunning = false;
|
|
57
|
+
this.startTime = null;
|
|
58
|
+
|
|
59
|
+
// Setup hot reload event handlers
|
|
60
|
+
this._setupHotReloadHandlers();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Setup hot reload event handlers
|
|
65
|
+
*
|
|
66
|
+
* @private
|
|
67
|
+
*/
|
|
68
|
+
_setupHotReloadHandlers() {
|
|
69
|
+
// Plugin reloaded
|
|
70
|
+
this.hotReload.on('plugin:reloaded', ({ path, duration }) => {
|
|
71
|
+
this._log(`✓ Plugin reloaded: ${path} (${duration}ms)`, 'success');
|
|
72
|
+
this.emit('plugin:reloaded', { path, duration });
|
|
73
|
+
|
|
74
|
+
if (this.options.notifyOnReload) {
|
|
75
|
+
this._notify(`Plugin reloaded: ${path}`, 'success');
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Plugin reload failed
|
|
80
|
+
this.hotReload.on('plugin:reload-failed', ({ path, error }) => {
|
|
81
|
+
this._log(`✗ Plugin reload failed: ${path} - ${error}`, 'error');
|
|
82
|
+
this.emit('plugin:reload-failed', { path, error });
|
|
83
|
+
|
|
84
|
+
if (this.options.notifyOnReload) {
|
|
85
|
+
this._notify(`Plugin reload failed: ${path}`, 'error');
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Config reloaded
|
|
90
|
+
this.hotReload.on('config:reloaded', ({ path, duration }) => {
|
|
91
|
+
this._log(`✓ Configuration reloaded: ${path} (${duration}ms)`, 'success');
|
|
92
|
+
this.emit('config:reloaded', { path, duration });
|
|
93
|
+
|
|
94
|
+
if (this.options.notifyOnReload) {
|
|
95
|
+
this._notify(`Configuration reloaded`, 'success');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Reinitialize pipeline if provided
|
|
99
|
+
if (this.options.pipeline && this.options.pipeline.reinitialize) {
|
|
100
|
+
this.options.pipeline.reinitialize();
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Config reload failed
|
|
105
|
+
this.hotReload.on('config:reload-failed', ({ path, error }) => {
|
|
106
|
+
this._log(`✗ Configuration reload failed: ${path} - ${error}`, 'error');
|
|
107
|
+
this.emit('config:reload-failed', { path, error });
|
|
108
|
+
|
|
109
|
+
if (this.options.notifyOnReload) {
|
|
110
|
+
this._notify(`Configuration reload failed`, 'error');
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Plugin added
|
|
115
|
+
this.hotReload.on('plugin:added', ({ path }) => {
|
|
116
|
+
this._log(`+ New plugin detected: ${path}`, 'info');
|
|
117
|
+
this.emit('plugin:added', { path });
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// Plugin removed
|
|
121
|
+
this.hotReload.on('plugin:removed', ({ path }) => {
|
|
122
|
+
this._log(`- Plugin removed: ${path}`, 'info');
|
|
123
|
+
this.emit('plugin:removed', { path });
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Error
|
|
127
|
+
this.hotReload.on('error', ({ message, error }) => {
|
|
128
|
+
this._log(`ERROR: ${message} - ${error}`, 'error');
|
|
129
|
+
this.emit('error', { message, error });
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Start the development server
|
|
135
|
+
*
|
|
136
|
+
* @returns {Promise<void>}
|
|
137
|
+
*/
|
|
138
|
+
async start() {
|
|
139
|
+
if (this.isRunning) {
|
|
140
|
+
this._log('Development server is already running', 'warn');
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
this._log('Starting development server...', 'info');
|
|
145
|
+
this.startTime = Date.now();
|
|
146
|
+
|
|
147
|
+
// Start hot reload
|
|
148
|
+
await this.hotReload.start();
|
|
149
|
+
|
|
150
|
+
this.isRunning = true;
|
|
151
|
+
|
|
152
|
+
this._log(
|
|
153
|
+
`Development server started on ${this.options.host}:${this.options.port}`,
|
|
154
|
+
'success',
|
|
155
|
+
);
|
|
156
|
+
this._log(`Watching: ${this.options.watchPaths.join(', ')}`, 'info');
|
|
157
|
+
this._log(
|
|
158
|
+
'Hot reload enabled - changes will be applied automatically',
|
|
159
|
+
'info',
|
|
160
|
+
);
|
|
161
|
+
this._log('Press Ctrl+C to stop', 'info');
|
|
162
|
+
|
|
163
|
+
this.emit('started');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Stop the development server
|
|
168
|
+
*
|
|
169
|
+
* @returns {Promise<void>}
|
|
170
|
+
*/
|
|
171
|
+
async stop() {
|
|
172
|
+
if (!this.isRunning) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
this._log('Stopping development server...', 'info');
|
|
177
|
+
|
|
178
|
+
// Stop hot reload
|
|
179
|
+
await this.hotReload.stop();
|
|
180
|
+
|
|
181
|
+
this.isRunning = false;
|
|
182
|
+
|
|
183
|
+
const uptime = this.startTime ? Date.now() - this.startTime : 0;
|
|
184
|
+
this._log(
|
|
185
|
+
`Development server stopped (uptime: ${this._formatDuration(uptime)})`,
|
|
186
|
+
'info',
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
this.emit('stopped');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Get server status
|
|
194
|
+
*
|
|
195
|
+
* @returns {object} Server status
|
|
196
|
+
*/
|
|
197
|
+
getStatus() {
|
|
198
|
+
const stats = this.hotReload.getStats();
|
|
199
|
+
const uptime = this.startTime ? Date.now() - this.startTime : 0;
|
|
200
|
+
|
|
201
|
+
return {
|
|
202
|
+
isRunning: this.isRunning,
|
|
203
|
+
uptime,
|
|
204
|
+
host: this.options.host,
|
|
205
|
+
port: this.options.port,
|
|
206
|
+
watchPaths: this.options.watchPaths,
|
|
207
|
+
configPath: this.options.configPath,
|
|
208
|
+
hotReload: {
|
|
209
|
+
enabled: this.options.autoReload,
|
|
210
|
+
stats,
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Get statistics dashboard
|
|
217
|
+
*
|
|
218
|
+
* @returns {string} Formatted statistics
|
|
219
|
+
*/
|
|
220
|
+
getStatistics() {
|
|
221
|
+
const stats = this.hotReload.getStats();
|
|
222
|
+
const uptime = this.startTime ? Date.now() - this.startTime : 0;
|
|
223
|
+
|
|
224
|
+
return `
|
|
225
|
+
╔════════════════════════════════════════════════════════════════╗
|
|
226
|
+
║ Development Server Statistics ║
|
|
227
|
+
╠════════════════════════════════════════════════════════════════╣
|
|
228
|
+
║ Status: ${this.isRunning ? 'Running' : 'Stopped'} ║
|
|
229
|
+
║ Uptime: ${this._formatDuration(uptime).padEnd(39)}║
|
|
230
|
+
║ ║
|
|
231
|
+
║ Hot Reload: ║
|
|
232
|
+
║ Total Reloads: ${String(stats.totalReloads).padEnd(39)}║
|
|
233
|
+
║ Successful: ${String(stats.successfulReloads).padEnd(39)}║
|
|
234
|
+
║ Failed: ${String(stats.failedReloads).padEnd(39)}║
|
|
235
|
+
║ Plugin Reloads: ${String(stats.pluginReloads).padEnd(39)}║
|
|
236
|
+
║ Config Reloads: ${String(stats.configReloads).padEnd(39)}║
|
|
237
|
+
║ Avg Reload Time: ${String(Math.round(stats.averageReloadTime) + 'ms').padEnd(39)}║
|
|
238
|
+
║ ║
|
|
239
|
+
║ Watching: ║
|
|
240
|
+
${this.options.watchPaths.map((p) => `║ - ${p.padEnd(56)}║`).join('\n')}
|
|
241
|
+
╚════════════════════════════════════════════════════════════════╝
|
|
242
|
+
`.trim();
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Manually trigger a reload
|
|
247
|
+
*
|
|
248
|
+
* @param {string} filePath - File path to reload
|
|
249
|
+
* @param {string} type - Type ('plugin' or 'config')
|
|
250
|
+
* @returns {Promise<void>}
|
|
251
|
+
*/
|
|
252
|
+
async triggerReload(filePath, type = 'plugin') {
|
|
253
|
+
this._log(`Manually triggering reload: ${filePath}`, 'info');
|
|
254
|
+
await this.hotReload.triggerReload(filePath, type);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Register a lifecycle hook
|
|
259
|
+
*
|
|
260
|
+
* @param {string} hookName - Hook name
|
|
261
|
+
* @param {Function} callback - Hook callback
|
|
262
|
+
*/
|
|
263
|
+
registerHook(hookName, callback) {
|
|
264
|
+
this.hotReload.registerHook(hookName, callback);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Unregister a lifecycle hook
|
|
269
|
+
*
|
|
270
|
+
* @param {string} hookName - Hook name
|
|
271
|
+
* @param {Function} callback - Hook callback
|
|
272
|
+
*/
|
|
273
|
+
unregisterHook(hookName, callback) {
|
|
274
|
+
this.hotReload.unregisterHook(hookName, callback);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Log message
|
|
279
|
+
*
|
|
280
|
+
* @private
|
|
281
|
+
* @param {string} message - Log message
|
|
282
|
+
* @param {string} level - Log level
|
|
283
|
+
*/
|
|
284
|
+
_log(message, level = 'info') {
|
|
285
|
+
if (!this.options.verbose && level === 'info') {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const prefix = '[DevServer]';
|
|
290
|
+
|
|
291
|
+
switch (level) {
|
|
292
|
+
case 'success':
|
|
293
|
+
console.log(`${prefix} ✓ ${message}`);
|
|
294
|
+
break;
|
|
295
|
+
case 'error':
|
|
296
|
+
console.error(`${prefix} ✗ ${message}`);
|
|
297
|
+
break;
|
|
298
|
+
case 'warn':
|
|
299
|
+
console.warn(`${prefix} ⚠ ${message}`);
|
|
300
|
+
break;
|
|
301
|
+
case 'info':
|
|
302
|
+
default:
|
|
303
|
+
console.log(`${prefix} ${message}`);
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Send notification
|
|
310
|
+
*
|
|
311
|
+
* @private
|
|
312
|
+
* @param {string} message - Notification message
|
|
313
|
+
* @param {string} type - Notification type
|
|
314
|
+
*/
|
|
315
|
+
_notify(message, type = 'info') {
|
|
316
|
+
// In a real implementation, this could send desktop notifications
|
|
317
|
+
// or WebSocket messages to connected clients
|
|
318
|
+
this.emit('notification', { message, type, timestamp: new Date() });
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Format duration
|
|
323
|
+
*
|
|
324
|
+
* @private
|
|
325
|
+
* @param {number} ms - Duration in milliseconds
|
|
326
|
+
* @returns {string} Formatted duration
|
|
327
|
+
*/
|
|
328
|
+
_formatDuration(ms) {
|
|
329
|
+
const seconds = Math.floor(ms / 1000);
|
|
330
|
+
const minutes = Math.floor(seconds / 60);
|
|
331
|
+
const hours = Math.floor(minutes / 60);
|
|
332
|
+
|
|
333
|
+
if (hours > 0) {
|
|
334
|
+
return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
|
|
335
|
+
} else if (minutes > 0) {
|
|
336
|
+
return `${minutes}m ${seconds % 60}s`;
|
|
337
|
+
} else {
|
|
338
|
+
return `${seconds}s`;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Create development server
|
|
345
|
+
*
|
|
346
|
+
* @param {object} options - Server options
|
|
347
|
+
* @returns {DevServer} Development server instance
|
|
348
|
+
*/
|
|
349
|
+
function createDevServer(options = {}) {
|
|
350
|
+
return new DevServer(options);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
module.exports = {
|
|
354
|
+
DevServer,
|
|
355
|
+
createDevServer,
|
|
356
|
+
};
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Hot Reload Usage Examples
|
|
5
|
+
*
|
|
6
|
+
* This file demonstrates various ways to use the hot reload functionality
|
|
7
|
+
* in development environments.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { createHotReloadManager } = require('../hot-reload');
|
|
11
|
+
const { createDevServer } = require('../dev-server');
|
|
12
|
+
const { createRagPipeline } = require('../../core/create-pipeline');
|
|
13
|
+
const pluginRegistry = require('../../core/plugin-registry');
|
|
14
|
+
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// Example 1: Basic Hot Reload Setup
|
|
17
|
+
// ============================================================================
|
|
18
|
+
|
|
19
|
+
function basicHotReloadExample() {
|
|
20
|
+
console.log('\n=== Example 1: Basic Hot Reload ===\n');
|
|
21
|
+
|
|
22
|
+
// Create hot reload manager
|
|
23
|
+
const hotReload = createHotReloadManager({
|
|
24
|
+
enabled: true,
|
|
25
|
+
watchPaths: ['./src/plugins', './src/mocks'],
|
|
26
|
+
configPath: '.ragrc.json',
|
|
27
|
+
verbose: true,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Listen to events
|
|
31
|
+
hotReload.on('plugin:reloaded', ({ path, duration }) => {
|
|
32
|
+
console.log(`Plugin reloaded: ${path} in ${duration}ms`);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
hotReload.on('config:reloaded', ({ config }) => {
|
|
36
|
+
console.log('Configuration reloaded:', config.metadata?.name);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Start watching
|
|
40
|
+
hotReload.start().then(() => {
|
|
41
|
+
console.log('Hot reload started');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// To stop:
|
|
45
|
+
// hotReload.stop();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ============================================================================
|
|
49
|
+
// Example 2: Hot Reload with Plugin Registry Integration
|
|
50
|
+
// ============================================================================
|
|
51
|
+
|
|
52
|
+
async function hotReloadWithRegistryExample() {
|
|
53
|
+
console.log('\n=== Example 2: Hot Reload with Plugin Registry ===\n');
|
|
54
|
+
|
|
55
|
+
// Create hot reload manager with plugin registry
|
|
56
|
+
const hotReload = createHotReloadManager({
|
|
57
|
+
enabled: true,
|
|
58
|
+
watchPaths: ['./src/plugins'],
|
|
59
|
+
pluginRegistry: pluginRegistry,
|
|
60
|
+
verbose: true,
|
|
61
|
+
preserveState: true, // Preserve plugin state during reloads
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Register hooks for advanced control
|
|
65
|
+
hotReload.registerHook('beforeReload', async (data) => {
|
|
66
|
+
console.log(`About to reload ${data.type}: ${data.path}`);
|
|
67
|
+
// Perform any cleanup or preparation
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
hotReload.registerHook('afterReload', async (data) => {
|
|
71
|
+
console.log(`Reload completed for ${data.type}: ${data.path}`);
|
|
72
|
+
// Re-register with plugin registry, update references, etc.
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
hotReload.registerHook('onError', async ({ message, error }) => {
|
|
76
|
+
console.error(`Reload error: ${message}`, error);
|
|
77
|
+
// Send notification, log to service, etc.
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
await hotReload.start();
|
|
81
|
+
|
|
82
|
+
// Get statistics
|
|
83
|
+
setInterval(() => {
|
|
84
|
+
const stats = hotReload.getStats();
|
|
85
|
+
console.log('Reload Stats:', {
|
|
86
|
+
total: stats.totalReloads,
|
|
87
|
+
successful: stats.successfulReloads,
|
|
88
|
+
failed: stats.failedReloads,
|
|
89
|
+
avgTime: Math.round(stats.averageReloadTime) + 'ms',
|
|
90
|
+
});
|
|
91
|
+
}, 60000); // Every minute
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ============================================================================
|
|
95
|
+
// Example 3: Development Server with Hot Reload
|
|
96
|
+
// ============================================================================
|
|
97
|
+
|
|
98
|
+
async function devServerExample() {
|
|
99
|
+
console.log('\n=== Example 3: Development Server ===\n');
|
|
100
|
+
|
|
101
|
+
// Create development server with integrated hot reload
|
|
102
|
+
const devServer = createDevServer({
|
|
103
|
+
port: 3000,
|
|
104
|
+
host: 'localhost',
|
|
105
|
+
watchPaths: ['./src/plugins', './src/mocks'],
|
|
106
|
+
configPath: '.ragrc.json',
|
|
107
|
+
verbose: true,
|
|
108
|
+
autoReload: true,
|
|
109
|
+
notifyOnReload: true,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Listen to server events
|
|
113
|
+
devServer.on('started', () => {
|
|
114
|
+
console.log('Development server started');
|
|
115
|
+
console.log(devServer.getStatistics());
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
devServer.on('plugin:reloaded', ({ path, duration }) => {
|
|
119
|
+
console.log(`✓ Plugin reloaded: ${path} (${duration}ms)`);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
devServer.on('config:reloaded', ({ path, duration }) => {
|
|
123
|
+
console.log(`✓ Config reloaded: ${path} (${duration}ms)`);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
devServer.on('notification', ({ message, type }) => {
|
|
127
|
+
console.log(`[${type.toUpperCase()}] ${message}`);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// Start the server
|
|
131
|
+
await devServer.start();
|
|
132
|
+
|
|
133
|
+
// Display statistics periodically
|
|
134
|
+
setInterval(() => {
|
|
135
|
+
console.log(devServer.getStatistics());
|
|
136
|
+
}, 300000); // Every 5 minutes
|
|
137
|
+
|
|
138
|
+
// Handle graceful shutdown
|
|
139
|
+
process.on('SIGINT', async () => {
|
|
140
|
+
console.log('\nShutting down...');
|
|
141
|
+
await devServer.stop();
|
|
142
|
+
process.exit(0);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// ============================================================================
|
|
147
|
+
// Example 4: Hot Reload with RAG Pipeline
|
|
148
|
+
// ============================================================================
|
|
149
|
+
|
|
150
|
+
async function hotReloadWithPipelineExample() {
|
|
151
|
+
console.log('\n=== Example 4: Hot Reload with Pipeline ===\n');
|
|
152
|
+
|
|
153
|
+
// Create pipeline
|
|
154
|
+
const pipeline = await createRagPipeline({
|
|
155
|
+
configPath: '.ragrc.json',
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Create dev server with pipeline integration
|
|
159
|
+
const devServer = createDevServer({
|
|
160
|
+
watchPaths: ['./src/plugins', './src/mocks'],
|
|
161
|
+
configPath: '.ragrc.json',
|
|
162
|
+
verbose: true,
|
|
163
|
+
pluginRegistry: pluginRegistry,
|
|
164
|
+
pipeline: pipeline,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// When config changes, pipeline will be reinitialized automatically
|
|
168
|
+
devServer.on('config:reloaded', async () => {
|
|
169
|
+
console.log('Pipeline configuration updated');
|
|
170
|
+
// Pipeline is automatically reinitialized by dev server
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// When plugins change, they're hot-reloaded
|
|
174
|
+
devServer.on('plugin:reloaded', async ({ path }) => {
|
|
175
|
+
console.log(`Plugin ${path} updated and reloaded`);
|
|
176
|
+
// Plugin is automatically updated in registry
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
await devServer.start();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ============================================================================
|
|
183
|
+
// Example 5: Custom State Preservation
|
|
184
|
+
// ============================================================================
|
|
185
|
+
|
|
186
|
+
async function customStatePreservationExample() {
|
|
187
|
+
console.log('\n=== Example 5: Custom State Preservation ===\n');
|
|
188
|
+
|
|
189
|
+
const hotReload = createHotReloadManager({
|
|
190
|
+
enabled: true,
|
|
191
|
+
watchPaths: ['./src/plugins'],
|
|
192
|
+
preserveState: true,
|
|
193
|
+
verbose: true,
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Hook into state preservation
|
|
197
|
+
hotReload.registerHook('onStatePreserve', async ({ path, state }) => {
|
|
198
|
+
console.log(`Preserving state for ${path}:`, state);
|
|
199
|
+
// You can save state to external storage here
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
hotReload.registerHook('onStateRestore', async ({ plugin, state }) => {
|
|
203
|
+
console.log('Restoring state:', state);
|
|
204
|
+
// You can restore state from external storage here
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
await hotReload.start();
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// ============================================================================
|
|
211
|
+
// Example 6: Manual Reload Triggering
|
|
212
|
+
// ============================================================================
|
|
213
|
+
|
|
214
|
+
async function manualReloadExample() {
|
|
215
|
+
console.log('\n=== Example 6: Manual Reload ===\n');
|
|
216
|
+
|
|
217
|
+
const devServer = createDevServer({
|
|
218
|
+
watchPaths: ['./src/plugins'],
|
|
219
|
+
autoReload: false, // Disable automatic reloading
|
|
220
|
+
verbose: true,
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
await devServer.start();
|
|
224
|
+
|
|
225
|
+
// Manually trigger reloads
|
|
226
|
+
await devServer.triggerReload('./src/plugins/my-plugin.js', 'plugin');
|
|
227
|
+
await devServer.triggerReload('.ragrc.json', 'config');
|
|
228
|
+
|
|
229
|
+
console.log('Manual reloads completed');
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// ============================================================================
|
|
233
|
+
// Example 7: Configuration Validation
|
|
234
|
+
// ============================================================================
|
|
235
|
+
|
|
236
|
+
async function configValidationExample() {
|
|
237
|
+
console.log('\n=== Example 7: Config Validation ===\n');
|
|
238
|
+
|
|
239
|
+
const hotReload = createHotReloadManager({
|
|
240
|
+
enabled: true,
|
|
241
|
+
configPath: '.ragrc.json',
|
|
242
|
+
verbose: true,
|
|
243
|
+
// Custom config validator
|
|
244
|
+
configValidator: (config) => {
|
|
245
|
+
const errors = [];
|
|
246
|
+
|
|
247
|
+
// Validate required fields
|
|
248
|
+
if (!config.metadata || !config.metadata.name) {
|
|
249
|
+
errors.push({ message: 'metadata.name is required' });
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (!config.pipeline || !config.pipeline.stages) {
|
|
253
|
+
errors.push({ message: 'pipeline.stages is required' });
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return {
|
|
257
|
+
valid: errors.length === 0,
|
|
258
|
+
errors,
|
|
259
|
+
};
|
|
260
|
+
},
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
hotReload.on('config:reload-failed', ({ error }) => {
|
|
264
|
+
console.error('Configuration validation failed:', error);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
await hotReload.start();
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// ============================================================================
|
|
271
|
+
// Example 8: Development Workflow Integration
|
|
272
|
+
// ============================================================================
|
|
273
|
+
|
|
274
|
+
async function developmentWorkflowExample() {
|
|
275
|
+
console.log('\n=== Example 8: Complete Development Workflow ===\n');
|
|
276
|
+
|
|
277
|
+
// Create a complete development environment
|
|
278
|
+
const devServer = createDevServer({
|
|
279
|
+
port: 3000,
|
|
280
|
+
host: 'localhost',
|
|
281
|
+
watchPaths: ['./src/plugins', './src/mocks', './src/config'],
|
|
282
|
+
configPath: '.ragrc.json',
|
|
283
|
+
verbose: true,
|
|
284
|
+
autoReload: true,
|
|
285
|
+
notifyOnReload: true,
|
|
286
|
+
pluginRegistry: pluginRegistry,
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// Add custom hooks
|
|
290
|
+
devServer.registerHook('beforeReload', async (data) => {
|
|
291
|
+
console.log(`[BEFORE] Reloading ${data.type}: ${data.path}`);
|
|
292
|
+
// Run pre-reload tasks (tests, linting, etc.)
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
devServer.registerHook('afterReload', async (data) => {
|
|
296
|
+
console.log(`[AFTER] Reloaded ${data.type}: ${data.path}`);
|
|
297
|
+
// Run post-reload tasks (smoke tests, notifications, etc.)
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// Start server
|
|
301
|
+
await devServer.start();
|
|
302
|
+
|
|
303
|
+
// Log status every 5 minutes
|
|
304
|
+
setInterval(() => {
|
|
305
|
+
const status = devServer.getStatus();
|
|
306
|
+
console.log('\n=== Server Status ===');
|
|
307
|
+
console.log(`Uptime: ${Math.floor(status.uptime / 1000)}s`);
|
|
308
|
+
console.log(`Total Reloads: ${status.hotReload.stats.totalReloads}`);
|
|
309
|
+
console.log(
|
|
310
|
+
`Success Rate: ${
|
|
311
|
+
status.hotReload.stats.totalReloads > 0
|
|
312
|
+
? Math.round(
|
|
313
|
+
(status.hotReload.stats.successfulReloads /
|
|
314
|
+
status.hotReload.stats.totalReloads) *
|
|
315
|
+
100,
|
|
316
|
+
) + '%'
|
|
317
|
+
: 'N/A'
|
|
318
|
+
}`,
|
|
319
|
+
);
|
|
320
|
+
}, 300000);
|
|
321
|
+
|
|
322
|
+
// Handle shutdown
|
|
323
|
+
process.on('SIGINT', async () => {
|
|
324
|
+
console.log('\n\nShutting down development server...');
|
|
325
|
+
console.log(devServer.getStatistics());
|
|
326
|
+
await devServer.stop();
|
|
327
|
+
process.exit(0);
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// ============================================================================
|
|
332
|
+
// Run Examples
|
|
333
|
+
// ============================================================================
|
|
334
|
+
|
|
335
|
+
// Uncomment the example you want to run:
|
|
336
|
+
|
|
337
|
+
// basicHotReloadExample();
|
|
338
|
+
// hotReloadWithRegistryExample();
|
|
339
|
+
// devServerExample();
|
|
340
|
+
// hotReloadWithPipelineExample();
|
|
341
|
+
// customStatePreservationExample();
|
|
342
|
+
// manualReloadExample();
|
|
343
|
+
// configValidationExample();
|
|
344
|
+
// developmentWorkflowExample();
|
|
345
|
+
|
|
346
|
+
module.exports = {
|
|
347
|
+
basicHotReloadExample,
|
|
348
|
+
hotReloadWithRegistryExample,
|
|
349
|
+
devServerExample,
|
|
350
|
+
hotReloadWithPipelineExample,
|
|
351
|
+
customStatePreservationExample,
|
|
352
|
+
manualReloadExample,
|
|
353
|
+
configValidationExample,
|
|
354
|
+
developmentWorkflowExample,
|
|
355
|
+
};
|