@friggframework/admin-scripts 2.0.0--canary.517.300ded3.0 → 2.0.0--canary.517.35ee143.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.
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Delete Schedule Use Case
3
+ *
4
+ * Application Layer - Hexagonal Architecture
5
+ *
6
+ * Deletes a schedule override and cleans up external scheduler resources.
7
+ * Returns the effective schedule after deletion (may fall back to definition).
8
+ */
9
+ class DeleteScheduleUseCase {
10
+ constructor({ commands, schedulerAdapter, scriptFactory }) {
11
+ this.commands = commands;
12
+ this.schedulerAdapter = schedulerAdapter;
13
+ this.scriptFactory = scriptFactory;
14
+ }
15
+
16
+ /**
17
+ * Delete a schedule override
18
+ * @param {string} scriptName - Name of the script
19
+ * @returns {Promise<{success: boolean, deletedCount: number, message: string, effectiveSchedule: Object, schedulerWarning?: string}>}
20
+ */
21
+ async execute(scriptName) {
22
+ this._validateScriptExists(scriptName);
23
+
24
+ // Delete from database
25
+ const deleteResult = await this.commands.deleteSchedule(scriptName);
26
+
27
+ // Cleanup external scheduler if needed
28
+ const schedulerWarning = await this._cleanupExternalScheduler(
29
+ scriptName,
30
+ deleteResult.deleted?.externalScheduleId
31
+ );
32
+
33
+ // Determine effective schedule after deletion
34
+ const effectiveSchedule = this._getEffectiveScheduleAfterDeletion(scriptName);
35
+
36
+ return {
37
+ success: true,
38
+ deletedCount: deleteResult.deletedCount,
39
+ message: deleteResult.deletedCount > 0
40
+ ? 'Schedule override removed'
41
+ : 'No schedule override found',
42
+ effectiveSchedule,
43
+ ...(schedulerWarning && { schedulerWarning }),
44
+ };
45
+ }
46
+
47
+ /**
48
+ * @private
49
+ */
50
+ _validateScriptExists(scriptName) {
51
+ if (!this.scriptFactory.has(scriptName)) {
52
+ const error = new Error(`Script "${scriptName}" not found`);
53
+ error.code = 'SCRIPT_NOT_FOUND';
54
+ throw error;
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Get the definition schedule from a script class
60
+ * @private
61
+ */
62
+ _getDefinitionSchedule(scriptName) {
63
+ const scriptClass = this.scriptFactory.get(scriptName);
64
+ return scriptClass.Definition?.schedule || null;
65
+ }
66
+
67
+ /**
68
+ * Determine effective schedule after deletion
69
+ * @private
70
+ */
71
+ _getEffectiveScheduleAfterDeletion(scriptName) {
72
+ const definitionSchedule = this._getDefinitionSchedule(scriptName);
73
+
74
+ if (definitionSchedule?.enabled) {
75
+ return {
76
+ source: 'definition',
77
+ enabled: definitionSchedule.enabled,
78
+ cronExpression: definitionSchedule.cronExpression,
79
+ timezone: definitionSchedule.timezone || 'UTC',
80
+ };
81
+ }
82
+
83
+ return {
84
+ source: 'none',
85
+ enabled: false,
86
+ };
87
+ }
88
+
89
+ /**
90
+ * Cleanup external scheduler resources
91
+ * @private
92
+ */
93
+ async _cleanupExternalScheduler(scriptName, externalScheduleId) {
94
+ if (!externalScheduleId) {
95
+ return null;
96
+ }
97
+
98
+ try {
99
+ await this.schedulerAdapter.deleteSchedule(scriptName);
100
+ return null;
101
+ } catch (error) {
102
+ // Non-fatal: DB is cleaned up, external scheduler can be retried
103
+ return error.message;
104
+ }
105
+ }
106
+ }
107
+
108
+ module.exports = { DeleteScheduleUseCase };
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Get Effective Schedule Use Case
3
+ *
4
+ * Application Layer - Hexagonal Architecture
5
+ *
6
+ * Resolves the effective schedule for a script following priority:
7
+ * 1. Database override (runtime configuration)
8
+ * 2. Definition default (code-defined schedule)
9
+ * 3. None (manual execution only)
10
+ */
11
+ class GetEffectiveScheduleUseCase {
12
+ constructor({ commands, scriptFactory }) {
13
+ this.commands = commands;
14
+ this.scriptFactory = scriptFactory;
15
+ }
16
+
17
+ /**
18
+ * Get effective schedule for a script
19
+ * @param {string} scriptName - Name of the script
20
+ * @returns {Promise<{source: 'database'|'definition'|'none', schedule: Object}>}
21
+ */
22
+ async execute(scriptName) {
23
+ this._validateScriptExists(scriptName);
24
+
25
+ // Priority 1: Database override
26
+ const dbSchedule = await this.commands.getScheduleByScriptName(scriptName);
27
+ if (dbSchedule) {
28
+ return {
29
+ source: 'database',
30
+ schedule: dbSchedule,
31
+ };
32
+ }
33
+
34
+ // Priority 2: Definition default
35
+ const definitionSchedule = this._getDefinitionSchedule(scriptName);
36
+ if (definitionSchedule?.enabled) {
37
+ return {
38
+ source: 'definition',
39
+ schedule: {
40
+ scriptName,
41
+ enabled: definitionSchedule.enabled,
42
+ cronExpression: definitionSchedule.cronExpression,
43
+ timezone: definitionSchedule.timezone || 'UTC',
44
+ },
45
+ };
46
+ }
47
+
48
+ // Priority 3: No schedule
49
+ return {
50
+ source: 'none',
51
+ schedule: {
52
+ scriptName,
53
+ enabled: false,
54
+ },
55
+ };
56
+ }
57
+
58
+ /**
59
+ * @private
60
+ */
61
+ _validateScriptExists(scriptName) {
62
+ if (!this.scriptFactory.has(scriptName)) {
63
+ const error = new Error(`Script "${scriptName}" not found`);
64
+ error.code = 'SCRIPT_NOT_FOUND';
65
+ throw error;
66
+ }
67
+ }
68
+
69
+ /**
70
+ * @private
71
+ */
72
+ _getDefinitionSchedule(scriptName) {
73
+ const scriptClass = this.scriptFactory.get(scriptName);
74
+ return scriptClass.Definition?.schedule || null;
75
+ }
76
+ }
77
+
78
+ module.exports = { GetEffectiveScheduleUseCase };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Schedule Management Use Cases
3
+ *
4
+ * Separated by Single Responsibility Principle:
5
+ * - GetEffectiveScheduleUseCase: Read schedule with priority resolution
6
+ * - UpsertScheduleUseCase: Create/update schedule with scheduler sync
7
+ * - DeleteScheduleUseCase: Delete schedule with scheduler cleanup
8
+ */
9
+
10
+ const { GetEffectiveScheduleUseCase } = require('./get-effective-schedule-use-case');
11
+ const { UpsertScheduleUseCase } = require('./upsert-schedule-use-case');
12
+ const { DeleteScheduleUseCase } = require('./delete-schedule-use-case');
13
+
14
+ module.exports = {
15
+ GetEffectiveScheduleUseCase,
16
+ UpsertScheduleUseCase,
17
+ DeleteScheduleUseCase,
18
+ };
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Upsert Schedule Use Case
3
+ *
4
+ * Application Layer - Hexagonal Architecture
5
+ *
6
+ * Creates or updates a schedule override with external scheduler provisioning.
7
+ * Abstracts scheduler provider (AWS EventBridge, etc.) behind schedulerAdapter.
8
+ */
9
+ class UpsertScheduleUseCase {
10
+ constructor({ commands, schedulerAdapter, scriptFactory }) {
11
+ this.commands = commands;
12
+ this.schedulerAdapter = schedulerAdapter;
13
+ this.scriptFactory = scriptFactory;
14
+ }
15
+
16
+ /**
17
+ * Create or update a schedule
18
+ * @param {string} scriptName - Name of the script
19
+ * @param {Object} input - Schedule configuration
20
+ * @param {boolean} input.enabled - Whether schedule is enabled
21
+ * @param {string} [input.cronExpression] - Cron expression (required if enabled)
22
+ * @param {string} [input.timezone] - Timezone (defaults to UTC)
23
+ * @returns {Promise<{success: boolean, schedule: Object, schedulerWarning?: string}>}
24
+ */
25
+ async execute(scriptName, { enabled, cronExpression, timezone }) {
26
+ this._validateScriptExists(scriptName);
27
+ this._validateInput(enabled, cronExpression);
28
+
29
+ // Save to database
30
+ const schedule = await this.commands.upsertSchedule({
31
+ scriptName,
32
+ enabled,
33
+ cronExpression: cronExpression || null,
34
+ timezone: timezone || 'UTC',
35
+ });
36
+
37
+ // Sync with external scheduler (AWS EventBridge, etc.)
38
+ const schedulerResult = await this._syncExternalScheduler(
39
+ scriptName,
40
+ enabled,
41
+ cronExpression,
42
+ timezone,
43
+ schedule.externalScheduleId
44
+ );
45
+
46
+ return {
47
+ success: true,
48
+ schedule: {
49
+ ...schedule,
50
+ externalScheduleId: schedulerResult.externalScheduleId || schedule.externalScheduleId,
51
+ externalScheduleName: schedulerResult.externalScheduleName || schedule.externalScheduleName,
52
+ },
53
+ ...(schedulerResult.warning && { schedulerWarning: schedulerResult.warning }),
54
+ };
55
+ }
56
+
57
+ /**
58
+ * @private
59
+ */
60
+ _validateScriptExists(scriptName) {
61
+ if (!this.scriptFactory.has(scriptName)) {
62
+ const error = new Error(`Script "${scriptName}" not found`);
63
+ error.code = 'SCRIPT_NOT_FOUND';
64
+ throw error;
65
+ }
66
+ }
67
+
68
+ /**
69
+ * @private
70
+ */
71
+ _validateInput(enabled, cronExpression) {
72
+ if (typeof enabled !== 'boolean') {
73
+ const error = new Error('enabled must be a boolean');
74
+ error.code = 'INVALID_INPUT';
75
+ throw error;
76
+ }
77
+
78
+ if (enabled && !cronExpression) {
79
+ const error = new Error('cronExpression is required when enabled is true');
80
+ error.code = 'INVALID_INPUT';
81
+ throw error;
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Sync with external scheduler service
87
+ * Abstracts AWS EventBridge or other scheduler providers
88
+ * @private
89
+ */
90
+ async _syncExternalScheduler(scriptName, enabled, cronExpression, timezone, existingId) {
91
+ const result = { externalScheduleId: null, externalScheduleName: null, warning: null };
92
+
93
+ try {
94
+ if (enabled && cronExpression) {
95
+ // Create/update external schedule
96
+ const schedulerInfo = await this.schedulerAdapter.createSchedule({
97
+ scriptName,
98
+ cronExpression,
99
+ timezone: timezone || 'UTC',
100
+ });
101
+
102
+ if (schedulerInfo?.scheduleArn) {
103
+ await this.commands.updateScheduleExternalInfo(scriptName, {
104
+ externalScheduleId: schedulerInfo.scheduleArn,
105
+ externalScheduleName: schedulerInfo.scheduleName,
106
+ });
107
+ result.externalScheduleId = schedulerInfo.scheduleArn;
108
+ result.externalScheduleName = schedulerInfo.scheduleName;
109
+ }
110
+ } else if (!enabled && existingId) {
111
+ // Delete external schedule
112
+ await this.schedulerAdapter.deleteSchedule(scriptName);
113
+ await this.commands.updateScheduleExternalInfo(scriptName, {
114
+ externalScheduleId: null,
115
+ externalScheduleName: null,
116
+ });
117
+ }
118
+ } catch (error) {
119
+ // Non-fatal: DB schedule is saved, external scheduler can be retried
120
+ result.warning = error.message;
121
+ }
122
+
123
+ return result;
124
+ }
125
+ }
126
+
127
+ module.exports = { UpsertScheduleUseCase };
@@ -6,7 +6,7 @@ describe('IntegrationHealthCheckScript', () => {
6
6
  expect(IntegrationHealthCheckScript.Definition.name).toBe('integration-health-check');
7
7
  expect(IntegrationHealthCheckScript.Definition.version).toBe('1.0.0');
8
8
  expect(IntegrationHealthCheckScript.Definition.source).toBe('BUILTIN');
9
- expect(IntegrationHealthCheckScript.Definition.config.requiresIntegrationFactory).toBe(true);
9
+ expect(IntegrationHealthCheckScript.Definition.config.requireIntegrationInstance).toBe(true);
10
10
  });
11
11
 
12
12
  it('should have valid input schema', () => {
@@ -6,7 +6,7 @@ describe('OAuthTokenRefreshScript', () => {
6
6
  expect(OAuthTokenRefreshScript.Definition.name).toBe('oauth-token-refresh');
7
7
  expect(OAuthTokenRefreshScript.Definition.version).toBe('1.0.0');
8
8
  expect(OAuthTokenRefreshScript.Definition.source).toBe('BUILTIN');
9
- expect(OAuthTokenRefreshScript.Definition.config.requiresIntegrationFactory).toBe(true);
9
+ expect(OAuthTokenRefreshScript.Definition.config.requireIntegrationInstance).toBe(true);
10
10
  });
11
11
 
12
12
  it('should have valid input schema', () => {
@@ -54,7 +54,7 @@ class IntegrationHealthCheckScript extends AdminScriptBase {
54
54
  config: {
55
55
  timeout: 900000, // 15 minutes
56
56
  maxRetries: 0,
57
- requiresIntegrationFactory: true,
57
+ requireIntegrationInstance: true,
58
58
  },
59
59
 
60
60
  schedule: {
@@ -47,7 +47,7 @@ class OAuthTokenRefreshScript extends AdminScriptBase {
47
47
  config: {
48
48
  timeout: 600000, // 10 minutes
49
49
  maxRetries: 1,
50
- requiresIntegrationFactory: true, // Needs to call external APIs
50
+ requireIntegrationInstance: true, // Needs to call external APIs
51
51
  },
52
52
 
53
53
  display: {
@@ -99,7 +99,7 @@ describe('Admin Script Router', () => {
99
99
  version: '1.0.0',
100
100
  description: 'Test script',
101
101
  category: 'test',
102
- requiresIntegrationFactory: false,
102
+ requireIntegrationInstance: false,
103
103
  schedule: null,
104
104
  });
105
105
  });
@@ -293,8 +293,8 @@ describe('Admin Script Router', () => {
293
293
  timezone: 'America/New_York',
294
294
  lastTriggeredAt: new Date('2025-01-01T09:00:00Z'),
295
295
  nextTriggerAt: new Date('2025-01-02T09:00:00Z'),
296
- awsScheduleArn: 'arn:aws:events:us-east-1:123456789012:rule/test',
297
- awsScheduleName: 'test-script-schedule',
296
+ externalScheduleId: 'arn:aws:events:us-east-1:123456789012:rule/test',
297
+ externalScheduleName: 'test-script-schedule',
298
298
  createdAt: new Date('2025-01-01T00:00:00Z'),
299
299
  updatedAt: new Date('2025-01-01T00:00:00Z'),
300
300
  };
@@ -470,7 +470,7 @@ describe('Admin Script Router', () => {
470
470
  };
471
471
 
472
472
  mockCommands.upsertSchedule = jest.fn().mockResolvedValue(newSchedule);
473
- mockCommands.updateScheduleAwsInfo = jest.fn().mockResolvedValue(newSchedule);
473
+ mockCommands.updateScheduleExternalInfo = jest.fn().mockResolvedValue(newSchedule);
474
474
  mockSchedulerAdapter.createSchedule.mockResolvedValue({
475
475
  scheduleArn: 'arn:aws:scheduler:us-east-1:123456789012:schedule/frigg-admin-scripts/frigg-script-test-script',
476
476
  scheduleName: 'frigg-script-test-script',
@@ -490,11 +490,11 @@ describe('Admin Script Router', () => {
490
490
  cronExpression: '0 12 * * *',
491
491
  timezone: 'America/Los_Angeles',
492
492
  });
493
- expect(mockCommands.updateScheduleAwsInfo).toHaveBeenCalledWith('test-script', {
494
- awsScheduleArn: 'arn:aws:scheduler:us-east-1:123456789012:schedule/frigg-admin-scripts/frigg-script-test-script',
495
- awsScheduleName: 'frigg-script-test-script',
493
+ expect(mockCommands.updateScheduleExternalInfo).toHaveBeenCalledWith('test-script', {
494
+ externalScheduleId: 'arn:aws:scheduler:us-east-1:123456789012:schedule/frigg-admin-scripts/frigg-script-test-script',
495
+ externalScheduleName: 'frigg-script-test-script',
496
496
  });
497
- expect(response.body.schedule.awsScheduleArn).toBe('arn:aws:scheduler:us-east-1:123456789012:schedule/frigg-admin-scripts/frigg-script-test-script');
497
+ expect(response.body.schedule.externalScheduleId).toBe('arn:aws:scheduler:us-east-1:123456789012:schedule/frigg-admin-scripts/frigg-script-test-script');
498
498
  });
499
499
 
500
500
  it('should delete EventBridge schedule when disabling existing schedule', async () => {
@@ -503,14 +503,14 @@ describe('Admin Script Router', () => {
503
503
  enabled: false,
504
504
  cronExpression: null,
505
505
  timezone: 'UTC',
506
- awsScheduleArn: 'arn:aws:scheduler:us-east-1:123456789012:schedule/frigg-admin-scripts/frigg-script-test-script',
507
- awsScheduleName: 'frigg-script-test-script',
506
+ externalScheduleId: 'arn:aws:scheduler:us-east-1:123456789012:schedule/frigg-admin-scripts/frigg-script-test-script',
507
+ externalScheduleName: 'frigg-script-test-script',
508
508
  createdAt: new Date(),
509
509
  updatedAt: new Date(),
510
510
  };
511
511
 
512
512
  mockCommands.upsertSchedule = jest.fn().mockResolvedValue(existingSchedule);
513
- mockCommands.updateScheduleAwsInfo = jest.fn().mockResolvedValue(existingSchedule);
513
+ mockCommands.updateScheduleExternalInfo = jest.fn().mockResolvedValue(existingSchedule);
514
514
  mockSchedulerAdapter.deleteSchedule.mockResolvedValue();
515
515
 
516
516
  const response = await request(app)
@@ -521,9 +521,9 @@ describe('Admin Script Router', () => {
521
521
 
522
522
  expect(response.status).toBe(200);
523
523
  expect(mockSchedulerAdapter.deleteSchedule).toHaveBeenCalledWith('test-script');
524
- expect(mockCommands.updateScheduleAwsInfo).toHaveBeenCalledWith('test-script', {
525
- awsScheduleArn: null,
526
- awsScheduleName: null,
524
+ expect(mockCommands.updateScheduleExternalInfo).toHaveBeenCalledWith('test-script', {
525
+ externalScheduleId: null,
526
+ externalScheduleName: null,
527
527
  });
528
528
  });
529
529
 
@@ -632,7 +632,7 @@ describe('Admin Script Router', () => {
632
632
  expect(response.body.code).toBe('SCRIPT_NOT_FOUND');
633
633
  });
634
634
 
635
- it('should delete EventBridge schedule when AWS rule exists', async () => {
635
+ it('should delete EventBridge schedule when external rule exists', async () => {
636
636
  mockCommands.deleteSchedule = jest.fn().mockResolvedValue({
637
637
  acknowledged: true,
638
638
  deletedCount: 1,
@@ -640,8 +640,8 @@ describe('Admin Script Router', () => {
640
640
  scriptName: 'test-script',
641
641
  enabled: true,
642
642
  cronExpression: '0 12 * * *',
643
- awsScheduleArn: 'arn:aws:scheduler:us-east-1:123456789012:schedule/frigg-admin-scripts/frigg-script-test-script',
644
- awsScheduleName: 'frigg-script-test-script',
643
+ externalScheduleId: 'arn:aws:scheduler:us-east-1:123456789012:schedule/frigg-admin-scripts/frigg-script-test-script',
644
+ externalScheduleName: 'frigg-script-test-script',
645
645
  },
646
646
  });
647
647
  mockSchedulerAdapter.deleteSchedule.mockResolvedValue();
@@ -654,7 +654,7 @@ describe('Admin Script Router', () => {
654
654
  expect(mockSchedulerAdapter.deleteSchedule).toHaveBeenCalledWith('test-script');
655
655
  });
656
656
 
657
- it('should not call scheduler when no AWS rule exists', async () => {
657
+ it('should not call scheduler when no external rule exists', async () => {
658
658
  mockCommands.deleteSchedule = jest.fn().mockResolvedValue({
659
659
  acknowledged: true,
660
660
  deletedCount: 1,
@@ -662,7 +662,7 @@ describe('Admin Script Router', () => {
662
662
  scriptName: 'test-script',
663
663
  enabled: true,
664
664
  cronExpression: '0 12 * * *',
665
- // No awsScheduleArn
665
+ // No externalScheduleId
666
666
  },
667
667
  });
668
668
 
@@ -682,10 +682,10 @@ describe('Admin Script Router', () => {
682
682
  scriptName: 'test-script',
683
683
  enabled: true,
684
684
  cronExpression: '0 12 * * *',
685
- awsScheduleArn: 'arn:aws:scheduler:us-east-1:123456789012:schedule/frigg-admin-scripts/frigg-script-test-script',
685
+ externalScheduleId: 'arn:aws:scheduler:us-east-1:123456789012:schedule/frigg-admin-scripts/frigg-script-test-script',
686
686
  },
687
687
  });
688
- mockSchedulerAdapter.deleteSchedule.mockRejectedValue(new Error('AWS Scheduler delete failed'));
688
+ mockSchedulerAdapter.deleteSchedule.mockRejectedValue(new Error('Scheduler delete failed'));
689
689
 
690
690
  const response = await request(app).delete(
691
691
  '/admin/scripts/test-script/schedule'
@@ -694,7 +694,7 @@ describe('Admin Script Router', () => {
694
694
  // Request should succeed despite scheduler error
695
695
  expect(response.status).toBe(200);
696
696
  expect(response.body.success).toBe(true);
697
- expect(response.body.schedulerWarning).toBe('AWS Scheduler delete failed');
697
+ expect(response.body.schedulerWarning).toBe('Scheduler delete failed');
698
698
  });
699
699
  });
700
700
  });
@@ -6,7 +6,11 @@ const { createScriptRunner } = require('../application/script-runner');
6
6
  const { createAdminScriptCommands } = require('@friggframework/core/application/commands/admin-script-commands');
7
7
  const { QueuerUtil } = require('@friggframework/core/queues');
8
8
  const { createSchedulerAdapter } = require('../adapters/scheduler-adapter-factory');
9
- const { ScheduleManagementUseCase } = require('../application/schedule-management-use-case');
9
+ const {
10
+ GetEffectiveScheduleUseCase,
11
+ UpsertScheduleUseCase,
12
+ DeleteScheduleUseCase,
13
+ } = require('../application/use-cases');
10
14
 
11
15
  const router = express.Router();
12
16
 
@@ -14,15 +18,19 @@ const router = express.Router();
14
18
  router.use(validateAdminApiKey);
15
19
 
16
20
  /**
17
- * Create ScheduleManagementUseCase instance
21
+ * Create schedule use case instances
18
22
  * @private
19
23
  */
20
- function createScheduleManagementUseCase() {
21
- return new ScheduleManagementUseCase({
22
- commands: createAdminScriptCommands(),
23
- schedulerAdapter: createSchedulerAdapter(),
24
- scriptFactory: getScriptFactory(),
25
- });
24
+ function createScheduleUseCases() {
25
+ const commands = createAdminScriptCommands();
26
+ const schedulerAdapter = createSchedulerAdapter();
27
+ const scriptFactory = getScriptFactory();
28
+
29
+ return {
30
+ getEffectiveSchedule: new GetEffectiveScheduleUseCase({ commands, scriptFactory }),
31
+ upsertSchedule: new UpsertScheduleUseCase({ commands, schedulerAdapter, scriptFactory }),
32
+ deleteSchedule: new DeleteScheduleUseCase({ commands, schedulerAdapter, scriptFactory }),
33
+ };
26
34
  }
27
35
 
28
36
  /**
@@ -40,8 +48,8 @@ router.get('/scripts', async (req, res) => {
40
48
  version: s.definition.version,
41
49
  description: s.definition.description,
42
50
  category: s.definition.display?.category || 'custom',
43
- requiresIntegrationFactory:
44
- s.definition.config?.requiresIntegrationFactory || false,
51
+ requireIntegrationInstance:
52
+ s.definition.config?.requireIntegrationInstance || false,
45
53
  schedule: s.definition.schedule || null,
46
54
  })),
47
55
  });
@@ -211,9 +219,9 @@ router.get('/scripts/:scriptName/executions', async (req, res) => {
211
219
  router.get('/scripts/:scriptName/schedule', async (req, res) => {
212
220
  try {
213
221
  const { scriptName } = req.params;
214
- const useCase = createScheduleManagementUseCase();
222
+ const { getEffectiveSchedule } = createScheduleUseCases();
215
223
 
216
- const result = await useCase.getEffectiveSchedule(scriptName);
224
+ const result = await getEffectiveSchedule.execute(scriptName);
217
225
 
218
226
  res.json({
219
227
  source: result.source,
@@ -240,9 +248,9 @@ router.put('/scripts/:scriptName/schedule', async (req, res) => {
240
248
  try {
241
249
  const { scriptName } = req.params;
242
250
  const { enabled, cronExpression, timezone } = req.body;
243
- const useCase = createScheduleManagementUseCase();
251
+ const { upsertSchedule } = createScheduleUseCases();
244
252
 
245
- const result = await useCase.upsertSchedule(scriptName, {
253
+ const result = await upsertSchedule.execute(scriptName, {
246
254
  enabled,
247
255
  cronExpression,
248
256
  timezone,
@@ -281,9 +289,9 @@ router.put('/scripts/:scriptName/schedule', async (req, res) => {
281
289
  router.delete('/scripts/:scriptName/schedule', async (req, res) => {
282
290
  try {
283
291
  const { scriptName } = req.params;
284
- const useCase = createScheduleManagementUseCase();
292
+ const { deleteSchedule } = createScheduleUseCases();
285
293
 
286
- const result = await useCase.deleteSchedule(scriptName);
294
+ const result = await deleteSchedule.execute(scriptName);
287
295
 
288
296
  res.json(result);
289
297
  } catch (error) {