@rws-framework/db 2.0.2 → 2.0.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.
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DBService = void 0;
7
+ const client_1 = require("@prisma/client");
8
+ const mongodb_1 = require("mongodb");
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ class DBService {
11
+ constructor(configService) {
12
+ this.configService = configService;
13
+ this.opts = null;
14
+ this.connected = false;
15
+ }
16
+ connectToDB(opts = null) {
17
+ if (opts) {
18
+ this.opts = opts;
19
+ }
20
+ else {
21
+ this.opts = {
22
+ dbUrl: this.configService.get('mongo_url'),
23
+ dbName: this.configService.get('mongo_db'),
24
+ };
25
+ }
26
+ if (!this.opts.dbUrl) {
27
+ console.log(chalk_1.default.red('No database config set in @rws-framework/db'));
28
+ return;
29
+ }
30
+ try {
31
+ this.client = new client_1.PrismaClient({
32
+ datasources: {
33
+ db: {
34
+ url: this.opts.dbUrl
35
+ },
36
+ },
37
+ });
38
+ this.connected = true;
39
+ }
40
+ catch (e) {
41
+ console.error(e);
42
+ throw new Error('PRISMA CONNECTION ERROR');
43
+ }
44
+ }
45
+ async createBaseMongoClient() {
46
+ var _a;
47
+ const dbUrl = ((_a = this.opts) === null || _a === void 0 ? void 0 : _a.dbUrl) || this.configService.get('mongo_url');
48
+ const client = new mongodb_1.MongoClient(dbUrl);
49
+ await client.connect();
50
+ return client;
51
+ }
52
+ async createBaseMongoClientDB() {
53
+ var _a;
54
+ const dbName = ((_a = this.opts) === null || _a === void 0 ? void 0 : _a.dbName) || this.configService.get('mongo_db');
55
+ const client = await this.createBaseMongoClient();
56
+ return client.db(dbName);
57
+ }
58
+ async cloneDatabase(source, target) {
59
+ const client = await this.createBaseMongoClient();
60
+ // Source and target DB
61
+ const sourceDb = client.db(source);
62
+ const targetDb = client.db(target);
63
+ // Get all collections from source DB
64
+ const collections = await sourceDb.listCollections().toArray();
65
+ // Loop over all collections and copy them to the target DB
66
+ for (const collection of collections) {
67
+ const docs = await sourceDb.collection(collection.name).find({}).toArray();
68
+ await targetDb.collection(collection.name).insertMany(docs);
69
+ }
70
+ await client.close();
71
+ }
72
+ async watchCollection(collectionName, preRun) {
73
+ const db = await this.createBaseMongoClientDB();
74
+ const collection = db.collection(collectionName);
75
+ const changeStream = collection.watch();
76
+ return new Promise((resolve) => {
77
+ changeStream.on('change', (change) => {
78
+ resolve(change);
79
+ });
80
+ preRun();
81
+ });
82
+ }
83
+ async insert(data, collection, isTimeSeries = false) {
84
+ let result = data;
85
+ // Insert time-series data outside of the transaction
86
+ if (isTimeSeries) {
87
+ const db = await this.createBaseMongoClientDB();
88
+ const collectionHandler = db.collection(collection);
89
+ const insert = await collectionHandler.insertOne(data);
90
+ result = await this.findOneBy(collection, { id: insert.insertedId.toString() });
91
+ return result;
92
+ }
93
+ const prismaCollection = this.getCollectionHandler(collection);
94
+ result = await prismaCollection.create({ data });
95
+ return await this.findOneBy(collection, { id: result.id });
96
+ }
97
+ async update(data, collection) {
98
+ const model_id = data.id;
99
+ delete data['id'];
100
+ const prismaCollection = this.getCollectionHandler(collection);
101
+ await prismaCollection.update({
102
+ where: {
103
+ id: model_id,
104
+ },
105
+ data: data,
106
+ });
107
+ return await this.findOneBy(collection, { id: model_id });
108
+ }
109
+ async findOneBy(collection, conditions, fields = null, ordering = null, allowRelations = true) {
110
+ const params = { where: conditions };
111
+ if (fields) {
112
+ params.select = {};
113
+ fields.forEach((fieldName) => {
114
+ params.select[fieldName] = true;
115
+ });
116
+ }
117
+ if (ordering) {
118
+ params.orderBy = ordering;
119
+ }
120
+ const retData = await this.getCollectionHandler(collection).findFirst(params);
121
+ return retData;
122
+ }
123
+ async delete(collection, conditions) {
124
+ await this.getCollectionHandler(collection).deleteMany({ where: conditions });
125
+ return;
126
+ }
127
+ async findBy(collection, conditions, fields = null, ordering = null, allowRelations = true) {
128
+ const params = { where: conditions };
129
+ if (fields) {
130
+ params.select = {};
131
+ fields.forEach((fieldName) => {
132
+ params.select[fieldName] = true;
133
+ });
134
+ }
135
+ if (ordering) {
136
+ params.orderBy = ordering;
137
+ }
138
+ const retData = await this.getCollectionHandler(collection).findMany(params);
139
+ return retData;
140
+ }
141
+ async collectionExists(collection_name) {
142
+ var _a;
143
+ const dbUrl = ((_a = this.opts) === null || _a === void 0 ? void 0 : _a.dbUrl) || this.configService.get('mongo_url');
144
+ const client = new mongodb_1.MongoClient(dbUrl);
145
+ try {
146
+ await client.connect();
147
+ const db = client.db(this.configService.get('mongo_db'));
148
+ const collections = await db.listCollections().toArray();
149
+ const existingCollectionNames = collections.map((collection) => collection.name);
150
+ return existingCollectionNames.includes(collection_name);
151
+ }
152
+ catch (error) {
153
+ console.error('Error connecting to MongoDB:', error);
154
+ throw error;
155
+ }
156
+ }
157
+ async createTimeSeriesCollection(collection_name) {
158
+ try {
159
+ const db = await this.createBaseMongoClientDB();
160
+ // Create a time series collection
161
+ const options = {
162
+ timeseries: {
163
+ timeField: 'timestamp', // Replace with your timestamp field
164
+ metaField: 'params' // Replace with your metadata field
165
+ }
166
+ };
167
+ await db.createCollection(collection_name, options); // Replace with your collection name
168
+ return db.collection(collection_name);
169
+ }
170
+ catch (error) {
171
+ console.error('Error connecting to MongoDB:', error);
172
+ throw error;
173
+ }
174
+ }
175
+ getCollectionHandler(collection) {
176
+ if (!this.client || !this.connected) {
177
+ this.connectToDB();
178
+ }
179
+ return this.client[collection];
180
+ }
181
+ setOpts(opts = null) {
182
+ this.opts = opts;
183
+ return this;
184
+ }
185
+ }
186
+ exports.DBService = DBService;
@@ -0,0 +1,9 @@
1
+ import { OpModelType } from "../models/_model";
2
+ export interface IDbConfigParams {
3
+ mongo_url?: string;
4
+ mongo_db?: string;
5
+ db_models?: OpModelType<any>[];
6
+ }
7
+ export interface IDbConfigHandler {
8
+ get<K extends keyof IDbConfigParams>(key: K): IDbConfigParams[K];
9
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,9 @@
1
+ export type FindByType = {
2
+ conditions?: any;
3
+ ordering?: {
4
+ [fieldName: string]: string;
5
+ };
6
+ fields?: string[];
7
+ allowRelations?: boolean;
8
+ fullData?: boolean;
9
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ export interface IRWSModel {
2
+ id?: string;
3
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,6 @@
1
+ export interface ITimeSeries {
2
+ value: number;
3
+ timestamp?: Date;
4
+ params?: any;
5
+ time_tracker_id?: string;
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@rws-framework/db",
3
3
  "private": false,
4
- "version": "2.0.2",
4
+ "version": "2.0.4",
5
5
  "description": "",
6
- "main": "src/index.ts",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
7
8
  "scripts": {},
8
9
  "author": "papablack",
9
10
  "license": "ISC",
@@ -20,14 +21,12 @@
20
21
  "crypto": "^1.0.1",
21
22
  "source-map-support": "^0.5.21",
22
23
  "tsconfig-paths": "^4.2.0",
23
- "tsconfig-paths-webpack-plugin": "^4.1.0",
24
- "webpack": "^5.97.1",
25
- "webpack-cli": "^6.0.1",
26
- "webpack-bundle-analyzer": "^4.10.2",
27
- "webpack-node-externals": "^3.0.0"
24
+ "tsconfig-paths-webpack-plugin": "^4.1.0"
28
25
  },
29
26
  "devDependencies": {
30
- "@types/xml2js": "^0.4.14"
27
+ "@types/xml2js": "^0.4.14",
28
+ "typescript": "^5.7.2"
29
+
31
30
  },
32
31
  "repository": {
33
32
  "type": "git",
@@ -76,7 +76,7 @@ export class DbHelper {
76
76
  }
77
77
  }
78
78
 
79
- static async generateModelSections<T extends unknown>(model: OpModelType<T>): Promise<string> {
79
+ static async generateModelSections(model: OpModelType<any>): Promise<string> {
80
80
  let section = '';
81
81
  const modelMetadatas: Record<string, {annotationType: string, metadata: any}> = await RWSModel.getModelAnnotations(model);
82
82
 
@@ -95,7 +95,7 @@ export class DbHelper {
95
95
  }
96
96
 
97
97
  if(annotationType === 'Relation'){
98
- const relatedModel = modelMetadata.relatedTo as OpModelType<T>;
98
+ const relatedModel = modelMetadata.relatedTo as OpModelType<any>;
99
99
  // Handle direct relation (many-to-one or one-to-one)
100
100
  section += `\t${key} ${relatedModel._collection}${requiredString} @relation("${modelName}_${relatedModel._collection}", fields: [${modelMetadata.relationField}], references: [${modelMetadata.relatedToField}], onDelete: Cascade)\n`;
101
101
  section += `\t${modelMetadata.relationField} String${requiredString} @db.ObjectId\n`;
@@ -29,6 +29,7 @@ type RelManyMetaType<T extends IRWSModel> = {[key: string]: {key: string, invers
29
29
 
30
30
  export interface OpModelType<ChildClass> {
31
31
  new(data?: any | null): ChildClass;
32
+ services: IRWSModelServices;
32
33
  name: string
33
34
  _collection: string;
34
35
  _RELATIONS: {[key: string]: boolean}
@@ -37,8 +38,6 @@ export interface OpModelType<ChildClass> {
37
38
  loadModels: () => OpModelType<any>[];
38
39
  checkForInclusionWithThrow: (className: string) => void;
39
40
  checkForInclusion: (className: string) => boolean;
40
- configService?: IDbConfigHandler;
41
- dbService?: DBService;
42
41
  findOneBy<T extends RWSModel<T>>(
43
42
  this: OpModelType<T>,
44
43
  findParams: FindByType
@@ -60,14 +59,12 @@ export interface OpModelType<ChildClass> {
60
59
  getRelationOneMeta(model: any, classFields: string[]): Promise<RelOneMetaType<IRWSModel>>;
61
60
  getRelationManyMeta(model: any, classFields: string[]): Promise<RelManyMetaType<IRWSModel>>;
62
61
  getCollection(): string;
62
+ setServices(services: IRWSModelServices): void;
63
63
  }
64
64
 
65
65
  class RWSModel<ChildClass> implements IModel{
66
- static services: IRWSModelServices = {}
67
-
68
- static configService: IDbConfigHandler;
69
- static dbService: DBService
70
-
66
+ static services: IRWSModelServices = {};
67
+
71
68
  [key: string]: any;
72
69
  @TrackType(String)
73
70
  id: string;
@@ -83,8 +80,8 @@ class RWSModel<ChildClass> implements IModel{
83
80
 
84
81
  }
85
82
 
86
- this.dbService = RWSModel.dbService;
87
- this.configService = RWSModel.configService;
83
+ this.dbService = RWSModel.services.dbService;
84
+ this.configService = RWSModel.services.configService;
88
85
 
89
86
  if(!data){
90
87
  return;
@@ -99,7 +96,7 @@ class RWSModel<ChildClass> implements IModel{
99
96
 
100
97
  checkForInclusionWithThrow(): void
101
98
  {
102
- this.checkForInclusionWithThrow()
99
+ this.checkForInclusionWithThrow();
103
100
  }
104
101
 
105
102
  static checkForInclusionWithThrow(this: OpModelType<any>, checkModelType: string): void
@@ -117,8 +114,8 @@ class RWSModel<ChildClass> implements IModel{
117
114
  static checkForInclusion(this: OpModelType<any>, checkModelType: string): boolean
118
115
  {
119
116
  return this.loadModels().find((definedModel: OpModelType<any>) => {
120
- return definedModel.name === checkModelType
121
- }) !== undefined
117
+ return definedModel.name === checkModelType;
118
+ }) !== undefined;
122
119
  }
123
120
 
124
121
  protected _fill(data: any): RWSModel<ChildClass>{
@@ -543,7 +540,7 @@ class RWSModel<ChildClass> implements IModel{
543
540
  ){
544
541
  const collection = Reflect.get(this, '_collection');
545
542
  this.checkForInclusionWithThrow(this.name);
546
- return await this.dbService.watchCollection(collection, preRun);
543
+ return await this.services.dbService.watchCollection(collection, preRun);
547
544
  }
548
545
 
549
546
  public static async findOneBy<ChildClass extends RWSModel<ChildClass>>(
@@ -560,7 +557,7 @@ class RWSModel<ChildClass> implements IModel{
560
557
 
561
558
 
562
559
  const collection = Reflect.get(this, '_collection');
563
- const dbData = await this.dbService.findOneBy(collection, conditions, fields, ordering, allowRelations);
560
+ const dbData = await this.services.dbService.findOneBy(collection, conditions, fields, ordering, allowRelations);
564
561
 
565
562
 
566
563
  if (dbData) {
@@ -584,7 +581,7 @@ class RWSModel<ChildClass> implements IModel{
584
581
  const collection = Reflect.get(this, '_collection');
585
582
  this.checkForInclusionWithThrow(this.name);
586
583
 
587
- const dbData = await this.dbService.findOneBy(collection, { id }, fields, ordering, allowRelations);
584
+ const dbData = await this.services.dbService.findOneBy(collection, { id }, fields, ordering, allowRelations);
588
585
 
589
586
  if (dbData) {
590
587
  const inst: ChildClass = new (this as { new(): ChildClass })();
@@ -607,7 +604,7 @@ class RWSModel<ChildClass> implements IModel{
607
604
  const collection = Reflect.get(this, '_collection');
608
605
  this.checkForInclusionWithThrow(this.name);
609
606
  try {
610
- const dbData = await this.dbService.findBy(collection, conditions, fields, ordering, allowRelations);
607
+ const dbData = await this.services.dbService.findBy(collection, conditions, fields, ordering, allowRelations);
611
608
  if (dbData.length) {
612
609
  const instanced: ChildClass[] = [];
613
610
 
@@ -633,7 +630,7 @@ class RWSModel<ChildClass> implements IModel{
633
630
  ): Promise<void> {
634
631
  const collection = Reflect.get(this, '_collection');
635
632
  this.checkForInclusionWithThrow(this.name);
636
- return await this.dbService.delete(collection, conditions);
633
+ return await this.services.dbService.delete(collection, conditions);
637
634
  }
638
635
 
639
636
  public async delete<ChildClass extends RWSModel<ChildClass>>(): Promise<void> {
@@ -657,7 +654,7 @@ class RWSModel<ChildClass> implements IModel{
657
654
 
658
655
  static loadModels(): OpModelType<any>[]
659
656
  {
660
- return RWSModel.allModels;
657
+ return this.allModels || [];
661
658
  }
662
659
 
663
660
  loadModels(): OpModelType<any>[]
@@ -670,8 +667,9 @@ class RWSModel<ChildClass> implements IModel{
670
667
  return Object.keys((this as any).constructor._RELATIONS).includes(key) && (this as any).constructor._RELATIONS[key] === true
671
668
  }
672
669
 
673
- public static setServices(services: IRWSModelServices){
674
- RWSModel.services = {...RWSModel.services, ...services};
670
+ public static setServices(services: IRWSModelServices){
671
+ this.allModels = services.configService.get('db_models');
672
+ this.services = services;
675
673
  }
676
674
  }
677
675
 
package/tsconfig.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "baseUrl": ".",
4
+ "experimentalDecorators": true,
5
+ "emitDecoratorMetadata": true,
6
+ "target": "ES2018",
7
+ "module": "commonjs",
8
+ "moduleResolution": "node",
9
+ "strict": true,
10
+ "skipLibCheck": true,
11
+ "esModuleInterop": true,
12
+ "resolveJsonModule": true,
13
+ "strictNullChecks": false,
14
+ "allowSyntheticDefaultImports": true,
15
+ "sourceMap": false,
16
+ "declaration": true,
17
+ "outDir": "./dist"
18
+ },
19
+ "include": [
20
+ "src"
21
+ ],
22
+ "exclude": []
23
+ }