@reldens/storage 0.92.0 → 0.93.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/CLAUDE.md +14 -7
- package/lib/generators/models-generation.js +5 -3
- package/lib/mikro-orm/mikro-orm-data-server.js +1 -1
- package/lib/mikro-orm/mikro-orm-driver.js +8 -8
- package/lib/prisma/prisma-client-loader.js +3 -2
- package/lib/prisma/prisma-data-server.js +2 -1
- package/lib/prisma/prisma-metadata-loader.js +2 -1
- package/lib/prisma/prisma-schema-generator.js +11 -6
- package/package.json +11 -10
- package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-categories-model.js +1 -1
- package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-products-model.js +3 -3
- package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-reviews-model.js +2 -2
- package/tests/utils/prisma-subprocess-worker.js +23 -22
- package/tests/utils/test-helpers.js +25 -13
package/CLAUDE.md
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
# CLAUDE.md
|
|
2
|
-
|
|
3
|
-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
-
|
|
5
1
|
## ⚠️ CRITICAL: The Library Works - Fix The Tests
|
|
6
2
|
|
|
7
3
|
**This package is battle-tested in hundreds of production projects handling thousands of API calls successfully.**
|
|
@@ -128,6 +124,10 @@ npx reldens-storage-prisma --host=<host> --database=<db> --user=<user> --passwor
|
|
|
128
124
|
- MongoDB support
|
|
129
125
|
- Entity metadata decorators
|
|
130
126
|
- Automatic schema synchronization
|
|
127
|
+
- **MikroORM v7 breaking changes applied:**
|
|
128
|
+
- `prop.joinColumn` renamed to `prop.joinColumns` (now an array) - use `prop.joinColumns[0]`
|
|
129
|
+
- `entity` in relation properties must be a function reference, not a string: `entity: () => require('./model-file').ModelClass`
|
|
130
|
+
- `orm.driver.connection.options` removed (private in v7) - use `orm.config.get('dbName')` instead
|
|
131
131
|
|
|
132
132
|
**Prisma Driver** (`lib/prisma/`):
|
|
133
133
|
- `prisma-driver.js`: Driver implementation with enhanced validation
|
|
@@ -144,11 +144,17 @@ npx reldens-storage-prisma --host=<host> --database=<db> --user=<user> --passwor
|
|
|
144
144
|
- Database default value support (skips validation for fields with defaults)
|
|
145
145
|
- VARCHAR foreign key support using relation connect syntax
|
|
146
146
|
- Introspection via `prisma db pull`
|
|
147
|
-
- Binary targets configuration
|
|
148
147
|
- Data proxy support
|
|
149
148
|
- Windows permission error handling
|
|
150
149
|
- **Prisma.DbNull handling**: PrismaDataServer passes `Prisma.DbNull` to driver, which passes it to type caster
|
|
151
150
|
- **Type caster isolation**: PrismaTypeCaster never requires `@prisma/client` directly, receives `prismaDbNull` as prop
|
|
151
|
+
- **Prisma v7 breaking changes applied:**
|
|
152
|
+
- Requires `@prisma/adapter-mariadb` for MySQL connections (WASM engine mandates a driver adapter)
|
|
153
|
+
- `datasource` block in `schema.prisma` no longer accepts `url` - connection URL is provided via `prisma.config.js` generated at project root using `{ datasource: { url: process.env.DATABASE_URL } }`
|
|
154
|
+
- `PrismaClient` constructor no longer accepts `datasources` or `datasourceUrl` - use `adapter: new PrismaMariaDb(connectionString)` instead
|
|
155
|
+
- `provider = "prisma-client-js"` is kept (deprecated but functional); switching to `prisma-client` would require additional adapter changes
|
|
156
|
+
- `_runtimeDataModel` in Prisma 7 is pruned: fields only contain `{ name, kind, type, relationName, dbName }` - `isId`, `isRequired`, `hasDefaultValue` are stripped. ID field detection falls back to `field.name === 'id' && field.kind === 'scalar'`
|
|
157
|
+
- `prisma.config.js` at project root is generated automatically by `PrismaSchemaGenerator.generateConfigFile()` and cleaned up after tests
|
|
152
158
|
|
|
153
159
|
### Generators
|
|
154
160
|
|
|
@@ -465,9 +471,10 @@ PrismaClientLoader.load(projectPath, customPath, connectionData)
|
|
|
465
471
|
- Otherwise, uses a default path: `projectPath/prisma/client`
|
|
466
472
|
- Validates that Prisma Client exists at the path
|
|
467
473
|
- Requires `prismaModule.PrismaClient` export
|
|
468
|
-
- If `connectionData` is null:
|
|
469
|
-
- If `connectionData` is provided: Builds
|
|
474
|
+
- If `connectionData` is null: Creates adapter using `process.env.DATABASE_URL`
|
|
475
|
+
- If `connectionData` is provided: Builds connection string and creates `PrismaMariaDb` adapter
|
|
470
476
|
- Returns initialized PrismaClient instance
|
|
477
|
+
- **Prisma v7**: Uses `@prisma/adapter-mariadb` - `PrismaClient` constructor receives `{ adapter }` instead of `{ datasources }`
|
|
471
478
|
|
|
472
479
|
**Usage Examples:**
|
|
473
480
|
|
|
@@ -528,12 +528,13 @@ class ModelsGeneration extends BaseGenerator
|
|
|
528
528
|
for(let relationKey of Object.keys(relations)){
|
|
529
529
|
let relation = relations[relationKey];
|
|
530
530
|
let relatedModelClass = sc.capitalizedCamelCase(relation.referencedTable)+'Model';
|
|
531
|
+
let relatedModelFile = sc.kebabCase(relation.referencedTable)+'-model';
|
|
531
532
|
let kind = sc.get(this.mikroOrmRelationKindMap, relation.relationType, 'm:1');
|
|
532
533
|
let propDef = relationKey+': {\n';
|
|
533
534
|
propDef += ' kind: \''+kind+'\',\n';
|
|
534
|
-
propDef += ' entity: \''+
|
|
535
|
+
propDef += ' entity: () => require(\'./'+relatedModelFile+'\').'+relatedModelClass;
|
|
535
536
|
if(relation.fromColumn){
|
|
536
|
-
propDef += ',\n
|
|
537
|
+
propDef += ',\n joinColumns: [\''+relation.fromColumn+'\']';
|
|
537
538
|
}
|
|
538
539
|
propDef += '\n }';
|
|
539
540
|
entityProps.push(propDef);
|
|
@@ -542,11 +543,12 @@ class ModelsGeneration extends BaseGenerator
|
|
|
542
543
|
for(let relationKey of Object.keys(reverseRelations)){
|
|
543
544
|
let relation = reverseRelations[relationKey];
|
|
544
545
|
let relatedModelClass = sc.capitalizedCamelCase(relation.referencingTable)+'Model';
|
|
546
|
+
let relatedModelFile = sc.kebabCase(relation.referencingTable)+'-model';
|
|
545
547
|
let kind = sc.get(this.mikroOrmRelationKindMap, relation.relationType, '1:m');
|
|
546
548
|
let mappedBy = this.findMappedByKey(tableName, relation.referencingTable, relation);
|
|
547
549
|
let propDef = relationKey+': {\n';
|
|
548
550
|
propDef += ' kind: \''+kind+'\',\n';
|
|
549
|
-
propDef += ' entity: \''+
|
|
551
|
+
propDef += ' entity: () => require(\'./'+relatedModelFile+'\').'+relatedModelClass;
|
|
550
552
|
if(mappedBy){
|
|
551
553
|
propDef += ',\n mappedBy: \''+mappedBy+'\'';
|
|
552
554
|
}
|
|
@@ -215,13 +215,13 @@ class MikroOrmDriver extends BaseDriver
|
|
|
215
215
|
continue;
|
|
216
216
|
}
|
|
217
217
|
let alias = 'rel_'+aliasCounter;
|
|
218
|
-
if('m:1' === prop.kind && prop.
|
|
219
|
-
queryBuilder.leftJoin(relationName, alias, 'e.'+prop.
|
|
218
|
+
if('m:1' === prop.kind && prop.joinColumns && prop.joinColumns[0]){
|
|
219
|
+
queryBuilder.leftJoin(relationName, alias, 'e.'+prop.joinColumns[0]+' = '+alias+'.id');
|
|
220
220
|
}
|
|
221
221
|
if('1:m' === prop.kind && prop.mappedBy){
|
|
222
222
|
let mappedProp = relationDriver.entitySchema.meta.properties[prop.mappedBy];
|
|
223
|
-
if(mappedProp && mappedProp.
|
|
224
|
-
queryBuilder.leftJoin(relationName, alias, 'e.id = '+alias+'.'+mappedProp.
|
|
223
|
+
if(mappedProp && mappedProp.joinColumns && mappedProp.joinColumns[0]){
|
|
224
|
+
queryBuilder.leftJoin(relationName, alias, 'e.id = '+alias+'.'+mappedProp.joinColumns[0]);
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
227
|
aliasCounter++;
|
|
@@ -505,8 +505,8 @@ class MikroOrmDriver extends BaseDriver
|
|
|
505
505
|
async createOne(params, relationName, relationDriver, newInstance, prop)
|
|
506
506
|
{
|
|
507
507
|
let nestedData = params[relationName];
|
|
508
|
-
if(prop.
|
|
509
|
-
nestedData[prop.
|
|
508
|
+
if(prop.joinColumns && prop.joinColumns[0]){
|
|
509
|
+
nestedData[prop.joinColumns[0]] = newInstance.id;
|
|
510
510
|
}
|
|
511
511
|
let nestedObject = await relationDriver.create(nestedData);
|
|
512
512
|
await this.orm.em.flush();
|
|
@@ -517,8 +517,8 @@ class MikroOrmDriver extends BaseDriver
|
|
|
517
517
|
{
|
|
518
518
|
let nestedArray = [];
|
|
519
519
|
for(let objectData of params[relationName]){
|
|
520
|
-
if(prop.
|
|
521
|
-
objectData[prop.
|
|
520
|
+
if(prop.joinColumns && prop.joinColumns[0]){
|
|
521
|
+
objectData[prop.joinColumns[0]] = newInstance.id;
|
|
522
522
|
}
|
|
523
523
|
let nestedObject = await relationDriver.create(objectData);
|
|
524
524
|
await this.orm.em.flush();
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
const { Logger } = require('@reldens/utils');
|
|
8
8
|
const { FileHandler } = require('@reldens/server-utils');
|
|
9
|
+
const { PrismaMariaDb } = require('@prisma/adapter-mariadb');
|
|
9
10
|
|
|
10
11
|
class PrismaClientLoader
|
|
11
12
|
{
|
|
@@ -28,7 +29,7 @@ class PrismaClientLoader
|
|
|
28
29
|
}
|
|
29
30
|
if(!connectionData){
|
|
30
31
|
Logger.info('Creating PrismaClient with default connection from schema');
|
|
31
|
-
return new prismaModule.PrismaClient({log: ['error']});
|
|
32
|
+
return new prismaModule.PrismaClient({adapter: new PrismaMariaDb(process.env.DATABASE_URL), log: ['error']});
|
|
32
33
|
}
|
|
33
34
|
let connectionString = connectionData.client+'://'
|
|
34
35
|
+connectionData.user
|
|
@@ -37,7 +38,7 @@ class PrismaClientLoader
|
|
|
37
38
|
+':'+connectionData.port
|
|
38
39
|
+'/'+connectionData.database;
|
|
39
40
|
Logger.info('Creating PrismaClient with connection to: '+connectionData.database);
|
|
40
|
-
return new prismaModule.PrismaClient({
|
|
41
|
+
return new prismaModule.PrismaClient({adapter: new PrismaMariaDb(connectionString), log: ['error']});
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
}
|
|
@@ -8,6 +8,7 @@ const { BaseDataServer } = require('../base-data-server');
|
|
|
8
8
|
const { PrismaDriver } = require('./prisma-driver');
|
|
9
9
|
const { MySQLTablesProvider } = require('../mysql-tables-provider');
|
|
10
10
|
const { PrismaClient, Prisma } = require('@prisma/client');
|
|
11
|
+
const { PrismaMariaDb } = require('@prisma/adapter-mariadb');
|
|
11
12
|
const { FileHandler } = require('@reldens/server-utils');
|
|
12
13
|
const { Logger, sc } = require('@reldens/utils');
|
|
13
14
|
|
|
@@ -30,7 +31,7 @@ class PrismaDataServer extends BaseDataServer
|
|
|
30
31
|
try {
|
|
31
32
|
if(!this.prisma && this.defaultClientIsGenerated()){
|
|
32
33
|
this.prisma = new PrismaClient({
|
|
33
|
-
|
|
34
|
+
adapter: new PrismaMariaDb(this.connectString),
|
|
34
35
|
log: this.debug ? ['query', 'info', 'warn', 'error'] : ['error']
|
|
35
36
|
});
|
|
36
37
|
}
|
|
@@ -79,7 +79,8 @@ class PrismaMetadataLoader
|
|
|
79
79
|
if('Json' === field.type){
|
|
80
80
|
metadata.jsonFields.add(field.name);
|
|
81
81
|
}
|
|
82
|
-
|
|
82
|
+
let isIdField = field.isId || ('id' === field.name && 'scalar' === field.kind);
|
|
83
|
+
if(isIdField){
|
|
83
84
|
metadata.idFieldType = field.type;
|
|
84
85
|
metadata.idFieldName = field.name;
|
|
85
86
|
}
|
|
@@ -31,6 +31,7 @@ class PrismaSchemaGenerator
|
|
|
31
31
|
FileHandler.createFolder(this.prismaSchemaPath);
|
|
32
32
|
this.generateSchemaFile();
|
|
33
33
|
this.setDatabaseEnvironmentVariables();
|
|
34
|
+
this.generateConfigFile();
|
|
34
35
|
Logger.info('Running prisma introspect "npx prisma db pull"...');
|
|
35
36
|
try {
|
|
36
37
|
execSync('npx prisma db pull', {stdio: 'inherit'});
|
|
@@ -64,9 +65,9 @@ class PrismaSchemaGenerator
|
|
|
64
65
|
setDatabaseEnvironmentVariables()
|
|
65
66
|
{
|
|
66
67
|
let datasourceProvider = this.getDatasourceProvider();
|
|
67
|
-
process.env.
|
|
68
|
+
process.env.DATABASE_URL = this.buildConnectionString(datasourceProvider);
|
|
68
69
|
if(this.dataProxy){
|
|
69
|
-
process.env.
|
|
70
|
+
process.env.DATABASE_DIRECT_URL = this.buildDirectConnectionString(datasourceProvider);
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
|
|
@@ -105,6 +106,14 @@ class PrismaSchemaGenerator
|
|
|
105
106
|
return FileHandler.joinPaths(this.prismaSchemaPath, clientPath);
|
|
106
107
|
}
|
|
107
108
|
|
|
109
|
+
generateConfigFile()
|
|
110
|
+
{
|
|
111
|
+
let configContent = 'module.exports = { datasource: { url: process.env.DATABASE_URL } };\n';
|
|
112
|
+
let configPath = FileHandler.joinPaths(process.cwd(), 'prisma.config.js');
|
|
113
|
+
FileHandler.writeFile(configPath, configContent);
|
|
114
|
+
Logger.info('Generated Prisma config file at: '+configPath);
|
|
115
|
+
}
|
|
116
|
+
|
|
108
117
|
generateSchemaFile()
|
|
109
118
|
{
|
|
110
119
|
let datasourceProvider = this.getDatasourceProvider();
|
|
@@ -176,10 +185,6 @@ class PrismaSchemaGenerator
|
|
|
176
185
|
{
|
|
177
186
|
let datasourceContent = 'datasource db {\n';
|
|
178
187
|
datasourceContent += ' provider = "'+datasourceProvider+'"\n';
|
|
179
|
-
datasourceContent += ' url = env("RELDENS_DB_URL")\n';
|
|
180
|
-
if(this.dataProxy){
|
|
181
|
-
datasourceContent += ' directUrl = env("RELDENS_DB_DIRECT_URL")\n';
|
|
182
|
-
}
|
|
183
188
|
datasourceContent += '}';
|
|
184
189
|
return datasourceContent;
|
|
185
190
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reldens/storage",
|
|
3
3
|
"scope": "@reldens",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.93.0",
|
|
5
5
|
"description": "Reldens - Storage",
|
|
6
6
|
"author": "Damian A. Pastorini",
|
|
7
7
|
"license": "MIT",
|
|
@@ -51,16 +51,17 @@
|
|
|
51
51
|
"test:driver": "node tests/run-tests.js --driver="
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@mikro-orm/core": "
|
|
55
|
-
"@mikro-orm/mongodb": "
|
|
56
|
-
"@mikro-orm/mysql": "
|
|
57
|
-
"@prisma/
|
|
58
|
-
"@
|
|
59
|
-
"@reldens/utils": "^0.
|
|
60
|
-
"
|
|
54
|
+
"@mikro-orm/core": "7.0.11",
|
|
55
|
+
"@mikro-orm/mongodb": "7.0.11",
|
|
56
|
+
"@mikro-orm/mysql": "7.0.11",
|
|
57
|
+
"@prisma/adapter-mariadb": "^7.7.0",
|
|
58
|
+
"@prisma/client": "7.7.0",
|
|
59
|
+
"@reldens/server-utils": "^0.49.0",
|
|
60
|
+
"@reldens/utils": "^0.56.0",
|
|
61
|
+
"knex": "3.2.9",
|
|
61
62
|
"mysql": "2.18.1",
|
|
62
|
-
"mysql2": "3.
|
|
63
|
+
"mysql2": "3.22.2",
|
|
63
64
|
"objection": "3.1.5",
|
|
64
|
-
"prisma": "
|
|
65
|
+
"prisma": "7.7.0"
|
|
65
66
|
}
|
|
66
67
|
}
|
package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-categories-model.js
CHANGED
|
@@ -44,7 +44,7 @@ const schema = new EntitySchema({
|
|
|
44
44
|
updated_at: { type: 'Date', nullable: true },
|
|
45
45
|
related_test_products: {
|
|
46
46
|
kind: '1:m',
|
|
47
|
-
entity: 'TestProductsModel
|
|
47
|
+
entity: () => require('./test-products-model').TestProductsModel,
|
|
48
48
|
mappedBy: 'related_test_categories'
|
|
49
49
|
}
|
|
50
50
|
},
|
|
@@ -54,12 +54,12 @@ const schema = new EntitySchema({
|
|
|
54
54
|
updated_at: { type: 'Date', nullable: true },
|
|
55
55
|
related_test_categories: {
|
|
56
56
|
kind: 'm:1',
|
|
57
|
-
entity: 'TestCategoriesModel
|
|
58
|
-
|
|
57
|
+
entity: () => require('./test-categories-model').TestCategoriesModel,
|
|
58
|
+
joinColumns: ['category_id']
|
|
59
59
|
},
|
|
60
60
|
related_test_reviews: {
|
|
61
61
|
kind: '1:m',
|
|
62
|
-
entity: 'TestReviewsModel
|
|
62
|
+
entity: () => require('./test-reviews-model').TestReviewsModel,
|
|
63
63
|
mappedBy: 'related_test_products'
|
|
64
64
|
}
|
|
65
65
|
},
|
|
@@ -50,8 +50,8 @@ const schema = new EntitySchema({
|
|
|
50
50
|
updated_at: { type: 'Date', nullable: true },
|
|
51
51
|
related_test_products: {
|
|
52
52
|
kind: 'm:1',
|
|
53
|
-
entity: 'TestProductsModel
|
|
54
|
-
|
|
53
|
+
entity: () => require('./test-products-model').TestProductsModel,
|
|
54
|
+
joinColumns: ['product_id']
|
|
55
55
|
}
|
|
56
56
|
},
|
|
57
57
|
});
|
|
@@ -8,7 +8,6 @@ const { FileHandler } = require('@reldens/server-utils');
|
|
|
8
8
|
const { Logger, sc } = require('@reldens/utils');
|
|
9
9
|
const { exec } = require('child_process');
|
|
10
10
|
const { promisify } = require('util');
|
|
11
|
-
const execAsync = promisify(exec);
|
|
12
11
|
|
|
13
12
|
class PrismaTestSubprocessWorker
|
|
14
13
|
{
|
|
@@ -25,19 +24,16 @@ class PrismaTestSubprocessWorker
|
|
|
25
24
|
await this.processIncomingMessage(message);
|
|
26
25
|
} catch(error) {
|
|
27
26
|
Logger.error('PrismaTestSubprocessWorker error: '+error.message);
|
|
28
|
-
this.sendErrorResponse(error.message);
|
|
29
|
-
setTimeout(() => process.exit(1), 100);
|
|
27
|
+
this.sendErrorResponse(error.message, () => process.exit(1));
|
|
30
28
|
}
|
|
31
29
|
});
|
|
32
30
|
process.on('uncaughtException', (error) => {
|
|
33
31
|
Logger.error('PrismaTestSubprocessWorker uncaught exception: '+error.message);
|
|
34
|
-
this.sendErrorResponse(error.message);
|
|
35
|
-
setTimeout(() => process.exit(1), 100);
|
|
32
|
+
this.sendErrorResponse(error.message, () => process.exit(1));
|
|
36
33
|
});
|
|
37
34
|
process.on('unhandledRejection', (error) => {
|
|
38
35
|
Logger.error('PrismaTestSubprocessWorker unhandled rejection: '+error.message);
|
|
39
|
-
this.sendErrorResponse(error.message);
|
|
40
|
-
setTimeout(() => process.exit(1), 100);
|
|
36
|
+
this.sendErrorResponse(error.message, () => process.exit(1));
|
|
41
37
|
});
|
|
42
38
|
}
|
|
43
39
|
|
|
@@ -94,10 +90,17 @@ class PrismaTestSubprocessWorker
|
|
|
94
90
|
|
|
95
91
|
async generateMinimalPrismaClient(projectRoot, config)
|
|
96
92
|
{
|
|
93
|
+
let execAsync = promisify(exec);
|
|
97
94
|
let prismaPath = FileHandler.joinPaths(projectRoot, 'prisma');
|
|
98
95
|
let schemaPath = FileHandler.joinPaths(prismaPath, 'schema.prisma');
|
|
99
96
|
FileHandler.createFolder(prismaPath);
|
|
100
|
-
|
|
97
|
+
FileHandler.writeFile(
|
|
98
|
+
FileHandler.joinPaths(projectRoot, 'prisma.config.js'),
|
|
99
|
+
'module.exports = { datasource: { url: \'mysql://'
|
|
100
|
+
+config.user+':'+config.password
|
|
101
|
+
+'@'+config.host+':'+config.port
|
|
102
|
+
+'/'+config.database+'\' } };\n'
|
|
103
|
+
);
|
|
101
104
|
let schemaContent = 'generator client {\n'
|
|
102
105
|
+ ' provider = "prisma-client-js"\n'
|
|
103
106
|
+ ' output = "./client"\n'
|
|
@@ -105,32 +108,30 @@ class PrismaTestSubprocessWorker
|
|
|
105
108
|
+ '\n'
|
|
106
109
|
+ 'datasource db {\n'
|
|
107
110
|
+ ' provider = "mysql"\n'
|
|
108
|
-
+ ' url = "'+dbUrl+'"\n'
|
|
109
111
|
+ '}';
|
|
110
112
|
FileHandler.writeFile(schemaPath, schemaContent);
|
|
111
113
|
Logger.info('Subprocess: Running prisma db pull to introspect database...');
|
|
112
114
|
try {
|
|
113
|
-
|
|
114
|
-
if(pullStderr && !pullStderr.includes('Introspected')){
|
|
115
|
-
Logger.warning('Subprocess: Prisma db pull stderr: '+pullStderr);
|
|
116
|
-
}
|
|
115
|
+
await execAsync('npx prisma db pull', {cwd: projectRoot});
|
|
117
116
|
Logger.info('Subprocess: Database introspection completed');
|
|
118
117
|
} catch(error) {
|
|
119
|
-
Logger.critical('Subprocess: Prisma db pull failed:
|
|
118
|
+
Logger.critical('Subprocess: Prisma db pull failed:', error.message, error.stdout, error.stderr);
|
|
120
119
|
return false;
|
|
121
120
|
}
|
|
122
121
|
Logger.info('Subprocess: Running prisma generate...');
|
|
123
122
|
try {
|
|
124
|
-
|
|
125
|
-
if(stderr && !stderr.includes('Generated Prisma Client')){
|
|
126
|
-
Logger.warning('Subprocess: Prisma generate stderr: '+stderr);
|
|
127
|
-
}
|
|
123
|
+
await execAsync('npx prisma generate', {cwd: projectRoot});
|
|
128
124
|
Logger.info('Subprocess: Prisma client generated successfully');
|
|
129
125
|
let clientPath = FileHandler.joinPaths(projectRoot, 'prisma', 'client');
|
|
130
126
|
let { PrismaClient } = require(clientPath);
|
|
131
|
-
|
|
127
|
+
let { PrismaMariaDb } = require('@prisma/adapter-mariadb');
|
|
128
|
+
return new PrismaClient({
|
|
129
|
+
adapter: new PrismaMariaDb(
|
|
130
|
+
'mysql://'+config.user+':'+config.password+'@'+config.host+':'+config.port+'/'+config.database
|
|
131
|
+
)
|
|
132
|
+
});
|
|
132
133
|
} catch(error) {
|
|
133
|
-
Logger.critical('Subprocess: Prisma generate failed:
|
|
134
|
+
Logger.critical('Subprocess: Prisma generate failed:', error.message, error.stdout, error.stderr);
|
|
134
135
|
return false;
|
|
135
136
|
}
|
|
136
137
|
}
|
|
@@ -140,9 +141,9 @@ class PrismaTestSubprocessWorker
|
|
|
140
141
|
process.send({success: true, message: message});
|
|
141
142
|
}
|
|
142
143
|
|
|
143
|
-
sendErrorResponse(errorMessage)
|
|
144
|
+
sendErrorResponse(errorMessage, callback)
|
|
144
145
|
{
|
|
145
|
-
process.send({success: false, error: errorMessage});
|
|
146
|
+
process.send({success: false, error: errorMessage}, callback);
|
|
146
147
|
}
|
|
147
148
|
|
|
148
149
|
}
|
|
@@ -44,7 +44,7 @@ class TestHelpers
|
|
|
44
44
|
rawEntities: rawEntities
|
|
45
45
|
};
|
|
46
46
|
if('prisma' === driverName){
|
|
47
|
-
let prismaClient = await this.loadPrismaClient(process.cwd());
|
|
47
|
+
let prismaClient = await this.loadPrismaClient(process.cwd(), config);
|
|
48
48
|
if(!prismaClient){
|
|
49
49
|
throw new Error('Failed to load Prisma client');
|
|
50
50
|
}
|
|
@@ -278,15 +278,15 @@ class TestHelpers
|
|
|
278
278
|
static verifyAllPackages()
|
|
279
279
|
{
|
|
280
280
|
let required = [
|
|
281
|
-
{name: '@mikro-orm/core', version: '
|
|
282
|
-
{name: "@mikro-orm/mongodb", version: "
|
|
283
|
-
{name: '@mikro-orm/mysql', version: '
|
|
284
|
-
{name: '@prisma/client', version: '
|
|
285
|
-
{name: 'knex', version: '3.
|
|
281
|
+
{name: '@mikro-orm/core', version: '7.0.11'},
|
|
282
|
+
{name: "@mikro-orm/mongodb", version: "7.0.11"},
|
|
283
|
+
{name: '@mikro-orm/mysql', version: '7.0.11'},
|
|
284
|
+
{name: '@prisma/client', version: '7.7.0'},
|
|
285
|
+
{name: 'knex', version: '3.2.9'},
|
|
286
286
|
{name: 'mysql', version: '2.18.1'},
|
|
287
|
-
{name: 'mysql2', version: '3.
|
|
287
|
+
{name: 'mysql2', version: '3.22.2'},
|
|
288
288
|
{name: 'objection', version: '3.1.5'},
|
|
289
|
-
{name: 'prisma', version: '
|
|
289
|
+
{name: 'prisma', version: '7.7.0'}
|
|
290
290
|
];
|
|
291
291
|
let allVerified = true;
|
|
292
292
|
for(let pkg of required){
|
|
@@ -371,7 +371,7 @@ class TestHelpers
|
|
|
371
371
|
return subprocessSuccess;
|
|
372
372
|
}
|
|
373
373
|
|
|
374
|
-
static async loadPrismaClient(projectRoot)
|
|
374
|
+
static async loadPrismaClient(projectRoot, config)
|
|
375
375
|
{
|
|
376
376
|
try {
|
|
377
377
|
let clientPath = FileHandler.joinPaths(projectRoot, 'prisma', 'client');
|
|
@@ -384,7 +384,11 @@ class TestHelpers
|
|
|
384
384
|
Logger.critical('PrismaClient not found in module.');
|
|
385
385
|
return false;
|
|
386
386
|
}
|
|
387
|
-
let
|
|
387
|
+
let { PrismaMariaDb } = require('@prisma/adapter-mariadb');
|
|
388
|
+
let adapterConfig = config
|
|
389
|
+
? { host: config.host, port: config.port, user: config.user, password: config.password, database: config.database }
|
|
390
|
+
: process.env.DATABASE_URL;
|
|
391
|
+
let client = new PrismaClient({ adapter: new PrismaMariaDb(adapterConfig) });
|
|
388
392
|
await client.$connect();
|
|
389
393
|
return client;
|
|
390
394
|
} catch(error) {
|
|
@@ -400,6 +404,11 @@ class TestHelpers
|
|
|
400
404
|
Logger.info('Cleaning up Prisma folder: '+prismaPath);
|
|
401
405
|
FileHandler.remove(prismaPath);
|
|
402
406
|
}
|
|
407
|
+
let prismaConfigPath = FileHandler.joinPaths(process.cwd(), 'prisma.config.js');
|
|
408
|
+
if(FileHandler.exists(prismaConfigPath)){
|
|
409
|
+
Logger.info('Cleaning up Prisma config file: '+prismaConfigPath);
|
|
410
|
+
FileHandler.remove(prismaConfigPath);
|
|
411
|
+
}
|
|
403
412
|
let entitiesPath = FileHandler.joinPaths(process.cwd(), 'generated-entities');
|
|
404
413
|
if(FileHandler.exists(entitiesPath)){
|
|
405
414
|
Logger.info('Cleaning up generated entities folder: '+entitiesPath);
|
|
@@ -437,7 +446,7 @@ class TestHelpers
|
|
|
437
446
|
Logger.critical('Prisma schema not found at: '+schemaPath);
|
|
438
447
|
return false;
|
|
439
448
|
}
|
|
440
|
-
let cmd = 'npx prisma generate
|
|
449
|
+
let cmd = 'npx prisma generate';
|
|
441
450
|
Logger.info('Generating Prisma client...');
|
|
442
451
|
try {
|
|
443
452
|
let { stdout, stderr } = await execAsync(cmd);
|
|
@@ -605,7 +614,10 @@ class TestHelpers
|
|
|
605
614
|
let expectedFiles = FileHandler.getFilesInFolder(expectedPath, ['.js']);
|
|
606
615
|
let generatedFiles = FileHandler.getFilesInFolder(generatedPath, ['.js']);
|
|
607
616
|
if(expectedFiles.length !== generatedFiles.length){
|
|
608
|
-
throw new Error(
|
|
617
|
+
throw new Error(
|
|
618
|
+
'File count mismatch in '+relativePath+':'
|
|
619
|
+
+' expected '+expectedFiles.length+', got '+generatedFiles.length
|
|
620
|
+
);
|
|
609
621
|
}
|
|
610
622
|
for(let filename of expectedFiles){
|
|
611
623
|
let expectedContent = FileHandler.readFile(FileHandler.joinPaths(expectedPath, filename));
|
|
@@ -678,7 +690,7 @@ class TestHelpers
|
|
|
678
690
|
throw new Error('Failed to generate Prisma client');
|
|
679
691
|
}
|
|
680
692
|
await dataServer.disconnect();
|
|
681
|
-
delete require.cache[require.resolve('
|
|
693
|
+
delete require.cache[require.resolve(FileHandler.joinPaths(process.cwd(), 'prisma', 'client'))];
|
|
682
694
|
await dataServer.connect();
|
|
683
695
|
}
|
|
684
696
|
}
|