@friggframework/core 2.0.0-next.6 → 2.0.0-next.60

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 (285) hide show
  1. package/CLAUDE.md +694 -0
  2. package/README.md +959 -50
  3. package/application/commands/README.md +451 -0
  4. package/application/commands/credential-commands.js +245 -0
  5. package/application/commands/entity-commands.js +336 -0
  6. package/application/commands/integration-commands.js +210 -0
  7. package/application/commands/user-commands.js +283 -0
  8. package/application/index.js +69 -0
  9. package/core/CLAUDE.md +690 -0
  10. package/core/Worker.js +8 -21
  11. package/core/create-handler.js +14 -7
  12. package/credential/repositories/credential-repository-documentdb.js +304 -0
  13. package/credential/repositories/credential-repository-factory.js +54 -0
  14. package/credential/repositories/credential-repository-interface.js +98 -0
  15. package/credential/repositories/credential-repository-mongo.js +269 -0
  16. package/credential/repositories/credential-repository-postgres.js +291 -0
  17. package/credential/repositories/credential-repository.js +302 -0
  18. package/credential/use-cases/get-credential-for-user.js +25 -0
  19. package/credential/use-cases/update-authentication-status.js +15 -0
  20. package/database/MONGODB_TRANSACTION_FIX.md +198 -0
  21. package/database/adapters/lambda-invoker.js +97 -0
  22. package/database/config.js +154 -0
  23. package/database/documentdb-encryption-service.js +330 -0
  24. package/database/documentdb-utils.js +136 -0
  25. package/database/encryption/README.md +839 -0
  26. package/database/encryption/documentdb-encryption-service.md +3575 -0
  27. package/database/encryption/encryption-schema-registry.js +268 -0
  28. package/database/encryption/field-encryption-service.js +226 -0
  29. package/database/encryption/logger.js +79 -0
  30. package/database/encryption/prisma-encryption-extension.js +222 -0
  31. package/database/index.js +61 -21
  32. package/database/models/WebsocketConnection.js +16 -10
  33. package/database/models/readme.md +1 -0
  34. package/database/prisma.js +182 -0
  35. package/database/repositories/health-check-repository-documentdb.js +134 -0
  36. package/database/repositories/health-check-repository-factory.js +48 -0
  37. package/database/repositories/health-check-repository-interface.js +82 -0
  38. package/database/repositories/health-check-repository-mongodb.js +89 -0
  39. package/database/repositories/health-check-repository-postgres.js +82 -0
  40. package/database/repositories/health-check-repository.js +108 -0
  41. package/database/repositories/migration-status-repository-s3.js +137 -0
  42. package/database/use-cases/check-database-health-use-case.js +29 -0
  43. package/database/use-cases/check-database-state-use-case.js +81 -0
  44. package/database/use-cases/check-encryption-health-use-case.js +83 -0
  45. package/database/use-cases/get-database-state-via-worker-use-case.js +61 -0
  46. package/database/use-cases/get-migration-status-use-case.js +93 -0
  47. package/database/use-cases/run-database-migration-use-case.js +139 -0
  48. package/database/use-cases/test-encryption-use-case.js +253 -0
  49. package/database/use-cases/trigger-database-migration-use-case.js +157 -0
  50. package/database/utils/mongodb-collection-utils.js +91 -0
  51. package/database/utils/mongodb-schema-init.js +106 -0
  52. package/database/utils/prisma-runner.js +477 -0
  53. package/database/utils/prisma-schema-parser.js +182 -0
  54. package/docs/PROCESS_MANAGEMENT_QUEUE_SPEC.md +517 -0
  55. package/encrypt/Cryptor.js +34 -168
  56. package/encrypt/index.js +1 -2
  57. package/encrypt/test-encrypt.js +0 -2
  58. package/errors/client-safe-error.js +26 -0
  59. package/errors/fetch-error.js +2 -1
  60. package/errors/index.js +2 -0
  61. package/generated/prisma-mongodb/client.d.ts +1 -0
  62. package/generated/prisma-mongodb/client.js +4 -0
  63. package/generated/prisma-mongodb/default.d.ts +1 -0
  64. package/generated/prisma-mongodb/default.js +4 -0
  65. package/generated/prisma-mongodb/edge.d.ts +1 -0
  66. package/generated/prisma-mongodb/edge.js +334 -0
  67. package/generated/prisma-mongodb/index-browser.js +316 -0
  68. package/generated/prisma-mongodb/index.d.ts +22903 -0
  69. package/generated/prisma-mongodb/index.js +359 -0
  70. package/generated/prisma-mongodb/package.json +183 -0
  71. package/generated/prisma-mongodb/query-engine-debian-openssl-3.0.x +0 -0
  72. package/generated/prisma-mongodb/query-engine-rhel-openssl-3.0.x +0 -0
  73. package/generated/prisma-mongodb/runtime/binary.d.ts +1 -0
  74. package/generated/prisma-mongodb/runtime/binary.js +289 -0
  75. package/generated/prisma-mongodb/runtime/edge-esm.js +34 -0
  76. package/generated/prisma-mongodb/runtime/edge.js +34 -0
  77. package/generated/prisma-mongodb/runtime/index-browser.d.ts +370 -0
  78. package/generated/prisma-mongodb/runtime/index-browser.js +16 -0
  79. package/generated/prisma-mongodb/runtime/library.d.ts +3977 -0
  80. package/generated/prisma-mongodb/runtime/react-native.js +83 -0
  81. package/generated/prisma-mongodb/runtime/wasm-compiler-edge.js +84 -0
  82. package/generated/prisma-mongodb/runtime/wasm-engine-edge.js +36 -0
  83. package/generated/prisma-mongodb/schema.prisma +360 -0
  84. package/generated/prisma-mongodb/wasm-edge-light-loader.mjs +4 -0
  85. package/generated/prisma-mongodb/wasm-worker-loader.mjs +4 -0
  86. package/generated/prisma-mongodb/wasm.d.ts +1 -0
  87. package/generated/prisma-mongodb/wasm.js +341 -0
  88. package/generated/prisma-postgresql/client.d.ts +1 -0
  89. package/generated/prisma-postgresql/client.js +4 -0
  90. package/generated/prisma-postgresql/default.d.ts +1 -0
  91. package/generated/prisma-postgresql/default.js +4 -0
  92. package/generated/prisma-postgresql/edge.d.ts +1 -0
  93. package/generated/prisma-postgresql/edge.js +356 -0
  94. package/generated/prisma-postgresql/index-browser.js +338 -0
  95. package/generated/prisma-postgresql/index.d.ts +25077 -0
  96. package/generated/prisma-postgresql/index.js +381 -0
  97. package/generated/prisma-postgresql/package.json +183 -0
  98. package/generated/prisma-postgresql/query-engine-debian-openssl-3.0.x +0 -0
  99. package/generated/prisma-postgresql/query-engine-rhel-openssl-3.0.x +0 -0
  100. package/generated/prisma-postgresql/query_engine_bg.js +2 -0
  101. package/generated/prisma-postgresql/query_engine_bg.wasm +0 -0
  102. package/generated/prisma-postgresql/runtime/binary.d.ts +1 -0
  103. package/generated/prisma-postgresql/runtime/binary.js +289 -0
  104. package/generated/prisma-postgresql/runtime/edge-esm.js +34 -0
  105. package/generated/prisma-postgresql/runtime/edge.js +34 -0
  106. package/generated/prisma-postgresql/runtime/index-browser.d.ts +370 -0
  107. package/generated/prisma-postgresql/runtime/index-browser.js +16 -0
  108. package/generated/prisma-postgresql/runtime/library.d.ts +3977 -0
  109. package/generated/prisma-postgresql/runtime/react-native.js +83 -0
  110. package/generated/prisma-postgresql/runtime/wasm-compiler-edge.js +84 -0
  111. package/generated/prisma-postgresql/runtime/wasm-engine-edge.js +36 -0
  112. package/generated/prisma-postgresql/schema.prisma +343 -0
  113. package/generated/prisma-postgresql/wasm-edge-light-loader.mjs +4 -0
  114. package/generated/prisma-postgresql/wasm-worker-loader.mjs +4 -0
  115. package/generated/prisma-postgresql/wasm.d.ts +1 -0
  116. package/generated/prisma-postgresql/wasm.js +363 -0
  117. package/handlers/WEBHOOKS.md +653 -0
  118. package/handlers/app-definition-loader.js +38 -0
  119. package/handlers/app-handler-helpers.js +56 -0
  120. package/handlers/backend-utils.js +186 -0
  121. package/handlers/database-migration-handler.js +227 -0
  122. package/handlers/integration-event-dispatcher.js +54 -0
  123. package/handlers/routers/HEALTHCHECK.md +342 -0
  124. package/handlers/routers/auth.js +15 -0
  125. package/handlers/routers/db-migration.handler.js +29 -0
  126. package/handlers/routers/db-migration.js +326 -0
  127. package/handlers/routers/health.js +516 -0
  128. package/handlers/routers/integration-defined-routers.js +45 -0
  129. package/handlers/routers/integration-webhook-routers.js +67 -0
  130. package/handlers/routers/user.js +63 -0
  131. package/handlers/routers/websocket.js +57 -0
  132. package/handlers/use-cases/check-external-apis-health-use-case.js +81 -0
  133. package/handlers/use-cases/check-integrations-health-use-case.js +44 -0
  134. package/handlers/workers/db-migration.js +352 -0
  135. package/handlers/workers/integration-defined-workers.js +27 -0
  136. package/index.js +77 -22
  137. package/integrations/WEBHOOK-QUICKSTART.md +151 -0
  138. package/integrations/index.js +12 -10
  139. package/integrations/integration-base.js +326 -55
  140. package/integrations/integration-router.js +374 -179
  141. package/integrations/options.js +1 -1
  142. package/integrations/repositories/integration-mapping-repository-documentdb.js +280 -0
  143. package/integrations/repositories/integration-mapping-repository-factory.js +57 -0
  144. package/integrations/repositories/integration-mapping-repository-interface.js +106 -0
  145. package/integrations/repositories/integration-mapping-repository-mongo.js +161 -0
  146. package/integrations/repositories/integration-mapping-repository-postgres.js +227 -0
  147. package/integrations/repositories/integration-mapping-repository.js +156 -0
  148. package/integrations/repositories/integration-repository-documentdb.js +210 -0
  149. package/integrations/repositories/integration-repository-factory.js +51 -0
  150. package/integrations/repositories/integration-repository-interface.js +127 -0
  151. package/integrations/repositories/integration-repository-mongo.js +303 -0
  152. package/integrations/repositories/integration-repository-postgres.js +352 -0
  153. package/integrations/repositories/process-repository-documentdb.js +243 -0
  154. package/integrations/repositories/process-repository-factory.js +53 -0
  155. package/integrations/repositories/process-repository-interface.js +90 -0
  156. package/integrations/repositories/process-repository-mongo.js +190 -0
  157. package/integrations/repositories/process-repository-postgres.js +217 -0
  158. package/integrations/tests/doubles/dummy-integration-class.js +83 -0
  159. package/integrations/tests/doubles/test-integration-repository.js +99 -0
  160. package/integrations/use-cases/create-integration.js +83 -0
  161. package/integrations/use-cases/create-process.js +128 -0
  162. package/integrations/use-cases/delete-integration-for-user.js +101 -0
  163. package/integrations/use-cases/find-integration-context-by-external-entity-id.js +72 -0
  164. package/integrations/use-cases/get-integration-for-user.js +78 -0
  165. package/integrations/use-cases/get-integration-instance-by-definition.js +67 -0
  166. package/integrations/use-cases/get-integration-instance.js +83 -0
  167. package/integrations/use-cases/get-integrations-for-user.js +88 -0
  168. package/integrations/use-cases/get-possible-integrations.js +27 -0
  169. package/integrations/use-cases/get-process.js +87 -0
  170. package/integrations/use-cases/index.js +19 -0
  171. package/integrations/use-cases/load-integration-context.js +71 -0
  172. package/integrations/use-cases/update-integration-messages.js +44 -0
  173. package/integrations/use-cases/update-integration-status.js +32 -0
  174. package/integrations/use-cases/update-integration.js +93 -0
  175. package/integrations/use-cases/update-process-metrics.js +201 -0
  176. package/integrations/use-cases/update-process-state.js +119 -0
  177. package/integrations/utils/map-integration-dto.js +37 -0
  178. package/jest-global-setup-noop.js +3 -0
  179. package/jest-global-teardown-noop.js +3 -0
  180. package/logs/logger.js +0 -4
  181. package/{module-plugin → modules}/entity.js +1 -1
  182. package/{module-plugin → modules}/index.js +0 -8
  183. package/modules/module-factory.js +56 -0
  184. package/modules/module.js +221 -0
  185. package/modules/repositories/module-repository-documentdb.js +307 -0
  186. package/modules/repositories/module-repository-factory.js +40 -0
  187. package/modules/repositories/module-repository-interface.js +129 -0
  188. package/modules/repositories/module-repository-mongo.js +377 -0
  189. package/modules/repositories/module-repository-postgres.js +426 -0
  190. package/modules/repositories/module-repository.js +316 -0
  191. package/modules/requester/api-key.js +52 -0
  192. package/{module-plugin → modules}/requester/requester.js +1 -0
  193. package/{module-plugin → modules}/test/mock-api/api.js +8 -3
  194. package/{module-plugin → modules}/test/mock-api/definition.js +12 -8
  195. package/modules/tests/doubles/test-module-factory.js +16 -0
  196. package/modules/tests/doubles/test-module-repository.js +39 -0
  197. package/modules/use-cases/get-entities-for-user.js +32 -0
  198. package/modules/use-cases/get-entity-options-by-id.js +71 -0
  199. package/modules/use-cases/get-entity-options-by-type.js +34 -0
  200. package/modules/use-cases/get-module-instance-from-type.js +31 -0
  201. package/modules/use-cases/get-module.js +74 -0
  202. package/modules/use-cases/process-authorization-callback.js +133 -0
  203. package/modules/use-cases/refresh-entity-options.js +72 -0
  204. package/modules/use-cases/test-module-auth.js +72 -0
  205. package/modules/utils/map-module-dto.js +18 -0
  206. package/package.json +82 -50
  207. package/prisma-mongodb/schema.prisma +360 -0
  208. package/prisma-postgresql/migrations/20250930193005_init/migration.sql +315 -0
  209. package/prisma-postgresql/migrations/20251006135218_init/migration.sql +9 -0
  210. package/prisma-postgresql/migrations/20251010000000_remove_unused_entity_reference_map/migration.sql +3 -0
  211. package/prisma-postgresql/migrations/20251112195422_update_user_unique_constraints/migration.sql +25 -0
  212. package/prisma-postgresql/migrations/migration_lock.toml +3 -0
  213. package/prisma-postgresql/schema.prisma +343 -0
  214. package/queues/queuer-util.js +27 -22
  215. package/syncs/manager.js +468 -443
  216. package/syncs/repositories/sync-repository-documentdb.js +240 -0
  217. package/syncs/repositories/sync-repository-factory.js +43 -0
  218. package/syncs/repositories/sync-repository-interface.js +109 -0
  219. package/syncs/repositories/sync-repository-mongo.js +239 -0
  220. package/syncs/repositories/sync-repository-postgres.js +319 -0
  221. package/syncs/sync.js +0 -1
  222. package/token/repositories/token-repository-documentdb.js +137 -0
  223. package/token/repositories/token-repository-factory.js +40 -0
  224. package/token/repositories/token-repository-interface.js +131 -0
  225. package/token/repositories/token-repository-mongo.js +219 -0
  226. package/token/repositories/token-repository-postgres.js +264 -0
  227. package/token/repositories/token-repository.js +219 -0
  228. package/types/core/index.d.ts +2 -2
  229. package/types/integrations/index.d.ts +2 -6
  230. package/types/module-plugin/index.d.ts +5 -59
  231. package/types/syncs/index.d.ts +0 -2
  232. package/user/repositories/user-repository-documentdb.js +441 -0
  233. package/user/repositories/user-repository-factory.js +52 -0
  234. package/user/repositories/user-repository-interface.js +201 -0
  235. package/user/repositories/user-repository-mongo.js +308 -0
  236. package/user/repositories/user-repository-postgres.js +360 -0
  237. package/user/tests/doubles/test-user-repository.js +72 -0
  238. package/user/use-cases/authenticate-user.js +127 -0
  239. package/user/use-cases/authenticate-with-shared-secret.js +48 -0
  240. package/user/use-cases/create-individual-user.js +61 -0
  241. package/user/use-cases/create-organization-user.js +47 -0
  242. package/user/use-cases/create-token-for-user-id.js +30 -0
  243. package/user/use-cases/get-user-from-adopter-jwt.js +149 -0
  244. package/user/use-cases/get-user-from-bearer-token.js +77 -0
  245. package/user/use-cases/get-user-from-x-frigg-headers.js +132 -0
  246. package/user/use-cases/login-user.js +122 -0
  247. package/user/user.js +125 -0
  248. package/utils/backend-path.js +38 -0
  249. package/utils/index.js +6 -0
  250. package/websocket/repositories/websocket-connection-repository-documentdb.js +119 -0
  251. package/websocket/repositories/websocket-connection-repository-factory.js +44 -0
  252. package/websocket/repositories/websocket-connection-repository-interface.js +106 -0
  253. package/websocket/repositories/websocket-connection-repository-mongo.js +156 -0
  254. package/websocket/repositories/websocket-connection-repository-postgres.js +196 -0
  255. package/websocket/repositories/websocket-connection-repository.js +161 -0
  256. package/database/models/State.js +0 -9
  257. package/database/models/Token.js +0 -70
  258. package/database/mongo.js +0 -45
  259. package/encrypt/Cryptor.test.js +0 -32
  260. package/encrypt/encrypt.js +0 -132
  261. package/encrypt/encrypt.test.js +0 -1069
  262. package/errors/base-error.test.js +0 -32
  263. package/errors/fetch-error.test.js +0 -79
  264. package/errors/halt-error.test.js +0 -11
  265. package/errors/validation-errors.test.js +0 -120
  266. package/integrations/create-frigg-backend.js +0 -31
  267. package/integrations/integration-factory.js +0 -251
  268. package/integrations/integration-mapping.js +0 -43
  269. package/integrations/integration-model.js +0 -46
  270. package/integrations/integration-user.js +0 -144
  271. package/integrations/test/integration-base.test.js +0 -144
  272. package/lambda/TimeoutCatcher.test.js +0 -68
  273. package/logs/logger.test.js +0 -76
  274. package/module-plugin/auther.js +0 -393
  275. package/module-plugin/credential.js +0 -22
  276. package/module-plugin/entity-manager.js +0 -70
  277. package/module-plugin/manager.js +0 -169
  278. package/module-plugin/module-factory.js +0 -61
  279. package/module-plugin/requester/api-key.js +0 -36
  280. package/module-plugin/requester/requester.test.js +0 -28
  281. package/module-plugin/test/auther.test.js +0 -97
  282. /package/{module-plugin → modules}/ModuleConstants.js +0 -0
  283. /package/{module-plugin → modules}/requester/basic.js +0 -0
  284. /package/{module-plugin → modules}/requester/oauth-2.js +0 -0
  285. /package/{module-plugin → modules}/test/mock-api/mocks/hubspot.js +0 -0
