@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,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Script Execution Repository Interface
|
|
3
|
+
* Abstract base class defining the contract for script execution 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 executions track the lifecycle of admin script runs, including:
|
|
11
|
+
* - Input parameters and output results
|
|
12
|
+
* - Execution status and error details
|
|
13
|
+
* - Performance metrics
|
|
14
|
+
* - Audit trail (who triggered, when, from where)
|
|
15
|
+
* - Real-time logs
|
|
16
|
+
*
|
|
17
|
+
* @abstract
|
|
18
|
+
*/
|
|
19
|
+
class ScriptExecutionRepositoryInterface {
|
|
20
|
+
/**
|
|
21
|
+
* Create a new script execution record
|
|
22
|
+
*
|
|
23
|
+
* @param {Object} params - Execution creation parameters
|
|
24
|
+
* @param {string} params.scriptName - Name of the script being executed
|
|
25
|
+
* @param {string} [params.scriptVersion] - Version of the script
|
|
26
|
+
* @param {string} params.trigger - Trigger type ('MANUAL', 'SCHEDULED', 'QUEUE', 'WEBHOOK')
|
|
27
|
+
* @param {string} [params.mode] - Execution mode ('sync' or 'async', default 'async')
|
|
28
|
+
* @param {Object} [params.input] - Input parameters for the script
|
|
29
|
+
* @param {Object} [params.audit] - Audit information
|
|
30
|
+
* @param {string} [params.audit.apiKeyName] - Name of API key used
|
|
31
|
+
* @param {string} [params.audit.apiKeyLast4] - Last 4 chars of API key
|
|
32
|
+
* @param {string} [params.audit.ipAddress] - IP address of requester
|
|
33
|
+
* @returns {Promise<Object>} The created execution record
|
|
34
|
+
* @abstract
|
|
35
|
+
*/
|
|
36
|
+
async createExecution({
|
|
37
|
+
scriptName,
|
|
38
|
+
scriptVersion,
|
|
39
|
+
trigger,
|
|
40
|
+
mode,
|
|
41
|
+
input,
|
|
42
|
+
audit,
|
|
43
|
+
}) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
'Method createExecution must be implemented by subclass'
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Find an execution by its ID
|
|
51
|
+
*
|
|
52
|
+
* @param {string|number} id - The execution ID
|
|
53
|
+
* @returns {Promise<Object|null>} The execution record or null if not found
|
|
54
|
+
* @abstract
|
|
55
|
+
*/
|
|
56
|
+
async findExecutionById(id) {
|
|
57
|
+
throw new Error(
|
|
58
|
+
'Method findExecutionById must be implemented by subclass'
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Find all executions for a specific script
|
|
64
|
+
*
|
|
65
|
+
* @param {string} scriptName - The script name to filter by
|
|
66
|
+
* @param {Object} [options] - Query options
|
|
67
|
+
* @param {number} [options.limit] - Maximum number of results
|
|
68
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
69
|
+
* @param {string} [options.sortBy] - Field to sort by
|
|
70
|
+
* @param {string} [options.sortOrder] - Sort order ('asc' or 'desc')
|
|
71
|
+
* @returns {Promise<Array>} Array of execution records
|
|
72
|
+
* @abstract
|
|
73
|
+
*/
|
|
74
|
+
async findExecutionsByScriptName(scriptName, options = {}) {
|
|
75
|
+
throw new Error(
|
|
76
|
+
'Method findExecutionsByScriptName must be implemented by subclass'
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Find all executions with a specific status
|
|
82
|
+
*
|
|
83
|
+
* @param {string} status - Status to filter by ('PENDING', 'RUNNING', 'COMPLETED', 'FAILED', 'TIMEOUT', 'CANCELLED')
|
|
84
|
+
* @param {Object} [options] - Query options
|
|
85
|
+
* @param {number} [options.limit] - Maximum number of results
|
|
86
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
87
|
+
* @param {string} [options.sortBy] - Field to sort by
|
|
88
|
+
* @param {string} [options.sortOrder] - Sort order ('asc' or 'desc')
|
|
89
|
+
* @returns {Promise<Array>} Array of execution records
|
|
90
|
+
* @abstract
|
|
91
|
+
*/
|
|
92
|
+
async findExecutionsByStatus(status, options = {}) {
|
|
93
|
+
throw new Error(
|
|
94
|
+
'Method findExecutionsByStatus must be implemented by subclass'
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Update the status of an execution
|
|
100
|
+
*
|
|
101
|
+
* @param {string|number} id - The execution ID
|
|
102
|
+
* @param {string} status - New status value
|
|
103
|
+
* @returns {Promise<Object>} Updated execution record
|
|
104
|
+
* @abstract
|
|
105
|
+
*/
|
|
106
|
+
async updateExecutionStatus(id, status) {
|
|
107
|
+
throw new Error(
|
|
108
|
+
'Method updateExecutionStatus must be implemented by subclass'
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Update the output result of an execution
|
|
114
|
+
*
|
|
115
|
+
* @param {string|number} id - The execution ID
|
|
116
|
+
* @param {Object} output - Output data from the script
|
|
117
|
+
* @returns {Promise<Object>} Updated execution record
|
|
118
|
+
* @abstract
|
|
119
|
+
*/
|
|
120
|
+
async updateExecutionOutput(id, output) {
|
|
121
|
+
throw new Error(
|
|
122
|
+
'Method updateExecutionOutput must be implemented by subclass'
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Update the error details of a failed execution
|
|
128
|
+
*
|
|
129
|
+
* @param {string|number} id - The execution ID
|
|
130
|
+
* @param {Object} error - Error information
|
|
131
|
+
* @param {string} error.name - Error name/type
|
|
132
|
+
* @param {string} error.message - Error message
|
|
133
|
+
* @param {string} [error.stack] - Error stack trace
|
|
134
|
+
* @returns {Promise<Object>} Updated execution record
|
|
135
|
+
* @abstract
|
|
136
|
+
*/
|
|
137
|
+
async updateExecutionError(id, error) {
|
|
138
|
+
throw new Error(
|
|
139
|
+
'Method updateExecutionError must be implemented by subclass'
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Update the performance metrics of an execution
|
|
145
|
+
*
|
|
146
|
+
* @param {string|number} id - The execution ID
|
|
147
|
+
* @param {Object} metrics - Performance metrics
|
|
148
|
+
* @param {Date} [metrics.startTime] - Execution start time
|
|
149
|
+
* @param {Date} [metrics.endTime] - Execution end time
|
|
150
|
+
* @param {number} [metrics.durationMs] - Duration in milliseconds
|
|
151
|
+
* @returns {Promise<Object>} Updated execution record
|
|
152
|
+
* @abstract
|
|
153
|
+
*/
|
|
154
|
+
async updateExecutionMetrics(id, metrics) {
|
|
155
|
+
throw new Error(
|
|
156
|
+
'Method updateExecutionMetrics must be implemented by subclass'
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Append a log entry to an execution's log array
|
|
162
|
+
*
|
|
163
|
+
* @param {string|number} id - The execution ID
|
|
164
|
+
* @param {Object} logEntry - Log entry to append
|
|
165
|
+
* @param {string} logEntry.level - Log level ('debug', 'info', 'warn', 'error')
|
|
166
|
+
* @param {string} logEntry.message - Log message
|
|
167
|
+
* @param {Object} [logEntry.data] - Additional log data
|
|
168
|
+
* @param {string} logEntry.timestamp - ISO timestamp
|
|
169
|
+
* @returns {Promise<Object>} Updated execution record
|
|
170
|
+
* @abstract
|
|
171
|
+
*/
|
|
172
|
+
async appendExecutionLog(id, logEntry) {
|
|
173
|
+
throw new Error(
|
|
174
|
+
'Method appendExecutionLog must be implemented by subclass'
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Delete all executions older than a specific date
|
|
180
|
+
* Used for cleanup and retention policies
|
|
181
|
+
*
|
|
182
|
+
* @param {Date} date - Delete executions older than this date
|
|
183
|
+
* @returns {Promise<Object>} Deletion result with count
|
|
184
|
+
* @abstract
|
|
185
|
+
*/
|
|
186
|
+
async deleteExecutionsOlderThan(date) {
|
|
187
|
+
throw new Error(
|
|
188
|
+
'Method deleteExecutionsOlderThan must be implemented by subclass'
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
module.exports = { ScriptExecutionRepositoryInterface };
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
const { prisma } = require('../../database/prisma');
|
|
2
|
+
const {
|
|
3
|
+
ScriptExecutionRepositoryInterface,
|
|
4
|
+
} = require('./script-execution-repository-interface');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* MongoDB Script Execution Repository Adapter
|
|
8
|
+
* Handles script execution persistence using Prisma with MongoDB
|
|
9
|
+
*
|
|
10
|
+
* MongoDB-specific characteristics:
|
|
11
|
+
* - IDs are strings with @db.ObjectId
|
|
12
|
+
* - logs field is Json[] - supports push operations
|
|
13
|
+
* - Audit fields stored as separate columns
|
|
14
|
+
*/
|
|
15
|
+
class ScriptExecutionRepositoryMongo extends ScriptExecutionRepositoryInterface {
|
|
16
|
+
constructor() {
|
|
17
|
+
super();
|
|
18
|
+
this.prisma = prisma;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Create a new script execution record
|
|
23
|
+
*
|
|
24
|
+
* @param {Object} params - Execution creation parameters
|
|
25
|
+
* @param {string} params.scriptName - Name of the script being executed
|
|
26
|
+
* @param {string} [params.scriptVersion] - Version of the script
|
|
27
|
+
* @param {string} params.trigger - Trigger type
|
|
28
|
+
* @param {string} [params.mode] - Execution mode ('sync' or 'async', default 'async')
|
|
29
|
+
* @param {Object} [params.input] - Input parameters for the script
|
|
30
|
+
* @param {Object} [params.audit] - Audit information
|
|
31
|
+
* @param {string} [params.audit.apiKeyName] - Name of API key used
|
|
32
|
+
* @param {string} [params.audit.apiKeyLast4] - Last 4 chars of API key
|
|
33
|
+
* @param {string} [params.audit.ipAddress] - IP address of requester
|
|
34
|
+
* @returns {Promise<Object>} The created execution record
|
|
35
|
+
*/
|
|
36
|
+
async createExecution({
|
|
37
|
+
scriptName,
|
|
38
|
+
scriptVersion,
|
|
39
|
+
trigger,
|
|
40
|
+
mode,
|
|
41
|
+
input,
|
|
42
|
+
audit,
|
|
43
|
+
}) {
|
|
44
|
+
const data = {
|
|
45
|
+
scriptName,
|
|
46
|
+
scriptVersion,
|
|
47
|
+
trigger,
|
|
48
|
+
mode: mode || 'async',
|
|
49
|
+
input,
|
|
50
|
+
logs: [],
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// Map audit object to separate fields
|
|
54
|
+
if (audit) {
|
|
55
|
+
if (audit.apiKeyName) data.auditApiKeyName = audit.apiKeyName;
|
|
56
|
+
if (audit.apiKeyLast4) data.auditApiKeyLast4 = audit.apiKeyLast4;
|
|
57
|
+
if (audit.ipAddress) data.auditIpAddress = audit.ipAddress;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const execution = await this.prisma.scriptExecution.create({
|
|
61
|
+
data,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
return execution;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Find an execution by its ID
|
|
69
|
+
*
|
|
70
|
+
* @param {string} id - The execution ID
|
|
71
|
+
* @returns {Promise<Object|null>} The execution record or null if not found
|
|
72
|
+
*/
|
|
73
|
+
async findExecutionById(id) {
|
|
74
|
+
const execution = await this.prisma.scriptExecution.findUnique({
|
|
75
|
+
where: { id },
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
return execution;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Find all executions for a specific script
|
|
83
|
+
*
|
|
84
|
+
* @param {string} scriptName - The script name to filter by
|
|
85
|
+
* @param {Object} [options] - Query options
|
|
86
|
+
* @param {number} [options.limit] - Maximum number of results
|
|
87
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
88
|
+
* @param {string} [options.sortBy] - Field to sort by
|
|
89
|
+
* @param {string} [options.sortOrder] - Sort order ('asc' or 'desc')
|
|
90
|
+
* @returns {Promise<Array>} Array of execution records
|
|
91
|
+
*/
|
|
92
|
+
async findExecutionsByScriptName(scriptName, options = {}) {
|
|
93
|
+
const {
|
|
94
|
+
limit,
|
|
95
|
+
offset,
|
|
96
|
+
sortBy = 'createdAt',
|
|
97
|
+
sortOrder = 'desc',
|
|
98
|
+
} = options;
|
|
99
|
+
|
|
100
|
+
const executions = await this.prisma.scriptExecution.findMany({
|
|
101
|
+
where: { scriptName },
|
|
102
|
+
orderBy: { [sortBy]: sortOrder },
|
|
103
|
+
take: limit,
|
|
104
|
+
skip: offset,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
return executions;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Find all executions with a specific status
|
|
112
|
+
*
|
|
113
|
+
* @param {string} status - Status to filter by
|
|
114
|
+
* @param {Object} [options] - Query options
|
|
115
|
+
* @param {number} [options.limit] - Maximum number of results
|
|
116
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
117
|
+
* @param {string} [options.sortBy] - Field to sort by
|
|
118
|
+
* @param {string} [options.sortOrder] - Sort order ('asc' or 'desc')
|
|
119
|
+
* @returns {Promise<Array>} Array of execution records
|
|
120
|
+
*/
|
|
121
|
+
async findExecutionsByStatus(status, options = {}) {
|
|
122
|
+
const {
|
|
123
|
+
limit,
|
|
124
|
+
offset,
|
|
125
|
+
sortBy = 'createdAt',
|
|
126
|
+
sortOrder = 'desc',
|
|
127
|
+
} = options;
|
|
128
|
+
|
|
129
|
+
const executions = await this.prisma.scriptExecution.findMany({
|
|
130
|
+
where: { status },
|
|
131
|
+
orderBy: { [sortBy]: sortOrder },
|
|
132
|
+
take: limit,
|
|
133
|
+
skip: offset,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
return executions;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Update the status of an execution
|
|
141
|
+
*
|
|
142
|
+
* @param {string} id - The execution ID
|
|
143
|
+
* @param {string} status - New status value
|
|
144
|
+
* @returns {Promise<Object>} Updated execution record
|
|
145
|
+
*/
|
|
146
|
+
async updateExecutionStatus(id, status) {
|
|
147
|
+
const execution = await this.prisma.scriptExecution.update({
|
|
148
|
+
where: { id },
|
|
149
|
+
data: { status },
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
return execution;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Update the output result of an execution
|
|
157
|
+
*
|
|
158
|
+
* @param {string} id - The execution ID
|
|
159
|
+
* @param {Object} output - Output data from the script
|
|
160
|
+
* @returns {Promise<Object>} Updated execution record
|
|
161
|
+
*/
|
|
162
|
+
async updateExecutionOutput(id, output) {
|
|
163
|
+
const execution = await this.prisma.scriptExecution.update({
|
|
164
|
+
where: { id },
|
|
165
|
+
data: { output },
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
return execution;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Update the error details of a failed execution
|
|
173
|
+
*
|
|
174
|
+
* @param {string} id - The execution ID
|
|
175
|
+
* @param {Object} error - Error information
|
|
176
|
+
* @param {string} error.name - Error name/type
|
|
177
|
+
* @param {string} error.message - Error message
|
|
178
|
+
* @param {string} [error.stack] - Error stack trace
|
|
179
|
+
* @returns {Promise<Object>} Updated execution record
|
|
180
|
+
*/
|
|
181
|
+
async updateExecutionError(id, error) {
|
|
182
|
+
const execution = await this.prisma.scriptExecution.update({
|
|
183
|
+
where: { id },
|
|
184
|
+
data: {
|
|
185
|
+
errorName: error.name,
|
|
186
|
+
errorMessage: error.message,
|
|
187
|
+
errorStack: error.stack,
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
return execution;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Update the performance metrics of an execution
|
|
196
|
+
*
|
|
197
|
+
* @param {string} id - The execution ID
|
|
198
|
+
* @param {Object} metrics - Performance metrics
|
|
199
|
+
* @param {Date} [metrics.startTime] - Execution start time
|
|
200
|
+
* @param {Date} [metrics.endTime] - Execution end time
|
|
201
|
+
* @param {number} [metrics.durationMs] - Duration in milliseconds
|
|
202
|
+
* @returns {Promise<Object>} Updated execution record
|
|
203
|
+
*/
|
|
204
|
+
async updateExecutionMetrics(id, metrics) {
|
|
205
|
+
const data = {};
|
|
206
|
+
if (metrics.startTime !== undefined)
|
|
207
|
+
data.metricsStartTime = metrics.startTime;
|
|
208
|
+
if (metrics.endTime !== undefined)
|
|
209
|
+
data.metricsEndTime = metrics.endTime;
|
|
210
|
+
if (metrics.durationMs !== undefined)
|
|
211
|
+
data.metricsDurationMs = metrics.durationMs;
|
|
212
|
+
|
|
213
|
+
const execution = await this.prisma.scriptExecution.update({
|
|
214
|
+
where: { id },
|
|
215
|
+
data,
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
return execution;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Append a log entry to an execution's log array
|
|
223
|
+
*
|
|
224
|
+
* @param {string} id - The execution ID
|
|
225
|
+
* @param {Object} logEntry - Log entry to append
|
|
226
|
+
* @param {string} logEntry.level - Log level ('debug', 'info', 'warn', 'error')
|
|
227
|
+
* @param {string} logEntry.message - Log message
|
|
228
|
+
* @param {Object} [logEntry.data] - Additional log data
|
|
229
|
+
* @param {string} logEntry.timestamp - ISO timestamp
|
|
230
|
+
* @returns {Promise<Object>} Updated execution record
|
|
231
|
+
*/
|
|
232
|
+
async appendExecutionLog(id, logEntry) {
|
|
233
|
+
// Get current execution
|
|
234
|
+
const execution = await this.prisma.scriptExecution.findUnique({
|
|
235
|
+
where: { id },
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
if (!execution) {
|
|
239
|
+
throw new Error(`Execution ${id} not found`);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Append log entry to logs array (copy to avoid mutating original)
|
|
243
|
+
const logs = Array.isArray(execution.logs) ? [...execution.logs] : [];
|
|
244
|
+
logs.push(logEntry);
|
|
245
|
+
|
|
246
|
+
// Update with new logs array
|
|
247
|
+
const updated = await this.prisma.scriptExecution.update({
|
|
248
|
+
where: { id },
|
|
249
|
+
data: { logs },
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
return updated;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Delete all executions older than a specific date
|
|
257
|
+
* Used for cleanup and retention policies
|
|
258
|
+
*
|
|
259
|
+
* @param {Date} date - Delete executions older than this date
|
|
260
|
+
* @returns {Promise<Object>} Deletion result with count
|
|
261
|
+
*/
|
|
262
|
+
async deleteExecutionsOlderThan(date) {
|
|
263
|
+
const result = await this.prisma.scriptExecution.deleteMany({
|
|
264
|
+
where: {
|
|
265
|
+
createdAt: {
|
|
266
|
+
lt: date,
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
return {
|
|
272
|
+
acknowledged: true,
|
|
273
|
+
deletedCount: result.count,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
module.exports = { ScriptExecutionRepositoryMongo };
|