openwrangler 0.0.3 → 0.0.4
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/dist/index.d.mts +9 -2
- package/dist/index.d.ts +9 -2
- package/dist/index.mjs +405 -1
- package/package.json +4 -4
package/dist/index.d.mts
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import { R2Bucket, KVNamespace, D1Database } from '@cloudflare/workers-types/experimental';
|
|
2
2
|
|
|
3
|
+
interface R2Config {
|
|
4
|
+
accountId: string;
|
|
5
|
+
r2AccessKeyId: string;
|
|
6
|
+
r2SecretAccessKey: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
3
9
|
interface BindingsConfig {
|
|
4
10
|
accountId: string;
|
|
5
11
|
apiToken: string;
|
|
6
12
|
}
|
|
7
|
-
|
|
13
|
+
|
|
14
|
+
declare function createR2Binding(config: R2Config, bucketName: string): R2Bucket;
|
|
8
15
|
declare function createKVBinding(config: BindingsConfig, namespaceId: string): KVNamespace;
|
|
9
16
|
declare function createD1Binding(config: BindingsConfig, databaseId: string): D1Database;
|
|
10
17
|
|
|
11
18
|
export { createD1Binding, createKVBinding, createR2Binding };
|
|
12
|
-
export type { BindingsConfig };
|
|
19
|
+
export type { BindingsConfig, R2Config };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import { R2Bucket, KVNamespace, D1Database } from '@cloudflare/workers-types/experimental';
|
|
2
2
|
|
|
3
|
+
interface R2Config {
|
|
4
|
+
accountId: string;
|
|
5
|
+
r2AccessKeyId: string;
|
|
6
|
+
r2SecretAccessKey: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
3
9
|
interface BindingsConfig {
|
|
4
10
|
accountId: string;
|
|
5
11
|
apiToken: string;
|
|
6
12
|
}
|
|
7
|
-
|
|
13
|
+
|
|
14
|
+
declare function createR2Binding(config: R2Config, bucketName: string): R2Bucket;
|
|
8
15
|
declare function createKVBinding(config: BindingsConfig, namespaceId: string): KVNamespace;
|
|
9
16
|
declare function createD1Binding(config: BindingsConfig, databaseId: string): D1Database;
|
|
10
17
|
|
|
11
18
|
export { createD1Binding, createKVBinding, createR2Binding };
|
|
12
|
-
export type { BindingsConfig };
|
|
19
|
+
export type { BindingsConfig, R2Config };
|
package/dist/index.mjs
CHANGED
|
@@ -383,8 +383,412 @@ function createD1Binding$1(client, databaseId) {
|
|
|
383
383
|
};
|
|
384
384
|
}
|
|
385
385
|
|
|
386
|
+
async function sha256(data) {
|
|
387
|
+
const encoder = new TextEncoder();
|
|
388
|
+
const dataBuffer = typeof data === "string" ? encoder.encode(data) : data;
|
|
389
|
+
return await crypto.subtle.digest("SHA-256", dataBuffer);
|
|
390
|
+
}
|
|
391
|
+
function hex(buffer) {
|
|
392
|
+
return Array.from(new Uint8Array(buffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
393
|
+
}
|
|
394
|
+
async function hmac(key, data) {
|
|
395
|
+
const encoder = new TextEncoder();
|
|
396
|
+
const cryptoKey = await crypto.subtle.importKey(
|
|
397
|
+
"raw",
|
|
398
|
+
key,
|
|
399
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
400
|
+
false,
|
|
401
|
+
["sign"]
|
|
402
|
+
);
|
|
403
|
+
return await crypto.subtle.sign("HMAC", cryptoKey, encoder.encode(data));
|
|
404
|
+
}
|
|
405
|
+
async function getSignatureKey(secretAccessKey, dateStamp, region, service) {
|
|
406
|
+
const encoder = new TextEncoder();
|
|
407
|
+
const kDate = await hmac(encoder.encode(`AWS4${secretAccessKey}`), dateStamp);
|
|
408
|
+
const kRegion = await hmac(kDate, region);
|
|
409
|
+
const kService = await hmac(kRegion, service);
|
|
410
|
+
const kSigning = await hmac(kService, "aws4_request");
|
|
411
|
+
return kSigning;
|
|
412
|
+
}
|
|
413
|
+
async function signRequest(params) {
|
|
414
|
+
const {
|
|
415
|
+
method,
|
|
416
|
+
url,
|
|
417
|
+
headers,
|
|
418
|
+
body,
|
|
419
|
+
accessKeyId,
|
|
420
|
+
secretAccessKey,
|
|
421
|
+
region = "auto",
|
|
422
|
+
service = "s3"
|
|
423
|
+
} = params;
|
|
424
|
+
const urlObj = new URL(url);
|
|
425
|
+
const host = urlObj.host;
|
|
426
|
+
const path = urlObj.pathname || "/";
|
|
427
|
+
const queryString = urlObj.search.slice(1);
|
|
428
|
+
const now = /* @__PURE__ */ new Date();
|
|
429
|
+
const amzDate = now.toISOString().replace(/[:-]|\.\d{3}/g, "");
|
|
430
|
+
const dateStamp = amzDate.slice(0, 8);
|
|
431
|
+
const canonicalHeaders = {
|
|
432
|
+
host,
|
|
433
|
+
"x-amz-date": amzDate,
|
|
434
|
+
...headers
|
|
435
|
+
};
|
|
436
|
+
const signedHeaders = Object.keys(canonicalHeaders).sort().join(";");
|
|
437
|
+
const canonicalHeadersString = Object.keys(canonicalHeaders).sort().map((key) => `${key}:${canonicalHeaders[key]}`).join("\n");
|
|
438
|
+
const payloadHash = body ? hex(await sha256(body)) : hex(await sha256(""));
|
|
439
|
+
const canonicalRequest = [
|
|
440
|
+
method,
|
|
441
|
+
path,
|
|
442
|
+
queryString,
|
|
443
|
+
canonicalHeadersString + "\n",
|
|
444
|
+
signedHeaders,
|
|
445
|
+
payloadHash
|
|
446
|
+
].join("\n");
|
|
447
|
+
const algorithm = "AWS4-HMAC-SHA256";
|
|
448
|
+
const credentialScope = `${dateStamp}/${region}/${service}/aws4_request`;
|
|
449
|
+
const stringToSign = [
|
|
450
|
+
algorithm,
|
|
451
|
+
amzDate,
|
|
452
|
+
credentialScope,
|
|
453
|
+
hex(await sha256(canonicalRequest))
|
|
454
|
+
].join("\n");
|
|
455
|
+
const signingKey = await getSignatureKey(secretAccessKey, dateStamp, region, service);
|
|
456
|
+
const signature = hex(await hmac(signingKey, stringToSign));
|
|
457
|
+
const authorization = `${algorithm} Credential=${accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;
|
|
458
|
+
return {
|
|
459
|
+
"Authorization": authorization,
|
|
460
|
+
"x-amz-date": amzDate,
|
|
461
|
+
"x-amz-content-sha256": payloadHash
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
function createR2Binding$1(config, bucketName) {
|
|
466
|
+
const { accountId, r2AccessKeyId, r2SecretAccessKey } = config;
|
|
467
|
+
const baseUrl = `https://${accountId}.r2.cloudflarestorage.com/${bucketName}`;
|
|
468
|
+
async function signedFetch(method, key, options) {
|
|
469
|
+
const queryString = options?.queryParams ? "?" + new URLSearchParams(options.queryParams).toString() : "";
|
|
470
|
+
const url = `${baseUrl}/${encodeURIComponent(key)}${queryString}`;
|
|
471
|
+
let body;
|
|
472
|
+
if (options?.body instanceof ReadableStream) {
|
|
473
|
+
const reader = options.body.getReader();
|
|
474
|
+
const chunks = [];
|
|
475
|
+
while (true) {
|
|
476
|
+
const { done, value } = await reader.read();
|
|
477
|
+
if (done) break;
|
|
478
|
+
chunks.push(value);
|
|
479
|
+
}
|
|
480
|
+
const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
|
|
481
|
+
const result = new Uint8Array(totalLength);
|
|
482
|
+
let offset = 0;
|
|
483
|
+
for (const chunk of chunks) {
|
|
484
|
+
result.set(chunk, offset);
|
|
485
|
+
offset += chunk.length;
|
|
486
|
+
}
|
|
487
|
+
body = result.buffer;
|
|
488
|
+
} else {
|
|
489
|
+
body = options?.body;
|
|
490
|
+
}
|
|
491
|
+
const signatureHeaders = await signRequest({
|
|
492
|
+
method,
|
|
493
|
+
url,
|
|
494
|
+
headers: options?.headers || {},
|
|
495
|
+
body,
|
|
496
|
+
accessKeyId: r2AccessKeyId,
|
|
497
|
+
secretAccessKey: r2SecretAccessKey
|
|
498
|
+
});
|
|
499
|
+
return fetch(url, {
|
|
500
|
+
method,
|
|
501
|
+
headers: {
|
|
502
|
+
...options?.headers,
|
|
503
|
+
...signatureHeaders
|
|
504
|
+
},
|
|
505
|
+
body
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
async function signedFetchBucket(method, options) {
|
|
509
|
+
const queryString = options?.queryParams ? "?" + new URLSearchParams(options.queryParams).toString() : "";
|
|
510
|
+
const url = `${baseUrl}${queryString}`;
|
|
511
|
+
const signatureHeaders = await signRequest({
|
|
512
|
+
method,
|
|
513
|
+
url,
|
|
514
|
+
headers: options?.headers || {},
|
|
515
|
+
accessKeyId: r2AccessKeyId,
|
|
516
|
+
secretAccessKey: r2SecretAccessKey
|
|
517
|
+
});
|
|
518
|
+
return fetch(url, {
|
|
519
|
+
method,
|
|
520
|
+
headers: {
|
|
521
|
+
...options?.headers,
|
|
522
|
+
...signatureHeaders
|
|
523
|
+
}
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
const r2Bucket = {
|
|
527
|
+
async get(key, options) {
|
|
528
|
+
const headers = {};
|
|
529
|
+
if (options?.range) {
|
|
530
|
+
if (typeof options.range === "object") {
|
|
531
|
+
const { offset, length, suffix } = options.range;
|
|
532
|
+
if (suffix) {
|
|
533
|
+
headers["Range"] = `bytes=-${suffix}`;
|
|
534
|
+
} else if (offset !== void 0) {
|
|
535
|
+
headers["Range"] = length ? `bytes=${offset}-${offset + length - 1}` : `bytes=${offset}-`;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
if (options?.onlyIf) {
|
|
540
|
+
if (options.onlyIf.etagMatches) {
|
|
541
|
+
headers["If-Match"] = options.onlyIf.etagMatches;
|
|
542
|
+
}
|
|
543
|
+
if (options.onlyIf.etagDoesNotMatch) {
|
|
544
|
+
headers["If-None-Match"] = options.onlyIf.etagDoesNotMatch;
|
|
545
|
+
}
|
|
546
|
+
if (options.onlyIf.uploadedBefore) {
|
|
547
|
+
headers["If-Unmodified-Since"] = options.onlyIf.uploadedBefore.toUTCString();
|
|
548
|
+
}
|
|
549
|
+
if (options.onlyIf.uploadedAfter) {
|
|
550
|
+
headers["If-Modified-Since"] = options.onlyIf.uploadedAfter.toUTCString();
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
const response = await signedFetch("GET", key, { headers });
|
|
554
|
+
if (response.status === 404) {
|
|
555
|
+
return null;
|
|
556
|
+
}
|
|
557
|
+
if (!response.ok) {
|
|
558
|
+
throw new Error(`R2 GET failed: ${response.status}`);
|
|
559
|
+
}
|
|
560
|
+
const customMetadata = {};
|
|
561
|
+
response.headers.forEach((value, key2) => {
|
|
562
|
+
if (key2.toLowerCase().startsWith("x-amz-meta-")) {
|
|
563
|
+
const metaKey = key2.slice("x-amz-meta-".length);
|
|
564
|
+
customMetadata[metaKey] = value;
|
|
565
|
+
}
|
|
566
|
+
});
|
|
567
|
+
const r2Object = {
|
|
568
|
+
key,
|
|
569
|
+
version: response.headers.get("x-amz-version-id") || "",
|
|
570
|
+
size: parseInt(response.headers.get("content-length") || "0", 10),
|
|
571
|
+
etag: response.headers.get("etag") || "",
|
|
572
|
+
httpEtag: response.headers.get("etag") || "",
|
|
573
|
+
checksums: {},
|
|
574
|
+
uploaded: new Date(response.headers.get("last-modified") || Date.now()),
|
|
575
|
+
httpMetadata: {
|
|
576
|
+
contentType: response.headers.get("content-type") || void 0,
|
|
577
|
+
contentLanguage: response.headers.get("content-language") || void 0,
|
|
578
|
+
contentDisposition: response.headers.get("content-disposition") || void 0,
|
|
579
|
+
contentEncoding: response.headers.get("content-encoding") || void 0,
|
|
580
|
+
cacheControl: response.headers.get("cache-control") || void 0,
|
|
581
|
+
cacheExpiry: response.headers.get("expires") ? new Date(response.headers.get("expires")) : void 0
|
|
582
|
+
},
|
|
583
|
+
customMetadata,
|
|
584
|
+
range: options?.range ? {
|
|
585
|
+
offset: 0,
|
|
586
|
+
length: parseInt(response.headers.get("content-length") || "0", 10)
|
|
587
|
+
} : void 0,
|
|
588
|
+
body: response.body,
|
|
589
|
+
bodyUsed: false,
|
|
590
|
+
arrayBuffer: () => response.arrayBuffer(),
|
|
591
|
+
text: () => response.text(),
|
|
592
|
+
json: () => response.json(),
|
|
593
|
+
blob: () => response.blob(),
|
|
594
|
+
writeHttpMetadata: (headers2) => {
|
|
595
|
+
if (r2Object.httpMetadata.contentType) {
|
|
596
|
+
headers2.set("content-type", r2Object.httpMetadata.contentType);
|
|
597
|
+
}
|
|
598
|
+
if (r2Object.httpMetadata.contentLanguage) {
|
|
599
|
+
headers2.set("content-language", r2Object.httpMetadata.contentLanguage);
|
|
600
|
+
}
|
|
601
|
+
if (r2Object.httpMetadata.contentDisposition) {
|
|
602
|
+
headers2.set("content-disposition", r2Object.httpMetadata.contentDisposition);
|
|
603
|
+
}
|
|
604
|
+
if (r2Object.httpMetadata.contentEncoding) {
|
|
605
|
+
headers2.set("content-encoding", r2Object.httpMetadata.contentEncoding);
|
|
606
|
+
}
|
|
607
|
+
if (r2Object.httpMetadata.cacheControl) {
|
|
608
|
+
headers2.set("cache-control", r2Object.httpMetadata.cacheControl);
|
|
609
|
+
}
|
|
610
|
+
if (r2Object.httpMetadata.cacheExpiry) {
|
|
611
|
+
headers2.set("expires", r2Object.httpMetadata.cacheExpiry.toUTCString());
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
return r2Object;
|
|
616
|
+
},
|
|
617
|
+
async put(key, value, options) {
|
|
618
|
+
const headers = {};
|
|
619
|
+
if (options?.httpMetadata) {
|
|
620
|
+
if (options.httpMetadata.contentType) {
|
|
621
|
+
headers["Content-Type"] = options.httpMetadata.contentType;
|
|
622
|
+
}
|
|
623
|
+
if (options.httpMetadata.contentLanguage) {
|
|
624
|
+
headers["Content-Language"] = options.httpMetadata.contentLanguage;
|
|
625
|
+
}
|
|
626
|
+
if (options.httpMetadata.contentDisposition) {
|
|
627
|
+
headers["Content-Disposition"] = options.httpMetadata.contentDisposition;
|
|
628
|
+
}
|
|
629
|
+
if (options.httpMetadata.contentEncoding) {
|
|
630
|
+
headers["Content-Encoding"] = options.httpMetadata.contentEncoding;
|
|
631
|
+
}
|
|
632
|
+
if (options.httpMetadata.cacheControl) {
|
|
633
|
+
headers["Cache-Control"] = options.httpMetadata.cacheControl;
|
|
634
|
+
}
|
|
635
|
+
if (options.httpMetadata.cacheExpiry) {
|
|
636
|
+
headers["Expires"] = options.httpMetadata.cacheExpiry.toUTCString();
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
if (options?.customMetadata) {
|
|
640
|
+
for (const [key2, value2] of Object.entries(options.customMetadata)) {
|
|
641
|
+
headers[`x-amz-meta-${key2}`] = value2;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
let body;
|
|
645
|
+
if (ArrayBuffer.isView(value)) {
|
|
646
|
+
body = value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength);
|
|
647
|
+
} else {
|
|
648
|
+
body = value;
|
|
649
|
+
}
|
|
650
|
+
const response = await signedFetch("PUT", key, { headers, body });
|
|
651
|
+
if (!response.ok) {
|
|
652
|
+
throw new Error(`R2 PUT failed: ${response.status}`);
|
|
653
|
+
}
|
|
654
|
+
return {
|
|
655
|
+
key,
|
|
656
|
+
version: response.headers.get("x-amz-version-id") || "",
|
|
657
|
+
size: typeof value === "string" ? value.length : 0,
|
|
658
|
+
etag: response.headers.get("etag") || "",
|
|
659
|
+
httpEtag: response.headers.get("etag") || "",
|
|
660
|
+
checksums: {},
|
|
661
|
+
uploaded: /* @__PURE__ */ new Date(),
|
|
662
|
+
httpMetadata: options?.httpMetadata || {},
|
|
663
|
+
customMetadata: options?.customMetadata || {}
|
|
664
|
+
};
|
|
665
|
+
},
|
|
666
|
+
async delete(keys) {
|
|
667
|
+
const keyArray = Array.isArray(keys) ? keys : [keys];
|
|
668
|
+
if (keyArray.length === 1) {
|
|
669
|
+
const response = await signedFetch("DELETE", keyArray[0]);
|
|
670
|
+
if (!response.ok && response.status !== 404) {
|
|
671
|
+
throw new Error(`R2 DELETE failed: ${response.status}`);
|
|
672
|
+
}
|
|
673
|
+
} else {
|
|
674
|
+
`<?xml version="1.0" encoding="UTF-8"?>
|
|
675
|
+
<Delete>
|
|
676
|
+
${keyArray.map((key) => `<Object><Key>${key}</Key></Object>`).join("")}
|
|
677
|
+
</Delete>`;
|
|
678
|
+
const response = await signedFetchBucket("POST", {
|
|
679
|
+
queryParams: { delete: "" },
|
|
680
|
+
headers: { "Content-Type": "application/xml" }
|
|
681
|
+
});
|
|
682
|
+
if (!response.ok) {
|
|
683
|
+
throw new Error(`R2 DELETE BULK failed: ${response.status}`);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
},
|
|
687
|
+
async head(key) {
|
|
688
|
+
const response = await signedFetch("HEAD", key);
|
|
689
|
+
if (response.status === 404) {
|
|
690
|
+
return null;
|
|
691
|
+
}
|
|
692
|
+
if (!response.ok) {
|
|
693
|
+
throw new Error(`R2 HEAD failed: ${response.status}`);
|
|
694
|
+
}
|
|
695
|
+
const customMetadata = {};
|
|
696
|
+
response.headers.forEach((value, key2) => {
|
|
697
|
+
if (key2.toLowerCase().startsWith("x-amz-meta-")) {
|
|
698
|
+
const metaKey = key2.slice("x-amz-meta-".length);
|
|
699
|
+
customMetadata[metaKey] = value;
|
|
700
|
+
}
|
|
701
|
+
});
|
|
702
|
+
return {
|
|
703
|
+
key,
|
|
704
|
+
version: response.headers.get("x-amz-version-id") || "",
|
|
705
|
+
size: parseInt(response.headers.get("content-length") || "0", 10),
|
|
706
|
+
etag: response.headers.get("etag") || "",
|
|
707
|
+
httpEtag: response.headers.get("etag") || "",
|
|
708
|
+
checksums: {},
|
|
709
|
+
uploaded: new Date(response.headers.get("last-modified") || Date.now()),
|
|
710
|
+
httpMetadata: {
|
|
711
|
+
contentType: response.headers.get("content-type") || void 0,
|
|
712
|
+
contentLanguage: response.headers.get("content-language") || void 0,
|
|
713
|
+
contentDisposition: response.headers.get("content-disposition") || void 0,
|
|
714
|
+
contentEncoding: response.headers.get("content-encoding") || void 0,
|
|
715
|
+
cacheControl: response.headers.get("cache-control") || void 0,
|
|
716
|
+
cacheExpiry: response.headers.get("expires") ? new Date(response.headers.get("expires")) : void 0
|
|
717
|
+
},
|
|
718
|
+
customMetadata
|
|
719
|
+
};
|
|
720
|
+
},
|
|
721
|
+
async list(options) {
|
|
722
|
+
const queryParams = {
|
|
723
|
+
"list-type": "2"
|
|
724
|
+
};
|
|
725
|
+
if (options?.limit) {
|
|
726
|
+
queryParams["max-keys"] = options.limit.toString();
|
|
727
|
+
}
|
|
728
|
+
if (options?.prefix) {
|
|
729
|
+
queryParams["prefix"] = options.prefix;
|
|
730
|
+
}
|
|
731
|
+
if (options?.cursor) {
|
|
732
|
+
queryParams["continuation-token"] = options.cursor;
|
|
733
|
+
}
|
|
734
|
+
if (options?.delimiter) {
|
|
735
|
+
queryParams["delimiter"] = options.delimiter;
|
|
736
|
+
}
|
|
737
|
+
if (options?.startAfter) {
|
|
738
|
+
queryParams["start-after"] = options.startAfter;
|
|
739
|
+
}
|
|
740
|
+
const response = await signedFetchBucket("GET", { queryParams });
|
|
741
|
+
if (!response.ok) {
|
|
742
|
+
throw new Error(`R2 LIST failed: ${response.status}`);
|
|
743
|
+
}
|
|
744
|
+
const xml = await response.text();
|
|
745
|
+
const objects = [];
|
|
746
|
+
const delimitedPrefixes = [];
|
|
747
|
+
const contentsRegex = /<Contents>(.*?)<\/Contents>/gs;
|
|
748
|
+
let match;
|
|
749
|
+
while ((match = contentsRegex.exec(xml)) !== null) {
|
|
750
|
+
const content = match[1];
|
|
751
|
+
const key = content.match(/<Key>(.*?)<\/Key>/)?.[1] || "";
|
|
752
|
+
const size = parseInt(content.match(/<Size>(.*?)<\/Size>/)?.[1] || "0", 10);
|
|
753
|
+
const etag = content.match(/<ETag>(.*?)<\/ETag>/)?.[1] || "";
|
|
754
|
+
const lastModified = content.match(/<LastModified>(.*?)<\/LastModified>/)?.[1] || "";
|
|
755
|
+
objects.push({
|
|
756
|
+
key,
|
|
757
|
+
version: "",
|
|
758
|
+
size,
|
|
759
|
+
etag,
|
|
760
|
+
httpEtag: etag,
|
|
761
|
+
checksums: {},
|
|
762
|
+
uploaded: new Date(lastModified),
|
|
763
|
+
httpMetadata: {},
|
|
764
|
+
customMetadata: {}
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
const prefixRegex = /<CommonPrefixes>.*?<Prefix>(.*?)<\/Prefix>.*?<\/CommonPrefixes>/gs;
|
|
768
|
+
while ((match = prefixRegex.exec(xml)) !== null) {
|
|
769
|
+
delimitedPrefixes.push(match[1]);
|
|
770
|
+
}
|
|
771
|
+
const isTruncated = xml.includes("<IsTruncated>true</IsTruncated>");
|
|
772
|
+
const nextContinuationToken = xml.match(/<NextContinuationToken>(.*?)<\/NextContinuationToken>/)?.[1];
|
|
773
|
+
return {
|
|
774
|
+
objects,
|
|
775
|
+
truncated: isTruncated,
|
|
776
|
+
cursor: nextContinuationToken,
|
|
777
|
+
delimitedPrefixes
|
|
778
|
+
};
|
|
779
|
+
},
|
|
780
|
+
createMultipartUpload(key, options) {
|
|
781
|
+
throw new Error("R2 multipart upload not yet implemented");
|
|
782
|
+
},
|
|
783
|
+
resumeMultipartUpload(key, uploadId) {
|
|
784
|
+
throw new Error("R2 multipart upload not yet implemented");
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
return r2Bucket;
|
|
788
|
+
}
|
|
789
|
+
|
|
386
790
|
function createR2Binding(config, bucketName) {
|
|
387
|
-
|
|
791
|
+
return createR2Binding$1(config, bucketName);
|
|
388
792
|
}
|
|
389
793
|
function createKVBinding(config, namespaceId) {
|
|
390
794
|
const client = new CloudflareAPIClient(config.accountId, config.apiToken);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openwrangler",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
"@cloudflare/workers-types": "^4.20251231.0",
|
|
18
18
|
"nuxt": "^3.15.0",
|
|
19
19
|
"typescript": "^5.7.2",
|
|
20
|
+
"wrangler": "^4.54.0",
|
|
20
21
|
"unbuild": "^3.3.1",
|
|
21
|
-
"
|
|
22
|
-
"@binochoi/nitro-cloudflare-dev": "npm:@bino0216/nitro-cloudflare-dev@0.2.5"
|
|
22
|
+
"@bino0216/nitro-cloudflare-dev": "0.2.6"
|
|
23
23
|
},
|
|
24
24
|
"scripts": {
|
|
25
|
-
"dev": "
|
|
25
|
+
"dev": "cd ./playground && pnpm dev",
|
|
26
26
|
"build": "unbuild"
|
|
27
27
|
}
|
|
28
28
|
}
|