package/CLAUDE.md ADDED
@@ -0,0 +1,694 @@
1
+ # CLAUDE.md - Frigg Framework Core Package
2
+
3
+ This file provides guidance to Claude Code when working with the Frigg Framework's core package (`@friggframework/core`).
4
+
5
+ ## Critical Context (Read First)
6
+
7
+ - **Package Purpose**: Core framework functionality for building enterprise serverless integrations
8
+ - **Main Architecture**: Hexagonal/DDD architecture with clear separation of adapters, use cases, and repositories
9
+ - **Key Technologies**: Node.js, Express, AWS Lambda, MongoDB/PostgreSQL (Prisma), AWS KMS encryption
10
+ - **Core Value**: Provides building blocks for integration developers - they extend IntegrationBase and use framework services
11
+ - **Security Model**: Field-level encryption, OAuth2 flows, signature validation, VPC deployment
12
+ - **DO NOT**: Bypass architectural layers, skip encryption for sensitive data, expose internal errors to users
13
+
14
+ ## Table of Contents
15
+
16
+ 1. [Package Overview](#package-overview)
17
+ 2. [Architecture Principles](#architecture-principles)
18
+ 3. [Essential Commands](#essential-commands)
19
+ 4. [Directory Structure](#directory-structure)
20
+ 5. [Core Components](#core-components)
21
+ 6. [Development Workflow](#development-workflow)
22
+ 7. [Testing Strategy](#testing-strategy)
23
+ 8. [Anti-Patterns](#anti-patterns)
24
+
25
+ ## Package Overview
26
+
27
+ `@friggframework/core` is the foundational package of the Frigg Framework, providing:
28
+
29
+ - **IntegrationBase**: Base class all integrations extend
30
+ - **Database Layer**: Multi-database support (MongoDB, DocumentDB, PostgreSQL) with Prisma ORM
31
+ - **Encryption**: Transparent field-level encryption with AWS KMS or AES
32
+ - **User Management**: Individual and organizational user support
33
+ - **Module System**: API module loading and credential management
34
+ - **Lambda Runtime**: Handler factory, worker base class, timeout management
35
+ - **Error Handling**: Standardized error types with proper HTTP status codes
36
+ - **Event System**: Integration lifecycle events and user actions
37
+
38
+ ## Architecture Principles
39
+
40
+ ### Hexagonal Architecture (Ports and Adapters)
41
+
42
+ The core package strictly follows hexagonal architecture:
43
+
44
+ ```
45
+ ┌─────────────────────────────────────────────────────────┐
46
+ │ Adapters (Inbound) │
47
+ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
48
+ │ │ HTTP/REST │ │ Lambda │ │ SQS Workers │ │
49
+ │ │ (handlers/) │ │ (core/) │ │ (queues/) │ │
50
+ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
51
+ └─────────┼─────────────────┼─────────────────┼───────────┘
52
+ │ │ │
53
+ ┌─────────▼─────────────────▼─────────────────▼───────────┐
54
+ │ Application Layer (Use Cases) │
55
+ │ ┌────────────────────────────────────────────────┐ │
56
+ │ │ CreateIntegration, UpdateIntegration, │ │
57
+ │ │ LoginUser, ProcessAttachmentJob, etc. │ │
58
+ │ └────────────────────┬───────────────────────────┘ │
59
+ └───────────────────────┼─────────────────────────────────┘
60
+ │ calls
61
+ ┌───────────────────────▼─────────────────────────────────┐
62
+ │ Domain Layer (Entities) │
63
+ │ ┌────────────────────────────────────────────────┐ │
64
+ │ │ IntegrationBase, User, Credential, Entity │ │
65
+ │ └────────────────────┬───────────────────────────┘ │
66
+ └───────────────────────┼─────────────────────────────────┘
67
+ │ persisted by
68
+ ┌───────────────────────▼─────────────────────────────────┐
69
+ │ Infrastructure Layer (Repositories) │
70
+ │ ┌────────────────────────────────────────────────┐ │
71
+ │ │ IntegrationRepository, UserRepository, │ │
72
+ │ │ CredentialRepository, ModuleRepository │ │
73
+ │ └────────────────────┬───────────────────────────┘ │
74
+ └───────────────────────┼─────────────────────────────────┘
75
+ │ accesses
76
+ ┌───────────────────────▼─────────────────────────────────┐
77
+ │ External Systems │
78
+ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
79
+ │ │ MongoDB │ │ Postgres │ │ AWS KMS │ │
80
+ │ └──────────┘ └──────────┘ └──────────┘ │
81
+ └─────────────────────────────────────────────────────────┘
82
+ ```
83
+
84
+ ### Golden Rules
85
+
86
+ 1. **Handlers NEVER call repositories directly** - Always go through use cases
87
+ 2. **Use cases contain business logic** - Not repositories or handlers
88
+ 3. **Repositories are pure data access** - No business logic or orchestration
89
+ 4. **Domain entities have behavior** - Not just data bags
90
+ 5. **Encryption is transparent** - Application code works with plain data
91
+
92
+ ## Essential Commands
93
+
94
+ ### Development
95
+
96
+ ```bash
97
+ # Install dependencies
98
+ npm install
99
+
100
+ # Generate Prisma clients (both MongoDB and PostgreSQL)
101
+ npm run prisma:generate
102
+
103
+ # Format and lint code
104
+ npm run lint:fix
105
+
106
+ # Run tests
107
+ npm test
108
+
109
+ # Run specific test file
110
+ npm test -- path/to/test.test.js
111
+
112
+ # Run tests for specific pattern
113
+ npm test -- --testPathPattern="encryption"
114
+ ```
115
+
116
+ ### Prisma Database Operations
117
+
118
+ ```bash
119
+ # Generate clients
120
+ npm run prisma:generate:mongo # MongoDB only
121
+ npm run prisma:generate:postgres # PostgreSQL only
122
+ npm run prisma:generate # Both databases
123
+
124
+ # Database migrations
125
+ npm run prisma:push:mongo # Push MongoDB schema
126
+ npm run prisma:migrate:postgres # Run PostgreSQL migrations
127
+ ```
128
+
129
+ ### Testing
130
+
131
+ ```bash
132
+ # All tests
133
+ npm test
134
+
135
+ # Specific test categories
136
+ npm test -- database/encryption/ # Encryption tests
137
+ npm test -- integrations/ # Integration tests
138
+ npm test -- handlers/ # Handler tests
139
+ ```
140
+
141
+ ## Directory Structure
142
+
143
+ ```
144
+ packages/core/
145
+ ├── application/ # Application-level commands and initialization
146
+ │ └── commands/ # Command pattern implementations
147
+ ├── assertions/ # Validation and assertion utilities
148
+ ├── associations/ # Entity association management
149
+ ├── core/ # Runtime system (Lambda, Workers, Delegates)
150
+ │ └── CLAUDE.md # Detailed core runtime documentation
151
+ ├── credential/ # Credential management
152
+ │ ├── repositories/ # Credential data access
153
+ │ └── use-cases/ # Credential business logic
154
+ ├── database/ # Database layer and encryption
155
+ │ ├── encryption/ # Field-level encryption system
156
+ │ │ └── README.md # Comprehensive encryption documentation
157
+ │ ├── models/ # Mongoose models
158
+ │ ├── repositories/ # Database repositories
159
+ │ └── use-cases/ # Database health and management
160
+ ├── encrypt/ # Cryptor adapter for AWS KMS and AES
161
+ ├── errors/ # Error type definitions
162
+ ├── handlers/ # HTTP/Lambda request handlers
163
+ │ └── routers/ # Express routers
164
+ ├── integrations/ # Integration domain and lifecycle
165
+ │ ├── integration-base.js # Base class for all integrations
166
+ │ ├── repositories/ # Integration data access
167
+ │ ├── tests/ # Integration tests
168
+ │ └── use-cases/ # Integration business logic
169
+ ├── lambda/ # AWS Lambda utilities
170
+ ├── logs/ # Logging system
171
+ ├── modules/ # API module system
172
+ │ ├── requester/ # HTTP client implementations
173
+ │ └── repositories/ # Module data access
174
+ ├── prisma-mongodb/ # MongoDB Prisma schema
175
+ ├── prisma-postgresql/ # PostgreSQL Prisma schema
176
+ ├── queues/ # SQS job queue management
177
+ ├── syncs/ # Data synchronization
178
+ ├── token/ # Token management
179
+ │ └── repositories/ # Token data access
180
+ ├── types/ # TypeScript type definitions
181
+ ├── user/ # User management
182
+ │ ├── repositories/ # User data access
183
+ │ └── use-cases/ # User business logic
184
+ ├── utils/ # Utility functions
185
+ ├── websocket/ # WebSocket connection management
186
+ │ └── repositories/ # WebSocket data access
187
+ ├── index.js # Main export file
188
+ ├── package.json # Package configuration
189
+ └── README.md # Package documentation
190
+ ```
191
+
192
+ ## Core Components
193
+
194
+ ### 1. Integration System (`/integrations`)
195
+
196
+ **Purpose**: Foundation for building integrations between external systems.
197
+
198
+ **Key Files**:
199
+ - `integration-base.js` - Base class all integrations extend
200
+ - `integration.js` - Integration domain aggregate using Proxy pattern
201
+ - `options.js` - Integration configuration and options
202
+
203
+ **Use Cases**:
204
+ - `create-integration.js` - Create new integration instance
205
+ - `update-integration.js` - Update integration configuration
206
+ - `delete-integration-for-user.js` - Remove integration
207
+ - `get-integration-instance.js` - Load integration with modules
208
+ - `load-integration-context.js` - Full integration context loading
209
+
210
+ **Repositories**:
211
+ - `integration-repository-factory.js` - Creates database-specific repositories
212
+ - `integration-repository-mongo.js` - MongoDB implementation
213
+ - `integration-repository-postgres.js` - PostgreSQL implementation
214
+ - `integration-mapping-repository-*.js` - Mapping data persistence
215
+
216
+ **Integration developers extend IntegrationBase**:
217
+
218
+ ```javascript
219
+ const { IntegrationBase } = require('@friggframework/core');
220
+
221
+ class MyIntegration extends IntegrationBase {
222
+ static Definition = {
223
+ name: 'my-integration',
224
+ version: '1.0.0',
225
+ modules: {
226
+ serviceA: 'service-a',
227
+ serviceB: 'service-b'
228
+ }
229
+ };
230
+
231
+ async onCreate({ integrationId }) {
232
+ // Setup logic
233
+ await super.onCreate({ integrationId });
234
+ }
235
+ }
236
+ ```
237
+
238
+ ### 2. Database Layer (`/database`)
239
+
240
+ **Purpose**: Multi-database support with transparent encryption.
241
+
242
+ **Key Components**:
243
+ - `prisma.js` - Prisma client initialization with encryption extension
244
+ - `mongo.js` - Mongoose connection management (legacy)
245
+ - `models/` - Mongoose model definitions
246
+
247
+ **Encryption System** (`/database/encryption`):
248
+ - **Transparent encryption**: Application code never sees encrypted data
249
+ - **Database-agnostic**: Works with MongoDB and PostgreSQL
250
+ - **AWS KMS or AES**: Production KMS, development AES
251
+ - **Configurable**: Via environment variables and app definition
252
+
253
+ **See**: `database/encryption/README.md` for comprehensive documentation
254
+
255
+ **Repositories**:
256
+ - `health-check-repository.js` - Database health monitoring
257
+ - `token-repository.js` - Authentication tokens
258
+ - `websocket-connection-repository.js` - WebSocket connections
259
+ - DocumentDB-enabled adapters mirror the MongoDB APIs but execute raw commands (`$runCommandRaw`, `$aggregateRaw`) for compatibility; encrypted models (e.g., credentials) still delegate reads to Prisma so the encryption extension can decrypt secrets transparently.
260
+
261
+ **Use Cases**:
262
+ - `check-database-health-use-case.js` - Database health checks
263
+ - `test-encryption-use-case.js` - Encryption verification
264
+
265
+ ### 3. User Management (`/user`)
266
+
267
+ **Purpose**: Individual and organizational user authentication.
268
+
269
+ **User Types**:
270
+ - **Individual Users**: Personal accounts with email/password
271
+ - **Organization Users**: Business accounts with organization-level access
272
+ - **Hybrid**: Support both simultaneously
273
+
274
+ **Authentication Methods**:
275
+ - Password-based (bcrypt hashed)
276
+ - Token-based (Bearer tokens)
277
+ - App-based (external app user IDs)
278
+
279
+ **Use Cases**:
280
+ - `login-user.js` - User authentication
281
+ - `create-individual-user.js` - Create personal account
282
+ - `create-organization-user.js` - Create business account
283
+ - `get-user-from-bearer-token.js` - Token authentication
284
+
285
+ **Repositories**:
286
+ - `user-repository-factory.js` - Creates database-specific repositories
287
+ - `user-repository-mongo.js` - MongoDB implementation
288
+ - `user-repository-postgres.js` - PostgreSQL implementation
289
+
290
+ **Configuration** (in app definition):
291
+
292
+ ```javascript
293
+ {
294
+ user: {
295
+ usePassword: true, // Enable password auth
296
+ primary: 'individual', // Primary user type
297
+ individualUserRequired: true, // Require individual user
298
+ organizationUserRequired: false // Optional org user
299
+ }
300
+ }
301
+ ```
302
+
303
+ ### 4. Module System (`/modules`)
304
+
305
+ **Purpose**: API module loading, credential management, and HTTP clients.
306
+
307
+ **Key Classes**:
308
+ - `Credential` - API credentials domain entity
309
+ - `Entity` - External service entity (account, workspace, etc.)
310
+ - `Requester` - Base HTTP client class
311
+ - `OAuth2Requester` - OAuth 2.0 flow implementation
312
+ - `ApiKeyRequester` - API key authentication
313
+ - `BasicAuthRequester` - Basic authentication
314
+
315
+ **Module Factory**:
316
+ - `ModuleFactory` - Creates and configures API module instances
317
+ - Handles credential injection
318
+ - Manages module lifecycle
319
+
320
+ **Repositories**:
321
+ - `module-repository.js` - Module data access
322
+ - `credential-repository.js` - Credential persistence (encrypted)
323
+
324
+ ### 5. Core Runtime System (`/core`)
325
+
326
+ **Purpose**: Lambda-optimized runtime with handlers, workers, and delegates.
327
+
328
+ **See**: `core/CLAUDE.md` for comprehensive documentation
329
+
330
+ **Key Components**:
331
+ - `create-handler.js` - Lambda handler factory
332
+ - `Worker.js` - SQS job processing base class
333
+ - `Delegate.js` - Observer/delegation pattern
334
+ - `load-installed-modules.js` - Dynamic module loading
335
+
336
+ **Handler Pattern**:
337
+
338
+ ```javascript
339
+ const { createHandler } = require('@friggframework/core');
340
+
341
+ const handler = createHandler({
342
+ eventName: 'MyIntegration',
343
+ isUserFacingResponse: true, // Sanitize errors
344
+ shouldUseDatabase: true, // Connect to DB
345
+ method: async (event, context) => {
346
+ // Your logic here
347
+ return { statusCode: 200, body: 'Success' };
348
+ }
349
+ });
350
+ ```
351
+
352
+ **Worker Pattern**:
353
+
354
+ ```javascript
355
+ const { Worker } = require('@friggframework/core');
356
+
357
+ class MyWorker extends Worker {
358
+ _validateParams(params) {
359
+ this._verifyParamExists(params, 'requiredField');
360
+ }
361
+
362
+ async _run(params, context) {
363
+ // Process SQS message
364
+ }
365
+ }
366
+ ```
367
+
368
+ ### 6. Encryption System (`/encrypt`)
369
+
370
+ **Purpose**: Cryptor adapter for AWS KMS and AES encryption.
371
+
372
+ **Key Class**: `Cryptor.js`
373
+ - Envelope encryption pattern
374
+ - AWS KMS integration
375
+ - AES-256-GCM fallback
376
+ - Key rotation support
377
+
378
+ **Usage**:
379
+
380
+ ```javascript
381
+ const { Cryptor } = require('@friggframework/core');
382
+
383
+ const cryptor = new Cryptor({
384
+ shouldUseAws: process.env.KMS_KEY_ARN ? true : false
385
+ });
386
+
387
+ const encrypted = await cryptor.encrypt('sensitive-data');
388
+ const decrypted = await cryptor.decrypt(encrypted);
389
+ ```
390
+
391
+ ### 7. Handlers & Routers (`/handlers`)
392
+
393
+ **Purpose**: HTTP/Lambda request handling and routing.
394
+
395
+ **Key Routers**:
396
+ - `integration-router.js` - Integration CRUD operations
397
+ - `auth.js` - Authentication endpoints
398
+ - `health.js` - Health check endpoints with encryption verification
399
+
400
+ **Handler Types**:
401
+ - **User-facing**: Sanitize errors, friendly responses
402
+ - **Server-to-server**: Full error details for debugging
403
+ - **Background workers**: SQS message processing
404
+
405
+ **Event Dispatcher**:
406
+ - `integration-event-dispatcher.js` - Routes events to integration handlers
407
+ - Supports lifecycle events and user actions
408
+
409
+ ### 8. Error Handling (`/errors`)
410
+
411
+ **Purpose**: Standardized error types with proper HTTP semantics.
412
+
413
+ **Error Types**:
414
+ - `BaseError` - Base error class
415
+ - `FetchError` - HTTP request failures
416
+ - `HaltError` - Stop processing without retry
417
+ - `RequiredPropertyError` - Missing required parameters
418
+ - `ParameterTypeError` - Invalid parameter type
419
+
420
+ **Usage**:
421
+
422
+ ```javascript
423
+ const { RequiredPropertyError } = require('@friggframework/core');
424
+
425
+ if (!userId) {
426
+ throw new RequiredPropertyError('userId is required');
427
+ }
428
+ ```
429
+
430
+ ### 9. Logging System (`/logs`)
431
+
432
+ **Purpose**: Structured logging with debug capabilities.
433
+
434
+ **Functions**:
435
+ - `debug(message, data)` - Debug logging
436
+ - `initDebugLog(eventName, event)` - Initialize debug context
437
+ - `flushDebugLog(error)` - Flush logs on error
438
+
439
+ **Usage**:
440
+
441
+ ```javascript
442
+ const { debug, initDebugLog, flushDebugLog } = require('@friggframework/core');
443
+
444
+ initDebugLog('MyIntegration', event);
445
+ debug('Processing request', { userId, action });
446
+ // ... your code ...
447
+ flushDebugLog(); // On error
448
+ ```
449
+
450
+ ### 10. Lambda Utilities (`/lambda`)
451
+
452
+ **Purpose**: AWS Lambda-specific utilities.
453
+
454
+ **Key Classes**:
455
+ - `TimeoutCatcher` - Detect approaching Lambda timeout
456
+ - Graceful shutdown handling
457
+
458
+ **Usage**:
459
+
460
+ ```javascript
461
+ const { TimeoutCatcher } = require('@friggframework/core');
462
+
463
+ exports.handler = async (event, context) => {
464
+ const timeoutCatcher = new TimeoutCatcher(context);
465
+
466
+ if (timeoutCatcher.isNearTimeout()) {
467
+ // Save state and exit gracefully
468
+ }
469
+ };
470
+ ```
471
+
472
+ ## Development Workflow
473
+
474
+ ### Adding a New Use Case
475
+
476
+ 1. **Create use case file** in appropriate `use-cases/` directory:
477
+
478
+ ```javascript
479
+ // integrations/use-cases/my-new-use-case.js
480
+ class MyNewUseCase {
481
+ constructor({ integrationRepository, userRepository }) {
482
+ this.integrationRepo = integrationRepository;
483
+ this.userRepo = userRepository;
484
+ }
485
+
486
+ async execute(userId, integrationId) {
487
+ // Business logic here
488
+ const user = await this.userRepo.findById(userId);
489
+ const integration = await this.integrationRepo.findById(integrationId);
490
+
491
+ // Validate, orchestrate, coordinate
492
+ // Return result
493
+ }
494
+ }
495
+
496
+ module.exports = { MyNewUseCase };
497
+ ```
498
+
499
+ 2. **Add tests** in corresponding `tests/` directory
500
+ 3. **Export** from parent index.js if needed
501
+ 4. **Use in handler** - handlers call use cases, not repositories
502
+
503
+ ### Adding Encrypted Fields
504
+
505
+ **For custom models** (integration developers):
506
+
507
+ In `backend/index.js`:
508
+
509
+ ```javascript
510
+ const appDefinition = {
511
+ encryption: {
512
+ schema: {
513
+ MyCustomModel: {
514
+ fields: ['secretData', 'data.apiKey']
515
+ }
516
+ }
517
+ }
518
+ };
519
+ ```
520
+
521
+ **For core models** (framework developers):
522
+
523
+ Edit `database/encryption/encryption-schema-registry.js`:
524
+
525
+ ```javascript
526
+ const ENCRYPTION_SCHEMA = {
527
+ MyModel: {
528
+ fields: ['sensitiveField']
529
+ }
530
+ };
531
+ ```
532
+
533
+ ### Database Migrations
534
+
535
+ **MongoDB** (Prisma push):
536
+
537
+ ```bash
538
+ npm run prisma:push:mongo
539
+ ```
540
+
541
+ **PostgreSQL** (Prisma migrate):
542
+
543
+ ```bash
544
+ npm run prisma:migrate:postgres
545
+ ```
546
+
547
+ ### Integration Development
548
+
549
+ 1. **Extend IntegrationBase** in your app
550
+ 2. **Define static Definition** with name, version, modules
551
+ 3. **Implement lifecycle methods**: `onCreate`, `onUpdate`, `onDelete`
552
+ 4. **Add event handlers** for webhooks and user actions
553
+ 5. **Use framework services**: repositories, encryption, logging
554
+
555
+ ## Testing Strategy
556
+
557
+ ### Test Categories
558
+
559
+ 1. **Unit Tests**: Use cases with mocked repositories
560
+ 2. **Integration Tests**: Full flow with real dependencies
561
+ 3. **Repository Tests**: Database operations
562
+ 4. **Handler Tests**: HTTP/Lambda response testing
563
+
564
+ ### Test Structure
565
+
566
+ ```javascript
567
+ describe('MyUseCase', () => {
568
+ let useCase;
569
+ let mockRepository;
570
+
571
+ beforeEach(() => {
572
+ mockRepository = {
573
+ findById: jest.fn(),
574
+ save: jest.fn()
575
+ };
576
+ useCase = new MyUseCase({ repository: mockRepository });
577
+ });
578
+
579
+ it('executes successfully', async () => {
580
+ mockRepository.findById.mockResolvedValue({ id: '123' });
581
+
582
+ const result = await useCase.execute('123');
583
+
584
+ expect(result).toBeDefined();
585
+ expect(mockRepository.findById).toHaveBeenCalledWith('123');
586
+ });
587
+ });
588
+ ```
589
+
590
+ ### Running Tests
591
+
592
+ ```bash
593
+ # All tests
594
+ npm test
595
+
596
+ # Specific file
597
+ npm test -- path/to/test.test.js
598
+
599
+ # Pattern matching
600
+ npm test -- --testPathPattern="encryption"
601
+
602
+ # With coverage
603
+ npm test -- --coverage
604
+ ```
605
+
606
+ ### Test Doubles
607
+
608
+ Use test doubles from `@friggframework/test` package for consistent mocking.
609
+
610
+ ## Anti-Patterns
611
+
612
+ ### Architecture Anti-Patterns
613
+
614
+ ❌ **Don't call repositories from handlers** - Always use use cases
615
+ ❌ **Don't put business logic in repositories** - Repositories are pure data access
616
+ ❌ **Don't put HTTP concerns in use cases** - Use cases are protocol-agnostic
617
+ ❌ **Don't bypass encryption** - Sensitive data must be encrypted
618
+ ❌ **Don't expose internal errors to users** - Use `isUserFacingResponse: true`
619
+ ❌ **Don't skip connection pooling** - Set `callbackWaitsForEmptyEventLoop = false`
620
+
621
+ ### Development Anti-Patterns
622
+
623
+ ❌ **Don't modify node_modules** - Extend through proper patterns
624
+ ❌ **Don't hardcode credentials** - Use environment variables
625
+ ❌ **Don't skip tests** - Maintain test coverage
626
+ ❌ **Don't commit secrets** - Use .gitignore and AWS Secrets Manager
627
+ ❌ **Don't ignore linting errors** - Run `npm run lint:fix`
628
+
629
+ ### Integration Development Anti-Patterns
630
+
631
+ ❌ **Don't bypass IntegrationBase** - Always extend the base class
632
+ ❌ **Don't ignore lifecycle methods** - Implement onCreate, onUpdate, onDelete
633
+ ❌ **Don't skip signature validation** - Validate all webhooks
634
+ ❌ **Don't sync operations in handlers** - Use background workers for long tasks
635
+ ❌ **Don't ignore errors** - Proper error handling and logging
636
+
637
+ ## Environment Variables
638
+
639
+ ### Required
640
+
641
+ - `AWS_REGION` - AWS region for services
642
+ - `DATABASE_URL` - Database connection string (auto-set)
643
+ - `DB_TYPE` - Database type: 'mongodb' or 'postgresql'
644
+
645
+ ### Encryption
646
+
647
+ - `KMS_KEY_ARN` - AWS KMS key ARN (production)
648
+ - `AES_KEY_ID` - AES key ID (development)
649
+ - `AES_KEY` - AES encryption key (development)
650
+ - `STAGE` - Environment stage (dev, test, local bypass encryption)
651
+
652
+ ### Optional
653
+
654
+ - `SECRET_ARN` - AWS Secrets Manager ARN for auto-injection
655
+ - `DEBUG` - Debug logging pattern
656
+ - `LOG_LEVEL` - Logging level (debug, info, warn, error)
657
+
658
+ ## Version Information
659
+
660
+ - **Current Version**: 2.0.0-next.0 (pre-release)
661
+ - **Node.js**: >=18 required
662
+ - **Dependencies**: See package.json for full list
663
+
664
+ ## Support and Documentation
665
+
666
+ - **Main Framework CLAUDE.md**: See root Frigg CLAUDE.md for framework-wide guidance
667
+ - **Core Runtime**: See `core/CLAUDE.md` for Lambda/Worker patterns
668
+ - **Encryption**: See `database/encryption/README.md` for encryption details
669
+ - **Package README**: See `README.md` for API reference
670
+
671
+ ## Recent Important Changes
672
+
673
+ ### Field-Level Encryption JSON Object Support
674
+
675
+ **Date**: 2025-01-06
676
+
677
+ **Problem**: The `FieldEncryptionService` was converting objects to the string `"[object Object]"` before encrypting, corrupting JSON fields like `IntegrationMapping.mapping`.
678
+
679
+ **Solution**: Added `_serializeForEncryption()` and `_deserializeAfterDecryption()` methods:
680
+ - Objects are now JSON.stringify'd before encryption
681
+ - Decrypted strings are JSON.parse'd back to objects
682
+ - Plain strings work as before
683
+
684
+ **Files Changed**:
685
+ - `database/encryption/field-encryption-service.js`
686
+ - `database/encryption/field-encryption-service.test.js`
687
+
688
+ **Test Coverage**: All 40 tests pass, including new object encryption test.
689
+
690
+ **Impact**: `IntegrationMapping.mapping` and other JSON fields now correctly round-trip through encryption.
691
+
692
+ ---
693
+
694
+ **Built with ❤️ by the Frigg Framework team**