@sera4/essentia 1.1.65 → 3.0.6
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 +352 -8
- package/dist/ts/cache/index.d.ts +33 -0
- package/dist/ts/cache/index.js +171 -0
- package/dist/ts/cache/index.js.map +1 -0
- package/dist/ts/configurations/server-config.d.ts +4 -0
- package/dist/ts/configurations/server-config.js +2 -0
- package/dist/ts/configurations/server-config.js.map +1 -0
- package/dist/ts/constants/index.d.ts +7 -0
- package/{constants → dist/ts/constants}/index.js +5 -6
- package/dist/ts/constants/index.js.map +1 -0
- package/dist/ts/cycle/index.d.ts +53 -0
- package/dist/ts/cycle/index.js +169 -0
- package/dist/ts/cycle/index.js.map +1 -0
- package/dist/ts/dns/DnsCache.d.ts +50 -0
- package/dist/ts/dns/DnsCache.js +137 -0
- package/dist/ts/dns/DnsCache.js.map +1 -0
- package/dist/ts/dns/index.d.ts +4 -0
- package/dist/ts/dns/index.js +4 -0
- package/dist/ts/dns/index.js.map +1 -0
- package/dist/ts/formatter/index.d.ts +44 -0
- package/dist/ts/formatter/index.js +76 -0
- package/dist/ts/formatter/index.js.map +1 -0
- package/dist/ts/hal/index.d.ts +26 -0
- package/dist/ts/hal/index.js +70 -0
- package/dist/ts/hal/index.js.map +1 -0
- package/dist/ts/health/index.d.ts +53 -0
- package/dist/ts/health/index.js +165 -0
- package/dist/ts/health/index.js.map +1 -0
- package/dist/ts/helpers/index.d.ts +1 -0
- package/dist/ts/helpers/index.js +2 -0
- package/dist/ts/helpers/index.js.map +1 -0
- package/dist/ts/helpers/test-server-wrapper.d.ts +56 -0
- package/dist/ts/helpers/test-server-wrapper.js +144 -0
- package/dist/ts/helpers/test-server-wrapper.js.map +1 -0
- package/dist/ts/index.d.ts +21 -0
- package/dist/ts/index.js +25 -0
- package/dist/ts/index.js.map +1 -0
- package/dist/ts/last-commit/index.d.ts +12 -0
- package/dist/ts/last-commit/index.js +82 -0
- package/dist/ts/last-commit/index.js.map +1 -0
- package/dist/ts/logger/index.d.ts +3 -0
- package/dist/ts/logger/index.js +4 -0
- package/dist/ts/logger/index.js.map +1 -0
- package/dist/ts/logger/s4-logger.d.ts +23 -0
- package/dist/ts/logger/s4-logger.js +103 -0
- package/dist/ts/logger/s4-logger.js.map +1 -0
- package/dist/ts/paginator/index.d.ts +2 -0
- package/dist/ts/paginator/index.js +3 -0
- package/dist/ts/paginator/index.js.map +1 -0
- package/dist/ts/paginator/s4-pagination.d.ts +26 -0
- package/dist/ts/paginator/s4-pagination.js +49 -0
- package/dist/ts/paginator/s4-pagination.js.map +1 -0
- package/dist/ts/paginator/sql-pagination.d.ts +52 -0
- package/dist/ts/paginator/sql-pagination.js +157 -0
- package/dist/ts/paginator/sql-pagination.js.map +1 -0
- package/dist/ts/paper-trail/helpers.d.ts +14 -0
- package/dist/ts/paper-trail/helpers.js +74 -0
- package/dist/ts/paper-trail/helpers.js.map +1 -0
- package/dist/ts/paper-trail/index.d.ts +54 -0
- package/dist/ts/paper-trail/index.js +236 -0
- package/dist/ts/paper-trail/index.js.map +1 -0
- package/dist/ts/prompts/index.d.ts +21 -0
- package/dist/ts/prompts/index.js +68 -0
- package/dist/ts/prompts/index.js.map +1 -0
- package/dist/ts/queue/index.d.ts +196 -0
- package/dist/ts/queue/index.js +371 -0
- package/dist/ts/queue/index.js.map +1 -0
- package/dist/ts/queue/publisher.d.ts +41 -0
- package/dist/ts/queue/publisher.js +84 -0
- package/dist/ts/queue/publisher.js.map +1 -0
- package/dist/ts/queue/queue-logger.d.ts +10 -0
- package/dist/ts/queue/queue-logger.js +35 -0
- package/dist/ts/queue/queue-logger.js.map +1 -0
- package/dist/ts/queue/subscriber.d.ts +55 -0
- package/dist/ts/queue/subscriber.js +98 -0
- package/dist/ts/queue/subscriber.js.map +1 -0
- package/dist/ts/safe-proxy/index.d.ts +35 -0
- package/dist/ts/safe-proxy/index.js +54 -0
- package/dist/ts/safe-proxy/index.js.map +1 -0
- package/dist/ts/serializer/index.d.ts +52 -0
- package/dist/ts/serializer/index.js +83 -0
- package/dist/ts/serializer/index.js.map +1 -0
- package/dist/ts/utils/index.d.ts +49 -0
- package/dist/ts/utils/index.js +157 -0
- package/dist/ts/utils/index.js.map +1 -0
- package/package.json +52 -11
- package/package.tar.gz +0 -0
- package/cache/index.js +0 -188
- package/formatter/index.js +0 -81
- package/hal/README.md +0 -54
- package/hal/index.js +0 -75
- package/health/health-logger.js +0 -40
- package/health/index.js +0 -188
- package/helpers/index.js +0 -1
- package/helpers/test-server-wrapper.js +0 -196
- package/last-commit.js +0 -12
- package/last_commit/index.js +0 -82
- package/logger/s4-logger.js +0 -128
- package/paginator/README.md +0 -183
- package/paginator/s4-pagination.js +0 -51
- package/paginator/sql-pagination.js +0 -178
- package/paper-trail/README.md +0 -68
- package/paper-trail/helpers.js +0 -99
- package/paper-trail/index.js +0 -842
- package/prompts/index.js +0 -78
- package/queue/index.js +0 -414
- package/queue/publisher.js +0 -96
- package/queue/queue-logger.js +0 -40
- package/queue/subscriber.js +0 -107
- package/safe_proxy/index.js +0 -61
- package/serializer/index.js +0 -90
- package/utils/index.js +0 -74
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import logger from "./queue-logger.js";
|
|
2
|
+
/**
|
|
3
|
+
* A subscriber for AMQP service
|
|
4
|
+
*/
|
|
5
|
+
export class Subscriber {
|
|
6
|
+
get key() {
|
|
7
|
+
return this._key;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Builds a subscriber
|
|
11
|
+
* @param exchange name of the AMQP exchange
|
|
12
|
+
* @param queue name of the AMQP service
|
|
13
|
+
* @param key routing key. This will be used to bind the queue to the exchange
|
|
14
|
+
* @param name a useful name to be printed in the logs
|
|
15
|
+
*/
|
|
16
|
+
constructor(exchange, queue, key, name) {
|
|
17
|
+
this.exchange = exchange;
|
|
18
|
+
this.queue = queue;
|
|
19
|
+
this._key = key;
|
|
20
|
+
this.name = name;
|
|
21
|
+
this.channel = null;
|
|
22
|
+
this.callbacks = [];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Initializes the subscriber on the given connection.
|
|
26
|
+
* During this call, the exchange and the queues are asserted
|
|
27
|
+
* and bound via the key provided in the constructor.
|
|
28
|
+
* @param conn amqp connection object
|
|
29
|
+
*/
|
|
30
|
+
async init(conn) {
|
|
31
|
+
logger.debug(`Initializing SUB channel for ${this.name}`);
|
|
32
|
+
if (this.channel) {
|
|
33
|
+
logger.warn(`SUB channel for ${this.name} already initialized`);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
this.channel = await conn.createChannel();
|
|
37
|
+
if (!this.channel) {
|
|
38
|
+
throw new Error(`Cannot create SUB channel for ${this.name}`);
|
|
39
|
+
}
|
|
40
|
+
this.channel.on("error", (err) => {
|
|
41
|
+
logger.debug(`Connection error for ${this.name}`, err);
|
|
42
|
+
this.channel = null;
|
|
43
|
+
});
|
|
44
|
+
this.channel.on("close", () => {
|
|
45
|
+
logger.debug(`Connection closed for ${this.name}`);
|
|
46
|
+
this.channel = null;
|
|
47
|
+
});
|
|
48
|
+
logger.debug(`Initialized SUB channel for ${this.name}`);
|
|
49
|
+
const { name: exchangeName, options: exchangeOptions, type } = this.exchange;
|
|
50
|
+
const { name: queueName, options: queueOptions } = this.queue;
|
|
51
|
+
await this.channel.assertExchange(exchangeName, type, exchangeOptions);
|
|
52
|
+
await this.channel.assertQueue(queueName, queueOptions);
|
|
53
|
+
logger.debug(`Binding queue ${queueName} on ${exchangeName} exchange for ${this._key} key`);
|
|
54
|
+
await this.channel.bindQueue(queueName, exchangeName, this._key);
|
|
55
|
+
this.channel.consume(queueName, (msg) => {
|
|
56
|
+
const { fields, content } = msg;
|
|
57
|
+
let payload = { metadata: fields };
|
|
58
|
+
let error = null;
|
|
59
|
+
try {
|
|
60
|
+
const parsedContent = JSON.parse(content.toString());
|
|
61
|
+
payload = { ...parsedContent, metadata: fields };
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
logger.error("Failed to parse incoming message:", e);
|
|
65
|
+
error = e;
|
|
66
|
+
payload = { error, original_content: content.toString(), metadata: fields };
|
|
67
|
+
}
|
|
68
|
+
logger.debug(`Got message from exchange '${fields.exchange}' with key '${fields.routingKey}'`);
|
|
69
|
+
logger.debug("Content", payload);
|
|
70
|
+
this.callbacks.forEach(cb => {
|
|
71
|
+
cb(payload, error);
|
|
72
|
+
});
|
|
73
|
+
this.channel.ack(msg);
|
|
74
|
+
}, { noAck: false });
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Closes the channel
|
|
78
|
+
* @returns promise
|
|
79
|
+
*/
|
|
80
|
+
async closeChannel() {
|
|
81
|
+
if (this.channel) {
|
|
82
|
+
logger.debug("Closing subscriber channel", this.name);
|
|
83
|
+
return this.channel.close();
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
logger.error("Can't close a null subscriber channel");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Register a new callback to receive message through this
|
|
91
|
+
* subscriber object
|
|
92
|
+
* @param cb A callback to be called when a message arrives
|
|
93
|
+
*/
|
|
94
|
+
registerCallback(cb) {
|
|
95
|
+
this.callbacks.push(cb);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=subscriber.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscriber.js","sourceRoot":"","sources":["../../../ts/queue/subscriber.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { AxiosResponse } from "axios";
|
|
2
|
+
interface Locals {
|
|
3
|
+
account?: {
|
|
4
|
+
id?: string;
|
|
5
|
+
};
|
|
6
|
+
tenant?: {
|
|
7
|
+
id?: string;
|
|
8
|
+
};
|
|
9
|
+
membership?: {
|
|
10
|
+
id?: string;
|
|
11
|
+
} | null;
|
|
12
|
+
}
|
|
13
|
+
interface RequestOptions {
|
|
14
|
+
headers?: Record<string, string>;
|
|
15
|
+
data?: any;
|
|
16
|
+
}
|
|
17
|
+
interface ProxyLocals {
|
|
18
|
+
account?: {
|
|
19
|
+
id?: string;
|
|
20
|
+
};
|
|
21
|
+
tenant?: {
|
|
22
|
+
id?: string;
|
|
23
|
+
};
|
|
24
|
+
membership?: {
|
|
25
|
+
id?: string;
|
|
26
|
+
} | null;
|
|
27
|
+
}
|
|
28
|
+
declare class SafeProxy {
|
|
29
|
+
constructor();
|
|
30
|
+
post(locals: Locals, url: string, options?: RequestOptions): Promise<AxiosResponse>;
|
|
31
|
+
delete(locals: Locals, url: string, options?: RequestOptions): Promise<AxiosResponse>;
|
|
32
|
+
private _proxyRequest;
|
|
33
|
+
}
|
|
34
|
+
export declare const safeProxy: SafeProxy;
|
|
35
|
+
export type { Locals, RequestOptions, ProxyLocals };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
const { omitBy, isNil } = _;
|
|
4
|
+
/* A class which safely wraps an axios connection in order to pass the current user through to
|
|
5
|
+
* the next service. Useful when one of our microservices requires auth as either an admin (sera4tal)
|
|
6
|
+
* or as the end user (example: DELETE /auth/sessions/:id
|
|
7
|
+
*
|
|
8
|
+
* Similar to proxy however this isn't a proxy, it's a full out new call that we can manage
|
|
9
|
+
* each method requires a res.locals from a pre-authd session
|
|
10
|
+
*/
|
|
11
|
+
class SafeProxy {
|
|
12
|
+
constructor() {
|
|
13
|
+
}
|
|
14
|
+
// a safe post request
|
|
15
|
+
// locals = res.locals - your authentication details
|
|
16
|
+
post(locals, url, options = { headers: {}, data: {} }) {
|
|
17
|
+
const { account, tenant, membership } = locals;
|
|
18
|
+
return this._proxyRequest({ account, tenant, membership }, url, "post", options);
|
|
19
|
+
}
|
|
20
|
+
delete(locals, url, options = { headers: {}, data: {} }) {
|
|
21
|
+
const { account, tenant, membership } = locals;
|
|
22
|
+
return this._proxyRequest({ account, tenant, membership }, url, "delete", options);
|
|
23
|
+
}
|
|
24
|
+
/* private methods */
|
|
25
|
+
// supports get, delete, post
|
|
26
|
+
// options includes { headers, data } for post / delete payloads
|
|
27
|
+
async _proxyRequest(locals, url, method = "get", options) {
|
|
28
|
+
let request;
|
|
29
|
+
const membership = locals.membership ? JSON.stringify(locals.membership) : null;
|
|
30
|
+
const headers = omitBy({
|
|
31
|
+
...options.headers,
|
|
32
|
+
"tws-account-id": locals.account?.id,
|
|
33
|
+
"tws-tenant-id": locals.tenant?.id,
|
|
34
|
+
"tws-membership-id": locals.membership?.id,
|
|
35
|
+
"tws-membership": membership
|
|
36
|
+
}, isNil);
|
|
37
|
+
switch (method) {
|
|
38
|
+
case "post":
|
|
39
|
+
request = axios.post(url, { ...options.data }, { headers });
|
|
40
|
+
break;
|
|
41
|
+
case "delete":
|
|
42
|
+
request = axios.delete(url, { data: options.data, headers });
|
|
43
|
+
break;
|
|
44
|
+
case "get":
|
|
45
|
+
request = axios.get(url, { headers });
|
|
46
|
+
break;
|
|
47
|
+
default:
|
|
48
|
+
throw new Error("unknown type called in proxyRequest");
|
|
49
|
+
}
|
|
50
|
+
return request;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export const safeProxy = new SafeProxy();
|
|
54
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../ts/safe-proxy/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAA4C,MAAM,OAAO,CAAC;AACjE,OAAO,CAAC,MAAM,QAAQ,CAAC;AAEvB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AA+B5B;;;;;;GAMG;AACH,MAAM,SAAS;IACb;IACA,CAAC;IAED,sBAAsB;IACtB,oDAAoD;IACpD,IAAI,CAAC,MAAc,EAAE,GAAW,EAAE,UAA0B,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACnF,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC;QAC/C,OAAO,IAAI,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACnF,CAAC;IAED,MAAM,CAAC,MAAc,EAAE,GAAW,EAAE,UAA0B,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACrF,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC;QAC/C,OAAO,IAAI,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACrF,CAAC;IAED,qBAAqB;IACrB,6BAA6B;IAC7B,gEAAgE;IACxD,KAAK,CAAC,aAAa,CAAC,MAAmB,EAAE,GAAW,EAAE,SAAoC,KAAK,EAAE,OAAuB;QAC9H,IAAI,OAA+B,CAAC;QACpC,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAChF,MAAM,OAAO,GAAG,MAAM,CAAC;YACrB,GAAG,OAAO,CAAC,OAAO;YAClB,gBAAgB,EAAE,MAAM,CAAC,OAAO,EAAE,EAAE;YACpC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE;YAClC,mBAAmB,EAAE,MAAM,CAAC,UAAU,EAAE,EAAE;YAC1C,gBAAgB,EAAE,UAAU;SAC7B,EAAE,KAAK,CAAC,CAAC;QAEV,QAAO,MAAM,EAAE,CAAC;YACd,KAAK,MAAM;gBACT,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC5D,MAAM;YACR,KAAK,QAAQ;gBACX,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC7D,MAAM;YACR,KAAK,KAAK;gBACR,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;gBACtC,MAAM;YACR;gBACE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAC3D,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,SAAS,EAAE,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
interface SerializerOptions {
|
|
2
|
+
hide?: string[];
|
|
3
|
+
remove?: string[];
|
|
4
|
+
decorators?: Decorator[];
|
|
5
|
+
includeAllFields?: boolean;
|
|
6
|
+
includeFields?: Record<string, boolean>;
|
|
7
|
+
}
|
|
8
|
+
interface EachOptions {
|
|
9
|
+
includeAllFields?: boolean;
|
|
10
|
+
includeFields?: Record<string, boolean>;
|
|
11
|
+
handlerOptions?: Record<string, any>;
|
|
12
|
+
serializer?: string;
|
|
13
|
+
includes?: Array<Record<string, any>>;
|
|
14
|
+
}
|
|
15
|
+
interface Decorator {
|
|
16
|
+
name: string;
|
|
17
|
+
handler?: (value: any) => any;
|
|
18
|
+
advHandler?: (value: any, object: any, options: Record<string, any>) => any;
|
|
19
|
+
}
|
|
20
|
+
interface ModelInstance {
|
|
21
|
+
get: () => Record<string, any>;
|
|
22
|
+
prototype: {
|
|
23
|
+
toJSON: (options?: EachOptions) => Record<string, any>;
|
|
24
|
+
get: () => Record<string, any>;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
interface CustomSerializers {
|
|
28
|
+
[name: string]: (data: Record<string, any>) => Record<string, any>;
|
|
29
|
+
}
|
|
30
|
+
declare const _default: {
|
|
31
|
+
/**
|
|
32
|
+
* Serializes a Sequelize Model.
|
|
33
|
+
* @param {Object} Model the sequelize model to add this plugin to
|
|
34
|
+
* @param {Object} options various options for serialization. These can be:
|
|
35
|
+
* • hide - an array of fields to be omitted
|
|
36
|
+
* • remove - an array of fields to be REMOVED so they cannot be unhidden
|
|
37
|
+
* • decorators - an array of special decorators to run during serialization
|
|
38
|
+
* • handler - a handler for transforming data using only the values
|
|
39
|
+
* • advhandler - an advanced handler for transforming data using the value, object or options
|
|
40
|
+
* • includeAllFields - show fields that are normally hidden
|
|
41
|
+
* • includeFields[..] - show specific fields that are normally hidden
|
|
42
|
+
*/
|
|
43
|
+
serialize: (Model: ModelInstance, options?: SerializerOptions) => void;
|
|
44
|
+
/**
|
|
45
|
+
* Registers a custom serializer.
|
|
46
|
+
* @param {String} name the name of the custom serializer
|
|
47
|
+
* @param {Function} serializer a custom serializer function associated with the name
|
|
48
|
+
*/
|
|
49
|
+
register: (name: string, serializer: (data: Record<string, any>) => Record<string, any>) => void;
|
|
50
|
+
};
|
|
51
|
+
export default _default;
|
|
52
|
+
export type { SerializerOptions, EachOptions, Decorator, ModelInstance, CustomSerializers };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import _ from "lodash";
|
|
2
|
+
const customSerializers = {};
|
|
3
|
+
export default {
|
|
4
|
+
/**
|
|
5
|
+
* Serializes a Sequelize Model.
|
|
6
|
+
* @param {Object} Model the sequelize model to add this plugin to
|
|
7
|
+
* @param {Object} options various options for serialization. These can be:
|
|
8
|
+
* • hide - an array of fields to be omitted
|
|
9
|
+
* • remove - an array of fields to be REMOVED so they cannot be unhidden
|
|
10
|
+
* • decorators - an array of special decorators to run during serialization
|
|
11
|
+
* • handler - a handler for transforming data using only the values
|
|
12
|
+
* • advhandler - an advanced handler for transforming data using the value, object or options
|
|
13
|
+
* • includeAllFields - show fields that are normally hidden
|
|
14
|
+
* • includeFields[..] - show specific fields that are normally hidden
|
|
15
|
+
*/
|
|
16
|
+
serialize: (Model, options = {}) => {
|
|
17
|
+
Model.prototype.toJSON = function (eachOptions = {}) {
|
|
18
|
+
const hide = options.hide || [];
|
|
19
|
+
const remove = options.remove || [];
|
|
20
|
+
// ignore hide principles; but still do NOT show null
|
|
21
|
+
const includeAllFields = eachOptions.includeAllFields;
|
|
22
|
+
// optionally force a normally hidden fields to be seen (by name)
|
|
23
|
+
const includeFields = eachOptions.includeFields || {};
|
|
24
|
+
const handlerOptions = eachOptions.handlerOptions || {};
|
|
25
|
+
const values = this.get();
|
|
26
|
+
if (options.decorators) {
|
|
27
|
+
options.decorators.forEach(dec => {
|
|
28
|
+
const k = dec.name;
|
|
29
|
+
const v = values[k];
|
|
30
|
+
// the advanced handler takes more parameters
|
|
31
|
+
if (dec.advHandler) {
|
|
32
|
+
values[k] = dec.advHandler(v, this, handlerOptions);
|
|
33
|
+
}
|
|
34
|
+
else if (dec.handler) {
|
|
35
|
+
values[k] = dec.handler(v);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
// for security reasons, some fields may need to be removed, such as
|
|
40
|
+
// password salts and mfa tokens
|
|
41
|
+
remove.forEach((field) => {
|
|
42
|
+
delete values[field];
|
|
43
|
+
});
|
|
44
|
+
// hidden fields CAN be resurrected if NOT null, and forced to be
|
|
45
|
+
// included
|
|
46
|
+
let serialized = _.omitBy(values, (v, k) => {
|
|
47
|
+
if (v === null)
|
|
48
|
+
return true;
|
|
49
|
+
let omitted = (includeAllFields ? false : hide.includes(k));
|
|
50
|
+
if (omitted && includeFields[k])
|
|
51
|
+
omitted = false;
|
|
52
|
+
return omitted;
|
|
53
|
+
});
|
|
54
|
+
const s = eachOptions.serializer;
|
|
55
|
+
if (s && customSerializers[s]) {
|
|
56
|
+
serialized = customSerializers[s](serialized);
|
|
57
|
+
}
|
|
58
|
+
if (Array.isArray(eachOptions.includes)) {
|
|
59
|
+
// Attach any included options that are
|
|
60
|
+
// not null or undefined
|
|
61
|
+
eachOptions.includes.forEach(include => {
|
|
62
|
+
if (include) {
|
|
63
|
+
const key = Object.keys(include)[0];
|
|
64
|
+
const value = include[key];
|
|
65
|
+
if (value) {
|
|
66
|
+
serialized[key] = value;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return serialized;
|
|
72
|
+
};
|
|
73
|
+
},
|
|
74
|
+
/**
|
|
75
|
+
* Registers a custom serializer.
|
|
76
|
+
* @param {String} name the name of the custom serializer
|
|
77
|
+
* @param {Function} serializer a custom serializer function associated with the name
|
|
78
|
+
*/
|
|
79
|
+
register: (name, serializer) => {
|
|
80
|
+
customSerializers[name] = serializer;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../ts/serializer/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
interface RecursiveIteratorMeta {
|
|
2
|
+
node: any;
|
|
3
|
+
parent: any;
|
|
4
|
+
path: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare const utils: {
|
|
7
|
+
isValidUuidV4: (input: any) => boolean;
|
|
8
|
+
convertToIntegerArray(input: any): number[];
|
|
9
|
+
convertToArray: (input: any) => string[];
|
|
10
|
+
isBlank: (str: any) => boolean;
|
|
11
|
+
getRouteType: (domain: string) => number;
|
|
12
|
+
isWebRoute: (sessionType: any) => boolean;
|
|
13
|
+
isApiRoute: (sessionType: any) => boolean;
|
|
14
|
+
isMobileRoute: (sessionType: any) => boolean;
|
|
15
|
+
isOtherRoute: (sessionType: any) => boolean;
|
|
16
|
+
recursiveOmitBy: (object: any, callback: (meta: RecursiveIteratorMeta) => boolean, ...recursiveIteratorOpts: any[]) => any;
|
|
17
|
+
/**
|
|
18
|
+
* Helper function to safely update JSONB columns in Sequelize models
|
|
19
|
+
*
|
|
20
|
+
* @param model - The Sequelize model instance
|
|
21
|
+
* @param columnName - The name of the JSONB column to update
|
|
22
|
+
* @param obj - The object to merge with existing column data
|
|
23
|
+
*
|
|
24
|
+
* Features:
|
|
25
|
+
* - Merges new data with existing data
|
|
26
|
+
* - Removes null/undefined values recursively
|
|
27
|
+
* - Only updates if data actually changed
|
|
28
|
+
* - Handles errors gracefully
|
|
29
|
+
* - Triggers sequelize's changed method to mark the column as changed *** VERY IMPORTANT ***
|
|
30
|
+
*
|
|
31
|
+
* Usage:
|
|
32
|
+
* // In a model prototype method
|
|
33
|
+
* Account.prototype.setOptions = function(obj) {
|
|
34
|
+
* utils.setJSONBOptionsForColumn(this, "options", obj);
|
|
35
|
+
* };
|
|
36
|
+
*
|
|
37
|
+
* // Direct usage
|
|
38
|
+
* utils.setJSONBOptionsForColumn(account, "auth_options", { field: null }); // will remove the field
|
|
39
|
+
* utils.setJSONBOptionsForColumn(account, "auth_options", { field: undefined }); // will remove the field
|
|
40
|
+
* utils.setJSONBOptionsForColumn(account, "auth_options", { field: "value" }); // will set the field
|
|
41
|
+
* utils.setJSONBOptionsForColumn(account, "auth_options", { field: { subfield: "value" } }); // will set the subfield
|
|
42
|
+
* utils.setJSONBOptionsForColumn(account, "auth_options", { field: { subfield: null } }); // will remove the subfield
|
|
43
|
+
* utils.setJSONBOptionsForColumn(account, "auth_options", { field: { subfield: undefined } }); // will remove the subfield
|
|
44
|
+
* utils.setJSONBOptionsForColumn(account, "auth_options", { field: { subfield: "value" } }); // will set the subfield
|
|
45
|
+
* utils.setJSONBOptionsForColumn(account, "auth_options", { field: { subfield: null } }); // will remove the subfield
|
|
46
|
+
*/
|
|
47
|
+
setJSONBOptionsForColumn: (model: any, columnName: string, obj: any) => void;
|
|
48
|
+
};
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import RecursiveIterator from 'recursive-iterator';
|
|
2
|
+
import { TWS_ROUTE_TYPES } from "../constants/index.js";
|
|
3
|
+
import _ from "lodash";
|
|
4
|
+
const { merge, isEqual } = _;
|
|
5
|
+
import logger from "../logger/s4-logger.js";
|
|
6
|
+
// Helper function to delete object properties by path
|
|
7
|
+
const delObjectPath = (obj, path) => {
|
|
8
|
+
const keys = path.split('.');
|
|
9
|
+
const lastKey = keys.pop();
|
|
10
|
+
const target = keys.reduce((current, key) => current && current[key], obj);
|
|
11
|
+
if (target && target.hasOwnProperty(lastKey)) {
|
|
12
|
+
delete target[lastKey];
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
export const utils = {
|
|
16
|
+
isValidUuidV4: (input) => {
|
|
17
|
+
if (!input) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
return /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(input);
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
// convert a regular string or Array to array (ie, "[1,2,3, 0xA]", "1,2,3,10")
|
|
25
|
+
// useful for controller inputs
|
|
26
|
+
// - also accepts hex
|
|
27
|
+
convertToIntegerArray(input) {
|
|
28
|
+
return this.convertToArray(input)
|
|
29
|
+
.filter((el) => /^[0-9]+/.test(el))
|
|
30
|
+
.map((el) => parseInt(el))
|
|
31
|
+
.filter((el) => Number.isInteger(el));
|
|
32
|
+
},
|
|
33
|
+
convertToArray: (input) => {
|
|
34
|
+
if (Array.isArray(input)) {
|
|
35
|
+
return input;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
if (!!input) {
|
|
39
|
+
if (typeof input === "number") {
|
|
40
|
+
return [input.toString()];
|
|
41
|
+
}
|
|
42
|
+
let matches;
|
|
43
|
+
if (matches = input.match(/\[(.*?)\]/)) {
|
|
44
|
+
input = matches[1];
|
|
45
|
+
}
|
|
46
|
+
input = input.replace(/[\[\]]/, '');
|
|
47
|
+
return input.replace(/\s+/, '').split(',').filter((el) => /^[0-9A-Za-z-.]+/.test(el));
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
isBlank: (str) => {
|
|
55
|
+
return ((str === null) || (str === undefined) || /^\s*$/.test(str));
|
|
56
|
+
},
|
|
57
|
+
getRouteType: (domain) => {
|
|
58
|
+
if (!domain)
|
|
59
|
+
return -1;
|
|
60
|
+
let routeType;
|
|
61
|
+
switch (true) {
|
|
62
|
+
case /^(tws-web|local-gateway)/i.test(domain):
|
|
63
|
+
routeType = TWS_ROUTE_TYPES['web'];
|
|
64
|
+
break;
|
|
65
|
+
case /^tws-mob/i.test(domain):
|
|
66
|
+
routeType = TWS_ROUTE_TYPES['mobile'];
|
|
67
|
+
break;
|
|
68
|
+
case /^(tws-api-)/i.test(domain):
|
|
69
|
+
routeType = TWS_ROUTE_TYPES['api'];
|
|
70
|
+
break;
|
|
71
|
+
default:
|
|
72
|
+
routeType = TWS_ROUTE_TYPES['other'];
|
|
73
|
+
}
|
|
74
|
+
return routeType;
|
|
75
|
+
},
|
|
76
|
+
isWebRoute: (sessionType) => (parseInt(sessionType) === TWS_ROUTE_TYPES['web']),
|
|
77
|
+
isApiRoute: (sessionType) => (parseInt(sessionType) === TWS_ROUTE_TYPES['api']),
|
|
78
|
+
isMobileRoute: (sessionType) => (parseInt(sessionType) === TWS_ROUTE_TYPES['mobile']),
|
|
79
|
+
isOtherRoute: (sessionType) => {
|
|
80
|
+
const value = parseInt(sessionType);
|
|
81
|
+
return ((value === TWS_ROUTE_TYPES['other']) || isNaN(value)) ? true : false;
|
|
82
|
+
},
|
|
83
|
+
recursiveOmitBy: (object, callback, ...recursiveIteratorOpts) => {
|
|
84
|
+
const results = merge({}, object);
|
|
85
|
+
for (let meta of new RecursiveIterator(object, ...recursiveIteratorOpts)) {
|
|
86
|
+
const shouldOmit = callback(meta);
|
|
87
|
+
if (shouldOmit) {
|
|
88
|
+
// Check if this is an array element
|
|
89
|
+
const pathParts = meta.path;
|
|
90
|
+
const lastPart = pathParts[pathParts.length - 1];
|
|
91
|
+
if (!isNaN(Number(lastPart)) && Array.isArray(meta.parent)) {
|
|
92
|
+
// This is an array element, remove it from the array
|
|
93
|
+
const parentPath = pathParts.slice(0, -1).join('.');
|
|
94
|
+
const parent = parentPath ? pathParts.slice(0, -1).reduce((current, key) => current && current[key], results) : results;
|
|
95
|
+
if (parent && Array.isArray(parent[pathParts[pathParts.length - 2]])) {
|
|
96
|
+
const arrayIndex = parseInt(lastPart);
|
|
97
|
+
parent[pathParts[pathParts.length - 2]].splice(arrayIndex, 1);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
// This is an object property, delete it
|
|
102
|
+
delObjectPath(results, meta.path.join('.'));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return results;
|
|
107
|
+
},
|
|
108
|
+
/**
|
|
109
|
+
* Helper function to safely update JSONB columns in Sequelize models
|
|
110
|
+
*
|
|
111
|
+
* @param model - The Sequelize model instance
|
|
112
|
+
* @param columnName - The name of the JSONB column to update
|
|
113
|
+
* @param obj - The object to merge with existing column data
|
|
114
|
+
*
|
|
115
|
+
* Features:
|
|
116
|
+
* - Merges new data with existing data
|
|
117
|
+
* - Removes null/undefined values recursively
|
|
118
|
+
* - Only updates if data actually changed
|
|
119
|
+
* - Handles errors gracefully
|
|
120
|
+
* - Triggers sequelize's changed method to mark the column as changed *** VERY IMPORTANT ***
|
|
121
|
+
*
|
|
122
|
+
* Usage:
|
|
123
|
+
* // In a model prototype method
|
|
124
|
+
* Account.prototype.setOptions = function(obj) {
|
|
125
|
+
* utils.setJSONBOptionsForColumn(this, "options", obj);
|
|
126
|
+
* };
|
|
127
|
+
*
|
|
128
|
+
* // Direct usage
|
|
129
|
+
* utils.setJSONBOptionsForColumn(account, "auth_options", { field: null }); // will remove the field
|
|
130
|
+
* utils.setJSONBOptionsForColumn(account, "auth_options", { field: undefined }); // will remove the field
|
|
131
|
+
* utils.setJSONBOptionsForColumn(account, "auth_options", { field: "value" }); // will set the field
|
|
132
|
+
* utils.setJSONBOptionsForColumn(account, "auth_options", { field: { subfield: "value" } }); // will set the subfield
|
|
133
|
+
* utils.setJSONBOptionsForColumn(account, "auth_options", { field: { subfield: null } }); // will remove the subfield
|
|
134
|
+
* utils.setJSONBOptionsForColumn(account, "auth_options", { field: { subfield: undefined } }); // will remove the subfield
|
|
135
|
+
* utils.setJSONBOptionsForColumn(account, "auth_options", { field: { subfield: "value" } }); // will set the subfield
|
|
136
|
+
* utils.setJSONBOptionsForColumn(account, "auth_options", { field: { subfield: null } }); // will remove the subfield
|
|
137
|
+
*/
|
|
138
|
+
setJSONBOptionsForColumn: (model, columnName, obj) => {
|
|
139
|
+
try {
|
|
140
|
+
if (!model[columnName])
|
|
141
|
+
model[columnName] = {};
|
|
142
|
+
// Merge incoming options
|
|
143
|
+
const newOptions = merge({}, model[columnName], obj);
|
|
144
|
+
// Clean null/undefined values
|
|
145
|
+
const cleaned = utils.recursiveOmitBy(newOptions, ({ node }) => node === undefined || node === null);
|
|
146
|
+
const isEqualResult = isEqual(model[columnName], cleaned);
|
|
147
|
+
if (!isEqualResult) {
|
|
148
|
+
model.set(columnName, JSON.parse(JSON.stringify(cleaned)));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch (e) {
|
|
152
|
+
logger.warn(`Error setting ${columnName}:`, e);
|
|
153
|
+
throw e;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../ts/utils/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,33 +1,73 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sera4/essentia",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.6",
|
|
4
4
|
"description": "A library of utilities for Teleporte Web Services",
|
|
5
|
-
"main": "index.js",
|
|
5
|
+
"main": "dist/ts/index.js",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"types": "dist/ts/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./dist/ts/index.js",
|
|
10
|
+
"./ts/dns": "./dist/ts/dns/index.js",
|
|
11
|
+
"./ts/logger": "./dist/ts/logger/index.js",
|
|
12
|
+
"./ts/health": "./dist/ts/health/index.js",
|
|
13
|
+
"./ts/cycle": "./dist/ts/cycle/index.js",
|
|
14
|
+
"./ts/constants": "./dist/ts/constants/index.js",
|
|
15
|
+
"./ts/utils": "./dist/ts/utils/index.js",
|
|
16
|
+
"./ts/helpers": "./dist/ts/helpers/index.js",
|
|
17
|
+
"./ts/paginator": "./dist/ts/paginator/index.js",
|
|
18
|
+
"./ts/cache": "./dist/ts/cache/index.js",
|
|
19
|
+
"./ts/prompts": "./dist/ts/prompts/index.js",
|
|
20
|
+
"./ts/safe-proxy": "./dist/ts/safe-proxy/index.js",
|
|
21
|
+
"./ts/queue": "./dist/ts/queue/index.js",
|
|
22
|
+
"./ts/last-commit": "./dist/ts/last-commit/index.js",
|
|
23
|
+
"./ts/hal": "./dist/ts/hal/index.js",
|
|
24
|
+
"./ts/formatter": "./dist/ts/formatter/index.js",
|
|
25
|
+
"./ts/serializer": "./dist/ts/serializer/index.js",
|
|
26
|
+
"./ts/paper-trail": "./dist/ts/paper-trail/index.js"
|
|
27
|
+
},
|
|
7
28
|
"scripts": {
|
|
8
|
-
"test": "NODE_ENV=test
|
|
9
|
-
"test:dev": "NODE_ENV=test
|
|
10
|
-
"test:only": "NODE_ENV=test
|
|
11
|
-
"test:pretty": "NODE_ENV=test
|
|
12
|
-
"
|
|
29
|
+
"test": "NODE_ENV=test NODE_OPTIONS='--import tsx' mocha --forbid-only --reporter mocha-junit-reporter --reporter-options mochaFile=./test-results/result.xml --exit 'test/**/*.test.ts' 'test/**/*.spec.ts' 'test/**/*.test.js' 'test/**/*.spec.js'",
|
|
30
|
+
"test:dev": "NODE_ENV=test NODE_OPTIONS='--no-warnings --loader ts-node/esm' mocha --forbid-only 'test/**/*.test.ts' 'test/**/*.spec.ts' 'test/**/*.test.js' 'test/**/*.spec.js'",
|
|
31
|
+
"test:only": "NODE_ENV=test NODE_OPTIONS='--no-warnings --loader ts-node/esm' mocha --watch 'test/**/*.test.ts' 'test/**/*.spec.ts' 'test/**/*.test.js' 'test/**/*.spec.js'",
|
|
32
|
+
"test:pretty": "NODE_ENV=test NODE_OPTIONS='--no-warnings --loader ts-node/esm' mocha --reporter mocha-simple-html-reporter --reporter-options output=./test-results/result.html --exit 'test/**/*.test.ts' 'test/**/*.spec.ts' 'test/**/*.test.js' 'test/**/*.spec.js'",
|
|
33
|
+
"test:coverage": "NODE_ENV=test NODE_OPTIONS='--no-warnings --loader ts-node/esm' c8 --all --include='ts/**/*.ts' --exclude='test/**/*.ts' --reporter=html --reporter=text --reporter=lcov mocha --forbid-only --exit 'test/**/*.test.ts' 'test/**/*.spec.ts' 'test/**/*.test.js' 'test/**/*.spec.js'",
|
|
34
|
+
"last-commit": "node last-commit.js",
|
|
35
|
+
"build": "tsc",
|
|
36
|
+
"build:watch": "tsc -w",
|
|
37
|
+
"clean": "rm -rf dist"
|
|
13
38
|
},
|
|
14
39
|
"author": "Dev DM <dev@sera4.com>",
|
|
15
40
|
"repository": {
|
|
16
41
|
"type": "git",
|
|
17
|
-
"url": "git@bitbucket.org
|
|
42
|
+
"url": "git+ssh://git@bitbucket.org/lockedup/essentia.git"
|
|
18
43
|
},
|
|
19
44
|
"license": "UNLICENSED",
|
|
20
45
|
"devDependencies": {
|
|
21
|
-
"
|
|
46
|
+
"@types/argparse": "^2.0.17",
|
|
47
|
+
"@types/chai": "^4.3.11",
|
|
48
|
+
"@types/express": "^4.17.21",
|
|
49
|
+
"@types/lodash": "^4.17.20",
|
|
50
|
+
"@types/mocha": "^10.0.10",
|
|
51
|
+
"@types/morgan": "^1.9.9",
|
|
52
|
+
"@types/node": "^20.17.32",
|
|
53
|
+
"@types/prompt": "^1.1.9",
|
|
54
|
+
"@types/sinon": "^10.0.20",
|
|
55
|
+
"@types/sinon-chai": "^4.0.0",
|
|
56
|
+
"c8": "^8.0.1",
|
|
57
|
+
"chai": "^5.2.0",
|
|
22
58
|
"express": "^4.17.1",
|
|
23
59
|
"mocha": "^11.1.0",
|
|
24
60
|
"mocha-junit-reporter": "^2.2.1",
|
|
25
61
|
"node-mocks-http": "^1.16.2",
|
|
26
62
|
"should": "^13.2.3",
|
|
27
|
-
"sinon": "^5.1.1"
|
|
63
|
+
"sinon": "^5.1.1",
|
|
64
|
+
"sinon-chai": "^4.0.0",
|
|
65
|
+
"ts-node": "^10.9.2",
|
|
66
|
+
"tsx": "^4.20.5",
|
|
67
|
+
"typescript": "^5.3.3"
|
|
28
68
|
},
|
|
29
69
|
"dependencies": {
|
|
30
|
-
"amqplib": "^0.
|
|
70
|
+
"amqplib": "^0.10.7",
|
|
31
71
|
"argparse": "^2.0.1",
|
|
32
72
|
"async": "^3.2.2",
|
|
33
73
|
"axios": "^1.7.7",
|
|
@@ -38,6 +78,7 @@
|
|
|
38
78
|
"lodash": "^4.17.21",
|
|
39
79
|
"morgan": "^1.10.0",
|
|
40
80
|
"prompt": "^1.3.0",
|
|
81
|
+
"recursive-iterator": "^3.3.0",
|
|
41
82
|
"url-parse": "^1.5.10",
|
|
42
83
|
"uuid": "^9.0.0",
|
|
43
84
|
"winston": "^3.3.3",
|