@xitkov/core 2.4.9
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 +256 -0
- package/lib/app.d.ts +75 -0
- package/lib/app.js +143 -0
- package/lib/app.js.map +1 -0
- package/lib/errors/index.d.ts +25 -0
- package/lib/errors/index.js +41 -0
- package/lib/errors/index.js.map +1 -0
- package/lib/hooks/business.d.ts +1 -0
- package/lib/hooks/business.js +26 -0
- package/lib/hooks/business.js.map +1 -0
- package/lib/hooks/hooks.d.ts +4 -0
- package/lib/hooks/hooks.js +66 -0
- package/lib/hooks/hooks.js.map +1 -0
- package/lib/hooks/index.d.ts +3 -0
- package/lib/hooks/index.js +20 -0
- package/lib/hooks/index.js.map +1 -0
- package/lib/hooks/types.d.ts +9 -0
- package/lib/hooks/types.js +3 -0
- package/lib/hooks/types.js.map +1 -0
- package/lib/index.d.ts +17 -0
- package/lib/index.js +23 -0
- package/lib/index.js.map +1 -0
- package/lib/libs/cache.d.ts +7 -0
- package/lib/libs/cache.js +22 -0
- package/lib/libs/cache.js.map +1 -0
- package/lib/libs/index.d.ts +5 -0
- package/lib/libs/index.js +22 -0
- package/lib/libs/index.js.map +1 -0
- package/lib/libs/logs.d.ts +5 -0
- package/lib/libs/logs.js +26 -0
- package/lib/libs/logs.js.map +1 -0
- package/lib/libs/queue.d.ts +21 -0
- package/lib/libs/queue.js +49 -0
- package/lib/libs/queue.js.map +1 -0
- package/lib/libs/socket.d.ts +8 -0
- package/lib/libs/socket.js +26 -0
- package/lib/libs/socket.js.map +1 -0
- package/lib/libs/utils.d.ts +8 -0
- package/lib/libs/utils.js +28 -0
- package/lib/libs/utils.js.map +1 -0
- package/lib/logger/index.d.ts +11 -0
- package/lib/logger/index.js +50 -0
- package/lib/logger/index.js.map +1 -0
- package/lib/services/auth.d.ts +19 -0
- package/lib/services/auth.js +41 -0
- package/lib/services/auth.js.map +1 -0
- package/lib/services/databases/index.d.ts +3 -0
- package/lib/services/databases/index.js +20 -0
- package/lib/services/databases/index.js.map +1 -0
- package/lib/services/databases/mongo-service.d.ts +26 -0
- package/lib/services/databases/mongo-service.js +55 -0
- package/lib/services/databases/mongo-service.js.map +1 -0
- package/lib/services/databases/postgres-service.d.ts +28 -0
- package/lib/services/databases/postgres-service.js +126 -0
- package/lib/services/databases/postgres-service.js.map +1 -0
- package/lib/services/databases/types.d.ts +26 -0
- package/lib/services/databases/types.js +3 -0
- package/lib/services/databases/types.js.map +1 -0
- package/lib/services/index.d.ts +6 -0
- package/lib/services/index.js +23 -0
- package/lib/services/index.js.map +1 -0
- package/lib/services/micro-service.d.ts +60 -0
- package/lib/services/micro-service.js +146 -0
- package/lib/services/micro-service.js.map +1 -0
- package/lib/services/register-micro-services.d.ts +1 -0
- package/lib/services/register-micro-services.js +41 -0
- package/lib/services/register-micro-services.js.map +1 -0
- package/lib/services/register-services.d.ts +5 -0
- package/lib/services/register-services.js +272 -0
- package/lib/services/register-services.js.map +1 -0
- package/lib/services/service.d.ts +46 -0
- package/lib/services/service.js +63 -0
- package/lib/services/service.js.map +1 -0
- package/package.json +49 -0
- package/src/app.ts +182 -0
- package/src/errors/index.ts +37 -0
- package/src/hooks/business.ts +23 -0
- package/src/hooks/hooks.ts +60 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/types.ts +9 -0
- package/src/index.ts +18 -0
- package/src/libs/cache.ts +25 -0
- package/src/libs/index.ts +5 -0
- package/src/libs/logs.ts +21 -0
- package/src/libs/queue.ts +48 -0
- package/src/libs/socket.ts +28 -0
- package/src/libs/utils.ts +28 -0
- package/src/logger/index.ts +49 -0
- package/src/services/auth.ts +48 -0
- package/src/services/databases/index.ts +3 -0
- package/src/services/databases/mongo-service.ts +75 -0
- package/src/services/databases/postgres-service.ts +149 -0
- package/src/services/databases/types.ts +29 -0
- package/src/services/index.ts +6 -0
- package/src/services/micro-service.ts +188 -0
- package/src/services/register-micro-services.ts +37 -0
- package/src/services/register-services.ts +268 -0
- package/src/services/service.ts +118 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
interface IUser {
|
|
2
|
+
userBusinessId?: string;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function setBusinessId(...params: any[]) {
|
|
6
|
+
const req = params[params.length - 2];
|
|
7
|
+
const hookName = params[params.length - 1];
|
|
8
|
+
const user: IUser = req?.user;
|
|
9
|
+
const { userBusinessId: businessId } = user ?? {};
|
|
10
|
+
let idx = 0;
|
|
11
|
+
if (/^(patch|update|remove|get)$/i.test(hookName)) {
|
|
12
|
+
idx = 1;
|
|
13
|
+
}
|
|
14
|
+
const target = params[idx];
|
|
15
|
+
if (target == null) return;
|
|
16
|
+
if (Array.isArray(target)) {
|
|
17
|
+
target.forEach(item => { if (item && typeof item === 'object') item.businessId = businessId });
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (typeof target === 'object') {
|
|
21
|
+
target.businessId = businessId;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Op } from "sequelize";
|
|
2
|
+
import { NotFound, Unauthorized } from "../errors";
|
|
3
|
+
import { Logger } from "../logger";
|
|
4
|
+
|
|
5
|
+
export const disallow = () => {
|
|
6
|
+
throw new NotFound('Not Found')
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const externalDisallow = (...params: any[]) => {
|
|
10
|
+
const req = params[params.length - 2]
|
|
11
|
+
const internalToken = req.headers['internaltoken']
|
|
12
|
+
if (internalToken === (process.env.INTERNAL_TOKEN ?? 'internal_token')) {
|
|
13
|
+
Logger.info('externalDisallow', { internalToken })
|
|
14
|
+
return
|
|
15
|
+
}
|
|
16
|
+
throw new NotFound('Not Found')
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const loggedIn = (...params: any[]) => {
|
|
20
|
+
const req = params[params.length - 2]
|
|
21
|
+
const user = req?.user
|
|
22
|
+
if (!user) {
|
|
23
|
+
throw new Unauthorized("Logged in required")
|
|
24
|
+
}
|
|
25
|
+
return user;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const addQuerySupport = (...params: any[]) => {
|
|
29
|
+
const hookName = params[params.length - 1];
|
|
30
|
+
let queryIndex = 0;
|
|
31
|
+
|
|
32
|
+
if (/^(create|patch|update|remove|get)$/i.test(hookName)) {
|
|
33
|
+
queryIndex = 1;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const query = params[queryIndex] ?? {};
|
|
37
|
+
const queryObj: any = {};
|
|
38
|
+
Object.keys(query).forEach(key => {
|
|
39
|
+
const value = query[key];
|
|
40
|
+
if (typeof value === 'object') {
|
|
41
|
+
let [conditionValue] = Object.values(value);
|
|
42
|
+
const [condition] = Object.keys(value);
|
|
43
|
+
const sequelizeOp = (Op as any)[condition.replace('$', '')];
|
|
44
|
+
try {
|
|
45
|
+
conditionValue = JSON.parse(conditionValue as any);
|
|
46
|
+
} catch (err) {
|
|
47
|
+
//
|
|
48
|
+
}
|
|
49
|
+
if (sequelizeOp) {
|
|
50
|
+
queryObj[key] = {
|
|
51
|
+
[sequelizeOp]: conditionValue,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
queryObj[key] = value;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
params[queryIndex] = queryObj;
|
|
59
|
+
return queryObj;
|
|
60
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export * from './services';
|
|
2
|
+
export * from './errors';
|
|
3
|
+
export * from './hooks';
|
|
4
|
+
export * from './libs';
|
|
5
|
+
export * from './logger';
|
|
6
|
+
export * from './app';
|
|
7
|
+
|
|
8
|
+
export interface ServiceTypes {
|
|
9
|
+
[service: string]: any
|
|
10
|
+
}
|
|
11
|
+
export interface MicroServiceNames {
|
|
12
|
+
[microService: string]: {
|
|
13
|
+
[service: string]: any;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export interface SubMicroServiceNames {
|
|
17
|
+
[service: string]: any;
|
|
18
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {Redis} from 'ioredis';
|
|
2
|
+
|
|
3
|
+
export class Cache {
|
|
4
|
+
static client: Redis;
|
|
5
|
+
static async set(key: string, value: any, expirationInSeconds = 600) {
|
|
6
|
+
await Cache.client.set(key, JSON.stringify(value));
|
|
7
|
+
await Cache.client.expire(key, expirationInSeconds);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
static async get(key: string) {
|
|
11
|
+
const cacheData = await Cache.client.get(key);
|
|
12
|
+
if (!cacheData) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const data = JSON.parse(cacheData);
|
|
16
|
+
|
|
17
|
+
return data;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static async delete(key: string) {
|
|
21
|
+
await Cache.client.del(key);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
|
package/src/libs/logs.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import winston from 'winston';
|
|
2
|
+
import expressWinston from 'express-winston';
|
|
3
|
+
|
|
4
|
+
export class InternalLogs {
|
|
5
|
+
static middleware(options?: Partial<expressWinston.LoggerOptions>) {
|
|
6
|
+
return expressWinston.logger({
|
|
7
|
+
transports: [
|
|
8
|
+
new winston.transports.Console()
|
|
9
|
+
],
|
|
10
|
+
format: winston.format.combine(
|
|
11
|
+
winston.format.json(),
|
|
12
|
+
),
|
|
13
|
+
meta: true, // optional: control whether you want to log the meta data about the request (default to true)
|
|
14
|
+
msg: "HTTP {{req.method}} {{req.url}}", // optional: customize the default logging message. E.g. "{{res.statusCode}} {{req.method}} {{res.responseTime}}ms {{req.url}}"
|
|
15
|
+
expressFormat: true, // Use the default Express/morgan request formatting. Enabling this will override any msg if true. Will only output colors with colorize set to true
|
|
16
|
+
colorize: false, // Color the text and status code, using the Express/morgan color palette (text: gray, status: default green, 3XX cyan, 4XX yellow, 5XX red).
|
|
17
|
+
ignoreRoute: function (req, res) { return false; }, // optional: allows to skip some log messages based on request and/or response
|
|
18
|
+
...(options ?? {})
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import BullQueue from 'bull';
|
|
2
|
+
import { Logger } from '../logger';
|
|
3
|
+
|
|
4
|
+
export class Queue<T = any> {
|
|
5
|
+
readonly queue: BullQueue.Queue<T>;
|
|
6
|
+
private readonly queueName: string;
|
|
7
|
+
|
|
8
|
+
constructor(name: string, redisUrl: string, opts: BullQueue.QueueOptions = {}) {
|
|
9
|
+
const defaultOpts: BullQueue.QueueOptions = {
|
|
10
|
+
limiter: {
|
|
11
|
+
duration: 50000,
|
|
12
|
+
max: 30,
|
|
13
|
+
},
|
|
14
|
+
...opts
|
|
15
|
+
}
|
|
16
|
+
const env = process.env.ENVIRONMENT ?? 'dev';
|
|
17
|
+
let queueName = `${name}_${env}`
|
|
18
|
+
if (/prod/gi.test(env) && !/pre/gi.test(env)) {
|
|
19
|
+
queueName = name
|
|
20
|
+
}
|
|
21
|
+
this.queue = new BullQueue(queueName, redisUrl, defaultOpts);
|
|
22
|
+
this.queueName = queueName
|
|
23
|
+
|
|
24
|
+
this.queue.on('completed', function (job, result) {
|
|
25
|
+
const payload = { job, result }
|
|
26
|
+
Logger.info(`Completed ${queueName}: `, payload)
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
this.queue.on('failed', async function (job, error) {
|
|
30
|
+
const payload = { job, error }
|
|
31
|
+
Logger.info(`Failed ${queueName}: `, payload)
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async add(data: T, opts?: BullQueue.JobOptions) {
|
|
36
|
+
const options: BullQueue.JobOptions = {
|
|
37
|
+
removeOnComplete: true, // removes job from queue on success
|
|
38
|
+
removeOnFail: true, // removes job from queue on failure,
|
|
39
|
+
attempts: 1,
|
|
40
|
+
...(opts ?? {})
|
|
41
|
+
}
|
|
42
|
+
return this.queue.add(data, options);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get consume() {
|
|
46
|
+
return this.queue.process;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { DefaultEventsMap } from "socket.io/dist/typed-events";
|
|
2
|
+
import { Server, Socket as SocketIO } from "socket.io";
|
|
3
|
+
import { Logger } from "..";
|
|
4
|
+
|
|
5
|
+
export class Socket {
|
|
6
|
+
static io: Server<DefaultEventsMap, DefaultEventsMap, DefaultEventsMap, any>
|
|
7
|
+
|
|
8
|
+
static emit(eventName: string, data: any) {
|
|
9
|
+
return Socket.io.emit(eventName, data)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
static on(eventName: string, cb: (...args: any[]) => void) {
|
|
13
|
+
return Socket.io.on(eventName, cb)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static client(cb: (socket: SocketIO<DefaultEventsMap, DefaultEventsMap, DefaultEventsMap, any>) => void, debug = false) {
|
|
17
|
+
Socket.io.on('connection', function(socket) {
|
|
18
|
+
if (debug) {
|
|
19
|
+
Logger.debug('Client Connected', socket.id);
|
|
20
|
+
}
|
|
21
|
+
cb(socket);
|
|
22
|
+
// Whenever someone disconnects this piece of code executed
|
|
23
|
+
socket.on('disconnect', function () {
|
|
24
|
+
Logger.debug('Client Disconnected', socket.id);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Function to slice an array given a limit and offset
|
|
3
|
+
* @param array input array
|
|
4
|
+
* @param limit how many records to return
|
|
5
|
+
* @param offset offset to discard elements
|
|
6
|
+
* @returns sliced array or empty if input is null or has length = 0 or even if the params (limit/offset) exceeds the array length
|
|
7
|
+
*/
|
|
8
|
+
export function limitOffset<T>(array: T[], limit: string, offset: string): T[] {
|
|
9
|
+
if (!array) return [];
|
|
10
|
+
|
|
11
|
+
const $limit = parseInt(limit, 10);
|
|
12
|
+
const $offset = parseInt(offset, 10);
|
|
13
|
+
|
|
14
|
+
const length = array.length;
|
|
15
|
+
|
|
16
|
+
if (!length) {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
if ($offset > length - 1) {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const start = Math.min(length - 1, $offset);
|
|
24
|
+
const end = Math.min(length, $offset + $limit);
|
|
25
|
+
|
|
26
|
+
return array.slice(start, end);
|
|
27
|
+
}
|
|
28
|
+
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import winston from 'winston';
|
|
2
|
+
|
|
3
|
+
export type Level = "error" | "warn" | "info" | "http" | "verbose" | "debug" | "silly"
|
|
4
|
+
|
|
5
|
+
export class Logger {
|
|
6
|
+
private static isLocalEnv = process.env.NODE_ENV === "local"
|
|
7
|
+
static readonly instance = winston.createLogger({
|
|
8
|
+
transports: [
|
|
9
|
+
new winston.transports.Console(),
|
|
10
|
+
],
|
|
11
|
+
format: winston.format.combine(
|
|
12
|
+
winston.format.json()
|
|
13
|
+
),
|
|
14
|
+
exitOnError: false,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
static info(message: string, payload: any = {}) {
|
|
18
|
+
if (Logger.isLocalEnv) {
|
|
19
|
+
console.info(message, payload)
|
|
20
|
+
return
|
|
21
|
+
}
|
|
22
|
+
Logger.instance.info(message, payload);
|
|
23
|
+
}
|
|
24
|
+
static error(message: string, error: any) {
|
|
25
|
+
if (Logger.isLocalEnv) {
|
|
26
|
+
console.error(message, error)
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
Logger.instance.error(message, error);
|
|
30
|
+
}
|
|
31
|
+
static warn(message: string, data: any) {
|
|
32
|
+
if (Logger.isLocalEnv) {
|
|
33
|
+
console.warn(message, data)
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
Logger.instance.warn(message, data);
|
|
37
|
+
}
|
|
38
|
+
static debug(message: string, data: any) {
|
|
39
|
+
if (Logger.isLocalEnv) {
|
|
40
|
+
console.debug(message, data)
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
Logger.instance.debug(message, data);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static enableLogger() {
|
|
47
|
+
Logger.isLocalEnv = false
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
|
|
2
|
+
import { BadRequest, InternalServer, NoContent, Unauthorized } from '../errors';
|
|
3
|
+
|
|
4
|
+
export type AuthServiceQuery = {[key: string]: any};
|
|
5
|
+
|
|
6
|
+
export interface InternalAuthServiceMethods {
|
|
7
|
+
readonly request: AxiosInstance;
|
|
8
|
+
readonly baseURL: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface InternalAuthServiceOptions {
|
|
12
|
+
axiosConfig?: AxiosRequestConfig;
|
|
13
|
+
baseURL: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class AuthService implements InternalAuthServiceMethods {
|
|
17
|
+
readonly request: AxiosInstance
|
|
18
|
+
readonly baseURL: string
|
|
19
|
+
|
|
20
|
+
constructor({ axiosConfig, baseURL }: InternalAuthServiceOptions) {
|
|
21
|
+
this.request = axios.create({ ...(axiosConfig ?? {}), baseURL,})
|
|
22
|
+
this.baseURL = baseURL;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
throwError(err: any): never {
|
|
26
|
+
const message = err?.response?.data?.message
|
|
27
|
+
const status = err?.response?.status
|
|
28
|
+
if (message) {
|
|
29
|
+
switch(status) {
|
|
30
|
+
case 401: throw new Unauthorized(message)
|
|
31
|
+
case 400: throw new BadRequest(message)
|
|
32
|
+
case 500: throw new InternalServer(message)
|
|
33
|
+
case 204: throw new NoContent(message)
|
|
34
|
+
default: throw new InternalServer(message)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
throw new InternalServer(err?.message ?? String(err))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async verify<T = any>(query?: AuthServiceQuery, config: AxiosRequestConfig = {}): Promise<T> {
|
|
41
|
+
try {
|
|
42
|
+
const { data } = await this.request.post(`/verify`, undefined, { ...config, params: query })
|
|
43
|
+
return data?.data ?? data
|
|
44
|
+
} catch(err: any) {
|
|
45
|
+
this.throwError(err)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Request, Response } from "express";
|
|
2
|
+
import { Model } from "mongoose";
|
|
3
|
+
import type { InternalServiceMethods, Query, User } from "./types";
|
|
4
|
+
|
|
5
|
+
export interface MongoInternalServiceMethods<T = any> extends InternalServiceMethods<T> {
|
|
6
|
+
model: Model<T>
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface MongoInternalServiceOptions {
|
|
10
|
+
Model: Model<any>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class MongoDBService<T> implements MongoInternalServiceMethods<T> {
|
|
14
|
+
readonly Model: Model<any>;
|
|
15
|
+
constructor({Model}: MongoInternalServiceOptions) {
|
|
16
|
+
this.Model = Model;
|
|
17
|
+
}
|
|
18
|
+
async find(query?: Query, user?: User, req?: Request, res?: Response): Promise<T[]> {
|
|
19
|
+
return await this.Model.find(query ?? {})
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async get(id: string | null, query?: Query, user?: User, req?: Request, res?: Response): Promise<T | null> {
|
|
23
|
+
return await this.Model.findOne({
|
|
24
|
+
_id: id,
|
|
25
|
+
...query
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async create(data: Partial<T> | Partial<T>[], query?: Query, user?: User, req?: Request, res?: Response): Promise<T | T[]> {
|
|
30
|
+
return (await this.Model.create(data as any)).toJSON()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async update(id: string, data: T, query?: Query, user?: User, req?: Request, res?: Response): Promise<T | null> {
|
|
34
|
+
return await this.Model.findOneAndUpdate({_id: id}, {$set: data as any}, {new:true}) as any;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async patch(id: string, data: Partial<T>, query?: Query, user?: User, req?: Request, res?: Response): Promise<T | T[] | null> {
|
|
38
|
+
return await this.Model.findOneAndUpdate({_id: id}, {$set: data as any}, {new:true}) as any;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async remove(id: string, query?: Query, user?: User, req?: Request, res?: Response): Promise<T | T[] | null> {
|
|
42
|
+
return await this.Model.findOneAndDelete({_id: id, ...query});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get model() {
|
|
46
|
+
return this.Model
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async _find(query?: Query): Promise<T[]> {
|
|
50
|
+
return await this.Model.find(query ?? {})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async _get(id: string | null, query?: Query): Promise<T | null> {
|
|
54
|
+
return await this.Model.findOne({
|
|
55
|
+
_id: id,
|
|
56
|
+
...query
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async _create(data: Partial<T> | Partial<T>[]): Promise<T | T[]> {
|
|
61
|
+
return (await this.Model.create(data as any)).toJSON()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async _update(id: string, data: T): Promise<T | null> {
|
|
65
|
+
return await this.Model.findOneAndUpdate({_id: id}, {$set: data as any}, {new:true}) as any;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async _patch(id: string, data: Partial<T>): Promise<T | T[] | null> {
|
|
69
|
+
return await this.Model.findOneAndUpdate({_id: id}, {$set: data as any}, {new:true}) as any;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async _remove(id: string, query?: Query): Promise<T | T[] | null> {
|
|
73
|
+
return await this.Model.findOneAndDelete({_id: id, ...query});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { Request, Response } from "express";
|
|
2
|
+
import { ModelStatic, FindOptions, DestroyOptions } from 'sequelize'
|
|
3
|
+
|
|
4
|
+
import { FindResponse, InternalServiceMethods, Query, User } from "./types";
|
|
5
|
+
|
|
6
|
+
export interface PostgresInternalServiceMethods<T = any> extends InternalServiceMethods<any> {
|
|
7
|
+
model: ModelStatic<any>
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface PostgresInternalServiceOptions<T = any> {
|
|
11
|
+
Model: ModelStatic<any>
|
|
12
|
+
pagination?: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class PostgreSQLService<T = any> implements PostgresInternalServiceMethods<T> {
|
|
16
|
+
protected readonly Model: ModelStatic<any>;
|
|
17
|
+
pagination?: boolean | undefined;
|
|
18
|
+
constructor({Model, pagination}: PostgresInternalServiceOptions<T>) {
|
|
19
|
+
this.Model = Model;
|
|
20
|
+
this.pagination = pagination
|
|
21
|
+
}
|
|
22
|
+
async find(query?: any, user?: User, req?: Request): Promise<FindResponse<T>> {
|
|
23
|
+
const { $limit, $offset, ...restQuery } = query ?? {}
|
|
24
|
+
const modelQuery: FindOptions<any> = {
|
|
25
|
+
where: {
|
|
26
|
+
...(restQuery ?? {})
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
if ($limit) {
|
|
30
|
+
modelQuery.limit = $limit
|
|
31
|
+
}
|
|
32
|
+
if ($offset) {
|
|
33
|
+
modelQuery.offset = $offset
|
|
34
|
+
}
|
|
35
|
+
if (this.pagination) {
|
|
36
|
+
return await this.Model.findAndCountAll(modelQuery)
|
|
37
|
+
}
|
|
38
|
+
return await this.Model.findAll(modelQuery)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async get(id: string | null, query?: Query, user?: User, req?: Request, res?: Response): Promise<T | null> {
|
|
42
|
+
if(id) {
|
|
43
|
+
return await this.Model.findByPk(id)
|
|
44
|
+
}
|
|
45
|
+
return await this.Model.findOne({
|
|
46
|
+
where: {
|
|
47
|
+
...(query ?? {})
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async create(data: Partial<T> | Partial<T>[], query?: Query, user?: User, req?: Request, res?: Response): Promise<T | T[]> {
|
|
53
|
+
return await this.Model.create(data as any) as any
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async update(id: string, data: any, query?: Query, user?: User, req?: Request, res?: Response): Promise<any> {
|
|
57
|
+
return await this.Model.update({ ...data }, {
|
|
58
|
+
where: {
|
|
59
|
+
id,
|
|
60
|
+
...(query ?? {})
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async patch(id: string, data: Partial<T>, query?: Query, user?: User, req?: Request, res?: Response): Promise<any> {
|
|
66
|
+
return await this.Model.update({ ...data }, {
|
|
67
|
+
where: {
|
|
68
|
+
id,
|
|
69
|
+
...(query ?? {})
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async remove(id: string, query?: DestroyOptions, user?: User, req?: Request, res?: Response): Promise<any> {
|
|
75
|
+
return await this.Model.destroy({
|
|
76
|
+
where: {
|
|
77
|
+
id,
|
|
78
|
+
...(query ?? {})
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
get model() {
|
|
84
|
+
return this.Model
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async _find(query?: Query, user?: User, req?: Request): Promise<FindResponse<T>> {
|
|
88
|
+
const { $limit, $offset, ...restQuery } = query ?? {}
|
|
89
|
+
const modelQuery: FindOptions<any> = {
|
|
90
|
+
where: {
|
|
91
|
+
...(restQuery ?? {})
|
|
92
|
+
},
|
|
93
|
+
}
|
|
94
|
+
if ($limit) {
|
|
95
|
+
modelQuery.limit = $limit
|
|
96
|
+
}
|
|
97
|
+
if ($offset) {
|
|
98
|
+
modelQuery.offset = $offset
|
|
99
|
+
}
|
|
100
|
+
if (this.pagination) {
|
|
101
|
+
return await this.Model.findAndCountAll(modelQuery)
|
|
102
|
+
}
|
|
103
|
+
return await this.Model.findAll(modelQuery)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async _get(id: string | null, query?: Query): Promise<T | null> {
|
|
107
|
+
if(id) {
|
|
108
|
+
return await this.Model.findByPk(id)
|
|
109
|
+
}
|
|
110
|
+
return await this.Model.findOne({
|
|
111
|
+
where: {
|
|
112
|
+
...(query ?? {})
|
|
113
|
+
}
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async _create(data: Partial<T> | Partial<T>[]): Promise<T | T[]> {
|
|
118
|
+
return await this.Model.create(data as any)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async _update(id: string, data: Partial<any>): Promise<any> {
|
|
122
|
+
const [, updatedData] = await this.Model.update({ ...data }, {
|
|
123
|
+
where: {
|
|
124
|
+
id
|
|
125
|
+
},
|
|
126
|
+
returning: true
|
|
127
|
+
});
|
|
128
|
+
return updatedData
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async _patch(id: string, data: Partial<T>): Promise<any> {
|
|
132
|
+
const [, updatedData] = await this.Model.update({ ...data }, {
|
|
133
|
+
where: {
|
|
134
|
+
id
|
|
135
|
+
},
|
|
136
|
+
returning: true,
|
|
137
|
+
});
|
|
138
|
+
return updatedData
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async _remove(id: string, query?: Query): Promise<any> {
|
|
142
|
+
return await this.Model.destroy({
|
|
143
|
+
where: {
|
|
144
|
+
id,
|
|
145
|
+
...(query ?? {})
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Request, Response } from "express";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export type Query = {[key: string]: any};
|
|
5
|
+
|
|
6
|
+
export type User = any
|
|
7
|
+
|
|
8
|
+
export type FindResponse<T> = T[] | {
|
|
9
|
+
rows: T[];
|
|
10
|
+
count: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface InternalServiceMethods<T = any> {
|
|
14
|
+
find(query: Query, user?: any, req?: Request, res?: Response): Promise<FindResponse<T>>;
|
|
15
|
+
get(id: string | null, query?: Query, user?: User, req?: Request, res?: Response): Promise<T | null>;
|
|
16
|
+
create(data: Partial<T> | Partial<T>[], query?: Query, user?: User, req?: Request, res?: Response): Promise<T | T[]>;
|
|
17
|
+
update(id: string, data: T, query?: Query, user?: User, req?: Request, res?: Response): Promise<T | null>;
|
|
18
|
+
patch(id: string, data: Partial<T>, query?: Query, user?: User, req?: Request, res?: Response): Promise<T | T[] | null>;
|
|
19
|
+
remove(id: string, query?: Query, user?: User, req?: Request, res?: Response): Promise<T | T[] | null>;
|
|
20
|
+
_find: InternalServiceMethods<T>['find']
|
|
21
|
+
_get: InternalServiceMethods<T>['get']
|
|
22
|
+
_create: InternalServiceMethods<T>['create']
|
|
23
|
+
_patch: InternalServiceMethods<T>['patch']
|
|
24
|
+
_update: InternalServiceMethods<T>['update']
|
|
25
|
+
_remove: InternalServiceMethods<T>['remove']
|
|
26
|
+
pagination?: boolean
|
|
27
|
+
filtering?: boolean
|
|
28
|
+
auth?: boolean
|
|
29
|
+
}
|