@friggframework/core 2.0.0--canary.490.29e70f4.0 → 2.0.0--canary.490.1898b5d.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.
@@ -2,7 +2,7 @@ const { prisma } = require('../../database/prisma');
2
2
  const {
3
3
  CredentialRepositoryInterface,
4
4
  } = require('./credential-repository-interface');
5
- const { removeUndefinedValues } = require('../../database/utils/documentdb-compatibility');
5
+ const { BaseRepositoryMongoDB } = require('../../database/repositories/base-repository-mongodb');
6
6
 
7
7
  /**
8
8
  * MongoDB Credential Repository Adapter
@@ -16,7 +16,10 @@ const { removeUndefinedValues } = require('../../database/utils/documentdb-compa
16
16
  class CredentialRepositoryMongo extends CredentialRepositoryInterface {
17
17
  constructor() {
18
18
  super();
19
- this.prisma = prisma;
19
+
20
+ // Use MongoDB base repository for DocumentDB compatibility
21
+ const mongoBase = new BaseRepositoryMongoDB({ prismaClient: prisma });
22
+ this.prisma = mongoBase.prisma;
20
23
  }
21
24
 
22
25
  /**
@@ -157,16 +160,14 @@ class CredentialRepositoryMongo extends CredentialRepositoryInterface {
157
160
  }
158
161
 
159
162
  // Create new credential
160
- // Remove undefined values to prevent Prisma from using $$REMOVE (DocumentDB unsupported)
161
- const credentialData = removeUndefinedValues({
162
- userId: userId || user,
163
- externalId,
164
- authIsValid: authIsValid,
165
- data: oauthData,
166
- });
167
-
163
+ // DocumentDB compatibility handled by BaseRepositoryMongoDB wrapper
168
164
  const created = await this.prisma.credential.create({
169
- data: credentialData,
165
+ data: {
166
+ userId: userId || user,
167
+ externalId,
168
+ authIsValid: authIsValid,
169
+ data: oauthData,
170
+ },
170
171
  });
171
172
 
172
173
  return {
@@ -0,0 +1,201 @@
1
+ # Database Layer Architecture
2
+
3
+ ## Hexagonal Architecture (Ports & Adapters)
4
+
5
+ ```
6
+ ┌─────────────────────────────────────────────────────────────────┐
7
+ │ DOMAIN LAYER │
8
+ │ (Database Agnostic) │
9
+ │ │
10
+ │ ┌──────────────────────────────────────────────────────────┐ │
11
+ │ │ Use Cases │ │
12
+ │ │ - CreateCredentialUseCase │ │
13
+ │ │ - TestEncryptionUseCase │ │
14
+ │ │ - GetUserIntegrationsUseCase │ │
15
+ │ └──────────────────────────────────────────────────────────┘ │
16
+ │ │ │
17
+ │ │ depends on │
18
+ │ ▼ │
19
+ │ ┌──────────────────────────────────────────────────────────┐ │
20
+ │ │ PORTS (Interfaces) │ │
21
+ │ │ - CredentialRepositoryInterface │ │
22
+ │ │ - UserRepositoryInterface │ │
23
+ │ │ - IntegrationRepositoryInterface │ │
24
+ │ └──────────────────────────────────────────────────────────┘ │
25
+ └─────────────────────────────────────────────────────────────────┘
26
+ │
27
+ │ implemented by
28
+ ▼
29
+ ┌─────────────────────────────────────────────────────────────────┐
30
+ │ INFRASTRUCTURE LAYER │
31
+ │ (Adapters) │
32
+ │ │
33
+ │ ┌──────────────────────────────────────────────────────────┐ │
34
+ │ │ MongoDB Adapters │ │
35
+ │ │ │ │
36
+ │ │ BaseRepositoryMongoDB (DocumentDB compatibility) │ │
37
+ │ │ ▲ │ │
38
+ │ │ │ extends │ │
39
+ │ │ │ │ │
40
+ │ │ ┌────────┴────────┬────────────────┬──────────────┐ │ │
41
+ │ │ │ │ │ │ │ │
42
+ │ │ CredentialRepo UserRepo IntegrationRepo ModuleRepo│ │
43
+ │ │ Mongo Mongo Mongo Mongo │ │
44
+ │ └──────────────────────────────────────────────────────────┘ │
45
+ │ │
46
+ │ ┌──────────────────────────────────────────────────────────┐ │
47
+ │ │ PostgreSQL Adapters │ │
48
+ │ │ │ │
49
+ │ │ CredentialRepositoryPostgres │ │
50
+ │ │ UserRepositoryPostgres │ │
51
+ │ │ IntegrationRepositoryPostgres │ │
52
+ │ └──────────────────────────────────────────────────────────┘ │
53
+ │ │
54
+ │ ┌──────────────────────────────────────────────────────────┐ │
55
+ │ │ Database Clients │ │
56
+ │ │ │ │
57
+ │ │ Prisma Client (core) │ │
58
+ │ │ ├── prisma-mongodb/schema.prisma │ │
59
+ │ │ └── prisma-postgresql/schema.prisma │ │
60
+ │ └──────────────────────────────────────────────────────────┘ │
61
+ └─────────────────────────────────────────────────────────────────┘
62
+ ```
63
+
64
+ ## Directory Structure
65
+
66
+ ```
67
+ packages/core/
68
+ ├── credential/
69
+ │ ├── use-cases/ # Domain layer
70
+ │ └── repositories/ # Adapter layer
71
+ │ ├── credential-repository-interface.js # PORT
72
+ │ ├── credential-repository-mongo.js # ADAPTER (MongoDB)
73
+ │ ├── credential-repository-postgres.js # ADAPTER (PostgreSQL)
74
+ │ └── credential-repository-factory.js # Factory
75
+ │
76
+ ├── database/
77
+ │ ├── repositories/
78
+ │ │ ├── base-repository-mongodb.js # MongoDB adapter base
79
+ │ │ ├── health-check-repository-interface.js # PORT
80
+ │ │ ├── health-check-repository-mongodb.js # ADAPTER (MongoDB)
81
+ │ │ └── health-check-repository-postgres.js # ADAPTER (PostgreSQL)
82
+ │ │
83
+ │ ├── utils/
84
+ │ │ ├── documentdb-compatibility.js # DocumentDB utilities
85
+ │ │ └── prisma-documentdb-wrapper.js # Wrapper for adapters
86
+ │ │
87
+ │ ├── prisma.js # Core Prisma client
88
+ │ ├── prisma-mongodb/schema.prisma # MongoDB schema
89
+ │ └── prisma-postgresql/schema.prisma # PostgreSQL schema
90
+ │
91
+ ├── user/
92
+ │ ├── use-cases/ # Domain layer
93
+ │ └── repositories/ # Adapter layer
94
+ │ ├── user-repository-interface.js # PORT
95
+ │ ├── user-repository-mongo.js # ADAPTER (MongoDB)
96
+ │ └── user-repository-postgres.js # ADAPTER (PostgreSQL)
97
+ │
98
+ └── integrations/
99
+ ├── use-cases/ # Domain layer
100
+ └── repositories/ # Adapter layer
101
+ ├── integration-repository-interface.js # PORT
102
+ ├── integration-repository-mongo.js # ADAPTER (MongoDB)
103
+ └── integration-repository-postgres.js # ADAPTER (PostgreSQL)
104
+ ```
105
+
106
+ ## Key Principles
107
+
108
+ ### 1. **Separation of Concerns**
109
+
110
+ **Domain Layer (Use Cases):**
111
+ - Business logic only
112
+ - No database-specific code
113
+ - Depends on repository interfaces (ports)
114
+
115
+ **Infrastructure Layer (Repositories):**
116
+ - Database-specific implementations
117
+ - MongoDB adapters handle DocumentDB compatibility
118
+ - PostgreSQL adapters handle PostgreSQL specifics
119
+
120
+ ### 2. **DocumentDB Compatibility Location**
121
+
122
+ ❌ **WRONG: Global wrapper in `prisma.js`**
123
+ ```javascript
124
+ // This would leak infrastructure concerns into core
125
+ const client = wrapPrismaForDocumentDB(new PrismaClient());
126
+ ```
127
+
128
+ ✅ **CORRECT: Adapter layer in MongoDB repositories**
129
+ ```javascript
130
+ // DocumentDB is a MongoDB adapter concern
131
+ class CredentialRepositoryMongo extends CredentialRepositoryInterface {
132
+ constructor() {
133
+ const mongoBase = new BaseRepositoryMongoDB({ prismaClient: prisma });
134
+ this.prisma = mongoBase.prisma; // ← DocumentDB compatibility applied HERE
135
+ }
136
+ }
137
+ ```
138
+
139
+ ### 3. **Why This Follows Hexagonal Architecture**
140
+
141
+ **Port (Interface):**
142
+ ```javascript
143
+ class CredentialRepositoryInterface {
144
+ async createCredential(data) {
145
+ throw new Error('Must be implemented by adapter');
146
+ }
147
+ }
148
+ ```
149
+
150
+ **Adapter (MongoDB with DocumentDB compatibility):**
151
+ ```javascript
152
+ class CredentialRepositoryMongo extends CredentialRepositoryInterface {
153
+ constructor() {
154
+ // MongoDB-specific adapter wraps Prisma for DocumentDB
155
+ const mongoBase = new BaseRepositoryMongoDB({ prismaClient: prisma });
156
+ this.prisma = mongoBase.prisma;
157
+ }
158
+
159
+ async createCredential(data) {
160
+ // DocumentDB compatibility handled by wrapper
161
+ return this.prisma.credential.create({ data });
162
+ }
163
+ }
164
+ ```
165
+
166
+ **Adapter (PostgreSQL - no DocumentDB concerns):**
167
+ ```javascript
168
+ class CredentialRepositoryPostgres extends CredentialRepositoryInterface {
169
+ constructor() {
170
+ // PostgreSQL adapter uses Prisma directly (no DocumentDB concerns)
171
+ this.prisma = prisma;
172
+ }
173
+
174
+ async createCredential(data) {
175
+ return this.prisma.credential.create({ data });
176
+ }
177
+ }
178
+ ```
179
+
180
+ ### 4. **BaseRepositoryMongoDB Role**
181
+
182
+ `BaseRepositoryMongoDB` is the **MongoDB adapter base class** that:
183
+ - Encapsulates MongoDB/DocumentDB-specific concerns
184
+ - Applies DocumentDB compatibility wrapper
185
+ - Provides common MongoDB functionality
186
+ - All MongoDB repositories extend it
187
+
188
+ **This is NOT a generic base repository** - it's specifically for MongoDB adapters.
189
+
190
+ ## Summary
191
+
192
+ ✅ **You were right to question it!** The architecture is:
193
+
194
+ - **`prisma-mongodb/`** - Schema definition (infrastructure)
195
+ - **`repositories/*-mongo.js`** - MongoDB adapters (infrastructure)
196
+ - **`BaseRepositoryMongoDB`** - MongoDB adapter base class (infrastructure)
197
+ - **`repositories/*-interface.js`** - Ports (domain boundary)
198
+ - **`use-cases/`** - Domain logic (core)
199
+
200
+ DocumentDB compatibility belongs in the **MongoDB adapter layer**, which is exactly where we put it! 🎯
201
+
@@ -207,11 +207,6 @@ const prismaClientSingleton = () => {
207
207
  logger.info('Field-level encryption disabled');
208
208
  }
209
209
 
210
- // Wrap Prisma client for DocumentDB compatibility
211
- // Automatically removes undefined values to prevent $$REMOVE operator errors
212
- const { wrapPrismaForDocumentDB } = require('./utils/prisma-documentdb-wrapper');
213
- client = wrapPrismaForDocumentDB(client);
214
-
215
210
  return client;
216
211
  };
217
212
 
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Base MongoDB Repository
3
+ *
4
+ * Provides DocumentDB-compatible Prisma client for MongoDB repositories.
5
+ * Follows Hexagonal Architecture - infrastructure adapter for MongoDB/DocumentDB.
6
+ *
7
+ * All MongoDB repositories should extend this class to ensure DocumentDB compatibility.
8
+ */
9
+
10
+ const { wrapPrismaForDocumentDB } = require('../utils/prisma-documentdb-wrapper');
11
+
12
+ class BaseRepositoryMongoDB {
13
+ /**
14
+ * @param {Object} params
15
+ * @param {Object} params.prismaClient - Prisma client instance
16
+ */
17
+ constructor({ prismaClient }) {
18
+ // Wrap Prisma client for DocumentDB compatibility
19
+ // Only activates for DocumentDB connections (zero overhead for MongoDB)
20
+ this.prisma = wrapPrismaForDocumentDB(prismaClient);
21
+ }
22
+ }
23
+
24
+ module.exports = { BaseRepositoryMongoDB };
25
+
@@ -2,7 +2,7 @@ const { mongoose } = require('../mongoose');
2
2
  const {
3
3
  HealthCheckRepositoryInterface,
4
4
  } = require('./health-check-repository-interface');
