@friggframework/core 2.0.0--canary.548.c8ae0ca.0 → 2.0.0--canary.545.c40eca4.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/CHANGELOG.md +66 -67
- package/CLAUDE.md +148 -124
- package/README.md +165 -130
- package/admin-scripts/index.js +52 -0
- package/admin-scripts/repositories/admin-api-key-repository-documentdb.js +21 -0
- package/admin-scripts/repositories/admin-api-key-repository-factory.js +51 -0
- package/admin-scripts/repositories/admin-api-key-repository-interface.js +121 -0
- package/admin-scripts/repositories/admin-api-key-repository-mongo.js +155 -0
- package/admin-scripts/repositories/admin-api-key-repository-postgres.js +189 -0
- package/admin-scripts/repositories/admin-process-repository-documentdb.js +21 -0
- package/admin-scripts/repositories/admin-process-repository-factory.js +49 -0
- package/admin-scripts/repositories/admin-process-repository-interface.js +150 -0
- package/admin-scripts/repositories/admin-process-repository-mongo.js +213 -0
- package/admin-scripts/repositories/admin-process-repository-postgres.js +251 -0
- package/admin-scripts/repositories/script-execution-repository-documentdb.js +21 -0
- package/admin-scripts/repositories/script-execution-repository-factory.js +51 -0
- package/admin-scripts/repositories/script-execution-repository-interface.js +193 -0
- package/admin-scripts/repositories/script-execution-repository-mongo.js +278 -0
- package/admin-scripts/repositories/script-execution-repository-postgres.js +320 -0
- package/admin-scripts/repositories/script-schedule-repository-documentdb.js +21 -0
- package/admin-scripts/repositories/script-schedule-repository-factory.js +49 -0
- package/admin-scripts/repositories/script-schedule-repository-interface.js +108 -0
- package/admin-scripts/repositories/script-schedule-repository-mongo.js +179 -0
- package/admin-scripts/repositories/script-schedule-repository-postgres.js +210 -0
- package/application/commands/admin-script-commands.js +348 -0
- package/application/commands/integration-commands.js +12 -6
- package/application/index.js +5 -3
- package/assertions/get.js +17 -7
- package/associations/association.js +59 -57
- package/core/CLAUDE.md +222 -156
- package/core/Worker.js +33 -12
- package/credential/credential-router.js +262 -0
- package/credential/repositories/credential-repository-documentdb.js +71 -1
- package/credential/repositories/credential-repository-factory.js +4 -6
- package/credential/repositories/credential-repository-interface.js +8 -2
- package/credential/repositories/credential-repository-mongo.js +45 -4
- package/credential/repositories/credential-repository-postgres.js +44 -3
- package/credential/repositories/credential-repository.js +3 -1
- package/credential/use-cases/delete-credential-for-user.js +50 -0
- package/credential/use-cases/get-credential-for-user.js +21 -3
- package/credential/use-cases/list-credentials-for-user.js +31 -0
- package/credential/use-cases/reauthorize-credential.js +103 -0
- package/credential/use-cases/update-authentication-status.js +5 -2
- package/database/MONGODB_TRANSACTION_FIX.md +72 -52
- package/database/config.js +13 -59
- package/database/documentdb-encryption-service.js +29 -13
- package/database/documentdb-utils.js +21 -12
- package/database/encryption/README.md +53 -36
- package/database/encryption/encryption-schema-registry.js +29 -23
- package/database/encryption/field-encryption-service.js +15 -4
- package/database/encryption/logger.js +3 -2
- package/database/encryption/prisma-encryption-extension.js +5 -8
- package/database/prisma.js +22 -14
- package/database/repositories/health-check-repository-factory.js +7 -5
- package/database/repositories/health-check-repository-interface.js +15 -5
- package/database/repositories/health-check-repository-postgres.js +1 -1
- package/database/use-cases/check-database-health-use-case.js +3 -2
- package/database/use-cases/check-database-state-use-case.js +8 -7
- package/database/use-cases/get-database-state-via-worker-use-case.js +15 -12
- package/database/use-cases/get-migration-status-use-case.js +4 -2
- package/database/use-cases/run-database-migration-use-case.js +41 -9
- package/database/use-cases/test-encryption-use-case.js +4 -5
- package/database/use-cases/trigger-database-migration-use-case.js +9 -8
- package/database/utils/mongodb-collection-utils.js +11 -3
- package/database/utils/mongodb-schema-init.js +10 -4
- package/database/utils/prisma-runner.js +144 -74
- package/database/utils/prisma-schema-parser.js +2 -2
- package/docs/PROCESS_MANAGEMENT_QUEUE_SPEC.md +135 -80
- package/encrypt/Cryptor.js +54 -49
- package/encrypt/aes-encryption-key-provider.js +82 -0
- package/encrypt/encryption-key-provider-interface.js +50 -0
- package/errors/fetch-error.js +1 -1
- package/generated/prisma-mongodb/edge.js +59 -4
- package/generated/prisma-mongodb/index-browser.js +49 -1
- package/generated/prisma-mongodb/index.d.ts +4023 -61
- package/generated/prisma-mongodb/index.js +59 -4
- package/generated/prisma-mongodb/package.json +1 -1
- package/generated/prisma-mongodb/schema.prisma +87 -0
- package/generated/prisma-mongodb/wasm.js +59 -4
- package/generated/prisma-postgresql/edge.js +58 -4
- package/generated/prisma-postgresql/index-browser.js +48 -1
- package/generated/prisma-postgresql/index.d.ts +4738 -54
- package/generated/prisma-postgresql/index.js +58 -4
- package/generated/prisma-postgresql/package.json +1 -1
- package/generated/prisma-postgresql/schema.prisma +85 -0
- package/generated/prisma-postgresql/wasm.js +58 -4
- package/handlers/WEBHOOKS.md +104 -81
- package/handlers/app-definition-loader.js +53 -10
- package/handlers/app-handler-helpers.js +14 -3
- package/handlers/backend-utils.js +0 -1
- package/handlers/database-migration-handler.js +64 -45
- package/handlers/middleware/admin-auth.js +53 -0
- package/handlers/routers/HEALTHCHECK.md +170 -135
- package/handlers/routers/admin.js +474 -0
- package/handlers/routers/auth.js +51 -9
- package/handlers/routers/db-migration.handler.js +2 -3
- package/handlers/routers/db-migration.js +102 -66
- package/handlers/routers/docs.js +180 -0
- package/handlers/routers/health.js +84 -283
- package/handlers/routers/integration-defined-routers.js +44 -33
- package/handlers/routers/integration-webhook-routers.js +73 -52
- package/handlers/routers/middleware/loadUser.js +39 -0
- package/handlers/routers/middleware/requireAdmin.js +43 -0
- package/handlers/routers/middleware/requireLoggedInUser.js +19 -0
- package/handlers/routers/user.js +30 -14
- package/handlers/routers/websocket.js +18 -4
- package/handlers/use-cases/check-integrations-health-use-case.js +13 -6
- package/handlers/workers/db-migration.js +74 -35
- package/handlers/workers/integration-defined-workers.js +31 -20
- package/index.js +50 -16
- package/infrastructure/scheduler/index.js +15 -11
- package/infrastructure/scheduler/netlify-scheduler-adapter.js +185 -0
- package/infrastructure/scheduler/scheduler-service-factory.js +38 -31
- package/integrations/WEBHOOK-QUICKSTART.md +21 -14
- package/integrations/index.js +4 -0
- package/integrations/integration-base.js +9 -6
- package/integrations/integration-router.js +1828 -157
- package/integrations/options.js +47 -20
- package/integrations/repositories/integration-mapping-repository-factory.js +4 -8
- package/integrations/repositories/integration-repository-documentdb.js +53 -24
- package/integrations/repositories/integration-repository-factory.js +6 -6
- package/integrations/repositories/integration-repository-interface.js +27 -9
- package/integrations/repositories/integration-repository-postgres.js +3 -3
- package/integrations/repositories/process-repository-factory.js +4 -7
- package/integrations/repositories/process-repository-interface.js +9 -5
- package/integrations/repositories/process-repository-mongo.js +7 -3
- package/integrations/repositories/process-repository-postgres.js +2 -2
- package/integrations/tests/doubles/config-capturing-integration.js +9 -8
- package/integrations/tests/doubles/dummy-integration-class.js +81 -8
- package/integrations/tests/doubles/test-integration-repository.js +51 -11
- package/integrations/use-cases/create-integration.js +36 -32
- package/integrations/use-cases/create-process.js +20 -9
- package/integrations/use-cases/delete-integration-for-user.js +5 -4
- package/integrations/use-cases/execute-proxy-request.js +564 -0
- package/integrations/use-cases/get-integration-for-user.js +25 -10
- package/integrations/use-cases/get-integration-instance-by-definition.js +13 -7
- package/integrations/use-cases/get-integrations-for-user.js +4 -1
- package/integrations/use-cases/get-possible-integrations.js +1 -1
- package/integrations/use-cases/get-process.js +5 -6
- package/integrations/use-cases/index.js +3 -1
- package/integrations/use-cases/load-integration-context.js +1 -5
- package/integrations/use-cases/update-process-state.js +10 -8
- package/integrations/utils/map-integration-dto.js +9 -3
- package/jest-setup.js +1 -1
- package/jest-teardown.js +1 -1
- package/lambda/TimeoutCatcher.js +32 -30
- package/lambda/index.js +1 -1
- package/logs/index.js +3 -3
- package/modules/domain/entities/AuthorizationSession.js +131 -0
- package/modules/domain/entities/index.js +10 -0
- package/modules/module.js +4 -9
- package/modules/repositories/authorization-session-repository-factory.js +53 -0
- package/modules/repositories/authorization-session-repository-interface.js +75 -0
- package/modules/repositories/authorization-session-repository-mongo.js +169 -0
- package/modules/repositories/authorization-session-repository-postgres.js +170 -0
- package/modules/repositories/module-repository-documentdb.js +89 -41
- package/modules/repositories/module-repository-factory.js +4 -6
- package/modules/repositories/module-repository-interface.js +13 -0
- package/modules/repositories/module-repository-mongo.js +40 -5
- package/modules/repositories/module-repository-postgres.js +42 -5
- package/modules/repositories/module-repository.js +28 -0
- package/modules/requester/api-key.js +0 -2
- package/modules/requester/basic.js +0 -1
- package/modules/requester/oauth-2.js +3 -14
- package/modules/test/mock-api/definition.js +15 -10
- package/modules/test/mock-api/mocks/hubspot.js +36 -36
- package/modules/tests/doubles/test-module-factory.js +10 -4
- package/modules/tests/doubles/test-module-repository.js +1 -1
- package/modules/use-cases/delete-module-entity.js +23 -0
- package/modules/use-cases/get-authorization-requirements.js +110 -0
- package/modules/use-cases/get-entities-for-user.js +1 -1
- package/modules/use-cases/get-entity-options-by-id.js +8 -6
- package/modules/use-cases/get-module-entity-by-id.js +16 -0
- package/modules/use-cases/get-module.js +12 -9
- package/modules/use-cases/process-authorization-callback.js +12 -6
- package/modules/use-cases/process-authorization-step.js +160 -0
- package/modules/use-cases/refresh-entity-options.js +8 -6
- package/modules/use-cases/start-authorization-session.js +86 -0
- package/modules/use-cases/test-module-auth.js +8 -6
- package/modules/use-cases/update-module-entity.js +27 -0
- package/modules/utils/map-module-dto.js +2 -2
- package/openapi/openapi-spec-generator.js +370 -0
- package/openapi/openapi-v1.yaml +1360 -0
- package/openapi/openapi-v2.yaml +1535 -0
- package/package.json +7 -9
- package/prisma-mongodb/schema.prisma +87 -0
- package/prisma-postgresql/migrations/20260222000000_add_admin_process_and_script_schedule/migration.sql +55 -0
- package/prisma-postgresql/schema.prisma +85 -0
- package/providers/index.js +13 -0
- package/providers/resolve-provider.js +93 -0
- package/queues/index.js +19 -0
- package/queues/providers/index.js +7 -0
- package/queues/providers/netlify-background-provider.js +76 -0
- package/queues/providers/qstash-queue-provider.js +122 -0
- package/queues/queue-client-interface.js +55 -0
- package/queues/queue-provider-factory.js +93 -0
- package/queues/queue-provider.js +46 -0
- package/queues/queuer-util.js +33 -25
- package/syncs/repositories/sync-repository-documentdb.js +39 -19
- package/syncs/repositories/sync-repository-factory.js +4 -4
- package/syncs/repositories/sync-repository-interface.js +6 -2
- package/syncs/repositories/sync-repository-postgres.js +19 -13
- package/syncs/sync.js +104 -100
- package/token/repositories/token-repository-factory.js +4 -6
- package/types/assertions/index.d.ts +72 -72
- package/types/core/index.d.ts +98 -53
- package/types/errors/index.d.ts +61 -54
- package/types/eslint-config/index.d.ts +40 -40
- package/types/lambda/index.d.ts +26 -26
- package/types/logs/index.d.ts +4 -4
- package/types/prettier-config/index.d.ts +5 -5
- package/types/test-environment/index.d.ts +14 -14
- package/types/tsconfig.json +95 -93
- package/user/repositories/user-repository-factory.js +4 -4
- package/user/tests/doubles/test-user-repository.js +5 -2
- package/user/use-cases/authenticate-user.js +2 -4
- package/user/use-cases/authenticate-with-shared-secret.js +1 -1
- package/user/use-cases/create-individual-user.js +8 -7
- package/user/use-cases/create-organization-user.js +1 -1
- package/user/use-cases/create-token-for-user-id.js +1 -1
- package/user/use-cases/delete-user.js +47 -0
- package/user/use-cases/get-user-from-adopter-jwt.js +0 -2
- package/user/use-cases/get-user-from-bearer-token.js +7 -3
- package/user/use-cases/get-user-from-x-frigg-headers.js +14 -11
- package/user/use-cases/login-user.js +8 -8
- package/user/user.js +18 -4
- package/utils/backend-path.js +2 -2
- package/utils/index.js +4 -1
- package/websocket/repositories/websocket-connection-repository-documentdb.js +46 -21
- package/websocket/repositories/websocket-connection-repository-factory.js +4 -8
- package/websocket/repositories/websocket-connection-repository-mongo.js +26 -16
- package/websocket/repositories/websocket-connection-repository-postgres.js +26 -15
- package/websocket/repositories/websocket-connection-repository.js +26 -20
- package/websocket/websocket-message-sender-interface.js +38 -0
- package/database/adapters/lambda-invoker.js +0 -97
- package/database/repositories/migration-status-repository-s3.js +0 -137
- package/infrastructure/scheduler/eventbridge-scheduler-adapter.js +0 -184
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
const { prisma } = require('../../database/prisma');
|
|
2
|
+
const {
|
|
3
|
+
ScriptExecutionRepositoryInterface,
|
|
4
|
+
} = require('./script-execution-repository-interface');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* PostgreSQL Script Execution Repository Adapter
|
|
8
|
+
* Handles script execution persistence using Prisma with PostgreSQL
|
|
9
|
+
*
|
|
10
|
+
* PostgreSQL-specific characteristics:
|
|
11
|
+
* - Uses Int IDs with autoincrement
|
|
12
|
+
* - Requires ID conversion: String (app layer) ↔ Int (database)
|
|
13
|
+
* - All returned IDs are converted to strings for application layer consistency
|
|
14
|
+
* - logs field is Json[] - supports push operations
|
|
15
|
+
*/
|
|
16
|
+
class ScriptExecutionRepositoryPostgres extends ScriptExecutionRepositoryInterface {
|
|
17
|
+
constructor() {
|
|
18
|
+
super();
|
|
19
|
+
this.prisma = prisma;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Convert string ID to integer for PostgreSQL queries
|
|
24
|
+
* @private
|
|
25
|
+
* @param {string|number|null|undefined} id - ID to convert
|
|
26
|
+
* @returns {number|null|undefined} Integer ID or null/undefined
|
|
27
|
+
* @throws {Error} If ID cannot be converted to integer
|
|
28
|
+
*/
|
|
29
|
+
_convertId(id) {
|
|
30
|
+
if (id === null || id === undefined) return id;
|
|
31
|
+
const parsed = Number.parseInt(id, 10);
|
|
32
|
+
if (Number.isNaN(parsed)) {
|
|
33
|
+
throw new Error(`Invalid ID: ${id} cannot be converted to integer`);
|
|
34
|
+
}
|
|
35
|
+
return parsed;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Convert execution object IDs to strings
|
|
40
|
+
* @private
|
|
41
|
+
* @param {Object|null} execution - Execution object from database
|
|
42
|
+
* @returns {Object|null} Execution with string IDs
|
|
43
|
+
*/
|
|
44
|
+
_convertExecutionIds(execution) {
|
|
45
|
+
if (!execution) return execution;
|
|
46
|
+
return {
|
|
47
|
+
...execution,
|
|
48
|
+
id: execution.id?.toString(),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Create a new script execution record
|
|
54
|
+
*
|
|
55
|
+
* @param {Object} params - Execution creation parameters
|
|
56
|
+
* @param {string} params.scriptName - Name of the script being executed
|
|
57
|
+
* @param {string} [params.scriptVersion] - Version of the script
|
|
58
|
+
* @param {string} params.trigger - Trigger type
|
|
59
|
+
* @param {string} [params.mode] - Execution mode ('sync' or 'async', default 'async')
|
|
60
|
+
* @param {Object} [params.input] - Input parameters for the script
|
|
61
|
+
* @param {Object} [params.audit] - Audit information
|
|
62
|
+
* @param {string} [params.audit.apiKeyName] - Name of API key used
|
|
63
|
+
* @param {string} [params.audit.apiKeyLast4] - Last 4 chars of API key
|
|
64
|
+
* @param {string} [params.audit.ipAddress] - IP address of requester
|
|
65
|
+
* @returns {Promise<Object>} The created execution record with string ID
|
|
66
|
+
*/
|
|
67
|
+
async createExecution({
|
|
68
|
+
scriptName,
|
|
69
|
+
scriptVersion,
|
|
70
|
+
trigger,
|
|
71
|
+
mode,
|
|
72
|
+
input,
|
|
73
|
+
audit,
|
|
74
|
+
}) {
|
|
75
|
+
const data = {
|
|
76
|
+
scriptName,
|
|
77
|
+
scriptVersion,
|
|
78
|
+
trigger,
|
|
79
|
+
mode: mode || 'async',
|
|
80
|
+
input,
|
|
81
|
+
logs: [],
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// Map audit object to separate fields
|
|
85
|
+
if (audit) {
|
|
86
|
+
if (audit.apiKeyName) data.auditApiKeyName = audit.apiKeyName;
|
|
87
|
+
if (audit.apiKeyLast4) data.auditApiKeyLast4 = audit.apiKeyLast4;
|
|
88
|
+
if (audit.ipAddress) data.auditIpAddress = audit.ipAddress;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const execution = await this.prisma.scriptExecution.create({
|
|
92
|
+
data,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
return this._convertExecutionIds(execution);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Find an execution by its ID
|
|
100
|
+
*
|
|
101
|
+
* @param {string|number} id - The execution ID
|
|
102
|
+
* @returns {Promise<Object|null>} The execution record with string ID or null if not found
|
|
103
|
+
*/
|
|
104
|
+
async findExecutionById(id) {
|
|
105
|
+
const intId = this._convertId(id);
|
|
106
|
+
const execution = await this.prisma.scriptExecution.findUnique({
|
|
107
|
+
where: { id: intId },
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
return this._convertExecutionIds(execution);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Find all executions for a specific script
|
|
115
|
+
*
|
|
116
|
+
* @param {string} scriptName - The script name to filter by
|
|
117
|
+
* @param {Object} [options] - Query options
|
|
118
|
+
* @param {number} [options.limit] - Maximum number of results
|
|
119
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
120
|
+
* @param {string} [options.sortBy] - Field to sort by
|
|
121
|
+
* @param {string} [options.sortOrder] - Sort order ('asc' or 'desc')
|
|
122
|
+
* @returns {Promise<Array>} Array of execution records with string IDs
|
|
123
|
+
*/
|
|
124
|
+
async findExecutionsByScriptName(scriptName, options = {}) {
|
|
125
|
+
const {
|
|
126
|
+
limit,
|
|
127
|
+
offset,
|
|
128
|
+
sortBy = 'createdAt',
|
|
129
|
+
sortOrder = 'desc',
|
|
130
|
+
} = options;
|
|
131
|
+
|
|
132
|
+
const executions = await this.prisma.scriptExecution.findMany({
|
|
133
|
+
where: { scriptName },
|
|
134
|
+
orderBy: { [sortBy]: sortOrder },
|
|
135
|
+
take: limit,
|
|
136
|
+
skip: offset,
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
return executions.map((execution) =>
|
|
140
|
+
this._convertExecutionIds(execution)
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Find all executions with a specific status
|
|
146
|
+
*
|
|
147
|
+
* @param {string} status - Status to filter by
|
|
148
|
+
* @param {Object} [options] - Query options
|
|
149
|
+
* @param {number} [options.limit] - Maximum number of results
|
|
150
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
151
|
+
* @param {string} [options.sortBy] - Field to sort by
|
|
152
|
+
* @param {string} [options.sortOrder] - Sort order ('asc' or 'desc')
|
|
153
|
+
* @returns {Promise<Array>} Array of execution records with string IDs
|
|
154
|
+
*/
|
|
155
|
+
async findExecutionsByStatus(status, options = {}) {
|
|
156
|
+
const {
|
|
157
|
+
limit,
|
|
158
|
+
offset,
|
|
159
|
+
sortBy = 'createdAt',
|
|
160
|
+
sortOrder = 'desc',
|
|
161
|
+
} = options;
|
|
162
|
+
|
|
163
|
+
const executions = await this.prisma.scriptExecution.findMany({
|
|
164
|
+
where: { status },
|
|
165
|
+
orderBy: { [sortBy]: sortOrder },
|
|
166
|
+
take: limit,
|
|
167
|
+
skip: offset,
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
return executions.map((execution) =>
|
|
171
|
+
this._convertExecutionIds(execution)
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Update the status of an execution
|
|
177
|
+
*
|
|
178
|
+
* @param {string|number} id - The execution ID
|
|
179
|
+
* @param {string} status - New status value
|
|
180
|
+
* @returns {Promise<Object>} Updated execution record with string ID
|
|
181
|
+
*/
|
|
182
|
+
async updateExecutionStatus(id, status) {
|
|
183
|
+
const intId = this._convertId(id);
|
|
184
|
+
const execution = await this.prisma.scriptExecution.update({
|
|
185
|
+
where: { id: intId },
|
|
186
|
+
data: { status },
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
return this._convertExecutionIds(execution);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Update the output result of an execution
|
|
194
|
+
*
|
|
195
|
+
* @param {string|number} id - The execution ID
|
|
196
|
+
* @param {Object} output - Output data from the script
|
|
197
|
+
* @returns {Promise<Object>} Updated execution record with string ID
|
|
198
|
+
*/
|
|
199
|
+
async updateExecutionOutput(id, output) {
|
|
200
|
+
const intId = this._convertId(id);
|
|
201
|
+
const execution = await this.prisma.scriptExecution.update({
|
|
202
|
+
where: { id: intId },
|
|
203
|
+
data: { output },
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
return this._convertExecutionIds(execution);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Update the error details of a failed execution
|
|
211
|
+
*
|
|
212
|
+
* @param {string|number} id - The execution ID
|
|
213
|
+
* @param {Object} error - Error information
|
|
214
|
+
* @param {string} error.name - Error name/type
|
|
215
|
+
* @param {string} error.message - Error message
|
|
216
|
+
* @param {string} [error.stack] - Error stack trace
|
|
217
|
+
* @returns {Promise<Object>} Updated execution record with string ID
|
|
218
|
+
*/
|
|
219
|
+
async updateExecutionError(id, error) {
|
|
220
|
+
const intId = this._convertId(id);
|
|
221
|
+
const execution = await this.prisma.scriptExecution.update({
|
|
222
|
+
where: { id: intId },
|
|
223
|
+
data: {
|
|
224
|
+
errorName: error.name,
|
|
225
|
+
errorMessage: error.message,
|
|
226
|
+
errorStack: error.stack,
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
return this._convertExecutionIds(execution);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Update the performance metrics of an execution
|
|
235
|
+
*
|
|
236
|
+
* @param {string|number} id - The execution ID
|
|
237
|
+
* @param {Object} metrics - Performance metrics
|
|
238
|
+
* @param {Date} [metrics.startTime] - Execution start time
|
|
239
|
+
* @param {Date} [metrics.endTime] - Execution end time
|
|
240
|
+
* @param {number} [metrics.durationMs] - Duration in milliseconds
|
|
241
|
+
* @returns {Promise<Object>} Updated execution record with string ID
|
|
242
|
+
*/
|
|
243
|
+
async updateExecutionMetrics(id, metrics) {
|
|
244
|
+
const intId = this._convertId(id);
|
|
245
|
+
const data = {};
|
|
246
|
+
if (metrics.startTime !== undefined)
|
|
247
|
+
data.metricsStartTime = metrics.startTime;
|
|
248
|
+
if (metrics.endTime !== undefined)
|
|
249
|
+
data.metricsEndTime = metrics.endTime;
|
|
250
|
+
if (metrics.durationMs !== undefined)
|
|
251
|
+
data.metricsDurationMs = metrics.durationMs;
|
|
252
|
+
|
|
253
|
+
const execution = await this.prisma.scriptExecution.update({
|
|
254
|
+
where: { id: intId },
|
|
255
|
+
data,
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
return this._convertExecutionIds(execution);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Append a log entry to an execution's log array
|
|
263
|
+
*
|
|
264
|
+
* @param {string|number} id - The execution ID
|
|
265
|
+
* @param {Object} logEntry - Log entry to append
|
|
266
|
+
* @param {string} logEntry.level - Log level ('debug', 'info', 'warn', 'error')
|
|
267
|
+
* @param {string} logEntry.message - Log message
|
|
268
|
+
* @param {Object} [logEntry.data] - Additional log data
|
|
269
|
+
* @param {string} logEntry.timestamp - ISO timestamp
|
|
270
|
+
* @returns {Promise<Object>} Updated execution record with string ID
|
|
271
|
+
*/
|
|
272
|
+
async appendExecutionLog(id, logEntry) {
|
|
273
|
+
const intId = this._convertId(id);
|
|
274
|
+
|
|
275
|
+
// Get current execution
|
|
276
|
+
const execution = await this.prisma.scriptExecution.findUnique({
|
|
277
|
+
where: { id: intId },
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
if (!execution) {
|
|
281
|
+
throw new Error(`Execution ${id} not found`);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Append log entry to logs array (copy to avoid mutating original)
|
|
285
|
+
const logs = Array.isArray(execution.logs) ? [...execution.logs] : [];
|
|
286
|
+
logs.push(logEntry);
|
|
287
|
+
|
|
288
|
+
// Update with new logs array
|
|
289
|
+
const updated = await this.prisma.scriptExecution.update({
|
|
290
|
+
where: { id: intId },
|
|
291
|
+
data: { logs },
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
return this._convertExecutionIds(updated);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Delete all executions older than a specific date
|
|
299
|
+
* Used for cleanup and retention policies
|
|
300
|
+
*
|
|
301
|
+
* @param {Date} date - Delete executions older than this date
|
|
302
|
+
* @returns {Promise<Object>} Deletion result with count
|
|
303
|
+
*/
|
|
304
|
+
async deleteExecutionsOlderThan(date) {
|
|
305
|
+
const result = await this.prisma.scriptExecution.deleteMany({
|
|
306
|
+
where: {
|
|
307
|
+
createdAt: {
|
|
308
|
+
lt: date,
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
return {
|
|
314
|
+
acknowledged: true,
|
|
315
|
+
deletedCount: result.count,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
module.exports = { ScriptExecutionRepositoryPostgres };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const {
|
|
2
|
+
ScriptScheduleRepositoryMongo,
|
|
3
|
+
} = require('./script-schedule-repository-mongo');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* DocumentDB Script Schedule Repository Adapter
|
|
7
|
+
* Handles script schedule persistence using Prisma with AWS DocumentDB
|
|
8
|
+
*
|
|
9
|
+
* DocumentDB is MongoDB-compatible with some limitations:
|
|
10
|
+
* - Uses MongoDB wire protocol
|
|
11
|
+
* - Same Prisma schema as MongoDB
|
|
12
|
+
* - Inherits all MongoDB repository methods
|
|
13
|
+
*
|
|
14
|
+
* For schedule operations, DocumentDB and MongoDB behavior is identical.
|
|
15
|
+
*/
|
|
16
|
+
class ScriptScheduleRepositoryDocumentDB extends ScriptScheduleRepositoryMongo {
|
|
17
|
+
// Inherits all methods from MongoDB implementation
|
|
18
|
+
// DocumentDB is MongoDB-compatible for these operations
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = { ScriptScheduleRepositoryDocumentDB };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const { ScriptScheduleRepositoryPostgres } = require('./script-schedule-repository-postgres');
|
|
2
|
+
const config = require('../../database/config');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Script Schedule Repository Factory
|
|
6
|
+
* Creates the appropriate repository adapter based on database type
|
|
7
|
+
*
|
|
8
|
+
* This implements the Factory pattern for Hexagonal Architecture:
|
|
9
|
+
* - Reads database type from app definition (backend/index.js)
|
|
10
|
+
* - Returns correct adapter (MongoDB, DocumentDB, or PostgreSQL)
|
|
11
|
+
* - Provides clear error for unsupported databases
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* ```javascript
|
|
15
|
+
* const repository = createScriptScheduleRepository();
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @returns {ScriptScheduleRepositoryInterface} Configured repository adapter
|
|
19
|
+
* @throws {Error} If database type is not supported
|
|
20
|
+
*/
|
|
21
|
+
function createScriptScheduleRepository() {
|
|
22
|
+
const dbType = config.DB_TYPE;
|
|
23
|
+
|
|
24
|
+
switch (dbType) {
|
|
25
|
+
case 'mongodb':
|
|
26
|
+
const { ScriptScheduleRepositoryMongo } = require('./script-schedule-repository-mongo');
|
|
27
|
+
return new ScriptScheduleRepositoryMongo();
|
|
28
|
+
|
|
29
|
+
case 'postgresql':
|
|
30
|
+
return new ScriptScheduleRepositoryPostgres();
|
|
31
|
+
|
|
32
|
+
case 'documentdb':
|
|
33
|
+
const { ScriptScheduleRepositoryDocumentDB } = require('./script-schedule-repository-documentdb');
|
|
34
|
+
return new ScriptScheduleRepositoryDocumentDB();
|
|
35
|
+
|
|
36
|
+
default:
|
|
37
|
+
throw new Error(
|
|
38
|
+
`Unsupported database type: ${dbType}. Supported values: 'mongodb', 'documentdb', 'postgresql'`
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
module.exports = {
|
|
44
|
+
createScriptScheduleRepository,
|
|
45
|
+
// Export adapters for direct testing
|
|
46
|
+
get ScriptScheduleRepositoryMongo() { return require('./script-schedule-repository-mongo').ScriptScheduleRepositoryMongo; },
|
|
47
|
+
ScriptScheduleRepositoryPostgres,
|
|
48
|
+
get ScriptScheduleRepositoryDocumentDB() { return require('./script-schedule-repository-documentdb').ScriptScheduleRepositoryDocumentDB; },
|
|
49
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Script Schedule Repository Interface
|
|
3
|
+
* Abstract base class defining the contract for script schedule persistence adapters
|
|
4
|
+
*
|
|
5
|
+
* This follows the Port in Hexagonal Architecture:
|
|
6
|
+
* - Domain layer depends on this abstraction
|
|
7
|
+
* - Concrete adapters implement this interface
|
|
8
|
+
* - Use cases receive repositories via dependency injection
|
|
9
|
+
*
|
|
10
|
+
* Script schedules support Phase 2 hybrid scheduling:
|
|
11
|
+
* - Database overrides take precedence over Definition defaults
|
|
12
|
+
* - EventBridge rules provisioned for enabled schedules
|
|
13
|
+
* - lastTriggeredAt and nextTriggerAt for monitoring
|
|
14
|
+
*
|
|
15
|
+
* @abstract
|
|
16
|
+
*/
|
|
17
|
+
class ScriptScheduleRepositoryInterface {
|
|
18
|
+
/**
|
|
19
|
+
* Find a schedule by script name
|
|
20
|
+
*
|
|
21
|
+
* @param {string} scriptName - The script name
|
|
22
|
+
* @returns {Promise<Object|null>} Schedule record or null if not found
|
|
23
|
+
* @abstract
|
|
24
|
+
*/
|
|
25
|
+
async findScheduleByScriptName(scriptName) {
|
|
26
|
+
throw new Error('Method findScheduleByScriptName must be implemented by subclass');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Create or update a schedule (upsert)
|
|
31
|
+
*
|
|
32
|
+
* @param {Object} params - Schedule parameters
|
|
33
|
+
* @param {string} params.scriptName - Name of the script
|
|
34
|
+
* @param {boolean} params.enabled - Whether schedule is enabled
|
|
35
|
+
* @param {string} params.cronExpression - Cron expression
|
|
36
|
+
* @param {string} [params.timezone] - Timezone (default 'UTC')
|
|
37
|
+
* @param {string} [params.externalScheduleId] - External scheduler ID (e.g., AWS ARN)
|
|
38
|
+
* @param {string} [params.externalScheduleName] - External scheduler name
|
|
39
|
+
* @returns {Promise<Object>} Created or updated schedule record
|
|
40
|
+
* @abstract
|
|
41
|
+
*/
|
|
42
|
+
async upsertSchedule({ scriptName, enabled, cronExpression, timezone, externalScheduleId, externalScheduleName }) {
|
|
43
|
+
throw new Error('Method upsertSchedule must be implemented by subclass');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Delete a schedule by script name
|
|
48
|
+
*
|
|
49
|
+
* @param {string} scriptName - The script name
|
|
50
|
+
* @returns {Promise<Object>} Deletion result
|
|
51
|
+
* @abstract
|
|
52
|
+
*/
|
|
53
|
+
async deleteSchedule(scriptName) {
|
|
54
|
+
throw new Error('Method deleteSchedule must be implemented by subclass');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Update external scheduler information
|
|
59
|
+
*
|
|
60
|
+
* @param {string} scriptName - The script name
|
|
61
|
+
* @param {Object} externalInfo - External schedule information
|
|
62
|
+
* @param {string} [externalInfo.externalScheduleId] - External scheduler ID (e.g., AWS ARN)
|
|
63
|
+
* @param {string} [externalInfo.externalScheduleName] - External scheduler name
|
|
64
|
+
* @returns {Promise<Object>} Updated schedule record
|
|
65
|
+
* @abstract
|
|
66
|
+
*/
|
|
67
|
+
async updateScheduleExternalInfo(scriptName, { externalScheduleId, externalScheduleName }) {
|
|
68
|
+
throw new Error('Method updateScheduleExternalInfo must be implemented by subclass');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Update last triggered timestamp
|
|
73
|
+
*
|
|
74
|
+
* @param {string} scriptName - The script name
|
|
75
|
+
* @param {Date} [timestamp] - Trigger timestamp (default: now)
|
|
76
|
+
* @returns {Promise<Object>} Updated schedule record
|
|
77
|
+
* @abstract
|
|
78
|
+
*/
|
|
79
|
+
async updateScheduleLastTriggered(scriptName, timestamp) {
|
|
80
|
+
throw new Error('Method updateScheduleLastTriggered must be implemented by subclass');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Update next trigger timestamp
|
|
85
|
+
*
|
|
86
|
+
* @param {string} scriptName - The script name
|
|
87
|
+
* @param {Date} timestamp - Next trigger timestamp
|
|
88
|
+
* @returns {Promise<Object>} Updated schedule record
|
|
89
|
+
* @abstract
|
|
90
|
+
*/
|
|
91
|
+
async updateScheduleNextTrigger(scriptName, timestamp) {
|
|
92
|
+
throw new Error('Method updateScheduleNextTrigger must be implemented by subclass');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* List all schedules
|
|
97
|
+
*
|
|
98
|
+
* @param {Object} [options] - Query options
|
|
99
|
+
* @param {boolean} [options.enabledOnly] - Only return enabled schedules
|
|
100
|
+
* @returns {Promise<Array>} Array of schedule records
|
|
101
|
+
* @abstract
|
|
102
|
+
*/
|
|
103
|
+
async listSchedules(options = {}) {
|
|
104
|
+
throw new Error('Method listSchedules must be implemented by subclass');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
module.exports = { ScriptScheduleRepositoryInterface };
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
const { prisma } = require('../../database/prisma');
|
|
2
|
+
const {
|
|
3
|
+
ScriptScheduleRepositoryInterface,
|
|
4
|
+
} = require('./script-schedule-repository-interface');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* MongoDB Script Schedule Repository Adapter
|
|
8
|
+
* Handles script schedule persistence using Prisma with MongoDB
|
|
9
|
+
*
|
|
10
|
+
* MongoDB-specific characteristics:
|
|
11
|
+
* - IDs are strings with @db.ObjectId
|
|
12
|
+
* - scriptName has unique index
|
|
13
|
+
* - Supports upsert operations natively
|
|
14
|
+
*/
|
|
15
|
+
class ScriptScheduleRepositoryMongo extends ScriptScheduleRepositoryInterface {
|
|
16
|
+
constructor() {
|
|
17
|
+
super();
|
|
18
|
+
this.prisma = prisma;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Find a schedule by script name
|
|
23
|
+
*
|
|
24
|
+
* @param {string} scriptName - The script name
|
|
25
|
+
* @returns {Promise<Object|null>} Schedule record or null if not found
|
|
26
|
+
*/
|
|
27
|
+
async findScheduleByScriptName(scriptName) {
|
|
28
|
+
const schedule = await this.prisma.scriptSchedule.findUnique({
|
|
29
|
+
where: { scriptName },
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
return schedule;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Create or update a schedule (upsert)
|
|
37
|
+
*
|
|
38
|
+
* @param {Object} params - Schedule parameters
|
|
39
|
+
* @param {string} params.scriptName - Name of the script
|
|
40
|
+
* @param {boolean} params.enabled - Whether schedule is enabled
|
|
41
|
+
* @param {string} params.cronExpression - Cron expression
|
|
42
|
+
* @param {string} [params.timezone] - Timezone (default 'UTC')
|
|
43
|
+
* @param {string} [params.externalScheduleId] - External scheduler ID (e.g., AWS ARN)
|
|
44
|
+
* @param {string} [params.externalScheduleName] - External scheduler name
|
|
45
|
+
* @returns {Promise<Object>} Created or updated schedule record
|
|
46
|
+
*/
|
|
47
|
+
async upsertSchedule({ scriptName, enabled, cronExpression, timezone, externalScheduleId, externalScheduleName }) {
|
|
48
|
+
const data = {
|
|
49
|
+
enabled,
|
|
50
|
+
cronExpression,
|
|
51
|
+
timezone: timezone || 'UTC',
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Only set external scheduler fields if provided
|
|
55
|
+
if (externalScheduleId !== undefined) data.externalScheduleId = externalScheduleId;
|
|
56
|
+
if (externalScheduleName !== undefined) data.externalScheduleName = externalScheduleName;
|
|
57
|
+
|
|
58
|
+
const schedule = await this.prisma.scriptSchedule.upsert({
|
|
59
|
+
where: { scriptName },
|
|
60
|
+
update: data,
|
|
61
|
+
create: {
|
|
62
|
+
scriptName,
|
|
63
|
+
...data,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
return schedule;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Delete a schedule by script name
|
|
72
|
+
*
|
|
73
|
+
* @param {string} scriptName - The script name
|
|
74
|
+
* @returns {Promise<Object>} Deletion result
|
|
75
|
+
*/
|
|
76
|
+
async deleteSchedule(scriptName) {
|
|
77
|
+
try {
|
|
78
|
+
const schedule = await this.prisma.scriptSchedule.delete({
|
|
79
|
+
where: { scriptName },
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
acknowledged: true,
|
|
84
|
+
deletedCount: 1,
|
|
85
|
+
deleted: schedule,
|
|
86
|
+
};
|
|
87
|
+
} catch (error) {
|
|
88
|
+
// Return 0 count if not found
|
|
89
|
+
if (error.code === 'P2025') {
|
|
90
|
+
return {
|
|
91
|
+
acknowledged: true,
|
|
92
|
+
deletedCount: 0,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Update external scheduler information
|
|
101
|
+
*
|
|
102
|
+
* @param {string} scriptName - The script name
|
|
103
|
+
* @param {Object} externalInfo - External schedule information
|
|
104
|
+
* @param {string} [externalInfo.externalScheduleId] - External scheduler ID (e.g., AWS ARN)
|
|
105
|
+
* @param {string} [externalInfo.externalScheduleName] - External scheduler name
|
|
106
|
+
* @returns {Promise<Object>} Updated schedule record
|
|
107
|
+
*/
|
|
108
|
+
async updateScheduleExternalInfo(scriptName, { externalScheduleId, externalScheduleName }) {
|
|
109
|
+
const data = {};
|
|
110
|
+
if (externalScheduleId !== undefined) data.externalScheduleId = externalScheduleId;
|
|
111
|
+
if (externalScheduleName !== undefined) data.externalScheduleName = externalScheduleName;
|
|
112
|
+
|
|
113
|
+
const schedule = await this.prisma.scriptSchedule.update({
|
|
114
|
+
where: { scriptName },
|
|
115
|
+
data,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
return schedule;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Update last triggered timestamp
|
|
123
|
+
*
|
|
124
|
+
* @param {string} scriptName - The script name
|
|
125
|
+
* @param {Date} [timestamp] - Trigger timestamp (default: now)
|
|
126
|
+
* @returns {Promise<Object>} Updated schedule record
|
|
127
|
+
*/
|
|
128
|
+
async updateScheduleLastTriggered(scriptName, timestamp) {
|
|
129
|
+
const schedule = await this.prisma.scriptSchedule.update({
|
|
130
|
+
where: { scriptName },
|
|
131
|
+
data: {
|
|
132
|
+
lastTriggeredAt: timestamp || new Date(),
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
return schedule;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Update next trigger timestamp
|
|
141
|
+
*
|
|
142
|
+
* @param {string} scriptName - The script name
|
|
143
|
+
* @param {Date} timestamp - Next trigger timestamp
|
|
144
|
+
* @returns {Promise<Object>} Updated schedule record
|
|
145
|
+
*/
|
|
146
|
+
async updateScheduleNextTrigger(scriptName, timestamp) {
|
|
147
|
+
const schedule = await this.prisma.scriptSchedule.update({
|
|
148
|
+
where: { scriptName },
|
|
149
|
+
data: {
|
|
150
|
+
nextTriggerAt: timestamp,
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
return schedule;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* List all schedules
|
|
159
|
+
*
|
|
160
|
+
* @param {Object} [options] - Query options
|
|
161
|
+
* @param {boolean} [options.enabledOnly] - Only return enabled schedules
|
|
162
|
+
* @returns {Promise<Array>} Array of schedule records
|
|
163
|
+
*/
|
|
164
|
+
async listSchedules(options = {}) {
|
|
165
|
+
const where = {};
|
|
166
|
+
if (options.enabledOnly) {
|
|
167
|
+
where.enabled = true;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const schedules = await this.prisma.scriptSchedule.findMany({
|
|
171
|
+
where,
|
|
172
|
+
orderBy: { scriptName: 'asc' },
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
return schedules;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
module.exports = { ScriptScheduleRepositoryMongo };
|