bd-orm 0.0.1

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.
Files changed (59) hide show
  1. package/.github/workflows/build-and-test.yml +26 -0
  2. package/.github/workflows/publish.yml +36 -0
  3. package/.prettierrc.json +14 -0
  4. package/CHANGELOG.md +3 -0
  5. package/README.md +5 -0
  6. package/check NBR en TODO.txt +32 -0
  7. package/dist/_/BdORMBase.d.ts +111 -0
  8. package/dist/_/BdORMBase.js +262 -0
  9. package/dist/_/BdORMCrud.d.ts +51 -0
  10. package/dist/_/BdORMCrud.js +223 -0
  11. package/dist/_/BdORMError.d.ts +4 -0
  12. package/dist/_/BdORMError.js +14 -0
  13. package/dist/_/BdOrmConnection.d.ts +32 -0
  14. package/dist/_/BdOrmConnection.js +5 -0
  15. package/dist/_/cdsBaseOrm.d.ts +12 -0
  16. package/dist/_/cdsBaseOrm.js +21 -0
  17. package/dist/dbConnections/BdOrmDbConnectionCapHana/index.d.ts +26 -0
  18. package/dist/dbConnections/BdOrmDbConnectionCapHana/index.js +78 -0
  19. package/dist/dbConnections/BdOrmDbConnectionCapHana/utils.d.ts +14 -0
  20. package/dist/dbConnections/BdOrmDbConnectionCapHana/utils.js +49 -0
  21. package/dist/dbConnections/BdOrmDbConnectionCapSqlite/index.d.ts +22 -0
  22. package/dist/dbConnections/BdOrmDbConnectionCapSqlite/index.js +85 -0
  23. package/dist/dbConnections/BdOrmDbConnectionCapSqlite/utils.d.ts +3 -0
  24. package/dist/dbConnections/BdOrmDbConnectionCapSqlite/utils.js +74 -0
  25. package/dist/dbConnections/BdOrmDbConnectionSQLBase.d.ts +32 -0
  26. package/dist/dbConnections/BdOrmDbConnectionSQLBase.js +99 -0
  27. package/dist/index.d.ts +8 -0
  28. package/dist/index.js +18 -0
  29. package/dist/test-assets/Post.d.ts +12 -0
  30. package/dist/test-assets/Post.js +13 -0
  31. package/dist/test-assets/User.d.ts +16 -0
  32. package/dist/test-assets/User.js +13 -0
  33. package/dist/test-assets/jestUtils.d.ts +5 -0
  34. package/dist/test-assets/jestUtils.js +30 -0
  35. package/jest.config.js +7 -0
  36. package/package.json +53 -0
  37. package/src/_/BdORMBase.ts +288 -0
  38. package/src/_/BdORMCrud.test.ts +198 -0
  39. package/src/_/BdORMCrud.ts +240 -0
  40. package/src/_/BdORMError.ts +10 -0
  41. package/src/_/BdORMbase.test.ts +166 -0
  42. package/src/_/BdOrmConnection.ts +39 -0
  43. package/src/_/cdsBaseOrm.ts +18 -0
  44. package/src/dbConnections/BdOrmDbConnectionCapHana/index.ts +95 -0
  45. package/src/dbConnections/BdOrmDbConnectionCapHana/utils.ts +47 -0
  46. package/src/dbConnections/BdOrmDbConnectionCapHana.test.ts +18 -0
  47. package/src/dbConnections/BdOrmDbConnectionCapSqlite/index.ts +89 -0
  48. package/src/dbConnections/BdOrmDbConnectionCapSqlite/utils.ts +75 -0
  49. package/src/dbConnections/BdOrmDbConnectionCapSqlite.test.ts +41 -0
  50. package/src/dbConnections/BdOrmDbConnectionSQLBase.ts +124 -0
  51. package/src/index.ts +8 -0
  52. package/src/test-assets/Post.ts +16 -0
  53. package/src/test-assets/User.ts +18 -0
  54. package/src/test-assets/db/BdOrm.cds +20 -0
  55. package/src/test-assets/db/csv/bdorm-user.csv +3 -0
  56. package/src/test-assets/db/views/user.hdbview +3 -0
  57. package/src/test-assets/jestUtils.ts +24 -0
  58. package/tsconfig.json +16 -0
  59. package/validate-package.js +113 -0
