@friggframework/core 2.0.0--canary.522.cbd3d5a.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.
Files changed (225) hide show
  1. package/CHANGELOG.md +67 -66
  2. package/CLAUDE.md +124 -148
  3. package/README.md +130 -165
  4. package/admin-scripts/index.js +16 -30
  5. package/admin-scripts/repositories/{admin-api-key-repository-documentdb.js → admin-process-repository-documentdb.js} +5 -5
  6. package/admin-scripts/repositories/{admin-api-key-repository-factory.js → admin-process-repository-factory.js} +15 -19
  7. package/admin-scripts/repositories/admin-process-repository-interface.js +150 -0
  8. package/admin-scripts/repositories/admin-process-repository-mongo.js +213 -0
  9. package/admin-scripts/repositories/admin-process-repository-postgres.js +251 -0
  10. package/admin-scripts/repositories/script-schedule-repository-factory.js +2 -6
  11. package/admin-scripts/repositories/script-schedule-repository-interface.js +14 -36
  12. package/admin-scripts/repositories/script-schedule-repository-mongo.js +13 -25
  13. package/admin-scripts/repositories/script-schedule-repository-postgres.js +13 -25
  14. package/application/commands/admin-script-commands.js +102 -266
  15. package/application/commands/integration-commands.js +6 -12
  16. package/application/index.js +3 -1
  17. package/assertions/get.js +4 -1
  18. package/associations/association.js +57 -59
  19. package/associations/model.js +41 -41
  20. package/core/CLAUDE.md +156 -222
  21. package/core/Worker.js +1 -5
  22. package/credential/repositories/credential-repository-documentdb.js +1 -71
  23. package/credential/repositories/credential-repository-interface.js +2 -8
  24. package/credential/repositories/credential-repository-mongo.js +4 -45
  25. package/credential/repositories/credential-repository-postgres.js +3 -44
  26. package/credential/repositories/credential-repository.js +4 -6
  27. package/credential/use-cases/get-credential-for-user.js +3 -21
  28. package/credential/use-cases/update-authentication-status.js +2 -5
  29. package/database/MONGODB_TRANSACTION_FIX.md +52 -72
  30. package/database/adapters/lambda-invoker.js +7 -8
  31. package/database/config.js +13 -15
  32. package/database/documentdb-encryption-service.js +13 -29
  33. package/database/documentdb-utils.js +12 -21
  34. package/database/encryption/README.md +36 -53
  35. package/database/encryption/encryption-schema-registry.js +9 -21
  36. package/database/encryption/field-encryption-service.js +4 -15
  37. package/database/encryption/logger.js +2 -3
  38. package/database/encryption/prisma-encryption-extension.js +8 -5
  39. package/database/index.js +2 -4
  40. package/database/models/IndividualUser.js +15 -15
  41. package/database/models/OrganizationUser.js +4 -6
  42. package/database/models/UserModel.js +2 -2
  43. package/database/models/WebsocketConnection.js +1 -4
  44. package/database/mongoose.js +2 -2
  45. package/database/prisma.js +14 -22
  46. package/database/repositories/health-check-repository-documentdb.js +7 -22
  47. package/database/repositories/health-check-repository-factory.js +3 -9
  48. package/database/repositories/health-check-repository-interface.js +5 -15
  49. package/database/repositories/health-check-repository-mongodb.js +6 -9
  50. package/database/repositories/health-check-repository-postgres.js +1 -1
  51. package/database/repositories/migration-status-repository-s3.js +5 -10
  52. package/database/use-cases/check-database-health-use-case.js +2 -3
  53. package/database/use-cases/check-database-state-use-case.js +7 -9
  54. package/database/use-cases/get-database-state-via-worker-use-case.js +12 -15
  55. package/database/use-cases/get-migration-status-use-case.js +2 -4
  56. package/database/use-cases/run-database-migration-use-case.js +9 -41
  57. package/database/use-cases/test-encryption-use-case.js +5 -4
  58. package/database/use-cases/trigger-database-migration-use-case.js +8 -9
  59. package/database/utils/mongodb-collection-utils.js +3 -11
  60. package/database/utils/mongodb-schema-init.js +4 -10
  61. package/database/utils/prisma-runner.js +74 -144
  62. package/database/utils/prisma-schema-parser.js +2 -2
  63. package/docs/PROCESS_MANAGEMENT_QUEUE_SPEC.md +80 -135
  64. package/encrypt/Cryptor.js +2 -8
  65. package/errors/fetch-error.js +1 -1
  66. package/generated/prisma-mongodb/edge.js +16 -59
  67. package/generated/prisma-mongodb/index-browser.js +12 -62
  68. package/generated/prisma-mongodb/index.d.ts +4850 -8136
  69. package/generated/prisma-mongodb/index.js +16 -59
  70. package/generated/prisma-mongodb/package.json +1 -1
  71. package/generated/prisma-mongodb/schema.prisma +33 -75
  72. package/generated/prisma-mongodb/wasm.js +16 -59
  73. package/generated/prisma-postgresql/edge.js +15 -59
  74. package/generated/prisma-postgresql/index-browser.js +11 -62
  75. package/generated/prisma-postgresql/index.d.ts +5963 -8930
  76. package/generated/prisma-postgresql/index.js +15 -59
  77. package/generated/prisma-postgresql/package.json +1 -1
  78. package/generated/prisma-postgresql/schema.prisma +33 -73
  79. package/generated/prisma-postgresql/wasm.js +15 -59
  80. package/handlers/WEBHOOKS.md +81 -104
  81. package/handlers/app-definition-loader.js +1 -1
  82. package/handlers/app-handler-helpers.js +2 -14
  83. package/handlers/backend-utils.js +1 -0
  84. package/handlers/database-migration-handler.js +45 -64
  85. package/handlers/middleware/admin-auth.js +53 -0
  86. package/handlers/routers/HEALTHCHECK.md +135 -170
  87. package/handlers/routers/auth.js +2 -23
  88. package/handlers/routers/db-migration.handler.js +3 -2
  89. package/handlers/routers/db-migration.js +33 -69
  90. package/handlers/routers/health.js +8 -23
  91. package/handlers/routers/integration-defined-routers.js +4 -4
  92. package/handlers/routers/integration-webhook-routers.js +7 -17
  93. package/handlers/routers/websocket.js +3 -9
  94. package/handlers/use-cases/check-integrations-health-use-case.js +6 -13
  95. package/handlers/workers/db-migration.js +26 -54
  96. package/index.js +9 -5
  97. package/integrations/WEBHOOK-QUICKSTART.md +14 -21
  98. package/integrations/index.js +0 -4
  99. package/integrations/integration-base.js +6 -9
  100. package/integrations/integration-router.js +146 -1817
  101. package/integrations/options.js +20 -47
  102. package/integrations/repositories/integration-repository-documentdb.js +24 -53
  103. package/integrations/repositories/integration-repository-factory.js +2 -6
  104. package/integrations/repositories/integration-repository-interface.js +9 -27
  105. package/integrations/repositories/integration-repository-postgres.js +3 -3
  106. package/integrations/repositories/process-repository-factory.js +1 -0
  107. package/integrations/repositories/process-repository-interface.js +5 -9
  108. package/integrations/repositories/process-repository-mongo.js +3 -7
  109. package/integrations/repositories/process-repository-postgres.js +2 -2
  110. package/integrations/tests/doubles/config-capturing-integration.js +8 -9
  111. package/integrations/tests/doubles/dummy-integration-class.js +8 -81
  112. package/integrations/tests/doubles/test-integration-repository.js +11 -51
  113. package/integrations/use-cases/create-integration.js +32 -36
  114. package/integrations/use-cases/create-process.js +9 -20
  115. package/integrations/use-cases/delete-integration-for-user.js +4 -5
  116. package/integrations/use-cases/get-integration-for-user.js +10 -25
  117. package/integrations/use-cases/get-integration-instance-by-definition.js +7 -13
  118. package/integrations/use-cases/get-integrations-for-user.js +1 -4
  119. package/integrations/use-cases/get-possible-integrations.js +1 -1
  120. package/integrations/use-cases/get-process.js +6 -5
  121. package/integrations/use-cases/index.js +1 -3
  122. package/integrations/use-cases/load-integration-context.js +5 -1
  123. package/integrations/use-cases/update-process-state.js +8 -10
  124. package/integrations/utils/map-integration-dto.js +3 -9
  125. package/jest-setup.js +1 -1
  126. package/jest-teardown.js +1 -1
  127. package/lambda/TimeoutCatcher.js +30 -32
  128. package/lambda/index.js +1 -1
  129. package/logs/index.js +3 -3
  130. package/modules/module.js +1 -3
  131. package/modules/repositories/module-repository-documentdb.js +48 -114
  132. package/modules/repositories/module-repository-interface.js +0 -13
  133. package/modules/repositories/module-repository-mongo.js +6 -46
  134. package/modules/repositories/module-repository-postgres.js +6 -48
  135. package/modules/repositories/module-repository.js +1 -34
  136. package/modules/requester/api-key.js +2 -0
  137. package/modules/requester/basic.js +1 -0
  138. package/modules/requester/oauth-2.js +2 -3
  139. package/modules/test/mock-api/definition.js +10 -15
  140. package/modules/test/mock-api/mocks/hubspot.js +36 -36
  141. package/modules/tests/doubles/test-module-factory.js +4 -10
  142. package/modules/tests/doubles/test-module-repository.js +1 -1
  143. package/modules/use-cases/get-entities-for-user.js +1 -1
  144. package/modules/use-cases/get-entity-options-by-id.js +6 -8
  145. package/modules/use-cases/get-module.js +9 -12
  146. package/modules/use-cases/process-authorization-callback.js +6 -12
  147. package/modules/use-cases/refresh-entity-options.js +6 -8
  148. package/modules/use-cases/test-module-auth.js +6 -8
  149. package/modules/utils/map-module-dto.js +2 -2
  150. package/package.json +5 -7
  151. package/prisma-mongodb/schema.prisma +33 -75
  152. package/prisma-postgresql/schema.prisma +33 -73
  153. package/queues/queuer-util.js +1 -5
  154. package/syncs/model.js +51 -51
  155. package/syncs/repositories/sync-repository-documentdb.js +19 -39
  156. package/syncs/repositories/sync-repository-interface.js +2 -6
  157. package/syncs/repositories/sync-repository-postgres.js +13 -19
  158. package/syncs/sync.js +100 -104
  159. package/token/repositories/token-repository-factory.js +3 -1
  160. package/types/assertions/index.d.ts +72 -72
  161. package/types/associations/index.d.ts +57 -57
  162. package/types/core/index.d.ts +53 -59
  163. package/types/database/index.d.ts +2 -2
  164. package/types/encrypt/index.d.ts +3 -3
  165. package/types/errors/index.d.ts +54 -61
  166. package/types/eslint-config/index.d.ts +40 -40
  167. package/types/integrations/index.d.ts +183 -185
  168. package/types/lambda/index.d.ts +26 -26
  169. package/types/logs/index.d.ts +4 -4
  170. package/types/module-plugin/index.d.ts +237 -239
  171. package/types/prettier-config/index.d.ts +5 -5
  172. package/types/syncs/index.d.ts +108 -102
  173. package/types/test-environment/index.d.ts +14 -14
  174. package/types/tsconfig.json +93 -95
  175. package/user/tests/doubles/test-user-repository.js +2 -5
  176. package/user/use-cases/authenticate-user.js +4 -2
  177. package/user/use-cases/authenticate-with-shared-secret.js +1 -1
  178. package/user/use-cases/create-individual-user.js +7 -8
  179. package/user/use-cases/create-organization-user.js +1 -1
  180. package/user/use-cases/create-token-for-user-id.js +1 -1
  181. package/user/use-cases/get-user-from-adopter-jwt.js +2 -0
  182. package/user/use-cases/get-user-from-bearer-token.js +3 -7
  183. package/user/use-cases/get-user-from-x-frigg-headers.js +11 -14
  184. package/user/use-cases/login-user.js +8 -8
  185. package/user/user.js +4 -18
  186. package/utils/backend-path.js +2 -2
  187. package/utils/index.js +1 -4
  188. package/websocket/repositories/websocket-connection-repository-documentdb.js +8 -21
  189. package/websocket/repositories/websocket-connection-repository-mongo.js +4 -8
  190. package/websocket/repositories/websocket-connection-repository-postgres.js +4 -8
  191. package/websocket/repositories/websocket-connection-repository.js +4 -8
  192. package/admin-scripts/repositories/admin-api-key-repository-interface.js +0 -121
  193. package/admin-scripts/repositories/admin-api-key-repository-mongo.js +0 -155
  194. package/admin-scripts/repositories/admin-api-key-repository-postgres.js +0 -189
  195. package/admin-scripts/repositories/script-execution-repository-documentdb.js +0 -21
  196. package/admin-scripts/repositories/script-execution-repository-factory.js +0 -55
  197. package/admin-scripts/repositories/script-execution-repository-interface.js +0 -193
  198. package/admin-scripts/repositories/script-execution-repository-mongo.js +0 -278
  199. package/admin-scripts/repositories/script-execution-repository-postgres.js +0 -320
  200. package/credential/credential-router.js +0 -262
  201. package/credential/use-cases/delete-credential-for-user.js +0 -50
  202. package/credential/use-cases/list-credentials-for-user.js +0 -31
  203. package/credential/use-cases/reauthorize-credential.js +0 -103
  204. package/handlers/routers/admin.js +0 -450
  205. package/handlers/routers/docs.js +0 -180
  206. package/handlers/routers/middleware/loadUser.js +0 -39
  207. package/handlers/routers/middleware/requireAdmin.js +0 -41
  208. package/handlers/routers/middleware/requireLoggedInUser.js +0 -19
  209. package/integrations/use-cases/execute-proxy-request.js +0 -564
  210. package/modules/domain/entities/AuthorizationSession.js +0 -131
  211. package/modules/domain/entities/index.js +0 -10
  212. package/modules/repositories/authorization-session-repository-factory.js +0 -55
  213. package/modules/repositories/authorization-session-repository-interface.js +0 -75
  214. package/modules/repositories/authorization-session-repository-mongo.js +0 -169
  215. package/modules/repositories/authorization-session-repository-postgres.js +0 -170
  216. package/modules/use-cases/delete-module-entity.js +0 -23
  217. package/modules/use-cases/get-authorization-requirements.js +0 -110
  218. package/modules/use-cases/get-module-entity-by-id.js +0 -16
  219. package/modules/use-cases/process-authorization-step.js +0 -160
  220. package/modules/use-cases/start-authorization-session.js +0 -86
  221. package/modules/use-cases/update-module-entity.js +0 -27
  222. package/openapi/openapi-spec-generator.js +0 -370
  223. package/openapi/openapi-v1.yaml +0 -1360
  224. package/openapi/openapi-v2.yaml +0 -1535
  225. package/user/use-cases/delete-user.js +0 -47
@@ -1,278 +0,0 @@
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 };
@@ -1,320 +0,0 @@
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 };