@rws-framework/db 2.3.1 → 2.3.4
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/README.md +67 -30
- package/dist/helper/DbHelper.d.ts +6 -2
- package/dist/helper/DbHelper.js +38 -11
- package/dist/index.d.ts +2 -2
- package/dist/models/core/RWSModel.d.ts +3 -3
- package/dist/models/core/RWSModel.js +2 -2
- package/dist/models/interfaces/IModel.d.ts +1 -1
- package/dist/models/utils/RelationUtils.d.ts +1 -1
- package/dist/services/DBService.d.ts +1 -1
- package/dist/services/DBService.js +6 -6
- package/dist/types/DbConfigHandler.d.ts +7 -2
- package/dist/types/IRWSModel.d.ts +1 -1
- package/exec/src/cli.ts +6 -4
- package/package.json +1 -1
- package/src/helper/DbHelper.ts +59 -14
- package/src/index.ts +2 -1
- package/src/models/core/RWSModel.ts +3 -3
- package/src/models/interfaces/IModel.ts +1 -1
- package/src/models/utils/RelationUtils.ts +1 -1
- package/src/services/DBService.ts +7 -7
- package/src/types/DbConfigHandler.ts +8 -2
- package/src/types/IRWSModel.ts +1 -1
package/README.md
CHANGED
|
@@ -218,8 +218,9 @@ export {InverseRelationOpts};
|
|
|
218
218
|
class Config implements IDbConfigHandler {
|
|
219
219
|
private data: IDbConfigParams = {
|
|
220
220
|
db_models: [],
|
|
221
|
-
|
|
222
|
-
|
|
221
|
+
db_name: null,
|
|
222
|
+
db_url: null,
|
|
223
|
+
db_type: null
|
|
223
224
|
};
|
|
224
225
|
|
|
225
226
|
private modelsDir: string;
|
|
@@ -242,14 +243,13 @@ class Config implements IDbConfigHandler {
|
|
|
242
243
|
|
|
243
244
|
async fill(): Promise<void>
|
|
244
245
|
{
|
|
245
|
-
this.data.
|
|
246
|
-
this.data.
|
|
246
|
+
this.data.db_url = args[0];
|
|
247
|
+
this.data.db_name = args[1];
|
|
248
|
+
this.data.db_type = args[2];
|
|
247
249
|
|
|
248
250
|
|
|
249
|
-
this.modelsDir = args[
|
|
250
|
-
this.cliExecRoot = args[
|
|
251
|
-
|
|
252
|
-
this.data.db_models = (await import('@V/index')).default;
|
|
251
|
+
this.modelsDir = args[3];
|
|
252
|
+
this.cliExecRoot = args[4];
|
|
253
253
|
}
|
|
254
254
|
|
|
255
255
|
getModelsDir(): string
|
|
@@ -285,58 +285,85 @@ The exec file.
|
|
|
285
285
|
/exec/src/console.js
|
|
286
286
|
```
|
|
287
287
|
|
|
288
|
+
dbType can be any prisma db driver - mongodb by default
|
|
289
|
+
|
|
288
290
|
```bash
|
|
289
291
|
#npm
|
|
290
292
|
|
|
291
|
-
npx rws-db "mongodb://user:pass@localhost:27017/databaseName?authSource=admin&replicaSet=rs0" databaseName src/models
|
|
293
|
+
npx rws-db "mongodb://user:pass@localhost:27017/databaseName?authSource=admin&replicaSet=rs0" databaseName dbType src/models
|
|
292
294
|
```
|
|
293
295
|
|
|
294
296
|
```bash
|
|
295
297
|
#yarn
|
|
296
298
|
|
|
297
|
-
yarn rws-db "mongodb://user:pass@localhost:27017/databaseName?authSource=admin&replicaSet=rs0" databaseName src/models
|
|
299
|
+
yarn rws-db "mongodb://user:pass@localhost:27017/databaseName?authSource=admin&replicaSet=rs0" databaseName dbType src/models
|
|
298
300
|
```
|
|
299
301
|
|
|
300
302
|
```bash
|
|
301
303
|
#bun
|
|
302
304
|
|
|
303
|
-
bunx rws-db "mongodb://user:pass@localhost:27017/databaseName?authSource=admin&replicaSet=rs0" databaseName src/models
|
|
305
|
+
bunx rws-db "mongodb://user:pass@localhost:27017/databaseName?authSource=admin&replicaSet=rs0" databaseName dbType src/models
|
|
304
306
|
```
|
|
305
307
|
|
|
306
308
|
Code for RWS to prisma conversion from "@rws-framework/server" package:
|
|
307
309
|
|
|
308
310
|
```typescript
|
|
309
|
-
async
|
|
311
|
+
static async generateModelSections(model: OpModelType<any>): Promise<string> {
|
|
310
312
|
let section = '';
|
|
311
|
-
const modelMetadatas: Record<string, {annotationType: string, metadata: any}> = await
|
|
313
|
+
const modelMetadatas: Record<string, {annotationType: string, metadata: any}> = await RWSModel.getModelAnnotations(model);
|
|
312
314
|
|
|
313
315
|
const modelName: string = (model as any)._collection;
|
|
314
316
|
|
|
315
317
|
section += `model ${modelName} {\n`;
|
|
316
318
|
section += '\tid String @map("_id") @id @default(auto()) @db.ObjectId\n';
|
|
317
|
-
|
|
319
|
+
|
|
318
320
|
for (const key in modelMetadatas) {
|
|
319
|
-
const modelMetadata
|
|
320
|
-
|
|
321
|
+
const modelMetadata = modelMetadatas[key].metadata;
|
|
322
|
+
let requiredString = modelMetadata.required ? '' : '?';
|
|
321
323
|
const annotationType: string = modelMetadatas[key].annotationType;
|
|
322
324
|
|
|
323
325
|
if(key === 'id'){
|
|
324
326
|
continue;
|
|
325
327
|
}
|
|
328
|
+
|
|
326
329
|
|
|
327
330
|
if(annotationType === 'Relation'){
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
331
|
+
const relationMeta = modelMetadata as IRelationOpts
|
|
332
|
+
|
|
333
|
+
const relatedModel = relationMeta.relatedTo as OpModelType<any>;
|
|
334
|
+
const isMany = relationMeta.many;
|
|
335
|
+
const cascadeOpts = [];
|
|
336
|
+
|
|
337
|
+
if (relationMeta.cascade?.onDelete) {
|
|
338
|
+
cascadeOpts.push(`onDelete: ${relationMeta.cascade.onDelete}`);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (relationMeta.cascade?.onUpdate) {
|
|
342
|
+
cascadeOpts.push(`onUpdate: ${relationMeta.cascade.onUpdate}`);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (isMany) {
|
|
346
|
+
// Handle many-to-many or one-to-many relation
|
|
347
|
+
section += `\t${key} ${relatedModel._collection}[] @relation("${modelName}_${relatedModel._collection}")\n`;
|
|
348
|
+
} else {
|
|
349
|
+
// Handle one-to-one or many-to-one relation
|
|
350
|
+
section += `\t${key} ${relatedModel._collection}${requiredString} @relation("${modelName}_${relatedModel._collection}", fields: [${modelMetadata.relationField}], references: [${modelMetadata.relatedToField || 'id'}], ${cascadeOpts.join(', ')})\n`;
|
|
351
|
+
section += `\t${modelMetadata.relationField} String${requiredString} @db.ObjectId\n`;
|
|
352
|
+
}
|
|
353
|
+
} else if (annotationType === 'InverseRelation'){
|
|
354
|
+
const relationMeta = modelMetadata as InverseRelationOpts;
|
|
355
|
+
|
|
333
356
|
// Handle inverse relation (one-to-many or one-to-one)
|
|
334
|
-
section += `\t${key} ${
|
|
357
|
+
section += `\t${key} ${relationMeta.inversionModel._collection}[] @relation("${ relationMeta.relationName ? relationMeta.relationName : `${relationMeta.inversionModel._collection}_${modelName}`}")\n`;
|
|
335
358
|
} else if (annotationType === 'InverseTimeSeries'){
|
|
336
359
|
section += `\t${key} String[] @db.ObjectId\n`;
|
|
337
360
|
} else if (annotationType === 'TrackType'){
|
|
338
|
-
const tags: string[] = modelMetadata.tags.map((item: string) => '@' + item);
|
|
339
|
-
|
|
361
|
+
const tags: string[] = modelMetadata.tags.map((item: string) => '@' + item);
|
|
362
|
+
|
|
363
|
+
if(modelMetadata.isArray || modelMetadata.type.name === 'Array'){
|
|
364
|
+
requiredString = '';
|
|
365
|
+
}
|
|
366
|
+
section += `\t${key} ${DbHelper.toConfigCase(modelMetadata)}${requiredString} ${tags.join(' ')}\n`;
|
|
340
367
|
}
|
|
341
368
|
}
|
|
342
369
|
|
|
@@ -344,25 +371,35 @@ async function generateModelSections<T extends Model<T>>(model: OpModelType<T>):
|
|
|
344
371
|
return section;
|
|
345
372
|
}
|
|
346
373
|
|
|
347
|
-
|
|
374
|
+
static toConfigCase(modelType: IMetaOpts): string {
|
|
348
375
|
const type = modelType.type;
|
|
349
|
-
|
|
376
|
+
let input = type.name;
|
|
377
|
+
|
|
350
378
|
|
|
351
379
|
if(input == 'Number'){
|
|
352
|
-
|
|
380
|
+
input = 'Int';
|
|
353
381
|
}
|
|
354
382
|
|
|
355
383
|
if(input == 'Object'){
|
|
356
|
-
|
|
384
|
+
input = 'Json';
|
|
357
385
|
}
|
|
358
386
|
|
|
359
387
|
if(input == 'Date'){
|
|
360
|
-
|
|
388
|
+
input = 'DateTime';
|
|
361
389
|
}
|
|
362
390
|
|
|
391
|
+
if(input == 'Array'){
|
|
392
|
+
input = 'Json[]';
|
|
393
|
+
}
|
|
363
394
|
|
|
364
395
|
const firstChar = input.charAt(0).toUpperCase();
|
|
365
396
|
const restOfString = input.slice(1);
|
|
366
|
-
|
|
397
|
+
let resultField = firstChar + restOfString;
|
|
398
|
+
|
|
399
|
+
if(modelType.isArray){
|
|
400
|
+
resultField += '[]';
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
return resultField;
|
|
367
404
|
}
|
|
368
405
|
```
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import { IDbConfigHandler } from '../types/DbConfigHandler';
|
|
1
|
+
import { IDbConfigHandler, IDbConfigParams, IdGeneratorOptions } from '../types/DbConfigHandler';
|
|
2
2
|
import { IMetaOpts, OpModelType } from '../models/_model';
|
|
3
3
|
import { DBService } from '../services/DBService';
|
|
4
4
|
export declare class DbHelper {
|
|
5
|
+
static dbUrlVarName: string;
|
|
5
6
|
static installPrisma(configService: IDbConfigHandler, dbService: DBService, leaveFile?: boolean): Promise<void>;
|
|
6
|
-
static
|
|
7
|
+
static generateId(dbType: IDbConfigParams['db_type'], options?: IdGeneratorOptions): string;
|
|
8
|
+
static detectInstaller(): string;
|
|
9
|
+
static pushDBModels(configService: IDbConfigHandler, dbService: DBService, leaveFile?: boolean): Promise<void>;
|
|
10
|
+
static generateModelSections(model: OpModelType<any>, configService: IDbConfigHandler): Promise<string>;
|
|
7
11
|
static toConfigCase(modelType: IMetaOpts): string;
|
|
8
12
|
}
|
package/dist/helper/DbHelper.js
CHANGED
|
@@ -14,19 +14,19 @@ const workspaceRoot = console_1.rwsPath.findRootWorkspacePath();
|
|
|
14
14
|
const moduleDir = path_1.default.resolve(workspaceRoot, 'node_modules', '@rws-framework', 'db');
|
|
15
15
|
class DbHelper {
|
|
16
16
|
static async installPrisma(configService, dbService, leaveFile = false) {
|
|
17
|
-
const dbUrl = configService.get('
|
|
18
|
-
const dbType = 'mongodb';
|
|
17
|
+
const dbUrl = configService.get('db_url');
|
|
18
|
+
const dbType = configService.get('db_type') || 'mongodb';
|
|
19
19
|
let template = `generator client {\n
|
|
20
20
|
provider = "prisma-client-js"\n
|
|
21
21
|
}\n\n`;
|
|
22
22
|
template += `\ndatasource db {\n
|
|
23
23
|
provider = "${dbType}"\n
|
|
24
|
-
url = env("
|
|
24
|
+
url = env("${this.dbUrlVarName}")\n
|
|
25
25
|
}\n\n`;
|
|
26
26
|
const dbModels = configService.get('db_models');
|
|
27
27
|
if (dbModels) {
|
|
28
28
|
for (const model of dbModels) {
|
|
29
|
-
const modelSection = await DbHelper.generateModelSections(model);
|
|
29
|
+
const modelSection = await DbHelper.generateModelSections(model, configService);
|
|
30
30
|
template += '\n\n' + modelSection;
|
|
31
31
|
log(chalk_1.default.green('[RWS]'), chalk_1.default.blue('Building DB Model'), model.name);
|
|
32
32
|
// if(RWSModel.isSubclass(model as any, TimeSeriesModel)){
|
|
@@ -48,11 +48,8 @@ class DbHelper {
|
|
|
48
48
|
fs_1.default.unlinkSync(schemaPath);
|
|
49
49
|
}
|
|
50
50
|
fs_1.default.writeFileSync(schemaPath, template);
|
|
51
|
-
process.env
|
|
52
|
-
|
|
53
|
-
// console.log({cwd: process.cwd()})
|
|
54
|
-
// const clientPath = path.join(rwsPath.findRootWorkspacePath(), 'node_modules', '.prisma', 'client');
|
|
55
|
-
await console_1.rwsShell.runCommand(`${endPrisma} generate --schema=${schemaPath}`, process.cwd());
|
|
51
|
+
process.env = { ...process.env, [this.dbUrlVarName]: dbUrl };
|
|
52
|
+
await console_1.rwsShell.runCommand(`${this.detectInstaller()} prisma generate --schema="${schemaPath}"`, process.cwd());
|
|
56
53
|
leaveFile = false;
|
|
57
54
|
log(chalk_1.default.green('[RWS Init]') + ' prisma schema generated from ', schemaPath);
|
|
58
55
|
if (!leaveFile) {
|
|
@@ -60,13 +57,42 @@ class DbHelper {
|
|
|
60
57
|
}
|
|
61
58
|
}
|
|
62
59
|
}
|
|
63
|
-
static
|
|
60
|
+
static generateId(dbType, options = {}) {
|
|
61
|
+
const { useUuid = false, customType } = options;
|
|
62
|
+
if (customType) {
|
|
63
|
+
return `id ${customType} @id`;
|
|
64
|
+
}
|
|
65
|
+
switch (dbType) {
|
|
66
|
+
case 'mongodb':
|
|
67
|
+
return 'id String @id @default(auto()) @map("_id") @db.ObjectId';
|
|
68
|
+
case 'mysql':
|
|
69
|
+
return useUuid
|
|
70
|
+
? 'id String @id @default(uuid())'
|
|
71
|
+
: 'id Int @id @default(autoincrement())';
|
|
72
|
+
case 'sqlite':
|
|
73
|
+
return 'id Int @id @default(autoincrement())';
|
|
74
|
+
default:
|
|
75
|
+
throw new Error('Kurwa, nieobsługiwany typ bazy danych!');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
static detectInstaller() {
|
|
79
|
+
if (fs_1.default.existsSync(path_1.default.join(workspaceRoot, 'yarn.lock'))) {
|
|
80
|
+
return 'yarn';
|
|
81
|
+
}
|
|
82
|
+
return 'npx';
|
|
83
|
+
}
|
|
84
|
+
static async pushDBModels(configService, dbService, leaveFile = false) {
|
|
85
|
+
process.env = { ...process.env, [this.dbUrlVarName]: configService.get('db_url') };
|
|
86
|
+
const schemaPath = path_1.default.join(workspaceRoot, 'node_modules', '.prisma', 'client', 'schema.prisma');
|
|
87
|
+
await console_1.rwsShell.runCommand(`${this.detectInstaller()} prisma db push --schema="${schemaPath}"`, process.cwd());
|
|
88
|
+
}
|
|
89
|
+
static async generateModelSections(model, configService) {
|
|
64
90
|
var _a, _b;
|
|
65
91
|
let section = '';
|
|
66
92
|
const modelMetadatas = await _model_1.RWSModel.getModelAnnotations(model);
|
|
67
93
|
const modelName = model._collection;
|
|
68
94
|
section += `model ${modelName} {\n`;
|
|
69
|
-
section +=
|
|
95
|
+
section += `\t${this.generateId(configService.get('db_type'))}\n`;
|
|
70
96
|
for (const key in modelMetadatas) {
|
|
71
97
|
const modelMetadata = modelMetadatas[key].metadata;
|
|
72
98
|
let requiredString = modelMetadata.required ? '' : '?';
|
|
@@ -139,3 +165,4 @@ class DbHelper {
|
|
|
139
165
|
}
|
|
140
166
|
}
|
|
141
167
|
exports.DbHelper = DbHelper;
|
|
168
|
+
DbHelper.dbUrlVarName = 'PRISMA_DB_URL';
|
package/dist/index.d.ts
CHANGED
|
@@ -5,8 +5,8 @@ import { DbHelper } from './helper/DbHelper';
|
|
|
5
5
|
import { FieldsHelper } from './helper/FieldsHelper';
|
|
6
6
|
import type { FindByType } from './types/FindParams';
|
|
7
7
|
import type { ITimeSeries } from './types/ITimeSeries';
|
|
8
|
-
import type { IDbConfigHandler } from './types/DbConfigHandler';
|
|
8
|
+
import type { IDbConfigHandler, IDbConfigParams } from './types/DbConfigHandler';
|
|
9
9
|
import type { IRWSModel } from './types/IRWSModel';
|
|
10
10
|
import { RWSCollection, IRWSCollectionMeta, IRWSCollectionOpts } from "./decorators/RWSCollection";
|
|
11
|
-
export type { IRWSCollectionMeta, IRWSCollectionOpts, IRWSModel, IMetaOpts, OpModelType, IDbConfigHandler, ITimeSeries, };
|
|
11
|
+
export type { IRWSCollectionMeta, IRWSCollectionOpts, IRWSModel, IMetaOpts, OpModelType, IDbConfigHandler, IDbConfigParams, ITimeSeries, };
|
|
12
12
|
export { RWSModel, RWSCollection, DBService, FindByType, InverseRelation, Relation, TrackType, InverseTimeSeries, DbHelper, FieldsHelper };
|
|
@@ -6,13 +6,13 @@ import { DBService } from '../../services/DBService';
|
|
|
6
6
|
declare class RWSModel<T> implements IModel {
|
|
7
7
|
static services: IRWSModelServices;
|
|
8
8
|
[key: string]: any;
|
|
9
|
-
id: string;
|
|
9
|
+
id: string | number;
|
|
10
10
|
static _collection: string;
|
|
11
11
|
static _RELATIONS: {};
|
|
12
12
|
static _BANNED_KEYS: string[];
|
|
13
13
|
static allModels: OpModelType<any>[];
|
|
14
14
|
static _CUT_KEYS: string[];
|
|
15
|
-
constructor(data
|
|
15
|
+
constructor(data?: any);
|
|
16
16
|
checkForInclusionWithThrow(): void;
|
|
17
17
|
static checkForInclusionWithThrow(this: OpModelType<any>, checkModelType: string): void;
|
|
18
18
|
checkForInclusion(): boolean;
|
|
@@ -21,7 +21,7 @@ declare class RWSModel<T> implements IModel {
|
|
|
21
21
|
protected hasRelation(key: string): boolean;
|
|
22
22
|
protected bindRelation(key: string, relatedModel: RWSModel<any>): {
|
|
23
23
|
connect: {
|
|
24
|
-
id: string;
|
|
24
|
+
id: string | number;
|
|
25
25
|
};
|
|
26
26
|
};
|
|
27
27
|
_asyncFill(data: any, fullDataMode?: boolean, allowRelations?: boolean): Promise<T>;
|
|
@@ -16,7 +16,7 @@ const RelationUtils_1 = require("../utils/RelationUtils");
|
|
|
16
16
|
const TimeSeriesUtils_1 = require("../utils/TimeSeriesUtils");
|
|
17
17
|
const ModelUtils_1 = require("../utils/ModelUtils");
|
|
18
18
|
class RWSModel {
|
|
19
|
-
constructor(data) {
|
|
19
|
+
constructor(data = null) {
|
|
20
20
|
if (!this.getCollection()) {
|
|
21
21
|
throw new Error('Model must have a collection defined');
|
|
22
22
|
}
|
|
@@ -396,5 +396,5 @@ RWSModel.allModels = [];
|
|
|
396
396
|
RWSModel._CUT_KEYS = [];
|
|
397
397
|
__decorate([
|
|
398
398
|
(0, decorators_1.TrackType)(String),
|
|
399
|
-
__metadata("design:type",
|
|
399
|
+
__metadata("design:type", Object)
|
|
400
400
|
], RWSModel.prototype, "id", void 0);
|
|
@@ -2,7 +2,7 @@ import { IDbConfigHandler } from '../../types/DbConfigHandler';
|
|
|
2
2
|
import { DBService } from '../../services/DBService';
|
|
3
3
|
export interface IModel {
|
|
4
4
|
[key: string]: any;
|
|
5
|
-
id: string | null;
|
|
5
|
+
id: string | number | null;
|
|
6
6
|
save: () => void;
|
|
7
7
|
getDb: () => DBService;
|
|
8
8
|
getCollection: () => string | null;
|
|
@@ -6,7 +6,7 @@ export declare class RelationUtils {
|
|
|
6
6
|
static getRelationManyMeta(model: RWSModel<any>, classFields: string[]): Promise<RelManyMetaType<IRWSModel>>;
|
|
7
7
|
static bindRelation(relatedModel: RWSModel<any>): {
|
|
8
8
|
connect: {
|
|
9
|
-
id: string;
|
|
9
|
+
id: string | number;
|
|
10
10
|
};
|
|
11
11
|
};
|
|
12
12
|
static hasRelation(model: RWSModel<any>, key: string): boolean;
|
|
@@ -2,7 +2,7 @@ import { Collection, Db, MongoClient } from 'mongodb';
|
|
|
2
2
|
import { ITimeSeries } from '../types/ITimeSeries';
|
|
3
3
|
import { IModel } from '../models/interfaces/IModel';
|
|
4
4
|
import { IDbConfigHandler } from '../types/DbConfigHandler';
|
|
5
|
-
import { IPaginationParams } from '
|
|
5
|
+
import { IPaginationParams } from '../types/FindParams';
|
|
6
6
|
interface IDBClientCreate {
|
|
7
7
|
dbUrl?: string;
|
|
8
8
|
dbName?: string;
|
|
@@ -19,8 +19,8 @@ class DBService {
|
|
|
19
19
|
}
|
|
20
20
|
else {
|
|
21
21
|
this.opts = {
|
|
22
|
-
dbUrl: this.configService.get('
|
|
23
|
-
dbName: this.configService.get('
|
|
22
|
+
dbUrl: this.configService.get('db_url'),
|
|
23
|
+
dbName: this.configService.get('db_name'),
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
if (!this.opts.dbUrl) {
|
|
@@ -51,14 +51,14 @@ class DBService {
|
|
|
51
51
|
}
|
|
52
52
|
async createBaseMongoClient() {
|
|
53
53
|
var _a;
|
|
54
|
-
const dbUrl = ((_a = this.opts) === null || _a === void 0 ? void 0 : _a.dbUrl) || this.configService.get('
|
|
54
|
+
const dbUrl = ((_a = this.opts) === null || _a === void 0 ? void 0 : _a.dbUrl) || this.configService.get('db_url');
|
|
55
55
|
const client = DBService.baseClientConstruct(dbUrl);
|
|
56
56
|
await client.connect();
|
|
57
57
|
return client;
|
|
58
58
|
}
|
|
59
59
|
async createBaseMongoClientDB() {
|
|
60
60
|
var _a;
|
|
61
|
-
const dbName = ((_a = this.opts) === null || _a === void 0 ? void 0 : _a.dbName) || this.configService.get('
|
|
61
|
+
const dbName = ((_a = this.opts) === null || _a === void 0 ? void 0 : _a.dbName) || this.configService.get('db_name');
|
|
62
62
|
const client = await this.createBaseMongoClient();
|
|
63
63
|
return [client, client.db(dbName)];
|
|
64
64
|
}
|
|
@@ -152,11 +152,11 @@ class DBService {
|
|
|
152
152
|
}
|
|
153
153
|
async collectionExists(collection_name) {
|
|
154
154
|
var _a;
|
|
155
|
-
const dbUrl = ((_a = this.opts) === null || _a === void 0 ? void 0 : _a.dbUrl) || this.configService.get('
|
|
155
|
+
const dbUrl = ((_a = this.opts) === null || _a === void 0 ? void 0 : _a.dbUrl) || this.configService.get('db_url');
|
|
156
156
|
const client = new mongodb_1.MongoClient(dbUrl);
|
|
157
157
|
try {
|
|
158
158
|
await client.connect();
|
|
159
|
-
const db = client.db(this.configService.get('
|
|
159
|
+
const db = client.db(this.configService.get('db_name'));
|
|
160
160
|
const collections = await db.listCollections().toArray();
|
|
161
161
|
const existingCollectionNames = collections.map((collection) => collection.name);
|
|
162
162
|
return existingCollectionNames.includes(collection_name);
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { OpModelType } from "../models/interfaces/OpModelType";
|
|
2
2
|
export interface IDbConfigParams {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
db_url?: string;
|
|
4
|
+
db_name?: string;
|
|
5
|
+
db_type?: 'mongodb' | 'mysql' | 'sqlite';
|
|
5
6
|
db_models?: OpModelType<any>[];
|
|
6
7
|
}
|
|
8
|
+
export interface IdGeneratorOptions {
|
|
9
|
+
useUuid?: boolean;
|
|
10
|
+
customType?: string;
|
|
11
|
+
}
|
|
7
12
|
export interface IDbConfigHandler {
|
|
8
13
|
get<K extends keyof IDbConfigParams>(key: K): IDbConfigParams[K];
|
|
9
14
|
}
|
package/exec/src/cli.ts
CHANGED
|
@@ -34,12 +34,13 @@ class Config implements IDbConfigHandler {
|
|
|
34
34
|
|
|
35
35
|
async fill(): Promise<void>
|
|
36
36
|
{
|
|
37
|
-
this.data.
|
|
38
|
-
this.data.
|
|
37
|
+
this.data.db_url = args[0];
|
|
38
|
+
this.data.db_name = args[1];
|
|
39
|
+
this.data.db_type = args[2];
|
|
39
40
|
|
|
40
41
|
|
|
41
|
-
this.modelsDir = args[
|
|
42
|
-
this.cliExecRoot = args[
|
|
42
|
+
this.modelsDir = args[3];
|
|
43
|
+
this.cliExecRoot = args[4];
|
|
43
44
|
|
|
44
45
|
console.log({args})
|
|
45
46
|
|
|
@@ -65,6 +66,7 @@ async function main(): Promise<void>
|
|
|
65
66
|
{
|
|
66
67
|
console.log('INSTALL PRISMA');
|
|
67
68
|
const cfg = await Config.getInstance();
|
|
69
|
+
process.env.PRISMA_DB_URL = cfg.get('db_url');
|
|
68
70
|
DbHelper.installPrisma(cfg, new DBService(cfg), false);
|
|
69
71
|
}
|
|
70
72
|
|
package/package.json
CHANGED
package/src/helper/DbHelper.ts
CHANGED
|
@@ -3,7 +3,7 @@ import chalk from 'chalk';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import fs from 'fs';
|
|
5
5
|
|
|
6
|
-
import { IDbConfigHandler } from '../types/DbConfigHandler';
|
|
6
|
+
import { IDbConfigHandler, IDbConfigParams, IdGeneratorOptions } from '../types/DbConfigHandler';
|
|
7
7
|
import { IMetaOpts, OpModelType, RWSModel } from '../models/_model';
|
|
8
8
|
// import TimeSeriesModel from '../models/core/TimeSeriesModel';
|
|
9
9
|
import { DBService } from '../services/DBService';
|
|
@@ -15,10 +15,12 @@ const workspaceRoot = rwsPath.findRootWorkspacePath();
|
|
|
15
15
|
const moduleDir = path.resolve(workspaceRoot, 'node_modules', '@rws-framework', 'db');
|
|
16
16
|
|
|
17
17
|
export class DbHelper {
|
|
18
|
+
static dbUrlVarName: string = 'PRISMA_DB_URL';
|
|
19
|
+
|
|
18
20
|
static async installPrisma(configService: IDbConfigHandler, dbService: DBService, leaveFile = false): Promise<void>
|
|
19
21
|
{
|
|
20
|
-
const dbUrl = configService.get('
|
|
21
|
-
const dbType = 'mongodb';
|
|
22
|
+
const dbUrl = configService.get('db_url');
|
|
23
|
+
const dbType = configService.get('db_type') || 'mongodb';
|
|
22
24
|
|
|
23
25
|
let template: string = `generator client {\n
|
|
24
26
|
provider = "prisma-client-js"\n
|
|
@@ -26,7 +28,7 @@ export class DbHelper {
|
|
|
26
28
|
|
|
27
29
|
template += `\ndatasource db {\n
|
|
28
30
|
provider = "${dbType}"\n
|
|
29
|
-
url = env("
|
|
31
|
+
url = env("${this.dbUrlVarName}")\n
|
|
30
32
|
}\n\n`;
|
|
31
33
|
|
|
32
34
|
const dbModels: OpModelType<unknown>[] | null = configService.get('db_models');
|
|
@@ -34,7 +36,7 @@ export class DbHelper {
|
|
|
34
36
|
if(dbModels){
|
|
35
37
|
|
|
36
38
|
for (const model of dbModels){
|
|
37
|
-
const modelSection = await DbHelper.generateModelSections(model);
|
|
39
|
+
const modelSection = await DbHelper.generateModelSections(model, configService);
|
|
38
40
|
|
|
39
41
|
template += '\n\n' + modelSection;
|
|
40
42
|
|
|
@@ -65,12 +67,9 @@ export class DbHelper {
|
|
|
65
67
|
}
|
|
66
68
|
|
|
67
69
|
fs.writeFileSync(schemaPath, template);
|
|
68
|
-
process.env
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
// console.log({cwd: process.cwd()})
|
|
72
|
-
// const clientPath = path.join(rwsPath.findRootWorkspacePath(), 'node_modules', '.prisma', 'client');
|
|
73
|
-
await rwsShell.runCommand(`${endPrisma} generate --schema=${schemaPath}`, process.cwd());
|
|
70
|
+
process.env = { ...process.env, [this.dbUrlVarName]: dbUrl }
|
|
71
|
+
|
|
72
|
+
await rwsShell.runCommand(`${this.detectInstaller()} prisma generate --schema="${schemaPath}"`, process.cwd());
|
|
74
73
|
|
|
75
74
|
leaveFile = false;
|
|
76
75
|
log(chalk.green('[RWS Init]') + ' prisma schema generated from ', schemaPath);
|
|
@@ -81,14 +80,60 @@ export class DbHelper {
|
|
|
81
80
|
}
|
|
82
81
|
}
|
|
83
82
|
|
|
84
|
-
static
|
|
83
|
+
static generateId(
|
|
84
|
+
dbType: IDbConfigParams['db_type'],
|
|
85
|
+
options: IdGeneratorOptions = {}
|
|
86
|
+
): string {
|
|
87
|
+
const { useUuid = false, customType } = options;
|
|
88
|
+
|
|
89
|
+
if (customType) {
|
|
90
|
+
return `id ${customType} @id`;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
switch(dbType) {
|
|
94
|
+
case 'mongodb':
|
|
95
|
+
return 'id String @id @default(auto()) @map("_id") @db.ObjectId';
|
|
96
|
+
|
|
97
|
+
case 'mysql':
|
|
98
|
+
return useUuid
|
|
99
|
+
? 'id String @id @default(uuid())'
|
|
100
|
+
: 'id Int @id @default(autoincrement())';
|
|
101
|
+
|
|
102
|
+
case 'sqlite':
|
|
103
|
+
return 'id Int @id @default(autoincrement())';
|
|
104
|
+
|
|
105
|
+
default:
|
|
106
|
+
throw new Error('Kurwa, nieobsługiwany typ bazy danych!');
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
static detectInstaller(): string
|
|
111
|
+
{
|
|
112
|
+
|
|
113
|
+
if (fs.existsSync(path.join(workspaceRoot, 'yarn.lock'))){
|
|
114
|
+
return 'yarn';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return 'npx';
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
static async pushDBModels(configService: IDbConfigHandler, dbService: DBService, leaveFile = false){
|
|
121
|
+
process.env = { ...process.env, [this.dbUrlVarName]: configService.get('db_url') }
|
|
122
|
+
|
|
123
|
+
const schemaPath = path.join(workspaceRoot, 'node_modules', '.prisma', 'client','schema.prisma');
|
|
124
|
+
|
|
125
|
+
await rwsShell.runCommand(`${this.detectInstaller()} prisma db push --schema="${schemaPath}"`, process.cwd());
|
|
126
|
+
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
static async generateModelSections(model: OpModelType<any>, configService: IDbConfigHandler): Promise<string> {
|
|
85
130
|
let section = '';
|
|
86
131
|
const modelMetadatas: Record<string, {annotationType: string, metadata: any}> = await RWSModel.getModelAnnotations(model);
|
|
87
132
|
|
|
88
133
|
const modelName: string = (model as any)._collection;
|
|
89
134
|
|
|
90
135
|
section += `model ${modelName} {\n`;
|
|
91
|
-
section +=
|
|
136
|
+
section += `\t${this.generateId(configService.get('db_type'))}\n`;
|
|
92
137
|
|
|
93
138
|
for (const key in modelMetadatas) {
|
|
94
139
|
const modelMetadata = modelMetadatas[key].metadata;
|
|
@@ -175,4 +220,4 @@ export class DbHelper {
|
|
|
175
220
|
|
|
176
221
|
return resultField;
|
|
177
222
|
}
|
|
178
|
-
}
|
|
223
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { FieldsHelper } from './helper/FieldsHelper';
|
|
|
8
8
|
|
|
9
9
|
import type { FindByType } from './types/FindParams';
|
|
10
10
|
import type { ITimeSeries } from './types/ITimeSeries';
|
|
11
|
-
import type { IDbConfigHandler } from './types/DbConfigHandler';
|
|
11
|
+
import type { IDbConfigHandler, IDbConfigParams } from './types/DbConfigHandler';
|
|
12
12
|
import type { IRWSModel } from './types/IRWSModel';
|
|
13
13
|
import { RWSCollection, IRWSCollectionMeta, IRWSCollectionOpts } from "./decorators/RWSCollection";
|
|
14
14
|
|
|
@@ -18,6 +18,7 @@ export type {
|
|
|
18
18
|
IMetaOpts,
|
|
19
19
|
OpModelType,
|
|
20
20
|
IDbConfigHandler,
|
|
21
|
+
IDbConfigParams,
|
|
21
22
|
ITimeSeries,
|
|
22
23
|
}
|
|
23
24
|
|
|
@@ -16,14 +16,14 @@ class RWSModel<T> implements IModel {
|
|
|
16
16
|
|
|
17
17
|
[key: string]: any;
|
|
18
18
|
@TrackType(String)
|
|
19
|
-
id: string;
|
|
19
|
+
id: string | number;
|
|
20
20
|
static _collection: string = null;
|
|
21
21
|
static _RELATIONS = {};
|
|
22
22
|
static _BANNED_KEYS = ['_collection'];
|
|
23
23
|
static allModels: OpModelType<any>[] = [];
|
|
24
24
|
static _CUT_KEYS: string[] = [];
|
|
25
25
|
|
|
26
|
-
constructor(data: any) {
|
|
26
|
+
constructor(data: any = null) {
|
|
27
27
|
if(!this.getCollection()){
|
|
28
28
|
throw new Error('Model must have a collection defined');
|
|
29
29
|
}
|
|
@@ -89,7 +89,7 @@ class RWSModel<T> implements IModel {
|
|
|
89
89
|
return RelationUtils.hasRelation(this, key);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
protected bindRelation(key: string, relatedModel: RWSModel<any>): { connect: { id: string } } {
|
|
92
|
+
protected bindRelation(key: string, relatedModel: RWSModel<any>): { connect: { id: string | number } } {
|
|
93
93
|
return RelationUtils.bindRelation(relatedModel);
|
|
94
94
|
}
|
|
95
95
|
|
|
@@ -56,7 +56,7 @@ export class RelationUtils {
|
|
|
56
56
|
return relIds;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
static bindRelation(relatedModel: RWSModel<any>): { connect: { id: string } } {
|
|
59
|
+
static bindRelation(relatedModel: RWSModel<any>): { connect: { id: string | number } } {
|
|
60
60
|
return {
|
|
61
61
|
connect: {
|
|
62
62
|
id: relatedModel.id
|
|
@@ -4,7 +4,7 @@ import {ITimeSeries} from '../types/ITimeSeries';
|
|
|
4
4
|
import { IModel } from '../models/interfaces/IModel';
|
|
5
5
|
import chalk from 'chalk';
|
|
6
6
|
import { IDbConfigHandler } from '../types/DbConfigHandler';
|
|
7
|
-
import { IPaginationParams } from '
|
|
7
|
+
import { IPaginationParams } from '../types/FindParams';
|
|
8
8
|
|
|
9
9
|
interface IDBClientCreate {
|
|
10
10
|
dbUrl?: string;
|
|
@@ -23,8 +23,8 @@ class DBService {
|
|
|
23
23
|
this.opts = opts;
|
|
24
24
|
}else{
|
|
25
25
|
this.opts = {
|
|
26
|
-
dbUrl: this.configService.get('
|
|
27
|
-
dbName: this.configService.get('
|
|
26
|
+
dbUrl: this.configService.get('db_url'),
|
|
27
|
+
dbName: this.configService.get('db_name'),
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -65,7 +65,7 @@ class DBService {
|
|
|
65
65
|
|
|
66
66
|
public async createBaseMongoClient(): Promise<MongoClient>
|
|
67
67
|
{
|
|
68
|
-
const dbUrl = this.opts?.dbUrl || this.configService.get('
|
|
68
|
+
const dbUrl = this.opts?.dbUrl || this.configService.get('db_url');
|
|
69
69
|
const client = DBService.baseClientConstruct(dbUrl);
|
|
70
70
|
|
|
71
71
|
await client.connect();
|
|
@@ -76,7 +76,7 @@ class DBService {
|
|
|
76
76
|
|
|
77
77
|
public async createBaseMongoClientDB(): Promise<[MongoClient, Db]>
|
|
78
78
|
{
|
|
79
|
-
const dbName = this.opts?.dbName || this.configService.get('
|
|
79
|
+
const dbName = this.opts?.dbName || this.configService.get('db_name');
|
|
80
80
|
const client = await this.createBaseMongoClient();
|
|
81
81
|
return [client, client.db(dbName)];
|
|
82
82
|
}
|
|
@@ -215,13 +215,13 @@ class DBService {
|
|
|
215
215
|
|
|
216
216
|
async collectionExists(collection_name: string): Promise<boolean>
|
|
217
217
|
{
|
|
218
|
-
const dbUrl = this.opts?.dbUrl || this.configService.get('
|
|
218
|
+
const dbUrl = this.opts?.dbUrl || this.configService.get('db_url');
|
|
219
219
|
const client = new MongoClient(dbUrl);
|
|
220
220
|
|
|
221
221
|
try {
|
|
222
222
|
await client.connect();
|
|
223
223
|
|
|
224
|
-
const db = client.db(this.configService.get('
|
|
224
|
+
const db = client.db(this.configService.get('db_name'));
|
|
225
225
|
|
|
226
226
|
const collections = await db.listCollections().toArray();
|
|
227
227
|
const existingCollectionNames = collections.map((collection) => collection.name);
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { OpModelType } from "../models/interfaces/OpModelType";
|
|
2
2
|
|
|
3
3
|
export interface IDbConfigParams {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
db_url?: string;
|
|
5
|
+
db_name?: string;
|
|
6
|
+
db_type?: 'mongodb' | 'mysql' | 'sqlite';
|
|
6
7
|
db_models?: OpModelType<any>[]
|
|
7
8
|
}
|
|
8
9
|
|
|
10
|
+
export interface IdGeneratorOptions {
|
|
11
|
+
useUuid?: boolean; // dla MySQL
|
|
12
|
+
customType?: string; // dla custom typów
|
|
13
|
+
}
|
|
14
|
+
|
|
9
15
|
export interface IDbConfigHandler {
|
|
10
16
|
get<K extends keyof IDbConfigParams>(key: K): IDbConfigParams[K];
|
|
11
17
|
}
|
package/src/types/IRWSModel.ts
CHANGED