wrangler 2.0.9 → 2.0.11

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.
@@ -116942,7 +116942,7 @@ var yargs_default = Yargs;
116942
116942
 
116943
116943
  // package.json
116944
116944
  var name = "wrangler";
116945
- var version = "2.0.9";
116945
+ var version = "2.0.11";
116946
116946
  var author = "wrangler@cloudflare.com";
116947
116947
  var description = "Command-line interface for all things Cloudflare Workers";
116948
116948
  var bin = {
@@ -118217,9 +118217,13 @@ var isStringArray = (diagnostics, field, value) => {
118217
118217
  };
118218
118218
  var isObjectWith = (...properties) => (diagnostics, field, value) => {
118219
118219
  if (value !== void 0 && (typeof value !== "object" || value === null || !properties.every((prop) => prop in value))) {
118220
- diagnostics.errors.push(`Expected "${field}" to be of type object, containing properties ${properties}, but got ${JSON.stringify(value)}.`);
118220
+ diagnostics.errors.push(`Expected "${field}" to be of type object, containing only properties ${properties}, but got ${JSON.stringify(value)}.`);
118221
118221
  return false;
118222
118222
  }
118223
+ if (value !== void 0) {
118224
+ const restFields = Object.keys(value).filter((key2) => !properties.includes(key2));
118225
+ validateAdditionalProperties(diagnostics, field, restFields, []);
118226
+ }
118223
118227
  return true;
118224
118228
  };
118225
118229
  var isOneOf = (...choices) => (diagnostics, field, value) => {
@@ -118392,8 +118396,8 @@ Consider adding an environment configuration section to the wrangler.toml file:
118392
118396
  return { config, diagnostics };
118393
118397
  }
118394
118398
  function normalizeAndValidateBuild(diagnostics, rawEnv, rawBuild, configPath) {
118395
- const { command: command2, cwd: cwd2, watch_dir, upload, ...rest } = rawBuild;
118396
- const deprecatedUpload = { ...upload };
118399
+ const { command: command2, cwd: cwd2, watch_dir, upload: upload2, ...rest } = rawBuild;
118400
+ const deprecatedUpload = { ...upload2 };
118397
118401
  validateAdditionalProperties(diagnostics, "build", Object.keys(rest), []);
118398
118402
  validateOptionalProperty(diagnostics, "build", "command", command2, "string");
118399
118403
  validateOptionalProperty(diagnostics, "build", "cwd", cwd2, "string");
@@ -120999,27 +121003,36 @@ async function syncAssets(accountId, scriptName, siteAssets, preview, dryRun) {
120999
121003
  const namespaceKeysResponse = await listKVNamespaceKeys(accountId, namespace);
121000
121004
  const namespaceKeys = new Set(namespaceKeysResponse.map((x) => x.name));
121001
121005
  const manifest = {};
121002
- const toUpload = [];
121006
+ const uploadBuckets = [];
121007
+ let uploadBucket = [];
121008
+ let uploadBucketSize = 0;
121003
121009
  const include = createPatternMatcher(siteAssets.includePatterns, false);
121004
121010
  const exclude = createPatternMatcher(siteAssets.excludePatterns, true);
121005
121011
  const hasher = await e();
121006
121012
  const assetDirectory = path13.join(siteAssets.baseDirectory, siteAssets.assetDirectory);
121007
121013
  for await (const absAssetFile of getFilesInFolder(assetDirectory)) {
121008
- const assetFile = path13.relative(siteAssets.baseDirectory, absAssetFile);
121014
+ const assetFile = path13.relative(assetDirectory, absAssetFile);
121009
121015
  if (!include(assetFile)) {
121010
121016
  continue;
121011
121017
  }
121012
121018
  if (exclude(assetFile)) {
121013
121019
  continue;
121014
121020
  }
121015
- await validateAssetSize(absAssetFile, assetFile);
121016
121021
  logger.log(`Reading ${assetFile}...`);
121017
121022
  const content = await (0, import_promises3.readFile)(absAssetFile, "base64");
121023
+ await validateAssetSize(absAssetFile, assetFile);
121024
+ const assetSize = Buffer.from(content).length;
121018
121025
  const assetKey = hashAsset(hasher, assetFile, content);
121019
121026
  validateAssetKey(assetKey);
121020
121027
  if (!namespaceKeys.has(assetKey)) {
121021
121028
  logger.log(`Uploading as ${assetKey}...`);
121022
- toUpload.push({
121029
+ if (uploadBucketSize + assetSize > 100 * 1024 * 1024) {
121030
+ uploadBuckets.push(uploadBucket);
121031
+ uploadBucketSize = 0;
121032
+ uploadBucket = [];
121033
+ }
121034
+ uploadBucketSize += assetSize;
121035
+ uploadBucket.push({
121023
121036
  key: assetKey,
121024
121037
  value: content,
121025
121038
  base64: true
@@ -121028,16 +121041,19 @@ async function syncAssets(accountId, scriptName, siteAssets, preview, dryRun) {
121028
121041
  logger.log(`Skipping - already uploaded.`);
121029
121042
  }
121030
121043
  namespaceKeys.delete(assetKey);
121031
- const maifestKey = urlSafe(path13.relative(siteAssets.assetDirectory, absAssetFile));
121032
- manifest[maifestKey] = assetKey;
121044
+ const manifestKey = urlSafe(path13.relative(siteAssets.assetDirectory, absAssetFile));
121045
+ manifest[manifestKey] = assetKey;
121033
121046
  }
121047
+ uploadBuckets.push(uploadBucket);
121034
121048
  for (const key2 of namespaceKeys) {
121035
121049
  logger.log(`Deleting ${key2} from the asset store...`);
121036
121050
  }
121037
- await Promise.all([
121038
- putKVBulkKeyValue(accountId, namespace, toUpload),
121039
- deleteKVBulkKeyValue(accountId, namespace, Array.from(namespaceKeys))
121040
- ]);
121051
+ const bucketsToPut = [];
121052
+ for (const bucket of uploadBuckets) {
121053
+ bucketsToPut.push(putKVBulkKeyValue(accountId, namespace, bucket));
121054
+ }
121055
+ await Promise.all(bucketsToPut);
121056
+ await deleteKVBulkKeyValue(accountId, namespace, Array.from(namespaceKeys));
121041
121057
  logger.log("\u2197\uFE0F Done syncing assets");
121042
121058
  return { manifest, namespace };
121043
121059
  }
@@ -123393,6 +123409,197 @@ async function buildFunctions({
123393
123409
  }));
123394
123410
  }
123395
123411
  }
123412
+ var upload = async ({
123413
+ directory,
123414
+ accountId,
123415
+ projectName
123416
+ }) => {
123417
+ const IGNORE_LIST = [
123418
+ "_worker.js",
123419
+ "_redirects",
123420
+ "_headers",
123421
+ ".DS_Store",
123422
+ "node_modules",
123423
+ ".git"
123424
+ ];
123425
+ const walk = async (dir, fileMap2 = /* @__PURE__ */ new Map(), depth = 0) => {
123426
+ const files3 = await (0, import_promises9.readdir)(dir);
123427
+ await Promise.all(files3.map(async (file) => {
123428
+ const filepath = (0, import_node_path19.join)(dir, file);
123429
+ const filestat = await (0, import_promises9.stat)(filepath);
123430
+ if (IGNORE_LIST.includes(file)) {
123431
+ return;
123432
+ }
123433
+ if (filestat.isSymbolicLink()) {
123434
+ return;
123435
+ }
123436
+ if (filestat.isDirectory()) {
123437
+ fileMap2 = await walk(filepath, fileMap2, depth + 1);
123438
+ } else {
123439
+ let name2;
123440
+ if (depth) {
123441
+ name2 = filepath.split(import_node_path19.sep).slice(1).join("/");
123442
+ } else {
123443
+ name2 = file;
123444
+ }
123445
+ const fileContent = await (0, import_promises9.readFile)(filepath);
123446
+ const base64Content = fileContent.toString("base64");
123447
+ const extension = (0, import_node_path19.extname)((0, import_node_path19.basename)(name2)).substring(1);
123448
+ if (filestat.size > 25 * 1024 * 1024) {
123449
+ throw new Error(`Error: Pages only supports files up to ${prettyBytes(25 * 1024 * 1024)} in size
123450
+ ${name2} is ${prettyBytes(filestat.size)} in size`);
123451
+ }
123452
+ fileMap2.set(name2, {
123453
+ content: base64Content,
123454
+ contentType: (0, import_mime.getType)(name2) || "application/octet-stream",
123455
+ sizeInBytes: filestat.size,
123456
+ hash: (0, import_blake3_wasm.hash)(base64Content + extension).toString("hex").slice(0, 32)
123457
+ });
123458
+ }
123459
+ }));
123460
+ return fileMap2;
123461
+ };
123462
+ const fileMap = await walk(directory);
123463
+ if (fileMap.size > 2e4) {
123464
+ throw new FatalError(`Error: Pages only supports up to 20,000 files in a deployment. Ensure you have specified your build output directory correctly.`, 1);
123465
+ }
123466
+ const files2 = [...fileMap.values()];
123467
+ async function fetchJwt() {
123468
+ return (await fetchResult(`/accounts/${accountId}/pages/projects/${projectName}/upload-token`)).jwt;
123469
+ }
123470
+ let jwt = await fetchJwt();
123471
+ const start = Date.now();
123472
+ const missingHashes = await fetchResult(`/pages/assets/check-missing`, {
123473
+ method: "POST",
123474
+ headers: {
123475
+ "Content-Type": "application/json",
123476
+ Authorization: `Bearer ${jwt}`
123477
+ },
123478
+ body: JSON.stringify({
123479
+ hashes: files2.map(({ hash: hash2 }) => hash2)
123480
+ })
123481
+ });
123482
+ const sortedFiles = files2.filter((file) => missingHashes.includes(file.hash)).sort((a, b) => b.sizeInBytes - a.sizeInBytes);
123483
+ const buckets = new Array(BULK_UPLOAD_CONCURRENCY).fill(null).map(() => ({
123484
+ files: [],
123485
+ remainingSize: MAX_BUCKET_SIZE
123486
+ }));
123487
+ let bucketOffset = 0;
123488
+ for (const file of sortedFiles) {
123489
+ let inserted = false;
123490
+ for (let i2 = 0; i2 < buckets.length; i2++) {
123491
+ const bucket = buckets[(i2 + bucketOffset) % buckets.length];
123492
+ if (bucket.remainingSize >= file.sizeInBytes && bucket.files.length < MAX_BUCKET_FILE_COUNT) {
123493
+ bucket.files.push(file);
123494
+ bucket.remainingSize -= file.sizeInBytes;
123495
+ inserted = true;
123496
+ break;
123497
+ }
123498
+ }
123499
+ if (!inserted) {
123500
+ buckets.push({
123501
+ files: [file],
123502
+ remainingSize: MAX_BUCKET_SIZE - file.sizeInBytes
123503
+ });
123504
+ }
123505
+ bucketOffset++;
123506
+ }
123507
+ let counter = fileMap.size - sortedFiles.length;
123508
+ const { rerender, unmount } = (0, import_ink5.render)(/* @__PURE__ */ import_react9.default.createElement(Progress, {
123509
+ done: counter,
123510
+ total: fileMap.size
123511
+ }));
123512
+ const queue = new PQueue({ concurrency: BULK_UPLOAD_CONCURRENCY });
123513
+ for (const bucket of buckets) {
123514
+ if (bucket.files.length === 0)
123515
+ continue;
123516
+ const payload = bucket.files.map((file) => ({
123517
+ key: file.hash,
123518
+ value: file.content,
123519
+ metadata: {
123520
+ contentType: file.contentType
123521
+ },
123522
+ base64: true
123523
+ }));
123524
+ let attempts = 0;
123525
+ const doUpload = async () => {
123526
+ try {
123527
+ return await fetchResult(`/pages/assets/upload`, {
123528
+ method: "POST",
123529
+ headers: {
123530
+ "Content-Type": "application/json",
123531
+ Authorization: `Bearer ${jwt}`
123532
+ },
123533
+ body: JSON.stringify(payload)
123534
+ });
123535
+ } catch (e2) {
123536
+ if (attempts < MAX_UPLOAD_ATTEMPTS) {
123537
+ await new Promise((resolve11) => setTimeout(resolve11, attempts++ * 1e3));
123538
+ if (e2.code === 8000013) {
123539
+ jwt = await fetchJwt();
123540
+ }
123541
+ return doUpload();
123542
+ } else {
123543
+ throw e2;
123544
+ }
123545
+ }
123546
+ };
123547
+ queue.add(() => doUpload().then(() => {
123548
+ counter += bucket.files.length;
123549
+ rerender(/* @__PURE__ */ import_react9.default.createElement(Progress, {
123550
+ done: counter,
123551
+ total: fileMap.size
123552
+ }));
123553
+ }, (error) => {
123554
+ return Promise.reject(new FatalError("Failed to upload files. Please try again.", error.code || 1));
123555
+ }));
123556
+ }
123557
+ await queue.onIdle();
123558
+ unmount();
123559
+ const uploadMs = Date.now() - start;
123560
+ const skipped = fileMap.size - missingHashes.length;
123561
+ const skippedMessage = skipped > 0 ? `(${skipped} already uploaded) ` : "";
123562
+ logger.log(`\u2728 Success! Uploaded ${sortedFiles.length} files ${skippedMessage}${formatTime(uploadMs)}
123563
+ `);
123564
+ const doUpsertHashes = async () => {
123565
+ try {
123566
+ return await fetchResult(`/pages/assets/upsert-hashes`, {
123567
+ method: "POST",
123568
+ headers: {
123569
+ "Content-Type": "application/json",
123570
+ Authorization: `Bearer ${jwt}`
123571
+ },
123572
+ body: JSON.stringify({
123573
+ hashes: files2.map(({ hash: hash2 }) => hash2)
123574
+ })
123575
+ });
123576
+ } catch (e2) {
123577
+ await new Promise((resolve11) => setTimeout(resolve11, 1e3));
123578
+ if (e2.code === 8000013) {
123579
+ jwt = await fetchJwt();
123580
+ }
123581
+ return await fetchResult(`/pages/assets/upsert-hashes`, {
123582
+ method: "POST",
123583
+ headers: {
123584
+ "Content-Type": "application/json",
123585
+ Authorization: `Bearer ${jwt}`
123586
+ },
123587
+ body: JSON.stringify({
123588
+ hashes: files2.map(({ hash: hash2 }) => hash2)
123589
+ })
123590
+ });
123591
+ }
123592
+ };
123593
+ try {
123594
+ await doUpsertHashes();
123595
+ } catch {
123596
+ logger.warn("Failed to update file hashes. Every upload appeared to succeed for this deployment, but you might need to re-upload for future deployments. This shouldn't have any impact other than slowing the upload speed of your next deployment.");
123597
+ }
123598
+ return Object.fromEntries([...fileMap.entries()].map(([fileName, file]) => [
123599
+ `/${fileName}`,
123600
+ file.hash
123601
+ ]));
123602
+ };
123396
123603
  var createDeployment = {
123397
123604
  describe: "\u{1F199} Publish a directory of static assets as a Pages deployment",
123398
123605
  builder: (yargs) => {
@@ -123443,7 +123650,7 @@ var createDeployment = {
123443
123650
  let existingOrNew = "new";
123444
123651
  if (projects.length > 0) {
123445
123652
  existingOrNew = await new Promise((resolve11) => {
123446
- const { unmount: unmount2 } = (0, import_ink5.render)(/* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null, /* @__PURE__ */ import_react9.default.createElement(import_ink5.Text, null, "No project selected. Would you like to create one or use an existing project?"), /* @__PURE__ */ import_react9.default.createElement(import_ink_select_input3.default, {
123653
+ const { unmount } = (0, import_ink5.render)(/* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null, /* @__PURE__ */ import_react9.default.createElement(import_ink5.Text, null, "No project selected. Would you like to create one or use an existing project?"), /* @__PURE__ */ import_react9.default.createElement(import_ink_select_input3.default, {
123447
123654
  items: [
123448
123655
  {
123449
123656
  key: "new",
@@ -123458,7 +123665,7 @@ var createDeployment = {
123458
123665
  ],
123459
123666
  onSelect: async (selected) => {
123460
123667
  resolve11(selected.value);
123461
- unmount2();
123668
+ unmount();
123462
123669
  }
123463
123670
  })));
123464
123671
  });
@@ -123466,7 +123673,7 @@ var createDeployment = {
123466
123673
  switch (existingOrNew) {
123467
123674
  case "existing": {
123468
123675
  projectName = await new Promise((resolve11) => {
123469
- const { unmount: unmount2 } = (0, import_ink5.render)(/* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null, /* @__PURE__ */ import_react9.default.createElement(import_ink5.Text, null, "Select a project:"), /* @__PURE__ */ import_react9.default.createElement(import_ink_select_input3.default, {
123676
+ const { unmount } = (0, import_ink5.render)(/* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null, /* @__PURE__ */ import_react9.default.createElement(import_ink5.Text, null, "Select a project:"), /* @__PURE__ */ import_react9.default.createElement(import_ink_select_input3.default, {
123470
123677
  items: projects.map((project) => ({
123471
123678
  key: project.name,
123472
123679
  label: project.name,
@@ -123474,7 +123681,7 @@ var createDeployment = {
123474
123681
  })),
123475
123682
  onSelect: async (selected) => {
123476
123683
  resolve11(selected.value.name);
123477
- unmount2();
123684
+ unmount();
123478
123685
  }
123479
123686
  })));
123480
123687
  });
@@ -123559,156 +123766,9 @@ To silence this warning, pass in --commit-dirty=true`);
123559
123766
  }));
123560
123767
  builtFunctions = (0, import_node_fs7.readFileSync)(outfile, "utf-8");
123561
123768
  }
123562
- const IGNORE_LIST = [
123563
- "_worker.js",
123564
- "_redirects",
123565
- "_headers",
123566
- ".DS_Store",
123567
- "node_modules",
123568
- ".git"
123569
- ];
123570
- const walk = async (dir, fileMap2 = /* @__PURE__ */ new Map(), depth = 0) => {
123571
- const files3 = await (0, import_promises9.readdir)(dir);
123572
- await Promise.all(files3.map(async (file) => {
123573
- const filepath = (0, import_node_path19.join)(dir, file);
123574
- const filestat = await (0, import_promises9.stat)(filepath);
123575
- if (IGNORE_LIST.includes(file)) {
123576
- return;
123577
- }
123578
- if (filestat.isSymbolicLink()) {
123579
- return;
123580
- }
123581
- if (filestat.isDirectory()) {
123582
- fileMap2 = await walk(filepath, fileMap2, depth + 1);
123583
- } else {
123584
- let name2;
123585
- if (depth) {
123586
- name2 = filepath.split(import_node_path19.sep).slice(1).join("/");
123587
- } else {
123588
- name2 = file;
123589
- }
123590
- const fileContent = await (0, import_promises9.readFile)(filepath);
123591
- const base64Content = fileContent.toString("base64");
123592
- const extension = (0, import_node_path19.extname)((0, import_node_path19.basename)(name2)).substring(1);
123593
- if (filestat.size > 25 * 1024 * 1024) {
123594
- throw new Error(`Error: Pages only supports files up to ${prettyBytes(25 * 1024 * 1024)} in size
123595
- ${name2} is ${prettyBytes(filestat.size)} in size`);
123596
- }
123597
- fileMap2.set(name2, {
123598
- content: base64Content,
123599
- contentType: (0, import_mime.getType)(name2) || "application/octet-stream",
123600
- sizeInBytes: filestat.size,
123601
- hash: (0, import_blake3_wasm.hash)(base64Content + extension).toString("hex").slice(0, 32)
123602
- });
123603
- }
123604
- }));
123605
- return fileMap2;
123606
- };
123607
- const fileMap = await walk(directory);
123608
- if (fileMap.size > 2e4) {
123609
- throw new FatalError(`Error: Pages only supports up to 20,000 files in a deployment. Ensure you have specified your build output directory correctly.`, 1);
123610
- }
123611
- const files2 = [...fileMap.values()];
123612
- async function fetchJwt() {
123613
- return (await fetchResult(`/accounts/${accountId}/pages/projects/${projectName}/upload-token`)).jwt;
123614
- }
123615
- let jwt = await fetchJwt();
123616
- const start = Date.now();
123617
- const missingHashes = await fetchResult(`/pages/assets/check-missing`, {
123618
- method: "POST",
123619
- headers: {
123620
- "Content-Type": "application/json",
123621
- Authorization: `Bearer ${jwt}`
123622
- },
123623
- body: JSON.stringify({
123624
- hashes: files2.map(({ hash: hash2 }) => hash2)
123625
- })
123626
- });
123627
- const sortedFiles = files2.filter((file) => missingHashes.includes(file.hash)).sort((a, b) => b.sizeInBytes - a.sizeInBytes);
123628
- const buckets = new Array(BULK_UPLOAD_CONCURRENCY).fill(null).map(() => ({
123629
- files: [],
123630
- remainingSize: MAX_BUCKET_SIZE
123631
- }));
123632
- let bucketOffset = 0;
123633
- for (const file of sortedFiles) {
123634
- let inserted = false;
123635
- for (let i2 = 0; i2 < buckets.length; i2++) {
123636
- const bucket = buckets[(i2 + bucketOffset) % buckets.length];
123637
- if (bucket.remainingSize >= file.sizeInBytes && bucket.files.length < MAX_BUCKET_FILE_COUNT) {
123638
- bucket.files.push(file);
123639
- bucket.remainingSize -= file.sizeInBytes;
123640
- inserted = true;
123641
- break;
123642
- }
123643
- }
123644
- if (!inserted) {
123645
- buckets.push({
123646
- files: [file],
123647
- remainingSize: MAX_BUCKET_SIZE - file.sizeInBytes
123648
- });
123649
- }
123650
- bucketOffset++;
123651
- }
123652
- let counter = fileMap.size - sortedFiles.length;
123653
- const { rerender, unmount } = (0, import_ink5.render)(/* @__PURE__ */ import_react9.default.createElement(Progress, {
123654
- done: counter,
123655
- total: fileMap.size
123656
- }));
123657
- const queue = new PQueue({ concurrency: BULK_UPLOAD_CONCURRENCY });
123658
- for (const bucket of buckets) {
123659
- if (bucket.files.length === 0)
123660
- continue;
123661
- const payload = bucket.files.map((file) => ({
123662
- key: file.hash,
123663
- value: file.content,
123664
- metadata: {
123665
- contentType: file.contentType
123666
- },
123667
- base64: true
123668
- }));
123669
- let attempts = 0;
123670
- const doUpload = async () => {
123671
- try {
123672
- return await fetchResult(`/pages/assets/upload`, {
123673
- method: "POST",
123674
- headers: {
123675
- "Content-Type": "application/json",
123676
- Authorization: `Bearer ${jwt}`
123677
- },
123678
- body: JSON.stringify(payload)
123679
- });
123680
- } catch (e2) {
123681
- if (attempts < MAX_UPLOAD_ATTEMPTS) {
123682
- await new Promise((resolve11) => setTimeout(resolve11, attempts++ * 1e3));
123683
- if (e2.code === 8000013) {
123684
- jwt = await fetchJwt();
123685
- }
123686
- return doUpload();
123687
- } else {
123688
- throw e2;
123689
- }
123690
- }
123691
- };
123692
- queue.add(() => doUpload().then(() => {
123693
- counter += bucket.files.length;
123694
- rerender(/* @__PURE__ */ import_react9.default.createElement(Progress, {
123695
- done: counter,
123696
- total: fileMap.size
123697
- }));
123698
- }, (error) => {
123699
- return Promise.reject(new FatalError("Failed to upload files. Please try again.", error.code || 1));
123700
- }));
123701
- }
123702
- await queue.onIdle();
123703
- unmount();
123704
- const uploadMs = Date.now() - start;
123705
- logger.log(`\u2728 Success! Uploaded ${fileMap.size} files ${formatTime(uploadMs)}
123706
- `);
123769
+ const manifest = await upload({ directory, accountId, projectName });
123707
123770
  const formData = new import_undici6.FormData();
123708
- formData.append("manifest", JSON.stringify(Object.fromEntries([...fileMap.entries()].map(([fileName, file]) => [
123709
- `/${fileName}`,
123710
- file.hash
123711
- ]))));
123771
+ formData.append("manifest", JSON.stringify(manifest));
123712
123772
  if (branch) {
123713
123773
  formData.append("branch", branch);
123714
123774
  }