@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 CHANGED
@@ -218,8 +218,9 @@ export {InverseRelationOpts};
218
218
  class Config implements IDbConfigHandler {
219
219
  private data: IDbConfigParams = {
220
220
  db_models: [],
221
- mongo_db: null,
222
- mongo_url: null
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.mongo_url = args[0];
246
- this.data.mongo_db = args[1];
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[2];
250
- this.cliExecRoot = args[3];
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 function generateModelSections<T extends Model<T>>(model: OpModelType<T>): Promise<string> {
311
+ static async generateModelSections(model: OpModelType<any>): Promise<string> {
310
312
  let section = '';
311
- const modelMetadatas: Record<string, {annotationType: string, metadata: any}> = await Model.getModelAnnotations(model);
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: IMetaOpts = modelMetadatas[key].metadata;
320
- const requiredString = modelMetadata.required ? '' : '?';
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 relatedModel = modelMetadata.relatedTo as OpModelType<T>;
329
- // Handle direct relation (many-to-one or one-to-one)
330
- section += `\t${key} ${relatedModel._collection}${requiredString} @relation("${modelName}_${relatedModel._collection}", fields: [${modelMetadata.relationField}], references: [${modelMetadata.relatedToField}], onDelete: Cascade)\n`;
331
- section += `\t${modelMetadata.relationField} String${requiredString} @db.ObjectId\n`;
332
- } else if (annotationType === 'InverseRelation'){
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} ${modelMetadata.inversionModel._collection}[] @relation("${modelMetadata.inversionModel._collection}_${modelName}")\n`;
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
- section += `\t${key} ${toConfigCase(modelMetadata)}${requiredString} ${tags.join(' ')}\n`;
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
- function toConfigCase(modelType: any): string {
374
+ static toConfigCase(modelType: IMetaOpts): string {
348
375
  const type = modelType.type;
349
- const input = type.name;
376
+ let input = type.name;
377
+
350
378
 
351
379
  if(input == 'Number'){
352
- return 'Int';
380
+ input = 'Int';
353
381
  }
354
382
 
355
383
  if(input == 'Object'){
356
- return 'Json';
384
+ input = 'Json';
357
385
  }
358
386
 
359
387
  if(input == 'Date'){
360
- return 'DateTime';
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
- return firstChar + restOfString;
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 generateModelSections(model: OpModelType<any>): Promise<string>;
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
  }
@@ -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('mongo_url');
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("DATABASE_URL")\n
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.DB_URL = dbUrl;
52
- const endPrisma = 'npx prisma';
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 async generateModelSections(model) {
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 += '\tid String @map("_id") @id @default(auto()) @db.ObjectId\n';
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: any);
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", String)
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 'src/types/FindParams';
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('mongo_url'),
23
- dbName: this.configService.get('mongo_db'),
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('mongo_url');
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('mongo_db');
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('mongo_url');
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('mongo_db'));
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
- mongo_url?: string;
4
- mongo_db?: string;
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
  }
@@ -1,3 +1,3 @@
1
1
  export interface IRWSModel {
2
- id?: string;
2
+ id?: string | number;
3
3
  }
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.mongo_url = args[0];
38
- this.data.mongo_db = args[1];
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[2];
42
- this.cliExecRoot = args[3];
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rws-framework/db",
3
3
  "private": false,
4
- "version": "2.3.1",
4
+ "version": "2.3.4",
5
5
  "description": "",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -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('mongo_url');
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("DATABASE_URL")\n
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.DB_URL = dbUrl;
69
- const endPrisma = 'npx prisma';
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 async generateModelSections(model: OpModelType<any>): Promise<string> {
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 += '\tid String @map("_id") @id @default(auto()) @db.ObjectId\n';
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
 
@@ -3,7 +3,7 @@ import { DBService } from '../../services/DBService';
3
3
 
4
4
  export interface IModel {
5
5
  [key: string]: any;
6
- id: string | null;
6
+ id: string |number | null;
7
7
  save: () => void;
8
8
  getDb: () => DBService;
9
9
  getCollection: () => string | null;
@@ -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 'src/types/FindParams';
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('mongo_url'),
27
- dbName: this.configService.get('mongo_db'),
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('mongo_url');
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('mongo_db');
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('mongo_url');
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('mongo_db'));
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
- mongo_url?: string;
5
- mongo_db?: string;
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
  }
@@ -1,3 +1,3 @@
1
1
  export interface IRWSModel {
2
- id?: string
2
+ id?: string | number
3
3
  }