ismx-nexo-node-app 0.3.27 → 0.3.29

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.
@@ -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.errors.getQuery("id", request.query);
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.errors.getQuery("maxResults", request.query);
70
- let maxResultsNum = this.errors.isType("maxResults", maxResults, "number", Number.parseInt);
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 RepositoryPostgres_1 = __importDefault(require("./repository/RepositoryPostgres"));
64
- exports.RepositoryPostgres = RepositoryPostgres_1.default;
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
- class RepositoryPostgres {
17
+ const RepositoryDatabase_1 = __importDefault(require("./RepositoryDatabase"));
18
+ class RepositoryDatabasePostgres extends RepositoryDatabase_1.default {
18
19
  constructor() {
19
- this.connected = false;
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.query = this.query.bind(this);
28
- this.one = this.one.bind(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
- this.chain = chain;
28
+ super.init(chain);
36
29
  this.schema = chain.schema || "public";
37
30
  this.connect(chain);
38
31
  }
39
- isConnected() {
40
- return this.connected;
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.client = new pg_1.default.Client(connection);
48
- this.client.connect().then(() => __awaiter(this, void 0, void 0, function* () {
49
- yield this.introspect();
50
- setInterval(this.introspect, this.introspectIntervalTime);
51
- this.connected = true;
52
- this.onConnectListeners.map(l => l());
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.onIntrospectedListener.forEach((l) => l(this.tables));
202
+ this.onIntrospectedListeners.forEach((l) => l(this.tables));
212
203
  });
213
204
  }
214
205
  }
215
- exports.default = RepositoryPostgres;
206
+ exports.default = RepositoryDatabasePostgres;
@@ -1,40 +1,44 @@
1
1
  import { HttpRequest, HttpResponse } from "./Service";
2
2
  import ServiceRestFormal from "./ServiceRestFormal";
3
- import RepositoryPostgres, { Pagination } from "../repository/RepositoryPostgres";
4
- import BusinessErrors from "../business/BusinessErrors";
5
- export default class ServiceRestFormalTemplate<Req = any, Res = any> {
3
+ import { Pagination } from "../repository/RepositoryDatabase";
4
+ import RepositoryDatabase from "../repository/RepositoryDatabase";
5
+ export default class ServiceRestFormalTemplate<Model = any> {
6
6
  readonly resource: string;
7
7
  readonly tableName: string;
8
- readonly database: RepositoryPostgres;
9
- readonly errors: BusinessErrors;
10
- readonly get: ServiceRestFormal<Req, Res>;
11
- readonly post: ServiceRestFormal<Req, Res>;
12
- readonly put: ServiceRestFormal<Req, Res>;
13
- readonly del: ServiceRestFormal<Req, Res>;
14
- readonly select: ServiceRestFormal<Req, string[]>;
15
- readonly exist: ServiceRestFormal<Req, Boolean>;
16
- readonly count: ServiceRestFormal<Req, Number>;
17
- readonly getList: ServiceRestFormal<Req, Res[]>;
18
- readonly postList: ServiceRestFormal<Req, Res[]>;
19
- readonly page: ServiceRestFormal<Req, Pagination<Res>>;
20
- readonly map: ServiceRestFormal<Req, {
21
- [key: string]: Res;
8
+ readonly database: RepositoryDatabase;
9
+ readonly get: ServiceRestFormal<any, Model>;
10
+ readonly getList: ServiceRestFormal<any, Model[]>;
11
+ readonly post: ServiceRestFormal<Model, Model>;
12
+ readonly postList: ServiceRestFormal<Model[], Model[]>;
13
+ readonly put: ServiceRestFormal<Model, Model>;
14
+ readonly del: ServiceRestFormal<any, Model>;
15
+ readonly select: ServiceRestFormal<any, string[]>;
16
+ readonly exist: ServiceRestFormal<any, Boolean>;
17
+ readonly count: ServiceRestFormal<any, Number>;
18
+ readonly page: ServiceRestFormal<any, Pagination<Model>>;
19
+ readonly map: ServiceRestFormal<any, {
20
+ [key: string]: Model;
22
21
  }>;
23
- constructor(resource: string, tableName: string);
24
- protected serveGet(request: HttpRequest<Req>): Promise<HttpResponse<Res>>;
25
- protected serveGetList(request: HttpRequest<Req>): Promise<HttpResponse<Res[]>>;
26
- protected servePostList(request: HttpRequest<Req>): Promise<HttpResponse<Res[]>>;
27
- protected servePage(request: HttpRequest<Req>): Promise<HttpResponse<Pagination<Res>>>;
28
- protected serveMap(request: HttpRequest<Req>): Promise<HttpResponse<{
29
- [key: string]: Res;
30
- }>>;
22
+ constructor(resource: string, database: RepositoryDatabase, tableName: string);
31
23
  protected indexer: string;
32
- protected serveSelect(request: HttpRequest<Req>): Promise<HttpResponse<string[]>>;
33
- protected serveExist(request: HttpRequest<Req>): Promise<HttpResponse<Boolean>>;
34
- protected serveCount(request: HttpRequest<Req>): Promise<HttpResponse<Number>>;
35
- protected servePost(request: HttpRequest<Req>): Promise<HttpResponse<Res>>;
36
- protected servePut(request: HttpRequest<Req>): Promise<HttpResponse<Res>>;
37
- protected serveDel(request: HttpRequest<Req>): Promise<HttpResponse<Res>>;
24
+ getFormalId(request: HttpRequest): string;
25
+ getFormalPage(request: HttpRequest): {
26
+ maxResults: number;
27
+ pageNumber: number;
28
+ };
29
+ protected serveGet(request: HttpRequest): Promise<HttpResponse<Model>>;
30
+ protected serveGetList(request: HttpRequest): Promise<HttpResponse<Model[]>>;
31
+ protected servePostList(request: HttpRequest<Model[]>): Promise<HttpResponse<Model[]>>;
32
+ protected servePage(request: HttpRequest): Promise<HttpResponse<Pagination<Model>>>;
33
+ protected serveMap(request: HttpRequest): Promise<HttpResponse<{
34
+ [key: string]: Model;
35
+ }>>;
36
+ protected serveSelect(request: HttpRequest): Promise<HttpResponse<string[]>>;
37
+ protected serveExist(request: HttpRequest): Promise<HttpResponse<Boolean>>;
38
+ protected serveCount(request: HttpRequest): Promise<HttpResponse<Number>>;
39
+ protected servePost(request: HttpRequest<Model>): Promise<HttpResponse<Model>>;
40
+ protected servePut(request: HttpRequest<Model>): Promise<HttpResponse<Model>>;
41
+ protected serveDel(request: HttpRequest): Promise<HttpResponse<Model>>;
38
42
  protected readonly unwrap: typeof ServiceRestFormal.unwrap;
39
43
  protected readonly fullSelect: typeof ServiceRestFormal.fullSelect;
40
44
  }
@@ -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 BaseRepositoryPostgres from "./repository/RepositoryPostgres";
43
- export declare const RepositoryPostgres: typeof BaseRepositoryPostgres;
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, { ClientConfig, QueryResult } from "pg";
2
- export interface QueryOptions {
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 interface Pagination<T> {
19
- total: number;
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
- isConnected(): boolean;
37
- addOnConnect(listener: () => void): void;
38
- addOnQueryWillExecuteListener(listener: (query: string) => void): void;
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<unknown[]>;
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<void>;
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, Primitive } from "../RepositoryPostgres";
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,6 +1,6 @@
1
1
  {
2
2
  "name": "ismx-nexo-node-app",
3
- "version": "0.3.27",
3
+ "version": "0.3.29",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "build": "rm -rf ./dist && npx tsc",
@@ -1,31 +1,30 @@
1
- import Service, {HttpRequest, HttpResponse} from "./Service";
2
- import ServiceRestFormal, {Wrapper} from "./ServiceRestFormal";
3
- import RepositoryPostgres, {Pagination} from "../repository/RepositoryPostgres";
4
- import BusinessErrors from "../business/BusinessErrors";
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
- export default class ServiceRestFormalTemplate<Req=any, Res=any>
6
+ export default class ServiceRestFormalTemplate<Model=any>
7
7
  {
8
8
  readonly resource: string;
9
9
  readonly tableName: string;
10
- readonly database!: RepositoryPostgres;
11
- readonly errors!: BusinessErrors;
12
-
13
- readonly get!: ServiceRestFormal<Req, Res>;
14
- readonly post!: ServiceRestFormal<Req, Res>;
15
- readonly put!: ServiceRestFormal<Req, Res>;
16
- readonly del!: ServiceRestFormal<Req, Res>;
17
- readonly select!: ServiceRestFormal<Req, string[]>;
18
- readonly exist!: ServiceRestFormal<Req, Boolean>;
19
-
20
- readonly count!: ServiceRestFormal<Req, Number>;
21
- readonly getList!: ServiceRestFormal<Req, Res[]>;
22
-
23
- readonly postList!: ServiceRestFormal<Req, Res[]>;
24
- readonly page!: ServiceRestFormal<Req, Pagination<Res>>;
25
- readonly map!: ServiceRestFormal<Req, { [key:string]: Res }>;
26
-
27
- constructor(resource: string, tableName: string) {
10
+ readonly database!: RepositoryDatabase;
11
+
12
+ readonly get!: ServiceRestFormal<any, Model>;
13
+ readonly getList!: ServiceRestFormal<any, Model[]>;
14
+ readonly post!: ServiceRestFormal<Model, Model>;
15
+ readonly postList!: ServiceRestFormal<Model[], Model[]>;
16
+ readonly put!: ServiceRestFormal<Model, Model>;
17
+ readonly del!: ServiceRestFormal<any, Model>;
18
+
19
+ readonly select!: ServiceRestFormal<any, string[]>;
20
+ readonly exist!: ServiceRestFormal<any, Boolean>;
21
+ readonly count!: ServiceRestFormal<any, Number>;
22
+ readonly page!: ServiceRestFormal<any, Pagination<Model>>;
23
+ readonly map!: ServiceRestFormal<any, { [key:string]: Model }>;
24
+
25
+ constructor(resource: string, database: RepositoryDatabase, tableName: string) {
28
26
  this.resource = resource;
27
+ this.database = database;
29
28
  this.tableName = tableName;
30
29
 
31
30
  this.get = new ServiceRestFormal("GET", `${resource}`);
@@ -62,36 +61,48 @@ export default class ServiceRestFormalTemplate<Req=any, Res=any>
62
61
  this.del.serveRestFormal = this.serveDel.bind(this);
63
62
  }
64
63
 
65
- protected async serveGet(request: HttpRequest<Req>): Promise<HttpResponse<Res>> {
66
- let id = this.errors.getQuery("id", request.query)
67
- let result = await this.database.one<Res>(this.tableName, id);
64
+ protected indexer = "id"
65
+ getFormalId(request: HttpRequest): string {
66
+ let id = request.query?.[this.indexer];
67
+ if (id === undefined) throw new Error();
68
+ else return id;
69
+ }
70
+
71
+ getFormalPage(request: HttpRequest): { maxResults: number, pageNumber: number } {
72
+ let maxResultsStr = request.query?.["maxResults"];
73
+ if (!maxResultsStr) throw new Error();
74
+ let maxResults = Number.parseInt(maxResultsStr);
75
+ let pageNumberStr = request.query?.["pageNumber"];
76
+ if (!pageNumberStr) throw new Error();
77
+ let pageNumber = Number.parseInt(pageNumberStr);
78
+ return { maxResults, pageNumber }
79
+ }
80
+
81
+ protected async serveGet(request: HttpRequest): Promise<HttpResponse<Model>> {
82
+ let id = this.getFormalId(request);
83
+ let result = await this.database.one<Model>(this.tableName, id);
68
84
  return HttpResponse.ok(result);
69
85
  }
70
86
 
71
- protected async serveGetList(request: HttpRequest<Req>): Promise<HttpResponse<Res[]>> {
72
- return HttpResponse.ok(await this.database.find<Res>(this.tableName, { ...request.query }));
87
+ protected async serveGetList(request: HttpRequest): Promise<HttpResponse<Model[]>> {
88
+ return HttpResponse.ok(await this.database.find<Model>(this.tableName, { ...request.query }));
73
89
  }
74
90
 
75
- protected async servePostList(request: HttpRequest<Req>): Promise<HttpResponse<Res[]>> {
91
+ protected async servePostList(request: HttpRequest<Model[]>): Promise<HttpResponse<Model[]>> {
76
92
  let list = request.body
77
93
  if (!(list instanceof Array)) throw new Error("body must be a list");
78
- return HttpResponse.ok(this.database.addAll(this.tableName, list));
94
+ return HttpResponse.ok(this.database.addAll<Model>(this.tableName, list as any));
79
95
  }
80
96
 
81
- protected async servePage(request: HttpRequest<Req>): Promise<HttpResponse<Pagination<Res>>> {
82
- let maxResults = this.errors.getQuery("maxResults", request.query);
83
- let maxResultsNum = this.errors.isType("maxResults", maxResults, "number", Number.parseInt);
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);
97
+ protected async servePage(request: HttpRequest): Promise<HttpResponse<Pagination<Model>>> {
98
+ let { maxResults, pageNumber } = this.getFormalPage(request);
99
+ let results = await this.database.page<Model>(this.tableName, "timestamp", maxResults, pageNumber);
89
100
  return HttpResponse.ok(results);
90
101
  }
91
102
 
92
- protected async serveMap(request: HttpRequest<Req>): Promise<HttpResponse<{[key: string]: Res}>> {
93
- let results = await this.database.find<Res>(this.tableName, { ...request.query });
94
- let response: {[key: string]: Res} = {}; for (let result of results) {
103
+ protected async serveMap(request: HttpRequest): Promise<HttpResponse<{[key: string]: Model}>> {
104
+ let results = await this.database.find<Model>(this.tableName, { ...request.query });
105
+ let response: {[key: string]: Model} = {}; for (let result of results) {
95
106
  let key = (result as any)[this.indexer];
96
107
  if (!key) return HttpResponse.ok({});
97
108
  else response[key] = result;
@@ -99,32 +110,31 @@ export default class ServiceRestFormalTemplate<Req=any, Res=any>
99
110
  return HttpResponse.ok(response);
100
111
  }
101
112
 
102
- protected indexer = "id"
103
- protected async serveSelect(request: HttpRequest<Req>): Promise<HttpResponse<string[]>> {
113
+ protected async serveSelect(request: HttpRequest): Promise<HttpResponse<string[]>> {
104
114
  let selection = request.query?.["selection"] ?? this.indexer;
105
115
  delete request.query?.["selection"];
106
116
  let select = await this.database.select(this.tableName, selection, { ...request.query });
107
117
  return HttpResponse.ok(select);
108
118
  }
109
119
 
110
- protected async serveExist(request: HttpRequest<Req>): Promise<HttpResponse<Boolean>> {
120
+ protected async serveExist(request: HttpRequest): Promise<HttpResponse<Boolean>> {
111
121
  return HttpResponse.ok((await this.database.count(this.tableName, { ...request.query })) > 0);
112
122
  }
113
123
 
114
- protected async serveCount(request: HttpRequest<Req>): Promise<HttpResponse<Number>> {
124
+ protected async serveCount(request: HttpRequest): Promise<HttpResponse<Number>> {
115
125
  return HttpResponse.ok((await this.database.count(this.tableName, { ...request.query })));
116
126
  }
117
127
 
118
- protected async servePost(request: HttpRequest<Req>): Promise<HttpResponse<Res>> {
119
- let entity = this.database.add(this.tableName, request.body);
128
+ protected async servePost(request: HttpRequest<Model>): Promise<HttpResponse<Model>> {
129
+ let entity = this.database.add<Model>(this.tableName, request.body);
120
130
  return HttpResponse.ok(entity);
121
131
  }
122
132
 
123
- protected async servePut(request: HttpRequest<Req>): Promise<HttpResponse<Res>> {
133
+ protected async servePut(request: HttpRequest<Model>): Promise<HttpResponse<Model>> {
124
134
  return HttpResponse.ok("not implemented yet");
125
135
  }
126
136
 
127
- protected async serveDel(request: HttpRequest<Req>): Promise<HttpResponse<Res>> {
137
+ protected async serveDel(request: HttpRequest): Promise<HttpResponse<Model>> {
128
138
  return HttpResponse.ok("not implemented yet");
129
139
  }
130
140
 
@@ -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 BaseRepositoryPostgres from "./repository/RepositoryPostgres";
56
- export const RepositoryPostgres = BaseRepositoryPostgres
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 interface Pagination<T> {
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
- protected chain!: Chain;
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.query = this.query.bind(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
- this.chain = chain;
27
+ super.init(chain);
65
28
  this.schema = chain.schema || "public";
66
29
  this.connect(chain);
67
30
  }
68
31
 
69
- isConnected() {
70
- return this.connected;
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
- addOnConnect(listener: () => void) { this.onConnectListeners.push(listener); }
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.onIntrospectedListener.forEach((l) => l(this.tables));
201
+ this.onIntrospectedListeners.forEach((l) => l(this.tables));
243
202
 
244
203
  }
245
204
 
@@ -1,4 +1,5 @@
1
- import {Column, Primitive} from "../RepositoryPostgres";
1
+ import {Column} from "../RepositoryDatabasePostgres";
2
+ import {Primitive} from "../RepositoryDatabase";
2
3
 
3
4
  export default abstract class PostgresUtils
4
5
  {