@friggframework/admin-scripts 2.0.0--canary.517.7e78259.0 → 2.0.0--canary.517.2239974.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/package.json +6 -6
- package/src/application/__tests__/admin-frigg-commands.test.js +81 -295
- package/src/application/__tests__/admin-script-base.test.js +0 -91
- package/src/application/__tests__/script-runner.test.js +0 -133
- package/src/application/__tests__/validate-script-input.test.js +196 -0
- package/src/application/admin-frigg-commands.js +15 -78
- package/src/application/admin-script-base.js +0 -20
- package/src/application/script-runner.js +1 -111
- package/src/application/validate-script-input.js +116 -0
- package/src/builtins/__tests__/integration-health-check.test.js +27 -25
- package/src/builtins/__tests__/oauth-token-refresh.test.js +17 -15
- package/src/builtins/integration-health-check.js +3 -3
- package/src/builtins/oauth-token-refresh.js +2 -2
- package/src/infrastructure/__tests__/admin-script-router.test.js +2 -2
- package/src/infrastructure/admin-script-router.js +28 -14
- package/src/infrastructure/script-executor-handler.js +18 -35
|
@@ -46,104 +46,13 @@ describe('AdminScriptBase', () => {
|
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
it('should have clean display object without redundant fields', () => {
|
|
49
|
-
// Default display should only have UI-specific fields
|
|
50
49
|
expect(AdminScriptBase.Definition.display).toBeDefined();
|
|
51
50
|
expect(AdminScriptBase.Definition.display.category).toBe('maintenance');
|
|
52
|
-
// Should NOT have redundant label/description
|
|
53
51
|
expect(AdminScriptBase.Definition.display.label).toBeUndefined();
|
|
54
52
|
expect(AdminScriptBase.Definition.display.description).toBeUndefined();
|
|
55
53
|
});
|
|
56
54
|
});
|
|
57
55
|
|
|
58
|
-
describe('Static methods', () => {
|
|
59
|
-
it('getName() should return the script name', () => {
|
|
60
|
-
class TestScript extends AdminScriptBase {
|
|
61
|
-
static Definition = {
|
|
62
|
-
name: 'my-script',
|
|
63
|
-
version: '1.0.0',
|
|
64
|
-
description: 'test',
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
expect(TestScript.getName()).toBe('my-script');
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('getCurrentVersion() should return the version', () => {
|
|
72
|
-
class TestScript extends AdminScriptBase {
|
|
73
|
-
static Definition = {
|
|
74
|
-
name: 'my-script',
|
|
75
|
-
version: '2.3.1',
|
|
76
|
-
description: 'test',
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
expect(TestScript.getCurrentVersion()).toBe('2.3.1');
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it('getDefinition() should return the full Definition', () => {
|
|
84
|
-
class TestScript extends AdminScriptBase {
|
|
85
|
-
static Definition = {
|
|
86
|
-
name: 'my-script',
|
|
87
|
-
version: '1.0.0',
|
|
88
|
-
description: 'test',
|
|
89
|
-
source: 'USER_DEFINED',
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const definition = TestScript.getDefinition();
|
|
94
|
-
expect(definition).toEqual({
|
|
95
|
-
name: 'my-script',
|
|
96
|
-
version: '1.0.0',
|
|
97
|
-
description: 'test',
|
|
98
|
-
source: 'USER_DEFINED',
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('getDisplayLabel() should return display.label or fall back to name', () => {
|
|
103
|
-
class ScriptWithLabel extends AdminScriptBase {
|
|
104
|
-
static Definition = {
|
|
105
|
-
name: 'my-script',
|
|
106
|
-
version: '1.0.0',
|
|
107
|
-
description: 'test',
|
|
108
|
-
display: { label: 'My Custom Label' },
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
class ScriptWithoutLabel extends AdminScriptBase {
|
|
113
|
-
static Definition = {
|
|
114
|
-
name: 'another-script',
|
|
115
|
-
version: '1.0.0',
|
|
116
|
-
description: 'test',
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
expect(ScriptWithLabel.getDisplayLabel()).toBe('My Custom Label');
|
|
121
|
-
expect(ScriptWithoutLabel.getDisplayLabel()).toBe('another-script');
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it('getDisplayDescription() should return display.description or fall back to description', () => {
|
|
125
|
-
class ScriptWithDisplayDesc extends AdminScriptBase {
|
|
126
|
-
static Definition = {
|
|
127
|
-
name: 'my-script',
|
|
128
|
-
version: '1.0.0',
|
|
129
|
-
description: 'Technical description',
|
|
130
|
-
display: { description: 'User-friendly description' },
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
class ScriptWithoutDisplayDesc extends AdminScriptBase {
|
|
135
|
-
static Definition = {
|
|
136
|
-
name: 'another-script',
|
|
137
|
-
version: '1.0.0',
|
|
138
|
-
description: 'Technical description',
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
expect(ScriptWithDisplayDesc.getDisplayDescription()).toBe('User-friendly description');
|
|
143
|
-
expect(ScriptWithoutDisplayDesc.getDisplayDescription()).toBe('Technical description');
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
|
|
147
56
|
describe('Constructor', () => {
|
|
148
57
|
it('should initialize with default values', () => {
|
|
149
58
|
const script = new AdminScriptBase();
|
|
@@ -202,139 +202,6 @@ describe('ScriptRunner', () => {
|
|
|
202
202
|
});
|
|
203
203
|
});
|
|
204
204
|
|
|
205
|
-
describe('dry-run mode', () => {
|
|
206
|
-
it('should return preview without executing script', async () => {
|
|
207
|
-
const runner = new ScriptRunner({ scriptFactory, commands: mockCommands });
|
|
208
|
-
|
|
209
|
-
const result = await runner.execute('test-script', { foo: 'bar' }, {
|
|
210
|
-
trigger: 'MANUAL',
|
|
211
|
-
dryRun: true,
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
expect(result.dryRun).toBe(true);
|
|
215
|
-
expect(result.status).toBe('DRY_RUN_VALID');
|
|
216
|
-
expect(result.scriptName).toBe('test-script');
|
|
217
|
-
expect(result.preview.script.name).toBe('test-script');
|
|
218
|
-
expect(result.preview.script.version).toBe('1.0.0');
|
|
219
|
-
expect(result.preview.input).toEqual({ foo: 'bar' });
|
|
220
|
-
expect(result.message).toContain('validation passed');
|
|
221
|
-
|
|
222
|
-
// Should NOT create execution record or call commands
|
|
223
|
-
expect(mockCommands.createAdminProcess).not.toHaveBeenCalled();
|
|
224
|
-
expect(mockCommands.updateAdminProcessState).not.toHaveBeenCalled();
|
|
225
|
-
expect(mockCommands.completeAdminProcess).not.toHaveBeenCalled();
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
it('should validate required parameters in dry-run', async () => {
|
|
229
|
-
class SchemaScript extends AdminScriptBase {
|
|
230
|
-
static Definition = {
|
|
231
|
-
name: 'schema-script',
|
|
232
|
-
version: '1.0.0',
|
|
233
|
-
description: 'Script with schema',
|
|
234
|
-
inputSchema: {
|
|
235
|
-
type: 'object',
|
|
236
|
-
required: ['requiredParam'],
|
|
237
|
-
properties: {
|
|
238
|
-
requiredParam: { type: 'string' },
|
|
239
|
-
optionalParam: { type: 'number' },
|
|
240
|
-
},
|
|
241
|
-
},
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
async execute() {
|
|
245
|
-
return {};
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
scriptFactory.register(SchemaScript);
|
|
250
|
-
const runner = new ScriptRunner({ scriptFactory, commands: mockCommands });
|
|
251
|
-
|
|
252
|
-
// Missing required parameter
|
|
253
|
-
const result = await runner.execute('schema-script', {}, {
|
|
254
|
-
trigger: 'MANUAL',
|
|
255
|
-
dryRun: true,
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
expect(result.status).toBe('DRY_RUN_INVALID');
|
|
259
|
-
expect(result.preview.validation.valid).toBe(false);
|
|
260
|
-
expect(result.preview.validation.errors).toContain('Missing required parameter: requiredParam');
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
it('should validate parameter types in dry-run', async () => {
|
|
264
|
-
class TypedScript extends AdminScriptBase {
|
|
265
|
-
static Definition = {
|
|
266
|
-
name: 'typed-script',
|
|
267
|
-
version: '1.0.0',
|
|
268
|
-
description: 'Script with typed params',
|
|
269
|
-
inputSchema: {
|
|
270
|
-
type: 'object',
|
|
271
|
-
properties: {
|
|
272
|
-
count: { type: 'integer' },
|
|
273
|
-
name: { type: 'string' },
|
|
274
|
-
enabled: { type: 'boolean' },
|
|
275
|
-
},
|
|
276
|
-
},
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
async execute() {
|
|
280
|
-
return {};
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
scriptFactory.register(TypedScript);
|
|
285
|
-
const runner = new ScriptRunner({ scriptFactory, commands: mockCommands });
|
|
286
|
-
|
|
287
|
-
const result = await runner.execute('typed-script', {
|
|
288
|
-
count: 'not-a-number',
|
|
289
|
-
name: 123,
|
|
290
|
-
enabled: 'true',
|
|
291
|
-
}, {
|
|
292
|
-
trigger: 'MANUAL',
|
|
293
|
-
dryRun: true,
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
expect(result.status).toBe('DRY_RUN_INVALID');
|
|
297
|
-
expect(result.preview.validation.errors).toHaveLength(3);
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
it('should pass validation with correct parameters', async () => {
|
|
301
|
-
class ValidScript extends AdminScriptBase {
|
|
302
|
-
static Definition = {
|
|
303
|
-
name: 'valid-script',
|
|
304
|
-
version: '1.0.0',
|
|
305
|
-
description: 'Script for validation',
|
|
306
|
-
inputSchema: {
|
|
307
|
-
type: 'object',
|
|
308
|
-
required: ['name'],
|
|
309
|
-
properties: {
|
|
310
|
-
name: { type: 'string' },
|
|
311
|
-
count: { type: 'integer' },
|
|
312
|
-
},
|
|
313
|
-
},
|
|
314
|
-
};
|
|
315
|
-
|
|
316
|
-
async execute() {
|
|
317
|
-
return {};
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
scriptFactory.register(ValidScript);
|
|
322
|
-
const runner = new ScriptRunner({ scriptFactory, commands: mockCommands });
|
|
323
|
-
|
|
324
|
-
const result = await runner.execute('valid-script', {
|
|
325
|
-
name: 'test',
|
|
326
|
-
count: 42,
|
|
327
|
-
}, {
|
|
328
|
-
trigger: 'MANUAL',
|
|
329
|
-
dryRun: true,
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
expect(result.status).toBe('DRY_RUN_VALID');
|
|
333
|
-
expect(result.preview.validation.valid).toBe(true);
|
|
334
|
-
expect(result.preview.validation.errors).toHaveLength(0);
|
|
335
|
-
});
|
|
336
|
-
});
|
|
337
|
-
|
|
338
205
|
describe('createScriptRunner()', () => {
|
|
339
206
|
it('should create runner with default factory', () => {
|
|
340
207
|
const runner = createScriptRunner();
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
const { validateScriptInput, validateParams, validateType } = require('../validate-script-input');
|
|
2
|
+
const { ScriptFactory } = require('../script-factory');
|
|
3
|
+
const { AdminScriptBase } = require('../admin-script-base');
|
|
4
|
+
|
|
5
|
+
describe('validateScriptInput', () => {
|
|
6
|
+
let scriptFactory;
|
|
7
|
+
|
|
8
|
+
class TestScript extends AdminScriptBase {
|
|
9
|
+
static Definition = {
|
|
10
|
+
name: 'test-script',
|
|
11
|
+
version: '1.0.0',
|
|
12
|
+
description: 'Test script',
|
|
13
|
+
config: {
|
|
14
|
+
requireIntegrationInstance: false,
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
async execute(params) {
|
|
19
|
+
return { success: true, params };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
class SchemaScript extends AdminScriptBase {
|
|
24
|
+
static Definition = {
|
|
25
|
+
name: 'schema-script',
|
|
26
|
+
version: '1.0.0',
|
|
27
|
+
description: 'Script with schema',
|
|
28
|
+
inputSchema: {
|
|
29
|
+
type: 'object',
|
|
30
|
+
required: ['requiredParam'],
|
|
31
|
+
properties: {
|
|
32
|
+
requiredParam: { type: 'string' },
|
|
33
|
+
optionalParam: { type: 'number' },
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
async execute() {
|
|
39
|
+
return {};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
class TypedScript extends AdminScriptBase {
|
|
44
|
+
static Definition = {
|
|
45
|
+
name: 'typed-script',
|
|
46
|
+
version: '1.0.0',
|
|
47
|
+
description: 'Script with typed params',
|
|
48
|
+
inputSchema: {
|
|
49
|
+
type: 'object',
|
|
50
|
+
properties: {
|
|
51
|
+
count: { type: 'integer' },
|
|
52
|
+
name: { type: 'string' },
|
|
53
|
+
enabled: { type: 'boolean' },
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
async execute() {
|
|
59
|
+
return {};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
beforeEach(() => {
|
|
64
|
+
scriptFactory = new ScriptFactory([TestScript, SchemaScript, TypedScript]);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('validateScriptInput()', () => {
|
|
68
|
+
it('should return VALID for script without schema', () => {
|
|
69
|
+
const result = validateScriptInput(scriptFactory, 'test-script', { foo: 'bar' });
|
|
70
|
+
|
|
71
|
+
expect(result.status).toBe('VALID');
|
|
72
|
+
expect(result.scriptName).toBe('test-script');
|
|
73
|
+
expect(result.preview.script.name).toBe('test-script');
|
|
74
|
+
expect(result.preview.script.version).toBe('1.0.0');
|
|
75
|
+
expect(result.preview.input).toEqual({ foo: 'bar' });
|
|
76
|
+
expect(result.message).toContain('Validation passed');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should return INVALID when required parameters are missing', () => {
|
|
80
|
+
const result = validateScriptInput(scriptFactory, 'schema-script', {});
|
|
81
|
+
|
|
82
|
+
expect(result.status).toBe('INVALID');
|
|
83
|
+
expect(result.preview.validation.valid).toBe(false);
|
|
84
|
+
expect(result.preview.validation.errors).toContain('Missing required parameter: requiredParam');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should return INVALID for wrong parameter types', () => {
|
|
88
|
+
const result = validateScriptInput(scriptFactory, 'typed-script', {
|
|
89
|
+
count: 'not-a-number',
|
|
90
|
+
name: 123,
|
|
91
|
+
enabled: 'true',
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
expect(result.status).toBe('INVALID');
|
|
95
|
+
expect(result.preview.validation.errors).toHaveLength(3);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('should return VALID with correct parameters', () => {
|
|
99
|
+
const result = validateScriptInput(scriptFactory, 'schema-script', {
|
|
100
|
+
requiredParam: 'hello',
|
|
101
|
+
optionalParam: 42,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
expect(result.status).toBe('VALID');
|
|
105
|
+
expect(result.preview.validation.valid).toBe(true);
|
|
106
|
+
expect(result.preview.validation.errors).toHaveLength(0);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('should include inputSchema in preview', () => {
|
|
110
|
+
const result = validateScriptInput(scriptFactory, 'schema-script', {
|
|
111
|
+
requiredParam: 'test',
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
expect(result.preview.inputSchema).toEqual({
|
|
115
|
+
type: 'object',
|
|
116
|
+
required: ['requiredParam'],
|
|
117
|
+
properties: {
|
|
118
|
+
requiredParam: { type: 'string' },
|
|
119
|
+
optionalParam: { type: 'number' },
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('should return null inputSchema when script has no schema', () => {
|
|
125
|
+
const result = validateScriptInput(scriptFactory, 'test-script', {});
|
|
126
|
+
|
|
127
|
+
expect(result.preview.inputSchema).toBeNull();
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
describe('validateParams()', () => {
|
|
132
|
+
it('should return valid when no schema defined', () => {
|
|
133
|
+
const result = validateParams({ name: 'test' }, { anything: 'goes' });
|
|
134
|
+
|
|
135
|
+
expect(result.valid).toBe(true);
|
|
136
|
+
expect(result.errors).toHaveLength(0);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should check required fields', () => {
|
|
140
|
+
const definition = {
|
|
141
|
+
inputSchema: {
|
|
142
|
+
type: 'object',
|
|
143
|
+
required: ['a', 'b'],
|
|
144
|
+
properties: {
|
|
145
|
+
a: { type: 'string' },
|
|
146
|
+
b: { type: 'string' },
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const result = validateParams(definition, { a: 'yes' });
|
|
152
|
+
|
|
153
|
+
expect(result.valid).toBe(false);
|
|
154
|
+
expect(result.errors).toContain('Missing required parameter: b');
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
describe('validateType()', () => {
|
|
159
|
+
it('should validate integer type', () => {
|
|
160
|
+
expect(validateType('x', 42, { type: 'integer' })).toBeNull();
|
|
161
|
+
expect(validateType('x', 3.14, { type: 'integer' })).toContain('must be an integer');
|
|
162
|
+
expect(validateType('x', 'foo', { type: 'integer' })).toContain('must be an integer');
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('should validate number type', () => {
|
|
166
|
+
expect(validateType('x', 3.14, { type: 'number' })).toBeNull();
|
|
167
|
+
expect(validateType('x', 42, { type: 'number' })).toBeNull();
|
|
168
|
+
expect(validateType('x', 'foo', { type: 'number' })).toContain('must be a number');
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('should validate string type', () => {
|
|
172
|
+
expect(validateType('x', 'hello', { type: 'string' })).toBeNull();
|
|
173
|
+
expect(validateType('x', 123, { type: 'string' })).toContain('must be a string');
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('should validate boolean type', () => {
|
|
177
|
+
expect(validateType('x', true, { type: 'boolean' })).toBeNull();
|
|
178
|
+
expect(validateType('x', 'true', { type: 'boolean' })).toContain('must be a boolean');
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('should validate array type', () => {
|
|
182
|
+
expect(validateType('x', [1, 2], { type: 'array' })).toBeNull();
|
|
183
|
+
expect(validateType('x', 'not-array', { type: 'array' })).toContain('must be an array');
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('should validate object type', () => {
|
|
187
|
+
expect(validateType('x', { a: 1 }, { type: 'object' })).toBeNull();
|
|
188
|
+
expect(validateType('x', [1, 2], { type: 'object' })).toContain('must be an object');
|
|
189
|
+
expect(validateType('x', 'string', { type: 'object' })).toContain('must be an object');
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('should return null when no type specified', () => {
|
|
193
|
+
expect(validateType('x', 'anything', {})).toBeNull();
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
});
|
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
const { QueuerUtil } = require('@friggframework/core/queues');
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* AdminScriptContext - Execution environment for admin scripts
|
|
5
|
+
*
|
|
6
|
+
* Provides a controlled surface area for scripts to interact with
|
|
7
|
+
* the Frigg platform. Unique capabilities vs direct repo access:
|
|
8
|
+
*
|
|
9
|
+
* - **Admin bypass**: `instantiate()` passes `_isAdminContext: true` to
|
|
10
|
+
* skip user-ownership checks when loading integration instances
|
|
11
|
+
* - **Script chaining**: `queueScript()` / `queueScriptBatch()` let scripts
|
|
12
|
+
* enqueue follow-up work with parent execution tracking
|
|
13
|
+
* - **Execution-scoped logging**: `log()` collects structured entries tied
|
|
14
|
+
* to the current execution for post-run inspection
|
|
15
|
+
* - **Lazy-loaded repositories**: Repos are exposed directly as getters
|
|
16
|
+
* so scripts can query any data they need without wrapper indirection
|
|
17
|
+
*/
|
|
3
18
|
class AdminScriptContext {
|
|
4
19
|
constructor(params = {}) {
|
|
5
20
|
this.executionId = params.executionId || null;
|
|
@@ -13,7 +28,6 @@ class AdminScriptContext {
|
|
|
13
28
|
this._userRepository = null;
|
|
14
29
|
this._moduleRepository = null;
|
|
15
30
|
this._credentialRepository = null;
|
|
16
|
-
this._adminProcessRepository = null;
|
|
17
31
|
}
|
|
18
32
|
|
|
19
33
|
// ==================== LAZY-LOADED REPOSITORIES ====================
|
|
@@ -50,76 +64,6 @@ class AdminScriptContext {
|
|
|
50
64
|
return this._credentialRepository;
|
|
51
65
|
}
|
|
52
66
|
|
|
53
|
-
get adminProcessRepository() {
|
|
54
|
-
if (!this._adminProcessRepository) {
|
|
55
|
-
const { createAdminProcessRepository } = require('@friggframework/core/admin-scripts/repositories/admin-process-repository-factory');
|
|
56
|
-
this._adminProcessRepository = createAdminProcessRepository();
|
|
57
|
-
}
|
|
58
|
-
return this._adminProcessRepository;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// ==================== INTEGRATION QUERIES ====================
|
|
62
|
-
|
|
63
|
-
async listIntegrations(filter = {}) {
|
|
64
|
-
if (filter.userId) {
|
|
65
|
-
return this.integrationRepository.findIntegrationsByUserId(filter.userId);
|
|
66
|
-
}
|
|
67
|
-
return this.integrationRepository.findIntegrations(filter);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async findIntegrationById(id) {
|
|
71
|
-
return this.integrationRepository.findIntegrationById(id);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async findIntegrationsByUserId(userId) {
|
|
75
|
-
return this.integrationRepository.findIntegrationsByUserId(userId);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async updateIntegrationConfig(integrationId, config) {
|
|
79
|
-
return this.integrationRepository.updateIntegrationConfig(integrationId, config);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
async updateIntegrationStatus(integrationId, status) {
|
|
83
|
-
return this.integrationRepository.updateIntegrationStatus(integrationId, status);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// ==================== USER QUERIES ====================
|
|
87
|
-
|
|
88
|
-
async findUserById(userId) {
|
|
89
|
-
return this.userRepository.findIndividualUserById(userId);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async findUserByAppUserId(appUserId) {
|
|
93
|
-
return this.userRepository.findIndividualUserByAppUserId(appUserId);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
async findUserByUsername(username) {
|
|
97
|
-
return this.userRepository.findIndividualUserByUsername(username);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// ==================== ENTITY QUERIES ====================
|
|
101
|
-
|
|
102
|
-
async listEntities(filter = {}) {
|
|
103
|
-
if (filter.userId) {
|
|
104
|
-
return this.moduleRepository.findEntitiesByUserId(filter.userId);
|
|
105
|
-
}
|
|
106
|
-
return this.moduleRepository.findEntity(filter);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
async findEntityById(entityId) {
|
|
110
|
-
return this.moduleRepository.findEntityById(entityId);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// ==================== CREDENTIAL QUERIES ====================
|
|
114
|
-
|
|
115
|
-
async findCredential(filter) {
|
|
116
|
-
return this.credentialRepository.findCredential(filter);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
async updateCredential(credentialId, updates) {
|
|
120
|
-
return this.credentialRepository.updateCredential(credentialId, updates);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
67
|
// ==================== INTEGRATION INSTANTIATION ====================
|
|
124
68
|
|
|
125
69
|
/**
|
|
@@ -187,13 +131,6 @@ class AdminScriptContext {
|
|
|
187
131
|
timestamp: new Date().toISOString(),
|
|
188
132
|
};
|
|
189
133
|
this.logs.push(entry);
|
|
190
|
-
|
|
191
|
-
// Persist to execution record if we have an executionId
|
|
192
|
-
if (this.executionId) {
|
|
193
|
-
this.adminProcessRepository.appendProcessLog(this.executionId, entry)
|
|
194
|
-
.catch(err => console.error('Failed to persist log:', err));
|
|
195
|
-
}
|
|
196
|
-
|
|
197
134
|
return entry;
|
|
198
135
|
}
|
|
199
136
|
|
|
@@ -25,26 +25,6 @@ class AdminScriptBase {
|
|
|
25
25
|
},
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
static getName() {
|
|
29
|
-
return this.Definition.name;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
static getCurrentVersion() {
|
|
33
|
-
return this.Definition.version;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
static getDefinition() {
|
|
37
|
-
return this.Definition;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
static getDisplayLabel() {
|
|
41
|
-
return this.Definition.display?.label || this.Definition.name;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
static getDisplayDescription() {
|
|
45
|
-
return this.Definition.display?.description || this.Definition.description;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
28
|
constructor(params = {}) {
|
|
49
29
|
this.context = params.context || null;
|
|
50
30
|
this.executionId = params.executionId || null;
|