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.
- package/package.json +1 -1
- package/src/__tests__/configuration.test.ts +34 -0
- package/src/__tests__/publish.test.ts +244 -131
- package/src/config/validation-helpers.ts +10 -1
- package/src/pages.tsx +295 -240
- package/src/sites.tsx +49 -16
- package/wrangler-dist/cli.js +227 -167
package/wrangler-dist/cli.js
CHANGED
|
@@ -116942,7 +116942,7 @@ var yargs_default = Yargs;
|
|
|
116942
116942
|
|
|
116943
116943
|
// package.json
|
|
116944
116944
|
var name = "wrangler";
|
|
116945
|
-
var version = "2.0.
|
|
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 = { ...
|
|
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
|
|
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(
|
|
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
|
-
|
|
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
|
|
121032
|
-
manifest[
|
|
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
|
-
|
|
121038
|
-
|
|
121039
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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(
|
|
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
|
}
|