@qrvey/object-storage 2.0.2-1167 → 2.0.3-beta

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.
@@ -1,1600 +0,0 @@
1
- import { __name, __publicField, __spreadProps, __spreadValues, __asyncGenerator, __await, __yieldStar, __forAwait } from './chunk-66BQA4WX.mjs';
2
- import { backOff } from 'exponential-backoff';
3
- import { LoggerService } from '@qrvey/telemetry';
4
- import { S3Client, GetObjectCommand, HeadObjectCommand, PutObjectCommand, DeleteObjectCommand, DeleteObjectsCommand, ListObjectsV2Command, HeadBucketCommand, CreateMultipartUploadCommand, UploadPartCommand, CompleteMultipartUploadCommand, AbortMultipartUploadCommand, ListPartsCommand, ListMultipartUploadsCommand } from '@aws-sdk/client-s3';
5
- import { fromTokenFile, fromTemporaryCredentials, fromNodeProviderChain } from '@aws-sdk/credential-providers';
6
- import { NodeHttpHandler } from '@smithy/node-http-handler';
7
- import { Agent } from 'https';
8
- import { createHash, randomUUID } from 'crypto';
9
- import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
10
- import { Upload } from '@aws-sdk/lib-storage';
11
- import { Readable, PassThrough } from 'stream';
12
- import { BlobServiceClient, StorageSharedKeyCredential, BlobSASPermissions } from '@azure/storage-blob';
13
- import { DefaultAzureCredential } from '@azure/identity';
14
-
15
- // src/core/errors.ts
16
- var _StorageError = class _StorageError extends Error {
17
- constructor(options) {
18
- super(options.message);
19
- __publicField(this, "code");
20
- __publicField(this, "retryable");
21
- __publicField(this, "provider");
22
- __publicField(this, "requestId");
23
- __publicField(this, "cause");
24
- this.name = new.target.name;
25
- this.code = options.code;
26
- this.retryable = options.retryable;
27
- this.provider = options.provider;
28
- this.requestId = options.requestId;
29
- this.cause = options.cause;
30
- }
31
- };
32
- __name(_StorageError, "StorageError");
33
- var StorageError = _StorageError;
34
- var _ThrottledError = class _ThrottledError extends StorageError {
35
- constructor(options) {
36
- super(__spreadProps(__spreadValues({
37
- code: "THROTTLED"
38
- }, options), {
39
- retryable: true
40
- }));
41
- __publicField(this, "retryAfterMs");
42
- this.retryAfterMs = options.retryAfterMs;
43
- }
44
- };
45
- __name(_ThrottledError, "ThrottledError");
46
- var ThrottledError = _ThrottledError;
47
- var _NotFoundError = class _NotFoundError extends StorageError {
48
- constructor(options) {
49
- super(__spreadValues({
50
- code: "NOT_FOUND",
51
- retryable: false
52
- }, options));
53
- }
54
- };
55
- __name(_NotFoundError, "NotFoundError");
56
- var NotFoundError = _NotFoundError;
57
- var _AuthError = class _AuthError extends StorageError {
58
- constructor(options) {
59
- super(__spreadValues({
60
- code: "AUTH",
61
- retryable: false
62
- }, options));
63
- }
64
- };
65
- __name(_AuthError, "AuthError");
66
- var AuthError = _AuthError;
67
- var _ValidationError = class _ValidationError extends StorageError {
68
- constructor(options) {
69
- super(__spreadValues({
70
- code: "VALIDATION",
71
- retryable: false
72
- }, options));
73
- }
74
- };
75
- __name(_ValidationError, "ValidationError");
76
- var ValidationError = _ValidationError;
77
- var _ConfigurationError = class _ConfigurationError extends StorageError {
78
- constructor(options) {
79
- super(__spreadValues({
80
- code: "CONFIGURATION",
81
- retryable: false
82
- }, options));
83
- }
84
- };
85
- __name(_ConfigurationError, "ConfigurationError");
86
- var ConfigurationError = _ConfigurationError;
87
- var _NetworkError = class _NetworkError extends StorageError {
88
- constructor(options) {
89
- super(__spreadValues({
90
- code: "NETWORK",
91
- retryable: true
92
- }, options));
93
- }
94
- };
95
- __name(_NetworkError, "NetworkError");
96
- var NetworkError = _NetworkError;
97
- var _IntegrityError = class _IntegrityError extends StorageError {
98
- constructor(options) {
99
- super(__spreadValues({
100
- code: "INTEGRITY",
101
- retryable: false
102
- }, options));
103
- }
104
- };
105
- __name(_IntegrityError, "IntegrityError");
106
- var IntegrityError = _IntegrityError;
107
- var _MultipartSessionError = class _MultipartSessionError extends StorageError {
108
- constructor(options) {
109
- super(__spreadValues({
110
- code: "MULTIPART_SESSION",
111
- retryable: false
112
- }, options));
113
- }
114
- };
115
- __name(_MultipartSessionError, "MultipartSessionError");
116
- var MultipartSessionError = _MultipartSessionError;
117
-
118
- // src/core/providerRegistry.ts
119
- var envDefaults = /* @__PURE__ */ new Map();
120
- function registerProviderEnvDefaults(providerId, factory) {
121
- envDefaults.set(providerId, factory);
122
- }
123
- __name(registerProviderEnvDefaults, "registerProviderEnvDefaults");
124
- function resolveOptionsFromEnv(env = process.env) {
125
- var _a3, _b;
126
- const providerId = (_a3 = env.OBJECT_STORAGE_SERVICE) == null ? void 0 : _a3.toLowerCase();
127
- const factory = providerId ? envDefaults.get(providerId) : void 0;
128
- if (!factory) {
129
- throw new ConfigurationError({
130
- message: `Unsupported or missing OBJECT_STORAGE_SERVICE: "${(_b = env.OBJECT_STORAGE_SERVICE) != null ? _b : ""}". Registered providers: ${[
131
- ...envDefaults.keys()
132
- ].join(", ")}`
133
- });
134
- }
135
- return factory(env);
136
- }
137
- __name(resolveOptionsFromEnv, "resolveOptionsFromEnv");
138
- function resolveObjectStorageOptions(options, env = process.env) {
139
- return options != null ? options : resolveOptionsFromEnv(env);
140
- }
141
- __name(resolveObjectStorageOptions, "resolveObjectStorageOptions");
142
- var logger = new LoggerService("@qrvey/object-storage");
143
-
144
- // src/core/instrumentation.ts
145
- function recordRetry(code) {
146
- logger.warn("objectstorage.retry", {
147
- code: code != null ? code : "unknown"
148
- });
149
- }
150
- __name(recordRetry, "recordRetry");
151
- function recordThrottle(provider) {
152
- logger.warn("objectstorage.throttle", {
153
- provider: provider != null ? provider : "unknown"
154
- });
155
- }
156
- __name(recordThrottle, "recordThrottle");
157
- async function instrument(provider, operation, fn) {
158
- const startedAt = Date.now();
159
- try {
160
- const result = await fn();
161
- logger.debug("objectstorage.operation", {
162
- provider,
163
- operation,
164
- result: "ok",
165
- durationMs: Date.now() - startedAt
166
- });
167
- return result;
168
- } catch (error) {
169
- const meta = {
170
- provider,
171
- operation,
172
- result: "error",
173
- durationMs: Date.now() - startedAt
174
- };
175
- if (error instanceof StorageError) {
176
- meta.code = error.code;
177
- meta.retryable = error.retryable;
178
- if (error.requestId)
179
- meta.requestId = error.requestId;
180
- }
181
- logger.error("objectstorage.operation", meta);
182
- throw error;
183
- }
184
- }
185
- __name(instrument, "instrument");
186
-
187
- // src/core/retry.ts
188
- var DEFAULTS = {
189
- numOfAttempts: 5,
190
- startingDelayMs: 100,
191
- maxDelayMs: 5e3
192
- };
193
- function isRetryableError(error) {
194
- return error instanceof StorageError && error.retryable;
195
- }
196
- __name(isRetryableError, "isRetryableError");
197
- async function withRetry(fn, policy = {}) {
198
- var _a3;
199
- const { numOfAttempts, startingDelayMs, maxDelayMs } = __spreadValues(__spreadValues({}, DEFAULTS), policy);
200
- const shouldRetry = (_a3 = policy.retry) != null ? _a3 : isRetryableError;
201
- const options = {
202
- numOfAttempts,
203
- startingDelay: startingDelayMs,
204
- maxDelay: maxDelayMs,
205
- jitter: "full",
206
- retry: async (error, attempt) => {
207
- if (!shouldRetry(error, attempt))
208
- return false;
209
- const code = error instanceof StorageError ? error.code : void 0;
210
- recordRetry(code);
211
- if (error instanceof ThrottledError) {
212
- recordThrottle(error.provider);
213
- }
214
- logger.warn("object-storage operation retry", {
215
- attempt,
216
- numOfAttempts,
217
- code
218
- });
219
- if (error instanceof ThrottledError && error.retryAfterMs !== void 0) {
220
- await sleep(Math.min(error.retryAfterMs, maxDelayMs));
221
- }
222
- return true;
223
- }
224
- };
225
- return backOff(fn, options);
226
- }
227
- __name(withRetry, "withRetry");
228
- function sleep(ms) {
229
- return new Promise((resolve) => setTimeout(resolve, ms));
230
- }
231
- __name(sleep, "sleep");
232
-
233
- // src/core/concurrency.ts
234
- function createLimiter(options) {
235
- var _a3, _b;
236
- const ceiling = options.max;
237
- const floor = (_a3 = options.minMax) != null ? _a3 : 1;
238
- const growthThreshold = (_b = options.growthThreshold) != null ? _b : 10;
239
- let max = options.max;
240
- let inFlight = 0;
241
- let consecutiveSuccesses = 0;
242
- const queue = [];
243
- function release() {
244
- var _a4;
245
- inFlight--;
246
- (_a4 = queue.shift()) == null ? void 0 : _a4();
247
- }
248
- __name(release, "release");
249
- function acquire() {
250
- if (inFlight < max) {
251
- inFlight++;
252
- return Promise.resolve();
253
- }
254
- return new Promise((resolve) => queue.push(() => {
255
- inFlight++;
256
- resolve();
257
- }));
258
- }
259
- __name(acquire, "acquire");
260
- function onThrottle() {
261
- if (!options.adaptive)
262
- return;
263
- consecutiveSuccesses = 0;
264
- const reduced = Math.max(floor, Math.floor(max / 2));
265
- if (reduced < max) {
266
- max = reduced;
267
- logger.warn("object-storage limiter shrunk after throttle", {
268
- max
269
- });
270
- }
271
- }
272
- __name(onThrottle, "onThrottle");
273
- function onSuccess() {
274
- if (!options.adaptive || max >= ceiling)
275
- return;
276
- consecutiveSuccesses++;
277
- if (consecutiveSuccesses >= growthThreshold) {
278
- consecutiveSuccesses = 0;
279
- max = Math.min(ceiling, max + 1);
280
- }
281
- }
282
- __name(onSuccess, "onSuccess");
283
- return {
284
- async run(fn) {
285
- await acquire();
286
- try {
287
- const result = await fn();
288
- onSuccess();
289
- return result;
290
- } catch (error) {
291
- if (error instanceof ThrottledError)
292
- onThrottle();
293
- throw error;
294
- } finally {
295
- release();
296
- }
297
- },
298
- get inFlight() {
299
- return inFlight;
300
- },
301
- get pending() {
302
- return queue.length;
303
- },
304
- get currentMax() {
305
- return max;
306
- }
307
- };
308
- }
309
- __name(createLimiter, "createLimiter");
310
-
311
- // src/core/batch.ts
312
- function chunk(items, size) {
313
- const chunks = [];
314
- for (let i = 0; i < items.length; i += size) {
315
- chunks.push(items.slice(i, i + size));
316
- }
317
- return chunks;
318
- }
319
- __name(chunk, "chunk");
320
- async function mapBatched(items, batchSize, limiter, fn) {
321
- const batches = chunk(items, batchSize);
322
- return Promise.all(batches.map((batch, index) => limiter.run(() => fn(batch, index))));
323
- }
324
- __name(mapBatched, "mapBatched");
325
-
326
- // src/core/range.ts
327
- var BOUNDED = /^bytes=(\d+)-(\d+)?$/;
328
- var SUFFIX = /^bytes=-(\d+)$/;
329
- function parseRange(input) {
330
- const bounded = BOUNDED.exec(input);
331
- if (bounded && bounded[1] !== void 0) {
332
- const start = Number(bounded[1]);
333
- const end = bounded[2] !== void 0 ? Number(bounded[2]) : void 0;
334
- if (end !== void 0 && end < start) {
335
- throw new ValidationError({
336
- message: `Invalid range "${input}": end must be >= start`
337
- });
338
- }
339
- return {
340
- start,
341
- end
342
- };
343
- }
344
- const suffix = SUFFIX.exec(input);
345
- if (suffix && suffix[1] !== void 0) {
346
- return {
347
- suffixLength: Number(suffix[1])
348
- };
349
- }
350
- throw new ValidationError({
351
- message: `Invalid range "${input}": expected "bytes=start-[end]" or "bytes=-suffix"`
352
- });
353
- }
354
- __name(parseRange, "parseRange");
355
- function toRangeHeader(range) {
356
- var _a3;
357
- if (range.suffixLength !== void 0)
358
- return `bytes=-${range.suffixLength}`;
359
- return `bytes=${range.start}-${(_a3 = range.end) != null ? _a3 : ""}`;
360
- }
361
- __name(toRangeHeader, "toRangeHeader");
362
-
363
- // src/providers/aws-s3/config.ts
364
- var AWS_S3_PROVIDER_ID = "aws_s3";
365
- function isAwsS3StorageOptions(options) {
366
- return options.provider === AWS_S3_PROVIDER_ID;
367
- }
368
- __name(isAwsS3StorageOptions, "isAwsS3StorageOptions");
369
- function getDefaultAwsS3OptionsFromEnv(env = process.env) {
370
- const region = env.AWS_REGION || env.AWS_DEFAULT_REGION;
371
- if (!region) {
372
- throw new ConfigurationError({
373
- provider: AWS_S3_PROVIDER_ID,
374
- message: "Missing AWS_REGION (or AWS_DEFAULT_REGION) for aws_s3 provider"
375
- });
376
- }
377
- return {
378
- provider: AWS_S3_PROVIDER_ID,
379
- region,
380
- auth: {
381
- kind: "default"
382
- }
383
- };
384
- }
385
- __name(getDefaultAwsS3OptionsFromEnv, "getDefaultAwsS3OptionsFromEnv");
386
- registerProviderEnvDefaults(AWS_S3_PROVIDER_ID, getDefaultAwsS3OptionsFromEnv);
387
-
388
- // src/core/clientCache.ts
389
- var DEFAULT_MAX_SIZE = 32;
390
- var _ClientCache = class _ClientCache {
391
- constructor(options = {}) {
392
- __publicField(this, "options");
393
- __publicField(this, "entries");
394
- this.options = options;
395
- this.entries = /* @__PURE__ */ new Map();
396
- }
397
- getOrCreate(key, factory) {
398
- var _a3, _b, _c;
399
- const existing = this.entries.get(key);
400
- if (existing !== void 0) {
401
- this.entries.delete(key);
402
- this.entries.set(key, existing);
403
- return existing;
404
- }
405
- const client = factory();
406
- this.entries.set(key, client);
407
- logger.debug("object-storage client created", {
408
- size: this.entries.size
409
- });
410
- const maxSize = (_a3 = this.options.maxSize) != null ? _a3 : DEFAULT_MAX_SIZE;
411
- if (this.entries.size > maxSize) {
412
- const oldestKey = this.entries.keys().next().value;
413
- const oldest = this.entries.get(oldestKey);
414
- this.entries.delete(oldestKey);
415
- (_c = (_b = this.options).onEvict) == null ? void 0 : _c.call(_b, oldest, oldestKey);
416
- logger.warn("object-storage client evicted from cache", {
417
- maxSize
418
- });
419
- }
420
- return client;
421
- }
422
- get size() {
423
- return this.entries.size;
424
- }
425
- clear() {
426
- this.entries.clear();
427
- }
428
- };
429
- __name(_ClientCache, "ClientCache");
430
- var ClientCache = _ClientCache;
431
- function stableCacheKey(parts) {
432
- return JSON.stringify(sortDeep(parts));
433
- }
434
- __name(stableCacheKey, "stableCacheKey");
435
- function hashSecret(value) {
436
- return createHash("sha256").update(value).digest("hex").slice(0, 16);
437
- }
438
- __name(hashSecret, "hashSecret");
439
- function sortDeep(value) {
440
- if (Array.isArray(value))
441
- return value.map(sortDeep);
442
- if (value && typeof value === "object") {
443
- return Object.keys(value).sort().reduce((acc, key) => {
444
- acc[key] = sortDeep(value[key]);
445
- return acc;
446
- }, {});
447
- }
448
- return value;
449
- }
450
- __name(sortDeep, "sortDeep");
451
-
452
- // src/providers/aws-s3/clientFactory.ts
453
- var DEFAULT_HTTP = {
454
- connectionTimeoutMs: 5e3,
455
- requestTimeoutMs: 12e4,
456
- maxSockets: 64
457
- };
458
- var cache = new ClientCache({
459
- onEvict: (client) => client.destroy()
460
- });
461
- function getAwsS3Client(options) {
462
- var _a3;
463
- const auth = (_a3 = options.auth) != null ? _a3 : {
464
- kind: "default"
465
- };
466
- const key = stableCacheKey({
467
- provider: options.provider,
468
- region: options.region,
469
- endpoint: options.endpoint,
470
- http: options.http,
471
- auth: authKeyParts(auth)
472
- });
473
- return cache.getOrCreate(key, () => buildClient(options, auth));
474
- }
475
- __name(getAwsS3Client, "getAwsS3Client");
476
- function clearAwsS3ClientCache() {
477
- cache.clear();
478
- }
479
- __name(clearAwsS3ClientCache, "clearAwsS3ClientCache");
480
- function buildClient(options, auth) {
481
- const http = __spreadValues(__spreadValues({}, DEFAULT_HTTP), options.http);
482
- return new S3Client({
483
- region: options.region,
484
- endpoint: options.endpoint,
485
- credentials: credentialsFor(auth),
486
- requestHandler: new NodeHttpHandler({
487
- connectionTimeout: http.connectionTimeoutMs,
488
- requestTimeout: http.requestTimeoutMs,
489
- httpsAgent: new Agent({
490
- keepAlive: true,
491
- maxSockets: http.maxSockets
492
- })
493
- })
494
- });
495
- }
496
- __name(buildClient, "buildClient");
497
- function credentialsFor(auth) {
498
- switch (auth.kind) {
499
- case "default":
500
- return fromNodeProviderChain();
501
- case "static":
502
- return auth.credentials;
503
- case "assumeRole":
504
- return fromTemporaryCredentials({
505
- params: {
506
- RoleArn: auth.roleArn,
507
- ExternalId: auth.externalId,
508
- RoleSessionName: "qrvey-object-storage"
509
- }
510
- });
511
- case "webIdentity":
512
- return fromTokenFile(__spreadValues({
513
- roleArn: auth.roleArn
514
- }, auth.tokenFile && {
515
- webIdentityTokenFile: auth.tokenFile
516
- }));
517
- }
518
- }
519
- __name(credentialsFor, "credentialsFor");
520
- function authKeyParts(auth) {
521
- switch (auth.kind) {
522
- case "default":
523
- return {
524
- kind: auth.kind
525
- };
526
- case "static":
527
- return {
528
- kind: auth.kind,
529
- accessKeyId: auth.credentials.accessKeyId,
530
- secret: hashSecret(auth.credentials.secretAccessKey)
531
- };
532
- case "assumeRole":
533
- return {
534
- kind: auth.kind,
535
- roleArn: auth.roleArn,
536
- externalId: auth.externalId
537
- };
538
- case "webIdentity":
539
- return {
540
- kind: auth.kind,
541
- roleArn: auth.roleArn,
542
- tokenFile: auth.tokenFile
543
- };
544
- }
545
- }
546
- __name(authKeyParts, "authKeyParts");
547
-
548
- // src/providers/aws-s3/errors.ts
549
- var THROTTLE_NAMES = /* @__PURE__ */ new Set([
550
- "SlowDown",
551
- "ThrottlingException",
552
- "Throttling",
553
- "TooManyRequestsException",
554
- "RequestLimitExceeded",
555
- "ProvisionedThroughputExceededException"
556
- ]);
557
- var NOT_FOUND_NAMES = /* @__PURE__ */ new Set([
558
- "NoSuchKey",
559
- "NoSuchBucket",
560
- "NotFound",
561
- "NoSuchUpload"
562
- ]);
563
- var AUTH_NAMES = /* @__PURE__ */ new Set([
564
- "AccessDenied",
565
- "InvalidAccessKeyId",
566
- "SignatureDoesNotMatch",
567
- "ExpiredToken",
568
- "TokenRefreshRequired",
569
- "CredentialsProviderError"
570
- ]);
571
- function mapAwsError(error) {
572
- var _a3, _b, _c, _d, _e, _f;
573
- if (error instanceof StorageError)
574
- return error;
575
- const aws = error != null ? error : {};
576
- const name = (_a3 = aws.name) != null ? _a3 : "UnknownError";
577
- const message = (_b = aws.message) != null ? _b : String(error);
578
- const status = (_c = aws.$metadata) == null ? void 0 : _c.httpStatusCode;
579
- const base = {
580
- message: `${name}: ${message}`,
581
- provider: AWS_S3_PROVIDER_ID,
582
- requestId: (_d = aws.$metadata) == null ? void 0 : _d.requestId,
583
- cause: error
584
- };
585
- if (THROTTLE_NAMES.has(name) || status === 429) {
586
- const retryAfter = (_f = (_e = aws.$response) == null ? void 0 : _e.headers) == null ? void 0 : _f["retry-after"];
587
- return new ThrottledError(__spreadProps(__spreadValues({}, base), {
588
- code: name,
589
- retryAfterMs: retryAfter !== void 0 ? Number(retryAfter) * 1e3 : void 0
590
- }));
591
- }
592
- if (NOT_FOUND_NAMES.has(name) || status === 404) {
593
- return new NotFoundError(__spreadProps(__spreadValues({}, base), {
594
- code: name
595
- }));
596
- }
597
- if (AUTH_NAMES.has(name) || status === 403) {
598
- return new AuthError(__spreadProps(__spreadValues({}, base), {
599
- code: name
600
- }));
601
- }
602
- if (status !== void 0 && status >= 500 || name === "TimeoutError") {
603
- return new NetworkError(__spreadProps(__spreadValues({}, base), {
604
- code: name
605
- }));
606
- }
607
- return new StorageError(__spreadProps(__spreadValues({}, base), {
608
- code: name,
609
- retryable: false
610
- }));
611
- }
612
- __name(mapAwsError, "mapAwsError");
613
- var DELETE_BATCH_SIZE = 1e3;
614
- var DEFAULT_PRESIGN_SECONDS = 3600;
615
- var _AwsS3Provider = class _AwsS3Provider {
616
- constructor(config) {
617
- __publicField(this, "bucketName");
618
- __publicField(this, "multipart");
619
- __publicField(this, "client");
620
- __publicField(this, "retryPolicy");
621
- __publicField(this, "limiter");
622
- var _a3, _b;
623
- const resolved = resolveObjectStorageOptions(config.options);
624
- if (!isAwsS3StorageOptions(resolved)) {
625
- throw new ConfigurationError({
626
- message: `AwsS3Provider requires aws_s3 options, got provider "${resolved.provider}"`
627
- });
628
- }
629
- this.bucketName = config.bucketName;
630
- this.client = getAwsS3Client(resolved);
631
- this.retryPolicy = (_a3 = config.retry) != null ? _a3 : {};
632
- this.limiter = (_b = config.limiter) != null ? _b : createLimiter({
633
- max: 10,
634
- adaptive: true
635
- });
636
- this.multipart = new AwsS3MultipartClient(this.client, this.bucketName, this.retryPolicy, (operation, fn) => this.send(operation, fn));
637
- }
638
- send(operation, fn) {
639
- return instrument(AWS_S3_PROVIDER_ID, operation, () => withRetry(() => fn().catch((error) => Promise.reject(mapAwsError(error))), this.retryPolicy));
640
- }
641
- async getObject(key, options) {
642
- const range = (options == null ? void 0 : options.range) ? toRangeHeader(parseRange(options.range)) : void 0;
643
- const response = await this.send("getObject", () => this.client.send(new GetObjectCommand({
644
- Bucket: this.bucketName,
645
- Key: key,
646
- Range: range,
647
- VersionId: options == null ? void 0 : options.versionId
648
- })));
649
- return {
650
- body: response.Body,
651
- contentLength: response.ContentLength,
652
- contentType: response.ContentType,
653
- contentEncoding: response.ContentEncoding,
654
- contentDisposition: response.ContentDisposition,
655
- contentLanguage: response.ContentLanguage,
656
- cacheControl: response.CacheControl,
657
- etag: response.ETag,
658
- lastModified: response.LastModified,
659
- metadata: response.Metadata
660
- };
661
- }
662
- async getObjectProperties(key) {
663
- const response = await this.send("getObjectProperties", () => this.client.send(new HeadObjectCommand({
664
- Bucket: this.bucketName,
665
- Key: key
666
- })));
667
- return {
668
- contentLength: response.ContentLength,
669
- contentType: response.ContentType,
670
- etag: response.ETag,
671
- lastModified: response.LastModified,
672
- metadata: response.Metadata
673
- };
674
- }
675
- async upload(key, body, options) {
676
- if (body instanceof Readable) {
677
- return this.uploadStream(key, body, options);
678
- }
679
- const response = await this.send("upload", () => this.client.send(new PutObjectCommand(__spreadValues({
680
- Bucket: this.bucketName,
681
- Key: key,
682
- Body: body
683
- }, mapUploadOptions(options)))));
684
- return {
685
- key,
686
- etag: response.ETag,
687
- versionId: response.VersionId
688
- };
689
- }
690
- async uploadStream(key, body, options) {
691
- var _a3, _b;
692
- const upload = new Upload({
693
- client: this.client,
694
- params: __spreadValues({
695
- Bucket: this.bucketName,
696
- Key: key,
697
- Body: body
698
- }, mapUploadOptions(options)),
699
- queueSize: (_a3 = options == null ? void 0 : options.queueSize) != null ? _a3 : 5,
700
- partSize: (_b = options == null ? void 0 : options.partSizeBytes) != null ? _b : 8 * 1024 * 1024
701
- });
702
- return instrument(AWS_S3_PROVIDER_ID, "upload", async () => {
703
- try {
704
- const response = await upload.done();
705
- return {
706
- key,
707
- etag: response.ETag,
708
- versionId: response.VersionId
709
- };
710
- } catch (error) {
711
- throw mapAwsError(error);
712
- }
713
- });
714
- }
715
- createWriteStream(key, options) {
716
- var _a3, _b;
717
- const stream = new PassThrough();
718
- const upload = new Upload({
719
- client: this.client,
720
- params: __spreadValues({
721
- Bucket: this.bucketName,
722
- Key: key,
723
- Body: stream
724
- }, mapUploadOptions(options)),
725
- queueSize: (_a3 = options == null ? void 0 : options.queueSize) != null ? _a3 : 5,
726
- partSize: (_b = options == null ? void 0 : options.partSizeBytes) != null ? _b : 8 * 1024 * 1024
727
- });
728
- const done = instrument(AWS_S3_PROVIDER_ID, "createWriteStream", () => upload.done().then((response) => ({
729
- key,
730
- etag: response.ETag,
731
- versionId: response.VersionId
732
- })).catch((error) => Promise.reject(mapAwsError(error))));
733
- return {
734
- stream,
735
- done,
736
- abort: () => upload.abort()
737
- };
738
- }
739
- async delete(key) {
740
- await this.send("delete", () => this.client.send(new DeleteObjectCommand({
741
- Bucket: this.bucketName,
742
- Key: key
743
- })));
744
- }
745
- async deleteMany(keys) {
746
- const batchResults = await mapBatched(keys, DELETE_BATCH_SIZE, this.limiter, async (batch) => {
747
- var _a3;
748
- const response = await this.send("deleteMany", () => this.client.send(new DeleteObjectsCommand({
749
- Bucket: this.bucketName,
750
- Delete: {
751
- Objects: batch.map((key) => ({
752
- Key: key
753
- })),
754
- Quiet: false
755
- }
756
- })));
757
- const failed = new Map(((_a3 = response.Errors) != null ? _a3 : []).map((e) => {
758
- var _a4, _b;
759
- return [
760
- (_a4 = e.Key) != null ? _a4 : "",
761
- (_b = e.Message) != null ? _b : "delete failed"
762
- ];
763
- }));
764
- return batch.map((key) => ({
765
- key,
766
- deleted: !failed.has(key),
767
- error: failed.get(key)
768
- }));
769
- });
770
- return batchResults.flat();
771
- }
772
- async list(options) {
773
- var _a3;
774
- const response = await this.send("list", () => this.client.send(new ListObjectsV2Command({
775
- Bucket: this.bucketName,
776
- Prefix: options == null ? void 0 : options.prefix,
777
- MaxKeys: options == null ? void 0 : options.limit,
778
- ContinuationToken: options == null ? void 0 : options.continuationToken
779
- })));
780
- return {
781
- items: ((_a3 = response.Contents) != null ? _a3 : []).map(toObjectSummary),
782
- nextToken: response.NextContinuationToken
783
- };
784
- }
785
- iterate(options) {
786
- return __asyncGenerator(this, null, function* () {
787
- let token;
788
- do {
789
- const page = yield new __await(this.list({
790
- prefix: options == null ? void 0 : options.prefix,
791
- limit: options == null ? void 0 : options.pageSize,
792
- continuationToken: token
793
- }));
794
- yield* __yieldStar(page.items);
795
- token = page.nextToken;
796
- } while (token);
797
- });
798
- }
799
- async listAll(options) {
800
- const items = [];
801
- try {
802
- for (var iter = __forAwait(this.iterate(options)), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
803
- const item = temp.value;
804
- items.push(item);
805
- }
806
- } catch (temp) {
807
- error = [temp];
808
- } finally {
809
- try {
810
- more && (temp = iter.return) && await temp.call(iter);
811
- } finally {
812
- if (error)
813
- throw error[0];
814
- }
815
- }
816
- return items;
817
- }
818
- async headBucket() {
819
- try {
820
- await this.send("headBucket", () => this.client.send(new HeadBucketCommand({
821
- Bucket: this.bucketName
822
- })));
823
- return {
824
- exists: true
825
- };
826
- } catch (error) {
827
- if (error instanceof NotFoundError)
828
- return {
829
- exists: false
830
- };
831
- throw error;
832
- }
833
- }
834
- getDownloadUrl(key, options) {
835
- var _a3;
836
- return getSignedUrl(this.client, new GetObjectCommand({
837
- Bucket: this.bucketName,
838
- Key: key
839
- }), {
840
- expiresIn: (_a3 = options == null ? void 0 : options.expiresInSeconds) != null ? _a3 : DEFAULT_PRESIGN_SECONDS
841
- });
842
- }
843
- async getUploadUrl(key, options) {
844
- var _a3;
845
- const url = await getSignedUrl(this.client, new PutObjectCommand({
846
- Bucket: this.bucketName,
847
- Key: key,
848
- ContentType: options == null ? void 0 : options.contentType
849
- }), {
850
- expiresIn: (_a3 = options == null ? void 0 : options.expiresInSeconds) != null ? _a3 : DEFAULT_PRESIGN_SECONDS
851
- });
852
- return {
853
- key,
854
- url
855
- };
856
- }
857
- };
858
- __name(_AwsS3Provider, "AwsS3Provider");
859
- var AwsS3Provider = _AwsS3Provider;
860
- var _a;
861
- var AwsS3MultipartClient = (_a = class {
862
- constructor(client, bucketName, retryPolicy, send) {
863
- __publicField(this, "client");
864
- __publicField(this, "bucketName");
865
- __publicField(this, "retryPolicy");
866
- __publicField(this, "send");
867
- this.client = client;
868
- this.bucketName = bucketName;
869
- this.retryPolicy = retryPolicy;
870
- this.send = send;
871
- }
872
- async create(key, options) {
873
- const response = await this.send("multipart.create", () => this.client.send(new CreateMultipartUploadCommand(__spreadValues({
874
- Bucket: this.bucketName,
875
- Key: key
876
- }, mapUploadOptions(options)))));
877
- return {
878
- uploadId: response.UploadId
879
- };
880
- }
881
- async uploadPart(key, uploadId, partNumber, body, contentLengthBytes) {
882
- const response = await this.send("multipart.uploadPart", () => this.client.send(new UploadPartCommand({
883
- Bucket: this.bucketName,
884
- Key: key,
885
- UploadId: uploadId,
886
- PartNumber: partNumber,
887
- Body: body,
888
- ContentLength: contentLengthBytes
889
- })));
890
- return {
891
- partNumber,
892
- etag: response.ETag
893
- };
894
- }
895
- getPartUploadUrl(key, uploadId, partNumber, options) {
896
- var _a3;
897
- return getSignedUrl(this.client, new UploadPartCommand({
898
- Bucket: this.bucketName,
899
- Key: key,
900
- UploadId: uploadId,
901
- PartNumber: partNumber
902
- }), {
903
- expiresIn: (_a3 = options == null ? void 0 : options.expiresInSeconds) != null ? _a3 : DEFAULT_PRESIGN_SECONDS
904
- });
905
- }
906
- async complete(key, uploadId, parts) {
907
- const response = await this.send("multipart.complete", () => this.client.send(new CompleteMultipartUploadCommand({
908
- Bucket: this.bucketName,
909
- Key: key,
910
- UploadId: uploadId,
911
- MultipartUpload: {
912
- Parts: [
913
- ...parts
914
- ].sort((a, b) => a.partNumber - b.partNumber).map((p) => ({
915
- PartNumber: p.partNumber,
916
- ETag: p.etag
917
- }))
918
- }
919
- })));
920
- return {
921
- key,
922
- etag: response.ETag,
923
- versionId: response.VersionId
924
- };
925
- }
926
- async abort(key, uploadId) {
927
- await this.send("multipart.abort", () => this.client.send(new AbortMultipartUploadCommand({
928
- Bucket: this.bucketName,
929
- Key: key,
930
- UploadId: uploadId
931
- })));
932
- }
933
- async listParts(key, uploadId) {
934
- var _a3;
935
- const response = await this.send("multipart.listParts", () => this.client.send(new ListPartsCommand({
936
- Bucket: this.bucketName,
937
- Key: key,
938
- UploadId: uploadId
939
- })));
940
- return ((_a3 = response.Parts) != null ? _a3 : []).map((p) => ({
941
- partNumber: p.PartNumber,
942
- etag: p.ETag,
943
- size: p.Size,
944
- lastModified: p.LastModified
945
- }));
946
- }
947
- async listUploads(prefix) {
948
- var _a3;
949
- const response = await this.send("multipart.listUploads", () => this.client.send(new ListMultipartUploadsCommand({
950
- Bucket: this.bucketName,
951
- Prefix: prefix
952
- })));
953
- return ((_a3 = response.Uploads) != null ? _a3 : []).map((u) => ({
954
- key: u.Key,
955
- uploadId: u.UploadId,
956
- initiatedAt: u.Initiated
957
- }));
958
- }
959
- }, __name(_a, "AwsS3MultipartClient"), _a);
960
- function mapUploadOptions(options) {
961
- return {
962
- ContentType: options == null ? void 0 : options.contentType,
963
- ContentEncoding: options == null ? void 0 : options.contentEncoding,
964
- CacheControl: options == null ? void 0 : options.cacheControl,
965
- ContentDisposition: options == null ? void 0 : options.contentDisposition,
966
- Metadata: options == null ? void 0 : options.metadata
967
- };
968
- }
969
- __name(mapUploadOptions, "mapUploadOptions");
970
- function toObjectSummary(content) {
971
- return {
972
- key: content.Key,
973
- size: content.Size,
974
- etag: content.ETag,
975
- lastModified: content.LastModified
976
- };
977
- }
978
- __name(toObjectSummary, "toObjectSummary");
979
-
980
- // src/providers/azure-blob/config.ts
981
- var AZURE_BLOB_PROVIDER_ID = "azure_blob_storage";
982
- function isAzureBlobStorageOptions(options) {
983
- return options.provider === AZURE_BLOB_PROVIDER_ID;
984
- }
985
- __name(isAzureBlobStorageOptions, "isAzureBlobStorageOptions");
986
- function getDefaultAzureBlobOptionsFromEnv(env = process.env) {
987
- const connectionString = env.AZURE_DATALAKE_CONNECTION_STRING || env.AZURE_STORAGE_CONNECTION_STRING;
988
- if (!connectionString) {
989
- throw new ConfigurationError({
990
- provider: AZURE_BLOB_PROVIDER_ID,
991
- message: "Missing AZURE_DATALAKE_CONNECTION_STRING (or AZURE_STORAGE_CONNECTION_STRING) for azure_blob_storage provider"
992
- });
993
- }
994
- return {
995
- provider: AZURE_BLOB_PROVIDER_ID,
996
- auth: {
997
- kind: "connectionString",
998
- connectionString
999
- }
1000
- };
1001
- }
1002
- __name(getDefaultAzureBlobOptionsFromEnv, "getDefaultAzureBlobOptionsFromEnv");
1003
- registerProviderEnvDefaults(AZURE_BLOB_PROVIDER_ID, getDefaultAzureBlobOptionsFromEnv);
1004
- var cache2 = new ClientCache();
1005
- function getAzureBlobServiceClient(options) {
1006
- const key = stableCacheKey({
1007
- provider: options.provider,
1008
- endpoint: options.endpoint,
1009
- auth: authKeyParts2(options.auth)
1010
- });
1011
- return cache2.getOrCreate(key, () => buildClient2(options));
1012
- }
1013
- __name(getAzureBlobServiceClient, "getAzureBlobServiceClient");
1014
- function clearAzureBlobClientCache() {
1015
- cache2.clear();
1016
- }
1017
- __name(clearAzureBlobClientCache, "clearAzureBlobClientCache");
1018
- function buildClient2(options) {
1019
- const auth = options.auth;
1020
- switch (auth.kind) {
1021
- case "connectionString":
1022
- return BlobServiceClient.fromConnectionString(auth.connectionString);
1023
- case "accountKey":
1024
- return new BlobServiceClient(endpointFor(options, auth.accountName), new StorageSharedKeyCredential(auth.accountName, auth.accountKey));
1025
- case "sas":
1026
- return new BlobServiceClient(`${endpointFor(options, auth.accountName)}?${auth.sasToken.replace(/^\?/, "")}`);
1027
- case "workloadIdentity":
1028
- return new BlobServiceClient(endpointFor(options, auth.accountName), new DefaultAzureCredential());
1029
- }
1030
- }
1031
- __name(buildClient2, "buildClient");
1032
- function endpointFor(options, accountName) {
1033
- var _a3;
1034
- return (_a3 = options.endpoint) != null ? _a3 : `https://${accountName}.blob.core.windows.net`;
1035
- }
1036
- __name(endpointFor, "endpointFor");
1037
- function authKeyParts2(auth) {
1038
- switch (auth.kind) {
1039
- case "connectionString":
1040
- return {
1041
- kind: auth.kind,
1042
- connection: hashSecret(auth.connectionString)
1043
- };
1044
- case "accountKey":
1045
- return {
1046
- kind: auth.kind,
1047
- accountName: auth.accountName,
1048
- key: hashSecret(auth.accountKey)
1049
- };
1050
- case "sas":
1051
- return {
1052
- kind: auth.kind,
1053
- accountName: auth.accountName,
1054
- token: hashSecret(auth.sasToken)
1055
- };
1056
- case "workloadIdentity":
1057
- return {
1058
- kind: auth.kind,
1059
- accountName: auth.accountName
1060
- };
1061
- }
1062
- }
1063
- __name(authKeyParts2, "authKeyParts");
1064
-
1065
- // src/providers/azure-blob/errors.ts
1066
- var AUTH_CODES = /* @__PURE__ */ new Set([
1067
- "AuthenticationFailed",
1068
- "AuthorizationFailure",
1069
- "AuthorizationPermissionMismatch",
1070
- "InsufficientAccountPermissions",
1071
- "InvalidAuthenticationInfo"
1072
- ]);
1073
- var NOT_FOUND_CODES = /* @__PURE__ */ new Set([
1074
- "BlobNotFound",
1075
- "ContainerNotFound",
1076
- "ResourceNotFound"
1077
- ]);
1078
- function mapAzureError(error) {
1079
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
1080
- if (error instanceof StorageError)
1081
- return error;
1082
- const azure = error != null ? error : {};
1083
- const code = (_d = (_c = (_b = (_a3 = azure.details) == null ? void 0 : _a3.errorCode) != null ? _b : azure.code) != null ? _c : azure.name) != null ? _d : "UnknownError";
1084
- const status = azure.statusCode;
1085
- const base = {
1086
- message: `${code}: ${(_e = azure.message) != null ? _e : String(error)}`,
1087
- provider: AZURE_BLOB_PROVIDER_ID,
1088
- requestId: (_h = (_g = (_f = azure.response) == null ? void 0 : _f.headers) == null ? void 0 : _g.get) == null ? void 0 : _h.call(_g, "x-ms-request-id"),
1089
- cause: error
1090
- };
1091
- if (status === 429 || code === "ServerBusy") {
1092
- const retryAfter = (_k = (_j = (_i = azure.response) == null ? void 0 : _i.headers) == null ? void 0 : _j.get) == null ? void 0 : _k.call(_j, "retry-after");
1093
- return new ThrottledError(__spreadProps(__spreadValues({}, base), {
1094
- code,
1095
- retryAfterMs: retryAfter !== void 0 ? Number(retryAfter) * 1e3 : void 0
1096
- }));
1097
- }
1098
- if (NOT_FOUND_CODES.has(code) || status === 404) {
1099
- return new NotFoundError(__spreadProps(__spreadValues({}, base), {
1100
- code
1101
- }));
1102
- }
1103
- if (AUTH_CODES.has(code) || status === 403 || status === 401) {
1104
- return new AuthError(__spreadProps(__spreadValues({}, base), {
1105
- code
1106
- }));
1107
- }
1108
- if (status !== void 0 && status >= 500) {
1109
- return new NetworkError(__spreadProps(__spreadValues({}, base), {
1110
- code
1111
- }));
1112
- }
1113
- return new StorageError(__spreadProps(__spreadValues({}, base), {
1114
- code,
1115
- retryable: false
1116
- }));
1117
- }
1118
- __name(mapAzureError, "mapAzureError");
1119
-
1120
- // src/providers/azure-blob/multipartSessionStore.ts
1121
- var DEFAULT_TTL_MS = 24 * 60 * 60 * 1e3;
1122
- var _InMemoryMultipartSessionStore = class _InMemoryMultipartSessionStore {
1123
- constructor(ttlMs = DEFAULT_TTL_MS) {
1124
- __publicField(this, "ttlMs");
1125
- __publicField(this, "sessions");
1126
- this.ttlMs = ttlMs;
1127
- this.sessions = /* @__PURE__ */ new Map();
1128
- }
1129
- async create(session) {
1130
- this.evictExpired();
1131
- this.sessions.set(session.uploadId, session);
1132
- }
1133
- async get(uploadId) {
1134
- const session = this.sessions.get(uploadId);
1135
- if (!session)
1136
- return void 0;
1137
- if (this.isExpired(session)) {
1138
- this.sessions.delete(uploadId);
1139
- return void 0;
1140
- }
1141
- return session;
1142
- }
1143
- async appendBlock(uploadId, block) {
1144
- const session = await this.get(uploadId);
1145
- if (session)
1146
- session.blocks.push(block);
1147
- }
1148
- async delete(uploadId) {
1149
- this.sessions.delete(uploadId);
1150
- }
1151
- async list(containerName, blobNamePrefix) {
1152
- this.evictExpired();
1153
- return [
1154
- ...this.sessions.values()
1155
- ].filter((s) => s.containerName === containerName && (blobNamePrefix === void 0 || s.blobName.startsWith(blobNamePrefix)));
1156
- }
1157
- isExpired(session) {
1158
- return Date.now() - session.createdAt > this.ttlMs;
1159
- }
1160
- evictExpired() {
1161
- for (const [uploadId, session] of this.sessions) {
1162
- if (this.isExpired(session))
1163
- this.sessions.delete(uploadId);
1164
- }
1165
- }
1166
- };
1167
- __name(_InMemoryMultipartSessionStore, "InMemoryMultipartSessionStore");
1168
- var InMemoryMultipartSessionStore = _InMemoryMultipartSessionStore;
1169
- var DELETE_BATCH_SIZE2 = 256;
1170
- var DEFAULT_PRESIGN_SECONDS2 = 3600;
1171
- var PART_NUMBER_WIDTH = 5;
1172
- var _AzureBlobStorageProvider = class _AzureBlobStorageProvider {
1173
- constructor(config) {
1174
- __publicField(this, "bucketName");
1175
- __publicField(this, "multipart");
1176
- __publicField(this, "serviceClient");
1177
- __publicField(this, "container");
1178
- __publicField(this, "retryPolicy");
1179
- __publicField(this, "limiter");
1180
- var _a3, _b, _c;
1181
- const resolved = resolveObjectStorageOptions(config.options);
1182
- if (!isAzureBlobStorageOptions(resolved)) {
1183
- throw new ConfigurationError({
1184
- message: `AzureBlobStorageProvider requires azure_blob_storage options, got provider "${resolved.provider}"`
1185
- });
1186
- }
1187
- this.bucketName = config.bucketName;
1188
- this.serviceClient = getAzureBlobServiceClient(resolved);
1189
- this.container = this.serviceClient.getContainerClient(config.bucketName);
1190
- this.retryPolicy = (_a3 = config.retry) != null ? _a3 : {};
1191
- this.limiter = (_b = config.limiter) != null ? _b : createLimiter({
1192
- max: 10,
1193
- adaptive: true
1194
- });
1195
- this.multipart = new AzureBlobMultipartClient(this.container, this.bucketName, (_c = config.multipartStore) != null ? _c : new InMemoryMultipartSessionStore(), (operation, fn) => this.send(operation, fn));
1196
- }
1197
- send(operation, fn) {
1198
- return instrument(AZURE_BLOB_PROVIDER_ID, operation, () => withRetry(() => fn().catch((error) => Promise.reject(mapAzureError(error))), this.retryPolicy));
1199
- }
1200
- block(key) {
1201
- return this.container.getBlockBlobClient(key);
1202
- }
1203
- async getObject(key, options) {
1204
- const { offset, count } = await this.resolveRange(key, options == null ? void 0 : options.range);
1205
- const response = await this.send("getObject", () => this.block(key).download(offset, count));
1206
- if (!response.readableStreamBody) {
1207
- throw new NotFoundError({
1208
- message: `Empty body downloading "${key}"`,
1209
- provider: "azure_blob_storage"
1210
- });
1211
- }
1212
- return {
1213
- body: response.readableStreamBody,
1214
- contentLength: response.contentLength,
1215
- contentType: response.contentType,
1216
- contentEncoding: response.contentEncoding,
1217
- contentDisposition: response.contentDisposition,
1218
- contentLanguage: response.contentLanguage,
1219
- cacheControl: response.cacheControl,
1220
- etag: response.etag,
1221
- lastModified: response.lastModified,
1222
- metadata: response.metadata
1223
- };
1224
- }
1225
- async resolveRange(key, rangeInput) {
1226
- var _a3;
1227
- if (!rangeInput)
1228
- return {
1229
- offset: 0
1230
- };
1231
- const range = parseRange(rangeInput);
1232
- if (range.suffixLength !== void 0) {
1233
- const props = await this.getObjectProperties(key);
1234
- const total = (_a3 = props.contentLength) != null ? _a3 : 0;
1235
- const count2 = Math.min(range.suffixLength, total);
1236
- return {
1237
- offset: total - count2,
1238
- count: count2
1239
- };
1240
- }
1241
- const start = range.start;
1242
- const count = range.end !== void 0 ? range.end - start + 1 : void 0;
1243
- return {
1244
- offset: start,
1245
- count
1246
- };
1247
- }
1248
- async getObjectProperties(key) {
1249
- const response = await this.send("getObjectProperties", () => this.block(key).getProperties());
1250
- return {
1251
- contentLength: response.contentLength,
1252
- contentType: response.contentType,
1253
- etag: response.etag,
1254
- lastModified: response.lastModified,
1255
- metadata: response.metadata
1256
- };
1257
- }
1258
- async upload(key, body, options) {
1259
- const blob = this.block(key);
1260
- const headers = mapHttpHeaders(options);
1261
- if (body instanceof Readable) {
1262
- const response2 = await this.send("upload", () => blob.uploadStream(body, options == null ? void 0 : options.partSizeBytes, options == null ? void 0 : options.queueSize, {
1263
- blobHTTPHeaders: headers,
1264
- metadata: options == null ? void 0 : options.metadata
1265
- }));
1266
- return {
1267
- key,
1268
- etag: response2.etag
1269
- };
1270
- }
1271
- const data = typeof body === "string" ? Buffer.from(body) : Buffer.from(body);
1272
- const response = await this.send("upload", () => blob.upload(data, data.length, {
1273
- blobHTTPHeaders: headers,
1274
- metadata: options == null ? void 0 : options.metadata
1275
- }));
1276
- return {
1277
- key,
1278
- etag: response.etag
1279
- };
1280
- }
1281
- createWriteStream(key, options) {
1282
- const stream = new PassThrough();
1283
- let aborted = false;
1284
- const done = this.send("createWriteStream", () => this.block(key).uploadStream(stream, options == null ? void 0 : options.partSizeBytes, options == null ? void 0 : options.queueSize, {
1285
- blobHTTPHeaders: mapHttpHeaders(options),
1286
- metadata: options == null ? void 0 : options.metadata
1287
- })).then((response) => ({
1288
- key,
1289
- etag: response.etag
1290
- }));
1291
- return {
1292
- stream,
1293
- done,
1294
- abort: async () => {
1295
- if (!aborted) {
1296
- aborted = true;
1297
- stream.destroy(new Error("upload aborted"));
1298
- }
1299
- }
1300
- };
1301
- }
1302
- async delete(key) {
1303
- await this.send("delete", () => this.block(key).delete());
1304
- }
1305
- async deleteMany(keys) {
1306
- const batchResults = await mapBatched(keys, DELETE_BATCH_SIZE2, this.limiter, async (batch) => Promise.all(batch.map(async (key) => {
1307
- try {
1308
- await this.delete(key);
1309
- return {
1310
- key,
1311
- deleted: true
1312
- };
1313
- } catch (error) {
1314
- return {
1315
- key,
1316
- deleted: false,
1317
- error: error instanceof Error ? error.message : String(error)
1318
- };
1319
- }
1320
- })));
1321
- return batchResults.flat();
1322
- }
1323
- async list(options) {
1324
- var _a3, _b;
1325
- const iterator = this.container.listBlobsFlat({
1326
- prefix: options == null ? void 0 : options.prefix
1327
- }).byPage({
1328
- maxPageSize: options == null ? void 0 : options.limit,
1329
- continuationToken: (options == null ? void 0 : options.continuationToken) || void 0
1330
- });
1331
- const page = await this.send("list", async () => (await iterator.next()).value);
1332
- const items = ((_b = (_a3 = page == null ? void 0 : page.segment) == null ? void 0 : _a3.blobItems) != null ? _b : []).map((blob) => ({
1333
- key: blob.name,
1334
- size: blob.properties.contentLength,
1335
- etag: blob.properties.etag,
1336
- lastModified: blob.properties.lastModified
1337
- }));
1338
- return {
1339
- items,
1340
- nextToken: (page == null ? void 0 : page.continuationToken) || void 0
1341
- };
1342
- }
1343
- iterate(options) {
1344
- return __asyncGenerator(this, null, function* () {
1345
- let token;
1346
- do {
1347
- const page = yield new __await(this.list({
1348
- prefix: options == null ? void 0 : options.prefix,
1349
- limit: options == null ? void 0 : options.pageSize,
1350
- continuationToken: token
1351
- }));
1352
- yield* __yieldStar(page.items);
1353
- token = page.nextToken;
1354
- } while (token);
1355
- });
1356
- }
1357
- async listAll(options) {
1358
- const items = [];
1359
- try {
1360
- for (var iter = __forAwait(this.iterate(options)), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
1361
- const item = temp.value;
1362
- items.push(item);
1363
- }
1364
- } catch (temp) {
1365
- error = [temp];
1366
- } finally {
1367
- try {
1368
- more && (temp = iter.return) && await temp.call(iter);
1369
- } finally {
1370
- if (error)
1371
- throw error[0];
1372
- }
1373
- }
1374
- return items;
1375
- }
1376
- async headBucket() {
1377
- try {
1378
- const response = await this.send("headBucket", () => this.container.getProperties());
1379
- return {
1380
- exists: true,
1381
- metadata: response.metadata
1382
- };
1383
- } catch (error) {
1384
- if (error instanceof NotFoundError)
1385
- return {
1386
- exists: false
1387
- };
1388
- throw error;
1389
- }
1390
- }
1391
- async getDownloadUrl(key, options) {
1392
- return this.generateSasUrl(key, "r", options);
1393
- }
1394
- async getUploadUrl(key, options) {
1395
- const url = await this.generateSasUrl(key, "cw", options);
1396
- return {
1397
- key,
1398
- url
1399
- };
1400
- }
1401
- async generateSasUrl(key, permissions, options) {
1402
- var _a3;
1403
- const expiresInSeconds = (_a3 = options == null ? void 0 : options.expiresInSeconds) != null ? _a3 : DEFAULT_PRESIGN_SECONDS2;
1404
- try {
1405
- return await this.block(key).generateSasUrl({
1406
- permissions: BlobSASPermissions.parse(permissions),
1407
- expiresOn: new Date(Date.now() + expiresInSeconds * 1e3)
1408
- });
1409
- } catch (error) {
1410
- throw new ConfigurationError({
1411
- message: "SAS generation requires shared key credentials (connectionString or accountKey auth)",
1412
- provider: "azure_blob_storage",
1413
- cause: error
1414
- });
1415
- }
1416
- }
1417
- };
1418
- __name(_AzureBlobStorageProvider, "AzureBlobStorageProvider");
1419
- var AzureBlobStorageProvider = _AzureBlobStorageProvider;
1420
- var _a2;
1421
- var AzureBlobMultipartClient = (_a2 = class {
1422
- constructor(container, containerName, store, send) {
1423
- __publicField(this, "container");
1424
- __publicField(this, "containerName");
1425
- __publicField(this, "store");
1426
- __publicField(this, "send");
1427
- this.container = container;
1428
- this.containerName = containerName;
1429
- this.store = store;
1430
- this.send = send;
1431
- }
1432
- block(key) {
1433
- return this.container.getBlockBlobClient(key);
1434
- }
1435
- blockIdFor(uploadId, partNumber) {
1436
- return Buffer.from(`${uploadId}:${String(partNumber).padStart(PART_NUMBER_WIDTH, "0")}`).toString("base64");
1437
- }
1438
- async create(key) {
1439
- const uploadId = randomUUID();
1440
- await this.store.create({
1441
- uploadId,
1442
- blobName: key,
1443
- containerName: this.containerName,
1444
- blocks: [],
1445
- createdAt: Date.now()
1446
- });
1447
- return {
1448
- uploadId
1449
- };
1450
- }
1451
- async session(uploadId) {
1452
- const session = await this.store.get(uploadId);
1453
- if (!session) {
1454
- throw new MultipartSessionError({
1455
- message: `Unknown or expired multipart uploadId "${uploadId}"`,
1456
- provider: "azure_blob_storage"
1457
- });
1458
- }
1459
- return session;
1460
- }
1461
- async uploadPart(key, uploadId, partNumber, body, contentLengthBytes) {
1462
- await this.session(uploadId);
1463
- const blockId = this.blockIdFor(uploadId, partNumber);
1464
- const { data, length } = resolveBlockBody(body, contentLengthBytes);
1465
- await this.send("multipart.uploadPart", () => this.block(key).stageBlock(blockId, data, length));
1466
- await this.store.appendBlock(uploadId, {
1467
- blockId,
1468
- partNumber
1469
- });
1470
- return {
1471
- partNumber,
1472
- etag: blockId
1473
- };
1474
- }
1475
- async getPartUploadUrl(key, uploadId, partNumber, options) {
1476
- var _a3;
1477
- await this.session(uploadId);
1478
- const blockId = this.blockIdFor(uploadId, partNumber);
1479
- const expiresInSeconds = (_a3 = options == null ? void 0 : options.expiresInSeconds) != null ? _a3 : DEFAULT_PRESIGN_SECONDS2;
1480
- let sasUrl;
1481
- try {
1482
- sasUrl = await this.block(key).generateSasUrl({
1483
- permissions: BlobSASPermissions.parse("cw"),
1484
- expiresOn: new Date(Date.now() + expiresInSeconds * 1e3)
1485
- });
1486
- } catch (error) {
1487
- throw new ConfigurationError({
1488
- message: "SAS generation requires shared key credentials (connectionString or accountKey auth)",
1489
- provider: "azure_blob_storage",
1490
- cause: error
1491
- });
1492
- }
1493
- await this.store.appendBlock(uploadId, {
1494
- blockId,
1495
- partNumber
1496
- });
1497
- return `${sasUrl}&comp=block&blockid=${encodeURIComponent(blockId)}`;
1498
- }
1499
- async complete(key, uploadId, parts) {
1500
- await this.session(uploadId);
1501
- const blockIds = [
1502
- ...parts
1503
- ].sort((a, b) => a.partNumber - b.partNumber).map((p) => this.blockIdFor(uploadId, p.partNumber));
1504
- const response = await this.send("multipart.complete", () => this.block(key).commitBlockList(blockIds));
1505
- await this.store.delete(uploadId);
1506
- return {
1507
- key,
1508
- etag: response.etag
1509
- };
1510
- }
1511
- async abort(_key, uploadId) {
1512
- await this.store.delete(uploadId);
1513
- }
1514
- async listParts(_key, uploadId) {
1515
- const session = await this.session(uploadId);
1516
- return session.blocks.map((b) => ({
1517
- partNumber: b.partNumber,
1518
- etag: b.blockId
1519
- }));
1520
- }
1521
- async listUploads(prefix) {
1522
- const sessions = await this.store.list(this.containerName, prefix);
1523
- return sessions.map((s) => ({
1524
- key: s.blobName,
1525
- uploadId: s.uploadId,
1526
- initiatedAt: new Date(s.createdAt)
1527
- }));
1528
- }
1529
- }, __name(_a2, "AzureBlobMultipartClient"), _a2);
1530
- function resolveBlockBody(body, contentLengthBytes) {
1531
- if (body instanceof Readable) {
1532
- if (contentLengthBytes === void 0) {
1533
- throw new ValidationError({
1534
- message: "contentLengthBytes is required when uploading a part from a stream",
1535
- provider: "azure_blob_storage"
1536
- });
1537
- }
1538
- return {
1539
- data: body,
1540
- length: contentLengthBytes
1541
- };
1542
- }
1543
- const data = typeof body === "string" ? Buffer.from(body) : Buffer.from(body);
1544
- return {
1545
- data,
1546
- length: data.length
1547
- };
1548
- }
1549
- __name(resolveBlockBody, "resolveBlockBody");
1550
- function mapHttpHeaders(options) {
1551
- return {
1552
- blobContentType: options == null ? void 0 : options.contentType,
1553
- blobContentEncoding: options == null ? void 0 : options.contentEncoding,
1554
- blobCacheControl: options == null ? void 0 : options.cacheControl,
1555
- blobContentDisposition: options == null ? void 0 : options.contentDisposition,
1556
- blobContentLanguage: void 0
1557
- };
1558
- }
1559
- __name(mapHttpHeaders, "mapHttpHeaders");
1560
- var cache3 = new ClientCache();
1561
- function getObjectStorageClient(bucket, options) {
1562
- const resolved = resolveObjectStorageOptions(options);
1563
- const optionsHash = createHash("sha256").update(stableCacheKey(resolved)).digest("hex");
1564
- const key = `${resolved.provider}:${bucket}:${optionsHash}`;
1565
- return cache3.getOrCreate(key, () => buildProvider(bucket, resolved));
1566
- }
1567
- __name(getObjectStorageClient, "getObjectStorageClient");
1568
- function buildProvider(bucket, options) {
1569
- var _a3;
1570
- if (isAwsS3StorageOptions(options)) {
1571
- return new AwsS3Provider({
1572
- bucketName: bucket,
1573
- options
1574
- });
1575
- }
1576
- if (isAzureBlobStorageOptions(options)) {
1577
- return new AzureBlobStorageProvider({
1578
- bucketName: bucket,
1579
- options
1580
- });
1581
- }
1582
- throw new ConfigurationError({
1583
- message: `Unsupported object storage provider: "${(_a3 = options == null ? void 0 : options.provider) != null ? _a3 : "unknown"}"`
1584
- });
1585
- }
1586
- __name(buildProvider, "buildProvider");
1587
- function clearObjectStorageClientCache() {
1588
- cache3.clear();
1589
- }
1590
- __name(clearObjectStorageClientCache, "clearObjectStorageClientCache");
1591
-
1592
- // src/index-v2.ts
1593
- var OBJECT_STORAGE_PROVIDERS = Object.freeze({
1594
- AWS_S3: AWS_S3_PROVIDER_ID,
1595
- AZURE_BLOB_STORAGE: AZURE_BLOB_PROVIDER_ID
1596
- });
1597
-
1598
- export { AWS_S3_PROVIDER_ID, AZURE_BLOB_PROVIDER_ID, AuthError, AwsS3Provider, AzureBlobStorageProvider, ConfigurationError, InMemoryMultipartSessionStore, IntegrityError, MultipartSessionError, NetworkError, NotFoundError, OBJECT_STORAGE_PROVIDERS, StorageError, ThrottledError, ValidationError, chunk, clearAwsS3ClientCache, clearAzureBlobClientCache, clearObjectStorageClientCache, createLimiter, getAwsS3Client, getAzureBlobServiceClient, getDefaultAwsS3OptionsFromEnv, getDefaultAzureBlobOptionsFromEnv, getObjectStorageClient, isAwsS3StorageOptions, isAzureBlobStorageOptions, isRetryableError, mapAwsError, mapAzureError, mapBatched, parseRange, resolveObjectStorageOptions, resolveOptionsFromEnv, toRangeHeader, withRetry };
1599
- //# sourceMappingURL=out.js.map
1600
- //# sourceMappingURL=index-v2.mjs.map