sspart-be-lib 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/dist/common/clickhouse.service.d.ts +3 -0
- package/dist/common/clickhouse.service.js +41 -0
- package/dist/common/knex.service.d.ts +2 -0
- package/dist/common/knex.service.js +15 -0
- package/dist/common/mongo.service.d.ts +3 -0
- package/dist/common/mongo.service.js +42 -0
- package/dist/common/postgres.service.d.ts +4 -0
- package/dist/common/postgres.service.js +54 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +20 -0
- package/dist/models/clickhouse.base.model.d.ts +16 -0
- package/dist/models/clickhouse.base.model.js +132 -0
- package/dist/models/mongo.base.model.d.ts +24 -0
- package/dist/models/mongo.base.model.js +212 -0
- package/dist/models/postgresql.base.model.d.ts +14 -0
- package/dist/models/postgresql.base.model.js +171 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# sspart-be-lib
|
|
2
|
+
|
|
3
|
+
A small, focused backend utility library providing database connection helpers
|
|
4
|
+
and lightweight base models for ClickHouse (using `@clickhouse/client`), PostgreSQL (using `pg`) and MongoDB (using`mongoose`), plus a helper to create a Knex client. This library is intended
|
|
5
|
+
for internal use at SSPART Enterprises (sspart) and provides convenient
|
|
6
|
+
abstractions for common data access patterns.
|
|
7
|
+
|
|
8
|
+
**Package**
|
|
9
|
+
- **Name:** sspart-be-lib
|
|
10
|
+
- **Version:** 2.0.0
|
|
11
|
+
- **Description:** Backend library for database helpers and base models.
|
|
12
|
+
|
|
13
|
+
**License**
|
|
14
|
+
- ISC
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.closeClickHouse = exports.connectClickHouse = void 0;
|
|
13
|
+
const client_1 = require("@clickhouse/client");
|
|
14
|
+
let client = null;
|
|
15
|
+
const CLICKHOUSE_URL = process.env.CLICKHOUSE_URL || 'http://localhost:8123';
|
|
16
|
+
const CLICKHOUSE_USER = process.env.CLICKHOUSE_USER || 'default';
|
|
17
|
+
const CLICKHOUSE_PASSWORD = process.env.CLICKHOUSE_PASSWORD || '';
|
|
18
|
+
const CLICKHOUSE_DATABASE = process.env.CLICKHOUSE_DATABASE || 'default';
|
|
19
|
+
const connectClickHouse = () => {
|
|
20
|
+
if (client)
|
|
21
|
+
return client;
|
|
22
|
+
try {
|
|
23
|
+
client = (0, client_1.createClient)({ host: CLICKHOUSE_URL, username: CLICKHOUSE_USER,
|
|
24
|
+
password: CLICKHOUSE_PASSWORD, database: CLICKHOUSE_DATABASE });
|
|
25
|
+
console.log(`✅ ClickHouse connected successfully: ${CLICKHOUSE_URL}`);
|
|
26
|
+
return client;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
console.error(`❌ ClickHouse connection failed: ${error.message}`);
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
exports.connectClickHouse = connectClickHouse;
|
|
34
|
+
const closeClickHouse = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
35
|
+
if (client) {
|
|
36
|
+
yield client.close();
|
|
37
|
+
console.log('🔌 ClickHouse connection closed');
|
|
38
|
+
client = null;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
exports.closeClickHouse = closeClickHouse;
|
|
@@ -0,0 +1,15 @@
|
|
|
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.createKnexClient = void 0;
|
|
7
|
+
const knex_1 = __importDefault(require("knex"));
|
|
8
|
+
const createKnexClient = (config) => {
|
|
9
|
+
return (0, knex_1.default)({
|
|
10
|
+
client: 'pg',
|
|
11
|
+
connection: config,
|
|
12
|
+
pool: { min: 1, max: 10 }
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
exports.createKnexClient = createKnexClient;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.closeMongo = exports.connectMongo = void 0;
|
|
16
|
+
const mongoose_1 = __importDefault(require("mongoose"));
|
|
17
|
+
let isConnected = false;
|
|
18
|
+
const uri = process.env.MONGO_URI || 'mongodb://localhost:27017/test';
|
|
19
|
+
const connectMongo = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
20
|
+
if (isConnected)
|
|
21
|
+
return mongoose_1.default;
|
|
22
|
+
try {
|
|
23
|
+
mongoose_1.default.set('strictQuery', false);
|
|
24
|
+
yield mongoose_1.default.connect(uri);
|
|
25
|
+
isConnected = true;
|
|
26
|
+
console.log(`✅ MongoDB connected successfully: ${uri}`);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
console.error(`❌ MongoDB connection failed: ${error.message}`);
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
return mongoose_1.default;
|
|
33
|
+
});
|
|
34
|
+
exports.connectMongo = connectMongo;
|
|
35
|
+
const closeMongo = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
36
|
+
if (isConnected) {
|
|
37
|
+
yield mongoose_1.default.disconnect();
|
|
38
|
+
console.log('🔌 MongoDB connection closed');
|
|
39
|
+
isConnected = false;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
exports.closeMongo = closeMongo;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.closePostgres = exports.getPool = exports.connectPostgres = void 0;
|
|
13
|
+
const pg_1 = require("pg");
|
|
14
|
+
const dbConfig = {
|
|
15
|
+
host: process.env.PG_HOST || 'localhost',
|
|
16
|
+
user: process.env.PG_USER || 'postgres',
|
|
17
|
+
password: process.env.PG_PASSWORD || '',
|
|
18
|
+
database: process.env.PG_DATABASE || 'test',
|
|
19
|
+
port: Number(process.env.PG_PORT) || 5432,
|
|
20
|
+
max: 10,
|
|
21
|
+
idleTimeoutMillis: 30000,
|
|
22
|
+
};
|
|
23
|
+
let pool = null;
|
|
24
|
+
const connectPostgres = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
25
|
+
if (pool)
|
|
26
|
+
return pool;
|
|
27
|
+
try {
|
|
28
|
+
pool = new pg_1.Pool(dbConfig);
|
|
29
|
+
const client = yield pool.connect();
|
|
30
|
+
yield client.query('SELECT 1');
|
|
31
|
+
client.release();
|
|
32
|
+
console.log(`✅ PostgreSQL connected successfully: ${dbConfig.database}`);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
console.error(`❌ PostgreSQL connection failed: ${error.message}`);
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
return pool;
|
|
39
|
+
});
|
|
40
|
+
exports.connectPostgres = connectPostgres;
|
|
41
|
+
const getPool = () => {
|
|
42
|
+
if (!pool)
|
|
43
|
+
throw new Error('PostgreSQL not connected yet. Call connectWithRetry() first.');
|
|
44
|
+
return pool;
|
|
45
|
+
};
|
|
46
|
+
exports.getPool = getPool;
|
|
47
|
+
const closePostgres = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
48
|
+
if (pool) {
|
|
49
|
+
yield pool.end();
|
|
50
|
+
console.log('🔌 PostgreSQL pool closed');
|
|
51
|
+
pool = null;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
exports.closePostgres = closePostgres;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { PostgresSQLBaseModel } from './models/postgresql.base.model';
|
|
2
|
+
export { connectPostgres, closePostgres } from './common/postgres.service';
|
|
3
|
+
export { MongoBaseModel } from './models/mongo.base.model';
|
|
4
|
+
export { connectMongo, closeMongo } from './common/mongo.service';
|
|
5
|
+
export { ClickHouseBaseModel } from './models/clickhouse.base.model';
|
|
6
|
+
export { connectClickHouse, closeClickHouse } from './common/clickhouse.service';
|
|
7
|
+
export { createKnexClient } from './common/knex.service';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createKnexClient = exports.closeClickHouse = exports.connectClickHouse = exports.ClickHouseBaseModel = exports.closeMongo = exports.connectMongo = exports.MongoBaseModel = exports.closePostgres = exports.connectPostgres = exports.PostgresSQLBaseModel = void 0;
|
|
4
|
+
var postgresql_base_model_1 = require("./models/postgresql.base.model");
|
|
5
|
+
Object.defineProperty(exports, "PostgresSQLBaseModel", { enumerable: true, get: function () { return postgresql_base_model_1.PostgresSQLBaseModel; } });
|
|
6
|
+
var postgres_service_1 = require("./common/postgres.service");
|
|
7
|
+
Object.defineProperty(exports, "connectPostgres", { enumerable: true, get: function () { return postgres_service_1.connectPostgres; } });
|
|
8
|
+
Object.defineProperty(exports, "closePostgres", { enumerable: true, get: function () { return postgres_service_1.closePostgres; } });
|
|
9
|
+
var mongo_base_model_1 = require("./models/mongo.base.model");
|
|
10
|
+
Object.defineProperty(exports, "MongoBaseModel", { enumerable: true, get: function () { return mongo_base_model_1.MongoBaseModel; } });
|
|
11
|
+
var mongo_service_1 = require("./common/mongo.service");
|
|
12
|
+
Object.defineProperty(exports, "connectMongo", { enumerable: true, get: function () { return mongo_service_1.connectMongo; } });
|
|
13
|
+
Object.defineProperty(exports, "closeMongo", { enumerable: true, get: function () { return mongo_service_1.closeMongo; } });
|
|
14
|
+
var clickhouse_base_model_1 = require("./models/clickhouse.base.model");
|
|
15
|
+
Object.defineProperty(exports, "ClickHouseBaseModel", { enumerable: true, get: function () { return clickhouse_base_model_1.ClickHouseBaseModel; } });
|
|
16
|
+
var clickhouse_service_1 = require("./common/clickhouse.service");
|
|
17
|
+
Object.defineProperty(exports, "connectClickHouse", { enumerable: true, get: function () { return clickhouse_service_1.connectClickHouse; } });
|
|
18
|
+
Object.defineProperty(exports, "closeClickHouse", { enumerable: true, get: function () { return clickhouse_service_1.closeClickHouse; } });
|
|
19
|
+
var knex_service_1 = require("./common/knex.service");
|
|
20
|
+
Object.defineProperty(exports, "createKnexClient", { enumerable: true, get: function () { return knex_service_1.createKnexClient; } });
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ClickHouseClient } from '@clickhouse/client';
|
|
2
|
+
export declare abstract class ClickHouseBaseModel<T> {
|
|
3
|
+
protected client: ClickHouseClient;
|
|
4
|
+
protected tableName: string;
|
|
5
|
+
protected hasSoftDelete: boolean;
|
|
6
|
+
constructor(client: ClickHouseClient, tableName: string, hasSoftDelete?: boolean);
|
|
7
|
+
protected handleError(method: string, error: Error, ...args: any[]): void;
|
|
8
|
+
protected abstract createTableSQL(): string;
|
|
9
|
+
protected schemaMigrations(): string[];
|
|
10
|
+
createOrUpdateTable(): Promise<boolean>;
|
|
11
|
+
protected tableExists(): Promise<boolean>;
|
|
12
|
+
insertMany(data: T[]): Promise<boolean>;
|
|
13
|
+
findByTimeRange(columns: string, where: string, from: string, to: string, timeColumn?: string): Promise<T[] | []>;
|
|
14
|
+
softDelete(where: string): Promise<boolean>;
|
|
15
|
+
protected applySoftDelete(where: string): string;
|
|
16
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.ClickHouseBaseModel = void 0;
|
|
13
|
+
class ClickHouseBaseModel {
|
|
14
|
+
constructor(client, tableName, hasSoftDelete = false) {
|
|
15
|
+
this.client = client;
|
|
16
|
+
this.tableName = tableName;
|
|
17
|
+
this.hasSoftDelete = hasSoftDelete;
|
|
18
|
+
}
|
|
19
|
+
handleError(method, error, ...args) {
|
|
20
|
+
console.error(`ClickHouse :: ${this.tableName} :: ${method} :: Error :: ${error.message}`, ...args);
|
|
21
|
+
}
|
|
22
|
+
schemaMigrations() {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
createOrUpdateTable() {
|
|
26
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
27
|
+
try {
|
|
28
|
+
const exists = yield this.tableExists();
|
|
29
|
+
if (!exists) {
|
|
30
|
+
yield this.client.exec({ query: this.createTableSQL() });
|
|
31
|
+
console.log(`✅ Created table: ${this.tableName}`);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
for (const sql of this.schemaMigrations()) {
|
|
35
|
+
yield this.client.exec({ query: sql });
|
|
36
|
+
}
|
|
37
|
+
if (this.schemaMigrations().length) {
|
|
38
|
+
console.log(`🔁 Updated schema: ${this.tableName}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
console.error(`❌ ClickHouse :: ${this.tableName} :: createOrUpdateTable`, error.message);
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
tableExists() {
|
|
50
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
51
|
+
var _a;
|
|
52
|
+
const result = yield this.client.query({
|
|
53
|
+
query: `
|
|
54
|
+
SELECT count() AS cnt
|
|
55
|
+
FROM system.tables
|
|
56
|
+
WHERE database = currentDatabase()
|
|
57
|
+
AND name = '${this.tableName}'
|
|
58
|
+
`,
|
|
59
|
+
format: 'JSONEachRow',
|
|
60
|
+
});
|
|
61
|
+
const rows = yield result.json();
|
|
62
|
+
return ((_a = rows[0]) === null || _a === void 0 ? void 0 : _a.cnt) > 0;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
insertMany(data) {
|
|
66
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
67
|
+
if (!data.length)
|
|
68
|
+
return true;
|
|
69
|
+
try {
|
|
70
|
+
yield this.client.insert({
|
|
71
|
+
table: this.tableName,
|
|
72
|
+
values: data,
|
|
73
|
+
format: 'JSONEachRow',
|
|
74
|
+
});
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
this.handleError('insertMany', error, data);
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
findByTimeRange(columns_1, where_1, from_1, to_1) {
|
|
84
|
+
return __awaiter(this, arguments, void 0, function* (columns, where, from, to, timeColumn = 'ts') {
|
|
85
|
+
try {
|
|
86
|
+
const query = `
|
|
87
|
+
SELECT ${columns}
|
|
88
|
+
FROM ${this.tableName}
|
|
89
|
+
WHERE ${this.applySoftDelete(where)}
|
|
90
|
+
AND ${timeColumn} BETWEEN toDateTime('${from}')
|
|
91
|
+
AND toDateTime('${to}')
|
|
92
|
+
ORDER BY ${timeColumn}
|
|
93
|
+
`;
|
|
94
|
+
const result = yield this.client.query({
|
|
95
|
+
query, format: 'JSONEachRow'
|
|
96
|
+
});
|
|
97
|
+
return yield result.json();
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
this.handleError('findByTimeRange', error, where, from, to);
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
softDelete(where) {
|
|
106
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
107
|
+
if (!this.hasSoftDelete) {
|
|
108
|
+
throw new Error(`Soft delete not enabled for table ${this.tableName}`);
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
yield this.client.exec({
|
|
112
|
+
query: `
|
|
113
|
+
ALTER TABLE ${this.tableName}
|
|
114
|
+
UPDATE is_deleted = 1
|
|
115
|
+
WHERE ${where}
|
|
116
|
+
`,
|
|
117
|
+
});
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
this.handleError('softDelete', error, where);
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
applySoftDelete(where) {
|
|
127
|
+
return this.hasSoftDelete
|
|
128
|
+
? `(${where}) AND is_deleted = 0`
|
|
129
|
+
: where;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
exports.ClickHouseBaseModel = ClickHouseBaseModel;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Model, Document, AnyBulkWriteOperation, IndexDefinition } from 'mongoose';
|
|
2
|
+
export declare abstract class MongoBaseModel<T extends Document> {
|
|
3
|
+
protected model: Model<T>;
|
|
4
|
+
protected modelName: string;
|
|
5
|
+
constructor(model: Model<T>, modelName: string);
|
|
6
|
+
protected handleError(method: string, error: Error, ...args: any[]): void;
|
|
7
|
+
insertOne(data: Partial<T>): Promise<T | false>;
|
|
8
|
+
insertMany(data: Partial<T>[]): Promise<any[]>;
|
|
9
|
+
find(query: object): Promise<T[]>;
|
|
10
|
+
findLean(query: object): Promise<any[]>;
|
|
11
|
+
findOne(query: object): Promise<T | null>;
|
|
12
|
+
findOneLean(query: object): Promise<any | null>;
|
|
13
|
+
findOneAndUpdate(query: object, data: object): Promise<T | null>;
|
|
14
|
+
updateOne(query: object, data: object): Promise<any>;
|
|
15
|
+
updateMany(query: object, data: object): Promise<any>;
|
|
16
|
+
deleteOne(query: object): Promise<any>;
|
|
17
|
+
deleteMany(query: object): Promise<any>;
|
|
18
|
+
count(query: object): Promise<number>;
|
|
19
|
+
bulkWrite(operations: AnyBulkWriteOperation<any>[]): Promise<any>;
|
|
20
|
+
createIndex(name: string, index: IndexDefinition): Promise<boolean>;
|
|
21
|
+
getIndexes(): Promise<any>;
|
|
22
|
+
dropIndex(name: string): Promise<any>;
|
|
23
|
+
dropIndexes(): Promise<boolean>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.MongoBaseModel = void 0;
|
|
13
|
+
class MongoBaseModel {
|
|
14
|
+
constructor(model, modelName) {
|
|
15
|
+
this.model = model;
|
|
16
|
+
this.modelName = modelName;
|
|
17
|
+
}
|
|
18
|
+
handleError(method, error, ...args) {
|
|
19
|
+
console.error(`${this.modelName} :: ${method} :: Error :: ${error.message}`, ...args);
|
|
20
|
+
}
|
|
21
|
+
insertOne(data) {
|
|
22
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
23
|
+
try {
|
|
24
|
+
return yield this.model.create(data);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
this.handleError('insertOne', error, data);
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
insertMany(data) {
|
|
33
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
try {
|
|
35
|
+
return yield this.model.insertMany(data);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
this.handleError('insertMany', error, data);
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
find(query) {
|
|
44
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
+
try {
|
|
46
|
+
return yield this.model.find(query);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
this.handleError('find', error, query);
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
findLean(query) {
|
|
55
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
try {
|
|
57
|
+
return yield this.model.find(query).lean().exec();
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
this.handleError('findLean', error, query);
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
findOne(query) {
|
|
66
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
67
|
+
try {
|
|
68
|
+
return yield this.model.findOne(query);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
this.handleError('findOne', error, query);
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
findOneLean(query) {
|
|
77
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
78
|
+
try {
|
|
79
|
+
return yield this.model.findOne(query).lean().exec();
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
this.handleError('findOneLean', error, query);
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
findOneAndUpdate(query, data) {
|
|
88
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
89
|
+
try {
|
|
90
|
+
return yield this.model.findOneAndUpdate(query, data, { new: true });
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
this.handleError('findOneAndUpdate', error, query, data);
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
updateOne(query, data) {
|
|
99
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
100
|
+
try {
|
|
101
|
+
return yield this.model.updateOne(query, data);
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
this.handleError('updateOne', error, query, data);
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
updateMany(query, data) {
|
|
110
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
111
|
+
try {
|
|
112
|
+
return yield this.model.updateMany(query, data);
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
this.handleError('updateMany', error, query, data);
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
deleteOne(query) {
|
|
121
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
122
|
+
try {
|
|
123
|
+
return yield this.model.deleteOne(query);
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
this.handleError('deleteOne', error, query);
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
deleteMany(query) {
|
|
132
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
133
|
+
try {
|
|
134
|
+
return yield this.model.deleteMany(query);
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
this.handleError('deleteMany', error, query);
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
count(query) {
|
|
143
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
144
|
+
try {
|
|
145
|
+
return yield this.model.countDocuments(query);
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
this.handleError('count', error, query);
|
|
149
|
+
return 0;
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
bulkWrite(operations) {
|
|
154
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
155
|
+
try {
|
|
156
|
+
return yield this.model.bulkWrite(operations);
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
this.handleError('bulkWrite', error, operations);
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
createIndex(name, index) {
|
|
165
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
166
|
+
try {
|
|
167
|
+
this.model.schema.index(index, { name });
|
|
168
|
+
yield this.model.createIndexes();
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
this.handleError('createIndex', error, index);
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
getIndexes() {
|
|
178
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
179
|
+
try {
|
|
180
|
+
return this.model.collection.getIndexes();
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
this.handleError('getIndexes', error);
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
dropIndex(name) {
|
|
189
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
190
|
+
try {
|
|
191
|
+
return yield this.model.collection.dropIndex(name);
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
this.handleError('dropIndex', error, name);
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
dropIndexes() {
|
|
200
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
201
|
+
try {
|
|
202
|
+
yield this.model.collection.dropIndexes();
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
this.handleError('dropIndexes', error);
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
exports.MongoBaseModel = MongoBaseModel;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { QueryResult, QueryResultRow } from 'pg';
|
|
2
|
+
export declare abstract class PostgresSQLBaseModel<T extends object> {
|
|
3
|
+
protected tableName: string;
|
|
4
|
+
constructor(tableName: string);
|
|
5
|
+
protected query<R extends QueryResultRow = any>(sql: string, params?: any[]): Promise<QueryResult<R>>;
|
|
6
|
+
sendQuery<R extends QueryResultRow = any>(sql: string, params?: any[]): Promise<R[]>;
|
|
7
|
+
insertOne(data: Partial<T>, projection?: string): Promise<T | null>;
|
|
8
|
+
insertMany(data: Partial<T>[], projection?: string): Promise<T[]>;
|
|
9
|
+
find(query?: Partial<T>, columns?: string): Promise<T[]>;
|
|
10
|
+
count(query?: Partial<T>): Promise<number>;
|
|
11
|
+
update(query: Partial<T>, data: Partial<T>, projection?: string): Promise<T[]>;
|
|
12
|
+
delete(query: Partial<T>): Promise<number>;
|
|
13
|
+
deleteByQuery(query: string): Promise<number>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.PostgresSQLBaseModel = void 0;
|
|
13
|
+
const postgres_service_1 = require("../common/postgres.service");
|
|
14
|
+
class PostgresSQLBaseModel {
|
|
15
|
+
constructor(tableName) {
|
|
16
|
+
this.tableName = tableName;
|
|
17
|
+
}
|
|
18
|
+
query(sql_1) {
|
|
19
|
+
return __awaiter(this, arguments, void 0, function* (sql, params = []) {
|
|
20
|
+
const pool = (0, postgres_service_1.getPool)();
|
|
21
|
+
const client = yield pool.connect();
|
|
22
|
+
try {
|
|
23
|
+
return yield client.query(sql, params);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
console.error(`${this.tableName} :: Query Failed ::`, error.message, sql, params);
|
|
27
|
+
return { rows: [], rowCount: 0, command: 'ERROR',
|
|
28
|
+
oid: 0, fields: [] };
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
client.release();
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
sendQuery(sql_1) {
|
|
36
|
+
return __awaiter(this, arguments, void 0, function* (sql, params = []) {
|
|
37
|
+
const result = yield this.query(sql, params);
|
|
38
|
+
return result.rows;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
insertOne(data_1) {
|
|
42
|
+
return __awaiter(this, arguments, void 0, function* (data, projection = '*') {
|
|
43
|
+
const keys = [];
|
|
44
|
+
const values = [];
|
|
45
|
+
for (const [key, value] of Object.entries(data)) {
|
|
46
|
+
keys.push(key);
|
|
47
|
+
values.push(value);
|
|
48
|
+
}
|
|
49
|
+
const placeholders = keys.map((_, i) => `$${i + 1}`).join(', ');
|
|
50
|
+
const sql = `INSERT INTO ${this.tableName} (${keys.join(', ')})
|
|
51
|
+
VALUES (${placeholders}) RETURNING ${projection}`;
|
|
52
|
+
const result = yield this.query(sql, values);
|
|
53
|
+
return result.rows[0] || null;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
insertMany(data_1) {
|
|
57
|
+
return __awaiter(this, arguments, void 0, function* (data, projection = '*') {
|
|
58
|
+
if (!data.length)
|
|
59
|
+
return [];
|
|
60
|
+
const keys = Object.keys(data[0]);
|
|
61
|
+
const len = data.length;
|
|
62
|
+
const keyLen = keys.length;
|
|
63
|
+
const values = new Array(len * keyLen);
|
|
64
|
+
const columns = keys.map(k => `"${k}"`).join(', ');
|
|
65
|
+
const placeholderParts = new Array(len);
|
|
66
|
+
let paramIndex = 1;
|
|
67
|
+
let valueIndex = 0;
|
|
68
|
+
for (let i = 0; i < len; i++) {
|
|
69
|
+
const row = data[i];
|
|
70
|
+
const rowParts = new Array(keyLen);
|
|
71
|
+
for (let j = 0; j < keyLen; j++) {
|
|
72
|
+
const val = row[keys[j]];
|
|
73
|
+
values[valueIndex++] = val;
|
|
74
|
+
rowParts[j] = `$${paramIndex++}`;
|
|
75
|
+
}
|
|
76
|
+
placeholderParts[i] = `(${rowParts.join(',')})`;
|
|
77
|
+
}
|
|
78
|
+
const sql = `INSERT INTO ${this.tableName} (${columns}) VALUES ${placeholderParts.join(', ')} RETURNING ${projection};`;
|
|
79
|
+
const res = yield this.query(sql, values);
|
|
80
|
+
return res.rows;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
find() {
|
|
84
|
+
return __awaiter(this, arguments, void 0, function* (query = {}, columns = '*') {
|
|
85
|
+
const values = [];
|
|
86
|
+
const whereParts = [];
|
|
87
|
+
const entries = Object.entries(query);
|
|
88
|
+
for (let i = 0; i < entries.length; i++) {
|
|
89
|
+
const [key, val] = entries[i];
|
|
90
|
+
whereParts.push(`"${key}" = $${i + 1}`);
|
|
91
|
+
values.push(val);
|
|
92
|
+
}
|
|
93
|
+
const sql = `SELECT ${columns} FROM ${this.tableName}` +
|
|
94
|
+
(whereParts.length ? ' WHERE ' + whereParts.join(' AND ') : '');
|
|
95
|
+
const result = yield this.query(sql, values);
|
|
96
|
+
return result.rows;
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
count() {
|
|
100
|
+
return __awaiter(this, arguments, void 0, function* (query = {}) {
|
|
101
|
+
var _a;
|
|
102
|
+
const values = [];
|
|
103
|
+
const whereParts = [];
|
|
104
|
+
const entries = Object.entries(query);
|
|
105
|
+
for (let i = 0; i < entries.length; i++) {
|
|
106
|
+
const [key, val] = entries[i];
|
|
107
|
+
whereParts.push(`"${key}" = $${i + 1}`);
|
|
108
|
+
values.push(val);
|
|
109
|
+
}
|
|
110
|
+
const sql = `SELECT COUNT(*) AS count FROM ${this.tableName}` +
|
|
111
|
+
(whereParts.length ? ' WHERE ' + whereParts.join(' AND ') : '');
|
|
112
|
+
const result = yield this.query(sql, values);
|
|
113
|
+
return parseInt(((_a = result.rows[0]) === null || _a === void 0 ? void 0 : _a.count) || '0', 10);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
update(query_1, data_1) {
|
|
117
|
+
return __awaiter(this, arguments, void 0, function* (query, data, projection = '*') {
|
|
118
|
+
const dataKeys = Object.keys(data);
|
|
119
|
+
const queryKeys = Object.keys(query);
|
|
120
|
+
const setLen = dataKeys.length;
|
|
121
|
+
const whereLen = queryKeys.length;
|
|
122
|
+
if (setLen === 0)
|
|
123
|
+
return [];
|
|
124
|
+
const values = new Array(setLen + whereLen);
|
|
125
|
+
const setParts = new Array(setLen);
|
|
126
|
+
const whereParts = whereLen > 0 ? new Array(whereLen) : [];
|
|
127
|
+
for (let i = 0; i < setLen; i++) {
|
|
128
|
+
const key = dataKeys[i];
|
|
129
|
+
setParts[i] = `"${key}" = $${i + 1}`;
|
|
130
|
+
values[i] = data[key];
|
|
131
|
+
}
|
|
132
|
+
const setClause = setParts.join(',');
|
|
133
|
+
if (whereLen > 0) {
|
|
134
|
+
for (let i = 0; i < whereLen; i++) {
|
|
135
|
+
const key = queryKeys[i];
|
|
136
|
+
whereParts[i] = `"${key}" = $${setLen + i + 1}`;
|
|
137
|
+
values[setLen + i] = query[key];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const whereClause = whereLen > 0 ? ' WHERE ' + whereParts.join(' AND ') : '';
|
|
141
|
+
const sql = `UPDATE ${this.tableName} SET ${setClause}${whereClause} RETURNING ${projection};`;
|
|
142
|
+
const result = yield this.query(sql, values);
|
|
143
|
+
return result.rows;
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
delete(query) {
|
|
147
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
148
|
+
const values = [];
|
|
149
|
+
const whereParts = [];
|
|
150
|
+
const entries = Object.entries(query);
|
|
151
|
+
for (let i = 0; i < entries.length; i++) {
|
|
152
|
+
const [key, val] = entries[i];
|
|
153
|
+
whereParts.push(`"${key}" = $${i + 1}`);
|
|
154
|
+
values.push(val);
|
|
155
|
+
}
|
|
156
|
+
const sql = `DELETE FROM ${this.tableName}` +
|
|
157
|
+
(whereParts.length ? ' WHERE ' + whereParts.join(' AND ') : '');
|
|
158
|
+
const result = yield this.query(sql, values);
|
|
159
|
+
return result.rowCount || 0;
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
deleteByQuery(query) {
|
|
163
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
164
|
+
const values = [];
|
|
165
|
+
const sql = `DELETE FROM ${this.tableName} WHERE ${query}`;
|
|
166
|
+
const result = yield this.query(sql, values);
|
|
167
|
+
return result.rowCount || 0;
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
exports.PostgresSQLBaseModel = PostgresSQLBaseModel;
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sspart-be-lib",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "This is a backend library designed for sspart enterprises private limited.",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist",
|
|
8
|
+
"README.md"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc"
|
|
12
|
+
},
|
|
13
|
+
"main": "dist/index.js",
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@clickhouse/client": "^1.17.0",
|
|
16
|
+
"@types/pg": "^8.15.6",
|
|
17
|
+
"knex": "^3.1.0",
|
|
18
|
+
"mongoose": "^8.19.2",
|
|
19
|
+
"pg": "^8.16.3"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"typescript": "^5.7.2"
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://sspartorg@bitbucket.org/sspartorg/sspart-be-lib.git"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"Backend",
|
|
30
|
+
"library"
|
|
31
|
+
],
|
|
32
|
+
"author": "Ram",
|
|
33
|
+
"license": "ISC",
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://bitbucket.org/sspartorg/sspart-be-lib/issues"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://bitbucket.org/sspartorg/sspart-be-lib#readme"
|
|
38
|
+
}
|