@blamejs/core 0.7.4 → 0.7.18
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 +423 -395
- package/README.md +150 -149
- package/bin/blamejs.js +0 -0
- package/index.js +308 -284
- package/lib/api-key.js +660 -663
- 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.js +311 -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 +594 -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/codepoint-class.js +196 -0
- package/lib/config-drift.js +301 -301
- package/lib/consent.js +222 -222
- package/lib/constants.js +191 -191
- package/lib/cookies.js +315 -315
- package/lib/credential-hash.js +322 -322
- package/lib/crypto.js +266 -266
- package/lib/csv.js +275 -286
- package/lib/db-declare-row-policy.js +267 -267
- package/lib/db-declare-view.js +420 -421
- 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/file-upload.js +213 -10
- package/lib/forms.js +422 -422
- package/lib/framework-error.js +293 -215
- package/lib/framework-schema.js +717 -717
- package/lib/gate-contract.js +971 -0
- package/lib/guard-all.js +405 -0
- package/lib/guard-archive.js +739 -0
- package/lib/guard-csv.js +816 -0
- package/lib/guard-email.js +744 -0
- package/lib/guard-filename.js +724 -0
- package/lib/guard-html.js +976 -0
- package/lib/guard-json.js +729 -0
- package/lib/guard-markdown.js +586 -0
- package/lib/guard-svg.js +976 -0
- package/lib/guard-xml.js +405 -0
- package/lib/guard-yaml.js +529 -0
- 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 -362
- package/lib/mail.js +981 -962
- 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/body-parser.js +1170 -1091
- 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 +316 -316
- package/lib/middleware/db-role-for.js +264 -264
- package/lib/middleware/health.js +392 -392
- package/lib/middleware/index.js +79 -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 +116 -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 -91
- 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 +478 -478
- package/lib/slug.js +269 -269
- package/lib/ssrf-guard.js +401 -401
- package/lib/static.js +184 -4
- 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 -319
- 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,197 +1,197 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Object-store dispatcher — protocol-agnostic remote (and local) storage.
|
|
4
|
-
*
|
|
5
|
-
* The framework's storage abstraction (lib/storage.js) routes per-classification
|
|
6
|
-
* requests to one or more configured backends. Each backend is constructed
|
|
7
|
-
* here from a config object that picks a protocol and provides its options:
|
|
8
|
-
*
|
|
9
|
-
* protocol: 'local' → lib/object-store/local.js
|
|
10
|
-
* protocol: 'http-put' → lib/object-store/http-put.js
|
|
11
|
-
* protocol: 'sigv4' (S3 / R2 / B2 / MinIO / Wasabi / Tigris / DO Spaces /
|
|
12
|
-
* IDrive e2 / Linode Object Storage / Storj / etc.)
|
|
13
|
-
* → lib/object-store/sigv4.js
|
|
14
|
-
* protocol: 'gcs' (Google Cloud Storage native — HMAC + native API)
|
|
15
|
-
* → lib/object-store/gcs.js
|
|
16
|
-
* protocol: 'azure-blob' → lib/object-store/azure-blob.js
|
|
17
|
-
*
|
|
18
|
-
* Every backend is wrapped with retry + circuit-breaker so transient
|
|
19
|
-
* failures don't surface as call-site errors and persistent failures
|
|
20
|
-
* don't pile up retry storms.
|
|
21
|
-
*
|
|
22
|
-
* Common API across protocols:
|
|
23
|
-
* put(key, body, opts?) → { size, etag? }
|
|
24
|
-
* get(key) → Buffer
|
|
25
|
-
* getStream(key) → Readable
|
|
26
|
-
* head(key) → { size, etag?, lastModified? }
|
|
27
|
-
* delete(key) → boolean (true if deleted, false if missing)
|
|
28
|
-
* list(prefix, opts?) → { items: [{ key, size, lastModified }], truncated }
|
|
29
|
-
*/
|
|
30
|
-
var localProto = require("./local");
|
|
31
|
-
var httpPutProto = require("./http-put");
|
|
32
|
-
var sigv4Proto = require("./sigv4");
|
|
33
|
-
var sigv4BucketOps = require("./sigv4-bucket-ops");
|
|
34
|
-
var gcsProto = require("./gcs");
|
|
35
|
-
var gcsBucketOps = require("./gcs-bucket-ops");
|
|
36
|
-
var azureBlobProto = require("./azure-blob");
|
|
37
|
-
var azureBlobBucketOps = require("./azure-blob-bucket-ops");
|
|
38
|
-
var retryHelper = require("../retry");
|
|
39
|
-
var protocolDispatcher = require("../protocol-dispatcher");
|
|
40
|
-
var { ObjectStoreError } = require("../framework-error");
|
|
41
|
-
|
|
42
|
-
// All currently advertised protocols are bundled. The dispatcher's
|
|
43
|
-
// `deferred` slot is the hook for adding deferred ones later.
|
|
44
|
-
var dispatcher = protocolDispatcher.create({
|
|
45
|
-
name: "object-store",
|
|
46
|
-
errorClass: ObjectStoreError,
|
|
47
|
-
protocols: {
|
|
48
|
-
"local": localProto,
|
|
49
|
-
"http-put": httpPutProto,
|
|
50
|
-
"sigv4": sigv4Proto,
|
|
51
|
-
"gcs": gcsProto,
|
|
52
|
-
"azure-blob": azureBlobProto,
|
|
53
|
-
},
|
|
54
|
-
deferred: {},
|
|
55
|
-
fallbackProtocol: "local",
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
var _err = ObjectStoreError.factory;
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Build a backend instance from a backend config block.
|
|
62
|
-
*
|
|
63
|
-
* config:
|
|
64
|
-
* {
|
|
65
|
-
* protocol: 'local' | 'http-put' | 'sigv4' | 'gcs' | 'azure-blob',
|
|
66
|
-
* // protocol-specific config (rootDir for local, baseUrl for http-put, etc.)
|
|
67
|
-
* classifications: ['personal' | 'operational' | 'public' | <custom>],
|
|
68
|
-
* residencyTag: 'EU' | 'US' | 'UK' | 'CA' | 'unrestricted' | <custom>,
|
|
69
|
-
* retry: { maxAttempts, baseDelayMs, maxDelayMs, jitterFactor },
|
|
70
|
-
* breaker: { failureThreshold, cooldownMs, successThreshold },
|
|
71
|
-
* name: <stable-id-for-circuit-breaker>,
|
|
72
|
-
* }
|
|
73
|
-
*/
|
|
74
|
-
function buildBackend(config) {
|
|
75
|
-
if (!config) {
|
|
76
|
-
throw new Error("object-store backend requires { protocol }");
|
|
77
|
-
}
|
|
78
|
-
var proto = dispatcher.resolve(config.protocol);
|
|
79
|
-
var raw = proto.create(config);
|
|
80
|
-
|
|
81
|
-
// Validate classifications + residencyTag
|
|
82
|
-
var classifications = Array.isArray(config.classifications) && config.classifications.length > 0
|
|
83
|
-
? config.classifications.slice()
|
|
84
|
-
: ["*"]; // wildcard: backend serves any classification
|
|
85
|
-
var residencyTag = config.residencyTag || "unrestricted";
|
|
86
|
-
|
|
87
|
-
// Wrap protocol calls with retry + circuit breaker
|
|
88
|
-
var breaker = new retryHelper.CircuitBreaker(
|
|
89
|
-
config.name || (config.protocol + ":" + (raw.rootDir || raw.baseUrl || "anonymous")),
|
|
90
|
-
config.breaker
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
function wrap(name) {
|
|
94
|
-
var inner = raw[name];
|
|
95
|
-
if (typeof inner !== "function") return inner;
|
|
96
|
-
return function () {
|
|
97
|
-
var args = Array.prototype.slice.call(arguments);
|
|
98
|
-
// For sync methods (getStream returns a Readable directly, not a Promise):
|
|
99
|
-
if (name === "getStream") {
|
|
100
|
-
// Apply circuit breaker only — getStream is sync, retry doesn't apply.
|
|
101
|
-
// The Readable will surface its own errors as the consumer reads it.
|
|
102
|
-
return inner.apply(raw, args);
|
|
103
|
-
}
|
|
104
|
-
return retryHelper.withRetry(function () {
|
|
105
|
-
return breaker.wrap(function () {
|
|
106
|
-
return inner.apply(raw, args);
|
|
107
|
-
});
|
|
108
|
-
}, config.retry);
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return {
|
|
113
|
-
name: config.name || config.protocol,
|
|
114
|
-
protocol: config.protocol,
|
|
115
|
-
classifications: classifications,
|
|
116
|
-
residencyTag: residencyTag,
|
|
117
|
-
breaker: breaker,
|
|
118
|
-
raw: raw,
|
|
119
|
-
put: wrap("put"),
|
|
120
|
-
get: wrap("get"),
|
|
121
|
-
getStream: wrap("getStream"),
|
|
122
|
-
head: wrap("head"),
|
|
123
|
-
delete: wrap("delete"),
|
|
124
|
-
list: wrap("list"),
|
|
125
|
-
// presigned*Url are sync URL-builders (no network call), so they
|
|
126
|
-
// bypass retry + circuit-breaker — propagate any throw directly.
|
|
127
|
-
presignedUploadUrl: typeof raw.presignedUploadUrl === "function"
|
|
128
|
-
? raw.presignedUploadUrl.bind(raw) : null,
|
|
129
|
-
presignedDownloadUrl: typeof raw.presignedDownloadUrl === "function"
|
|
130
|
-
? raw.presignedDownloadUrl.bind(raw) : null,
|
|
131
|
-
presignedUploadPolicy: typeof raw.presignedUploadPolicy === "function"
|
|
132
|
-
? raw.presignedUploadPolicy.bind(raw) : null,
|
|
133
|
-
servesClassification: function (cls) {
|
|
134
|
-
return classifications.indexOf("*") !== -1 || classifications.indexOf(cls) !== -1;
|
|
135
|
-
},
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// ---- Bucket-level ops dispatcher ----
|
|
140
|
-
//
|
|
141
|
-
// Bucket lifecycle (create / delete / list) + lifecycle / CORS rules
|
|
142
|
-
// are service-scoped, not bucket-scoped — `b.objectStore.bucketOps`
|
|
143
|
-
// resolves a per-cloud factory by protocol. Each cloud's ops shape
|
|
144
|
-
// differs (S3 sigv4 vs Azure Shared Key vs GCS OAuth) so the
|
|
145
|
-
// per-protocol modules each own their own validation, signing, and
|
|
146
|
-
// REST-API translation; this dispatcher just routes.
|
|
147
|
-
//
|
|
148
|
-
// Operator entry point — unchanged from v0.6.x:
|
|
149
|
-
//
|
|
150
|
-
// var ops = b.objectStore.bucketOps.create({
|
|
151
|
-
// protocol: 'sigv4' | 'azure-blob' | 'gcs',
|
|
152
|
-
// // ... protocol-specific creds ...
|
|
153
|
-
// });
|
|
154
|
-
//
|
|
155
|
-
// Each returned ops object exposes (where supported per-cloud):
|
|
156
|
-
// ops.create(name, opts?)
|
|
157
|
-
// ops.delete(name)
|
|
158
|
-
// ops.list(opts?)
|
|
159
|
-
// ops.setLifecycle(name, rules)
|
|
160
|
-
// ops.setCorsRules(name, rules) // sigv4 + gcs accept (name, rules);
|
|
161
|
-
// // azure-blob accepts (rules) — its
|
|
162
|
-
// // CORS is account-level.
|
|
163
|
-
var BUCKET_OPS_BY_PROTOCOL = {
|
|
164
|
-
"sigv4": sigv4BucketOps,
|
|
165
|
-
"gcs": gcsBucketOps,
|
|
166
|
-
"azure-blob": azureBlobBucketOps,
|
|
167
|
-
};
|
|
168
|
-
function _bucketOpsCreate(config) {
|
|
169
|
-
if (!config) {
|
|
170
|
-
throw _err("BAD_OPT",
|
|
171
|
-
"objectStore.bucketOps.create: config required (must include " +
|
|
172
|
-
"{ protocol })", true);
|
|
173
|
-
}
|
|
174
|
-
var protoMod = BUCKET_OPS_BY_PROTOCOL[config.protocol];
|
|
175
|
-
if (!protoMod) {
|
|
176
|
-
throw _err("UNKNOWN_PROTOCOL",
|
|
177
|
-
"objectStore.bucketOps.create: unknown protocol '" + config.protocol +
|
|
178
|
-
"' (supported: " + Object.keys(BUCKET_OPS_BY_PROTOCOL).join(", ") +
|
|
179
|
-
")", true);
|
|
180
|
-
}
|
|
181
|
-
return protoMod.create(config);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
module.exports = {
|
|
185
|
-
buildBackend: buildBackend,
|
|
186
|
-
PROTOCOLS: dispatcher.protocols,
|
|
187
|
-
DEFERRED_PROTOCOLS: dispatcher.deferred,
|
|
188
|
-
bucketOps: {
|
|
189
|
-
create: _bucketOpsCreate,
|
|
190
|
-
PROTOCOLS: Object.keys(BUCKET_OPS_BY_PROTOCOL),
|
|
191
|
-
// Per-protocol modules exposed for advanced operators wiring
|
|
192
|
-
// their own dispatch / testing harnesses against a specific cloud.
|
|
193
|
-
sigv4: sigv4BucketOps,
|
|
194
|
-
gcs: gcsBucketOps,
|
|
195
|
-
"azure-blob": azureBlobBucketOps,
|
|
196
|
-
},
|
|
197
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Object-store dispatcher — protocol-agnostic remote (and local) storage.
|
|
4
|
+
*
|
|
5
|
+
* The framework's storage abstraction (lib/storage.js) routes per-classification
|
|
6
|
+
* requests to one or more configured backends. Each backend is constructed
|
|
7
|
+
* here from a config object that picks a protocol and provides its options:
|
|
8
|
+
*
|
|
9
|
+
* protocol: 'local' → lib/object-store/local.js
|
|
10
|
+
* protocol: 'http-put' → lib/object-store/http-put.js
|
|
11
|
+
* protocol: 'sigv4' (S3 / R2 / B2 / MinIO / Wasabi / Tigris / DO Spaces /
|
|
12
|
+
* IDrive e2 / Linode Object Storage / Storj / etc.)
|
|
13
|
+
* → lib/object-store/sigv4.js
|
|
14
|
+
* protocol: 'gcs' (Google Cloud Storage native — HMAC + native API)
|
|
15
|
+
* → lib/object-store/gcs.js
|
|
16
|
+
* protocol: 'azure-blob' → lib/object-store/azure-blob.js
|
|
17
|
+
*
|
|
18
|
+
* Every backend is wrapped with retry + circuit-breaker so transient
|
|
19
|
+
* failures don't surface as call-site errors and persistent failures
|
|
20
|
+
* don't pile up retry storms.
|
|
21
|
+
*
|
|
22
|
+
* Common API across protocols:
|
|
23
|
+
* put(key, body, opts?) → { size, etag? }
|
|
24
|
+
* get(key) → Buffer
|
|
25
|
+
* getStream(key) → Readable
|
|
26
|
+
* head(key) → { size, etag?, lastModified? }
|
|
27
|
+
* delete(key) → boolean (true if deleted, false if missing)
|
|
28
|
+
* list(prefix, opts?) → { items: [{ key, size, lastModified }], truncated }
|
|
29
|
+
*/
|
|
30
|
+
var localProto = require("./local");
|
|
31
|
+
var httpPutProto = require("./http-put");
|
|
32
|
+
var sigv4Proto = require("./sigv4");
|
|
33
|
+
var sigv4BucketOps = require("./sigv4-bucket-ops");
|
|
34
|
+
var gcsProto = require("./gcs");
|
|
35
|
+
var gcsBucketOps = require("./gcs-bucket-ops");
|
|
36
|
+
var azureBlobProto = require("./azure-blob");
|
|
37
|
+
var azureBlobBucketOps = require("./azure-blob-bucket-ops");
|
|
38
|
+
var retryHelper = require("../retry");
|
|
39
|
+
var protocolDispatcher = require("../protocol-dispatcher");
|
|
40
|
+
var { ObjectStoreError } = require("../framework-error");
|
|
41
|
+
|
|
42
|
+
// All currently advertised protocols are bundled. The dispatcher's
|
|
43
|
+
// `deferred` slot is the hook for adding deferred ones later.
|
|
44
|
+
var dispatcher = protocolDispatcher.create({
|
|
45
|
+
name: "object-store",
|
|
46
|
+
errorClass: ObjectStoreError,
|
|
47
|
+
protocols: {
|
|
48
|
+
"local": localProto,
|
|
49
|
+
"http-put": httpPutProto,
|
|
50
|
+
"sigv4": sigv4Proto,
|
|
51
|
+
"gcs": gcsProto,
|
|
52
|
+
"azure-blob": azureBlobProto,
|
|
53
|
+
},
|
|
54
|
+
deferred: {},
|
|
55
|
+
fallbackProtocol: "local",
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
var _err = ObjectStoreError.factory;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Build a backend instance from a backend config block.
|
|
62
|
+
*
|
|
63
|
+
* config:
|
|
64
|
+
* {
|
|
65
|
+
* protocol: 'local' | 'http-put' | 'sigv4' | 'gcs' | 'azure-blob',
|
|
66
|
+
* // protocol-specific config (rootDir for local, baseUrl for http-put, etc.)
|
|
67
|
+
* classifications: ['personal' | 'operational' | 'public' | <custom>],
|
|
68
|
+
* residencyTag: 'EU' | 'US' | 'UK' | 'CA' | 'unrestricted' | <custom>,
|
|
69
|
+
* retry: { maxAttempts, baseDelayMs, maxDelayMs, jitterFactor },
|
|
70
|
+
* breaker: { failureThreshold, cooldownMs, successThreshold },
|
|
71
|
+
* name: <stable-id-for-circuit-breaker>,
|
|
72
|
+
* }
|
|
73
|
+
*/
|
|
74
|
+
function buildBackend(config) {
|
|
75
|
+
if (!config) {
|
|
76
|
+
throw new Error("object-store backend requires { protocol }");
|
|
77
|
+
}
|
|
78
|
+
var proto = dispatcher.resolve(config.protocol);
|
|
79
|
+
var raw = proto.create(config);
|
|
80
|
+
|
|
81
|
+
// Validate classifications + residencyTag
|
|
82
|
+
var classifications = Array.isArray(config.classifications) && config.classifications.length > 0
|
|
83
|
+
? config.classifications.slice()
|
|
84
|
+
: ["*"]; // wildcard: backend serves any classification
|
|
85
|
+
var residencyTag = config.residencyTag || "unrestricted";
|
|
86
|
+
|
|
87
|
+
// Wrap protocol calls with retry + circuit breaker
|
|
88
|
+
var breaker = new retryHelper.CircuitBreaker(
|
|
89
|
+
config.name || (config.protocol + ":" + (raw.rootDir || raw.baseUrl || "anonymous")),
|
|
90
|
+
config.breaker
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
function wrap(name) {
|
|
94
|
+
var inner = raw[name];
|
|
95
|
+
if (typeof inner !== "function") return inner;
|
|
96
|
+
return function () {
|
|
97
|
+
var args = Array.prototype.slice.call(arguments);
|
|
98
|
+
// For sync methods (getStream returns a Readable directly, not a Promise):
|
|
99
|
+
if (name === "getStream") {
|
|
100
|
+
// Apply circuit breaker only — getStream is sync, retry doesn't apply.
|
|
101
|
+
// The Readable will surface its own errors as the consumer reads it.
|
|
102
|
+
return inner.apply(raw, args);
|
|
103
|
+
}
|
|
104
|
+
return retryHelper.withRetry(function () {
|
|
105
|
+
return breaker.wrap(function () {
|
|
106
|
+
return inner.apply(raw, args);
|
|
107
|
+
});
|
|
108
|
+
}, config.retry);
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
name: config.name || config.protocol,
|
|
114
|
+
protocol: config.protocol,
|
|
115
|
+
classifications: classifications,
|
|
116
|
+
residencyTag: residencyTag,
|
|
117
|
+
breaker: breaker,
|
|
118
|
+
raw: raw,
|
|
119
|
+
put: wrap("put"),
|
|
120
|
+
get: wrap("get"),
|
|
121
|
+
getStream: wrap("getStream"),
|
|
122
|
+
head: wrap("head"),
|
|
123
|
+
delete: wrap("delete"),
|
|
124
|
+
list: wrap("list"),
|
|
125
|
+
// presigned*Url are sync URL-builders (no network call), so they
|
|
126
|
+
// bypass retry + circuit-breaker — propagate any throw directly.
|
|
127
|
+
presignedUploadUrl: typeof raw.presignedUploadUrl === "function"
|
|
128
|
+
? raw.presignedUploadUrl.bind(raw) : null,
|
|
129
|
+
presignedDownloadUrl: typeof raw.presignedDownloadUrl === "function"
|
|
130
|
+
? raw.presignedDownloadUrl.bind(raw) : null,
|
|
131
|
+
presignedUploadPolicy: typeof raw.presignedUploadPolicy === "function"
|
|
132
|
+
? raw.presignedUploadPolicy.bind(raw) : null,
|
|
133
|
+
servesClassification: function (cls) {
|
|
134
|
+
return classifications.indexOf("*") !== -1 || classifications.indexOf(cls) !== -1;
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ---- Bucket-level ops dispatcher ----
|
|
140
|
+
//
|
|
141
|
+
// Bucket lifecycle (create / delete / list) + lifecycle / CORS rules
|
|
142
|
+
// are service-scoped, not bucket-scoped — `b.objectStore.bucketOps`
|
|
143
|
+
// resolves a per-cloud factory by protocol. Each cloud's ops shape
|
|
144
|
+
// differs (S3 sigv4 vs Azure Shared Key vs GCS OAuth) so the
|
|
145
|
+
// per-protocol modules each own their own validation, signing, and
|
|
146
|
+
// REST-API translation; this dispatcher just routes.
|
|
147
|
+
//
|
|
148
|
+
// Operator entry point — unchanged from v0.6.x:
|
|
149
|
+
//
|
|
150
|
+
// var ops = b.objectStore.bucketOps.create({
|
|
151
|
+
// protocol: 'sigv4' | 'azure-blob' | 'gcs',
|
|
152
|
+
// // ... protocol-specific creds ...
|
|
153
|
+
// });
|
|
154
|
+
//
|
|
155
|
+
// Each returned ops object exposes (where supported per-cloud):
|
|
156
|
+
// ops.create(name, opts?)
|
|
157
|
+
// ops.delete(name)
|
|
158
|
+
// ops.list(opts?)
|
|
159
|
+
// ops.setLifecycle(name, rules)
|
|
160
|
+
// ops.setCorsRules(name, rules) // sigv4 + gcs accept (name, rules);
|
|
161
|
+
// // azure-blob accepts (rules) — its
|
|
162
|
+
// // CORS is account-level.
|
|
163
|
+
var BUCKET_OPS_BY_PROTOCOL = {
|
|
164
|
+
"sigv4": sigv4BucketOps,
|
|
165
|
+
"gcs": gcsBucketOps,
|
|
166
|
+
"azure-blob": azureBlobBucketOps,
|
|
167
|
+
};
|
|
168
|
+
function _bucketOpsCreate(config) {
|
|
169
|
+
if (!config) {
|
|
170
|
+
throw _err("BAD_OPT",
|
|
171
|
+
"objectStore.bucketOps.create: config required (must include " +
|
|
172
|
+
"{ protocol })", true);
|
|
173
|
+
}
|
|
174
|
+
var protoMod = BUCKET_OPS_BY_PROTOCOL[config.protocol];
|
|
175
|
+
if (!protoMod) {
|
|
176
|
+
throw _err("UNKNOWN_PROTOCOL",
|
|
177
|
+
"objectStore.bucketOps.create: unknown protocol '" + config.protocol +
|
|
178
|
+
"' (supported: " + Object.keys(BUCKET_OPS_BY_PROTOCOL).join(", ") +
|
|
179
|
+
")", true);
|
|
180
|
+
}
|
|
181
|
+
return protoMod.create(config);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
module.exports = {
|
|
185
|
+
buildBackend: buildBackend,
|
|
186
|
+
PROTOCOLS: dispatcher.protocols,
|
|
187
|
+
DEFERRED_PROTOCOLS: dispatcher.deferred,
|
|
188
|
+
bucketOps: {
|
|
189
|
+
create: _bucketOpsCreate,
|
|
190
|
+
PROTOCOLS: Object.keys(BUCKET_OPS_BY_PROTOCOL),
|
|
191
|
+
// Per-protocol modules exposed for advanced operators wiring
|
|
192
|
+
// their own dispatch / testing harnesses against a specific cloud.
|
|
193
|
+
sigv4: sigv4BucketOps,
|
|
194
|
+
gcs: gcsBucketOps,
|
|
195
|
+
"azure-blob": azureBlobBucketOps,
|
|
196
|
+
},
|
|
197
|
+
};
|