@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
package/lib/deprecate.js
CHANGED
|
@@ -1,222 +1,222 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* deprecate — runtime deprecation API for the framework's LTS contract.
|
|
4
|
-
*
|
|
5
|
-
* Operators see a one-time stderr warning the first time deprecated
|
|
6
|
-
* surface is used, with the version it was deprecated in and the
|
|
7
|
-
* version it'll be removed in. Production runs suppress warnings by
|
|
8
|
-
* default (operators don't want stderr noise from deprecated paths in
|
|
9
|
-
* code they don't own), but BLAMEJS_DEPRECATIONS env var inverts that
|
|
10
|
-
* for visibility-on-demand.
|
|
11
|
-
*
|
|
12
|
-
* var dep = b.deprecate;
|
|
13
|
-
*
|
|
14
|
-
* // Direct warning at the call site
|
|
15
|
-
* dep.warn("auth.legacyVerify", {
|
|
16
|
-
* since: "0.2.0",
|
|
17
|
-
* removeIn: "0.4.0",
|
|
18
|
-
* message: "use auth.password.verify(stored, plain) instead",
|
|
19
|
-
* hint: "see MIGRATING.md#0-2-to-0-4",
|
|
20
|
-
* });
|
|
21
|
-
*
|
|
22
|
-
* // Wrap an old function so calls trigger the warning automatically
|
|
23
|
-
* var legacyVerify = dep.wrap(newVerify, "auth.legacyVerify", {
|
|
24
|
-
* since: "0.2.0", removeIn: "0.4.0",
|
|
25
|
-
* message: "renamed to auth.password.verify",
|
|
26
|
-
* });
|
|
27
|
-
*
|
|
28
|
-
* // Mark a property as deprecated; access triggers the warning
|
|
29
|
-
* dep.alias(targetObj, "oldKey", "newKey", {
|
|
30
|
-
* since: "0.2.0", removeIn: "0.4.0",
|
|
31
|
-
* });
|
|
32
|
-
*
|
|
33
|
-
* dep.list(); // → [{ name, since, removeIn, callCount, firstSeen }]
|
|
34
|
-
* dep.reset(); // clears the seen-set; tests
|
|
35
|
-
*
|
|
36
|
-
* BLAMEJS_DEPRECATIONS env var controls runtime behavior:
|
|
37
|
-
* "warn" — stderr warning on first use of each (name, since) pair
|
|
38
|
-
* (default outside production)
|
|
39
|
-
* "silent" — skip entirely (default in production)
|
|
40
|
-
* "error" — throw on first use; development tool to surface every
|
|
41
|
-
* deprecated call site as a hard failure during a sweep
|
|
42
|
-
*
|
|
43
|
-
* Mode resolution order:
|
|
44
|
-
* 1. process.env.BLAMEJS_DEPRECATIONS if set
|
|
45
|
-
* 2. "silent" when process.env.NODE_ENV === "production"
|
|
46
|
-
* 3. "warn" otherwise
|
|
47
|
-
*
|
|
48
|
-
* Warnings dedupe by (name, since) — calling deprecate.warn(...) ten
|
|
49
|
-
* thousand times with the same args produces one stderr line. The
|
|
50
|
-
* call counter is still incremented so dep.list() shows usage volume.
|
|
51
|
-
*/
|
|
52
|
-
|
|
53
|
-
var safeEnv = require("./parsers/safe-env");
|
|
54
|
-
var validateOpts = require("./validate-opts");
|
|
55
|
-
var { FrameworkError } = require("./framework-error");
|
|
56
|
-
|
|
57
|
-
class DeprecateError extends FrameworkError {
|
|
58
|
-
constructor(code, message) {
|
|
59
|
-
super(message, code);
|
|
60
|
-
this.name = "DeprecateError";
|
|
61
|
-
this.permanent = true;
|
|
62
|
-
this.isDeprecateError = true;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Map of "<name>:<since>" → { name, since, removeIn, callCount, firstSeen }
|
|
67
|
-
var _seen = new Map();
|
|
68
|
-
|
|
69
|
-
function _modeFromEnv() {
|
|
70
|
-
var env = safeEnv.readVar("BLAMEJS_DEPRECATIONS");
|
|
71
|
-
if (typeof env === "string" && env.length > 0) {
|
|
72
|
-
var v = env.toLowerCase();
|
|
73
|
-
if (v === "warn" || v === "silent" || v === "error") return v;
|
|
74
|
-
}
|
|
75
|
-
if (safeEnv.readVar("NODE_ENV") === "production") return "silent";
|
|
76
|
-
return "warn";
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function _format(name, opts) {
|
|
80
|
-
opts = opts || {};
|
|
81
|
-
var line = "[blamejs:deprecated] " + name;
|
|
82
|
-
if (opts.since) line += " (since " + opts.since + ")";
|
|
83
|
-
if (opts.removeIn) line += "; removed in " + opts.removeIn;
|
|
84
|
-
if (opts.message) line += " — " + opts.message;
|
|
85
|
-
if (opts.hint) line += " · " + opts.hint;
|
|
86
|
-
return line;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function _validateOpts(opts, fnName) {
|
|
90
|
-
if (!opts || typeof opts !== "object") {
|
|
91
|
-
throw new DeprecateError("deprecate/bad-opts",
|
|
92
|
-
fnName + ": opts is required (with at least 'since' and 'removeIn')");
|
|
93
|
-
}
|
|
94
|
-
validateOpts.requireNonEmptyString(opts.since, fnName + ": opts.since (version string)", DeprecateError, "deprecate/bad-opts");
|
|
95
|
-
validateOpts.requireNonEmptyString(opts.removeIn, fnName + ": opts.removeIn (version string)", DeprecateError, "deprecate/bad-opts");
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function warn(name, opts) {
|
|
99
|
-
if (typeof name !== "string" || name.length === 0) {
|
|
100
|
-
throw new DeprecateError("deprecate/bad-name",
|
|
101
|
-
"warn: name is required (the public identifier being deprecated)");
|
|
102
|
-
}
|
|
103
|
-
_validateOpts(opts, "warn");
|
|
104
|
-
|
|
105
|
-
var key = name + ":" + opts.since;
|
|
106
|
-
var entry = _seen.get(key);
|
|
107
|
-
if (!entry) {
|
|
108
|
-
entry = {
|
|
109
|
-
name: name,
|
|
110
|
-
since: opts.since,
|
|
111
|
-
removeIn: opts.removeIn,
|
|
112
|
-
message: opts.message || null,
|
|
113
|
-
hint: opts.hint || null,
|
|
114
|
-
callCount: 0,
|
|
115
|
-
firstSeen: new Date().toISOString(),
|
|
116
|
-
};
|
|
117
|
-
_seen.set(key, entry);
|
|
118
|
-
}
|
|
119
|
-
entry.callCount++;
|
|
120
|
-
|
|
121
|
-
var mode = _modeFromEnv();
|
|
122
|
-
if (mode === "silent") return;
|
|
123
|
-
|
|
124
|
-
// Emit on first occurrence only (dedupe)
|
|
125
|
-
if (entry.callCount > 1) return;
|
|
126
|
-
|
|
127
|
-
var line = _format(name, opts);
|
|
128
|
-
if (mode === "error") {
|
|
129
|
-
throw new DeprecateError("deprecate/used-in-error-mode",
|
|
130
|
-
line + " — BLAMEJS_DEPRECATIONS=error in effect");
|
|
131
|
-
}
|
|
132
|
-
// mode === "warn"
|
|
133
|
-
try { process.stderr.write(line + "\n"); }
|
|
134
|
-
catch (_e) { /* stderr write best-effort */ }
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Wrap a function so calling it issues a deprecation warning + delegates.
|
|
138
|
-
// The wrapper preserves the original function's `.length` (arity) so
|
|
139
|
-
// callers introspecting it as a callable see the same shape.
|
|
140
|
-
function wrap(fn, name, opts) {
|
|
141
|
-
if (typeof fn !== "function") {
|
|
142
|
-
throw new DeprecateError("deprecate/bad-target",
|
|
143
|
-
"wrap: first arg must be the replacement function (the new API)");
|
|
144
|
-
}
|
|
145
|
-
if (typeof name !== "string" || name.length === 0) {
|
|
146
|
-
throw new DeprecateError("deprecate/bad-name",
|
|
147
|
-
"wrap: name is required (the deprecated identifier)");
|
|
148
|
-
}
|
|
149
|
-
_validateOpts(opts, "wrap");
|
|
150
|
-
var wrapper = function () {
|
|
151
|
-
warn(name, opts);
|
|
152
|
-
return fn.apply(this, arguments);
|
|
153
|
-
};
|
|
154
|
-
// Preserve identity hints
|
|
155
|
-
Object.defineProperty(wrapper, "name", { value: name + ":deprecated", configurable: true });
|
|
156
|
-
return wrapper;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Define `oldKey` on `target` as a getter that warns then returns
|
|
160
|
-
// `target[newKey]`. The setter writes through so existing assignments
|
|
161
|
-
// still work, but the getter access trips the warning.
|
|
162
|
-
function alias(target, oldKey, newKey, opts) {
|
|
163
|
-
if (!target || typeof target !== "object") {
|
|
164
|
-
throw new DeprecateError("deprecate/bad-target",
|
|
165
|
-
"alias: target must be an object");
|
|
166
|
-
}
|
|
167
|
-
if (typeof oldKey !== "string" || oldKey.length === 0) {
|
|
168
|
-
throw new DeprecateError("deprecate/bad-name",
|
|
169
|
-
"alias: oldKey is required");
|
|
170
|
-
}
|
|
171
|
-
if (typeof newKey !== "string" || newKey.length === 0) {
|
|
172
|
-
throw new DeprecateError("deprecate/bad-name",
|
|
173
|
-
"alias: newKey is required");
|
|
174
|
-
}
|
|
175
|
-
_validateOpts(opts, "alias");
|
|
176
|
-
var aliasName = opts.aliasName ||
|
|
177
|
-
((target.constructor && target.constructor.name &&
|
|
178
|
-
target.constructor.name !== "Object" ? target.constructor.name + "." : "") + oldKey);
|
|
179
|
-
var fullOpts = Object.assign({
|
|
180
|
-
message: "use '" + newKey + "' instead",
|
|
181
|
-
}, opts);
|
|
182
|
-
Object.defineProperty(target, oldKey, {
|
|
183
|
-
configurable: true,
|
|
184
|
-
enumerable: false,
|
|
185
|
-
get: function () { warn(aliasName, fullOpts); return target[newKey]; },
|
|
186
|
-
set: function (v) { warn(aliasName, fullOpts); target[newKey] = v; },
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
function list() {
|
|
191
|
-
var out = [];
|
|
192
|
-
_seen.forEach(function (v) {
|
|
193
|
-
out.push({
|
|
194
|
-
name: v.name,
|
|
195
|
-
since: v.since,
|
|
196
|
-
removeIn: v.removeIn,
|
|
197
|
-
callCount: v.callCount,
|
|
198
|
-
firstSeen: v.firstSeen,
|
|
199
|
-
});
|
|
200
|
-
});
|
|
201
|
-
// Stable order: most-frequent first, ties broken by first-seen
|
|
202
|
-
out.sort(function (a, b) {
|
|
203
|
-
if (a.callCount !== b.callCount) return b.callCount - a.callCount;
|
|
204
|
-
return a.firstSeen < b.firstSeen ? -1 : 1;
|
|
205
|
-
});
|
|
206
|
-
return out;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
function reset() { _seen.clear(); }
|
|
210
|
-
|
|
211
|
-
// Export the resolved mode so tests + ops dashboards can introspect
|
|
212
|
-
function getMode() { return _modeFromEnv(); }
|
|
213
|
-
|
|
214
|
-
module.exports = {
|
|
215
|
-
warn: warn,
|
|
216
|
-
wrap: wrap,
|
|
217
|
-
alias: alias,
|
|
218
|
-
list: list,
|
|
219
|
-
reset: reset,
|
|
220
|
-
getMode: getMode,
|
|
221
|
-
DeprecateError: DeprecateError,
|
|
222
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* deprecate — runtime deprecation API for the framework's LTS contract.
|
|
4
|
+
*
|
|
5
|
+
* Operators see a one-time stderr warning the first time deprecated
|
|
6
|
+
* surface is used, with the version it was deprecated in and the
|
|
7
|
+
* version it'll be removed in. Production runs suppress warnings by
|
|
8
|
+
* default (operators don't want stderr noise from deprecated paths in
|
|
9
|
+
* code they don't own), but BLAMEJS_DEPRECATIONS env var inverts that
|
|
10
|
+
* for visibility-on-demand.
|
|
11
|
+
*
|
|
12
|
+
* var dep = b.deprecate;
|
|
13
|
+
*
|
|
14
|
+
* // Direct warning at the call site
|
|
15
|
+
* dep.warn("auth.legacyVerify", {
|
|
16
|
+
* since: "0.2.0",
|
|
17
|
+
* removeIn: "0.4.0",
|
|
18
|
+
* message: "use auth.password.verify(stored, plain) instead",
|
|
19
|
+
* hint: "see MIGRATING.md#0-2-to-0-4",
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* // Wrap an old function so calls trigger the warning automatically
|
|
23
|
+
* var legacyVerify = dep.wrap(newVerify, "auth.legacyVerify", {
|
|
24
|
+
* since: "0.2.0", removeIn: "0.4.0",
|
|
25
|
+
* message: "renamed to auth.password.verify",
|
|
26
|
+
* });
|
|
27
|
+
*
|
|
28
|
+
* // Mark a property as deprecated; access triggers the warning
|
|
29
|
+
* dep.alias(targetObj, "oldKey", "newKey", {
|
|
30
|
+
* since: "0.2.0", removeIn: "0.4.0",
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* dep.list(); // → [{ name, since, removeIn, callCount, firstSeen }]
|
|
34
|
+
* dep.reset(); // clears the seen-set; tests
|
|
35
|
+
*
|
|
36
|
+
* BLAMEJS_DEPRECATIONS env var controls runtime behavior:
|
|
37
|
+
* "warn" — stderr warning on first use of each (name, since) pair
|
|
38
|
+
* (default outside production)
|
|
39
|
+
* "silent" — skip entirely (default in production)
|
|
40
|
+
* "error" — throw on first use; development tool to surface every
|
|
41
|
+
* deprecated call site as a hard failure during a sweep
|
|
42
|
+
*
|
|
43
|
+
* Mode resolution order:
|
|
44
|
+
* 1. process.env.BLAMEJS_DEPRECATIONS if set
|
|
45
|
+
* 2. "silent" when process.env.NODE_ENV === "production"
|
|
46
|
+
* 3. "warn" otherwise
|
|
47
|
+
*
|
|
48
|
+
* Warnings dedupe by (name, since) — calling deprecate.warn(...) ten
|
|
49
|
+
* thousand times with the same args produces one stderr line. The
|
|
50
|
+
* call counter is still incremented so dep.list() shows usage volume.
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
var safeEnv = require("./parsers/safe-env");
|
|
54
|
+
var validateOpts = require("./validate-opts");
|
|
55
|
+
var { FrameworkError } = require("./framework-error");
|
|
56
|
+
|
|
57
|
+
class DeprecateError extends FrameworkError {
|
|
58
|
+
constructor(code, message) {
|
|
59
|
+
super(message, code);
|
|
60
|
+
this.name = "DeprecateError";
|
|
61
|
+
this.permanent = true;
|
|
62
|
+
this.isDeprecateError = true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Map of "<name>:<since>" → { name, since, removeIn, callCount, firstSeen }
|
|
67
|
+
var _seen = new Map();
|
|
68
|
+
|
|
69
|
+
function _modeFromEnv() {
|
|
70
|
+
var env = safeEnv.readVar("BLAMEJS_DEPRECATIONS");
|
|
71
|
+
if (typeof env === "string" && env.length > 0) {
|
|
72
|
+
var v = env.toLowerCase();
|
|
73
|
+
if (v === "warn" || v === "silent" || v === "error") return v;
|
|
74
|
+
}
|
|
75
|
+
if (safeEnv.readVar("NODE_ENV") === "production") return "silent";
|
|
76
|
+
return "warn";
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function _format(name, opts) {
|
|
80
|
+
opts = opts || {};
|
|
81
|
+
var line = "[blamejs:deprecated] " + name;
|
|
82
|
+
if (opts.since) line += " (since " + opts.since + ")";
|
|
83
|
+
if (opts.removeIn) line += "; removed in " + opts.removeIn;
|
|
84
|
+
if (opts.message) line += " — " + opts.message;
|
|
85
|
+
if (opts.hint) line += " · " + opts.hint;
|
|
86
|
+
return line;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function _validateOpts(opts, fnName) {
|
|
90
|
+
if (!opts || typeof opts !== "object") {
|
|
91
|
+
throw new DeprecateError("deprecate/bad-opts",
|
|
92
|
+
fnName + ": opts is required (with at least 'since' and 'removeIn')");
|
|
93
|
+
}
|
|
94
|
+
validateOpts.requireNonEmptyString(opts.since, fnName + ": opts.since (version string)", DeprecateError, "deprecate/bad-opts");
|
|
95
|
+
validateOpts.requireNonEmptyString(opts.removeIn, fnName + ": opts.removeIn (version string)", DeprecateError, "deprecate/bad-opts");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function warn(name, opts) {
|
|
99
|
+
if (typeof name !== "string" || name.length === 0) {
|
|
100
|
+
throw new DeprecateError("deprecate/bad-name",
|
|
101
|
+
"warn: name is required (the public identifier being deprecated)");
|
|
102
|
+
}
|
|
103
|
+
_validateOpts(opts, "warn");
|
|
104
|
+
|
|
105
|
+
var key = name + ":" + opts.since;
|
|
106
|
+
var entry = _seen.get(key);
|
|
107
|
+
if (!entry) {
|
|
108
|
+
entry = {
|
|
109
|
+
name: name,
|
|
110
|
+
since: opts.since,
|
|
111
|
+
removeIn: opts.removeIn,
|
|
112
|
+
message: opts.message || null,
|
|
113
|
+
hint: opts.hint || null,
|
|
114
|
+
callCount: 0,
|
|
115
|
+
firstSeen: new Date().toISOString(),
|
|
116
|
+
};
|
|
117
|
+
_seen.set(key, entry);
|
|
118
|
+
}
|
|
119
|
+
entry.callCount++;
|
|
120
|
+
|
|
121
|
+
var mode = _modeFromEnv();
|
|
122
|
+
if (mode === "silent") return;
|
|
123
|
+
|
|
124
|
+
// Emit on first occurrence only (dedupe)
|
|
125
|
+
if (entry.callCount > 1) return;
|
|
126
|
+
|
|
127
|
+
var line = _format(name, opts);
|
|
128
|
+
if (mode === "error") {
|
|
129
|
+
throw new DeprecateError("deprecate/used-in-error-mode",
|
|
130
|
+
line + " — BLAMEJS_DEPRECATIONS=error in effect");
|
|
131
|
+
}
|
|
132
|
+
// mode === "warn"
|
|
133
|
+
try { process.stderr.write(line + "\n"); }
|
|
134
|
+
catch (_e) { /* stderr write best-effort */ }
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Wrap a function so calling it issues a deprecation warning + delegates.
|
|
138
|
+
// The wrapper preserves the original function's `.length` (arity) so
|
|
139
|
+
// callers introspecting it as a callable see the same shape.
|
|
140
|
+
function wrap(fn, name, opts) {
|
|
141
|
+
if (typeof fn !== "function") {
|
|
142
|
+
throw new DeprecateError("deprecate/bad-target",
|
|
143
|
+
"wrap: first arg must be the replacement function (the new API)");
|
|
144
|
+
}
|
|
145
|
+
if (typeof name !== "string" || name.length === 0) {
|
|
146
|
+
throw new DeprecateError("deprecate/bad-name",
|
|
147
|
+
"wrap: name is required (the deprecated identifier)");
|
|
148
|
+
}
|
|
149
|
+
_validateOpts(opts, "wrap");
|
|
150
|
+
var wrapper = function () {
|
|
151
|
+
warn(name, opts);
|
|
152
|
+
return fn.apply(this, arguments);
|
|
153
|
+
};
|
|
154
|
+
// Preserve identity hints
|
|
155
|
+
Object.defineProperty(wrapper, "name", { value: name + ":deprecated", configurable: true });
|
|
156
|
+
return wrapper;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Define `oldKey` on `target` as a getter that warns then returns
|
|
160
|
+
// `target[newKey]`. The setter writes through so existing assignments
|
|
161
|
+
// still work, but the getter access trips the warning.
|
|
162
|
+
function alias(target, oldKey, newKey, opts) {
|
|
163
|
+
if (!target || typeof target !== "object") {
|
|
164
|
+
throw new DeprecateError("deprecate/bad-target",
|
|
165
|
+
"alias: target must be an object");
|
|
166
|
+
}
|
|
167
|
+
if (typeof oldKey !== "string" || oldKey.length === 0) {
|
|
168
|
+
throw new DeprecateError("deprecate/bad-name",
|
|
169
|
+
"alias: oldKey is required");
|
|
170
|
+
}
|
|
171
|
+
if (typeof newKey !== "string" || newKey.length === 0) {
|
|
172
|
+
throw new DeprecateError("deprecate/bad-name",
|
|
173
|
+
"alias: newKey is required");
|
|
174
|
+
}
|
|
175
|
+
_validateOpts(opts, "alias");
|
|
176
|
+
var aliasName = opts.aliasName ||
|
|
177
|
+
((target.constructor && target.constructor.name &&
|
|
178
|
+
target.constructor.name !== "Object" ? target.constructor.name + "." : "") + oldKey);
|
|
179
|
+
var fullOpts = Object.assign({
|
|
180
|
+
message: "use '" + newKey + "' instead",
|
|
181
|
+
}, opts);
|
|
182
|
+
Object.defineProperty(target, oldKey, {
|
|
183
|
+
configurable: true,
|
|
184
|
+
enumerable: false,
|
|
185
|
+
get: function () { warn(aliasName, fullOpts); return target[newKey]; },
|
|
186
|
+
set: function (v) { warn(aliasName, fullOpts); target[newKey] = v; },
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function list() {
|
|
191
|
+
var out = [];
|
|
192
|
+
_seen.forEach(function (v) {
|
|
193
|
+
out.push({
|
|
194
|
+
name: v.name,
|
|
195
|
+
since: v.since,
|
|
196
|
+
removeIn: v.removeIn,
|
|
197
|
+
callCount: v.callCount,
|
|
198
|
+
firstSeen: v.firstSeen,
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
// Stable order: most-frequent first, ties broken by first-seen
|
|
202
|
+
out.sort(function (a, b) {
|
|
203
|
+
if (a.callCount !== b.callCount) return b.callCount - a.callCount;
|
|
204
|
+
return a.firstSeen < b.firstSeen ? -1 : 1;
|
|
205
|
+
});
|
|
206
|
+
return out;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function reset() { _seen.clear(); }
|
|
210
|
+
|
|
211
|
+
// Export the resolved mode so tests + ops dashboards can introspect
|
|
212
|
+
function getMode() { return _modeFromEnv(); }
|
|
213
|
+
|
|
214
|
+
module.exports = {
|
|
215
|
+
warn: warn,
|
|
216
|
+
wrap: wrap,
|
|
217
|
+
alias: alias,
|
|
218
|
+
list: list,
|
|
219
|
+
reset: reset,
|
|
220
|
+
getMode: getMode,
|
|
221
|
+
DeprecateError: DeprecateError,
|
|
222
|
+
};
|