@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,131 +0,0 @@
1
- /**
2
- * AuthorizationSession Entity
3
- * Domain entity for multi-step authorization workflows
4
- *
5
- * Manages state for authentication flows that require multiple steps,
6
- * such as OTP verification, multi-factor authentication, or progressive
7
- * credential collection.
8
- *
9
- * @example
10
- * const session = new AuthorizationSession({
11
- * sessionId: '550e8400-e29b-41d4-a716-446655440000',
12
- * userId: 'user123',
13
- * entityType: 'nagaris',
14
- * currentStep: 1,
15
- * maxSteps: 2,
16
- * stepData: { email: 'user@example.com' },
17
- * expiresAt: new Date(Date.now() + 15 * 60 * 1000)
18
- * });
19
- */
20
- class AuthorizationSession {
21
- /**
22
- * Create an authorization session
23
- *
24
- * @param {Object} params - Session parameters
25
- * @param {string} params.sessionId - Unique session identifier (UUID)
26
- * @param {string} params.userId - User ID who initiated the auth flow
27
- * @param {string} params.entityType - Type of entity being authorized (module name)
28
- * @param {number} [params.currentStep=1] - Current step in the auth flow
29
- * @param {number} params.maxSteps - Total number of steps in the flow
30
- * @param {Object} [params.stepData={}] - Accumulated data from previous steps
31
- * @param {Date} params.expiresAt - Session expiration timestamp
32
- * @param {boolean} [params.completed=false] - Whether auth flow is complete
33
- * @param {Date} [params.createdAt=new Date()] - Session creation timestamp
34
- * @param {Date} [params.updatedAt=new Date()] - Last update timestamp
35
- */
36
- constructor({
37
- sessionId,
38
- userId,
39
- entityType,
40
- currentStep = 1,
41
- maxSteps,
42
- stepData = {},
43
- expiresAt,
44
- completed = false,
45
- createdAt = new Date(),
46
- updatedAt = new Date(),
47
- }) {
48
- this.sessionId = sessionId;
49
- this.userId = userId;
50
- this.entityType = entityType;
51
- this.currentStep = currentStep;
52
- this.maxSteps = maxSteps;
53
- this.stepData = stepData;
54
- this.expiresAt = expiresAt;
55
- this.completed = completed;
56
- this.createdAt = createdAt;
57
- this.updatedAt = updatedAt;
58
-
59
- this.validate();
60
- }
61
-
62
- /**
63
- * Validate session state
64
- *
65
- * @throws {Error} If validation fails
66
- */
67
- validate() {
68
- if (!this.sessionId) {
69
- throw new Error('Session ID is required');
70
- }
71
- if (!this.userId) {
72
- throw new Error('User ID is required');
73
- }
74
- if (!this.entityType) {
75
- throw new Error('Entity type is required');
76
- }
77
- if (this.currentStep < 1) {
78
- throw new Error('Step must be >= 1');
79
- }
80
- if (this.currentStep > this.maxSteps) {
81
- throw new Error('Current step cannot exceed max steps');
82
- }
83
- if (this.expiresAt < new Date()) {
84
- throw new Error('Session has expired');
85
- }
86
- }
87
-
88
- /**
89
- * Advance to next step with new data
90
- *
91
- * @param {Object} newStepData - Data collected from current step
92
- * @throws {Error} If session is already completed
93
- */
94
- advanceStep(newStepData) {
95
- if (this.completed) {
96
- throw new Error('Cannot advance completed session');
97
- }
98
-
99
- this.currentStep += 1;
100
- this.stepData = { ...this.stepData, ...newStepData };
101
- this.updatedAt = new Date();
102
- }
103
-
104
- /**
105
- * Mark session as complete
106
- */
107
- markComplete() {
108
- this.completed = true;
109
- this.updatedAt = new Date();
110
- }
111
-
112
- /**
113
- * Check if session has expired
114
- *
115
- * @returns {boolean} True if session is expired
116
- */
117
- isExpired() {
118
- return this.expiresAt < new Date();
119
- }
120
-
121
- /**
122
- * Check if session can advance to next step
123
- *
124
- * @returns {boolean} True if session can advance
125
- */
126
- canAdvance() {
127
- return !this.completed && this.currentStep < this.maxSteps;
128
- }
129
- }
130
-
131
- module.exports = { AuthorizationSession };
@@ -1,10 +0,0 @@
1
- /**
2
- * Domain Entities Index
3
- * Export all domain entities for convenient importing
4
- */
5
-
6
- const { AuthorizationSession } = require('./AuthorizationSession');
7
-
8
- module.exports = {
9
- AuthorizationSession,
10
- };
@@ -1,55 +0,0 @@
1
- const {
2
- AuthorizationSessionRepositoryMongo,
3
- } = require('./authorization-session-repository-mongo');
4
- const {
5
- AuthorizationSessionRepositoryPostgres,
6
- } = require('./authorization-session-repository-postgres');
7
-
8
- /**
9
- * Authorization Session Repository Factory
10
- * Creates the appropriate repository adapter based on database type
11
- *
12
- * Database-specific implementations:
13
- * - MongoDB: Uses String IDs (ObjectId), TTL index for auto-cleanup
14
- * - PostgreSQL: Uses Int IDs, manual cleanup via deleteExpired()
15
- *
16
- * All repository methods return AuthorizationSession domain entities,
17
- * ensuring application layer consistency regardless of database type.
18
- *
19
- * Environment Configuration:
20
- * - DB_TYPE=mongodb (default) - Uses MongoDB adapter
21
- * - DB_TYPE=postgresql - Uses PostgreSQL adapter
22
- *
23
- * @example
24
- * ```javascript
25
- * const repository = createAuthorizationSessionRepository();
26
- * const session = await repository.findBySessionId(sessionId);
27
- * ```
28
- *
29
- * @param {Object} [prismaClient] - Optional Prisma client for testing
30
- * @returns {AuthorizationSessionRepositoryInterface} Configured repository adapter
31
- * @throws {Error} If DB_TYPE is not supported
32
- */
33
- function createAuthorizationSessionRepository(prismaClient) {
34
- const dbType = process.env.DB_TYPE || 'mongodb';
35
-
36
- switch (dbType) {
37
- case 'mongodb':
38
- return new AuthorizationSessionRepositoryMongo(prismaClient);
39
-
40
- case 'postgresql':
41
- return new AuthorizationSessionRepositoryPostgres(prismaClient);
42
-
43
- default:
44
- throw new Error(
45
- `Unsupported DB_TYPE: ${dbType}. Supported values: 'mongodb', 'postgresql'`
46
- );
47
- }
48
- }
49
-
50
- module.exports = {
51
- createAuthorizationSessionRepository,
52
- // Export adapters for direct testing
53
- AuthorizationSessionRepositoryMongo,
54
- AuthorizationSessionRepositoryPostgres,
55
- };
@@ -1,75 +0,0 @@
1
- /**
2
- * Authorization Session Repository Interface
3
- * Abstract base class defining the contract for AuthorizationSession persistence adapters
4
- *
5
- * This follows the Port in Hexagonal Architecture:
6
- * - Domain layer depends on this abstraction
7
- * - Concrete adapters (MongoDB, PostgreSQL) implement this interface
8
- * - Use cases receive repositories via dependency injection
9
- *
10
- * @abstract
11
- */
12
- class AuthorizationSessionRepositoryInterface {
13
- /**
14
- * Create a new authorization session
15
- *
16
- * @param {import('../domain/entities/AuthorizationSession').AuthorizationSession} session - Session entity to create
17
- * @returns {Promise<import('../domain/entities/AuthorizationSession').AuthorizationSession>} Created session
18
- * @abstract
19
- */
20
- async create(session) {
21
- throw new Error('Method create must be implemented by subclass');
22
- }
23
-
24
- /**
25
- * Find session by session ID
26
- *
27
- * @param {string} sessionId - Unique session identifier
28
- * @returns {Promise<import('../domain/entities/AuthorizationSession').AuthorizationSession|null>} Session entity or null if not found/expired
29
- * @abstract
30
- */
31
- async findBySessionId(sessionId) {
32
- throw new Error(
33
- 'Method findBySessionId must be implemented by subclass'
34
- );
35
- }
36
-
37
- /**
38
- * Find active session for user and entity type
39
- * Returns the most recent active (non-completed, non-expired) session
40
- *
41
- * @param {string} userId - User ID
42
- * @param {string} entityType - Entity type (module name)
43
- * @returns {Promise<import('../domain/entities/AuthorizationSession').AuthorizationSession|null>} Session entity or null if not found
44
- * @abstract
45
- */
46
- async findActiveSession(userId, entityType) {
47
- throw new Error(
48
- 'Method findActiveSession must be implemented by subclass'
49
- );
50
- }
51
-
52
- /**
53
- * Update existing session
54
- *
55
- * @param {import('../domain/entities/AuthorizationSession').AuthorizationSession} session - Session entity with updated data
56
- * @returns {Promise<import('../domain/entities/AuthorizationSession').AuthorizationSession>} Updated session
57
- * @abstract
58
- */
59
- async update(session) {
60
- throw new Error('Method update must be implemented by subclass');
61
- }
62
-
63
- /**
64
- * Delete expired sessions (cleanup operation)
65
- * Should be called periodically to remove old sessions
66
- *
67
- * @returns {Promise<number>} Number of deleted sessions
68
- * @abstract
69
- */
70
- async deleteExpired() {
71
- throw new Error('Method deleteExpired must be implemented by subclass');
72
- }
73
- }
74
-
75
- module.exports = { AuthorizationSessionRepositoryInterface };
@@ -1,169 +0,0 @@
1
- const { prisma } = require('../../database/prisma');
2
- const {
3
- AuthorizationSession,
4
- } = require('../domain/entities/AuthorizationSession');
5
- const {
6
- AuthorizationSessionRepositoryInterface,
7
- } = require('./authorization-session-repository-interface');
8
-
9
- /**
10
- * MongoDB Authorization Session Repository Adapter
11
- * Handles AuthorizationSession persistence operations for MongoDB via Prisma
12
- *
13
- * MongoDB-specific characteristics:
14
- * - Uses String IDs (Prisma's default for MongoDB)
15
- * - TTL index on expiresAt for automatic cleanup
16
- * - No ID conversion needed (IDs are already strings)
17
- *
18
- * Schema Requirements (Prisma):
19
- * ```prisma
20
- * model AuthorizationSession {
21
- * id String @id @default(auto()) @map("_id") @db.ObjectId
22
- * sessionId String @unique
23
- * userId String
24
- * entityType String
25
- * currentStep Int @default(1)
26
- * maxSteps Int
27
- * stepData Json @default("{}")
28
- * expiresAt DateTime
29
- * completed Boolean @default(false)
30
- * createdAt DateTime @default(now())
31
- * updatedAt DateTime @updatedAt
32
- *
33
- * @@index([sessionId])
34
- * @@index([userId, entityType])
35
- * @@index([expiresAt])
36
- * @@index([completed])
37
- * }
38
- * ```
39
- */
40
- class AuthorizationSessionRepositoryMongo extends AuthorizationSessionRepositoryInterface {
41
- constructor(prismaClient = prisma) {
42
- super();
43
- this.prisma = prismaClient; // Allow injection for testing
44
- }
45
-
46
- /**
47
- * Create a new authorization session
48
- *
49
- * @param {AuthorizationSession} session - Session entity to create
50
- * @returns {Promise<AuthorizationSession>} Created session entity
51
- */
52
- async create(session) {
53
- const doc = await this.prisma.authorizationSession.create({
54
- data: {
55
- sessionId: session.sessionId,
56
- userId: session.userId,
57
- entityType: session.entityType,
58
- currentStep: session.currentStep,
59
- maxSteps: session.maxSteps,
60
- stepData: session.stepData,
61
- expiresAt: session.expiresAt,
62
- completed: session.completed,
63
- },
64
- });
65
-
66
- return this._toEntity(doc);
67
- }
68
-
69
- /**
70
- * Find session by session ID
71
- * Excludes expired sessions
72
- *
73
- * @param {string} sessionId - Unique session identifier
74
- * @returns {Promise<AuthorizationSession|null>} Session entity or null
75
- */
76
- async findBySessionId(sessionId) {
77
- const doc = await this.prisma.authorizationSession.findFirst({
78
- where: {
79
- sessionId,
80
- expiresAt: { gt: new Date() },
81
- },
82
- });
83
-
84
- return doc ? this._toEntity(doc) : null;
85
- }
86
-
87
- /**
88
- * Find active session for user and entity type
89
- * Returns most recent active session
90
- *
91
- * @param {string} userId - User ID
92
- * @param {string} entityType - Entity type (module name)
93
- * @returns {Promise<AuthorizationSession|null>} Session entity or null
94
- */
95
- async findActiveSession(userId, entityType) {
96
- const doc = await this.prisma.authorizationSession.findFirst({
97
- where: {
98
- userId,
99
- entityType,
100
- completed: false,
101
- expiresAt: { gt: new Date() },
102
- },
103
- orderBy: { createdAt: 'desc' },
104
- });
105
-
106
- return doc ? this._toEntity(doc) : null;
107
- }
108
-
109
- /**
110
- * Update existing session
111
- *
112
- * @param {AuthorizationSession} session - Session entity with updated data
113
- * @returns {Promise<AuthorizationSession>} Updated session entity
114
- */
115
- async update(session) {
116
- const updated = await this.prisma.authorizationSession.update({
117
- where: { sessionId: session.sessionId },
118
- data: {
119
- currentStep: session.currentStep,
120
- stepData: session.stepData,
121
- completed: session.completed,
122
- updatedAt: new Date(),
123
- },
124
- });
125
-
126
- return this._toEntity(updated);
127
- }
128
-
129
- /**
130
- * Delete expired sessions (cleanup operation)
131
- * Note: MongoDB TTL index handles automatic deletion, but this provides
132
- * manual cleanup capability
133
- *
134
- * @returns {Promise<number>} Number of deleted sessions
135
- */
136
- async deleteExpired() {
137
- const result = await this.prisma.authorizationSession.deleteMany({
138
- where: {
139
- expiresAt: { lt: new Date() },
140
- },
141
- });
142
-
143
- return result.count;
144
- }
145
-
146
- /**
147
- * Convert Prisma document to domain entity
148
- *
149
- * @private
150
- * @param {Object} doc - Prisma document
151
- * @returns {AuthorizationSession} Domain entity
152
- */
153
- _toEntity(doc) {
154
- return new AuthorizationSession({
155
- sessionId: doc.sessionId,
156
- userId: doc.userId,
157
- entityType: doc.entityType,
158
- currentStep: doc.currentStep,
159
- maxSteps: doc.maxSteps,
160
- stepData: doc.stepData,
161
- expiresAt: doc.expiresAt,
162
- completed: doc.completed,
163
- createdAt: doc.createdAt,
164
- updatedAt: doc.updatedAt,
165
- });
166
- }
167
- }
168
-
169
- module.exports = { AuthorizationSessionRepositoryMongo };
@@ -1,170 +0,0 @@
1
- const { prisma } = require('../../database/prisma');
2
- const {
3
- AuthorizationSession,
4
- } = require('../domain/entities/AuthorizationSession');
5
- const {
6
- AuthorizationSessionRepositoryInterface,
7
- } = require('./authorization-session-repository-interface');
8
-
9
- /**
10
- * PostgreSQL Authorization Session Repository Adapter
11
- * Handles AuthorizationSession persistence operations for PostgreSQL via Prisma
12
- *
13
- * PostgreSQL-specific characteristics:
14
- * - Uses Int IDs (auto-incrementing)
15
- * - Indexes on sessionId, userId+entityType, expiresAt, completed
16
- * - JSON/JSONB support for stepData
17
- * - No automatic TTL (manual cleanup via deleteExpired)
18
- *
19
- * Schema Requirements (Prisma):
20
- * ```prisma
21
- * model AuthorizationSession {
22
- * id Int @id @default(autoincrement())
23
- * sessionId String @unique
24
- * userId String
25
- * entityType String
26
- * currentStep Int @default(1)
27
- * maxSteps Int
28
- * stepData Json @default("{}")
29
- * expiresAt DateTime
30
- * completed Boolean @default(false)
31
- * createdAt DateTime @default(now())
32
- * updatedAt DateTime @updatedAt
33
- *
34
- * @@index([sessionId])
35
- * @@index([userId, entityType])
36
- * @@index([expiresAt])
37
- * @@index([completed])
38
- * }
39
- * ```
40
- */
41
- class AuthorizationSessionRepositoryPostgres extends AuthorizationSessionRepositoryInterface {
42
- constructor(prismaClient = prisma) {
43
- super();
44
- this.prisma = prismaClient; // Allow injection for testing
45
- }
46
-
47
- /**
48
- * Create a new authorization session
49
- *
50
- * @param {AuthorizationSession} session - Session entity to create
51
- * @returns {Promise<AuthorizationSession>} Created session entity
52
- */
53
- async create(session) {
54
- const created = await this.prisma.authorizationSession.create({
55
- data: {
56
- sessionId: session.sessionId,
57
- userId: session.userId,
58
- entityType: session.entityType,
59
- currentStep: session.currentStep,
60
- maxSteps: session.maxSteps,
61
- stepData: session.stepData,
62
- expiresAt: session.expiresAt,
63
- completed: session.completed,
64
- },
65
- });
66
-
67
- return this._toEntity(created);
68
- }
69
-
70
- /**
71
- * Find session by session ID
72
- * Excludes expired sessions
73
- *
74
- * @param {string} sessionId - Unique session identifier
75
- * @returns {Promise<AuthorizationSession|null>} Session entity or null
76
- */
77
- async findBySessionId(sessionId) {
78
- const record = await this.prisma.authorizationSession.findFirst({
79
- where: {
80
- sessionId,
81
- expiresAt: { gt: new Date() },
82
- },
83
- });
84
-
85
- return record ? this._toEntity(record) : null;
86
- }
87
-
88
- /**
89
- * Find active session for user and entity type
90
- * Returns most recent active session
91
- *
92
- * @param {string} userId - User ID
93
- * @param {string} entityType - Entity type (module name)
94
- * @returns {Promise<AuthorizationSession|null>} Session entity or null
95
- */
96
- async findActiveSession(userId, entityType) {
97
- const record = await this.prisma.authorizationSession.findFirst({
98
- where: {
99
- userId,
100
- entityType,
101
- completed: false,
102
- expiresAt: { gt: new Date() },
103
- },
104
- orderBy: { createdAt: 'desc' },
105
- });
106
-
107
- return record ? this._toEntity(record) : null;
108
- }
109
-
110
- /**
111
- * Update existing session
112
- *
113
- * @param {AuthorizationSession} session - Session entity with updated data
114
- * @returns {Promise<AuthorizationSession>} Updated session entity
115
- */
116
- async update(session) {
117
- const updated = await this.prisma.authorizationSession.update({
118
- where: { sessionId: session.sessionId },
119
- data: {
120
- currentStep: session.currentStep,
121
- stepData: session.stepData,
122
- completed: session.completed,
123
- updatedAt: new Date(),
124
- },
125
- });
126
-
127
- return this._toEntity(updated);
128
- }
129
-
130
- /**
131
- * Delete expired sessions (cleanup operation)
132
- * PostgreSQL doesn't have TTL indexes, so this must be called periodically
133
- * Recommend running as cron job or scheduled task
134
- *
135
- * @returns {Promise<number>} Number of deleted sessions
136
- */
137
- async deleteExpired() {
138
- const result = await this.prisma.authorizationSession.deleteMany({
139
- where: {
140
- expiresAt: { lt: new Date() },
141
- },
142
- });
143
-
144
- return result.count;
145
- }
146
-
147
- /**
148
- * Convert Prisma record to domain entity
149
- *
150
- * @private
151
- * @param {Object} record - Prisma record
152
- * @returns {AuthorizationSession} Domain entity
153
- */
154
- _toEntity(record) {
155
- return new AuthorizationSession({
156
- sessionId: record.sessionId,
157
- userId: record.userId,
158
- entityType: record.entityType,
159
- currentStep: record.currentStep,
160
- maxSteps: record.maxSteps,
161
- stepData: record.stepData,
162
- expiresAt: record.expiresAt,
163
- completed: record.completed,
164
- createdAt: record.createdAt,
165
- updatedAt: record.updatedAt,
166
- });
167
- }
168
- }
169
-
170
- module.exports = { AuthorizationSessionRepositoryPostgres };
@@ -1,23 +0,0 @@
1
- /**
2
- * DeleteModuleEntity Use Case
3
- * Deletes a module entity by its ID
4
- */
5
- class DeleteModuleEntity {
6
- constructor({ moduleRepository }) {
7
- this.moduleRepository = moduleRepository;
8
- }
9
-
10
- async execute(entityId) {
11
- const entity = await this.moduleRepository.findEntityById(entityId);
12
-
13
- if (!entity) {
14
- throw new Error(`Entity not found: ${entityId}`);
15
- }
16
-
17
- await this.moduleRepository.deleteEntity(entityId);
18
-
19
- return true;
20
- }
21
- }
22
-
23
- module.exports = { DeleteModuleEntity };