@blamejs/core 0.7.18 → 0.7.20
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/CHANGELOG.md +427 -423
- package/README.md +150 -150
- package/bin/blamejs.js +0 -0
- package/index.js +310 -308
- package/lib/api-key.js +660 -660
- package/lib/api-snapshot.js +338 -338
- package/lib/app-shutdown.js +385 -385
- package/lib/app.js +365 -365
- package/lib/archive.js +250 -250
- package/lib/atomic-file.js +544 -544
- package/lib/audit-chain.js +177 -177
- package/lib/audit-sign.js +344 -344
- package/lib/audit-tools.js +677 -677
- package/lib/audit.js +766 -766
- package/lib/auth/jwt-external.js +365 -0
- package/lib/auth/jwt.js +337 -311
- package/lib/auth/lockout.js +436 -436
- package/lib/auth/oauth.js +721 -721
- package/lib/auth/passkey.js +181 -181
- package/lib/auth/password.js +628 -594
- package/lib/backup/bundle.js +217 -217
- package/lib/backup/crypto.js +176 -176
- package/lib/backup/index.js +515 -515
- package/lib/backup/manifest.js +282 -282
- package/lib/break-glass.js +1338 -1338
- package/lib/bundler.js +441 -441
- package/lib/cache-redis.js +256 -256
- package/lib/cache.js +1206 -1206
- package/lib/canonical-json.js +115 -115
- package/lib/chain-writer.js +234 -234
- package/lib/cli-helpers.js +206 -206
- package/lib/cli.js +2334 -2334
- package/lib/cluster-provider-db.js +317 -317
- package/lib/cluster-storage.js +226 -226
- package/lib/cluster.js +703 -703
- package/lib/config-drift.js +301 -301
- package/lib/consent.js +222 -222
- package/lib/constants.js +191 -191
- package/lib/cookies.js +350 -315
- package/lib/credential-hash.js +322 -322
- package/lib/crypto.js +266 -266
- package/lib/csv.js +275 -275
- package/lib/db-declare-row-policy.js +267 -267
- package/lib/db-declare-view.js +420 -420
- package/lib/db-query.js +406 -406
- package/lib/db-schema.js +319 -319
- package/lib/db.js +1288 -1288
- package/lib/deprecate.js +222 -222
- package/lib/dev.js +335 -335
- package/lib/dual-control.js +473 -473
- package/lib/error-page.js +420 -420
- package/lib/external-db-migrate.js +441 -441
- package/lib/external-db.js +1061 -1061
- package/lib/file-type.js +273 -273
- package/lib/forms.js +422 -422
- package/lib/framework-error.js +293 -293
- package/lib/framework-schema.js +717 -717
- package/lib/handlers.js +350 -350
- package/lib/http-client-cookie-jar.js +508 -508
- package/lib/http-client.js +1195 -1195
- package/lib/i18n.js +878 -878
- package/lib/jobs.js +185 -185
- package/lib/log-stream-cloudwatch.js +369 -369
- package/lib/log-stream-local.js +146 -146
- package/lib/log-stream-otlp-grpc.js +410 -410
- package/lib/log-stream-otlp.js +286 -286
- package/lib/log-stream-syslog.js +302 -302
- package/lib/log-stream-webhook.js +199 -199
- package/lib/log-stream.js +330 -330
- package/lib/log.js +500 -500
- package/lib/mail-bounce.js +528 -528
- package/lib/mail-dkim.js +369 -369
- package/lib/mail.js +981 -981
- package/lib/metrics.js +683 -683
- package/lib/middleware/api-encrypt.js +936 -936
- package/lib/middleware/attach-user.js +157 -157
- package/lib/middleware/bearer-auth.js +152 -0
- package/lib/middleware/body-parser.js +1170 -1170
- package/lib/middleware/bot-guard.js +178 -178
- package/lib/middleware/compression.js +452 -452
- package/lib/middleware/cors.js +314 -314
- package/lib/middleware/csp-nonce.js +348 -348
- package/lib/middleware/csrf-protect.js +399 -316
- package/lib/middleware/db-role-for.js +264 -264
- package/lib/middleware/fetch-metadata.js +129 -0
- package/lib/middleware/health.js +392 -392
- package/lib/middleware/index.js +85 -79
- package/lib/middleware/rate-limit.js +358 -358
- package/lib/middleware/request-id.js +61 -61
- package/lib/middleware/request-log.js +168 -168
- package/lib/middleware/require-auth.js +104 -104
- package/lib/middleware/security-headers.js +121 -116
- package/lib/middleware/sse.js +166 -166
- package/lib/migrations.js +383 -383
- package/lib/mtls-ca.js +518 -518
- package/lib/mtls-engine-default.js +481 -481
- package/lib/network-dns.js +632 -632
- package/lib/network-heartbeat.js +290 -290
- package/lib/network-nts.js +574 -574
- package/lib/network-proxy.js +265 -265
- package/lib/network-tls.js +328 -328
- package/lib/network.js +233 -233
- package/lib/notify.js +612 -612
- package/lib/ntp-check.js +229 -229
- package/lib/numeric-bounds.js +111 -111
- package/lib/object-store/azure-blob-bucket-ops.js +349 -349
- package/lib/object-store/azure-blob.js +488 -488
- package/lib/object-store/gcs-bucket-ops.js +351 -351
- package/lib/object-store/gcs.js +519 -519
- package/lib/object-store/http-put.js +153 -153
- package/lib/object-store/index.js +197 -197
- package/lib/object-store/sigv4-bucket-ops.js +1092 -1092
- package/lib/object-store/sigv4.js +903 -903
- package/lib/observability.js +151 -151
- package/lib/otel-export.js +269 -269
- package/lib/pagination.js +464 -464
- package/lib/parsers/index.js +80 -80
- package/lib/parsers/safe-env.js +642 -642
- package/lib/parsers/safe-ini.js +292 -292
- package/lib/parsers/safe-toml.js +784 -784
- package/lib/parsers/safe-xml.js +390 -390
- package/lib/parsers/safe-yaml.js +1015 -1015
- package/lib/permissions.js +708 -708
- package/lib/pqc-agent.js +87 -87
- package/lib/pqc-gate.js +279 -279
- package/lib/protobuf-encoder.js +190 -190
- package/lib/protocol-dispatcher.js +161 -161
- package/lib/pubsub-redis.js +167 -167
- package/lib/pubsub.js +429 -429
- package/lib/queue-local.js +476 -476
- package/lib/queue-redis.js +745 -745
- package/lib/queue-sqs.js +319 -319
- package/lib/queue.js +695 -695
- package/lib/redis-client.js +519 -519
- package/lib/request-helpers.js +340 -340
- package/lib/restore-bundle.js +237 -237
- package/lib/restore-rollback.js +259 -259
- package/lib/restore.js +409 -409
- package/lib/retry.js +376 -376
- package/lib/router.js +748 -748
- package/lib/safe-async.js +735 -735
- package/lib/safe-buffer.js +237 -237
- package/lib/safe-json.js +541 -541
- package/lib/safe-schema.js +1266 -1266
- package/lib/safe-url.js +159 -159
- package/lib/scheduler.js +706 -706
- package/lib/security-assert.js +373 -373
- package/lib/seeders.js +618 -618
- package/lib/session.js +535 -478
- package/lib/slug.js +269 -269
- package/lib/ssrf-guard.js +401 -401
- package/lib/static.js +7 -5
- package/lib/storage.js +471 -471
- package/lib/subject.js +281 -281
- package/lib/template.js +791 -791
- package/lib/testing.js +798 -798
- package/lib/time.js +310 -310
- package/lib/totp.js +302 -302
- package/lib/tracing.js +494 -494
- package/lib/uuid.js +132 -132
- package/lib/validate-opts.js +340 -340
- package/lib/vault/index.js +308 -308
- package/lib/vault/rotate.js +784 -784
- package/lib/vault/wrap.js +296 -296
- package/lib/vendor/noble-ciphers.cjs +9 -9
- package/lib/webhook.js +595 -595
- package/lib/websocket.js +1048 -1048
- package/package.json +77 -77
- package/sbom.cyclonedx.json +7 -7
|
@@ -1,161 +1,161 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* protocol-dispatcher — pluggable protocol resolver with deferred-protocol
|
|
4
|
-
* surfacing.
|
|
5
|
-
*
|
|
6
|
-
* Three framework modules ship a "pick a backend by protocol name" surface:
|
|
7
|
-
* - lib/queue.js (local, deferred: redis/sqs/amqp/nats)
|
|
8
|
-
* - lib/log-stream.js (local + webhook + otlp + cloudwatch + syslog)
|
|
9
|
-
* - lib/object-store/index.js (local + http-put + sigv4 + gcs + azure-blob)
|
|
10
|
-
*
|
|
11
|
-
* Each previously copied a ~30-line dispatch block: validate config has a
|
|
12
|
-
* protocol, look up DEFERRED_PROTOCOLS for a clear "not yet implemented"
|
|
13
|
-
* error, look up PROTOCOLS for the real implementation, throw on unknown.
|
|
14
|
-
* This primitive owns that lookup + error shape so callers focus on
|
|
15
|
-
* post-resolve logic (retry+breaker wrapping, classification, etc.).
|
|
16
|
-
*
|
|
17
|
-
* Public API:
|
|
18
|
-
*
|
|
19
|
-
* var dispatcher = protocolDispatcher.create({
|
|
20
|
-
* name: "queue", // appears in error messages
|
|
21
|
-
* errorClass: QueueError, // thrown on unknown/deferred/missing
|
|
22
|
-
* protocols: { local: localProto }, // protocol-name → module
|
|
23
|
-
* deferred: { redis: { description: "Redis Streams" } },
|
|
24
|
-
* fallbackProtocol: "local", // hinted in deferred-error
|
|
25
|
-
* });
|
|
26
|
-
*
|
|
27
|
-
* var proto = dispatcher.resolve(cfg.protocol);
|
|
28
|
-
* // throws errorClass when:
|
|
29
|
-
* // - cfg.protocol is undefined / empty → MISSING_PROTOCOL
|
|
30
|
-
* // - cfg.protocol matches a deferred-protocol entry → PROTOCOL_NOT_IMPLEMENTED
|
|
31
|
-
* // - cfg.protocol is neither implemented nor deferred → UNKNOWN_PROTOCOL
|
|
32
|
-
* // returns the protocol module (caller invokes proto.create(cfg) etc.)
|
|
33
|
-
*
|
|
34
|
-
* dispatcher.protocols // → ["local"]
|
|
35
|
-
* dispatcher.deferred // → ["redis"]
|
|
36
|
-
*
|
|
37
|
-
* Why resolve-only (not build): the post-resolve flow differs per module
|
|
38
|
-
* (retry+breaker for queue+object-store, batched dispatch for log-stream,
|
|
39
|
-
* classification routing for object-store). A one-size-fits-all builder
|
|
40
|
-
* would either miss those concerns or expose them as a sprawling opts
|
|
41
|
-
* surface. Resolve-only keeps the primitive small and the post-resolve
|
|
42
|
-
* code where it belongs.
|
|
43
|
-
*
|
|
44
|
-
* Error surface: every throw carries the dispatcher's `name` so an
|
|
45
|
-
* operator with multiple dispatchers (queue + log-stream) reading the
|
|
46
|
-
* error message knows which one rejected the protocol.
|
|
47
|
-
*/
|
|
48
|
-
var validateOpts = require("./validate-opts");
|
|
49
|
-
var { defineClass } = require("./framework-error");
|
|
50
|
-
|
|
51
|
-
// Default error class — operators / test fixtures that don't want to
|
|
52
|
-
// supply their own get this generic shape with the same code namespace.
|
|
53
|
-
var ProtocolDispatcherError = defineClass("ProtocolDispatcherError", { withStatusCode: true });
|
|
54
|
-
|
|
55
|
-
// Throw at create-time on bad input so operators catch typos at app
|
|
56
|
-
// boot, not first request.
|
|
57
|
-
function _validateConfig(opts) {
|
|
58
|
-
if (!opts || typeof opts !== "object") {
|
|
59
|
-
throw new ProtocolDispatcherError("protocol-dispatcher/bad-opts",
|
|
60
|
-
"protocolDispatcher.create: opts is required");
|
|
61
|
-
}
|
|
62
|
-
validateOpts.requireNonEmptyString(opts.name, "protocolDispatcher.create: opts.name", ProtocolDispatcherError, "protocol-dispatcher/bad-name");
|
|
63
|
-
if (!opts.protocols || typeof opts.protocols !== "object" || Array.isArray(opts.protocols)) {
|
|
64
|
-
throw new ProtocolDispatcherError("protocol-dispatcher/bad-protocols",
|
|
65
|
-
"protocolDispatcher.create: opts.protocols (object) is required");
|
|
66
|
-
}
|
|
67
|
-
// Each protocol value should look like a module with .create — operators
|
|
68
|
-
// wiring a typo'd reference get a clearer error than "undefined is not
|
|
69
|
-
// a function" when resolve() hits it.
|
|
70
|
-
var pkeys = Object.keys(opts.protocols);
|
|
71
|
-
for (var i = 0; i < pkeys.length; i++) {
|
|
72
|
-
var p = opts.protocols[pkeys[i]];
|
|
73
|
-
if (!p || typeof p !== "object" || typeof p.create !== "function") {
|
|
74
|
-
throw new ProtocolDispatcherError("protocol-dispatcher/bad-protocol-entry",
|
|
75
|
-
"protocolDispatcher.create: opts.protocols['" + pkeys[i] +
|
|
76
|
-
"'] must be an object with a .create function (got " +
|
|
77
|
-
(p === null ? "null" : typeof p) + ")");
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
if (opts.deferred !== undefined && opts.deferred !== null) {
|
|
81
|
-
if (typeof opts.deferred !== "object" || Array.isArray(opts.deferred)) {
|
|
82
|
-
throw new ProtocolDispatcherError("protocol-dispatcher/bad-deferred",
|
|
83
|
-
"protocolDispatcher.create: opts.deferred must be an object (or omitted)");
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
if (opts.fallbackProtocol !== undefined && opts.fallbackProtocol !== null) {
|
|
87
|
-
if (typeof opts.fallbackProtocol !== "string" || opts.fallbackProtocol.length === 0) {
|
|
88
|
-
throw new ProtocolDispatcherError("protocol-dispatcher/bad-fallback",
|
|
89
|
-
"protocolDispatcher.create: opts.fallbackProtocol must be a non-empty string (or omitted)");
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
if (opts.errorClass !== undefined && opts.errorClass !== null) {
|
|
93
|
-
if (typeof opts.errorClass !== "function") {
|
|
94
|
-
throw new ProtocolDispatcherError("protocol-dispatcher/bad-error-class",
|
|
95
|
-
"protocolDispatcher.create: opts.errorClass must be a constructor (or omitted)");
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function create(opts) {
|
|
101
|
-
_validateConfig(opts);
|
|
102
|
-
var name = opts.name;
|
|
103
|
-
var protocols = Object.assign({}, opts.protocols);
|
|
104
|
-
var deferred = Object.assign({}, opts.deferred || {});
|
|
105
|
-
var fallbackProtocol = opts.fallbackProtocol || null;
|
|
106
|
-
var ErrorClass = opts.errorClass || ProtocolDispatcherError;
|
|
107
|
-
|
|
108
|
-
function _err(code, message) {
|
|
109
|
-
// ErrorClass is expected to be a defineClass-built class with
|
|
110
|
-
// (code, message, permanent[, statusCode]) signature. Pass
|
|
111
|
-
// permanent=true since protocol mismatches are config errors, not
|
|
112
|
-
// transient failures.
|
|
113
|
-
return new ErrorClass(code, message, true);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function resolve(protocol) {
|
|
117
|
-
if (typeof protocol !== "string" || protocol.length === 0) {
|
|
118
|
-
throw _err("MISSING_PROTOCOL",
|
|
119
|
-
name + " backend requires { protocol }");
|
|
120
|
-
}
|
|
121
|
-
if (Object.prototype.hasOwnProperty.call(deferred, protocol)) {
|
|
122
|
-
var d = deferred[protocol];
|
|
123
|
-
var msg = name + " protocol '" + protocol + "' is not yet implemented";
|
|
124
|
-
if (d && d.description) msg += " (" + d.description + ")";
|
|
125
|
-
if (d && d.since) msg += "; deferred to " + d.since;
|
|
126
|
-
if (fallbackProtocol) msg += ". Use protocol: '" + fallbackProtocol + "' for now.";
|
|
127
|
-
throw _err("PROTOCOL_NOT_IMPLEMENTED", msg);
|
|
128
|
-
}
|
|
129
|
-
if (!Object.prototype.hasOwnProperty.call(protocols, protocol)) {
|
|
130
|
-
// Diagnostic listing only — sorted protocol-name list for the
|
|
131
|
-
// operator-facing error message; not a canonicalization-for-hash
|
|
132
|
-
// walk, so the bare keys-then-sort is correct here.
|
|
133
|
-
var protoKeys = Object.keys(protocols);
|
|
134
|
-
protoKeys.sort();
|
|
135
|
-
var known = protoKeys.join(", ");
|
|
136
|
-
throw _err("UNKNOWN_PROTOCOL",
|
|
137
|
-
"unknown " + name + " protocol: '" + protocol +
|
|
138
|
-
"' (known: " + (known || "[none]") + ")");
|
|
139
|
-
}
|
|
140
|
-
return protocols[protocol];
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Same diagnostic-only sort for the dispatcher's introspection
|
|
144
|
-
// surface — operators read these to confirm wiring at boot.
|
|
145
|
-
var protocolNames = Object.keys(protocols);
|
|
146
|
-
protocolNames.sort();
|
|
147
|
-
var deferredNames = Object.keys(deferred);
|
|
148
|
-
deferredNames.sort();
|
|
149
|
-
|
|
150
|
-
return {
|
|
151
|
-
name: name,
|
|
152
|
-
resolve: resolve,
|
|
153
|
-
protocols: protocolNames,
|
|
154
|
-
deferred: deferredNames,
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
module.exports = {
|
|
159
|
-
create: create,
|
|
160
|
-
ProtocolDispatcherError: ProtocolDispatcherError,
|
|
161
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* protocol-dispatcher — pluggable protocol resolver with deferred-protocol
|
|
4
|
+
* surfacing.
|
|
5
|
+
*
|
|
6
|
+
* Three framework modules ship a "pick a backend by protocol name" surface:
|
|
7
|
+
* - lib/queue.js (local, deferred: redis/sqs/amqp/nats)
|
|
8
|
+
* - lib/log-stream.js (local + webhook + otlp + cloudwatch + syslog)
|
|
9
|
+
* - lib/object-store/index.js (local + http-put + sigv4 + gcs + azure-blob)
|
|
10
|
+
*
|
|
11
|
+
* Each previously copied a ~30-line dispatch block: validate config has a
|
|
12
|
+
* protocol, look up DEFERRED_PROTOCOLS for a clear "not yet implemented"
|
|
13
|
+
* error, look up PROTOCOLS for the real implementation, throw on unknown.
|
|
14
|
+
* This primitive owns that lookup + error shape so callers focus on
|
|
15
|
+
* post-resolve logic (retry+breaker wrapping, classification, etc.).
|
|
16
|
+
*
|
|
17
|
+
* Public API:
|
|
18
|
+
*
|
|
19
|
+
* var dispatcher = protocolDispatcher.create({
|
|
20
|
+
* name: "queue", // appears in error messages
|
|
21
|
+
* errorClass: QueueError, // thrown on unknown/deferred/missing
|
|
22
|
+
* protocols: { local: localProto }, // protocol-name → module
|
|
23
|
+
* deferred: { redis: { description: "Redis Streams" } },
|
|
24
|
+
* fallbackProtocol: "local", // hinted in deferred-error
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* var proto = dispatcher.resolve(cfg.protocol);
|
|
28
|
+
* // throws errorClass when:
|
|
29
|
+
* // - cfg.protocol is undefined / empty → MISSING_PROTOCOL
|
|
30
|
+
* // - cfg.protocol matches a deferred-protocol entry → PROTOCOL_NOT_IMPLEMENTED
|
|
31
|
+
* // - cfg.protocol is neither implemented nor deferred → UNKNOWN_PROTOCOL
|
|
32
|
+
* // returns the protocol module (caller invokes proto.create(cfg) etc.)
|
|
33
|
+
*
|
|
34
|
+
* dispatcher.protocols // → ["local"]
|
|
35
|
+
* dispatcher.deferred // → ["redis"]
|
|
36
|
+
*
|
|
37
|
+
* Why resolve-only (not build): the post-resolve flow differs per module
|
|
38
|
+
* (retry+breaker for queue+object-store, batched dispatch for log-stream,
|
|
39
|
+
* classification routing for object-store). A one-size-fits-all builder
|
|
40
|
+
* would either miss those concerns or expose them as a sprawling opts
|
|
41
|
+
* surface. Resolve-only keeps the primitive small and the post-resolve
|
|
42
|
+
* code where it belongs.
|
|
43
|
+
*
|
|
44
|
+
* Error surface: every throw carries the dispatcher's `name` so an
|
|
45
|
+
* operator with multiple dispatchers (queue + log-stream) reading the
|
|
46
|
+
* error message knows which one rejected the protocol.
|
|
47
|
+
*/
|
|
48
|
+
var validateOpts = require("./validate-opts");
|
|
49
|
+
var { defineClass } = require("./framework-error");
|
|
50
|
+
|
|
51
|
+
// Default error class — operators / test fixtures that don't want to
|
|
52
|
+
// supply their own get this generic shape with the same code namespace.
|
|
53
|
+
var ProtocolDispatcherError = defineClass("ProtocolDispatcherError", { withStatusCode: true });
|
|
54
|
+
|
|
55
|
+
// Throw at create-time on bad input so operators catch typos at app
|
|
56
|
+
// boot, not first request.
|
|
57
|
+
function _validateConfig(opts) {
|
|
58
|
+
if (!opts || typeof opts !== "object") {
|
|
59
|
+
throw new ProtocolDispatcherError("protocol-dispatcher/bad-opts",
|
|
60
|
+
"protocolDispatcher.create: opts is required");
|
|
61
|
+
}
|
|
62
|
+
validateOpts.requireNonEmptyString(opts.name, "protocolDispatcher.create: opts.name", ProtocolDispatcherError, "protocol-dispatcher/bad-name");
|
|
63
|
+
if (!opts.protocols || typeof opts.protocols !== "object" || Array.isArray(opts.protocols)) {
|
|
64
|
+
throw new ProtocolDispatcherError("protocol-dispatcher/bad-protocols",
|
|
65
|
+
"protocolDispatcher.create: opts.protocols (object) is required");
|
|
66
|
+
}
|
|
67
|
+
// Each protocol value should look like a module with .create — operators
|
|
68
|
+
// wiring a typo'd reference get a clearer error than "undefined is not
|
|
69
|
+
// a function" when resolve() hits it.
|
|
70
|
+
var pkeys = Object.keys(opts.protocols);
|
|
71
|
+
for (var i = 0; i < pkeys.length; i++) {
|
|
72
|
+
var p = opts.protocols[pkeys[i]];
|
|
73
|
+
if (!p || typeof p !== "object" || typeof p.create !== "function") {
|
|
74
|
+
throw new ProtocolDispatcherError("protocol-dispatcher/bad-protocol-entry",
|
|
75
|
+
"protocolDispatcher.create: opts.protocols['" + pkeys[i] +
|
|
76
|
+
"'] must be an object with a .create function (got " +
|
|
77
|
+
(p === null ? "null" : typeof p) + ")");
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (opts.deferred !== undefined && opts.deferred !== null) {
|
|
81
|
+
if (typeof opts.deferred !== "object" || Array.isArray(opts.deferred)) {
|
|
82
|
+
throw new ProtocolDispatcherError("protocol-dispatcher/bad-deferred",
|
|
83
|
+
"protocolDispatcher.create: opts.deferred must be an object (or omitted)");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (opts.fallbackProtocol !== undefined && opts.fallbackProtocol !== null) {
|
|
87
|
+
if (typeof opts.fallbackProtocol !== "string" || opts.fallbackProtocol.length === 0) {
|
|
88
|
+
throw new ProtocolDispatcherError("protocol-dispatcher/bad-fallback",
|
|
89
|
+
"protocolDispatcher.create: opts.fallbackProtocol must be a non-empty string (or omitted)");
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (opts.errorClass !== undefined && opts.errorClass !== null) {
|
|
93
|
+
if (typeof opts.errorClass !== "function") {
|
|
94
|
+
throw new ProtocolDispatcherError("protocol-dispatcher/bad-error-class",
|
|
95
|
+
"protocolDispatcher.create: opts.errorClass must be a constructor (or omitted)");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function create(opts) {
|
|
101
|
+
_validateConfig(opts);
|
|
102
|
+
var name = opts.name;
|
|
103
|
+
var protocols = Object.assign({}, opts.protocols);
|
|
104
|
+
var deferred = Object.assign({}, opts.deferred || {});
|
|
105
|
+
var fallbackProtocol = opts.fallbackProtocol || null;
|
|
106
|
+
var ErrorClass = opts.errorClass || ProtocolDispatcherError;
|
|
107
|
+
|
|
108
|
+
function _err(code, message) {
|
|
109
|
+
// ErrorClass is expected to be a defineClass-built class with
|
|
110
|
+
// (code, message, permanent[, statusCode]) signature. Pass
|
|
111
|
+
// permanent=true since protocol mismatches are config errors, not
|
|
112
|
+
// transient failures.
|
|
113
|
+
return new ErrorClass(code, message, true);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function resolve(protocol) {
|
|
117
|
+
if (typeof protocol !== "string" || protocol.length === 0) {
|
|
118
|
+
throw _err("MISSING_PROTOCOL",
|
|
119
|
+
name + " backend requires { protocol }");
|
|
120
|
+
}
|
|
121
|
+
if (Object.prototype.hasOwnProperty.call(deferred, protocol)) {
|
|
122
|
+
var d = deferred[protocol];
|
|
123
|
+
var msg = name + " protocol '" + protocol + "' is not yet implemented";
|
|
124
|
+
if (d && d.description) msg += " (" + d.description + ")";
|
|
125
|
+
if (d && d.since) msg += "; deferred to " + d.since;
|
|
126
|
+
if (fallbackProtocol) msg += ". Use protocol: '" + fallbackProtocol + "' for now.";
|
|
127
|
+
throw _err("PROTOCOL_NOT_IMPLEMENTED", msg);
|
|
128
|
+
}
|
|
129
|
+
if (!Object.prototype.hasOwnProperty.call(protocols, protocol)) {
|
|
130
|
+
// Diagnostic listing only — sorted protocol-name list for the
|
|
131
|
+
// operator-facing error message; not a canonicalization-for-hash
|
|
132
|
+
// walk, so the bare keys-then-sort is correct here.
|
|
133
|
+
var protoKeys = Object.keys(protocols);
|
|
134
|
+
protoKeys.sort();
|
|
135
|
+
var known = protoKeys.join(", ");
|
|
136
|
+
throw _err("UNKNOWN_PROTOCOL",
|
|
137
|
+
"unknown " + name + " protocol: '" + protocol +
|
|
138
|
+
"' (known: " + (known || "[none]") + ")");
|
|
139
|
+
}
|
|
140
|
+
return protocols[protocol];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Same diagnostic-only sort for the dispatcher's introspection
|
|
144
|
+
// surface — operators read these to confirm wiring at boot.
|
|
145
|
+
var protocolNames = Object.keys(protocols);
|
|
146
|
+
protocolNames.sort();
|
|
147
|
+
var deferredNames = Object.keys(deferred);
|
|
148
|
+
deferredNames.sort();
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
name: name,
|
|
152
|
+
resolve: resolve,
|
|
153
|
+
protocols: protocolNames,
|
|
154
|
+
deferred: deferredNames,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
module.exports = {
|
|
159
|
+
create: create,
|
|
160
|
+
ProtocolDispatcherError: ProtocolDispatcherError,
|
|
161
|
+
};
|