@zincapp/zn-vault-agent 1.6.13 → 1.6.14
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 +76 -0
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +15 -0
- package/dist/commands/start.js.map +1 -1
- package/dist/lib/config.d.ts +3 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/health.d.ts +14 -3
- package/dist/lib/health.d.ts.map +1 -1
- package/dist/lib/health.js +115 -94
- package/dist/lib/health.js.map +1 -1
- package/dist/lib/websocket.d.ts.map +1 -1
- package/dist/lib/websocket.js +109 -2
- package/dist/lib/websocket.js.map +1 -1
- package/dist/plugins/context.d.ts +17 -0
- package/dist/plugins/context.d.ts.map +1 -0
- package/dist/plugins/context.js +175 -0
- package/dist/plugins/context.js.map +1 -0
- package/dist/plugins/index.d.ts +5 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +9 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/loader.d.ts +116 -0
- package/dist/plugins/loader.d.ts.map +1 -0
- package/dist/plugins/loader.js +399 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/plugins/storage.d.ts +18 -0
- package/dist/plugins/storage.d.ts.map +1 -0
- package/dist/plugins/storage.js +166 -0
- package/dist/plugins/storage.js.map +1 -0
- package/dist/plugins/types.d.ts +341 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +12 -0
- package/dist/plugins/types.js.map +1 -0
- package/package.json +12 -1
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
// Path: src/plugins/loader.ts
|
|
2
|
+
// Plugin discovery, loading, and lifecycle management
|
|
3
|
+
import { EventEmitter } from 'node:events';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import { createLogger } from '../lib/logger.js';
|
|
7
|
+
import { createPluginContext } from './context.js';
|
|
8
|
+
const log = createLogger({ module: 'plugin-loader' });
|
|
9
|
+
/**
|
|
10
|
+
* Plugin event handler method names mapping
|
|
11
|
+
*/
|
|
12
|
+
const EVENT_HANDLERS = {
|
|
13
|
+
certificateDeployed: 'onCertificateDeployed',
|
|
14
|
+
secretDeployed: 'onSecretDeployed',
|
|
15
|
+
keyRotated: 'onKeyRotated',
|
|
16
|
+
childProcess: 'onChildProcessEvent',
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Manages plugin discovery, loading, and lifecycle
|
|
20
|
+
*/
|
|
21
|
+
export class PluginLoader extends EventEmitter {
|
|
22
|
+
plugins = new Map();
|
|
23
|
+
agentInternals;
|
|
24
|
+
options;
|
|
25
|
+
isStarted = false;
|
|
26
|
+
constructor(agentInternals, options = {}) {
|
|
27
|
+
super();
|
|
28
|
+
this.agentInternals = agentInternals;
|
|
29
|
+
this.options = options;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Load all plugins from config and auto-discovered locations
|
|
33
|
+
*/
|
|
34
|
+
async loadPlugins(config) {
|
|
35
|
+
log.info('Loading plugins');
|
|
36
|
+
// Load plugins from config
|
|
37
|
+
const pluginConfigs = config.plugins || [];
|
|
38
|
+
for (const pluginConfig of pluginConfigs) {
|
|
39
|
+
// Skip disabled plugins
|
|
40
|
+
if (pluginConfig.enabled === false) {
|
|
41
|
+
log.debug({ package: pluginConfig.package, path: pluginConfig.path }, 'Plugin disabled, skipping');
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
await this.loadPlugin(pluginConfig);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
log.error({ err, config: pluginConfig }, 'Failed to load plugin');
|
|
49
|
+
// Continue loading other plugins
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Discover local plugins if plugin directory exists
|
|
53
|
+
if (this.options.pluginDir) {
|
|
54
|
+
await this.loadLocalPlugins(this.options.pluginDir);
|
|
55
|
+
}
|
|
56
|
+
log.info({ count: this.plugins.size }, 'Plugins loaded');
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Load a single plugin by config
|
|
60
|
+
*/
|
|
61
|
+
async loadPlugin(config) {
|
|
62
|
+
const { package: packageName, path: localPath, config: pluginOptions } = config;
|
|
63
|
+
if (!packageName && !localPath) {
|
|
64
|
+
throw new Error('Plugin config must specify package or path');
|
|
65
|
+
}
|
|
66
|
+
const identifier = packageName || localPath;
|
|
67
|
+
log.debug({ package: packageName, path: localPath }, 'Loading plugin');
|
|
68
|
+
try {
|
|
69
|
+
let module;
|
|
70
|
+
if (localPath) {
|
|
71
|
+
// Resolve local path relative to config dir or as absolute
|
|
72
|
+
const resolvedPath = path.isAbsolute(localPath)
|
|
73
|
+
? localPath
|
|
74
|
+
: path.resolve(process.cwd(), localPath);
|
|
75
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
76
|
+
throw new Error(`Plugin file not found: ${resolvedPath}`);
|
|
77
|
+
}
|
|
78
|
+
module = await import(resolvedPath);
|
|
79
|
+
}
|
|
80
|
+
else if (packageName) {
|
|
81
|
+
// Import npm package
|
|
82
|
+
module = await import(packageName);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
throw new Error('Plugin config must specify package or path');
|
|
86
|
+
}
|
|
87
|
+
// Support both direct export and factory function
|
|
88
|
+
let plugin;
|
|
89
|
+
if (typeof module.default === 'function') {
|
|
90
|
+
// Factory function - pass plugin options
|
|
91
|
+
plugin = module.default(pluginOptions || {});
|
|
92
|
+
}
|
|
93
|
+
else if (module.default && typeof module.default === 'object') {
|
|
94
|
+
// Direct export
|
|
95
|
+
plugin = module.default;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
throw new Error(`Invalid plugin export from ${identifier}`);
|
|
99
|
+
}
|
|
100
|
+
// Validate plugin interface
|
|
101
|
+
this.validatePlugin(plugin);
|
|
102
|
+
// Check for duplicate names
|
|
103
|
+
if (this.plugins.has(plugin.name)) {
|
|
104
|
+
log.warn({ name: plugin.name }, 'Plugin with same name already loaded, skipping');
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
// Store loaded plugin
|
|
108
|
+
this.plugins.set(plugin.name, {
|
|
109
|
+
plugin,
|
|
110
|
+
config: pluginOptions,
|
|
111
|
+
status: 'loaded',
|
|
112
|
+
});
|
|
113
|
+
log.info({ name: plugin.name, version: plugin.version }, 'Plugin loaded');
|
|
114
|
+
return plugin;
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
118
|
+
log.error({ err: error, identifier }, 'Failed to load plugin');
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Load plugins from local directory
|
|
124
|
+
*/
|
|
125
|
+
async loadLocalPlugins(pluginDir) {
|
|
126
|
+
if (!fs.existsSync(pluginDir)) {
|
|
127
|
+
log.debug({ pluginDir }, 'Plugin directory does not exist');
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const entries = fs.readdirSync(pluginDir, { withFileTypes: true });
|
|
131
|
+
for (const entry of entries) {
|
|
132
|
+
if (!entry.isFile())
|
|
133
|
+
continue;
|
|
134
|
+
if (!entry.name.endsWith('.js') && !entry.name.endsWith('.mjs'))
|
|
135
|
+
continue;
|
|
136
|
+
const pluginPath = path.join(pluginDir, entry.name);
|
|
137
|
+
try {
|
|
138
|
+
await this.loadPlugin({ path: pluginPath });
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
log.warn({ err, path: pluginPath }, 'Failed to load local plugin');
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Validate plugin has required fields
|
|
147
|
+
*/
|
|
148
|
+
validatePlugin(plugin) {
|
|
149
|
+
if (!plugin || typeof plugin !== 'object') {
|
|
150
|
+
throw new Error('Plugin must be an object');
|
|
151
|
+
}
|
|
152
|
+
const p = plugin;
|
|
153
|
+
if (typeof p.name !== 'string' || !p.name) {
|
|
154
|
+
throw new Error('Plugin must have a name property');
|
|
155
|
+
}
|
|
156
|
+
if (typeof p.version !== 'string' || !p.version) {
|
|
157
|
+
throw new Error('Plugin must have a version property');
|
|
158
|
+
}
|
|
159
|
+
// Validate optional lifecycle methods are functions
|
|
160
|
+
const methods = ['onInit', 'onStart', 'onStop', 'routes', 'onCertificateDeployed',
|
|
161
|
+
'onSecretDeployed', 'onKeyRotated', 'onChildProcessEvent', 'healthCheck'];
|
|
162
|
+
for (const method of methods) {
|
|
163
|
+
if (p[method] !== undefined && typeof p[method] !== 'function') {
|
|
164
|
+
throw new Error(`Plugin ${p.name}: ${method} must be a function`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Initialize all loaded plugins
|
|
170
|
+
*/
|
|
171
|
+
async initializePlugins() {
|
|
172
|
+
log.debug('Initializing plugins');
|
|
173
|
+
for (const [name, loaded] of this.plugins) {
|
|
174
|
+
if (loaded.status !== 'loaded')
|
|
175
|
+
continue;
|
|
176
|
+
const ctx = createPluginContext(name, this.agentInternals, this);
|
|
177
|
+
if (loaded.plugin.onInit) {
|
|
178
|
+
try {
|
|
179
|
+
await loaded.plugin.onInit(ctx);
|
|
180
|
+
loaded.status = 'initialized';
|
|
181
|
+
log.debug({ name }, 'Plugin initialized');
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
185
|
+
log.error({ err: error, name }, 'Plugin initialization failed');
|
|
186
|
+
loaded.status = 'error';
|
|
187
|
+
loaded.error = error;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
// No init hook - mark as initialized
|
|
192
|
+
loaded.status = 'initialized';
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Start all initialized plugins
|
|
198
|
+
*/
|
|
199
|
+
async startPlugins() {
|
|
200
|
+
if (this.isStarted) {
|
|
201
|
+
log.warn('Plugins already started');
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
log.debug('Starting plugins');
|
|
205
|
+
for (const [name, loaded] of this.plugins) {
|
|
206
|
+
if (loaded.status !== 'initialized')
|
|
207
|
+
continue;
|
|
208
|
+
const ctx = createPluginContext(name, this.agentInternals, this);
|
|
209
|
+
if (loaded.plugin.onStart) {
|
|
210
|
+
try {
|
|
211
|
+
await loaded.plugin.onStart(ctx);
|
|
212
|
+
loaded.status = 'running';
|
|
213
|
+
log.debug({ name }, 'Plugin started');
|
|
214
|
+
}
|
|
215
|
+
catch (err) {
|
|
216
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
217
|
+
log.error({ err: error, name }, 'Plugin start failed');
|
|
218
|
+
loaded.status = 'error';
|
|
219
|
+
loaded.error = error;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
// No start hook - mark as running
|
|
224
|
+
loaded.status = 'running';
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
this.isStarted = true;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Stop all running plugins
|
|
231
|
+
*/
|
|
232
|
+
async stopPlugins() {
|
|
233
|
+
if (!this.isStarted) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
log.debug('Stopping plugins');
|
|
237
|
+
// Stop in reverse order
|
|
238
|
+
const plugins = Array.from(this.plugins.entries()).reverse();
|
|
239
|
+
for (const [name, loaded] of plugins) {
|
|
240
|
+
if (loaded.status !== 'running')
|
|
241
|
+
continue;
|
|
242
|
+
const ctx = createPluginContext(name, this.agentInternals, this);
|
|
243
|
+
if (loaded.plugin.onStop) {
|
|
244
|
+
try {
|
|
245
|
+
await loaded.plugin.onStop(ctx);
|
|
246
|
+
loaded.status = 'stopped';
|
|
247
|
+
log.debug({ name }, 'Plugin stopped');
|
|
248
|
+
}
|
|
249
|
+
catch (err) {
|
|
250
|
+
log.warn({ err, name }, 'Plugin stop error');
|
|
251
|
+
loaded.status = 'stopped';
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
loaded.status = 'stopped';
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
this.isStarted = false;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Register plugin routes on Fastify server
|
|
262
|
+
*/
|
|
263
|
+
async registerRoutes(fastify) {
|
|
264
|
+
for (const [name, loaded] of this.plugins) {
|
|
265
|
+
if (!loaded.plugin.routes)
|
|
266
|
+
continue;
|
|
267
|
+
const ctx = createPluginContext(name, this.agentInternals, this);
|
|
268
|
+
try {
|
|
269
|
+
// Register under /plugins/<name>/ prefix
|
|
270
|
+
await fastify.register(async (instance) => {
|
|
271
|
+
await loaded.plugin.routes(instance, ctx);
|
|
272
|
+
}, { prefix: `/plugins/${name}` });
|
|
273
|
+
log.debug({ name, prefix: `/plugins/${name}` }, 'Plugin routes registered');
|
|
274
|
+
}
|
|
275
|
+
catch (err) {
|
|
276
|
+
log.error({ err, name }, 'Failed to register plugin routes');
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Dispatch event to all plugins
|
|
282
|
+
*/
|
|
283
|
+
async dispatchEvent(eventType, event) {
|
|
284
|
+
const handlerName = EVENT_HANDLERS[eventType];
|
|
285
|
+
log.debug({ eventType, plugins: this.plugins.size }, 'Dispatching event to plugins');
|
|
286
|
+
for (const [name, loaded] of this.plugins) {
|
|
287
|
+
if (loaded.status !== 'running')
|
|
288
|
+
continue;
|
|
289
|
+
const handler = loaded.plugin[handlerName];
|
|
290
|
+
if (!handler)
|
|
291
|
+
continue;
|
|
292
|
+
const ctx = createPluginContext(name, this.agentInternals, this);
|
|
293
|
+
try {
|
|
294
|
+
await handler.call(loaded.plugin, event, ctx);
|
|
295
|
+
}
|
|
296
|
+
catch (err) {
|
|
297
|
+
log.error({ err, name, eventType }, 'Plugin event handler error');
|
|
298
|
+
// Don't fail other plugins
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Collect health status from all plugins
|
|
304
|
+
*/
|
|
305
|
+
async collectHealthStatus() {
|
|
306
|
+
const statuses = [];
|
|
307
|
+
for (const [name, loaded] of this.plugins) {
|
|
308
|
+
// Include status for errored plugins
|
|
309
|
+
if (loaded.status === 'error') {
|
|
310
|
+
statuses.push({
|
|
311
|
+
name,
|
|
312
|
+
status: 'unhealthy',
|
|
313
|
+
message: loaded.error?.message || 'Plugin failed to load',
|
|
314
|
+
});
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
if (loaded.status !== 'running' || !loaded.plugin.healthCheck)
|
|
318
|
+
continue;
|
|
319
|
+
const ctx = createPluginContext(name, this.agentInternals, this);
|
|
320
|
+
try {
|
|
321
|
+
const status = await loaded.plugin.healthCheck(ctx);
|
|
322
|
+
statuses.push(status);
|
|
323
|
+
}
|
|
324
|
+
catch (err) {
|
|
325
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
326
|
+
statuses.push({
|
|
327
|
+
name,
|
|
328
|
+
status: 'unhealthy',
|
|
329
|
+
message: `Health check failed: ${error.message}`,
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return statuses;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Get loaded plugins
|
|
337
|
+
*/
|
|
338
|
+
getPlugins() {
|
|
339
|
+
return Array.from(this.plugins.values()).map(l => l.plugin);
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Get plugin by name
|
|
343
|
+
*/
|
|
344
|
+
getPlugin(name) {
|
|
345
|
+
return this.plugins.get(name)?.plugin;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Get plugin status
|
|
349
|
+
*/
|
|
350
|
+
getPluginStatus(name) {
|
|
351
|
+
return this.plugins.get(name)?.status;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Get all plugin statuses
|
|
355
|
+
*/
|
|
356
|
+
getAllPluginStatuses() {
|
|
357
|
+
return Array.from(this.plugins.entries()).map(([name, loaded]) => ({
|
|
358
|
+
name,
|
|
359
|
+
status: loaded.status,
|
|
360
|
+
error: loaded.error?.message,
|
|
361
|
+
}));
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Check if any plugins are loaded
|
|
365
|
+
*/
|
|
366
|
+
hasPlugins() {
|
|
367
|
+
return this.plugins.size > 0;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Update agent internals (called when config changes)
|
|
371
|
+
*/
|
|
372
|
+
updateInternals(internals) {
|
|
373
|
+
this.agentInternals = { ...this.agentInternals, ...internals };
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Singleton plugin loader instance
|
|
378
|
+
*/
|
|
379
|
+
let pluginLoaderInstance = null;
|
|
380
|
+
/**
|
|
381
|
+
* Get or create the plugin loader instance
|
|
382
|
+
*/
|
|
383
|
+
export function getPluginLoader() {
|
|
384
|
+
return pluginLoaderInstance;
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Create and set the plugin loader instance
|
|
388
|
+
*/
|
|
389
|
+
export function createPluginLoader(agentInternals, options) {
|
|
390
|
+
pluginLoaderInstance = new PluginLoader(agentInternals, options);
|
|
391
|
+
return pluginLoaderInstance;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Clear the plugin loader instance (for testing)
|
|
395
|
+
*/
|
|
396
|
+
export function clearPluginLoader() {
|
|
397
|
+
pluginLoaderInstance = null;
|
|
398
|
+
}
|
|
399
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/plugins/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PluginStorage } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Create a PluginStorage instance for a specific plugin
|
|
4
|
+
*/
|
|
5
|
+
export declare function getPluginStorage(pluginName: string): PluginStorage;
|
|
6
|
+
/**
|
|
7
|
+
* Delete all storage for a plugin (for uninstall/cleanup)
|
|
8
|
+
*/
|
|
9
|
+
export declare function deletePluginStorage(pluginName: string): void;
|
|
10
|
+
/**
|
|
11
|
+
* List all plugins with storage
|
|
12
|
+
*/
|
|
13
|
+
export declare function listPluginsWithStorage(): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Clear storage cache (for testing)
|
|
16
|
+
*/
|
|
17
|
+
export declare function clearStorageCache(): void;
|
|
18
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/plugins/storage.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAqGhD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAiClE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAY5D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,EAAE,CAejD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// Path: src/plugins/storage.ts
|
|
2
|
+
// Persistent key-value storage for plugins
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { createLogger } from '../lib/logger.js';
|
|
6
|
+
const log = createLogger({ module: 'plugin-storage' });
|
|
7
|
+
/**
|
|
8
|
+
* Get storage directory for plugins
|
|
9
|
+
* Uses /etc/zn-vault-agent/plugins/ for system config or ~/.zn-vault-agent/plugins/ for user
|
|
10
|
+
*/
|
|
11
|
+
function getStorageDir() {
|
|
12
|
+
const customDir = process.env.ZNVAULT_AGENT_CONFIG_DIR;
|
|
13
|
+
if (customDir) {
|
|
14
|
+
return path.join(customDir, 'plugin-data');
|
|
15
|
+
}
|
|
16
|
+
// System config dir
|
|
17
|
+
const systemDir = '/etc/zn-vault-agent/plugin-data';
|
|
18
|
+
if (process.getuid?.() === 0 || fs.existsSync('/etc/zn-vault-agent')) {
|
|
19
|
+
return systemDir;
|
|
20
|
+
}
|
|
21
|
+
// User config dir
|
|
22
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || '/tmp';
|
|
23
|
+
return path.join(homeDir, '.zn-vault-agent', 'plugin-data');
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Storage file cache to avoid repeated disk reads
|
|
27
|
+
*/
|
|
28
|
+
const storageCache = new Map();
|
|
29
|
+
/**
|
|
30
|
+
* Get storage file path for a plugin
|
|
31
|
+
*/
|
|
32
|
+
function getStoragePath(pluginName) {
|
|
33
|
+
const storageDir = getStorageDir();
|
|
34
|
+
// Sanitize plugin name for filename
|
|
35
|
+
const safeName = pluginName.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
36
|
+
return path.join(storageDir, `${safeName}.json`);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Ensure storage directory exists
|
|
40
|
+
*/
|
|
41
|
+
function ensureStorageDir() {
|
|
42
|
+
const storageDir = getStorageDir();
|
|
43
|
+
if (!fs.existsSync(storageDir)) {
|
|
44
|
+
fs.mkdirSync(storageDir, { recursive: true, mode: 0o700 });
|
|
45
|
+
log.debug({ storageDir }, 'Created plugin storage directory');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Load storage data from disk
|
|
50
|
+
*/
|
|
51
|
+
function loadStorageData(pluginName) {
|
|
52
|
+
// Check cache first
|
|
53
|
+
if (storageCache.has(pluginName)) {
|
|
54
|
+
return storageCache.get(pluginName);
|
|
55
|
+
}
|
|
56
|
+
const storagePath = getStoragePath(pluginName);
|
|
57
|
+
if (!fs.existsSync(storagePath)) {
|
|
58
|
+
const empty = {};
|
|
59
|
+
storageCache.set(pluginName, empty);
|
|
60
|
+
return empty;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
const content = fs.readFileSync(storagePath, 'utf-8');
|
|
64
|
+
const data = JSON.parse(content);
|
|
65
|
+
storageCache.set(pluginName, data);
|
|
66
|
+
return data;
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
log.warn({ err, pluginName, path: storagePath }, 'Failed to load plugin storage');
|
|
70
|
+
const empty = {};
|
|
71
|
+
storageCache.set(pluginName, empty);
|
|
72
|
+
return empty;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Save storage data to disk
|
|
77
|
+
*/
|
|
78
|
+
function saveStorageData(pluginName, data) {
|
|
79
|
+
ensureStorageDir();
|
|
80
|
+
const storagePath = getStoragePath(pluginName);
|
|
81
|
+
try {
|
|
82
|
+
// Atomic write with temp file
|
|
83
|
+
const tempPath = `${storagePath}.tmp`;
|
|
84
|
+
fs.writeFileSync(tempPath, JSON.stringify(data, null, 2), { mode: 0o600 });
|
|
85
|
+
fs.renameSync(tempPath, storagePath);
|
|
86
|
+
storageCache.set(pluginName, data);
|
|
87
|
+
log.debug({ pluginName, path: storagePath }, 'Plugin storage saved');
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
log.error({ err, pluginName, path: storagePath }, 'Failed to save plugin storage');
|
|
91
|
+
throw err;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Create a PluginStorage instance for a specific plugin
|
|
96
|
+
*/
|
|
97
|
+
export function getPluginStorage(pluginName) {
|
|
98
|
+
return {
|
|
99
|
+
get(key) {
|
|
100
|
+
const data = loadStorageData(pluginName);
|
|
101
|
+
return data[key];
|
|
102
|
+
},
|
|
103
|
+
set(key, value) {
|
|
104
|
+
const data = loadStorageData(pluginName);
|
|
105
|
+
data[key] = value;
|
|
106
|
+
saveStorageData(pluginName, data);
|
|
107
|
+
},
|
|
108
|
+
delete(key) {
|
|
109
|
+
const data = loadStorageData(pluginName);
|
|
110
|
+
delete data[key];
|
|
111
|
+
saveStorageData(pluginName, data);
|
|
112
|
+
},
|
|
113
|
+
clear() {
|
|
114
|
+
saveStorageData(pluginName, {});
|
|
115
|
+
},
|
|
116
|
+
has(key) {
|
|
117
|
+
const data = loadStorageData(pluginName);
|
|
118
|
+
return key in data;
|
|
119
|
+
},
|
|
120
|
+
keys() {
|
|
121
|
+
const data = loadStorageData(pluginName);
|
|
122
|
+
return Object.keys(data);
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Delete all storage for a plugin (for uninstall/cleanup)
|
|
128
|
+
*/
|
|
129
|
+
export function deletePluginStorage(pluginName) {
|
|
130
|
+
const storagePath = getStoragePath(pluginName);
|
|
131
|
+
storageCache.delete(pluginName);
|
|
132
|
+
if (fs.existsSync(storagePath)) {
|
|
133
|
+
try {
|
|
134
|
+
fs.unlinkSync(storagePath);
|
|
135
|
+
log.debug({ pluginName, path: storagePath }, 'Plugin storage deleted');
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
log.warn({ err, pluginName, path: storagePath }, 'Failed to delete plugin storage');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* List all plugins with storage
|
|
144
|
+
*/
|
|
145
|
+
export function listPluginsWithStorage() {
|
|
146
|
+
const storageDir = getStorageDir();
|
|
147
|
+
if (!fs.existsSync(storageDir)) {
|
|
148
|
+
return [];
|
|
149
|
+
}
|
|
150
|
+
try {
|
|
151
|
+
const files = fs.readdirSync(storageDir);
|
|
152
|
+
return files
|
|
153
|
+
.filter(f => f.endsWith('.json'))
|
|
154
|
+
.map(f => f.replace(/\.json$/, ''));
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
return [];
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Clear storage cache (for testing)
|
|
162
|
+
*/
|
|
163
|
+
export function clearStorageCache() {
|
|
164
|
+
storageCache.clear();
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/plugins/storage.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,2CAA2C;AAE3C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGhD,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;AAEvD;;;GAGG;AACH,SAAS,aAAa;IACpB,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;IACvD,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IAC7C,CAAC;IAED,oBAAoB;IACpB,MAAM,SAAS,GAAG,iCAAiC,CAAC;IACpD,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,qBAAqB,CAAC,EAAE,CAAC;QACrE,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,kBAAkB;IAClB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,MAAM,CAAC;IACtE,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,iBAAiB,EAAE,aAAa,CAAC,CAAC;AAC9D,CAAC;AAED;;GAEG;AACH,MAAM,YAAY,GAAG,IAAI,GAAG,EAAmC,CAAC;AAEhE;;GAEG;AACH,SAAS,cAAc,CAAC,UAAkB;IACxC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,oCAAoC;IACpC,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;IAC5D,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,QAAQ,OAAO,CAAC,CAAC;AACnD,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB;IACvB,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,EAAE,kCAAkC,CAAC,CAAC;IAChE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,UAAkB;IACzC,oBAAoB;IACpB,IAAI,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QACjC,OAAO,YAAY,CAAC,GAAG,CAAC,UAAU,CAAE,CAAC;IACvC,CAAC;IAED,MAAM,WAAW,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAE/C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,MAAM,KAAK,GAA4B,EAAE,CAAC;QAC1C,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACpC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;QAC5D,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,+BAA+B,CAAC,CAAC;QAClF,MAAM,KAAK,GAA4B,EAAE,CAAC;QAC1C,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACpC,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,UAAkB,EAAE,IAA6B;IACxE,gBAAgB,EAAE,CAAC;IACnB,MAAM,WAAW,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAE/C,IAAI,CAAC;QACH,8BAA8B;QAC9B,MAAM,QAAQ,GAAG,GAAG,WAAW,MAAM,CAAC;QACtC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3E,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QACrC,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACnC,GAAG,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,sBAAsB,CAAC,CAAC;IACvE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,+BAA+B,CAAC,CAAC;QACnF,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAkB;IACjD,OAAO;QACL,GAAG,CAAI,GAAW;YAChB,MAAM,IAAI,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;YACzC,OAAO,IAAI,CAAC,GAAG,CAAkB,CAAC;QACpC,CAAC;QAED,GAAG,CAAI,GAAW,EAAE,KAAQ;YAC1B,MAAM,IAAI,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;YACzC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAgB,CAAC;YAC7B,eAAe,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACpC,CAAC;QAED,MAAM,CAAC,GAAW;YAChB,MAAM,IAAI,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;YACzC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;YACjB,eAAe,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACpC,CAAC;QAED,KAAK;YACH,eAAe,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAClC,CAAC;QAED,GAAG,CAAC,GAAW;YACb,MAAM,IAAI,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;YACzC,OAAO,GAAG,IAAI,IAAI,CAAC;QACrB,CAAC;QAED,IAAI;YACF,MAAM,IAAI,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;YACzC,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IACpD,MAAM,WAAW,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAC/C,YAAY,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAEhC,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;YAC3B,GAAG,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,wBAAwB,CAAC,CAAC;QACzE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,iCAAiC,CAAC,CAAC;QACtF,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB;IACpC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IAEnC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QACzC,OAAO,KAAK;aACT,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;aAChC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,YAAY,CAAC,KAAK,EAAE,CAAC;AACvB,CAAC"}
|