@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
@@ -17,9 +17,9 @@ schema.pre('save', async function () {
17
17
  this.hashword = await bcrypt.hashSync(
18
18
  this.hashword,
19
19
  parseInt(this.schema.statics.decimals)
20
- );
20
+ )
21
21
  }
22
- });
22
+ })
23
23
 
24
24
  schema.static({
25
25
  decimals: 10,
@@ -31,17 +31,18 @@ schema.static({
31
31
  );
32
32
  delete options.password;
33
33
  }
34
- return this.findOneAndUpdate({ _id: id }, options, {
35
- new: true,
36
- useFindAndModify: true,
37
- });
34
+ return this.findOneAndUpdate(
35
+ {_id: id},
36
+ options,
37
+ {new: true, useFindAndModify: true}
38
+ );
38
39
  },
39
40
  getUserByUsername: async function (username) {
40
41
  let getByUser;
41
- try {
42
- getByUser = await this.find({ username });
42
+ try{
43
+ getByUser = await this.find({username});
43
44
  } catch (e) {
44
- console.log('oops');
45
+ console.log('oops')
45
46
  }
46
47
 
47
48
  if (getByUser.length > 1) {
@@ -63,14 +64,13 @@ schema.static({
63
64
  );
64
65
  }
65
66
 
67
+
66
68
  if (getByUser.length === 1) {
67
69
  return getByUser[0];
68
70
  }
69
- },
70
- });
71
+ }
72
+ })
71
73
 
72
- const IndividualUser =
73
- Parent.discriminators?.IndividualUser ||
74
- Parent.discriminator(collectionName, schema);
74
+ const IndividualUser = Parent.discriminators?.IndividualUser || Parent.discriminator(collectionName, schema);
75
75
 
76
- module.exports = { IndividualUser };
76
+ module.exports = {IndividualUser};
@@ -21,11 +21,9 @@ schema.static({
21
21
  if (getByUser.length === 1) {
22
22
  return getByUser[0];
23
23
  }
24
- },
25
- });
24
+ }
25
+ })
26
26
 
27
- const OrganizationUser =
28
- Parent.discriminators?.OrganizationUser ||
29
- Parent.discriminator(collectionName, schema);
27
+ const OrganizationUser = Parent.discriminators?.OrganizationUser || Parent.discriminator(collectionName, schema);
30
28
 
31
- module.exports = { OrganizationUser };
29
+ module.exports = {OrganizationUser};
@@ -1,7 +1,7 @@
1
1
  const { mongoose } = require('../mongoose');
2
2
 
3
- const schema = new mongoose.Schema({}, { timestamps: true });
3
+ const schema = new mongoose.Schema({}, {timestamps: true})
4
4
 
5
- const UserModel = mongoose.models.User || mongoose.model('User', schema);
5
+ const UserModel = mongoose.models.User || mongoose.model('User',schema)
6
6
 
7
7
  module.exports = { UserModel: UserModel };
@@ -31,10 +31,7 @@ schema.statics.getActiveConnections = async function () {
31
31
  });
32
32
  await apigwManagementApi.send(command);