5
- const { removeUndefinedValues } = require('../utils/documentdb-compatibility');
5
+ const { BaseRepositoryMongoDB } = require('./base-repository-mongodb');
6
6
 
7
7
  class HealthCheckRepositoryMongoDB extends HealthCheckRepositoryInterface {
8
8
  /**
@@ -11,7 +11,10 @@ class HealthCheckRepositoryMongoDB extends HealthCheckRepositoryInterface {
11
11
  */
12
12
  constructor({ prismaClient }) {
13
13
  super();
14
- this.prisma = prismaClient;
14
+
15
+ // Use MongoDB base repository for DocumentDB compatibility
16
+ const mongoBase = new BaseRepositoryMongoDB({ prismaClient });
17
+ this.prisma = mongoBase.prisma;
15
18
  }
16
19
 
17
20
  /**
@@ -49,11 +52,9 @@ class HealthCheckRepositoryMongoDB extends HealthCheckRepositoryInterface {
49
52
  }
50
53
 
51
54
  async createCredential(credentialData) {
52
- // Remove undefined values to prevent Prisma from using $$REMOVE (DocumentDB unsupported)
53
- const cleanedData = removeUndefinedValues(credentialData);
54
-
55
+ // DocumentDB compatibility handled by BaseRepositoryMongoDB wrapper
55
56
  return await this.prisma.credential.create({
56
- data: cleanedData,
57
+ data: credentialData,
57
58
  });
58
59
  }
59
60
 
@@ -2,6 +2,7 @@ const { prisma } = require('../../database/prisma');
2
2
  const {
3
3
  IntegrationMappingRepositoryInterface,
4
4
  } = require('./integration-mapping-repository-interface');
5
+ const { BaseRepositoryMongoDB } = require('../../database/repositories/base-repository-mongodb');
5
6
 
6
7
  /**
7
8
  * MongoDB Integration Mapping Repository Adapter
@@ -15,7 +16,10 @@ const {
15
16
  class IntegrationMappingRepositoryMongo extends IntegrationMappingRepositoryInterface {
16
17
  constructor() {
17
18
  super();
18
- this.prisma = prisma;
19
+
20
+ // Use MongoDB base repository for DocumentDB compatibility
21
+ const mongoBase = new BaseRepositoryMongoDB({ prismaClient: prisma });
22
+ this.prisma = mongoBase.prisma;
19
23
  }
20
24
 
21
25
  /**
@@ -2,6 +2,7 @@ const { prisma } = require('../../database/prisma');
2
2
  const {
3
3
  IntegrationRepositoryInterface,
4
4
  } = require('./integration-repository-interface');
5
+ const { BaseRepositoryMongoDB } = require('../../database/repositories/base-repository-mongodb');
5
6
 
6
7
  /**
7
8
  * MongoDB Integration Repository Adapter
@@ -21,7 +22,10 @@ const {
21
22
  class IntegrationRepositoryMongo extends IntegrationRepositoryInterface {
22
23
  constructor() {
23
24
  super();
24
- this.prisma = prisma;
25
+
26
+ // Use MongoDB base repository for DocumentDB compatibility
27
+ const mongoBase = new BaseRepositoryMongoDB({ prismaClient: prisma });
28
+ this.prisma = mongoBase.prisma;
25
29
  }
26
30
 
27
31
  /**
@@ -1,5 +1,6 @@
1
1
  const { prisma } = require('../../database/prisma');
2
2
  const { ProcessRepositoryInterface } = require('./process-repository-interface');
3
+ const { BaseRepositoryMongoDB } = require('../../database/repositories/base-repository-mongodb');
3
4
 
4
5
  /**
5
6
  * MongoDB Process Repository Adapter
@@ -19,7 +20,10 @@ const { ProcessRepositoryInterface } = require('./process-repository-interface')
19
20
  class ProcessRepositoryMongo extends ProcessRepositoryInterface {
20
21
  constructor() {
21
22
  super();
22
- this.prisma = prisma;
23
+
24
+ // Use MongoDB base repository for DocumentDB compatibility
25
+ const mongoBase = new BaseRepositoryMongoDB({ prismaClient: prisma });
26
+ this.prisma = mongoBase.prisma;
23
27
  }
24
28
 
25
29
  /**
@@ -1,5 +1,6 @@
1
1
  const { prisma } = require('../../database/prisma');
2
2
  const { ModuleRepositoryInterface } = require('./module-repository-interface');
3
+ const { BaseRepositoryMongoDB } = require('../../database/repositories/base-repository-mongodb');
3
4
 
4
5
  /**
5
6
  * MongoDB Module Repository Adapter
@@ -15,7 +16,10 @@ const { ModuleRepositoryInterface } = require('./module-repository-interface');
15
16
  class ModuleRepositoryMongo extends ModuleRepositoryInterface {
16
17
  constructor() {
17
18
  super();
18
- this.prisma = prisma;
19
+
20
+ // Use MongoDB base repository for DocumentDB compatibility
21
+ const mongoBase = new BaseRepositoryMongoDB({ prismaClient: prisma });
22
+ this.prisma = mongoBase.prisma;
19
23
  }
20
24
 
21
25
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@friggframework/core",
3
3
  "prettier": "@friggframework/prettier-config",
4
- "version": "2.0.0--canary.490.29e70f4.0",
4
+ "version": "2.0.0--canary.490.1898b5d.0",
5
5
  "dependencies": {
6
6
  "@aws-sdk/client-apigatewaymanagementapi": "^3.588.0",
7
7
  "@aws-sdk/client-kms": "^3.588.0",
@@ -38,9 +38,9 @@
38
38
  }
39
39
  },
40
40
  "devDependencies": {
41
- "@friggframework/eslint-config": "2.0.0--canary.490.29e70f4.0",
42
- "@friggframework/prettier-config": "2.0.0--canary.490.29e70f4.0",
43
- "@friggframework/test": "2.0.0--canary.490.29e70f4.0",
41
+ "@friggframework/eslint-config": "2.0.0--canary.490.1898b5d.0",
42
+ "@friggframework/prettier-config": "2.0.0--canary.490.1898b5d.0",
43
+ "@friggframework/test": "2.0.0--canary.490.1898b5d.0",
44
44
  "@prisma/client": "^6.17.0",
45
45
  "@types/lodash": "4.17.15",
46
46
  "@typescript-eslint/eslint-plugin": "^8.0.0",
@@ -80,5 +80,5 @@
80
80
  "publishConfig": {
81
81
  "access": "public"
82
82
  },
83
- "gitHead": "29e70f49b632320b72f05d49fde3c254477139d2"
83
+ "gitHead": "1898b5d812df39fa3cd85a877428c9bb2255d093"
84
84
  }
@@ -1,5 +1,6 @@
1
1
  const { prisma } = require('../../database/prisma');
2
2
  const { SyncRepositoryInterface } = require('./sync-repository-interface');
3
+ const { BaseRepositoryMongoDB } = require('../../database/repositories/base-repository-mongodb');
3
4
 
4
5
  /**
5
6
  * MongoDB Sync Repository Adapter
@@ -18,7 +19,10 @@ const { SyncRepositoryInterface } = require('./sync-repository-interface');
18
19
  class SyncRepositoryMongo extends SyncRepositoryInterface {
19
20
  constructor() {
20
21
  super();
21
- this.prisma = prisma;
22
+
23
+ // Use MongoDB base repository for DocumentDB compatibility
24
+ const mongoBase = new BaseRepositoryMongoDB({ prismaClient: prisma });
25
+ this.prisma = mongoBase.prisma;
22
26
  }
23
27
 
24
28
  /**
@@ -1,6 +1,7 @@
1
1
  const { prisma } = require('../../database/prisma');
2
2
  const bcrypt = require('bcryptjs');
3
3
  const { TokenRepositoryInterface } = require('./token-repository-interface');
4
+ const { BaseRepositoryMongoDB } = require('../../database/repositories/base-repository-mongodb');
4
5
 
5
6
  const BCRYPT_ROUNDS = 10;
6
7
 
@@ -16,7 +17,10 @@ const BCRYPT_ROUNDS = 10;
16
17
  class TokenRepositoryMongo extends TokenRepositoryInterface {
17
18
  constructor() {
18
19
  super();
19
- this.prisma = prisma;
20
+
21
+ // Use MongoDB base repository for DocumentDB compatibility
22
+ const mongoBase = new BaseRepositoryMongoDB({ prismaClient: prisma });
23
+ this.prisma = mongoBase.prisma;
20
24
  }
21
25
 
22
26
  /**
@@ -4,6 +4,7 @@ const {
4
4
  createTokenRepository,
5
5
  } = require('../../token/repositories/token-repository-factory');
6
6
  const { UserRepositoryInterface } = require('./user-repository-interface');
7
+ const { BaseRepositoryMongoDB } = require('../../database/repositories/base-repository-mongodb');
7
8
 
8
9
  /**
9
10
  * MongoDB User Repository Adapter
@@ -17,7 +18,10 @@ const { UserRepositoryInterface } = require('./user-repository-interface');
17
18
  class UserRepositoryMongo extends UserRepositoryInterface {
18
19
  constructor() {
19
20
  super();
20
- this.prisma = prisma;
21
+
22
+ // Use MongoDB base repository for DocumentDB compatibility
23
+ const mongoBase = new BaseRepositoryMongoDB({ prismaClient: prisma });
24
+ this.prisma = mongoBase.prisma;
21
25
  this.tokenRepository = createTokenRepository();
22
26
  }
23
27
 
@@ -6,6 +6,7 @@ const {
6
6
  const {
7
7
  WebsocketConnectionRepositoryInterface,
8
8
  } = require('./websocket-connection-repository-interface');
9
+ const { BaseRepositoryMongoDB } = require('../../database/repositories/base-repository-mongodb');
9
10
 
10
11
  /**
11
12
  * MongoDB WebSocket Connection Repository Adapter
@@ -19,7 +20,10 @@ const {
19
20
  class WebsocketConnectionRepositoryMongo extends WebsocketConnectionRepositoryInterface {
20
21
  constructor() {
21
22
  super();
22
- this.prisma = prisma;
23
+
24
+ // Use MongoDB base repository for DocumentDB compatibility
25
+ const mongoBase = new BaseRepositoryMongoDB({ prismaClient: prisma });
26
+ this.prisma = mongoBase.prisma;
23
27
  }
24
28
 
25
29
  /**