@reldens/storage 0.117.0 → 0.119.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/test-architecture.md +27 -17
- package/CLAUDE.md +67 -11
- package/README.md +204 -22
- package/bin/reldens-storage.js +43 -10
- package/index.js +53 -12
- package/lib/drizzle/drizzle-data-server.js +123 -0
- package/lib/drizzle/drizzle-driver.js +228 -0
- package/lib/drizzle/drizzle-models-generation.js +49 -0
- package/lib/drizzle/drizzle-modules-loader.js +32 -0
- package/lib/drizzle/drizzle-modules-validator.js +74 -0
- package/lib/entities-generator.js +36 -7
- package/lib/entity-templates/drizzle-model.template +28 -0
- package/lib/entity-templates/query-builder-model.template +17 -0
- package/lib/generators/base-generator.js +13 -0
- package/lib/generators/entities-generation.js +0 -13
- package/lib/generators/models-generation.js +179 -680
- package/lib/generators/relations-detection.js +171 -0
- package/lib/knex/knex-data-server.js +128 -0
- package/lib/knex/knex-driver.js +157 -0
- package/lib/knex/knex-modules-loader.js +28 -0
- package/lib/knex/knex-modules-validator.js +45 -0
- package/lib/kysely/kysely-data-server.js +128 -0
- package/lib/kysely/kysely-driver.js +176 -0
- package/lib/kysely/kysely-modules-loader.js +28 -0
- package/lib/kysely/kysely-modules-validator.js +53 -0
- package/lib/mikro-orm/mikro-orm-data-server.js +48 -29
- package/lib/mikro-orm/mikro-orm-driver.js +317 -108
- package/lib/mikro-orm/mikro-orm-models-generation.js +178 -0
- package/lib/mikro-orm/mikro-orm-modules-loader.js +50 -0
- package/lib/mikro-orm/mikro-orm-modules-validator.js +46 -0
- package/lib/mysql2-connection-config.js +38 -0
- package/lib/objection-js/objection-js-data-server.js +71 -125
- package/lib/objection-js/objection-js-driver.js +4 -1
- package/lib/objection-js/objection-js-models-generation.js +98 -0
- package/lib/objection-js/objection-modules-loader.js +28 -0
- package/lib/objection-js/objection-modules-validator.js +31 -0
- package/lib/package-resolver.js +45 -0
- package/lib/prisma/prisma-client-loader.js +11 -1
- package/lib/prisma/prisma-driver.js +16 -2
- package/lib/prisma/prisma-filter-processor.js +5 -6
- package/lib/prisma/prisma-models-generation.js +236 -0
- package/lib/prisma/prisma-schema-generator.js +5 -1
- package/lib/prisma/prisma-type-caster.js +14 -0
- package/lib/query-builder-driver.js +210 -0
- package/lib/query-builder-models-generation.js +80 -0
- package/lib/relations-loader.js +192 -0
- package/lib/type-mapper.js +38 -0
- package/package.json +8 -8
- package/tests/.env.test.example +6 -0
- package/tests/fixtures/categories-fixtures.js +8 -0
- package/tests/fixtures/expected-entities/entities/test-product-details-entity.js +10 -1
- package/tests/fixtures/expected-entities/entities-translations.js +2 -0
- package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-categories-model.js +13 -8
- package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-product-details-model.js +30 -10
- package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-products-model.js +15 -14
- package/tests/fixtures/expected-entities-mikro-orm/models/mikro-orm/test-reviews-model.js +13 -12
- package/tests/fixtures/expected-entities-prisma/models/prisma/test-product-details-model.js +3 -1
- package/tests/fixtures/product-details-fixtures.js +4 -1
- package/tests/fixtures/reviews-fixtures.js +2 -1
- package/tests/fixtures/sql/test-schema.sql +11 -2
- package/tests/fixtures/table-columns-fixtures.js +97 -0
- package/tests/integration/test-cross-driver-equivalence.js +286 -0
- package/tests/integration/test-nested-filters.js +265 -408
- package/tests/integration/test-relations.js +135 -0
- package/tests/integration/test-reldens-sample-data.js +255 -0
- package/tests/integration/test-reldens-shape-relations.js +292 -0
- package/tests/run-tests.js +111 -65
- package/tests/unit/test-drivers.js +7 -1
- package/tests/unit/test-models-generation.js +28 -18
- package/tests/utils/column-value-assert.js +139 -0
- package/tests/utils/entity-projection.js +111 -0
- package/tests/utils/observed-value.js +41 -0
- package/tests/utils/projection-difference.js +151 -0
- package/tests/utils/relations-shape-support.js +104 -0
- package/tests/utils/reldens-schema-loader.js +274 -0
- package/tests/utils/test-helpers.js +143 -13
- package/tests/utils/test-runner.js +26 -5
- package/tests/utils/whole-result-assert.js +243 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - DrizzleModulesValidator
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { Logger, sc } = require('@reldens/utils');
|
|
8
|
+
|
|
9
|
+
let requiredOrmFunctions = [
|
|
10
|
+
'eq', 'ne', 'gt', 'gte', 'lt', 'lte', 'inArray', 'like', 'isNull', 'and', 'or', 'not', 'asc', 'desc', 'count'
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
class DrizzleModulesValidator
|
|
14
|
+
{
|
|
15
|
+
|
|
16
|
+
static validate(drizzleModules)
|
|
17
|
+
{
|
|
18
|
+
if(!sc.isObject(drizzleModules)){
|
|
19
|
+
Logger.critical('Missing "drizzleModules" object.');
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
if(!DrizzleModulesValidator.validateOrm(drizzleModules.orm)){
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
if(drizzleModules.db){
|
|
26
|
+
return DrizzleModulesValidator.validateDbInstance(drizzleModules.db);
|
|
27
|
+
}
|
|
28
|
+
if(!sc.isFunction(drizzleModules.drizzle)){
|
|
29
|
+
Logger.critical('Invalid "drizzleModules.drizzle".');
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static validateOrm(orm)
|
|
36
|
+
{
|
|
37
|
+
if(!sc.isObject(orm)){
|
|
38
|
+
Logger.critical('Missing "drizzleModules.orm" namespace.');
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
let missingFunctions = requiredOrmFunctions.filter(ormFunction => !sc.isFunction(orm[ormFunction]));
|
|
42
|
+
if(0 < missingFunctions.length){
|
|
43
|
+
Logger.critical('Invalid "drizzleModules.orm", missing: '+missingFunctions.join(', '));
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
if(!sc.isFunction(orm.sql)){
|
|
47
|
+
Logger.critical('Invalid "drizzleModules.orm", "sql" not found.');
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
if(!sc.isFunction(orm.sql.raw)){
|
|
51
|
+
Logger.critical('Invalid "drizzleModules.orm", "sql.raw" not found.');
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static validateDbInstance(db)
|
|
58
|
+
{
|
|
59
|
+
let requiredMethods = ['select', 'insert', 'update', 'delete', 'execute'];
|
|
60
|
+
let missingMethods = requiredMethods.filter(method => !sc.isFunction(db[method]));
|
|
61
|
+
if(0 < missingMethods.length){
|
|
62
|
+
Logger.critical('Invalid Drizzle instance, missing: '+missingMethods.join(', '));
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
if(!sc.isObjectFunction(db.$client, 'end')){
|
|
66
|
+
Logger.critical('Invalid Drizzle instance, "$client.end" not found.');
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
module.exports.DrizzleModulesValidator = DrizzleModulesValidator;
|
|
@@ -9,6 +9,9 @@ const { Logger, sc } = require('@reldens/utils');
|
|
|
9
9
|
const { ObjectionJsDataServer } = require('./objection-js/objection-js-data-server');
|
|
10
10
|
const { MikroOrmDataServer } = require('./mikro-orm/mikro-orm-data-server');
|
|
11
11
|
const { PrismaDataServer } = require('./prisma/prisma-data-server');
|
|
12
|
+
const { KnexDataServer } = require('./knex/knex-data-server');
|
|
13
|
+
const { KyselyDataServer } = require('./kysely/kysely-data-server');
|
|
14
|
+
const { DrizzleDataServer } = require('./drizzle/drizzle-data-server');
|
|
12
15
|
const { PrismaRelationsMetadataExtractor } = require('./prisma/prisma-relations-metadata-extractor');
|
|
13
16
|
const { EntitiesGeneration } = require('./generators/entities-generation');
|
|
14
17
|
const { ModelsGeneration } = require('./generators/models-generation');
|
|
@@ -25,6 +28,9 @@ class EntitiesGenerator
|
|
|
25
28
|
'objection-js': FileHandler.joinPaths(this.templatesFolderPath, 'objection-js-model.template'),
|
|
26
29
|
'mikro-orm': FileHandler.joinPaths(this.templatesFolderPath, 'mikro-orm-model.template'),
|
|
27
30
|
'prisma': FileHandler.joinPaths(this.templatesFolderPath, 'prisma-model.template'),
|
|
31
|
+
'knex': FileHandler.joinPaths(this.templatesFolderPath, 'query-builder-model.template'),
|
|
32
|
+
'kysely': FileHandler.joinPaths(this.templatesFolderPath, 'query-builder-model.template'),
|
|
33
|
+
'drizzle': FileHandler.joinPaths(this.templatesFolderPath, 'drizzle-model.template'),
|
|
28
34
|
'entity': FileHandler.joinPaths(this.templatesFolderPath, 'entity.template'),
|
|
29
35
|
'entities-config': FileHandler.joinPaths(this.templatesFolderPath, 'entities-config.template'),
|
|
30
36
|
'entities-translations': FileHandler.joinPaths(this.templatesFolderPath, 'entities-translations.template'),
|
|
@@ -39,17 +45,36 @@ class EntitiesGenerator
|
|
|
39
45
|
this.driverMap = {
|
|
40
46
|
'objection-js': ObjectionJsDataServer,
|
|
41
47
|
'mikro-orm': MikroOrmDataServer,
|
|
42
|
-
'prisma': PrismaDataServer
|
|
48
|
+
'prisma': PrismaDataServer,
|
|
49
|
+
'knex': KnexDataServer,
|
|
50
|
+
'kysely': KyselyDataServer,
|
|
51
|
+
'drizzle': DrizzleDataServer
|
|
43
52
|
};
|
|
44
53
|
this.driversClassMap = {
|
|
45
54
|
'ObjectionJsDataServer': 'objection-js',
|
|
46
55
|
'MikroOrmDataServer': 'mikro-orm',
|
|
47
|
-
'PrismaDataServer': 'prisma'
|
|
56
|
+
'PrismaDataServer': 'prisma',
|
|
57
|
+
'KnexDataServer': 'knex',
|
|
58
|
+
'KyselyDataServer': 'kysely',
|
|
59
|
+
'DrizzleDataServer': 'drizzle'
|
|
48
60
|
};
|
|
49
61
|
this.server = sc.get(props, 'server', false);
|
|
50
62
|
this.connectionData = sc.get(props, 'connectionData', false);
|
|
51
63
|
this.isOverride = sc.get(props, 'isOverride', false);
|
|
64
|
+
this.driverModulesProps = {
|
|
65
|
+
'objection-js': 'objectionModules',
|
|
66
|
+
'mikro-orm': 'mikroOrmModules',
|
|
67
|
+
'prisma': 'prismaModules',
|
|
68
|
+
'knex': 'knexModules',
|
|
69
|
+
'kysely': 'kyselyModules',
|
|
70
|
+
'drizzle': 'drizzleModules'
|
|
71
|
+
};
|
|
52
72
|
this.prismaModules = sc.get(props, 'prismaModules', false);
|
|
73
|
+
this.kyselyModules = sc.get(props, 'kyselyModules', false);
|
|
74
|
+
this.drizzleModules = sc.get(props, 'drizzleModules', false);
|
|
75
|
+
this.objectionModules = sc.get(props, 'objectionModules', false);
|
|
76
|
+
this.knexModules = sc.get(props, 'knexModules', false);
|
|
77
|
+
this.mikroOrmModules = sc.get(props, 'mikroOrmModules', false);
|
|
53
78
|
this.generatedEntities = {};
|
|
54
79
|
this.existingEntities = {};
|
|
55
80
|
this.existingEntityFields = {};
|
|
@@ -64,7 +89,10 @@ class EntitiesGenerator
|
|
|
64
89
|
templates: {
|
|
65
90
|
'objection-js': this.templates['objection-js'],
|
|
66
91
|
'mikro-orm': this.templates['mikro-orm'],
|
|
67
|
-
'prisma': this.templates['prisma']
|
|
92
|
+
'prisma': this.templates['prisma'],
|
|
93
|
+
'knex': this.templates['knex'],
|
|
94
|
+
'kysely': this.templates['kysely'],
|
|
95
|
+
'drizzle': this.templates['drizzle']
|
|
68
96
|
}
|
|
69
97
|
});
|
|
70
98
|
this.entitiesConfigGeneration = new EntitiesConfigGeneration({
|
|
@@ -288,7 +316,7 @@ class EntitiesGenerator
|
|
|
288
316
|
Logger.critical('Failed to fetch driver key.');
|
|
289
317
|
return false;
|
|
290
318
|
}
|
|
291
|
-
this.modelsGeneration.
|
|
319
|
+
this.modelsGeneration.relationsDetection.allTablesData = tables;
|
|
292
320
|
let tablesToGenerate = this.filterTablesToGenerate(tables, driverKey);
|
|
293
321
|
if(0 === Object.keys(tablesToGenerate).length && !this.isOverride){
|
|
294
322
|
return true;
|
|
@@ -340,7 +368,7 @@ class EntitiesGenerator
|
|
|
340
368
|
if(this.server){
|
|
341
369
|
return this.server;
|
|
342
370
|
}
|
|
343
|
-
let driverKey = sc.get(this.connectionData, 'driver', '
|
|
371
|
+
let driverKey = sc.get(this.connectionData, 'driver', 'knex');
|
|
344
372
|
let driverClassMapped = this.driverMap[driverKey];
|
|
345
373
|
if(!driverClassMapped){
|
|
346
374
|
Logger.critical('Unsupported driver: '+driverKey);
|
|
@@ -357,8 +385,9 @@ class EntitiesGenerator
|
|
|
357
385
|
},
|
|
358
386
|
projectRoot: this.projectPath
|
|
359
387
|
};
|
|
360
|
-
|
|
361
|
-
|
|
388
|
+
let modulesProp = sc.get(this.driverModulesProps, driverKey, false);
|
|
389
|
+
if(modulesProp && this[modulesProp]){
|
|
390
|
+
serverConfig[modulesProp] = this[modulesProp];
|
|
362
391
|
}
|
|
363
392
|
this.server = new driverClassMapped(serverConfig);
|
|
364
393
|
return this.server;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - {{modelClassName}}
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const DrizzleMysqlCore = require('drizzle-orm/mysql-core');
|
|
8
|
+
|
|
9
|
+
let table = DrizzleMysqlCore.mysqlTable('{{tableName}}', {
|
|
10
|
+
{{entityPropertiesDefinition}}
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
class {{modelClassName}}
|
|
14
|
+
{
|
|
15
|
+
|
|
16
|
+
static get tableName()
|
|
17
|
+
{
|
|
18
|
+
return '{{tableName}}';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static get table()
|
|
22
|
+
{
|
|
23
|
+
return table;
|
|
24
|
+
}
|
|
25
|
+
{{idColumn}}{{modelRelations}}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
module.exports.{{modelClassName}} = {{modelClassName}};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - {{modelClassName}}
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
class {{modelClassName}}
|
|
8
|
+
{
|
|
9
|
+
|
|
10
|
+
static get tableName()
|
|
11
|
+
{
|
|
12
|
+
return '{{tableName}}';
|
|
13
|
+
}
|
|
14
|
+
{{idColumn}}{{modelRelations}}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports.{{modelClassName}} = {{modelClassName}};
|
|
@@ -25,6 +25,19 @@ class BaseGenerator
|
|
|
25
25
|
props.push('onDelete: \''+deleteRule+'\'');
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
parseEnumValues(columnType)
|
|
29
|
+
{
|
|
30
|
+
if(!columnType){
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
let match = columnType.match(/^enum\('(.+)'\)$/i);
|
|
34
|
+
if(!match){
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
let valuesString = match[1];
|
|
38
|
+
return valuesString.split('\',\'');
|
|
39
|
+
}
|
|
40
|
+
|
|
28
41
|
mapDeleteRule(deleteRule)
|
|
29
42
|
{
|
|
30
43
|
if(!deleteRule){
|
|
@@ -277,19 +277,6 @@ class EntitiesGeneration extends BaseGenerator
|
|
|
277
277
|
);
|
|
278
278
|
}
|
|
279
279
|
|
|
280
|
-
parseEnumValues(columnType)
|
|
281
|
-
{
|
|
282
|
-
if(!columnType){
|
|
283
|
-
return [];
|
|
284
|
-
}
|
|
285
|
-
let match = columnType.match(/^enum\('(.+)'\)$/i);
|
|
286
|
-
if(!match){
|
|
287
|
-
return [];
|
|
288
|
-
}
|
|
289
|
-
let valuesString = match[1];
|
|
290
|
-
return valuesString.split('\',\'');
|
|
291
|
-
}
|
|
292
|
-
|
|
293
280
|
addRequiredAttribute(props, column)
|
|
294
281
|
{
|
|
295
282
|
if(!column.nullable && !column.default){
|