ismx-nexo-node-app 0.3.27 → 0.3.28
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/dist/js/api/ServiceRestFormalTemplate.js +25 -7
- package/dist/js/index.js +5 -3
- package/dist/js/repository/RepositoryDatabase.js +31 -0
- package/dist/js/repository/{RepositoryPostgres.js → RepositoryDatabasePostgres.js} +21 -30
- package/dist/types/api/ServiceRestFormalTemplate.d.ts +10 -6
- package/dist/types/index.d.ts +4 -2
- package/dist/types/repository/RepositoryDatabase.d.ts +61 -0
- package/dist/types/repository/{RepositoryPostgres.d.ts → RepositoryDatabasePostgres.d.ts} +11 -36
- package/dist/types/repository/utils/PostgresUtils.d.ts +2 -1
- package/package.json +1 -1
- package/src/main/node/api/ServiceRestFormalTemplate.ts +27 -16
- package/src/main/node/index.ts +5 -2
- package/src/main/node/repository/RepositoryDatabase.ts +81 -0
- package/src/main/node/repository/{RepositoryPostgres.ts → RepositoryDatabasePostgres.ts} +16 -57
- package/src/main/node/repository/utils/PostgresUtils.ts +2 -1
|
@@ -15,11 +15,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
const Service_1 = require("./Service");
|
|
16
16
|
const ServiceRestFormal_1 = __importDefault(require("./ServiceRestFormal"));
|
|
17
17
|
class ServiceRestFormalTemplate {
|
|
18
|
-
constructor(resource, tableName) {
|
|
18
|
+
constructor(resource, database, tableName) {
|
|
19
19
|
this.indexer = "id";
|
|
20
20
|
this.unwrap = ServiceRestFormal_1.default.unwrap;
|
|
21
21
|
this.fullSelect = ServiceRestFormal_1.default.fullSelect;
|
|
22
22
|
this.resource = resource;
|
|
23
|
+
this.database = database;
|
|
23
24
|
this.tableName = tableName;
|
|
24
25
|
this.get = new ServiceRestFormal_1.default("GET", `${resource}`);
|
|
25
26
|
this.get.serveRestFormal = this.serveGet.bind(this);
|
|
@@ -44,9 +45,29 @@ class ServiceRestFormalTemplate {
|
|
|
44
45
|
this.del = new ServiceRestFormal_1.default("DELETE", `${resource}`);
|
|
45
46
|
this.del.serveRestFormal = this.serveDel.bind(this);
|
|
46
47
|
}
|
|
48
|
+
getFormalId(request) {
|
|
49
|
+
var _a;
|
|
50
|
+
let id = (_a = request.query) === null || _a === void 0 ? void 0 : _a[this.indexer];
|
|
51
|
+
if (id === undefined)
|
|
52
|
+
throw new Error();
|
|
53
|
+
else
|
|
54
|
+
return id;
|
|
55
|
+
}
|
|
56
|
+
getFormalPage(request) {
|
|
57
|
+
var _a, _b;
|
|
58
|
+
let maxResultsStr = (_a = request.query) === null || _a === void 0 ? void 0 : _a["maxResults"];
|
|
59
|
+
if (!maxResultsStr)
|
|
60
|
+
throw new Error();
|
|
61
|
+
let maxResults = Number.parseInt(maxResultsStr);
|
|
62
|
+
let pageNumberStr = (_b = request.query) === null || _b === void 0 ? void 0 : _b["pageNumber"];
|
|
63
|
+
if (!pageNumberStr)
|
|
64
|
+
throw new Error();
|
|
65
|
+
let pageNumber = Number.parseInt(pageNumberStr);
|
|
66
|
+
return { maxResults, pageNumber };
|
|
67
|
+
}
|
|
47
68
|
serveGet(request) {
|
|
48
69
|
return __awaiter(this, void 0, void 0, function* () {
|
|
49
|
-
let id = this.
|
|
70
|
+
let id = this.getFormalId(request);
|
|
50
71
|
let result = yield this.database.one(this.tableName, id);
|
|
51
72
|
return Service_1.HttpResponse.ok(result);
|
|
52
73
|
});
|
|
@@ -66,11 +87,8 @@ class ServiceRestFormalTemplate {
|
|
|
66
87
|
}
|
|
67
88
|
servePage(request) {
|
|
68
89
|
return __awaiter(this, void 0, void 0, function* () {
|
|
69
|
-
let maxResults = this.
|
|
70
|
-
let
|
|
71
|
-
let pageNumber = this.errors.getQuery("pageNumber", request.query);
|
|
72
|
-
let pageNumberNum = this.errors.isType("pageNumber", pageNumber, "number", Number.parseInt);
|
|
73
|
-
let results = yield this.database.page(this.tableName, "timestamp", maxResultsNum, pageNumberNum);
|
|
90
|
+
let { maxResults, pageNumber } = this.getFormalPage(request);
|
|
91
|
+
let results = yield this.database.page(this.tableName, "timestamp", maxResults, pageNumber);
|
|
74
92
|
return Service_1.HttpResponse.ok(results);
|
|
75
93
|
});
|
|
76
94
|
}
|
package/dist/js/index.js
CHANGED
|
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.QueryUtils = exports.RepositoryPostgres = exports.Repository = exports.StringUtils = exports.NumberUtils = exports.CryptoUtils = exports.BusinessLogger = exports.BusinessErrors = exports.BusinessThread = exports.BusinessServer = exports.BusinessProxy = exports.BusinessState = exports.Business = exports.ServiceRestFormalTemplate = exports.ServiceRestFormal = exports.ServiceRest = exports.HttpResponse = exports.Service = void 0;
|
|
29
|
+
exports.QueryUtils = exports.RepositoryDatabasePostgres = exports.RepositoryPostgres = exports.Repository = exports.StringUtils = exports.NumberUtils = exports.CryptoUtils = exports.BusinessLogger = exports.BusinessErrors = exports.BusinessThread = exports.BusinessServer = exports.BusinessProxy = exports.BusinessState = exports.Business = exports.ServiceRestFormalTemplate = exports.ServiceRestFormal = exports.ServiceRest = exports.HttpResponse = exports.Service = void 0;
|
|
30
30
|
const Service_1 = __importStar(require("./api/Service"));
|
|
31
31
|
exports.Service = Service_1.default;
|
|
32
32
|
exports.HttpResponse = Service_1.HttpResponse;
|
|
@@ -60,7 +60,9 @@ exports.StringUtils = StringUtils_1.default;
|
|
|
60
60
|
/**************************************************************/
|
|
61
61
|
const Repository_1 = __importDefault(require("./repository/Repository"));
|
|
62
62
|
exports.Repository = Repository_1.default;
|
|
63
|
-
const
|
|
64
|
-
exports.RepositoryPostgres =
|
|
63
|
+
const RepositoryDatabase_1 = __importDefault(require("./repository/RepositoryDatabase"));
|
|
64
|
+
exports.RepositoryPostgres = RepositoryDatabase_1.default;
|
|
65
|
+
const RepositoryDatabasePostgres_1 = __importDefault(require("./repository/RepositoryDatabasePostgres"));
|
|
66
|
+
exports.RepositoryDatabasePostgres = RepositoryDatabasePostgres_1.default;
|
|
65
67
|
const QueryUtils_1 = __importDefault(require("./repository/utils/QueryUtils"));
|
|
66
68
|
exports.QueryUtils = QueryUtils_1.default;
|
|
@@ -0,0 +1,31 @@
|
|
|
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 Repository_1 = __importDefault(require("./Repository"));
|
|
7
|
+
class RepositoryDatabase extends Repository_1.default {
|
|
8
|
+
constructor() {
|
|
9
|
+
super(...arguments);
|
|
10
|
+
this.connected = false;
|
|
11
|
+
this.onConnectListeners = [];
|
|
12
|
+
this.onQueryWillExecuteListeners = [];
|
|
13
|
+
this.onQueryDidExecuteListeners = [];
|
|
14
|
+
}
|
|
15
|
+
init(chain) {
|
|
16
|
+
this.chain = chain;
|
|
17
|
+
}
|
|
18
|
+
isConnected() {
|
|
19
|
+
return this.connected;
|
|
20
|
+
}
|
|
21
|
+
addOnConnect(listener) {
|
|
22
|
+
this.onConnectListeners.push(listener);
|
|
23
|
+
}
|
|
24
|
+
addOnQueryWillExecuteListener(listener) {
|
|
25
|
+
this.onQueryWillExecuteListeners.push(listener);
|
|
26
|
+
}
|
|
27
|
+
addOnQueryDidExecuteListener(listener) {
|
|
28
|
+
this.onQueryDidExecuteListeners.push(listener);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.default = RepositoryDatabase;
|
|
@@ -14,43 +14,34 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
const pg_1 = __importDefault(require("pg"));
|
|
16
16
|
const PostgresUtils_1 = __importDefault(require("./utils/PostgresUtils"));
|
|
17
|
-
|
|
17
|
+
const RepositoryDatabase_1 = __importDefault(require("./RepositoryDatabase"));
|
|
18
|
+
class RepositoryDatabasePostgres extends RepositoryDatabase_1.default {
|
|
18
19
|
constructor() {
|
|
19
|
-
|
|
20
|
+
super();
|
|
21
|
+
this.introspectIntervalTime = 60 * 60 * 1000;
|
|
20
22
|
this.tables = {};
|
|
21
|
-
this.onConnectListeners = [];
|
|
22
|
-
this.onQueryWillExecuteListeners = [];
|
|
23
|
-
this.onQueryDidExecuteListeners = [];
|
|
24
|
-
this.onIntrospectedListener = [];
|
|
25
|
-
this.introspectIntervalTime = 5 * 60 * 1000;
|
|
26
23
|
this.schema = "public";
|
|
27
|
-
this.
|
|
28
|
-
this.
|
|
29
|
-
this.add = this.add.bind(this);
|
|
30
|
-
this.update = this.update.bind(this);
|
|
31
|
-
this.del = this.del.bind(this);
|
|
32
|
-
this.introspect = this.introspect.bind(this);
|
|
24
|
+
this.onIntrospectedListeners = [];
|
|
25
|
+
this.native = this.native.bind(this);
|
|
33
26
|
}
|
|
34
27
|
init(chain) {
|
|
35
|
-
|
|
28
|
+
super.init(chain);
|
|
36
29
|
this.schema = chain.schema || "public";
|
|
37
30
|
this.connect(chain);
|
|
38
31
|
}
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
addOnIntrospectedListener(listener) {
|
|
33
|
+
this.onIntrospectedListeners.push(listener);
|
|
41
34
|
}
|
|
42
|
-
addOnConnect(listener) { this.onConnectListeners.push(listener); }
|
|
43
|
-
addOnQueryWillExecuteListener(listener) { this.onQueryWillExecuteListeners.push(listener); }
|
|
44
|
-
setIntrospectInterval(time) { this.introspectIntervalTime = time; }
|
|
45
|
-
addOnIntrospected(listener) { this.onIntrospectedListener.push(listener); }
|
|
46
35
|
connect(connection) {
|
|
47
|
-
this
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
36
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
+
this.client = new pg_1.default.Client(connection);
|
|
38
|
+
return this.client.connect().then(() => __awaiter(this, void 0, void 0, function* () {
|
|
39
|
+
yield this.introspect();
|
|
40
|
+
setInterval(this.introspect, this.introspectIntervalTime);
|
|
41
|
+
this.connected = true;
|
|
42
|
+
this.onConnectListeners.map(l => l());
|
|
43
|
+
}));
|
|
44
|
+
});
|
|
54
45
|
}
|
|
55
46
|
native(query_1) {
|
|
56
47
|
return __awaiter(this, arguments, void 0, function* (query, values = [], options = {}) {
|
|
@@ -136,7 +127,7 @@ class RepositoryPostgres {
|
|
|
136
127
|
let values = [id, ...columns.map((column) => object[PostgresUtils_1.default.stringToCamel(column)])];
|
|
137
128
|
let query = `UPDATE ${this.schema}.${tableName} SET (${columns.join(",")}) = (${params}) WHERE id = $1 `;
|
|
138
129
|
query += `RETURNING *`;
|
|
139
|
-
return this.query(query, values);
|
|
130
|
+
return this.query(query, values).then((result) => result[0]);
|
|
140
131
|
});
|
|
141
132
|
}
|
|
142
133
|
page(tableName_1, sortKey_1) {
|
|
@@ -208,8 +199,8 @@ class RepositoryPostgres {
|
|
|
208
199
|
`, [this.schema]);
|
|
209
200
|
for (let table of result.rows)
|
|
210
201
|
this.tables[table["name"]] = table["columns"];
|
|
211
|
-
this.
|
|
202
|
+
this.onIntrospectedListeners.forEach((l) => l(this.tables));
|
|
212
203
|
});
|
|
213
204
|
}
|
|
214
205
|
}
|
|
215
|
-
exports.default =
|
|
206
|
+
exports.default = RepositoryDatabasePostgres;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { HttpRequest, HttpResponse } from "./Service";
|
|
2
2
|
import ServiceRestFormal from "./ServiceRestFormal";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import { Pagination } from "../repository/RepositoryDatabase";
|
|
4
|
+
import RepositoryDatabase from "../repository/RepositoryDatabase";
|
|
5
5
|
export default class ServiceRestFormalTemplate<Req = any, Res = any> {
|
|
6
6
|
readonly resource: string;
|
|
7
7
|
readonly tableName: string;
|
|
8
|
-
readonly database:
|
|
9
|
-
readonly errors: BusinessErrors;
|
|
8
|
+
readonly database: RepositoryDatabase;
|
|
10
9
|
readonly get: ServiceRestFormal<Req, Res>;
|
|
11
10
|
readonly post: ServiceRestFormal<Req, Res>;
|
|
12
11
|
readonly put: ServiceRestFormal<Req, Res>;
|
|
@@ -20,7 +19,13 @@ export default class ServiceRestFormalTemplate<Req = any, Res = any> {
|
|
|
20
19
|
readonly map: ServiceRestFormal<Req, {
|
|
21
20
|
[key: string]: Res;
|
|
22
21
|
}>;
|
|
23
|
-
constructor(resource: string, tableName: string);
|
|
22
|
+
constructor(resource: string, database: RepositoryDatabase, tableName: string);
|
|
23
|
+
protected indexer: string;
|
|
24
|
+
getFormalId(request: HttpRequest): string;
|
|
25
|
+
getFormalPage(request: HttpRequest): {
|
|
26
|
+
maxResults: number;
|
|
27
|
+
pageNumber: number;
|
|
28
|
+
};
|
|
24
29
|
protected serveGet(request: HttpRequest<Req>): Promise<HttpResponse<Res>>;
|
|
25
30
|
protected serveGetList(request: HttpRequest<Req>): Promise<HttpResponse<Res[]>>;
|
|
26
31
|
protected servePostList(request: HttpRequest<Req>): Promise<HttpResponse<Res[]>>;
|
|
@@ -28,7 +33,6 @@ export default class ServiceRestFormalTemplate<Req = any, Res = any> {
|
|
|
28
33
|
protected serveMap(request: HttpRequest<Req>): Promise<HttpResponse<{
|
|
29
34
|
[key: string]: Res;
|
|
30
35
|
}>>;
|
|
31
|
-
protected indexer: string;
|
|
32
36
|
protected serveSelect(request: HttpRequest<Req>): Promise<HttpResponse<string[]>>;
|
|
33
37
|
protected serveExist(request: HttpRequest<Req>): Promise<HttpResponse<Boolean>>;
|
|
34
38
|
protected serveCount(request: HttpRequest<Req>): Promise<HttpResponse<Number>>;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -39,7 +39,9 @@ export declare const StringUtils: typeof _StringUtils;
|
|
|
39
39
|
/**************************************************************/
|
|
40
40
|
import BaseRepository from "./repository/Repository";
|
|
41
41
|
export declare const Repository: typeof BaseRepository;
|
|
42
|
-
import
|
|
43
|
-
export declare const RepositoryPostgres: typeof
|
|
42
|
+
import _RepositoryDatabase from "./repository/RepositoryDatabase";
|
|
43
|
+
export declare const RepositoryPostgres: typeof _RepositoryDatabase;
|
|
44
|
+
import _RepositoryDatabasePostgres from "./repository/RepositoryDatabasePostgres";
|
|
45
|
+
export declare const RepositoryDatabasePostgres: typeof _RepositoryDatabasePostgres;
|
|
44
46
|
import _QueryUtils from "./repository/utils/QueryUtils";
|
|
45
47
|
export declare const QueryUtils: typeof _QueryUtils;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import Repository from "./Repository";
|
|
2
|
+
import { QueryResult } from "pg";
|
|
3
|
+
export interface QueryOptions {
|
|
4
|
+
schema?: string;
|
|
5
|
+
filters?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface Chain {
|
|
8
|
+
host: string;
|
|
9
|
+
port: number;
|
|
10
|
+
user: string;
|
|
11
|
+
password: string;
|
|
12
|
+
database: string;
|
|
13
|
+
schema: string;
|
|
14
|
+
}
|
|
15
|
+
export interface Pagination<T> {
|
|
16
|
+
total: number;
|
|
17
|
+
elements: T[];
|
|
18
|
+
}
|
|
19
|
+
export type Primitive = string | number | Date | null | undefined;
|
|
20
|
+
export default abstract class RepositoryDatabase extends Repository {
|
|
21
|
+
protected connected: boolean;
|
|
22
|
+
protected chain: Chain;
|
|
23
|
+
init(chain: Chain): void;
|
|
24
|
+
isConnected(): boolean;
|
|
25
|
+
protected readonly onConnectListeners: (() => void)[];
|
|
26
|
+
addOnConnect(listener: () => void): void;
|
|
27
|
+
protected readonly onQueryWillExecuteListeners: ((key: string) => void)[];
|
|
28
|
+
addOnQueryWillExecuteListener(listener: (query: string) => void): void;
|
|
29
|
+
protected readonly onQueryDidExecuteListeners: ((query: string) => void)[];
|
|
30
|
+
addOnQueryDidExecuteListener(listener: (query: string) => void): void;
|
|
31
|
+
abstract connect(connection: Chain): Promise<void>;
|
|
32
|
+
abstract native(query: string, values: any[], options: QueryOptions): Promise<QueryResult>;
|
|
33
|
+
abstract query<E>(query: string, values: any[], options: QueryOptions): Promise<E[]>;
|
|
34
|
+
abstract one<E>(tableName: string, id: string): Promise<E>;
|
|
35
|
+
abstract any<E>(tableName: string, filters: {
|
|
36
|
+
[key: string]: Primitive | Array<any>;
|
|
37
|
+
}): Promise<E>;
|
|
38
|
+
abstract find<E>(tableName: string, filters: {
|
|
39
|
+
[key: string]: Primitive | Array<any>;
|
|
40
|
+
}): Promise<E[]>;
|
|
41
|
+
abstract all_depr<E>(tableName: string, options: QueryOptions): Promise<E[]>;
|
|
42
|
+
abstract add<E>(tableName: string, object: {
|
|
43
|
+
[key: string]: Primitive;
|
|
44
|
+
} | any, id?: string): Promise<E>;
|
|
45
|
+
abstract addAll<T>(tableName: string, objects: {
|
|
46
|
+
[key: string]: Primitive;
|
|
47
|
+
}[]): Promise<T[]>;
|
|
48
|
+
abstract update<T>(tableName: string, id: string, object: {
|
|
49
|
+
[key: string]: Primitive;
|
|
50
|
+
}): Promise<T>;
|
|
51
|
+
abstract page<T>(tableName: string, sortKey: string, maxResults: number, pageNumber: number, filters?: {
|
|
52
|
+
[key: string]: Primitive | Array<Primitive>;
|
|
53
|
+
}): Promise<Pagination<T>>;
|
|
54
|
+
abstract count(tableName: string, filters?: {
|
|
55
|
+
[key: string]: Primitive | Array<Primitive>;
|
|
56
|
+
}): Promise<number>;
|
|
57
|
+
abstract select(tableName: string, select: string, filters?: {
|
|
58
|
+
[key: string]: Primitive | Array<Primitive>;
|
|
59
|
+
}): Promise<string[]>;
|
|
60
|
+
abstract del<T>(tableName: string, id: string): Promise<T>;
|
|
61
|
+
}
|
|
@@ -1,46 +1,21 @@
|
|
|
1
|
-
import pg, {
|
|
2
|
-
|
|
3
|
-
schema?: string;
|
|
4
|
-
filters?: string;
|
|
5
|
-
}
|
|
6
|
-
export interface Chain extends ClientConfig {
|
|
7
|
-
host: string;
|
|
8
|
-
port: number;
|
|
9
|
-
user: string;
|
|
10
|
-
password: string;
|
|
11
|
-
database: string;
|
|
12
|
-
schema: string;
|
|
13
|
-
}
|
|
1
|
+
import pg, { QueryResult } from "pg";
|
|
2
|
+
import RepositoryDatabase, { Chain, Pagination, Primitive, QueryOptions } from "./RepositoryDatabase";
|
|
14
3
|
export interface Column {
|
|
15
4
|
name: string;
|
|
16
5
|
default?: string;
|
|
17
6
|
}
|
|
18
|
-
export
|
|
19
|
-
|
|
20
|
-
elements: T[];
|
|
21
|
-
}
|
|
22
|
-
export type Primitive = string | number | Date | null | undefined;
|
|
23
|
-
export default abstract class RepositoryPostgres {
|
|
24
|
-
protected chain: Chain;
|
|
7
|
+
export default class RepositoryDatabasePostgres extends RepositoryDatabase {
|
|
8
|
+
private readonly introspectIntervalTime;
|
|
25
9
|
protected client: pg.Client;
|
|
26
|
-
private connected;
|
|
27
10
|
private tables;
|
|
28
|
-
private onConnectListeners;
|
|
29
|
-
private onQueryWillExecuteListeners;
|
|
30
|
-
private onQueryDidExecuteListeners;
|
|
31
|
-
private onIntrospectedListener;
|
|
32
|
-
private introspectIntervalTime;
|
|
33
11
|
private schema;
|
|
34
12
|
constructor();
|
|
35
13
|
init(chain: Chain): void;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
setIntrospectInterval(time: number): void;
|
|
40
|
-
addOnIntrospected(listener: (tables: {
|
|
41
|
-
[p: string]: Column[];
|
|
14
|
+
private onIntrospectedListeners;
|
|
15
|
+
addOnIntrospectedListener(listener: (tables: {
|
|
16
|
+
[key: string]: Column[];
|
|
42
17
|
}) => void): void;
|
|
43
|
-
connect(connection: Chain): void
|
|
18
|
+
connect(connection: Chain): Promise<void>;
|
|
44
19
|
native(query: string, values?: any[], options?: QueryOptions): Promise<QueryResult>;
|
|
45
20
|
query<E>(query: string, values?: any[], options?: QueryOptions): Promise<E[]>;
|
|
46
21
|
one<E>(tableName: string, id: string): Promise<E>;
|
|
@@ -57,9 +32,9 @@ export default abstract class RepositoryPostgres {
|
|
|
57
32
|
addAll<T>(tableName: string, objects: {
|
|
58
33
|
[key: string]: Primitive;
|
|
59
34
|
}[]): Promise<T[]>;
|
|
60
|
-
update(tableName: string, id: string, object: {
|
|
35
|
+
update<T>(tableName: string, id: string, object: {
|
|
61
36
|
[key: string]: Primitive;
|
|
62
|
-
}): Promise<
|
|
37
|
+
}): Promise<T>;
|
|
63
38
|
page<T>(tableName: string, sortKey: string, maxResults?: number, pageNumber?: number, filters?: {
|
|
64
39
|
[key: string]: Primitive | Array<Primitive>;
|
|
65
40
|
}): Promise<Pagination<T>>;
|
|
@@ -69,7 +44,7 @@ export default abstract class RepositoryPostgres {
|
|
|
69
44
|
select(tableName: string, select: string, filters?: {
|
|
70
45
|
[key: string]: Primitive | Array<Primitive>;
|
|
71
46
|
}): Promise<string[]>;
|
|
72
|
-
del(tableName: string, id: string): Promise<
|
|
47
|
+
del<T>(tableName: string, id: string): Promise<T>;
|
|
73
48
|
private toQuery;
|
|
74
49
|
private introspect;
|
|
75
50
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Column
|
|
1
|
+
import { Column } from "../RepositoryDatabasePostgres";
|
|
2
|
+
import { Primitive } from "../RepositoryDatabase";
|
|
2
3
|
export default abstract class PostgresUtils {
|
|
3
4
|
static stringToCamel(column: string): string;
|
|
4
5
|
static camelToSnake(column: string): string;
|
package/package.json
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import ServiceRestFormal
|
|
3
|
-
import
|
|
4
|
-
import
|
|
1
|
+
import {HttpRequest, HttpResponse} from "./Service";
|
|
2
|
+
import ServiceRestFormal from "./ServiceRestFormal";
|
|
3
|
+
import {Pagination} from "../repository/RepositoryDatabase";
|
|
4
|
+
import RepositoryDatabase from "../repository/RepositoryDatabase";
|
|
5
5
|
|
|
6
6
|
export default class ServiceRestFormalTemplate<Req=any, Res=any>
|
|
7
7
|
{
|
|
8
8
|
readonly resource: string;
|
|
9
9
|
readonly tableName: string;
|
|
10
|
-
readonly database!:
|
|
11
|
-
readonly errors!: BusinessErrors;
|
|
10
|
+
readonly database!: RepositoryDatabase;
|
|
12
11
|
|
|
13
12
|
readonly get!: ServiceRestFormal<Req, Res>;
|
|
14
13
|
readonly post!: ServiceRestFormal<Req, Res>;
|
|
@@ -24,8 +23,9 @@ export default class ServiceRestFormalTemplate<Req=any, Res=any>
|
|
|
24
23
|
readonly page!: ServiceRestFormal<Req, Pagination<Res>>;
|
|
25
24
|
readonly map!: ServiceRestFormal<Req, { [key:string]: Res }>;
|
|
26
25
|
|
|
27
|
-
constructor(resource: string, tableName: string) {
|
|
26
|
+
constructor(resource: string, database: RepositoryDatabase, tableName: string) {
|
|
28
27
|
this.resource = resource;
|
|
28
|
+
this.database = database;
|
|
29
29
|
this.tableName = tableName;
|
|
30
30
|
|
|
31
31
|
this.get = new ServiceRestFormal("GET", `${resource}`);
|
|
@@ -62,8 +62,25 @@ export default class ServiceRestFormalTemplate<Req=any, Res=any>
|
|
|
62
62
|
this.del.serveRestFormal = this.serveDel.bind(this);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
protected indexer = "id"
|
|
66
|
+
getFormalId(request: HttpRequest): string {
|
|
67
|
+
let id = request.query?.[this.indexer];
|
|
68
|
+
if (id === undefined) throw new Error();
|
|
69
|
+
else return id;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
getFormalPage(request: HttpRequest): { maxResults: number, pageNumber: number } {
|
|
73
|
+
let maxResultsStr = request.query?.["maxResults"];
|
|
74
|
+
if (!maxResultsStr) throw new Error();
|
|
75
|
+
let maxResults = Number.parseInt(maxResultsStr);
|
|
76
|
+
let pageNumberStr = request.query?.["pageNumber"];
|
|
77
|
+
if (!pageNumberStr) throw new Error();
|
|
78
|
+
let pageNumber = Number.parseInt(pageNumberStr);
|
|
79
|
+
return { maxResults, pageNumber }
|
|
80
|
+
}
|
|
81
|
+
|
|
65
82
|
protected async serveGet(request: HttpRequest<Req>): Promise<HttpResponse<Res>> {
|
|
66
|
-
let id = this.
|
|
83
|
+
let id = this.getFormalId(request);
|
|
67
84
|
let result = await this.database.one<Res>(this.tableName, id);
|
|
68
85
|
return HttpResponse.ok(result);
|
|
69
86
|
}
|
|
@@ -79,13 +96,8 @@ export default class ServiceRestFormalTemplate<Req=any, Res=any>
|
|
|
79
96
|
}
|
|
80
97
|
|
|
81
98
|
protected async servePage(request: HttpRequest<Req>): Promise<HttpResponse<Pagination<Res>>> {
|
|
82
|
-
let maxResults = this.
|
|
83
|
-
let
|
|
84
|
-
|
|
85
|
-
let pageNumber = this.errors.getQuery("pageNumber", request.query)
|
|
86
|
-
let pageNumberNum = this.errors.isType("pageNumber", pageNumber, "number", Number.parseInt)
|
|
87
|
-
|
|
88
|
-
let results = await this.database.page(this.tableName, "timestamp", maxResultsNum, pageNumberNum);
|
|
99
|
+
let { maxResults, pageNumber } = this.getFormalPage(request);
|
|
100
|
+
let results = await this.database.page(this.tableName, "timestamp", maxResults, pageNumber);
|
|
89
101
|
return HttpResponse.ok(results);
|
|
90
102
|
}
|
|
91
103
|
|
|
@@ -99,7 +111,6 @@ export default class ServiceRestFormalTemplate<Req=any, Res=any>
|
|
|
99
111
|
return HttpResponse.ok(response);
|
|
100
112
|
}
|
|
101
113
|
|
|
102
|
-
protected indexer = "id"
|
|
103
114
|
protected async serveSelect(request: HttpRequest<Req>): Promise<HttpResponse<string[]>> {
|
|
104
115
|
let selection = request.query?.["selection"] ?? this.indexer;
|
|
105
116
|
delete request.query?.["selection"];
|
package/src/main/node/index.ts
CHANGED
|
@@ -52,8 +52,11 @@ export const StringUtils = _StringUtils;
|
|
|
52
52
|
import BaseRepository from "./repository/Repository";
|
|
53
53
|
export const Repository = BaseRepository
|
|
54
54
|
|
|
55
|
-
import
|
|
56
|
-
export const RepositoryPostgres =
|
|
55
|
+
import _RepositoryDatabase from "./repository/RepositoryDatabase";
|
|
56
|
+
export const RepositoryPostgres = _RepositoryDatabase
|
|
57
|
+
|
|
58
|
+
import _RepositoryDatabasePostgres from "./repository/RepositoryDatabasePostgres";
|
|
59
|
+
export const RepositoryDatabasePostgres = _RepositoryDatabasePostgres
|
|
57
60
|
|
|
58
61
|
import _QueryUtils from "./repository/utils/QueryUtils";
|
|
59
62
|
export const QueryUtils = _QueryUtils;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import Repository from "./Repository";
|
|
2
|
+
import {QueryResult} from "pg";
|
|
3
|
+
|
|
4
|
+
export interface QueryOptions {
|
|
5
|
+
schema?: string;
|
|
6
|
+
filters?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface Chain {
|
|
10
|
+
host: string;
|
|
11
|
+
port: number;
|
|
12
|
+
user: string;
|
|
13
|
+
password: string;
|
|
14
|
+
database: string;
|
|
15
|
+
schema: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface Pagination<T> {
|
|
19
|
+
total: number;
|
|
20
|
+
elements: T[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type Primitive = string | number | Date | null | undefined;
|
|
24
|
+
|
|
25
|
+
export default abstract class RepositoryDatabase extends Repository
|
|
26
|
+
{
|
|
27
|
+
protected connected: boolean = false;
|
|
28
|
+
|
|
29
|
+
protected chain!: Chain;
|
|
30
|
+
|
|
31
|
+
init(chain: Chain) {
|
|
32
|
+
this.chain = chain;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
isConnected() {
|
|
36
|
+
return this.connected;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
protected readonly onConnectListeners: (()=>void)[] = [];
|
|
40
|
+
addOnConnect(listener: () => void) {
|
|
41
|
+
this.onConnectListeners.push(listener);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
protected readonly onQueryWillExecuteListeners: ((key:string)=>void)[] = [];
|
|
45
|
+
addOnQueryWillExecuteListener(listener: (query: string) => void) {
|
|
46
|
+
this.onQueryWillExecuteListeners.push(listener);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
protected readonly onQueryDidExecuteListeners: ((query:string)=>void)[] = [];
|
|
50
|
+
addOnQueryDidExecuteListener(listener: (query:string)=>void) {
|
|
51
|
+
this.onQueryDidExecuteListeners.push(listener);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
abstract connect(connection: Chain): Promise<void>;
|
|
55
|
+
|
|
56
|
+
abstract native(query: string, values: any[], options: QueryOptions): Promise<QueryResult>;
|
|
57
|
+
|
|
58
|
+
abstract query<E>(query: string, values: any[], options: QueryOptions): Promise<E[]>;
|
|
59
|
+
|
|
60
|
+
abstract one<E>(tableName: string, id: string): Promise<E>;
|
|
61
|
+
|
|
62
|
+
abstract any<E>(tableName: string, filters: { [key: string]: Primitive | Array<any> }): Promise<E>;
|
|
63
|
+
|
|
64
|
+
abstract find<E>(tableName: string, filters: { [key: string]: Primitive | Array<any> }): Promise<E[]>;
|
|
65
|
+
|
|
66
|
+
abstract all_depr<E>(tableName: string, options: QueryOptions): Promise<E[]>;
|
|
67
|
+
|
|
68
|
+
abstract add<E>(tableName: string, object: {[key:string]:Primitive} | any, id?: string): Promise<E>;
|
|
69
|
+
|
|
70
|
+
abstract addAll<T>(tableName: string, objects: {[key:string]:Primitive }[]): Promise<T[]>;
|
|
71
|
+
|
|
72
|
+
abstract update<T>(tableName: string, id: string, object: {[key:string]:Primitive}): Promise<T>;
|
|
73
|
+
|
|
74
|
+
abstract page<T>(tableName: string, sortKey: string, maxResults: number, pageNumber: number, filters?: {[key:string]:Primitive|Array<Primitive>}): Promise<Pagination<T>>;
|
|
75
|
+
|
|
76
|
+
abstract count(tableName: string, filters?: { [key: string]: Primitive | Array<Primitive> }): Promise<number>;
|
|
77
|
+
|
|
78
|
+
abstract select(tableName: string, select: string, filters?: { [key: string]: Primitive | Array<Primitive> }): Promise<string[]>;
|
|
79
|
+
|
|
80
|
+
abstract del<T>(tableName: string, id: string): Promise<T>;
|
|
81
|
+
}
|
|
@@ -1,83 +1,42 @@
|
|
|
1
1
|
import pg, {ClientConfig, QueryResult, QueryResultRow} from "pg";
|
|
2
2
|
import PostgresUtils from "./utils/PostgresUtils";
|
|
3
|
-
|
|
4
|
-
export interface QueryOptions {
|
|
5
|
-
schema?: string;
|
|
6
|
-
filters?: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export interface Chain extends ClientConfig {
|
|
10
|
-
host: string;
|
|
11
|
-
port: number;
|
|
12
|
-
user: string;
|
|
13
|
-
password: string;
|
|
14
|
-
database: string;
|
|
15
|
-
schema: string;
|
|
16
|
-
}
|
|
3
|
+
import RepositoryDatabase, {Chain, Pagination, Primitive, QueryOptions} from "./RepositoryDatabase";
|
|
17
4
|
|
|
18
5
|
export interface Column {
|
|
19
6
|
name: string
|
|
20
7
|
default?: string
|
|
21
8
|
}
|
|
22
9
|
|
|
23
|
-
export
|
|
24
|
-
total: number;
|
|
25
|
-
elements: T[];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export type Primitive = string | number | Date | null | undefined;
|
|
29
|
-
|
|
30
|
-
export default abstract class RepositoryPostgres
|
|
10
|
+
export default class RepositoryDatabasePostgres extends RepositoryDatabase
|
|
31
11
|
{
|
|
32
|
-
|
|
12
|
+
private readonly introspectIntervalTime: number = 60 * 60 * 1000;
|
|
33
13
|
|
|
34
14
|
protected client!: pg.Client;
|
|
35
15
|
|
|
36
|
-
private connected: boolean = false;
|
|
37
|
-
|
|
38
16
|
private tables: { [key: string]: Column[] } = {};
|
|
39
17
|
|
|
40
|
-
private onConnectListeners: (()=>void)[] = [];
|
|
41
|
-
|
|
42
|
-
private onQueryWillExecuteListeners: ((key:string)=>void)[] = [];
|
|
43
|
-
|
|
44
|
-
private onQueryDidExecuteListeners: ((key:string)=>void)[] = [];
|
|
45
|
-
|
|
46
|
-
private onIntrospectedListener: ((tables: { [p: string]: Column[] })=>void)[] = [];
|
|
47
|
-
|
|
48
|
-
private introspectIntervalTime = 5 * 60 * 1000
|
|
49
|
-
|
|
50
18
|
private schema: string = "public";
|
|
51
19
|
|
|
52
|
-
constructor()
|
|
53
|
-
|
|
54
|
-
this.
|
|
55
|
-
this.one = this.one.bind(this)
|
|
56
|
-
this.add = this.add.bind(this)
|
|
57
|
-
this.update = this.update.bind(this)
|
|
58
|
-
this.del = this.del.bind(this)
|
|
59
|
-
this.introspect = this.introspect.bind(this)
|
|
20
|
+
constructor() {
|
|
21
|
+
super();
|
|
22
|
+
this.native = this.native.bind(this);
|
|
60
23
|
}
|
|
61
24
|
|
|
62
25
|
init(chain: Chain)
|
|
63
26
|
{
|
|
64
|
-
|
|
27
|
+
super.init(chain);
|
|
65
28
|
this.schema = chain.schema || "public";
|
|
66
29
|
this.connect(chain);
|
|
67
30
|
}
|
|
68
31
|
|
|
69
|
-
|
|
70
|
-
|
|
32
|
+
private onIntrospectedListeners: ((tables: {[key: string]:Column[]})=>void)[] = [];
|
|
33
|
+
addOnIntrospectedListener(listener: (tables: {[key: string]:Column[]})=>void): void {
|
|
34
|
+
this.onIntrospectedListeners.push(listener);
|
|
71
35
|
}
|
|
72
36
|
|
|
73
|
-
|
|
74
|
-
addOnQueryWillExecuteListener(listener: (query: string) => void) { this.onQueryWillExecuteListeners.push(listener); }
|
|
75
|
-
setIntrospectInterval(time: number) { this.introspectIntervalTime = time; }
|
|
76
|
-
addOnIntrospected(listener: (tables: { [p: string]: Column[] })=>void) { this.onIntrospectedListener.push(listener); }
|
|
77
|
-
|
|
78
|
-
connect(connection: Chain) {
|
|
37
|
+
async connect(connection: Chain): Promise<void> {
|
|
79
38
|
this.client = new pg.Client(connection);
|
|
80
|
-
this.client.connect().then(async () => {
|
|
39
|
+
return this.client.connect().then(async () => {
|
|
81
40
|
await this.introspect();
|
|
82
41
|
setInterval(this.introspect, this.introspectIntervalTime);
|
|
83
42
|
this.connected = true;
|
|
@@ -155,7 +114,7 @@ export default abstract class RepositoryPostgres
|
|
|
155
114
|
return this.query(query, values);
|
|
156
115
|
}
|
|
157
116
|
|
|
158
|
-
async update(tableName: string, id: string, object: {[key:string]:Primitive})
|
|
117
|
+
async update<T>(tableName: string, id: string, object: {[key:string]:Primitive}): Promise<T>
|
|
159
118
|
{
|
|
160
119
|
if (!id) throw new Error(`field 'id' is mandatory when updating ${tableName}`);
|
|
161
120
|
if (!this.tables[tableName]) throw new Error(`table ${tableName} does not exist`);
|
|
@@ -167,7 +126,7 @@ export default abstract class RepositoryPostgres
|
|
|
167
126
|
let query = `UPDATE ${this.schema}.${tableName} SET (${columns.join(",")}) = (${params}) WHERE id = $1 `
|
|
168
127
|
query += `RETURNING *`;
|
|
169
128
|
|
|
170
|
-
return this.query(query, values);
|
|
129
|
+
return this.query<T>(query, values).then((result) => result[0]);
|
|
171
130
|
}
|
|
172
131
|
|
|
173
132
|
async page<T>(tableName: string, sortKey: string, maxResults: number = 50, pageNumber: number = 0, filters?: {[key:string]:Primitive|Array<Primitive>}): Promise<Pagination<T>>
|
|
@@ -203,7 +162,7 @@ export default abstract class RepositoryPostgres
|
|
|
203
162
|
return this.query<{list:string[]}>(query, values).then((result) => result[0].list);
|
|
204
163
|
}
|
|
205
164
|
|
|
206
|
-
async del(tableName: string, id: string)
|
|
165
|
+
async del<T>(tableName: string, id: string): Promise<T>
|
|
207
166
|
{
|
|
208
167
|
throw new Error(`not implemented yet`);
|
|
209
168
|
}
|
|
@@ -239,7 +198,7 @@ export default abstract class RepositoryPostgres
|
|
|
239
198
|
for (let table of result.rows)
|
|
240
199
|
this.tables[table["name"]] = table["columns"];
|
|
241
200
|
|
|
242
|
-
this.
|
|
201
|
+
this.onIntrospectedListeners.forEach((l) => l(this.tables));
|
|
243
202
|
|
|
244
203
|
}
|
|
245
204
|
|