@sera4/essentia 1.1.64 → 1.1.66-rc.1
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/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/configurations/index.html +116 -0
- package/coverage/configurations/server-config.ts.html +94 -0
- package/coverage/dns/DnsCache.ts.html +598 -0
- package/coverage/dns/index.html +131 -0
- package/coverage/dns/index.ts.html +94 -0
- package/coverage/favicon.png +0 -0
- package/coverage/health/index.html +116 -0
- package/coverage/health/index.ts.html +778 -0
- package/coverage/index.html +161 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/configurations/index.html +116 -0
- package/coverage/lcov-report/configurations/server-config.ts.html +94 -0
- package/coverage/lcov-report/dns/DnsCache.ts.html +598 -0
- package/coverage/lcov-report/dns/index.html +131 -0
- package/coverage/lcov-report/dns/index.ts.html +94 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/health/index.html +116 -0
- package/coverage/lcov-report/health/index.ts.html +778 -0
- package/coverage/lcov-report/index.html +161 -0
- package/coverage/lcov-report/logger/index.html +131 -0
- package/coverage/lcov-report/logger/index.ts.html +94 -0
- package/coverage/lcov-report/logger/s4-logger.ts.html +514 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +196 -0
- package/coverage/lcov.info +747 -0
- package/coverage/logger/index.html +131 -0
- package/coverage/logger/index.ts.html +94 -0
- package/coverage/logger/s4-logger.ts.html +514 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +196 -0
- package/coverage/tmp/coverage-24302-1746472691313-0.json +1 -0
- package/coverage/tmp/coverage-24302-1746472691366-1.json +1 -0
- package/dist/cache/index.d.ts +22 -0
- package/dist/cache/index.js +166 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/constants/index.d.ts +6 -0
- package/dist/constants/index.js +9 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/coverage/block-navigation.d.ts +1 -0
- package/dist/coverage/block-navigation.js +70 -0
- package/dist/coverage/block-navigation.js.map +1 -0
- package/dist/coverage/lcov-report/block-navigation.d.ts +1 -0
- package/dist/coverage/lcov-report/block-navigation.js +70 -0
- package/dist/coverage/lcov-report/block-navigation.js.map +1 -0
- package/dist/coverage/lcov-report/prettify.d.ts +0 -0
- package/dist/coverage/lcov-report/prettify.js +477 -0
- package/dist/coverage/lcov-report/prettify.js.map +1 -0
- package/dist/coverage/lcov-report/sorter.d.ts +1 -0
- package/dist/coverage/lcov-report/sorter.js +163 -0
- package/dist/coverage/lcov-report/sorter.js.map +1 -0
- package/dist/coverage/prettify.d.ts +0 -0
- package/dist/coverage/prettify.js +477 -0
- package/dist/coverage/prettify.js.map +1 -0
- package/dist/coverage/sorter.d.ts +1 -0
- package/dist/coverage/sorter.js +163 -0
- package/dist/coverage/sorter.js.map +1 -0
- package/dist/formatter/index.d.ts +37 -0
- package/dist/formatter/index.js +75 -0
- package/dist/formatter/index.js.map +1 -0
- package/dist/hal/index.d.ts +5 -0
- package/dist/hal/index.js +69 -0
- package/dist/hal/index.js.map +1 -0
- package/dist/health/health-logger.d.ts +9 -0
- package/dist/health/health-logger.js +34 -0
- package/dist/health/health-logger.js.map +1 -0
- package/dist/health/index.d.ts +19 -0
- package/dist/health/index.js +175 -0
- package/dist/health/index.js.map +1 -0
- package/dist/helpers/index.d.ts +1 -0
- package/dist/helpers/index.js +2 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/helpers/test-server-wrapper.d.ts +120 -0
- package/dist/helpers/test-server-wrapper.js +165 -0
- package/dist/helpers/test-server-wrapper.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/last-commit.d.ts +1 -0
- package/dist/last-commit.js +12 -0
- package/dist/last-commit.js.map +1 -0
- package/dist/last_commit/index.d.ts +7 -0
- package/dist/last_commit/index.js +83 -0
- package/dist/last_commit/index.js.map +1 -0
- package/dist/paginator/s4-pagination.d.ts +9 -0
- package/dist/paginator/s4-pagination.js +49 -0
- package/dist/paginator/s4-pagination.js.map +1 -0
- package/dist/paginator/sql-pagination.d.ts +27 -0
- package/dist/paginator/sql-pagination.js +166 -0
- package/dist/paginator/sql-pagination.js.map +1 -0
- package/dist/paper-trail/helpers.d.ts +11 -0
- package/dist/paper-trail/helpers.js +74 -0
- package/dist/paper-trail/helpers.js.map +1 -0
- package/dist/paper-trail/index.d.ts +13 -0
- package/dist/paper-trail/index.js +662 -0
- package/dist/paper-trail/index.js.map +1 -0
- package/dist/prompts/index.d.ts +14 -0
- package/dist/prompts/index.js +63 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/queue/index.d.ts +166 -0
- package/dist/queue/index.js +371 -0
- package/dist/queue/index.js.map +1 -0
- package/dist/queue/publisher.d.ts +31 -0
- package/dist/queue/publisher.js +84 -0
- package/dist/queue/publisher.js.map +1 -0
- package/dist/queue/queue-logger.d.ts +9 -0
- package/dist/queue/queue-logger.js +35 -0
- package/dist/queue/queue-logger.js.map +1 -0
- package/dist/queue/subscriber.d.ts +39 -0
- package/dist/queue/subscriber.js +97 -0
- package/dist/queue/subscriber.js.map +1 -0
- package/dist/safe_proxy/index.d.ts +13 -0
- package/dist/safe_proxy/index.js +54 -0
- package/dist/safe_proxy/index.js.map +1 -0
- package/dist/serializer/index.d.ts +5 -0
- package/dist/serializer/index.js +83 -0
- package/dist/serializer/index.js.map +1 -0
- package/dist/test/debug-array.d.ts +0 -0
- package/dist/test/debug-array.js +1 -0
- package/dist/test/debug-array.js.map +1 -0
- package/dist/test/debug-setJSONB.d.ts +0 -0
- package/dist/test/debug-setJSONB.js +1 -0
- package/dist/test/debug-setJSONB.js.map +1 -0
- package/dist/test/prompt.test.d.ts +1 -0
- package/dist/test/prompt.test.js +74 -0
- package/dist/test/prompt.test.js.map +1 -0
- package/dist/test/s4-formatter.spec.d.ts +1 -0
- package/dist/test/s4-formatter.spec.js +67 -0
- package/dist/test/s4-formatter.spec.js.map +1 -0
- package/dist/test/s4-pagination.spec.d.ts +1 -0
- package/dist/test/s4-pagination.spec.js +170 -0
- package/dist/test/s4-pagination.spec.js.map +1 -0
- package/dist/test/safe-proxy.spec.d.ts +1 -0
- package/dist/test/safe-proxy.spec.js +252 -0
- package/dist/test/safe-proxy.spec.js.map +1 -0
- package/dist/test/serializer.spec.d.ts +1 -0
- package/dist/test/serializer.spec.js +27 -0
- package/dist/test/serializer.spec.js.map +1 -0
- package/dist/test/utils.spec.d.ts +1 -0
- package/dist/test/utils.spec.js +446 -0
- package/dist/test/utils.spec.js.map +1 -0
- 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/dist/ts/constants/index.js +8 -0
- 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 +22 -0
- package/dist/ts/index.js +27 -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 +105 -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 +232 -0
- package/dist/ts/queue/index.js +440 -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/task-scheduler/index.d.ts +130 -0
- package/dist/ts/task-scheduler/index.js +259 -0
- package/dist/ts/task-scheduler/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 +10 -8
- package/paper-trail/index.js +36 -28
- package/queue/index.js +57 -69
- package/scripts/publish.sh +46 -0
- package/test/health.spec.js +213 -0
- package/test/prompt.test.js +91 -0
- package/test/s4-formatter.spec.js +80 -0
- package/test/s4-pagination.spec.js +196 -0
- package/test/serializer.spec.js +34 -0
- package/test/utils.spec.js +145 -0
- package/package.tar.gz +0 -0
package/paper-trail/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { createRequire } from 'module';
|
|
2
|
+
const jsdiff = createRequire(import.meta.url)('diff');
|
|
2
3
|
import _ from 'lodash';
|
|
3
4
|
import helpers from './helpers.js';
|
|
4
5
|
import paginator from "../paginator/sql-pagination.js";
|
|
@@ -297,35 +298,42 @@ paperTrail.init = (sequelize, sequelizePackage, optionsArg) => {
|
|
|
297
298
|
);
|
|
298
299
|
}
|
|
299
300
|
|
|
300
|
-
|
|
301
|
-
//
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
301
|
+
// For create/restore, keep full currentVersion (including JSONB/plain objects) so
|
|
302
|
+
// the revision document has complete newValues. For update, blank object values
|
|
303
|
+
// and repopulate only from delta so we store minimal nested changes.
|
|
304
|
+
const blankObjectsAndApplyDelta = !createOperation && !restoreOperation;
|
|
305
|
+
|
|
306
|
+
if (blankObjectsAndApplyDelta) {
|
|
307
|
+
let objectsChanged = new Set();
|
|
308
|
+
// if the previous version or new version contain objects; push them onto this list
|
|
309
|
+
_.forEach(previousVersion, (value, key) => {
|
|
310
|
+
if (typeof(value) === 'object' ) {
|
|
311
|
+
objectsChanged.add(key);
|
|
312
|
+
// blank it so we can set it equal to ONLY the values changed in the next segment
|
|
313
|
+
previousVersion[key] = {};
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
_.forEach(currentVersion, (value, key) => {
|
|
317
|
+
if (typeof(value) === 'object' ) {
|
|
318
|
+
objectsChanged.add(key);
|
|
319
|
+
currentVersion[key] = {};
|
|
320
|
+
}
|
|
321
|
+
});
|
|
315
322
|
|
|
316
323
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
324
|
+
// we don't want to see a full object; we want to see only
|
|
325
|
+
// x.y.z -> value
|
|
326
|
+
if (delta && objectsChanged.size > 0 ) {
|
|
327
|
+
// the format of these are A,E,D,N (added, edited, deleted, new) for the kind
|
|
328
|
+
// the array is either the key or key + subkeys ['options','subkey','subkey2'] etc.
|
|
329
|
+
// {kind: 'E', path: Array(2), lhs: false, rhs: true}
|
|
330
|
+
for (const difference of delta) {
|
|
331
|
+
// blank the currentVersion[difference.path[0]]
|
|
332
|
+
// and previousVersion[difference.path[0]]
|
|
333
|
+
_.set(currentVersion, difference.path, difference.rhs);
|
|
334
|
+
_.set(previousVersion, difference.path, difference.lhs);
|
|
335
|
+
};
|
|
336
|
+
}
|
|
329
337
|
}
|
|
330
338
|
|
|
331
339
|
let document;
|
package/queue/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
import amqp from "amqplib
|
|
2
|
+
import amqp from "amqplib";
|
|
3
3
|
import logger from "./queue-logger.js";
|
|
4
4
|
import urlParse from "url-parse";
|
|
5
5
|
import { Publisher } from "./publisher.js";
|
|
@@ -11,6 +11,7 @@ import { Subscriber } from "./subscriber.js";
|
|
|
11
11
|
class S4Queue {
|
|
12
12
|
constructor() {
|
|
13
13
|
this.connection = null;
|
|
14
|
+
this.connectionTestChannel = null;
|
|
14
15
|
this.retry = 10;
|
|
15
16
|
this.pubs = {};
|
|
16
17
|
this.subs = {};
|
|
@@ -30,15 +31,20 @@ class S4Queue {
|
|
|
30
31
|
async testConnection() {
|
|
31
32
|
if (!this.isConnected()) {
|
|
32
33
|
this.connectionTestChannel = null;
|
|
33
|
-
throw("queue service not connected")
|
|
34
|
+
throw new Error("queue service not connected");
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
this.connectionTestChannel = this.connectionTestChannel || await this.connection.createChannel();
|
|
37
37
|
if (!this.connectionTestChannel) {
|
|
38
|
-
|
|
38
|
+
const ch = await this.connection.createChannel();
|
|
39
|
+
if (!ch) {
|
|
40
|
+
throw new Error("queue service failed to obtain a channel");
|
|
41
|
+
}
|
|
42
|
+
ch.on("error", () => { this.connectionTestChannel = null; });
|
|
43
|
+
ch.on("close", () => { this.connectionTestChannel = null; });
|
|
44
|
+
this.connectionTestChannel = ch;
|
|
39
45
|
}
|
|
40
46
|
|
|
41
|
-
await this.connectionTestChannel.assertExchange("--health-check--", "topic", {durable: false});
|
|
47
|
+
await this.connectionTestChannel.assertExchange("--health-check--", "topic", { durable: false });
|
|
42
48
|
}
|
|
43
49
|
|
|
44
50
|
/**
|
|
@@ -56,60 +62,51 @@ class S4Queue {
|
|
|
56
62
|
const retry = parseInt(options.retryInterval);
|
|
57
63
|
this.retry = retry || 10;
|
|
58
64
|
|
|
59
|
-
|
|
65
|
+
// We may run into issues with SNI TLS if
|
|
66
|
+
// we host with 3rd parties using our own certs.
|
|
67
|
+
// To avoid any issues, let's parse the url
|
|
68
|
+
// and provide the server name in the socket options
|
|
69
|
+
const urlParts = urlParse(options.connectionUrl);
|
|
70
|
+
const socketOptions = { servername: urlParts.hostname };
|
|
60
71
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
// We may run into issues with SNI TLS if
|
|
67
|
-
// we host with 3rd parties using our own certs.
|
|
68
|
-
// To avoid any issues, let's parse the url
|
|
69
|
-
// and provide the server name in the socket options
|
|
70
|
-
const urlParts = urlParse(options.connectionUrl);
|
|
71
|
-
const socketOptions = {servername: urlParts.hostname};
|
|
72
|
+
return new Promise((resolve) => {
|
|
73
|
+
const attempt = async () => {
|
|
74
|
+
logger.debug("Attempting connection...");
|
|
75
|
+
try {
|
|
76
|
+
const conn = await amqp.connect(options.connectionUrl, socketOptions);
|
|
72
77
|
|
|
73
|
-
|
|
78
|
+
this.connection = conn;
|
|
79
|
+
this.updatePubsAndSubsConnectionRef(conn);
|
|
74
80
|
|
|
75
|
-
|
|
76
|
-
|
|
81
|
+
this.connection.on("error", (err) => {
|
|
82
|
+
logger.error("connection error", err);
|
|
83
|
+
// Do not attempt to reconnect as the
|
|
84
|
+
// 'close' event will also be emitted
|
|
85
|
+
// if this error closes the connection
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
this.connection.on("close", (err) => {
|
|
89
|
+
logger.error("connection closed");
|
|
90
|
+
this.connection = null;
|
|
91
|
+
this.connectionTestChannel = null;
|
|
92
|
+
if (err) {
|
|
93
|
+
logger.error("connection closed due to error:", err);
|
|
94
|
+
logger.error("Reconnecting in", this.retry, "seconds");
|
|
95
|
+
setTimeout(attempt, this.retry * 1000);
|
|
96
|
+
} else {
|
|
97
|
+
logger.debug("Will not re-attempt");
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
logger.debug("Connected");
|
|
102
|
+
resolve();
|
|
103
|
+
} catch (err) {
|
|
104
|
+
logger.error("Error while connecting", err);
|
|
77
105
|
logger.error("Attempting again in", this.retry, "seconds");
|
|
78
|
-
|
|
106
|
+
setTimeout(attempt, this.retry * 1000);
|
|
79
107
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (!this.connection) {
|
|
83
|
-
return reject(new Error("Failed to obtain connection"));
|
|
84
|
-
} else {
|
|
85
|
-
this.updatePubsAndSubsConnectionRef(conn);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
this.connection.on("error", (err) => {
|
|
89
|
-
logger.error("connection error", err);
|
|
90
|
-
// Do not attempt to reconnect as the
|
|
91
|
-
// 'close' event will also be emitted
|
|
92
|
-
// if this error closes the connection
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
this.connection.on("close", (err) => {
|
|
96
|
-
logger.error("connection closed");
|
|
97
|
-
this.connection = null;
|
|
98
|
-
if (err) {
|
|
99
|
-
logger.error("connection closed due to error:", err);
|
|
100
|
-
logger.error("Reconnecting in", this.retry, "seconds");
|
|
101
|
-
setTimeout(() => this.openConnection(options), this.retry * 1000);
|
|
102
|
-
} else {
|
|
103
|
-
// If there was no error, it is us who closed
|
|
104
|
-
// this connection, thus a reconnection will not
|
|
105
|
-
// be attempted.
|
|
106
|
-
logger.debug("Will not re-attempt");
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
logger.debug("Connected");
|
|
111
|
-
resolve();
|
|
112
|
-
});
|
|
108
|
+
};
|
|
109
|
+
attempt();
|
|
113
110
|
});
|
|
114
111
|
}
|
|
115
112
|
|
|
@@ -119,21 +116,12 @@ class S4Queue {
|
|
|
119
116
|
* and subscribers
|
|
120
117
|
*/
|
|
121
118
|
async closeConnection() {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
reject(err);
|
|
129
|
-
} else {
|
|
130
|
-
this.subs = {};
|
|
131
|
-
this.pubs = {};
|
|
132
|
-
this.connection = null;
|
|
133
|
-
resolve();
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
});
|
|
119
|
+
if (!this.connection) return;
|
|
120
|
+
await this.connection.close();
|
|
121
|
+
this.subs = {};
|
|
122
|
+
this.pubs = {};
|
|
123
|
+
this.connectionTestChannel = null;
|
|
124
|
+
this.connection = null;
|
|
137
125
|
}
|
|
138
126
|
|
|
139
127
|
/**
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
5
|
+
cd "$ROOT"
|
|
6
|
+
|
|
7
|
+
# ── Version resolution ────────────────────────────────────────────────────────
|
|
8
|
+
VERSION="${BUILD_VERSION:-}"
|
|
9
|
+
|
|
10
|
+
if [ -z "$VERSION" ]; then
|
|
11
|
+
VERSION=$(node -p "require('./package.json').version")
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
if [ -z "$VERSION" ] || [ "$VERSION" = "0.0.0" ]; then
|
|
15
|
+
echo "error: no version specified — set BUILD_VERSION or package.json version" >&2
|
|
16
|
+
exit 1
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
PACKAGE=$(node -p "require('./package.json').name")
|
|
20
|
+
echo "publishing $PACKAGE@$VERSION"
|
|
21
|
+
|
|
22
|
+
# ── Stamp version, restore on exit ───────────────────────────────────────────
|
|
23
|
+
ORIGINAL_VERSION=$(node -p "require('./package.json').version")
|
|
24
|
+
restore_version() {
|
|
25
|
+
npm pkg set version="$ORIGINAL_VERSION" --silent
|
|
26
|
+
}
|
|
27
|
+
trap restore_version EXIT
|
|
28
|
+
|
|
29
|
+
npm pkg set version="$VERSION" --silent
|
|
30
|
+
|
|
31
|
+
# ── Build ─────────────────────────────────────────────────────────────────────
|
|
32
|
+
echo "building..."
|
|
33
|
+
npm run build
|
|
34
|
+
|
|
35
|
+
# ── Dist-tag: prerelease versions get 'next', stable versions get 'latest' ───
|
|
36
|
+
if [[ "$VERSION" =~ -[a-zA-Z] ]]; then
|
|
37
|
+
DIST_TAG="next"
|
|
38
|
+
else
|
|
39
|
+
DIST_TAG="latest"
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# ── Publish ───────────────────────────────────────────────────────────────────
|
|
43
|
+
echo "publishing with tag: $DIST_TAG"
|
|
44
|
+
npm publish --access public --tag "$DIST_TAG"
|
|
45
|
+
|
|
46
|
+
echo "done: $PACKAGE@$VERSION"
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { expect, should as chaiShould } from "chai";
|
|
2
|
+
import sinon from "sinon";
|
|
3
|
+
import express from "express";
|
|
4
|
+
import { healthCheck as hc } from "../index.js";
|
|
5
|
+
|
|
6
|
+
const should = chaiShould();
|
|
7
|
+
|
|
8
|
+
const mockResponse = () => {
|
|
9
|
+
const res = {};
|
|
10
|
+
res.status = sinon.stub().returns(res);
|
|
11
|
+
res.setHeader = sinon.stub();
|
|
12
|
+
res.json = sinon.stub().returns(res);
|
|
13
|
+
res.send = sinon.spy();
|
|
14
|
+
return res;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/* algorithm for shuffling an array */
|
|
18
|
+
const shuffle = (a) => {
|
|
19
|
+
for (let i = a.length - 1; i > 0; i--) {
|
|
20
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
21
|
+
[a[i], a[j]] = [a[j], a[i]];
|
|
22
|
+
}
|
|
23
|
+
return a;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe("HealthCheck Testing", () => {
|
|
27
|
+
let healthCheck = new hc();
|
|
28
|
+
|
|
29
|
+
describe("Health Check Sanity", () => {
|
|
30
|
+
it ("Should have NO predefined health checks", () => {
|
|
31
|
+
return expect(healthCheck.healthChecks).to.be.an('array').that.is.empty;
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it ("Should have have a sane default path route", () => {
|
|
35
|
+
return expect(healthCheck.defaultPath()).to.match(/health_check/);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it ("Should have have sane response defaults", () => {
|
|
39
|
+
expect(healthCheck.defaultResponse).to.have.property("status", 200);
|
|
40
|
+
expect(healthCheck.defaultResponse).to.have.property("errors").to.be.an('object').to.be.empty;
|
|
41
|
+
})
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe("Health Check Router", () => {
|
|
45
|
+
it ("Should throw without a proper router object", () => {
|
|
46
|
+
expect(healthCheck.routes.bind(healthCheck)).to.throw('missing_express_router');
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it ("Should return a proper router object with an improved route", () => {
|
|
50
|
+
let router = express.Router();
|
|
51
|
+
let improved_router = healthCheck.routes(router);
|
|
52
|
+
expect(improved_router).to.equal(router);
|
|
53
|
+
})
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe("Check Health Checks", () => {
|
|
57
|
+
let req, res;
|
|
58
|
+
|
|
59
|
+
beforeEach("Setup hc object", () => {
|
|
60
|
+
res = mockResponse();
|
|
61
|
+
req = { baseUrl: "server.example.com/api/health_check.json" };
|
|
62
|
+
healthCheck = new hc();
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it ("Returns ok with no additional health check routes defined", (done) => {
|
|
66
|
+
req = { baseUrl: "server.example.com/api/health_check.json" };
|
|
67
|
+
|
|
68
|
+
const expectedResult = { check: 1, healthy: "true", message: "success" }
|
|
69
|
+
|
|
70
|
+
healthCheck.checkHealth(req, res)
|
|
71
|
+
.then((r) => {
|
|
72
|
+
sinon.assert.alwaysCalledWith(res.status, 200);
|
|
73
|
+
sinon.assert.calledOnce(res.status);
|
|
74
|
+
sinon.assert.alwaysCalledWith(res.json, expectedResult)
|
|
75
|
+
done()
|
|
76
|
+
});
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it("Returns success with a simple successful (v1) health check defined", (done) => {
|
|
80
|
+
const sampleCheck = async () => {
|
|
81
|
+
return { name: "db", "result": "success", critical: false };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
healthCheck.addCheck(sampleCheck);
|
|
85
|
+
expect(healthCheck.healthChecks).to.be.an('array').with.lengthOf(1);
|
|
86
|
+
|
|
87
|
+
const expectedResult = { check: 1, healthy: "true", message: "success" }
|
|
88
|
+
healthCheck.checkHealth(req, res)
|
|
89
|
+
.then((r) => {
|
|
90
|
+
sinon.assert.alwaysCalledWith(res.status, 200);
|
|
91
|
+
sinon.assert.alwaysCalledWith(res.json, expectedResult);
|
|
92
|
+
done()
|
|
93
|
+
});
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it("Returns fail with a failed health check", (done) => {
|
|
97
|
+
const sampleCheck = async () => {
|
|
98
|
+
return { name: "db", "result": "fail" };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
healthCheck.addCheck(sampleCheck);
|
|
102
|
+
expect(healthCheck.healthChecks).to.be.an('array').with.lengthOf(1);
|
|
103
|
+
|
|
104
|
+
const expectedResult = { check: 1, healthy: "false", message: "fail" }
|
|
105
|
+
healthCheck.checkHealth(req, res)
|
|
106
|
+
.then(e => { done() })
|
|
107
|
+
.catch(err => {
|
|
108
|
+
sinon.assert.alwaysCalledWith(res.status, 500);
|
|
109
|
+
sinon.assert.alwaysCalledWith(res.json, expectedResult);
|
|
110
|
+
done()
|
|
111
|
+
})
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
it("Returns unhealthy with an OK and failed health check", (done) => {
|
|
115
|
+
const sampleFail = async () => {
|
|
116
|
+
return { name: "db", "result": "fail" };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const sampleSuccess= async () => {
|
|
120
|
+
return { name: "redis", "result": "success" };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
shuffle([sampleFail, sampleSuccess]).forEach(el => {
|
|
124
|
+
healthCheck.addCheck(el);
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
expect(healthCheck.healthChecks).to.be.an('array').with.lengthOf(2);
|
|
128
|
+
|
|
129
|
+
healthCheck.checkHealth(req, res)
|
|
130
|
+
.then(e => { done() })
|
|
131
|
+
.catch(err => {
|
|
132
|
+
sinon.assert.alwaysCalledWith(res.status, 500);
|
|
133
|
+
sinon.assert.alwaysCalledWith(res.json, 'fail');
|
|
134
|
+
done()
|
|
135
|
+
})
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
it("Returns healthy/200 when non-critical element fails (v2)", async () => {
|
|
139
|
+
const sampleCheck= async () => { throw new Error({status: 500}) }
|
|
140
|
+
|
|
141
|
+
healthCheck.setupCheck({ name: "sample", critical: false, healthFunction: sampleCheck });
|
|
142
|
+
expect(healthCheck.healthChecks).to.be.an('array').with.lengthOf(1);
|
|
143
|
+
|
|
144
|
+
await healthCheck.checkHealth(req, res)
|
|
145
|
+
|
|
146
|
+
sinon.assert.alwaysCalledWith(res.status, 200);
|
|
147
|
+
|
|
148
|
+
const expectedResult = {
|
|
149
|
+
check: 1,
|
|
150
|
+
healthy: "true",
|
|
151
|
+
message: "fail",
|
|
152
|
+
services: [{ critical: false, name: "sample", result: "fail", status: undefined }]
|
|
153
|
+
}
|
|
154
|
+
sinon.assert.alwaysCalledWith(res.json, expectedResult);
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
it("Returns unhealthy/500 when a critical component returns failure (v2)", async () => {
|
|
158
|
+
const sampleCheck= async () => { throw new Error({status: 500}) }
|
|
159
|
+
|
|
160
|
+
healthCheck.setupCheck({ name: "sample", critical: true, healthFunction: sampleCheck });
|
|
161
|
+
expect(healthCheck.healthChecks).to.be.an('array').with.lengthOf(1);
|
|
162
|
+
|
|
163
|
+
await healthCheck.checkHealth(req, res)
|
|
164
|
+
|
|
165
|
+
const expectedResult = {
|
|
166
|
+
check: 1, healthy: false,
|
|
167
|
+
message: "fail",
|
|
168
|
+
services: [{ critical: true, name: "sample", result: "fail", status: undefined }]
|
|
169
|
+
}
|
|
170
|
+
sinon.assert.alwaysCalledWith(res.status, 500);
|
|
171
|
+
sinon.assert.alwaysCalledWith(res.json, expectedResult);
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
it("Returns unhealthy/500 when a critical component returns failure (v2)", async () => {
|
|
175
|
+
const sampleCheck= async () => { throw new Error({status: 500}) }
|
|
176
|
+
const sampleCheck2= async () => { return true }
|
|
177
|
+
|
|
178
|
+
healthCheck.setupCheck({ name: "sample", critical: true, healthFunction: sampleCheck });
|
|
179
|
+
healthCheck.setupCheck({ name: "sample2", critical: true, healthFunction: sampleCheck2 });
|
|
180
|
+
expect(healthCheck.healthChecks).to.be.an('array').with.lengthOf(2);
|
|
181
|
+
|
|
182
|
+
await healthCheck.checkHealth(req, res)
|
|
183
|
+
|
|
184
|
+
const expectedResult = {
|
|
185
|
+
check: 1, healthy: false,
|
|
186
|
+
message: "fail",
|
|
187
|
+
services: [
|
|
188
|
+
{ critical: true, name: "sample", result: "fail", status: undefined },
|
|
189
|
+
{ critical: true, name: "sample2", result: "success" }]
|
|
190
|
+
}
|
|
191
|
+
sinon.assert.alwaysCalledWith(res.status, 500);
|
|
192
|
+
sinon.assert.alwaysCalledWith(res.json, expectedResult);
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
it("Returns a different ID each time it runscheck", (done) => {
|
|
196
|
+
let req2, res2;
|
|
197
|
+
res2 = mockResponse();
|
|
198
|
+
|
|
199
|
+
req = { baseUrl: "server.example.com/api/health_check.json" };
|
|
200
|
+
req2 = req
|
|
201
|
+
|
|
202
|
+
healthCheck.checkHealth(req, res)
|
|
203
|
+
.then(() => {
|
|
204
|
+
expect(healthCheck.lastCallId).to.equal(1)
|
|
205
|
+
healthCheck.checkHealth(req2, res2)
|
|
206
|
+
.then(() => {
|
|
207
|
+
expect(healthCheck.lastCallId).to.equal(2)
|
|
208
|
+
done()
|
|
209
|
+
})
|
|
210
|
+
})
|
|
211
|
+
})
|
|
212
|
+
})
|
|
213
|
+
});
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { expect } from "chai";
|
|
2
|
+
import sinon from "sinon";
|
|
3
|
+
import prompt from "prompt";
|
|
4
|
+
import { ArgumentParser } from 'argparse';
|
|
5
|
+
import logger from "../logger/s4-logger.js";
|
|
6
|
+
|
|
7
|
+
import { setupCLIParser, cliSleep, promptCLIAsync, commonCLIInit, waitCLIPrompt, continueCLIPrompt } from "../prompts/index.js";
|
|
8
|
+
|
|
9
|
+
describe("Prompt Functions", () => {
|
|
10
|
+
describe("Setup Parser", () => {
|
|
11
|
+
let loggerStub;
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
loggerStub = sinon.stub(logger, "info");
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
loggerStub.restore();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("should create an ArgumentParser with the given description", () => {
|
|
22
|
+
const description = "Test Description";
|
|
23
|
+
const parser = setupCLIParser(description);
|
|
24
|
+
|
|
25
|
+
expect(parser).to.be.instanceOf(ArgumentParser);
|
|
26
|
+
expect(loggerStub.calledWith(description)).to.be.true;
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
describe("cliSleep", () => {
|
|
31
|
+
it("should return a promise that resolves after the specified time", async () => {
|
|
32
|
+
const clock = sinon.useFakeTimers();
|
|
33
|
+
const ms = 1000;
|
|
34
|
+
|
|
35
|
+
const promise = cliSleep(ms);
|
|
36
|
+
clock.tick(ms);
|
|
37
|
+
|
|
38
|
+
await promise;
|
|
39
|
+
clock.restore();
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe("Prompt Async", () => {
|
|
44
|
+
let promptStub;
|
|
45
|
+
|
|
46
|
+
beforeEach(() => {
|
|
47
|
+
promptStub = sinon.stub(prompt, "get");
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
afterEach(() => {
|
|
51
|
+
promptStub.restore();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("should resolve with response when prompt succeeds", async () => {
|
|
55
|
+
const options = { name: "test" };
|
|
56
|
+
const mockResponse = { name: "response" };
|
|
57
|
+
|
|
58
|
+
promptStub.yields(null, mockResponse);
|
|
59
|
+
|
|
60
|
+
const result = await promptCLIAsync(options);
|
|
61
|
+
expect(result).to.equal(mockResponse);
|
|
62
|
+
expect(promptStub.calledWith(options)).to.be.true;
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("should reject with error when prompt fails", async () => {
|
|
66
|
+
const options = { name: "test" };
|
|
67
|
+
const mockError = new Error("Prompt error");
|
|
68
|
+
|
|
69
|
+
promptStub.yields(mockError, null);
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
await promptCLIAsync(options);
|
|
73
|
+
expect.fail("Should have thrown an error");
|
|
74
|
+
} catch (error) {
|
|
75
|
+
expect(error).to.equal(mockError);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
describe("Prompt Objects", () => {
|
|
81
|
+
it("should define waitPrompt with correct structure", () => {
|
|
82
|
+
expect(waitCLIPrompt).to.have.property("Push <enter> when done");
|
|
83
|
+
expect(waitCLIPrompt["Push <enter> when done"]).to.have.property("type", "boolean");
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("should define continuePrompt with correct structure", () => {
|
|
87
|
+
expect(continueCLIPrompt).to.have.property("Push <enter> to continue");
|
|
88
|
+
expect(continueCLIPrompt["Push <enter> to continue"]).to.have.property("type", "boolean");
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import should from "should";
|
|
2
|
+
import { expect as expect } from "chai";
|
|
3
|
+
|
|
4
|
+
import S4Formatter from "../formatter/index.js";
|
|
5
|
+
|
|
6
|
+
describe("Formatter", function () {
|
|
7
|
+
let response;
|
|
8
|
+
|
|
9
|
+
describe("Sending legacy format []", function () {
|
|
10
|
+
before("Setup", function () {
|
|
11
|
+
const error = { status: 200, error: ["error1"] }
|
|
12
|
+
response = S4Formatter.formatError(error);
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
describe("Default values", function () {
|
|
16
|
+
it("should have a generic error", function () {
|
|
17
|
+
response.should.have.property("errors");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("should have error code set correctly", function () {
|
|
21
|
+
response.should.have.property("status", 200);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe("Support null error payloads", function () {
|
|
27
|
+
before("Setup", function () {
|
|
28
|
+
response = S4Formatter.formatError(null);
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
describe("Default values", function () {
|
|
32
|
+
it("Should have a default error level and blank errors", function () {
|
|
33
|
+
expect(response).to.have.property("status",422);
|
|
34
|
+
expect(response).to.have.property("errors").to.be.empty;
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe("Should not fold in funky keys/values", function () {
|
|
41
|
+
before("Setup", function () {
|
|
42
|
+
response = S4Formatter.formatError({randomKey: 123});
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
describe("Default values", function () {
|
|
46
|
+
it("Should not funky key name folded in", function () {
|
|
47
|
+
response.should.not.have.property("randomKey", {});
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe("Support validator formats", function () {
|
|
53
|
+
before("Setup", function () {
|
|
54
|
+
let error = {
|
|
55
|
+
"status": 422,
|
|
56
|
+
"errors": {
|
|
57
|
+
"password": {
|
|
58
|
+
"location": "body",
|
|
59
|
+
"param": "password",
|
|
60
|
+
"value": "badPassw0rd",
|
|
61
|
+
"msg": "weak"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
response = S4Formatter.formatError(error);
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
describe("Default values", function () {
|
|
70
|
+
it("Should have a default error level and blank errors", function () {
|
|
71
|
+
response.should.have.property("status", 422);
|
|
72
|
+
expect(response).to.be.an("object");
|
|
73
|
+
expect(response).to.have.property('errors');
|
|
74
|
+
expect(Object.keys(response['errors'])).to.have.lengthOf('1')
|
|
75
|
+
response.should.have.property("errors");
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
})
|