wrangler 2.0.11 → 2.0.12
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/kv-asset-handler.js +1 -0
- package/package.json +3 -1
- package/src/__tests__/configuration.test.ts +221 -142
- package/src/__tests__/dev.test.tsx +27 -0
- package/src/__tests__/index.test.ts +2 -1
- package/src/__tests__/kv.test.ts +23 -2
- package/src/__tests__/publish.test.ts +173 -54
- package/src/bundle.ts +9 -5
- package/src/config/environment.ts +1 -1
- package/src/config/validation.ts +22 -13
- package/src/dev/dev.tsx +29 -45
- package/src/dev/local.tsx +10 -7
- package/src/dev/remote.tsx +4 -1
- package/src/dev/use-esbuild.ts +1 -4
- package/src/index.tsx +236 -180
- package/src/kv.ts +1 -1
- package/src/parse.ts +21 -1
- package/src/proxy.ts +19 -6
- package/src/publish.ts +6 -1
- package/src/sites.tsx +1 -3
- package/templates/static-asset-facade.js +1 -5
- package/wrangler-dist/cli.js +73310 -73243
- package/vendor/@cloudflare/kv-asset-handler/CHANGELOG.md +0 -332
- package/vendor/@cloudflare/kv-asset-handler/LICENSE_APACHE +0 -176
- package/vendor/@cloudflare/kv-asset-handler/LICENSE_MIT +0 -25
- package/vendor/@cloudflare/kv-asset-handler/README.md +0 -245
- package/vendor/@cloudflare/kv-asset-handler/dist/index.d.ts +0 -32
- package/vendor/@cloudflare/kv-asset-handler/dist/index.js +0 -354
- package/vendor/@cloudflare/kv-asset-handler/dist/mocks.d.ts +0 -13
- package/vendor/@cloudflare/kv-asset-handler/dist/mocks.js +0 -148
- package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.d.ts +0 -1
- package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.js +0 -436
- package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.d.ts +0 -1
- package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.js +0 -40
- package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.d.ts +0 -1
- package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.js +0 -42
- package/vendor/@cloudflare/kv-asset-handler/dist/types.d.ts +0 -26
- package/vendor/@cloudflare/kv-asset-handler/dist/types.js +0 -31
- package/vendor/@cloudflare/kv-asset-handler/package.json +0 -52
- package/vendor/@cloudflare/kv-asset-handler/src/index.ts +0 -296
- package/vendor/@cloudflare/kv-asset-handler/src/mocks.ts +0 -136
- package/vendor/@cloudflare/kv-asset-handler/src/test/getAssetFromKV.ts +0 -464
- package/vendor/@cloudflare/kv-asset-handler/src/test/mapRequestToAsset.ts +0 -33
- package/vendor/@cloudflare/kv-asset-handler/src/test/serveSinglePageApp.ts +0 -42
- package/vendor/@cloudflare/kv-asset-handler/src/types.ts +0 -39
- package/vendor/wrangler-mime/CHANGELOG.md +0 -289
- package/vendor/wrangler-mime/LICENSE +0 -21
- package/vendor/wrangler-mime/Mime.js +0 -97
- package/vendor/wrangler-mime/README.md +0 -187
- package/vendor/wrangler-mime/cli.js +0 -46
- package/vendor/wrangler-mime/index.js +0 -4
- package/vendor/wrangler-mime/lite.js +0 -4
- package/vendor/wrangler-mime/package.json +0 -52
- package/vendor/wrangler-mime/types/other.js +0 -1
- package/vendor/wrangler-mime/types/standard.js +0 -1
|
@@ -1404,6 +1404,69 @@ addEventListener('fetch', event => {});`
|
|
|
1404
1404
|
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
1405
1405
|
});
|
|
1406
1406
|
|
|
1407
|
+
it("should upload all the files in the directory specified by `--experimental-public`", async () => {
|
|
1408
|
+
const assets = [
|
|
1409
|
+
{ filePath: "file-1.txt", content: "Content of file-1" },
|
|
1410
|
+
{ filePath: "file-2.txt", content: "Content of file-2" },
|
|
1411
|
+
];
|
|
1412
|
+
const kvNamespace = {
|
|
1413
|
+
title: "__test-name-workers_sites_assets",
|
|
1414
|
+
id: "__test-name-workers_sites_assets-id",
|
|
1415
|
+
};
|
|
1416
|
+
writeWranglerToml({
|
|
1417
|
+
main: "./index.js",
|
|
1418
|
+
});
|
|
1419
|
+
writeWorkerSource();
|
|
1420
|
+
writeAssets(assets);
|
|
1421
|
+
mockUploadWorkerRequest({
|
|
1422
|
+
expectedMainModule: "stdin.js",
|
|
1423
|
+
});
|
|
1424
|
+
mockSubDomainRequest();
|
|
1425
|
+
mockListKVNamespacesRequest(kvNamespace);
|
|
1426
|
+
mockKeyListRequest(kvNamespace.id, []);
|
|
1427
|
+
mockUploadAssetsToKVRequest(kvNamespace.id, assets);
|
|
1428
|
+
await runWrangler("publish --experimental-public assets");
|
|
1429
|
+
|
|
1430
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
1431
|
+
"Reading file-1.txt...
|
|
1432
|
+
Uploading as file-1.2ca234f380.txt...
|
|
1433
|
+
Reading file-2.txt...
|
|
1434
|
+
Uploading as file-2.5938485188.txt...
|
|
1435
|
+
↗️ Done syncing assets
|
|
1436
|
+
Uploaded test-name (TIMINGS)
|
|
1437
|
+
Published test-name (TIMINGS)
|
|
1438
|
+
test-name.test-sub-domain.workers.dev"
|
|
1439
|
+
`);
|
|
1440
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
1441
|
+
});
|
|
1442
|
+
|
|
1443
|
+
it("should error if --experimental-public and --site are used together", async () => {
|
|
1444
|
+
writeWranglerToml({
|
|
1445
|
+
main: "./index.js",
|
|
1446
|
+
});
|
|
1447
|
+
writeWorkerSource();
|
|
1448
|
+
await expect(
|
|
1449
|
+
runWrangler("publish --experimental-public abc --site xyz")
|
|
1450
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
1451
|
+
`"Cannot use --experimental-public and a Site configuration together."`
|
|
1452
|
+
);
|
|
1453
|
+
});
|
|
1454
|
+
|
|
1455
|
+
it("should error if --experimental-public and config.site are used together", async () => {
|
|
1456
|
+
writeWranglerToml({
|
|
1457
|
+
main: "./index.js",
|
|
1458
|
+
site: {
|
|
1459
|
+
bucket: "xyz",
|
|
1460
|
+
},
|
|
1461
|
+
});
|
|
1462
|
+
writeWorkerSource();
|
|
1463
|
+
await expect(
|
|
1464
|
+
runWrangler("publish --experimental-public abc")
|
|
1465
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
1466
|
+
`"Cannot use --experimental-public and a Site configuration together."`
|
|
1467
|
+
);
|
|
1468
|
+
});
|
|
1469
|
+
|
|
1407
1470
|
it("should not contain backslash for assets with nested directories", async () => {
|
|
1408
1471
|
const assets = [
|
|
1409
1472
|
{ filePath: "subdir/file-1.txt", content: "Content of file-1" },
|
|
@@ -2098,34 +2161,25 @@ addEventListener('fetch', event => {});`
|
|
|
2098
2161
|
mockSubDomainRequest();
|
|
2099
2162
|
mockListKVNamespacesRequest(kvNamespace);
|
|
2100
2163
|
mockKeyListRequest(kvNamespace.id, []);
|
|
2164
|
+
const requests = mockUploadAssetsToKVRequest(kvNamespace.id);
|
|
2165
|
+
|
|
2166
|
+
await runWrangler("publish");
|
|
2101
2167
|
|
|
2102
2168
|
// We expect this to be uploaded in 3 batches
|
|
2103
2169
|
// The first batch has 11 files (88mb)
|
|
2170
|
+
expect(requests[0].uploads.length).toEqual(11);
|
|
2104
2171
|
// The next batch has 5 files (93mb)
|
|
2172
|
+
expect(requests[1].uploads.length).toEqual(5);
|
|
2105
2173
|
// And the last one has 4 files (98mb)
|
|
2174
|
+
expect(requests[2].uploads.length).toEqual(4);
|
|
2106
2175
|
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
const removeFirstBulkUploadMockFn = mockUploadAssetsToKVRequest(
|
|
2113
|
-
kvNamespace.id,
|
|
2114
|
-
assets.slice(0, 11),
|
|
2115
|
-
() => {
|
|
2116
|
-
removeFirstBulkUploadMockFn();
|
|
2117
|
-
const removeSecondBulkUploadMockFn = mockUploadAssetsToKVRequest(
|
|
2118
|
-
kvNamespace.id,
|
|
2119
|
-
assets.slice(11, 16),
|
|
2120
|
-
() => {
|
|
2121
|
-
removeSecondBulkUploadMockFn();
|
|
2122
|
-
mockUploadAssetsToKVRequest(kvNamespace.id, assets.slice(16, 20));
|
|
2123
|
-
}
|
|
2124
|
-
);
|
|
2176
|
+
let assetIndex = 0;
|
|
2177
|
+
for (const request of requests) {
|
|
2178
|
+
for (const upload of request.uploads) {
|
|
2179
|
+
checkAssetUpload(assets[assetIndex], upload);
|
|
2180
|
+
assetIndex++;
|
|
2125
2181
|
}
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
await runWrangler("publish");
|
|
2182
|
+
}
|
|
2129
2183
|
|
|
2130
2184
|
expect(std).toMatchInlineSnapshot(`
|
|
2131
2185
|
Object {
|
|
@@ -2276,6 +2330,59 @@ addEventListener('fetch', event => {});`
|
|
|
2276
2330
|
`);
|
|
2277
2331
|
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
2278
2332
|
});
|
|
2333
|
+
|
|
2334
|
+
it("should generate an asset manifest with keys relative to site.bucket", async () => {
|
|
2335
|
+
const assets = [
|
|
2336
|
+
{ filePath: "file-1.txt", content: "Content of file-1" },
|
|
2337
|
+
{ filePath: "file-2.txt", content: "Content of file-2" },
|
|
2338
|
+
];
|
|
2339
|
+
const kvNamespace = {
|
|
2340
|
+
title: "__test-name-workers_sites_assets",
|
|
2341
|
+
id: "__test-name-workers_sites_assets-id",
|
|
2342
|
+
};
|
|
2343
|
+
|
|
2344
|
+
writeWranglerToml({
|
|
2345
|
+
main: "./src/index.js",
|
|
2346
|
+
site: {
|
|
2347
|
+
bucket: "assets",
|
|
2348
|
+
},
|
|
2349
|
+
});
|
|
2350
|
+
writeWorkerSource({ basePath: "src", type: "esm" });
|
|
2351
|
+
writeAssets(assets);
|
|
2352
|
+
mockUploadWorkerRequest({
|
|
2353
|
+
expectedBindings: [
|
|
2354
|
+
{
|
|
2355
|
+
name: "__STATIC_CONTENT",
|
|
2356
|
+
namespace_id: "__test-name-workers_sites_assets-id",
|
|
2357
|
+
type: "kv_namespace",
|
|
2358
|
+
},
|
|
2359
|
+
],
|
|
2360
|
+
expectedModules: {
|
|
2361
|
+
__STATIC_CONTENT_MANIFEST:
|
|
2362
|
+
'{"file-1.txt":"file-1.2ca234f380.txt","file-2.txt":"file-2.5938485188.txt"}',
|
|
2363
|
+
},
|
|
2364
|
+
});
|
|
2365
|
+
mockSubDomainRequest();
|
|
2366
|
+
mockListKVNamespacesRequest(kvNamespace);
|
|
2367
|
+
mockKeyListRequest(kvNamespace.id, []);
|
|
2368
|
+
mockUploadAssetsToKVRequest(kvNamespace.id, assets);
|
|
2369
|
+
|
|
2370
|
+
process.chdir("./src");
|
|
2371
|
+
await runWrangler("publish");
|
|
2372
|
+
process.chdir("../");
|
|
2373
|
+
|
|
2374
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
2375
|
+
"Reading file-1.txt...
|
|
2376
|
+
Uploading as file-1.2ca234f380.txt...
|
|
2377
|
+
Reading file-2.txt...
|
|
2378
|
+
Uploading as file-2.5938485188.txt...
|
|
2379
|
+
↗️ Done syncing assets
|
|
2380
|
+
Uploaded test-name (TIMINGS)
|
|
2381
|
+
Published test-name (TIMINGS)
|
|
2382
|
+
test-name.test-sub-domain.workers.dev"
|
|
2383
|
+
`);
|
|
2384
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
2385
|
+
});
|
|
2279
2386
|
});
|
|
2280
2387
|
|
|
2281
2388
|
describe("workers_dev setting", () => {
|
|
@@ -5258,6 +5365,7 @@ function mockUploadWorkerRequest(
|
|
|
5258
5365
|
options: {
|
|
5259
5366
|
available_on_subdomain?: boolean;
|
|
5260
5367
|
expectedEntry?: string;
|
|
5368
|
+
expectedMainModule?: string;
|
|
5261
5369
|
expectedType?: "esm" | "sw";
|
|
5262
5370
|
expectedBindings?: unknown;
|
|
5263
5371
|
expectedModules?: Record<string, string>;
|
|
@@ -5271,6 +5379,7 @@ function mockUploadWorkerRequest(
|
|
|
5271
5379
|
const {
|
|
5272
5380
|
available_on_subdomain = true,
|
|
5273
5381
|
expectedEntry,
|
|
5382
|
+
expectedMainModule = "index.js",
|
|
5274
5383
|
expectedType = "esm",
|
|
5275
5384
|
expectedBindings,
|
|
5276
5385
|
expectedModules = {},
|
|
@@ -5294,6 +5403,7 @@ function mockUploadWorkerRequest(
|
|
|
5294
5403
|
expect(envName).toEqual(env);
|
|
5295
5404
|
}
|
|
5296
5405
|
expect(queryParams.get("include_subdomain_availability")).toEqual("true");
|
|
5406
|
+
expect(queryParams.get("excludeScript")).toEqual("true");
|
|
5297
5407
|
const formBody = body as FormData;
|
|
5298
5408
|
if (expectedEntry !== undefined) {
|
|
5299
5409
|
expect(await (formBody.get("index.js") as File).text()).toMatch(
|
|
@@ -5304,7 +5414,7 @@ function mockUploadWorkerRequest(
|
|
|
5304
5414
|
formBody.get("metadata") as string
|
|
5305
5415
|
) as WorkerMetadata;
|
|
5306
5416
|
if (expectedType === "esm") {
|
|
5307
|
-
expect(metadata.main_module).toEqual(
|
|
5417
|
+
expect(metadata.main_module).toEqual(expectedMainModule);
|
|
5308
5418
|
} else {
|
|
5309
5419
|
expect(metadata.body_part).toEqual("index.js");
|
|
5310
5420
|
}
|
|
@@ -5565,51 +5675,60 @@ function mockListKVNamespacesRequest(...namespaces: KVNamespaceInfo[]) {
|
|
|
5565
5675
|
);
|
|
5566
5676
|
}
|
|
5567
5677
|
|
|
5678
|
+
interface ExpectedAsset {
|
|
5679
|
+
filePath: string;
|
|
5680
|
+
content: string;
|
|
5681
|
+
expiration?: number;
|
|
5682
|
+
expiration_ttl?: number;
|
|
5683
|
+
}
|
|
5684
|
+
interface StaticAssetUpload {
|
|
5685
|
+
key: string;
|
|
5686
|
+
base64: boolean;
|
|
5687
|
+
value: string;
|
|
5688
|
+
expiration: number | undefined;
|
|
5689
|
+
expiration_ttl: number | undefined;
|
|
5690
|
+
}
|
|
5691
|
+
|
|
5568
5692
|
/** Create a mock handler for the request that tries to do a bulk upload of assets to a KV namespace. */
|
|
5569
5693
|
function mockUploadAssetsToKVRequest(
|
|
5570
5694
|
expectedNamespaceId: string,
|
|
5571
|
-
assets
|
|
5572
|
-
filePath: string;
|
|
5573
|
-
content: string;
|
|
5574
|
-
expiration?: number;
|
|
5575
|
-
expiration_ttl?: number;
|
|
5576
|
-
}[],
|
|
5577
|
-
onUpload?: () => void
|
|
5695
|
+
assets?: ExpectedAsset[]
|
|
5578
5696
|
) {
|
|
5579
|
-
|
|
5697
|
+
const requests: {
|
|
5698
|
+
uploads: StaticAssetUpload[];
|
|
5699
|
+
}[] = [];
|
|
5700
|
+
setMockResponse(
|
|
5580
5701
|
"/accounts/:accountId/storage/kv/namespaces/:namespaceId/bulk",
|
|
5581
5702
|
"PUT",
|
|
5582
5703
|
([_url, accountId, namespaceId], { body }) => {
|
|
5583
5704
|
expect(accountId).toEqual("some-account-id");
|
|
5584
5705
|
expect(namespaceId).toEqual(expectedNamespaceId);
|
|
5585
5706
|
const uploads = JSON.parse(body as string);
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
// - the extension
|
|
5594
|
-
const keyMatcher = new RegExp(
|
|
5595
|
-
"^" +
|
|
5596
|
-
asset.filePath
|
|
5597
|
-
.replace(/(\.[^.]+)$/, ".[a-z0-9]+$1")
|
|
5598
|
-
.replace(/\./g, "\\.")
|
|
5599
|
-
);
|
|
5600
|
-
expect(upload.key).toMatch(keyMatcher);
|
|
5601
|
-
// The asset value is base64 encoded.
|
|
5602
|
-
expect(upload.base64).toBe(true);
|
|
5603
|
-
expect(Buffer.from(upload.value, "base64").toString()).toEqual(
|
|
5604
|
-
asset.content
|
|
5605
|
-
);
|
|
5606
|
-
expect(upload.expiration).toEqual(asset.expiration);
|
|
5607
|
-
expect(upload.expiration_ttl).toEqual(asset.expiration_ttl);
|
|
5707
|
+
if (assets) {
|
|
5708
|
+
expect(assets.length).toEqual(uploads.length);
|
|
5709
|
+
for (let i = 0; i < uploads.length; i++) {
|
|
5710
|
+
checkAssetUpload(assets[i], uploads[i]);
|
|
5711
|
+
}
|
|
5712
|
+
} else {
|
|
5713
|
+
requests.push({ uploads });
|
|
5608
5714
|
}
|
|
5609
|
-
onUpload?.();
|
|
5610
|
-
return null;
|
|
5611
5715
|
}
|
|
5612
5716
|
);
|
|
5717
|
+
return requests;
|
|
5718
|
+
}
|
|
5719
|
+
|
|
5720
|
+
function checkAssetUpload(asset: ExpectedAsset, upload: StaticAssetUpload) {
|
|
5721
|
+
// The asset key consists of: `<basename>.<hash>.<extension>`
|
|
5722
|
+
const keyMatcher = new RegExp(
|
|
5723
|
+
"^" +
|
|
5724
|
+
asset.filePath.replace(/(\.[^.]+)$/, ".[a-z0-9]+$1").replace(/\./g, "\\.")
|
|
5725
|
+
);
|
|
5726
|
+
expect(upload.key).toMatch(keyMatcher);
|
|
5727
|
+
// The asset value is base64 encoded.
|
|
5728
|
+
expect(upload.base64).toBe(true);
|
|
5729
|
+
expect(Buffer.from(upload.value, "base64").toString()).toEqual(asset.content);
|
|
5730
|
+
expect(upload.expiration).toEqual(asset.expiration);
|
|
5731
|
+
expect(upload.expiration_ttl).toEqual(asset.expiration_ttl);
|
|
5613
5732
|
}
|
|
5614
5733
|
|
|
5615
5734
|
/** Create a mock handler for thr request that does a bulk delete of unused assets */
|
package/src/bundle.ts
CHANGED
|
@@ -154,9 +154,7 @@ export async function bundleWorker(
|
|
|
154
154
|
};
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
type EntryPoint =
|
|
158
|
-
| { stdin: esbuild.StdinOptions; nodePaths: string[] }
|
|
159
|
-
| { entryPoints: string[] };
|
|
157
|
+
type EntryPoint = { stdin: esbuild.StdinOptions } | { entryPoints: string[] };
|
|
160
158
|
|
|
161
159
|
/**
|
|
162
160
|
* Create an object that describes the entry point for esbuild.
|
|
@@ -177,11 +175,17 @@ function getEntryPoint(
|
|
|
177
175
|
path.join(__dirname, "../templates/static-asset-facade.js"),
|
|
178
176
|
"utf8"
|
|
179
177
|
)
|
|
180
|
-
|
|
178
|
+
// on windows, escape backslashes in the path (`\`)
|
|
179
|
+
.replace("__ENTRY_POINT__", entryFile.replaceAll("\\", "\\\\"))
|
|
180
|
+
.replace(
|
|
181
|
+
"__KV_ASSET_HANDLER__",
|
|
182
|
+
path
|
|
183
|
+
.join(__dirname, "../kv-asset-handler.js")
|
|
184
|
+
.replaceAll("\\", "\\\\")
|
|
185
|
+
),
|
|
181
186
|
sourcefile: "static-asset-facade.js",
|
|
182
187
|
resolveDir: path.dirname(entryFile),
|
|
183
188
|
},
|
|
184
|
-
nodePaths: [path.join(__dirname, "../vendor")],
|
|
185
189
|
};
|
|
186
190
|
} else {
|
|
187
191
|
return { entryPoints: [entryFile] };
|
|
@@ -175,7 +175,7 @@ interface EnvironmentInheritable {
|
|
|
175
175
|
/** The directory in which the command is executed. */
|
|
176
176
|
cwd?: string;
|
|
177
177
|
/** The directory to watch for changes while using wrangler dev, defaults to the current working directory */
|
|
178
|
-
watch_dir?: string;
|
|
178
|
+
watch_dir?: string | string[];
|
|
179
179
|
/**
|
|
180
180
|
* Deprecated field previously used to configure the build and upload of the script.
|
|
181
181
|
* @deprecated
|
package/src/config/validation.ts
CHANGED
|
@@ -227,19 +227,23 @@ function normalizeAndValidateBuild(
|
|
|
227
227
|
rawBuild: Config["build"],
|
|
228
228
|
configPath: string | undefined
|
|
229
229
|
): Config["build"] & { deprecatedUpload: DeprecatedUpload } {
|
|
230
|
-
const { command, cwd, watch_dir, upload, ...rest } = rawBuild;
|
|
230
|
+
const { command, cwd, watch_dir = "./src", upload, ...rest } = rawBuild;
|
|
231
231
|
const deprecatedUpload: DeprecatedUpload = { ...upload };
|
|
232
232
|
validateAdditionalProperties(diagnostics, "build", Object.keys(rest), []);
|
|
233
233
|
|
|
234
234
|
validateOptionalProperty(diagnostics, "build", "command", command, "string");
|
|
235
235
|
validateOptionalProperty(diagnostics, "build", "cwd", cwd, "string");
|
|
236
|
-
|
|
237
|
-
diagnostics,
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
236
|
+
if (Array.isArray(watch_dir)) {
|
|
237
|
+
validateTypedArray(diagnostics, "build.watch_dir", watch_dir, "string");
|
|
238
|
+
} else {
|
|
239
|
+
validateOptionalProperty(
|
|
240
|
+
diagnostics,
|
|
241
|
+
"build",
|
|
242
|
+
"watch_dir",
|
|
243
|
+
watch_dir,
|
|
244
|
+
"string"
|
|
245
|
+
);
|
|
246
|
+
}
|
|
243
247
|
|
|
244
248
|
deprecated(
|
|
245
249
|
diagnostics,
|
|
@@ -288,13 +292,18 @@ function normalizeAndValidateBuild(
|
|
|
288
292
|
// - `configPath` will always be defined since `build` can only
|
|
289
293
|
// be configured in `wrangler.toml`, but who knows, that may
|
|
290
294
|
// change in the future, so we do a check anyway
|
|
291
|
-
command
|
|
292
|
-
?
|
|
293
|
-
?
|
|
295
|
+
command && configPath
|
|
296
|
+
? Array.isArray(watch_dir)
|
|
297
|
+
? watch_dir.map((dir) =>
|
|
298
|
+
path.relative(
|
|
299
|
+
process.cwd(),
|
|
300
|
+
path.join(path.dirname(configPath), `${dir}`)
|
|
301
|
+
)
|
|
302
|
+
)
|
|
303
|
+
: path.relative(
|
|
294
304
|
process.cwd(),
|
|
295
|
-
path.join(path.dirname(configPath), watch_dir
|
|
305
|
+
path.join(path.dirname(configPath), `${watch_dir}`)
|
|
296
306
|
)
|
|
297
|
-
: watch_dir || "./src"
|
|
298
307
|
: watch_dir,
|
|
299
308
|
cwd,
|
|
300
309
|
deprecatedUpload,
|
package/src/dev/dev.tsx
CHANGED
|
@@ -20,7 +20,6 @@ import type { Config } from "../config";
|
|
|
20
20
|
import type { Entry } from "../entry";
|
|
21
21
|
import type { AssetPaths } from "../sites";
|
|
22
22
|
import type { CfWorkerInit } from "../worker";
|
|
23
|
-
import type { EsbuildBundle } from "./use-esbuild";
|
|
24
23
|
|
|
25
24
|
export type DevProps = {
|
|
26
25
|
name?: string;
|
|
@@ -46,11 +45,7 @@ export type DevProps = {
|
|
|
46
45
|
usageModel: "bundled" | "unbound" | undefined;
|
|
47
46
|
minify: boolean | undefined;
|
|
48
47
|
nodeCompat: boolean | undefined;
|
|
49
|
-
build:
|
|
50
|
-
command?: string | undefined;
|
|
51
|
-
cwd?: string | undefined;
|
|
52
|
-
watch_dir?: string | undefined;
|
|
53
|
-
};
|
|
48
|
+
build: Config["build"];
|
|
54
49
|
env: string | undefined;
|
|
55
50
|
legacyEnv: boolean;
|
|
56
51
|
zone: string | undefined;
|
|
@@ -58,10 +53,6 @@ export type DevProps = {
|
|
|
58
53
|
};
|
|
59
54
|
|
|
60
55
|
export function DevImplementation(props: DevProps): JSX.Element {
|
|
61
|
-
const directory = useTmpDir();
|
|
62
|
-
|
|
63
|
-
useCustomBuild(props.entry, props.build);
|
|
64
|
-
|
|
65
56
|
if (props.public && props.entry.format === "service-worker") {
|
|
66
57
|
throw new Error(
|
|
67
58
|
"You cannot use the service-worker format with a `public` directory."
|
|
@@ -86,37 +77,16 @@ export function DevImplementation(props: DevProps): JSX.Element {
|
|
|
86
77
|
);
|
|
87
78
|
}
|
|
88
79
|
|
|
89
|
-
const bundle = useEsbuild({
|
|
90
|
-
entry: props.entry,
|
|
91
|
-
destination: directory,
|
|
92
|
-
staticRoot: props.public,
|
|
93
|
-
jsxFactory: props.jsxFactory,
|
|
94
|
-
rules: props.rules,
|
|
95
|
-
jsxFragment: props.jsxFragment,
|
|
96
|
-
serveAssetsFromWorker: !!props.public,
|
|
97
|
-
tsconfig: props.tsconfig,
|
|
98
|
-
minify: props.minify,
|
|
99
|
-
nodeCompat: props.nodeCompat,
|
|
100
|
-
});
|
|
101
|
-
|
|
102
80
|
// only load the UI if we're running in a supported environment
|
|
103
81
|
const { isRawModeSupported } = useStdin();
|
|
104
82
|
return isRawModeSupported ? (
|
|
105
|
-
<InteractiveDevSession {...props}
|
|
83
|
+
<InteractiveDevSession {...props} />
|
|
106
84
|
) : (
|
|
107
|
-
<DevSession
|
|
108
|
-
{...props}
|
|
109
|
-
bundle={bundle}
|
|
110
|
-
local={props.initialMode === "local"}
|
|
111
|
-
/>
|
|
85
|
+
<DevSession {...props} local={props.initialMode === "local"} />
|
|
112
86
|
);
|
|
113
87
|
}
|
|
114
88
|
|
|
115
|
-
|
|
116
|
-
bundle: EsbuildBundle | undefined;
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
function InteractiveDevSession(props: InteractiveDevSessionProps) {
|
|
89
|
+
function InteractiveDevSession(props: DevProps) {
|
|
120
90
|
const toggles = useHotkeys(
|
|
121
91
|
{
|
|
122
92
|
local: props.initialMode === "local",
|
|
@@ -149,15 +119,36 @@ function InteractiveDevSession(props: InteractiveDevSessionProps) {
|
|
|
149
119
|
);
|
|
150
120
|
}
|
|
151
121
|
|
|
152
|
-
type DevSessionProps =
|
|
122
|
+
type DevSessionProps = DevProps & {
|
|
123
|
+
local: boolean;
|
|
124
|
+
};
|
|
153
125
|
|
|
154
126
|
function DevSession(props: DevSessionProps) {
|
|
127
|
+
useCustomBuild(props.entry, props.build);
|
|
128
|
+
|
|
129
|
+
const directory = useTmpDir();
|
|
130
|
+
|
|
131
|
+
const bundle = useEsbuild({
|
|
132
|
+
entry: props.entry,
|
|
133
|
+
destination: directory,
|
|
134
|
+
staticRoot: props.public,
|
|
135
|
+
jsxFactory: props.jsxFactory,
|
|
136
|
+
rules: props.rules,
|
|
137
|
+
jsxFragment: props.jsxFragment,
|
|
138
|
+
// In dev for remote mode, we serve --experimental-assets from the local proxy before we send the request to the worker.
|
|
139
|
+
serveAssetsFromWorker: !!props.public && !!props.local,
|
|
140
|
+
tsconfig: props.tsconfig,
|
|
141
|
+
minify: props.minify,
|
|
142
|
+
nodeCompat: props.nodeCompat,
|
|
143
|
+
});
|
|
144
|
+
|
|
155
145
|
return props.local ? (
|
|
156
146
|
<Local
|
|
157
147
|
name={props.name}
|
|
158
|
-
bundle={
|
|
148
|
+
bundle={bundle}
|
|
159
149
|
format={props.entry.format}
|
|
160
150
|
compatibilityDate={props.compatibilityDate}
|
|
151
|
+
localProtocol={props.localProtocol}
|
|
161
152
|
compatibilityFlags={props.compatibilityFlags}
|
|
162
153
|
bindings={props.bindings}
|
|
163
154
|
assetPaths={props.assetPaths}
|
|
@@ -172,7 +163,7 @@ function DevSession(props: DevSessionProps) {
|
|
|
172
163
|
) : (
|
|
173
164
|
<Remote
|
|
174
165
|
name={props.name}
|
|
175
|
-
bundle={
|
|
166
|
+
bundle={bundle}
|
|
176
167
|
format={props.entry.format}
|
|
177
168
|
accountId={props.accountId}
|
|
178
169
|
bindings={props.bindings}
|
|
@@ -220,14 +211,7 @@ function useTmpDir(): string | undefined {
|
|
|
220
211
|
return directory?.name;
|
|
221
212
|
}
|
|
222
213
|
|
|
223
|
-
function useCustomBuild(
|
|
224
|
-
expectedEntry: Entry,
|
|
225
|
-
build: {
|
|
226
|
-
command?: string | undefined;
|
|
227
|
-
cwd?: string | undefined;
|
|
228
|
-
watch_dir?: string | undefined;
|
|
229
|
-
}
|
|
230
|
-
): void {
|
|
214
|
+
function useCustomBuild(expectedEntry: Entry, build: Config["build"]): void {
|
|
231
215
|
useEffect(() => {
|
|
232
216
|
if (!build.command) return;
|
|
233
217
|
let watcher: ReturnType<typeof watch> | undefined;
|
package/src/dev/local.tsx
CHANGED
|
@@ -21,6 +21,7 @@ interface LocalProps {
|
|
|
21
21
|
compatibilityDate: string;
|
|
22
22
|
compatibilityFlags: string[] | undefined;
|
|
23
23
|
bindings: CfWorkerInit["bindings"];
|
|
24
|
+
localProtocol: "http" | "https";
|
|
24
25
|
assetPaths: AssetPaths | undefined;
|
|
25
26
|
public: string | undefined;
|
|
26
27
|
port: number;
|
|
@@ -54,6 +55,7 @@ function useLocalWorker({
|
|
|
54
55
|
rules,
|
|
55
56
|
enableLocalPersistence,
|
|
56
57
|
ip,
|
|
58
|
+
localProtocol,
|
|
57
59
|
crons,
|
|
58
60
|
}: LocalProps) {
|
|
59
61
|
// TODO: pass vars via command line
|
|
@@ -82,11 +84,6 @@ function useLocalWorker({
|
|
|
82
84
|
abortSignal: abortController.signal,
|
|
83
85
|
});
|
|
84
86
|
|
|
85
|
-
if (publicDirectory) {
|
|
86
|
-
throw new Error(
|
|
87
|
-
'⎔ A "public" folder is not yet supported in local mode.'
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
87
|
if (bindings.services && bindings.services.length > 0) {
|
|
91
88
|
throw new Error(
|
|
92
89
|
"⎔ Service bindings are not yet supported in local mode."
|
|
@@ -164,6 +161,7 @@ function useLocalWorker({
|
|
|
164
161
|
name: workerName,
|
|
165
162
|
port,
|
|
166
163
|
scriptPath,
|
|
164
|
+
https: localProtocol === "https",
|
|
167
165
|
host: ip,
|
|
168
166
|
modules: format === "modules",
|
|
169
167
|
modulesRules: (rules || [])
|
|
@@ -251,12 +249,16 @@ function useLocalWorker({
|
|
|
251
249
|
process.stdout.write(data);
|
|
252
250
|
});
|
|
253
251
|
|
|
252
|
+
// parse the node inspector url (which may be received in chunks) from stderr
|
|
253
|
+
let stderrData = "";
|
|
254
254
|
local.current.stderr?.on("data", (data: Buffer) => {
|
|
255
|
+
stderrData += data.toString();
|
|
255
256
|
const matches =
|
|
256
|
-
/Debugger listening on (ws:\/\/127\.0\.0\.1:\d+\/[A-Za-z0-9-]+)/.exec(
|
|
257
|
-
|
|
257
|
+
/Debugger listening on (ws:\/\/127\.0\.0\.1:\d+\/[A-Za-z0-9-]+)[\r|\n]/.exec(
|
|
258
|
+
stderrData
|
|
258
259
|
);
|
|
259
260
|
if (matches) {
|
|
261
|
+
local.current?.stderr?.removeAllListeners("data");
|
|
260
262
|
setInspectorUrl(matches[1]);
|
|
261
263
|
}
|
|
262
264
|
});
|
|
@@ -298,6 +300,7 @@ function useLocalWorker({
|
|
|
298
300
|
workerName,
|
|
299
301
|
format,
|
|
300
302
|
port,
|
|
303
|
+
localProtocol,
|
|
301
304
|
ip,
|
|
302
305
|
bindings.durable_objects?.bindings,
|
|
303
306
|
bindings.kv_namespaces,
|
package/src/dev/remote.tsx
CHANGED
|
@@ -40,6 +40,7 @@ export function Remote(props: {
|
|
|
40
40
|
accountId: props.accountId,
|
|
41
41
|
bindings: props.bindings,
|
|
42
42
|
assetPaths: props.assetPaths,
|
|
43
|
+
public: props.public,
|
|
43
44
|
port: props.port,
|
|
44
45
|
compatibilityDate: props.compatibilityDate,
|
|
45
46
|
compatibilityFlags: props.compatibilityFlags,
|
|
@@ -74,6 +75,7 @@ export function useWorker(props: {
|
|
|
74
75
|
accountId: string | undefined;
|
|
75
76
|
bindings: CfWorkerInit["bindings"];
|
|
76
77
|
assetPaths: AssetPaths | undefined;
|
|
78
|
+
public: string | undefined;
|
|
77
79
|
port: number;
|
|
78
80
|
compatibilityDate: string | undefined;
|
|
79
81
|
compatibilityFlags: string[] | undefined;
|
|
@@ -131,7 +133,7 @@ export function useWorker(props: {
|
|
|
131
133
|
// include it in the kv namespace name regardless (since there's no
|
|
132
134
|
// concept of service environments for kv namespaces yet).
|
|
133
135
|
name + (!props.legacyEnv && props.env ? `-${props.env}` : ""),
|
|
134
|
-
assetPaths,
|
|
136
|
+
props.public ? undefined : assetPaths,
|
|
135
137
|
true,
|
|
136
138
|
false
|
|
137
139
|
); // TODO: cancellable?
|
|
@@ -223,6 +225,7 @@ export function useWorker(props: {
|
|
|
223
225
|
accountId,
|
|
224
226
|
port,
|
|
225
227
|
assetPaths,
|
|
228
|
+
props.public,
|
|
226
229
|
compatibilityDate,
|
|
227
230
|
compatibilityFlags,
|
|
228
231
|
usageModel,
|
package/src/dev/use-esbuild.ts
CHANGED
|
@@ -14,7 +14,6 @@ export type EsbuildBundle = {
|
|
|
14
14
|
entry: Entry;
|
|
15
15
|
type: "esm" | "commonjs";
|
|
16
16
|
modules: CfModule[];
|
|
17
|
-
serveAssetsFromWorker: boolean;
|
|
18
17
|
};
|
|
19
18
|
|
|
20
19
|
export function useEsbuild({
|
|
@@ -67,8 +66,7 @@ export function useEsbuild({
|
|
|
67
66
|
|
|
68
67
|
const { resolvedEntryPointPath, bundleType, modules, stop } =
|
|
69
68
|
await bundleWorker(entry, destination, {
|
|
70
|
-
|
|
71
|
-
serveAssetsFromWorker: false,
|
|
69
|
+
serveAssetsFromWorker,
|
|
72
70
|
jsxFactory,
|
|
73
71
|
jsxFragment,
|
|
74
72
|
rules,
|
|
@@ -87,7 +85,6 @@ export function useEsbuild({
|
|
|
87
85
|
path: resolvedEntryPointPath,
|
|
88
86
|
type: bundleType,
|
|
89
87
|
modules,
|
|
90
|
-
serveAssetsFromWorker,
|
|
91
88
|
});
|
|
92
89
|
}
|
|
93
90
|
|