33
33
  } catch (error) {
34
- if (
35
- error.statusCode === 410 ||
36
- error.$metadata?.httpStatusCode === 410
37
- ) {
34
+ if (error.statusCode === 410 || error.$metadata?.httpStatusCode === 410) {
38
35
  console.log(`Stale connection ${conn.connectionId}`);
39
36
  await this.deleteOne({
40
37
  connectionId: conn.connectionId,
@@ -1,5 +1,5 @@
1
1
  const mongoose = require('mongoose');
2
2
  mongoose.set('strictQuery', false);
3
3
  module.exports = {
4
- mongoose,
5
- };
4
+ mongoose
5
+ }
@@ -1,9 +1,7 @@
1
1
  const {
2
2
  createEncryptionExtension,
3
3
  } = require('./encryption/prisma-encryption-extension');
4
- const {
5
- loadCustomEncryptionSchema,
6
- } = require('./encryption/encryption-schema-registry');
4
+ const { loadCustomEncryptionSchema } = require('./encryption/encryption-schema-registry');
7
5
  const { logger } = require('./encryption/logger');
8
6
  const { Cryptor } = require('../encrypt/Cryptor');
9
7
  const config = require('./config');
@@ -12,7 +10,7 @@ const config = require('./config');
12
10
  * Ensures DATABASE_URL is set for MongoDB connections
13
11
  * Falls back to MONGO_URI if DATABASE_URL is not set
14
12
  * Infrastructure layer concern - maps legacy MONGO_URI to Prisma's expected DATABASE_URL
15
- *
13
+ *
16
14
  * Note: This should only be called when DB_TYPE is 'mongodb' or 'documentdb'
17
15
  */
18
16
  function ensureMongoDbUrl() {
@@ -24,9 +22,7 @@ function ensureMongoDbUrl() {
24
22
  // Fallback to MONGO_URI for backwards compatibility with DocumentDB deployments
25
23
  if (process.env.MONGO_URI && process.env.MONGO_URI.trim()) {
26
24
  process.env.DATABASE_URL = process.env.MONGO_URI;
27
- logger.debug(
28
- 'Using MONGO_URI as DATABASE_URL for Mongo-compatible connection'
29
- );
25
+ logger.debug('Using MONGO_URI as DATABASE_URL for Mongo-compatible connection');
30
26
  return;
31
27
  }
32
28
 
@@ -52,7 +48,7 @@ function getEncryptionConfig() {
52
48
  if (!hasKMS && !hasAES) {
53
49
  logger.warn(
54
50
  'No encryption keys configured (KMS_KEY_ARN or AES_KEY_ID). ' +
55
- 'Field-level encryption disabled. Set STAGE=production and configure keys to enable.'
51
+ 'Field-level encryption disabled. Set STAGE=production and configure keys to enable.'
56
52
  );
57
53
  return { enabled: false };
58
54
  }
@@ -84,9 +80,7 @@ const prismaClientSingleton = () => {
84
80
  }
85
81
 
86
82
  throw new Error(
87
- `Cannot find Prisma client for ${dbType}. Tried paths: ${paths.join(
88
- ', '
89
- )}`
83
+ `Cannot find Prisma client for ${dbType}. Tried paths: ${paths.join(', ')}`
90
84
  );
91
85
  };
92
86
 
@@ -131,7 +125,10 @@ const prismaClientSingleton = () => {
131
125
  `Field-level encryption enabled using ${encryptionConfig.method.toUpperCase()}`
132
126
  );
133
127
  } catch (error) {
134
- logger.error('Failed to initialize encryption extension:', error);
128
+ logger.error(
129
+ 'Failed to initialize encryption extension:',
130
+ error
131
+ );
135
132
  logger.warn('Continuing without encryption...');
136
133
  }
137
134
  } else {
@@ -152,14 +149,11 @@ function getPrismaClient() {
152
149
  }
153
150
 
154
151
  // Export a getter for lazy initialization
155
- const prisma = new Proxy(
156
- {},
157
- {
158
- get(target, prop) {
159
- return getPrismaClient()[prop];
160
- },
152
+ const prisma = new Proxy({}, {
153
+ get(target, prop) {
154
+ return getPrismaClient()[prop];
161
155
  }
162
- );
156
+ });
163
157
 
164
158
  async function disconnectPrisma() {
165
159
  await getPrismaClient().$disconnect();
@@ -172,9 +166,7 @@ async function connectPrisma() {
172
166
  // Only run for MongoDB/DocumentDB (not PostgreSQL)
173
167
  // This prevents "Cannot create namespace in multi-document transaction" errors
174
168
  if (config.DB_TYPE === 'mongodb' || config.DB_TYPE === 'documentdb') {
175
- const {
176
- initializeMongoDBSchema,
177
- } = require('./utils/mongodb-schema-init');
169
+ const { initializeMongoDBSchema } = require('./utils/mongodb-schema-init');
178
170
  await initializeMongoDBSchema();
179
171
  }
180
172
 
@@ -8,9 +8,7 @@ const {
8
8
  insertOne,
9
9
  deleteOne,
10
10
  } = require('../documentdb-utils');
11
- const {
12
- DocumentDBEncryptionService,
13
- } = require('../documentdb-encryption-service');
11
+ const { DocumentDBEncryptionService } = require('../documentdb-encryption-service');
14
12
 
15
13
  class HealthCheckRepositoryDocumentDB extends HealthCheckRepositoryInterface {
16
14
  /**
@@ -53,10 +51,7 @@ class HealthCheckRepositoryDocumentDB extends HealthCheckRepositoryInterface {
53
51
  const pingStart = Date.now();
54
52
 
55
53
  const timeoutPromise = new Promise((_, reject) =>
56
- setTimeout(
57
- () => reject(new Error('Database ping timeout')),
58
- maxTimeMS
59
- )
54
+ setTimeout(() => reject(new Error('Database ping timeout')), maxTimeMS)
60
55
  );
61
56
 
62
57
  await Promise.race([
@@ -80,14 +75,8 @@ class HealthCheckRepositoryDocumentDB extends HealthCheckRepositoryInterface {
80
75
  'Credential',
81
76
  document
82
77
  );
83
- const insertedId = await insertOne(
84
- this.prisma,
85
- 'Credential',
86
- encryptedDocument
87
- );
88
- const created = await findOne(this.prisma, 'Credential', {
89
- _id: insertedId,
90
- });
78
+ const insertedId = await insertOne(this.prisma, 'Credential', encryptedDocument);
79
+ const created = await findOne(this.prisma, 'Credential', { _id: insertedId });
91
80
 
92
81
  // Decrypt after read
93
82
  const decrypted = await this.encryptionService.decryptFields(
@@ -109,10 +98,7 @@ class HealthCheckRepositoryDocumentDB extends HealthCheckRepositoryInterface {
109
98
  if (!doc) return null;
110
99
 
111
100
  // Decrypt sensitive fields
112
- const decrypted = await this.encryptionService.decryptFields(
113
- 'Credential',
114
- doc
115
- );
101
+ const decrypted = await this.encryptionService.decryptFields('Credential', doc);
116
102
 
117
103
  return {
118
104
  id: fromObjectId(decrypted._id),
@@ -138,12 +124,11 @@ class HealthCheckRepositoryDocumentDB extends HealthCheckRepositoryInterface {
138
124
  const objectId = toObjectId(id);
139
125
  if (!objectId) return false;
140
126
 
141
- const result = await deleteOne(this.prisma, 'Credential', {
142
- _id: objectId,
143
- });
127
+ const result = await deleteOne(this.prisma, 'Credential', { _id: objectId });
144
128
  const deleted = result?.n ?? 0;
145
129
  return deleted > 0;
146
130
  }
147
131
  }
148
132
 
149
133
  module.exports = { HealthCheckRepositoryDocumentDB };
134
+
@@ -1,12 +1,6 @@
1
- const {
2
- HealthCheckRepositoryMongoDB,
3
- } = require('./health-check-repository-mongodb');
4
- const {
5
- HealthCheckRepositoryPostgreSQL,
6
- } = require('./health-check-repository-postgres');
7
- const {
8
- HealthCheckRepositoryDocumentDB,
9
- } = require('./health-check-repository-documentdb');
1
+ const { HealthCheckRepositoryMongoDB } = require('./health-check-repository-mongodb');
2
+ const { HealthCheckRepositoryPostgreSQL } = require('./health-check-repository-postgres');
3
+ const { HealthCheckRepositoryDocumentDB } = require('./health-check-repository-documentdb');
10
4
  const config = require('../config');
11
5
 
12
6
  /**
@@ -19,9 +19,7 @@ class HealthCheckRepositoryInterface {
19
19
  * @abstract
20
20
  */
21
21
  async getDatabaseConnectionState() {
22
- throw new Error(
23
- 'Method getDatabaseConnectionState must be implemented by subclass'
24
- );
22
+ throw new Error('Method getDatabaseConnectionState must be implemented by subclass');
25
23
  }
26
24
 
27
25
  /**
@@ -44,9 +42,7 @@ class HealthCheckRepositoryInterface {
44
42
  * @abstract
45
43
  */
46
44
  async createCredential(credentialData) {
47
- throw new Error(
48
- 'Method createCredential must be implemented by subclass'
49
- );
45
+ throw new Error('Method createCredential must be implemented by subclass');
50
46
  }
51
47
 
52
48
  /**
@@ -57,9 +53,7 @@ class HealthCheckRepositoryInterface {
57
53
  * @abstract
58
54
  */
59
55
  async findCredentialById(id) {
60
- throw new Error(
61
- 'Method findCredentialById must be implemented by subclass'
62
- );
56
+ throw new Error('Method findCredentialById must be implemented by subclass');
63
57
  }
64
58
 
65
59
  /**
@@ -70,9 +64,7 @@ class HealthCheckRepositoryInterface {
70
64
  * @abstract
71
65
  */
72
66
  async getRawCredentialById(id) {
73
- throw new Error(
74
- 'Method getRawCredentialById must be implemented by subclass'
75
- );
67
+ throw new Error('Method getRawCredentialById must be implemented by subclass');
76
68
  }
77
69
 
78
70
  /**
@@ -83,9 +75,7 @@ class HealthCheckRepositoryInterface {
83
75
  * @abstract
84
76
  */
85
77
  async deleteCredential(id) {
86
- throw new Error(
87
- 'Method deleteCredential must be implemented by subclass'
88
- );
78
+ throw new Error('Method deleteCredential must be implemented by subclass');
89
79
  }
90
80
  }
91
81
 
@@ -19,7 +19,7 @@ class HealthCheckRepositoryMongoDB extends HealthCheckRepositoryInterface {
19
19
  async getDatabaseConnectionState() {
20
20
  let isConnected = false;
21
21
  let stateName = 'unknown';
22
-
22
+
23
23
  try {
24
24
  await this.prisma.$runCommandRaw({ ping: 1 });
25
25
  isConnected = true;
@@ -38,22 +38,19 @@ class HealthCheckRepositoryMongoDB extends HealthCheckRepositoryInterface {
38
38
 
39
39
  async pingDatabase(maxTimeMS = 2000) {
40
40
  const pingStart = Date.now();
41
-
41
+
42
42
  // Create a timeout promise that rejects after maxTimeMS
43
- const timeoutPromise = new Promise((_, reject) =>
44
- setTimeout(
45
- () => reject(new Error('Database ping timeout')),
46
- maxTimeMS
47
- )
43
+ const timeoutPromise = new Promise((_, reject) =>
44
+ setTimeout(() => reject(new Error('Database ping timeout')), maxTimeMS)
48
45
  );
49
-
46
+
50
47
  // Race between the database ping and the timeout
51
48
  await Promise.race([
52
49
  prisma.$queryRaw`SELECT 1`.catch(() => {
53
50
  // For MongoDB, use runCommandRaw instead
54
51
  return prisma.$runCommandRaw({ ping: 1 });
55
52
  }),
56
- timeoutPromise,
53
+ timeoutPromise
57
54
  ]);
58
55
 
59
56
  return Date.now() - pingStart;
@@ -18,7 +18,7 @@ class HealthCheckRepositoryPostgreSQL extends HealthCheckRepositoryInterface {
18
18
  async getDatabaseConnectionState() {
19
19
  let isConnected = false;
20
20
  let stateName = 'unknown';
21
-
21
+
22
22
  try {
23
23
  await this.prisma.$queryRaw`SELECT 1`;
24
24
  isConnected = true;
@@ -1,17 +1,13 @@
1
1
  /**
2
2
  * Migration Status Repository - S3 Storage
3
- *
3
+ *
4
4
  * Infrastructure Layer - Hexagonal Architecture
5
- *
5
+ *
6
6
  * Stores migration status in S3 to avoid chicken-and-egg dependency on User/Process tables.
7
7
  * Initial database migrations can't use Process table (requires User FK which doesn't exist yet).
8
8
  */
9
9
 
10
- const {
11
- S3Client,
12
- PutObjectCommand,
13
- GetObjectCommand,
14
- } = require('@aws-sdk/client-s3');
10
+ const { S3Client, PutObjectCommand, GetObjectCommand } = require('@aws-sdk/client-s3');
15
11
  const { randomUUID } = require('crypto');
16
12
 
17
13
  class MigrationStatusRepositoryS3 {
@@ -21,9 +17,7 @@ class MigrationStatusRepositoryS3 {
21
17
  */
22
18
  constructor(bucketName, s3Client = null) {
23
19
  this.bucketName = bucketName;
24
- this.s3Client =
25
- s3Client ||
26
- new S3Client({ region: process.env.AWS_REGION || 'us-east-1' });
20
+ this.s3Client = s3Client || new S3Client({ region: process.env.AWS_REGION || 'us-east-1' });
27
21
  }
28
22
 
29
23
  /**
@@ -140,3 +134,4 @@ class MigrationStatusRepositoryS3 {
140
134
  }
141
135
 
142
136
  module.exports = { MigrationStatusRepositoryS3 };
137
+
@@ -11,8 +11,7 @@ class CheckDatabaseHealthUseCase {
11
11
  * @returns {Promise<{status: string, state: string, responseTime?: number}>}
12
12
  */
13
13
  async execute() {
14
- const { stateName, isConnected } =
15
- await this.repository.getDatabaseConnectionState();
14
+ const { stateName, isConnected } = await this.repository.getDatabaseConnectionState();
16
15
 
17
16
  const result = {
18
17
  status: isConnected ? 'healthy' : 'unhealthy',
@@ -27,4 +26,4 @@ class CheckDatabaseHealthUseCase {
27
26
  }
28
27
  }
29
28
 
30
- module.exports = { CheckDatabaseHealthUseCase };
29
+ module.exports = { CheckDatabaseHealthUseCase };
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Check Database State Use Case
3
- *
3
+ *
4
4
  * Domain logic for checking database state (pending migrations, errors, etc).
5
5
  * Does NOT trigger migrations, just reports current state.
6
- *
6
+ *
7
7
  * Architecture: Hexagonal/Clean
8
8
  * - Use Case (Domain Layer)
9
9
  * - Depends on prismaRunner (Infrastructure abstraction)
@@ -31,7 +31,7 @@ class CheckDatabaseStateUseCase {
31
31
 
32
32
  /**
33
33
  * Execute check migration status
34
- *
34
+ *
35
35
  * @param {string} dbType - Database type (postgresql, mongodb, or documentdb)
36
36
  * @param {string} stage - Deployment stage (default: 'production')
37
37
  * @returns {Promise<Object>} Migration status
@@ -43,9 +43,7 @@ class CheckDatabaseStateUseCase {
43
43
  }
44
44
 
45
45
  if (!['postgresql', 'mongodb', 'documentdb'].includes(dbType)) {
46
- throw new ValidationError(
47
- 'dbType must be postgresql, mongodb, or documentdb'
48
- );
46
+ throw new ValidationError('dbType must be postgresql, mongodb, or documentdb');
49
47
  }
50
48
 
51
49
  console.log(`Checking migration status for ${dbType} in ${stage}`);
@@ -64,13 +62,12 @@ class CheckDatabaseStateUseCase {
64
62
  // Add error if present
65
63
  if (state.error) {
66
64
  response.error = state.error;
67
- response.recommendation =
68
- 'Run POST /db-migrate to initialize database';
65
+ response.recommendation = 'Run POST /admin/db-migrate to initialize database';
69
66
  }
70
67
 
71
68
  // Add recommendation if migrations pending
72
69
  if (!state.upToDate && state.pendingMigrations > 0) {
73
- response.recommendation = `Run POST /db-migrate to apply ${state.pendingMigrations} pending migration(s)`;
70
+ response.recommendation = `Run POST /admin/db-migrate to apply ${state.pendingMigrations} pending migration(s)`;
74
71
  }
75
72
 
76
73
  return response;
@@ -81,3 +78,4 @@ module.exports = {
81
78
  CheckDatabaseStateUseCase,
82
79
  ValidationError,
83
80
  };
81
+
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * Get Database State Via Worker Use Case
3
- *
3
+ *
4
4
  * Domain logic for getting database state by invoking the worker Lambda.
5
5
  * This use case delegates to the worker Lambda which has Prisma CLI installed,
6
6
  * keeping the router Lambda lightweight.
7
- *
7
+ *
8
8
  * Architecture: Hexagonal/Clean
9
9
  * - Use Case (Domain Layer)
10
10
  * - Depends on LambdaInvoker (Infrastructure abstraction)
@@ -13,7 +13,7 @@
13
13
 
14
14
  /**
15
15
  * Domain Use Case: Get database state by invoking worker Lambda
16
- *
16
+ *
17
17
  * This use case delegates database state checking to the worker Lambda,
18
18
  * which has Prisma CLI installed. Keeps the router Lambda lightweight.
19
19
  */
@@ -36,29 +36,26 @@ class GetDatabaseStateViaWorkerUseCase {
36
36
 
37
37
  /**
38
38
  * Execute database state check via worker Lambda
39
- *
39
+ *
40
40
  * @param {string} stage - Deployment stage (prod, dev, etc)
41
41
  * @returns {Promise<Object>} Database state result
42
42
  */
43
43
  async execute(stage = 'production') {
44
44
  const dbType = process.env.DB_TYPE || 'postgresql';
45
45
 
46
- console.log(
47
- `Invoking worker Lambda to check database state: ${this.workerFunctionName}`
48
- );
46
+ console.log(`Invoking worker Lambda to check database state: ${this.workerFunctionName}`);
49
47
 
50
48
  // Invoke worker Lambda with checkStatus action
51
- const result = await this.lambdaInvoker.invoke(
52
- this.workerFunctionName,
53
- {
54
- action: 'checkStatus',
55
- dbType,
56
- stage,
57
- }
58
- );
49
+ const result = await this.lambdaInvoker.invoke(this.workerFunctionName, {
50
+ action: 'checkStatus',
51
+ dbType,
52
+ stage,
53
+ });
59
54
 
60
55
  return result;
61
56
  }
62
57
  }
63
58
 
64
59
  module.exports = { GetDatabaseStateViaWorkerUseCase };
60
+
61
+
@@ -39,10 +39,7 @@ class GetMigrationStatusUseCase {
39
39
 
40
40
  // Get migration status from S3
41
41
  try {
42
- const migrationStatus = await this.migrationStatusRepository.get(
43
- migrationId,
44
- effectiveStage
45
- );
42
+ const migrationStatus = await this.migrationStatusRepository.get(migrationId, effectiveStage);
46
43
  return migrationStatus;
47
44
  } catch (error) {
48
45
  if (error.message.includes('not found')) {
@@ -93,3 +90,4 @@ module.exports = {
93
90
  ValidationError,
94
91
  NotFoundError,
95
92
  };
93
+
@@ -38,22 +38,12 @@ class RunDatabaseMigrationUseCase {
38
38
  this._validateParams({ dbType, stage });
39
39
 
40
40
  // Step 1: Generate Prisma client
41
- const generateResult = await this.prismaRunner.runPrismaGenerate(
42
- dbType,
43
- verbose
44
- );
41
+ const generateResult = await this.prismaRunner.runPrismaGenerate(dbType, verbose);
45
42
 
46
43
  if (!generateResult.success) {
47
44
  throw new MigrationError(
48
- `Failed to generate Prisma client: ${
49
- generateResult.error || 'Unknown error'
50
- }`,
51
- {
52
- dbType,
53
- stage,
54
- step: 'generate',
55
- output: generateResult.output,
56
- }
45
+ `Failed to generate Prisma client: ${generateResult.error || 'Unknown error'}`,
46
+ { dbType, stage, step: 'generate', output: generateResult.output }
57
47
  );
58
48
  }
59
49
 
@@ -63,45 +53,23 @@ class RunDatabaseMigrationUseCase {
63
53
 
64
54
  if (dbType === 'postgresql') {
65
55
  migrationCommand = this.prismaRunner.getMigrationCommand(stage);
66
- migrationResult = await this.prismaRunner.runPrismaMigrate(
67
- migrationCommand,
68
- verbose
69
- );
56
+ migrationResult = await this.prismaRunner.runPrismaMigrate(migrationCommand, verbose);
70
57
 
71
58
  if (!migrationResult.success) {
72
59
  throw new MigrationError(
73
- `PostgreSQL migration failed: ${
74
- migrationResult.error || 'Unknown error'
75
- }`,
76
- {
77
- dbType,
78
- stage,
79
- command: migrationCommand,
80
- step: 'migrate',
81
- output: migrationResult.output,
82
- }
60
+ `PostgreSQL migration failed: ${migrationResult.error || 'Unknown error'}`,
61
+ { dbType, stage, command: migrationCommand, step: 'migrate', output: migrationResult.output }
83
62
  );
84
63
  }
85
64
  } else if (dbType === 'mongodb' || dbType === 'documentdb') {
86
65
  migrationCommand = 'db push';
87
66
  // Use non-interactive mode for automated/Lambda environments
88
- migrationResult = await this.prismaRunner.runPrismaDbPush(
89
- verbose,
90
- true
91
- );
67
+ migrationResult = await this.prismaRunner.runPrismaDbPush(verbose, true);
92
68
 
93
69
  if (!migrationResult.success) {
94
70
  throw new MigrationError(
95
- `Mongo-compatible push failed: ${
96
- migrationResult.error || 'Unknown error'
97
- }`,
98
- {
99
- dbType,
100
- stage,
101
- command: migrationCommand,
102
- step: 'push',
103
- output: migrationResult.output,
104
- }
71
+ `Mongo-compatible push failed: ${migrationResult.error || 'Unknown error'}`,
72
+ { dbType, stage, command: migrationCommand, step: 'push', output: migrationResult.output }
105
73
  );
106
74
  }
107
75
  } else {
@@ -88,9 +88,9 @@ class TestEncryptionUseCase {
88
88
  return {
89
89
  externalId: 'test-encryption-entity',
90
90
  data: {
91
- access_token: testData.testSecret, // Encrypted field
91
+ access_token: testData.testSecret, // Encrypted field
92
92
  refresh_token: testData.nestedSecret?.value, // Encrypted field
93
- domain: testData.normalField, // Not encrypted
93
+ domain: testData.normalField, // Not encrypted
94
94
  },
95
95
  };
96
96
  }
@@ -203,7 +203,8 @@ class TestEncryptionUseCase {
203
203
  ) {
204
204
  return {
205
205
  status: 'enabled',
206
- testResult: 'Encryption and decryption verified successfully',
206
+ testResult:
207
+ 'Encryption and decryption verified successfully',
207
208
  encryptionWorks: true,
208
209
  };
209
210
  }
@@ -249,4 +250,4 @@ class TestEncryptionUseCase {
249
250
  }
250
251
  }
251
252
 
252
- module.exports = { TestEncryptionUseCase };
253
+ module.exports = { TestEncryptionUseCase };