@@ -0,0 +1,223 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const BdORMBase_1 = __importStar(require("./BdORMBase"));
37
+ const BdORMError_1 = require("./BdORMError");
38
+ const _filerDataByTable = async (self) => {
39
+ const data = self.getData(true);
40
+ const columns = await self.constructor.getDbConnection().getTableColumns(self.getTable());
41
+ return Object.keys(data).reduce((acc, key) => {
42
+ if (columns.includes(key))
43
+ acc[key] = data[key];
44
+ return acc;
45
+ }, {});
46
+ };
47
+ class BdORMCrud extends BdORMBase_1.default {
48
+ static _DbConnection;
49
+ // Events
50
+ async beforeCreate(beforeCreateParams) {
51
+ /* Overschrijf deze functie indien nodig */
52
+ }
53
+ async beforeUpdate(beforeUpdateParams) {
54
+ /* Overschrijf deze functie indien nodig */
55
+ }
56
+ async beforeSave(beforeSaveParams) {
57
+ /* Overschrijf deze functie indien nodig */
58
+ }
59
+ async afterCreate(afterCreateParams) {
60
+ /* Overschrijf deze functie indien nodig */
61
+ }
62
+ async afterUpdate(afterUpdateParams) {
63
+ /* Overschrijf deze functie indien nodig */
64
+ }
65
+ async afterSave(afterSaveParams) {
66
+ /* Overschrijf deze functie indien nodig */
67
+ }
68
+ async beforeDelete() { }
69
+ async afterDelete() { }
70
+ _execDBConnectionMethod(method, ...args) {
71
+ //@ts-ignore
72
+ return this.constructor._DbConnection[method](...args);
73
+ }
74
+ async _create({ preventBeforeCreate = false, preventAfterCreate = false } = {}) {
75
+ if (!preventBeforeCreate)
76
+ await this.beforeCreate();
77
+ const data = await _filerDataByTable(this), primaryKey = this.getPrimaryKey();
78
+ if (primaryKey in data)
79
+ delete data[primaryKey];
80
+ const result = { ...(await this._execDBConnectionMethod('create', this.getTable(), data)) };
81
+ const primaryKeyValue = primaryKey in result ? result[primaryKey] : false;
82
+ if (primaryKeyValue)
83
+ delete result[primaryKey];
84
+ // when creating a new entry, it is not necessary to add all columns
85
+ // and with an insert, you get all columns back from the db
86
+ // so recreate the propertyDescriptors
87
+ (0, BdORMBase_1.definePropertyDescriptors)(this, result);
88
+ // important AFTER definePropertyDescriptors
89
+ if (primaryKeyValue)
90
+ this.setProperty(primaryKey, primaryKeyValue);
91
+ if (!preventAfterCreate)
92
+ await this.afterCreate();
93
+ this._setChangedProperties([]);
94
+ return {
95
+ [primaryKey]: primaryKeyValue,
96
+ ...result,
97
+ };
98
+ }
99
+ async _update({ preventBeforeUpdate = false, preventAfterUpdate = false } = {}) {
100
+ if (this.isNew())
101
+ throw new BdORMError_1.BdORMError('Cannot update an new instance');
102
+ if (!preventBeforeUpdate)
103
+ await this.beforeUpdate();
104
+ const data = await _filerDataByTable(this);
105
+ await this._execDBConnectionMethod('update', this.getTable(), data, {
106
+ primaryKey: this.getPrimaryKey(),
107
+ });
108
+ if (!preventAfterUpdate)
109
+ await this.afterUpdate();
110
+ }
111
+ /**
112
+ * Delete an instance from the database
113
+ */
114
+ async delete() {
115
+ this.constructor.isMethodAllowed('delete', { throwErrorIfNotAllowed: true });
116
+ if (!this.id) {
117
+ throw new BdORMError_1.BdORMError('Cannot delete an instance without an id');
118
+ }
119
+ await this.beforeDelete();
120
+ await this._execDBConnectionMethod('delete', this.getTable(), this.getPrimaryKeyValue(), {
121
+ primaryKey: this.getPrimaryKey(),
122
+ });
123
+ await this.afterDelete();
124
+ }
125
+ /**
126
+ * Duplicates the current instance and if the options asDraft is not defined or false it will be saved it to the database
127
+ */
128
+ async duplicate({ asDraft = false, newData = {}, excludeColumns = [] } = {}) {
129
+ const self = this.constructor;
130
+ self.isMethodAllowed('duplicate', { throwErrorIfNotAllowed: true });
131
+ if (!asDraft && this.isNew())
132
+ throw new BdORMError_1.BdORMError('Cannot duplicate an new instance');
133
+ const data = { ...this.getData(true) };
134
+ const primaryKey = this.getPrimaryKey();
135
+ if (primaryKey in data)
136
+ delete data[primaryKey];
137
+ for (const key in data) {
138
+ if (excludeColumns.includes(key) || self.PROPERTIES_NOT_ALLOWED_TO_DUPLICATE.includes(key)) {
139
+ delete data[key];
140
+ continue;
141
+ }
142
+ if (key in newData)
143
+ data[key] = typeof newData[key] === 'function' ? newData[key](data[key]) : newData[key];
144
+ }
145
+ const newInstance = new self(data);
146
+ if (!asDraft)
147
+ await newInstance.save({ preventBeforeSave: true, preventAfterSave: true });
148
+ return newInstance;
149
+ }
150
+ async save({ beforeSaveParams = {}, afterSaveParams = {}, preventAfterSave = false, preventBeforeSave = false, } = {}) {
151
+ this.constructor.isMethodAllowed('save', { throwErrorIfNotAllowed: true });
152
+ await this.beforeSave(beforeSaveParams);
153
+ if (this.isNew()) {
154
+ await this._create({ preventBeforeCreate: preventBeforeSave, preventAfterCreate: preventAfterSave });
155
+ }
156
+ else {
157
+ await this._update({ preventBeforeUpdate: preventBeforeSave, preventAfterUpdate: preventAfterSave });
158
+ }
159
+ if (!preventAfterSave) {
160
+ await this.afterSave(afterSaveParams);
161
+ }
162
+ return this;
163
+ }
164
+ // STATICS
165
+ static async count(where, values) {
166
+ const result = await this._DbConnection.list(this.VIEW, {
167
+ columns: 'COUNT(*) as count',
168
+ filters: where,
169
+ values,
170
+ });
171
+ return result[0].count;
172
+ }
173
+ static async create(data) {
174
+ const instance = new this(data);
175
+ await instance.save();
176
+ return instance;
177
+ }
178
+ static async fetch(where, values) {
179
+ const results = await this._DbConnection.list(this.VIEW, {
180
+ columns: this.COLUMNS_TO_FETCH,
181
+ filters: where,
182
+ values,
183
+ });
184
+ return results.map((result) => new this(result));
185
+ }
186
+ static async fetchById(id) {
187
+ return this.fetchByPrimaryKey(id);
188
+ }
189
+ static async fetchOne(where, values) {
190
+ let limit;
191
+ if (typeof where === 'string')
192
+ where += ' LIMIT 1';
193
+ else
194
+ limit = 1;
195
+ const results = await this._DbConnection.list(this.VIEW, {
196
+ columns: this.COLUMNS_TO_FETCH,
197
+ filters: where,
198
+ limit,
199
+ values,
200
+ });
201
+ return results?.length ? new this(results[0]) : undefined;
202
+ }
203
+ static async fetchByPrimaryKey(primaryKeyValue) {
204
+ const primaryKey = await this._DbConnection.getTablePrimaryKey(this.TABLE);
205
+ const result = await this._DbConnection.read(this.VIEW, primaryKeyValue, { primaryKey });
206
+ if (!result)
207
+ throw new BdORMError_1.BdORMError(`No entry found for ${this.VIEW} with ${this.PRIMARY_KEY} ${primaryKeyValue}`);
208
+ return new this(result);
209
+ }
210
+ static setDbConnection(dbConnection) {
211
+ if (this._DbConnection)
212
+ throw new BdORMError_1.BdORMError('DbConnection already set');
213
+ this._DbConnection = dbConnection;
214
+ }
215
+ static clearDbConnection() {
216
+ //@ts-ignore
217
+ this._DbConnection = undefined;
218
+ }
219
+ static getDbConnection() {
220
+ return this._DbConnection;
221
+ }
222
+ }
223
+ exports.default = BdORMCrud;
@@ -0,0 +1,4 @@
1
+ export declare class BdORMError extends Error {
2
+ constructor(msg: string);
3
+ static staticNotImplemented(methodName: string): BdORMError;
4
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BdORMError = void 0;
4
+ class BdORMError extends Error {
5
+ constructor(msg) {
6
+ super(`[bd-Orm Error]: ${msg}`);
7
+ Error.captureStackTrace(this, BdORMError);
8
+ this.name = 'BdORMError';
9
+ }
10
+ static staticNotImplemented(methodName) {
11
+ return new BdORMError(`static ${methodName} not implemented! Set in derived class`);
12
+ }
13
+ }
14
+ exports.BdORMError = BdORMError;
@@ -0,0 +1,32 @@
1
+ export default abstract class BdOrmDbConnection {
2
+ /**
3
+ * Create a new entry in the table
4
+ * @param table The table to create the entry in
5
+ * @param data The data to create the entry with
6
+ * @param params Additional parameters
7
+ * @returns The created entry
8
+ */
9
+ abstract create(table: string, data: Record<string, any>, params?: {
10
+ primaryKey: string;
11
+ }): Promise<Record<string, any>>;
12
+ abstract read(table: string, primaryKeyValue: string | number, params?: {
13
+ primaryKey: string;
14
+ }): Promise<Record<string, any> | undefined>;
15
+ abstract update(table: string, data: any, params?: {
16
+ primaryKey: string;
17
+ }): Promise<void>;
18
+ abstract delete(table: string, primaryKeyValue: string | number, params?: {
19
+ primaryKey: string;
20
+ }): Promise<void>;
21
+ abstract list(table: string, params?: {
22
+ columns?: string | string[];
23
+ filters?: Record<string, any> | string;
24
+ limit?: number;
25
+ offset?: number;
26
+ orderBy?: string;
27
+ values?: any[];
28
+ }): Promise<Record<string, any>[]>;
29
+ abstract query(query: string, escapedValues?: any[]): Promise<Record<string, any>[]>;
30
+ abstract getTablePrimaryKey(table: string): Promise<string>;
31
+ abstract getTableColumns(table: string): Promise<string[]>;
32
+ }
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class BdOrmDbConnection {
4
+ }
5
+ exports.default = BdOrmDbConnection;
@@ -0,0 +1,12 @@
1
+ import BaseORM from './BdORMBase';
2
+ import cds from '@sap/cds';
3
+ /**
4
+ * Base class for CDS ORM
5
+ */
6
+ export default abstract class cdsBaseOrm extends BaseORM {
7
+ /**
8
+ * Get the CDS model for the current table
9
+ * @returns the CDS model for the current table
10
+ */
11
+ static get CDS_MODEL(): cds.entity | undefined;
12
+ }
@@ -0,0 +1,21 @@
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
+ const BdORMBase_1 = __importDefault(require("./BdORMBase"));
7
+ const cds_1 = __importDefault(require("@sap/cds"));
8
+ /**
9
+ * Base class for CDS ORM
10
+ */
11
+ class cdsBaseOrm extends BdORMBase_1.default {
12
+ /**
13
+ * Get the CDS model for the current table
14
+ * @returns the CDS model for the current table
15
+ */
16
+ static get CDS_MODEL() {
17
+ const namespace = this.TABLE.split('_')[0].toLowerCase();
18
+ return Object.values(cds_1.default.entities(namespace)).find((o) => 'name' in o && o.name.toUpperCase().replace(/\./g, '_') === this.TABLE);
19
+ }
20
+ }
21
+ exports.default = cdsBaseOrm;
@@ -0,0 +1,26 @@
1
+ import BdOrmDbConnectionSQLBase from '../BdOrmDbConnectionSQLBase';
2
+ import cds from '@sap/cds';
3
+ export default class BdOrmDbConnectionCapHana extends BdOrmDbConnectionSQLBase {
4
+ protected _db(): Promise<cds.DatabaseService>;
5
+ close(): Promise<void>;
6
+ getTableColumns(table: string): Promise<string[]>;
7
+ /**
8
+ * Get the primary key of the table
9
+ */
10
+ getTablePrimaryKey(table: string): Promise<string>;
11
+ create(table: string, data: Record<string, any>): Promise<any>;
12
+ /**
13
+ * Custom overwrites for list and read > hana stores the db columns in uppercase, so we need to convert the columns to what is defined in the cds file
14
+ */
15
+ list(table: string, options?: {
16
+ columns?: string | string[];
17
+ filters?: Record<string, any> | string;
18
+ limit?: number;
19
+ offset?: number;
20
+ orderBy?: string;
21
+ values?: any[];
22
+ }): Promise<any>;
23
+ read(table: string, primaryKeyValue: string | number, { primaryKey }?: {
24
+ primaryKey?: string;
25
+ }): Promise<any>;
26
+ }
@@ -0,0 +1,78 @@
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
+ /**
7
+ * Use this connection when your project is using SAP CAP and running a SAP HANA DB
8
+ * This class extends the BdOrmDbConnectionSQLBase and provides methods to interact with a SQLite database
9
+ * Need to work with unit tests? use the BdOrmDbConnectionCapSqlite class
10
+ */
11
+ const BdORMError_1 = require("../../_/BdORMError");
12
+ const BdOrmDbConnectionSQLBase_1 = __importDefault(require("../BdOrmDbConnectionSQLBase"));
13
+ const utils_1 = require("./utils");
14
+ const cds_1 = __importDefault(require("@sap/cds"));
15
+ const PRIMARY_KEYS = {};
16
+ const TABLE_COLUMNS = {};
17
+ const remapResultColumns = (result, columns) => {
18
+ return Object.entries(result).reduce((resultMapped, [key, value]) => {
19
+ const column = columns.find(column => column.toUpperCase() === key.toUpperCase());
20
+ resultMapped[column ?? key] = value;
21
+ return resultMapped;
22
+ }, {});
23
+ };
24
+ class BdOrmDbConnectionCapHana extends BdOrmDbConnectionSQLBase_1.default {
25
+ async _db() {
26
+ return cds_1.default.db ? cds_1.default.db : await cds_1.default.connect.to('db');
27
+ }
28
+ async close() {
29
+ const db = await this._db();
30
+ //@ts-ignore jest zegt cds.disconnect does not exists
31
+ await db.disconnect();
32
+ }
33
+ async getTableColumns(table) {
34
+ const cdsColumns = (0, utils_1.getTableColumns)(table);
35
+ if (cdsColumns)
36
+ return cdsColumns;
37
+ if (TABLE_COLUMNS[table])
38
+ return TABLE_COLUMNS[table];
39
+ const tableInfo = await this.query(`SELECT COLUMN_NAME FROM TABLE_COLUMNS WHERE TABLE_NAME = '${table}'`);
40
+ if (tableInfo.length === 0)
41
+ throw new BdORMError_1.BdORMError(`No columns found for table ${table}`);
42
+ TABLE_COLUMNS[table] = tableInfo.map(info => info.COLUMN_NAME);
43
+ return TABLE_COLUMNS[table];
44
+ }
45
+ /**
46
+ * Get the primary key of the table
47
+ */
48
+ async getTablePrimaryKey(table) {
49
+ const primaryKey = (0, utils_1.getTablePrimaryKey)(table);
50
+ if (primaryKey)
51
+ return primaryKey;
52
+ if (PRIMARY_KEYS[table])
53
+ return PRIMARY_KEYS[table];
54
+ const tableInfo = await this.query(`SELECT COLUMN_NAME FROM SYS.INDEX_COLUMNS WHERE TABLE_NAME = '${table}' AND CONSTRAINT = 'PRIMARY KEY'`);
55
+ PRIMARY_KEYS[table] = tableInfo[0]?.COLUMN_NAME;
56
+ if (!PRIMARY_KEYS[table])
57
+ throw new BdORMError_1.BdORMError(`No primary key found for table ${table}`);
58
+ return PRIMARY_KEYS[table];
59
+ }
60
+ async create(table, data) {
61
+ const columns = Object.keys(data), placeholders = columns.map(() => '?').join(','), pk = await this.getTablePrimaryKey(table);
62
+ await this.query(`INSERT INTO ${table} (${columns.join(',')}) VALUES (${placeholders})`, columns.map(column => data[column]));
63
+ const result = await this.query(`SELECT * FROM ${table} ORDER BY ${pk} DESC LIMIT 1`);
64
+ return result[0];
65
+ }
66
+ /**
67
+ * Custom overwrites for list and read > hana stores the db columns in uppercase, so we need to convert the columns to what is defined in the cds file
68
+ */
69
+ async list(table, options = {}) {
70
+ const results = await super.list(table, options), columns = await this.getTableColumns(table);
71
+ return results?.map((result) => remapResultColumns(result, columns));
72
+ }
73
+ async read(table, primaryKeyValue, { primaryKey } = {}) {
74
+ const result = await super.read(table, primaryKeyValue, { primaryKey }), columns = await this.getTableColumns(table);
75
+ return result ? remapResultColumns(result, columns) : result;
76
+ }
77
+ }
78
+ exports.default = BdOrmDbConnectionCapHana;
@@ -0,0 +1,14 @@
1
+ type Definitions = {
2
+ [table: string]: {
3
+ primaryKey: string;
4
+ columnNames: string[];
5
+ };
6
+ };
7
+ declare const getDefinitions: () => Definitions | undefined;
8
+ declare const getTableDefinition: (table: string) => {
9
+ primaryKey: string;
10
+ columnNames: string[];
11
+ } | undefined;
12
+ declare const getTablePrimaryKey: (table: string) => string | undefined;
13
+ declare const getTableColumns: (table: string) => string[] | undefined;
14
+ export { getDefinitions, getTableDefinition, getTablePrimaryKey, getTableColumns };
@@ -0,0 +1,49 @@
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.getTableColumns = exports.getTablePrimaryKey = exports.getTableDefinition = exports.getDefinitions = void 0;
7
+ const cds_1 = __importDefault(require("@sap/cds"));
8
+ const _definitionCache = {};
9
+ const getDefinitions = () => {
10
+ if (Object.keys(_definitionCache).length)
11
+ return _definitionCache;
12
+ const cdsDefinitions = (cds_1.default?.model?.definitions ?? cds_1.default.entities ?? {});
13
+ if (Object.keys(cdsDefinitions).length === 0)
14
+ return undefined;
15
+ Object.entries(cdsDefinitions).forEach(([key, { elements, name }]) => {
16
+ if (elements === undefined)
17
+ return;
18
+ _definitionCache[name.toLowerCase().replace(/\./g, '_')] = {
19
+ primaryKey: Object.entries(elements).find(([_, { key }]) => key)?.[0] ?? '',
20
+ columnNames: Object.entries(elements).map(([column]) => column),
21
+ };
22
+ });
23
+ return _definitionCache;
24
+ };
25
+ exports.getDefinitions = getDefinitions;
26
+ const getTableDefinition = (table) => {
27
+ const definitions = getDefinitions();
28
+ if (!definitions)
29
+ return undefined;
30
+ const tableDefinition = definitions[table.toLowerCase().replace(/\./g, '_')];
31
+ if (!tableDefinition)
32
+ return undefined;
33
+ return tableDefinition;
34
+ };
35
+ exports.getTableDefinition = getTableDefinition;
36
+ const getTablePrimaryKey = (table) => {
37
+ const tableDefinition = getTableDefinition(table);
38
+ if (!tableDefinition)
39
+ return undefined;
40
+ return tableDefinition.primaryKey;
41
+ };
42
+ exports.getTablePrimaryKey = getTablePrimaryKey;
43
+ const getTableColumns = (table) => {
44
+ const tableDefinition = getTableDefinition(table);
45
+ if (!tableDefinition)
46
+ return undefined;
47
+ return tableDefinition.columnNames;
48
+ };
49
+ exports.getTableColumns = getTableColumns;
@@ -0,0 +1,22 @@
1
+ import BdOrmDbConnectionSQLBase from '../BdOrmDbConnectionSQLBase';
2
+ import cds from '@sap/cds';
3
+ export default class BdOrmDbConnectionCapSqlite extends BdOrmDbConnectionSQLBase {
4
+ private readonly _csvFiles;
5
+ private _deployed;
6
+ private _dbPath;
7
+ protected _db(): Promise<cds.DatabaseService>;
8
+ getDb(): Promise<cds.DatabaseService>;
9
+ constructor(dbPath: string, options?: {
10
+ csvFiles: string[];
11
+ });
12
+ getTableColumns(table: string): Promise<string[]>;
13
+ /**
14
+ * Get the primary key of the table
15
+ */
16
+ getTablePrimaryKey(table: string): Promise<string>;
17
+ /**
18
+ * Fills the database with data from the CSV files provided in the constructor
19
+ * note the table will be emptied before filling it with the data from the CSV file
20
+ */
21
+ fillTableFromCsvFile(table: string, csvFile: string): Promise<void>;
22
+ }
@@ -0,0 +1,85 @@
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
+ /**
7
+ * Use this connection class when writing unit tests
8
+ *
9
+ * This class extends the BdOrmDbConnection and provides methods to interact with a SQLite in-memory database
10
+ * for unit testing purposes. It includes functionality to create, read, update, delete, and list records
11
+ * in the database, as well as to execute arbitrary queries.
12
+ *
13
+ * The class maintains a record of deployed databases and primary keys for tables to optimize database
14
+ * operations. It uses the SAP CDS framework for database connectivity and operations.
15
+ *
16
+ * it automatically fills the database with data from the CSV files that are found in the provided database folder
17
+ * or from the CSV files provided in the constructor
18
+ */
19
+ const BdORMError_1 = require("../../_/BdORMError");
20
+ const BdOrmDbConnectionSQLBase_1 = __importDefault(require("../BdOrmDbConnectionSQLBase"));
21
+ const utils_1 = require("./utils");
22
+ const cds_1 = __importDefault(require("@sap/cds"));
23
+ const PRIMARY_KEYS = {};
24
+ const TABLE_INFO = {};
25
+ class BdOrmDbConnectionCapSqlite extends BdOrmDbConnectionSQLBase_1.default {
26
+ _csvFiles = [];
27
+ _deployed = false;
28
+ _dbPath = '';
29
+ async _db() {
30
+ let db;
31
+ if (!this._deployed) {
32
+ //@ts-ignore jest zegt cds.deploy does not exists
33
+ await cds_1.default.deploy(this._dbPath).to('sqlite::memory:');
34
+ db = await cds_1.default.connect.to('db');
35
+ if (!this._csvFiles.length)
36
+ await (0, utils_1.addCsvFilesFromDBFolder)(db, this._dbPath);
37
+ else {
38
+ for (const csvFile of this._csvFiles) {
39
+ await (0, utils_1.fillTableFromCsv)(db, csvFile.split('/').pop()?.replace('.csv', '').replace('-', '_'), csvFile);
40
+ }
41
+ }
42
+ await (0, utils_1.deployHdbViewFiles)(db, this._dbPath);
43
+ this._deployed = true;
44
+ }
45
+ return db ?? cds_1.default.connect.to('db');
46
+ }
47
+ async getDb() {
48
+ return this._db();
49
+ }
50
+ constructor(dbPath, options) {
51
+ super();
52
+ this._csvFiles = options?.csvFiles || [];
53
+ this._dbPath = dbPath;
54
+ }
55
+ async getTableColumns(table) {
56
+ if (TABLE_INFO[table])
57
+ return TABLE_INFO[table].map(info => info.name);
58
+ const tableInfo = await this.query(`PRAGMA table_info(${table})`);
59
+ TABLE_INFO[table] = tableInfo;
60
+ return tableInfo.map(info => info.name);
61
+ }
62
+ /**
63
+ * Get the primary key of the table
64
+ */
65
+ async getTablePrimaryKey(table) {
66
+ if (PRIMARY_KEYS[table])
67
+ return PRIMARY_KEYS[table];
68
+ const tableInfo = await this.query(`PRAGMA table_info(${table})`);
69
+ TABLE_INFO[table] = tableInfo;
70
+ const primaryKey = tableInfo.find(info => info.pk === 1)?.name;
71
+ if (!primaryKey)
72
+ throw new BdORMError_1.BdORMError(`No primary key found for table ${table}`);
73
+ PRIMARY_KEYS[table] = primaryKey;
74
+ return primaryKey;
75
+ }
76
+ /**
77
+ * Fills the database with data from the CSV files provided in the constructor
78
+ * note the table will be emptied before filling it with the data from the CSV file
79
+ */
80
+ async fillTableFromCsvFile(table, csvFile) {
81
+ const db = await this._db();
82
+ await (0, utils_1.fillTableFromCsv)(db, table, csvFile);
83
+ }
84
+ }
85
+ exports.default = BdOrmDbConnectionCapSqlite;
@@ -0,0 +1,3 @@
1
+ import cds from '@sap/cds';
2
+ declare const log: (message: string) => void, fillTableFromCsv: (db: cds.DatabaseService, table: string, csvFile: string) => Promise<void>, findFiles: (currentPath: string, extname: string) => Promise<string[]>, addCsvFilesFromDBFolder: (db: cds.DatabaseService, dbPath: string) => Promise<void>, deployHdbViewFiles: (db: cds.DatabaseService, dbPath: string) => Promise<void>;
3
+ export { addCsvFilesFromDBFolder, fillTableFromCsv, findFiles, log, deployHdbViewFiles };