@friggframework/core 2.0.0--canary.496.a94ee46.0 → 2.0.0--canary.490.feacde9.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.
- package/core/create-handler.js +63 -12
- package/database/PRISMA_BEST_PRACTICES.md +654 -0
- package/database/index.js +7 -29
- package/database/prisma.js +51 -19
- package/database/repositories/health-check-repository-mongodb.js +18 -22
- package/database/utils/mongodb-collection-utils.js +26 -18
- package/database/utils/mongodb-schema-init.js +7 -12
- package/generated/prisma-mongodb/edge.js +6 -6
- package/generated/prisma-mongodb/index-browser.js +4 -4
- package/generated/prisma-mongodb/index.d.ts +3 -2
- package/generated/prisma-mongodb/index.js +6 -6
- package/generated/prisma-mongodb/package.json +1 -1
- package/generated/prisma-mongodb/query-engine-debian-openssl-3.0.x +0 -0
- package/generated/prisma-mongodb/query-engine-rhel-openssl-3.0.x +0 -0
- package/generated/prisma-mongodb/runtime/binary.js +2 -2
- package/generated/prisma-mongodb/runtime/edge-esm.js +3 -3
- package/generated/prisma-mongodb/runtime/edge.js +3 -3
- package/generated/prisma-mongodb/runtime/library.d.ts +5 -0
- package/generated/prisma-mongodb/runtime/react-native.js +14 -14
- package/generated/prisma-mongodb/runtime/wasm-compiler-edge.js +18 -18
- package/generated/prisma-mongodb/runtime/wasm-engine-edge.js +11 -11
- package/generated/prisma-mongodb/wasm.js +6 -6
- package/generated/prisma-postgresql/edge.js +6 -6
- package/generated/prisma-postgresql/index-browser.js +4 -4
- package/generated/prisma-postgresql/index.d.ts +3 -2
- package/generated/prisma-postgresql/index.js +6 -6
- package/generated/prisma-postgresql/package.json +1 -1
- package/generated/prisma-postgresql/query-engine-debian-openssl-3.0.x +0 -0
- package/generated/prisma-postgresql/query-engine-rhel-openssl-3.0.x +0 -0
- package/generated/prisma-postgresql/query_engine_bg.js +2 -2
- package/generated/prisma-postgresql/query_engine_bg.wasm +0 -0
- package/generated/prisma-postgresql/runtime/binary.js +2 -2
- package/generated/prisma-postgresql/runtime/edge-esm.js +3 -3
- package/generated/prisma-postgresql/runtime/edge.js +3 -3
- package/generated/prisma-postgresql/runtime/library.d.ts +5 -0
- package/generated/prisma-postgresql/runtime/react-native.js +14 -14
- package/generated/prisma-postgresql/runtime/wasm-compiler-edge.js +18 -18
- package/generated/prisma-postgresql/runtime/wasm-engine-edge.js +11 -11
- package/generated/prisma-postgresql/wasm.js +6 -6
- package/integrations/integration-router.js +0 -1
- package/integrations/use-cases/delete-integration-for-user.js +3 -31
- package/integrations/use-cases/get-integrations-for-user.js +4 -5
- package/integrations/utils/map-integration-dto.js +1 -2
- package/modules/index.js +0 -2
- package/package.json +5 -5
- package/associations/model.js +0 -54
- package/database/models/UserModel.js +0 -7
- package/database/models/WebsocketConnection.js +0 -55
- package/database/repositories/health-check-repository.js +0 -108
- package/modules/entity.js +0 -46
- package/syncs/model.js +0 -62
package/database/prisma.js
CHANGED
|
@@ -14,22 +14,40 @@ const config = require('./config');
|
|
|
14
14
|
* Note: This should only be called when DB_TYPE is 'mongodb'
|
|
15
15
|
*/
|
|
16
16
|
function ensureMongoDbUrl() {
|
|
17
|
-
|
|
17
|
+
let connectionString;
|
|
18
|
+
|
|
18
19
|
if (process.env.DATABASE_URL && process.env.DATABASE_URL.trim()) {
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Fallback to MONGO_URI for backwards compatibility with DocumentDB deployments
|
|
23
|
-
if (process.env.MONGO_URI && process.env.MONGO_URI.trim()) {
|
|
24
|
-
process.env.DATABASE_URL = process.env.MONGO_URI;
|
|
20
|
+
connectionString = process.env.DATABASE_URL;
|
|
21
|
+
} else if (process.env.MONGO_URI && process.env.MONGO_URI.trim()) {
|
|
22
|
+
connectionString = process.env.MONGO_URI;
|
|
25
23
|
logger.debug('Using MONGO_URI as DATABASE_URL for MongoDB connection');
|
|
26
|
-
|
|
24
|
+
} else {
|
|
25
|
+
throw new Error(
|
|
26
|
+
'DATABASE_URL or MONGO_URI environment variable must be set for MongoDB'
|
|
27
|
+
);
|
|
27
28
|
}
|
|
28
|
-
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
|
|
30
|
+
// Ensure readPreference=primary for transaction support
|
|
31
|
+
// MongoDB requires this for all operations within transactions
|
|
32
|
+
try {
|
|
33
|
+
const url = new URL(connectionString);
|
|
34
|
+
const params = url.searchParams;
|
|
35
|
+
|
|
36
|
+
const existingReadPreference = params.get('readPreference');
|
|
37
|
+
if (existingReadPreference && existingReadPreference !== 'primary') {
|
|
38
|
+
params.set('readPreference', 'primary');
|
|
39
|
+
logger.debug(`Overrode readPreference from ${existingReadPreference} to primary for transaction support`);
|
|
40
|
+
} else if (!existingReadPreference) {
|
|
41
|
+
params.set('readPreference', 'primary');
|
|
42
|
+
logger.debug('Added readPreference=primary to MongoDB connection string for transaction support');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
connectionString = url.toString();
|
|
46
|
+
} catch (error) {
|
|
47
|
+
logger.warn('Failed to parse MongoDB connection string as URL, skipping readPreference configuration:', error.message);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
process.env.DATABASE_URL = connectionString;
|
|
33
51
|
}
|
|
34
52
|
|
|
35
53
|
function getEncryptionConfig() {
|
|
@@ -104,14 +122,27 @@ const prismaClientSingleton = () => {
|
|
|
104
122
|
|
|
105
123
|
// Helper to try loading Prisma client from multiple locations
|
|
106
124
|
const loadPrismaClient = (dbType) => {
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
125
|
+
const fs = require('fs');
|
|
126
|
+
const layerPath = `/opt/nodejs/node_modules/generated/prisma-${dbType}`;
|
|
127
|
+
|
|
128
|
+
// Check if layer exists (when usePrismaLambdaLayer=true)
|
|
129
|
+
if (fs.existsSync(layerPath)) {
|
|
130
|
+
try {
|
|
131
|
+
return require(layerPath).PrismaClient;
|
|
132
|
+
} catch (err) {
|
|
133
|
+
// Layer exists but failed to load - fall through to bundled paths
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Layer doesn't exist or failed - use bundled/local paths (when usePrismaLambdaLayer=false)
|
|
138
|
+
const localPaths = [
|
|
139
|
+
// Bundled with function (when usePrismaLambdaLayer=false)
|
|
140
|
+
`@friggframework/core/generated/prisma-${dbType}`,
|
|
141
|
+
// Local development (relative to core package)
|
|
111
142
|
`../generated/prisma-${dbType}`,
|
|
112
143
|
];
|
|
113
144
|
|
|
114
|
-
for (const path of
|
|
145
|
+
for (const path of localPaths) {
|
|
115
146
|
try {
|
|
116
147
|
return require(path).PrismaClient;
|
|
117
148
|
} catch (err) {
|
|
@@ -120,7 +151,8 @@ const prismaClientSingleton = () => {
|
|
|
120
151
|
}
|
|
121
152
|
|
|
122
153
|
throw new Error(
|
|
123
|
-
`Cannot find Prisma client for ${dbType}.
|
|
154
|
+
`Cannot find Prisma client for ${dbType}. ` +
|
|
155
|
+
`Tried layer path: ${layerPath}, local paths: ${localPaths.join(', ')}`
|
|
124
156
|
);
|
|
125
157
|
};
|
|
126
158
|
|
|
@@ -29,32 +29,21 @@ class HealthCheckRepositoryMongoDB extends HealthCheckRepositoryInterface {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
return {
|
|
32
|
-
readyState: isConnected ? 1 : 0,
|
|
33
32
|
readyState: isConnected ? 1 : 0,
|
|
34
33
|
stateName,
|
|
35
34
|
isConnected,
|
|
36
35
|
};
|
|
37
36
|
}
|
|
38
37
|
|
|
38
|
+
/**
|
|
39
|
+
* @param {number} maxTimeMS
|
|
40
|
+
* @returns {Promise<number>} Response time in milliseconds
|
|
41
|
+
*/
|
|
39
42
|
async pingDatabase(maxTimeMS = 2000) {
|
|
40
43
|
const pingStart = Date.now();
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
setTimeout(() => reject(new Error('Database ping timeout')), maxTimeMS)
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
// Race between the database ping and the timeout
|
|
48
|
-
await Promise.race([
|
|
49
|
-
prisma.$queryRaw`SELECT 1`.catch(() => {
|
|
50
|
-
// For MongoDB, use runCommandRaw instead
|
|
51
|
-
return prisma.$runCommandRaw({ ping: 1 });
|
|
52
|
-
}),
|
|
53
|
-
timeoutPromise
|
|
54
|
-
]);
|
|
55
|
-
|
|
56
|
-
return Date.now() - pingStart;
|
|
57
|
-
}
|
|
44
|
+
await this.prisma.$queryRaw`SELECT 1`.catch(() => {
|
|
45
|
+
return this.prisma.$runCommandRaw({ ping: 1 });
|
|
46
|
+
});
|
|
58
47
|
return Date.now() - pingStart;
|
|
59
48
|
}
|
|
60
49
|
|
|
@@ -75,10 +64,17 @@ class HealthCheckRepositoryMongoDB extends HealthCheckRepositoryInterface {
|
|
|
75
64
|
* @returns {Promise<Object|null>}
|
|
76
65
|
*/
|
|
77
66
|
async getRawCredentialById(id) {
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
67
|
+
const result = await this.prisma.$runCommandRaw({
|
|
68
|
+
find: 'Credential',
|
|
69
|
+
filter: { _id: { $oid: id } },
|
|
70
|
+
limit: 1,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
if (!result.cursor || !result.cursor.firstBatch || result.cursor.firstBatch.length === 0) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return result.cursor.firstBatch[0];
|
|
82
78
|
}
|
|
83
79
|
|
|
84
80
|
async deleteCredential(id) {
|
|
@@ -5,11 +5,14 @@
|
|
|
5
5
|
* handling the constraint that collections cannot be created inside
|
|
6
6
|
* multi-document transactions.
|
|
7
7
|
*
|
|
8
|
+
* Uses Prisma's $runCommandRaw to send native MongoDB commands directly,
|
|
9
|
+
* avoiding the need for mongoose connection.
|
|
10
|
+
*
|
|
8
11
|
* @see https://github.com/prisma/prisma/issues/8305
|
|
9
12
|
* @see https://www.mongodb.com/docs/manual/core/transactions/#transactions-and-operations
|
|
10
13
|
*/
|
|
11
14
|
|
|
12
|
-
const {
|
|
15
|
+
const { prisma } = require('../prisma');
|
|
13
16
|
|
|
14
17
|
/**
|
|
15
18
|
* Ensures a MongoDB collection exists
|
|
@@ -18,6 +21,9 @@ const { mongoose } = require('../mongoose');
|
|
|
18
21
|
* transactions. This function checks if a collection exists and creates it if needed,
|
|
19
22
|
* preventing "Cannot create namespace in multi-document transaction" errors.
|
|
20
23
|
*
|
|
24
|
+
* Uses Prisma's $runCommandRaw to send native MongoDB commands, which works with
|
|
25
|
+
* both MongoDB and DocumentDB.
|
|
26
|
+
*
|
|
21
27
|
* @param {string} collectionName - Name of the collection to ensure exists
|
|
22
28
|
* @returns {Promise<void>}
|
|
23
29
|
*
|
|
@@ -30,23 +36,24 @@ const { mongoose } = require('../mongoose');
|
|
|
30
36
|
*/
|
|
31
37
|
async function ensureCollectionExists(collectionName) {
|
|
32
38
|
try {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
// Check if collection exists using Prisma's $runCommandRaw
|
|
40
|
+
const collections = await prisma.$runCommandRaw({
|
|
41
|
+
listCollections: 1,
|
|
42
|
+
filter: { name: collectionName }
|
|
43
|
+
});
|
|
36
44
|
|
|
37
|
-
if (collections.length === 0) {
|
|
38
|
-
// Collection doesn't exist, create it
|
|
39
|
-
await
|
|
40
|
-
|
|
45
|
+
if (collections.cursor.firstBatch.length === 0) {
|
|
46
|
+
// Collection doesn't exist, create it
|
|
47
|
+
await prisma.$runCommandRaw({
|
|
48
|
+
create: collectionName
|
|
49
|
+
});
|
|
50
|
+
console.log(`✓ Created collection: ${collectionName}`);
|
|
41
51
|
}
|
|
42
52
|
} catch (error) {
|
|
43
|
-
//
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
// This is expected in race conditions, silently continue
|
|
47
|
-
return;
|
|
53
|
+
// Ignore "already exists" errors (code 48: NamespaceExists)
|
|
54
|
+
if (error.code !== 48 && error.codeName !== 'NamespaceExists') {
|
|
55
|
+
console.warn(`Warning: Could not ensure collection ${collectionName}:`, error.message);
|
|
48
56
|
}
|
|
49
|
-
console.warn(`Error ensuring collection ${collectionName} exists:`, error.message);
|
|
50
57
|
}
|
|
51
58
|
}
|
|
52
59
|
|
|
@@ -73,11 +80,12 @@ async function ensureCollectionsExist(collectionNames) {
|
|
|
73
80
|
*/
|
|
74
81
|
async function collectionExists(collectionName) {
|
|
75
82
|
try {
|
|
76
|
-
const collections = await
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
const collections = await prisma.$runCommandRaw({
|
|
84
|
+
listCollections: 1,
|
|
85
|
+
filter: { name: collectionName }
|
|
86
|
+
});
|
|
79
87
|
|
|
80
|
-
return collections.length > 0;
|
|
88
|
+
return collections.cursor.firstBatch.length > 0;
|
|
81
89
|
} catch (error) {
|
|
82
90
|
console.error(`Error checking if collection ${collectionName} exists:`, error.message);
|
|
83
91
|
return false;
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
* @see https://www.mongodb.com/docs/manual/core/transactions/#transactions-and-operations
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
const { mongoose } = require('../mongoose');
|
|
20
19
|
const { ensureCollectionsExist } = require('./mongodb-collection-utils');
|
|
21
20
|
const { getCollectionsFromSchemaSync } = require('./prisma-schema-parser');
|
|
22
21
|
const config = require('../config');
|
|
@@ -24,25 +23,29 @@ const config = require('../config');
|
|
|
24
23
|
/**
|
|
25
24
|
* Initialize MongoDB schema by ensuring all collections exist
|
|
26
25
|
*
|
|
27
|
-
* This should be called once at application startup, after
|
|
28
|
-
*
|
|
26
|
+
* This should be called once at application startup, after Prisma connection
|
|
27
|
+
* is established but before handling any requests.
|
|
29
28
|
*
|
|
30
29
|
* Dynamically parses the Prisma schema to extract collection names,
|
|
31
30
|
* ensuring automatic sync with schema changes.
|
|
32
31
|
*
|
|
32
|
+
* Uses Prisma's $runCommandRaw to create collections, which works with both
|
|
33
|
+
* MongoDB and DocumentDB without requiring mongoose connection.
|
|
34
|
+
*
|
|
33
35
|
* Benefits:
|
|
34
36
|
* - Prevents transaction namespace creation errors
|
|
35
37
|
* - Fails fast if there are database connection issues
|
|
36
38
|
* - Ensures consistent state across all instances
|
|
37
39
|
* - Idempotent - safe to run multiple times
|
|
38
40
|
* - Automatically syncs with Prisma schema changes
|
|
41
|
+
* - No mongoose dependency required
|
|
39
42
|
*
|
|
40
43
|
* @returns {Promise<void>}
|
|
41
44
|
*
|
|
42
45
|
* @example
|
|
43
46
|
* ```js
|
|
44
47
|
* await connectPrisma();
|
|
45
|
-
* await initializeMongoDBSchema(); // Run after connection
|
|
48
|
+
* await initializeMongoDBSchema(); // Run after Prisma connection
|
|
46
49
|
* // Now safe to handle requests
|
|
47
50
|
* ```
|
|
48
51
|
*/
|
|
@@ -53,14 +56,6 @@ async function initializeMongoDBSchema() {
|
|
|
53
56
|
return;
|
|
54
57
|
}
|
|
55
58
|
|
|
56
|
-
// Check if database is connected
|
|
57
|
-
if (mongoose.connection.readyState !== 1) {
|
|
58
|
-
throw new Error(
|
|
59
|
-
'Cannot initialize MongoDB schema - database not connected. ' +
|
|
60
|
-
'Call connectPrisma() before initializeMongoDBSchema()'
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
59
|
console.log('Initializing MongoDB schema - ensuring all collections exist...');
|
|
65
60
|
const startTime = Date.now();
|
|
66
61
|
|
|
@@ -35,12 +35,12 @@ exports.Prisma = Prisma
|
|
|
35
35
|
exports.$Enums = {}
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
|
-
* Prisma Client JS version: 6.
|
|
39
|
-
* Query Engine version:
|
|
38
|
+
* Prisma Client JS version: 6.18.0
|
|
39
|
+
* Query Engine version: 34b5a692b7bd79939a9a2c3ef97d816e749cda2f
|
|
40
40
|
*/
|
|
41
41
|
Prisma.prismaVersion = {
|
|
42
|
-
client: "6.
|
|
43
|
-
engine: "
|
|
42
|
+
client: "6.18.0",
|
|
43
|
+
engine: "34b5a692b7bd79939a9a2c3ef97d816e749cda2f"
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
Prisma.PrismaClientKnownRequestError = PrismaClientKnownRequestError;
|
|
@@ -291,8 +291,8 @@ const config = {
|
|
|
291
291
|
"rootEnvPath": null
|
|
292
292
|
},
|
|
293
293
|
"relativePath": "../../prisma-mongodb",
|
|
294
|
-
"clientVersion": "6.
|
|
295
|
-
"engineVersion": "
|
|
294
|
+
"clientVersion": "6.18.0",
|
|
295
|
+
"engineVersion": "34b5a692b7bd79939a9a2c3ef97d816e749cda2f",
|
|
296
296
|
"datasourceNames": [
|
|
297
297
|
"db"
|
|
298
298
|
],
|
|
@@ -20,12 +20,12 @@ exports.Prisma = Prisma
|
|
|
20
20
|
exports.$Enums = {}
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
-
* Prisma Client JS version: 6.
|
|
24
|
-
* Query Engine version:
|
|
23
|
+
* Prisma Client JS version: 6.18.0
|
|
24
|
+
* Query Engine version: 34b5a692b7bd79939a9a2c3ef97d816e749cda2f
|
|
25
25
|
*/
|
|
26
26
|
Prisma.prismaVersion = {
|
|
27
|
-
client: "6.
|
|
28
|
-
engine: "
|
|
27
|
+
client: "6.18.0",
|
|
28
|
+
engine: "34b5a692b7bd79939a9a2c3ef97d816e749cda2f"
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
Prisma.PrismaClientKnownRequestError = () => {
|
|
@@ -403,8 +403,8 @@ export namespace Prisma {
|
|
|
403
403
|
export import Exact = $Public.Exact
|
|
404
404
|
|
|
405
405
|
/**
|
|
406
|
-
* Prisma Client JS version: 6.
|
|
407
|
-
* Query Engine version:
|
|
406
|
+
* Prisma Client JS version: 6.18.0
|
|
407
|
+
* Query Engine version: 34b5a692b7bd79939a9a2c3ef97d816e749cda2f
|
|
408
408
|
*/
|
|
409
409
|
export type PrismaVersion = {
|
|
410
410
|
client: string
|
|
@@ -417,6 +417,7 @@ export namespace Prisma {
|
|
|
417
417
|
*/
|
|
418
418
|
|
|
419
419
|
|
|
420
|
+
export import Bytes = runtime.Bytes
|
|
420
421
|
export import JsonObject = runtime.JsonObject
|
|
421
422
|
export import JsonArray = runtime.JsonArray
|
|
422
423
|
export import JsonValue = runtime.JsonValue
|
|
@@ -35,12 +35,12 @@ exports.Prisma = Prisma
|
|
|
35
35
|
exports.$Enums = {}
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
|
-
* Prisma Client JS version: 6.
|
|
39
|
-
* Query Engine version:
|
|
38
|
+
* Prisma Client JS version: 6.18.0
|
|
39
|
+
* Query Engine version: 34b5a692b7bd79939a9a2c3ef97d816e749cda2f
|
|
40
40
|
*/
|
|
41
41
|
Prisma.prismaVersion = {
|
|
42
|
-
client: "6.
|
|
43
|
-
engine: "
|
|
42
|
+
client: "6.18.0",
|
|
43
|
+
engine: "34b5a692b7bd79939a9a2c3ef97d816e749cda2f"
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
Prisma.PrismaClientKnownRequestError = PrismaClientKnownRequestError;
|
|
@@ -292,8 +292,8 @@ const config = {
|
|
|
292
292
|
"rootEnvPath": null
|
|
293
293
|
},
|
|
294
294
|
"relativePath": "../../prisma-mongodb",
|
|
295
|
-
"clientVersion": "6.
|
|
296
|
-
"engineVersion": "
|
|
295
|
+
"clientVersion": "6.18.0",
|
|
296
|
+
"engineVersion": "34b5a692b7bd79939a9a2c3ef97d816e749cda2f",
|
|
297
297
|
"datasourceNames": [
|
|
298
298
|
"db"
|
|
299
299
|
],
|
|
Binary file
|
|
Binary file
|