wrangler 0.0.0-e7cf0caa → 0.0.0-e87ad068
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/miniflare-dist/index.mjs +167 -93
- package/package.json +6 -6
- package/src/__tests__/configuration.test.ts +218 -0
- package/src/__tests__/constellation.test.ts +371 -0
- package/src/__tests__/d1/migrate.test.ts +100 -0
- package/src/__tests__/index.test.ts +4 -2
- package/src/__tests__/init.test.ts +109 -3
- package/src/__tests__/mtls-certificates.test.ts +2 -1
- package/src/__tests__/pages/functions-build.test.ts +77 -0
- package/src/__tests__/pages-deployment-tail.test.ts +2 -0
- package/src/__tests__/publish.test.ts +646 -187
- package/src/__tests__/tail.test.ts +49 -7
- package/src/__tests__/tsconfig.tsbuildinfo +1 -1
- package/src/__tests__/unstableDev.test.ts +61 -0
- package/src/__tests__/user.test.ts +1 -1
- package/src/api/dev.ts +12 -0
- package/src/api/pages/create-worker-bundle-contents.ts +4 -0
- package/src/api/pages/publish.tsx +28 -12
- package/src/bundle.ts +58 -14
- package/src/cfetch/internal.ts +19 -14
- package/src/config/environment.ts +41 -0
- package/src/config/index.ts +21 -0
- package/src/config/validation.ts +182 -0
- package/src/constellation/createProject.tsx +51 -0
- package/src/constellation/deleteProject.ts +51 -0
- package/src/constellation/deleteProjectModel.ts +76 -0
- package/src/constellation/index.ts +75 -0
- package/src/constellation/listCatalog.tsx +35 -0
- package/src/constellation/listModel.tsx +49 -0
- package/src/constellation/listProject.tsx +28 -0
- package/src/constellation/listRuntime.tsx +28 -0
- package/src/constellation/options.ts +17 -0
- package/src/constellation/types.ts +17 -0
- package/src/constellation/uploadModel.tsx +84 -0
- package/src/constellation/utils.ts +90 -0
- package/src/create-worker-upload-form.ts +25 -0
- package/src/d1/backups.tsx +4 -4
- package/src/d1/constants.ts +3 -0
- package/src/d1/create.tsx +77 -43
- package/src/d1/delete.ts +1 -1
- package/src/d1/execute.tsx +27 -13
- package/src/d1/list.tsx +13 -11
- package/src/d1/migrations/apply.tsx +29 -6
- package/src/d1/migrations/helpers.ts +8 -9
- package/src/d1/types.ts +7 -0
- package/src/dev/dev.tsx +9 -2
- package/src/dev/local.tsx +52 -20
- package/src/dev/remote.tsx +4 -0
- package/src/dev/start-server.ts +64 -40
- package/src/dev/use-esbuild.ts +70 -43
- package/src/dev-registry.ts +11 -0
- package/src/dev.tsx +23 -6
- package/src/docs/helpers.ts +50 -0
- package/src/docs/index.ts +25 -68
- package/src/entry.ts +8 -1
- package/src/environment-variables/factory.ts +2 -1
- package/src/generate/index.ts +5 -0
- package/src/index.ts +12 -1
- package/src/init.ts +52 -10
- package/src/inspect.ts +107 -6
- package/src/kv/helpers.ts +7 -4
- package/src/logger.ts +5 -1
- package/src/miniflare-cli/index.ts +2 -2
- package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -1
- package/src/module-collection.ts +1 -1
- package/src/pages/build.ts +30 -17
- package/src/pages/dev.ts +51 -8
- package/src/pages/functions/buildPlugin.ts +1 -0
- package/src/pages/functions/buildWorker.ts +92 -2
- package/src/pages/functions/tsconfig.tsbuildinfo +1 -1
- package/src/publish/publish.ts +9 -1
- package/src/secret/index.ts +4 -0
- package/src/sites.ts +164 -52
- package/src/tail/createTail.ts +9 -0
- package/src/tail/printing.ts +12 -0
- package/src/traverse-module-graph.ts +2 -1
- package/src/type-generation.ts +6 -0
- package/src/user/user.ts +1 -0
- package/src/utils/render.ts +1 -1
- package/src/worker.ts +26 -0
- package/templates/__tests__/tsconfig.tsbuildinfo +1 -1
- package/templates/pages-dev-util.ts +4 -1
- package/templates/tsconfig.tsbuildinfo +1 -1
- package/wrangler-dist/cli.d.ts +78 -2
- package/wrangler-dist/cli.js +65057 -63883
package/src/dev.tsx
CHANGED
|
@@ -28,10 +28,10 @@ import {
|
|
|
28
28
|
printWranglerBanner,
|
|
29
29
|
} from "./index";
|
|
30
30
|
import type { Config, Environment } from "./config";
|
|
31
|
-
import type { Route } from "./config/environment";
|
|
31
|
+
import type { Route, Rule } from "./config/environment";
|
|
32
32
|
import type { LoggerLevel } from "./logger";
|
|
33
33
|
import type { EnablePagesAssetsServiceBindingOptions } from "./miniflare-cli/types";
|
|
34
|
-
import type { CfWorkerInit } from "./worker";
|
|
34
|
+
import type { CfWorkerInit, CfModule } from "./worker";
|
|
35
35
|
import type {
|
|
36
36
|
CommonYargsArgv,
|
|
37
37
|
StrictYargsOptionsToInterface,
|
|
@@ -334,6 +334,11 @@ export type AdditionalDevProps = {
|
|
|
334
334
|
preview_bucket_name?: string;
|
|
335
335
|
}[];
|
|
336
336
|
d1Databases?: Environment["d1_databases"];
|
|
337
|
+
processEntrypoint?: boolean;
|
|
338
|
+
additionalModules?: CfModule[];
|
|
339
|
+
moduleRoot?: string;
|
|
340
|
+
rules?: Rule[];
|
|
341
|
+
constellation?: Environment["constellation"];
|
|
337
342
|
};
|
|
338
343
|
|
|
339
344
|
type StartDevOptions = DevArguments &
|
|
@@ -397,6 +402,8 @@ export async function startDev(args: StartDevOptions) {
|
|
|
397
402
|
getInspectorPort,
|
|
398
403
|
cliDefines,
|
|
399
404
|
localPersistencePath,
|
|
405
|
+
processEntrypoint,
|
|
406
|
+
additionalModules,
|
|
400
407
|
} = await validateDevServerSettings(args, config);
|
|
401
408
|
|
|
402
409
|
await metrics.sendMetricsEvent(
|
|
@@ -424,7 +431,9 @@ export async function startDev(args: StartDevOptions) {
|
|
|
424
431
|
zone={zoneId}
|
|
425
432
|
host={host}
|
|
426
433
|
routes={routes}
|
|
427
|
-
|
|
434
|
+
processEntrypoint={processEntrypoint}
|
|
435
|
+
additionalModules={additionalModules}
|
|
436
|
+
rules={args.rules ?? getRules(configParam)}
|
|
428
437
|
legacyEnv={isLegacyEnv(configParam)}
|
|
429
438
|
minify={args.minify ?? configParam.minify}
|
|
430
439
|
legacyNodeCompat={legacyNodeCompat}
|
|
@@ -533,6 +542,8 @@ export async function startApiDev(args: StartDevOptions) {
|
|
|
533
542
|
getInspectorPort,
|
|
534
543
|
cliDefines,
|
|
535
544
|
localPersistencePath,
|
|
545
|
+
processEntrypoint,
|
|
546
|
+
additionalModules,
|
|
536
547
|
} = await validateDevServerSettings(args, config);
|
|
537
548
|
|
|
538
549
|
await metrics.sendMetricsEvent(
|
|
@@ -560,7 +571,9 @@ export async function startApiDev(args: StartDevOptions) {
|
|
|
560
571
|
zone: zoneId,
|
|
561
572
|
host: host,
|
|
562
573
|
routes: routes,
|
|
563
|
-
|
|
574
|
+
processEntrypoint,
|
|
575
|
+
additionalModules,
|
|
576
|
+
rules: args.rules ?? getRules(configParam),
|
|
564
577
|
legacyEnv: isLegacyEnv(configParam),
|
|
565
578
|
minify: args.minify ?? configParam.minify,
|
|
566
579
|
legacyNodeCompat,
|
|
@@ -661,7 +674,7 @@ async function getZoneIdHostAndRoutes(args: StartDevOptions, config: Config) {
|
|
|
661
674
|
args.local = true;
|
|
662
675
|
}
|
|
663
676
|
|
|
664
|
-
if (!args.local) {
|
|
677
|
+
if (!args.local && !args.experimentalLocal) {
|
|
665
678
|
if (host) {
|
|
666
679
|
zoneId = await getZoneIdFromHost(host);
|
|
667
680
|
}
|
|
@@ -687,7 +700,7 @@ async function validateDevServerSettings(
|
|
|
687
700
|
config: Config
|
|
688
701
|
) {
|
|
689
702
|
const entry = await getEntry(
|
|
690
|
-
{ assets: args.assets, script: args.script },
|
|
703
|
+
{ assets: args.assets, script: args.script, moduleRoot: args.moduleRoot },
|
|
691
704
|
config,
|
|
692
705
|
"dev"
|
|
693
706
|
);
|
|
@@ -787,6 +800,8 @@ async function validateDevServerSettings(
|
|
|
787
800
|
routes,
|
|
788
801
|
cliDefines,
|
|
789
802
|
localPersistencePath,
|
|
803
|
+
processEntrypoint: !!args.processEntrypoint,
|
|
804
|
+
additionalModules: args.additionalModules ?? [],
|
|
790
805
|
};
|
|
791
806
|
}
|
|
792
807
|
|
|
@@ -860,6 +875,7 @@ function getBindings(
|
|
|
860
875
|
},
|
|
861
876
|
wasm_modules: configParam.wasm_modules,
|
|
862
877
|
text_blobs: configParam.text_blobs,
|
|
878
|
+
browser: configParam.browser,
|
|
863
879
|
data_blobs: configParam.data_blobs,
|
|
864
880
|
durable_objects: {
|
|
865
881
|
bindings: [
|
|
@@ -923,6 +939,7 @@ function getBindings(
|
|
|
923
939
|
}),
|
|
924
940
|
...(args.d1Databases || []),
|
|
925
941
|
]),
|
|
942
|
+
constellation: configParam.constellation,
|
|
926
943
|
};
|
|
927
944
|
|
|
928
945
|
return bindings;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import { fetch } from "undici";
|
|
3
|
+
import { logger } from "../logger";
|
|
4
|
+
|
|
5
|
+
// The ALGOLIA_APP_ID and ALGOLIA_PUBLIC_KEY are provided at esbuild time as a `define` for production and beta releases.
|
|
6
|
+
// Otherwise it is left undefined, which disables search.
|
|
7
|
+
declare const ALGOLIA_APP_ID: string;
|
|
8
|
+
declare const ALGOLIA_PUBLIC_KEY: string;
|
|
9
|
+
|
|
10
|
+
export async function runSearch(searchTerm: string) {
|
|
11
|
+
const id = ALGOLIA_APP_ID;
|
|
12
|
+
const index = "developers-cloudflare2";
|
|
13
|
+
const key = ALGOLIA_PUBLIC_KEY;
|
|
14
|
+
const params = new URLSearchParams({
|
|
15
|
+
query: searchTerm,
|
|
16
|
+
hitsPerPage: "1",
|
|
17
|
+
getRankingInfo: "0",
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
assert(id, "Missing Algolia App ID");
|
|
21
|
+
assert(key, "Missing Algolia Key");
|
|
22
|
+
|
|
23
|
+
const searchResp = await fetch(
|
|
24
|
+
`https://${id}-dsn.algolia.net/1/indexes/${index}/query`,
|
|
25
|
+
{
|
|
26
|
+
method: "POST",
|
|
27
|
+
body: JSON.stringify({
|
|
28
|
+
params: params.toString(),
|
|
29
|
+
}),
|
|
30
|
+
headers: {
|
|
31
|
+
"X-Algolia-API-Key": key,
|
|
32
|
+
"X-Algolia-Application-Id": id,
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
if (!searchResp.ok) {
|
|
37
|
+
logger.error(`Could not search the docs. Please try again later.`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const searchData = (await searchResp.json()) as { hits: { url: string }[] };
|
|
41
|
+
logger.debug("searchData: ", searchData);
|
|
42
|
+
if (searchData.hits[0]) {
|
|
43
|
+
return searchData.hits[0].url;
|
|
44
|
+
} else {
|
|
45
|
+
logger.error(
|
|
46
|
+
`Could not find docs for: ${searchTerm}. Please try again with another search term.`
|
|
47
|
+
);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
}
|
package/src/docs/index.ts
CHANGED
|
@@ -3,89 +3,46 @@ import { readConfig } from "../config";
|
|
|
3
3
|
import { logger } from "../logger";
|
|
4
4
|
import * as metrics from "../metrics";
|
|
5
5
|
import openInBrowser from "../open-in-browser";
|
|
6
|
-
|
|
6
|
+
import { runSearch } from "./helpers";
|
|
7
7
|
import type {
|
|
8
8
|
CommonYargsArgv,
|
|
9
9
|
StrictYargsOptionsToInterface,
|
|
10
10
|
} from "../yargs-types";
|
|
11
11
|
|
|
12
|
-
const argToUrlHash = {
|
|
13
|
-
d1: "d1",
|
|
14
|
-
docs: "docs",
|
|
15
|
-
init: "init",
|
|
16
|
-
generate: "generate",
|
|
17
|
-
dev: "dev",
|
|
18
|
-
publish: "publish",
|
|
19
|
-
delete: "delete",
|
|
20
|
-
"kv:namespace": "kvnamespace",
|
|
21
|
-
"kv:key": "kvkey",
|
|
22
|
-
"kv:bulk": "kvbulk",
|
|
23
|
-
"r2 bucket": "r2-bucket",
|
|
24
|
-
"r2 object": "r2-object",
|
|
25
|
-
secret: "secret",
|
|
26
|
-
"secret:bulk": "secretbulk",
|
|
27
|
-
tail: "tail",
|
|
28
|
-
pages: "pages",
|
|
29
|
-
login: "login",
|
|
30
|
-
logout: "logout",
|
|
31
|
-
whoami: "whoami",
|
|
32
|
-
types: "types",
|
|
33
|
-
deployments: "deployments",
|
|
34
|
-
};
|
|
35
|
-
|
|
36
12
|
export function docsOptions(yargs: CommonYargsArgv) {
|
|
37
|
-
return yargs
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
"tail",
|
|
49
|
-
"secret",
|
|
50
|
-
"secret:bulk",
|
|
51
|
-
"kv:namespace",
|
|
52
|
-
"kv:key",
|
|
53
|
-
"kv:bulk",
|
|
54
|
-
"pages",
|
|
55
|
-
// "queues", //TODO: Undocumented
|
|
56
|
-
"r2 object",
|
|
57
|
-
"r2 bucket",
|
|
58
|
-
// "dispatch-namespace", // TODO: Undocumented - Workers for Platforms
|
|
59
|
-
"d1",
|
|
60
|
-
// "pubsub", //TODO: Undocumented
|
|
61
|
-
"login",
|
|
62
|
-
"logout",
|
|
63
|
-
"whoami",
|
|
64
|
-
"types",
|
|
65
|
-
"deployments",
|
|
66
|
-
"api",
|
|
67
|
-
],
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function isValidParam(k: string): k is keyof typeof argToUrlHash {
|
|
72
|
-
return k in argToUrlHash;
|
|
13
|
+
return yargs
|
|
14
|
+
.positional("command", {
|
|
15
|
+
describe: "Enter the wrangler command you want to know more about",
|
|
16
|
+
type: "string",
|
|
17
|
+
array: true,
|
|
18
|
+
})
|
|
19
|
+
.option("yes", {
|
|
20
|
+
alias: "y",
|
|
21
|
+
type: "boolean",
|
|
22
|
+
description: "Takes you to the docs, even if search fails",
|
|
23
|
+
});
|
|
73
24
|
}
|
|
74
25
|
|
|
75
26
|
export async function docsHandler(
|
|
76
27
|
args: StrictYargsOptionsToInterface<typeof docsOptions>
|
|
77
28
|
) {
|
|
29
|
+
//if no command is provided, open the docs homepage
|
|
30
|
+
//or, if a command IS provided, but we can't find anything, open the docs homepage
|
|
78
31
|
let urlToOpen =
|
|
79
|
-
|
|
32
|
+
args.yes || !args.command || args.command.length === 0
|
|
33
|
+
? "https://developers.cloudflare.com/workers/wrangler/commands/"
|
|
34
|
+
: "";
|
|
35
|
+
|
|
36
|
+
if (args.command && args.command.length > 0) {
|
|
37
|
+
const searchTerm = args.command.join(" ");
|
|
38
|
+
const searchResult = await runSearch(searchTerm);
|
|
80
39
|
|
|
81
|
-
|
|
82
|
-
//if api, take them to the API docs
|
|
83
|
-
urlToOpen = "https://developers.cloudflare.com/workers/wrangler/api/";
|
|
84
|
-
} else if (args.command && isValidParam(args.command)) {
|
|
85
|
-
//otherwise, they get the wrangler commands page
|
|
86
|
-
urlToOpen += `#${argToUrlHash[args.command]}`;
|
|
40
|
+
urlToOpen = searchResult ?? urlToOpen;
|
|
87
41
|
}
|
|
88
42
|
|
|
43
|
+
if (!urlToOpen) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
89
46
|
await printWranglerBanner();
|
|
90
47
|
|
|
91
48
|
logger.log(`Opening a link in your default browser: ${urlToOpen}`);
|
package/src/entry.ts
CHANGED
|
@@ -25,6 +25,11 @@ export type Entry = {
|
|
|
25
25
|
format: CfScriptFormat;
|
|
26
26
|
/** The directory that contains all of a `--no-bundle` worker's modules. Usually `${directory}/src`. Defaults to path.dirname(file) */
|
|
27
27
|
moduleRoot: string;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* A worker's name
|
|
31
|
+
*/
|
|
32
|
+
name?: string | undefined;
|
|
28
33
|
};
|
|
29
34
|
|
|
30
35
|
/**
|
|
@@ -35,6 +40,7 @@ export async function getEntry(
|
|
|
35
40
|
script?: string;
|
|
36
41
|
format?: CfScriptFormat | undefined;
|
|
37
42
|
assets?: string | undefined;
|
|
43
|
+
moduleRoot?: string;
|
|
38
44
|
},
|
|
39
45
|
config: Config,
|
|
40
46
|
command: "dev" | "publish" | "types"
|
|
@@ -113,7 +119,8 @@ export async function getEntry(
|
|
|
113
119
|
file,
|
|
114
120
|
directory,
|
|
115
121
|
format,
|
|
116
|
-
moduleRoot: config.base_dir ?? path.dirname(file),
|
|
122
|
+
moduleRoot: args.moduleRoot ?? config.base_dir ?? path.dirname(file),
|
|
123
|
+
name: config.name ?? "worker",
|
|
117
124
|
};
|
|
118
125
|
}
|
|
119
126
|
|
|
@@ -14,7 +14,8 @@ type VariableNames =
|
|
|
14
14
|
| "WRANGLER_AUTH_URL"
|
|
15
15
|
| "WRANGLER_TOKEN_URL"
|
|
16
16
|
| "WRANGLER_REVOKE_URL"
|
|
17
|
-
| "WRANGLER_CF_AUTHORIZATION_TOKEN"
|
|
17
|
+
| "WRANGLER_CF_AUTHORIZATION_TOKEN"
|
|
18
|
+
| "NO_CONSTELLATION_WARNING";
|
|
18
19
|
|
|
19
20
|
type DeprecatedNames =
|
|
20
21
|
| "CF_ACCOUNT_ID"
|
package/src/generate/index.ts
CHANGED
|
@@ -59,6 +59,11 @@ export async function generateHandler(args: GenerateArgs) {
|
|
|
59
59
|
// print down here cuz `init` prints it own its own
|
|
60
60
|
await printWranglerBanner();
|
|
61
61
|
|
|
62
|
+
logger.warn(
|
|
63
|
+
`The \`generate\` command is no longer supported and will be removed in a future version.`
|
|
64
|
+
// TODO: recommend replacement commands
|
|
65
|
+
);
|
|
66
|
+
|
|
62
67
|
if (args.type) {
|
|
63
68
|
let message = "The --type option is no longer supported.";
|
|
64
69
|
if (args.type === "webpack") {
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ import makeCLI from "yargs";
|
|
|
7
7
|
import { version as wranglerVersion } from "../package.json";
|
|
8
8
|
import { isBuildFailure } from "./bundle";
|
|
9
9
|
import { loadDotEnv, readConfig } from "./config";
|
|
10
|
+
import { constellation } from "./constellation";
|
|
10
11
|
import { d1 } from "./d1";
|
|
11
12
|
import { deleteHandler, deleteOptions } from "./delete";
|
|
12
13
|
import {
|
|
@@ -271,7 +272,7 @@ export function createCLIParser(argv: string[]) {
|
|
|
271
272
|
|
|
272
273
|
// docs
|
|
273
274
|
wrangler.command(
|
|
274
|
-
"docs [command]",
|
|
275
|
+
"docs [command..]",
|
|
275
276
|
"📚 Open wrangler's docs in your browser",
|
|
276
277
|
docsOptions,
|
|
277
278
|
docsHandler
|
|
@@ -431,6 +432,15 @@ export function createCLIParser(argv: string[]) {
|
|
|
431
432
|
return d1(d1Yargs.command(subHelp));
|
|
432
433
|
});
|
|
433
434
|
|
|
435
|
+
// ai
|
|
436
|
+
wrangler.command(
|
|
437
|
+
"constellation",
|
|
438
|
+
"🤖 Interact with Constellation models",
|
|
439
|
+
(aiYargs) => {
|
|
440
|
+
return constellation(aiYargs.command(subHelp));
|
|
441
|
+
}
|
|
442
|
+
);
|
|
443
|
+
|
|
434
444
|
// pubsub
|
|
435
445
|
wrangler.command(
|
|
436
446
|
"pubsub",
|
|
@@ -569,6 +579,7 @@ export function createCLIParser(argv: string[]) {
|
|
|
569
579
|
unsafe: config.unsafe,
|
|
570
580
|
rules: config.rules,
|
|
571
581
|
queues: config.queues,
|
|
582
|
+
constellation: config.constellation,
|
|
572
583
|
};
|
|
573
584
|
|
|
574
585
|
await generateTypes(configBindings, config);
|
package/src/init.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import { writeFile, mkdir } from "node:fs/promises";
|
|
3
|
-
import path from "node:path";
|
|
3
|
+
import path, { dirname } from "node:path";
|
|
4
4
|
import TOML from "@iarna/toml";
|
|
5
5
|
import { findUp } from "find-up";
|
|
6
6
|
import { version as wranglerVersion } from "../package.json";
|
|
@@ -18,7 +18,7 @@ import { requireAuth } from "./user";
|
|
|
18
18
|
import { CommandLineArgsError, printWranglerBanner } from "./index";
|
|
19
19
|
|
|
20
20
|
import type { RawConfig } from "./config";
|
|
21
|
-
import type { Route, SimpleRoute } from "./config/environment";
|
|
21
|
+
import type { Route, SimpleRoute, TailConsumer } from "./config/environment";
|
|
22
22
|
import type {
|
|
23
23
|
WorkerMetadata,
|
|
24
24
|
WorkerMetadataBinding,
|
|
@@ -29,6 +29,7 @@ import type {
|
|
|
29
29
|
CommonYargsArgv,
|
|
30
30
|
StrictYargsOptionsToInterface,
|
|
31
31
|
} from "./yargs-types";
|
|
32
|
+
import type { ReadableStream } from "stream/web";
|
|
32
33
|
|
|
33
34
|
export function initOptions(yargs: CommonYargsArgv) {
|
|
34
35
|
return yargs
|
|
@@ -80,6 +81,8 @@ export type ServiceMetadataRes = {
|
|
|
80
81
|
usage_model: "bundled" | "unbound";
|
|
81
82
|
compatibility_date: string;
|
|
82
83
|
last_deployed_from?: "wrangler" | "dash" | "api";
|
|
84
|
+
placement_mode?: "smart";
|
|
85
|
+
tail_consumers?: TailConsumer[];
|
|
83
86
|
};
|
|
84
87
|
};
|
|
85
88
|
created_on: string;
|
|
@@ -485,10 +488,20 @@ export async function initHandler(args: InitArgs) {
|
|
|
485
488
|
`/accounts/${accountId}/workers/services/${fromDashScriptName}/environments/${defaultEnvironment}/content`
|
|
486
489
|
);
|
|
487
490
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
491
|
+
// writeFile in small batches (of 10) to not exhaust system file descriptors
|
|
492
|
+
for (const files of createBatches(dashScript, 10)) {
|
|
493
|
+
await Promise.all(
|
|
494
|
+
files.map(async (file) => {
|
|
495
|
+
const filepath = path
|
|
496
|
+
.join(creationDirectory, `./src/${file.name}`)
|
|
497
|
+
.replace(/\.js$/, ".ts"); // change javascript extension to typescript extension
|
|
498
|
+
const directory = dirname(filepath);
|
|
499
|
+
|
|
500
|
+
await mkdir(directory, { recursive: true });
|
|
501
|
+
await writeFile(filepath, file.stream() as ReadableStream);
|
|
502
|
+
})
|
|
503
|
+
);
|
|
504
|
+
}
|
|
492
505
|
|
|
493
506
|
await writePackageJsonScriptsAndUpdateWranglerToml({
|
|
494
507
|
isWritingScripts: shouldWritePackageJsonScripts,
|
|
@@ -591,10 +604,21 @@ export async function initHandler(args: InitArgs) {
|
|
|
591
604
|
`/accounts/${accountId}/workers/services/${fromDashScriptName}/environments/${defaultEnvironment}/content`
|
|
592
605
|
);
|
|
593
606
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
607
|
+
// writeFile in small batches (of 10) to not exhaust system file descriptors
|
|
608
|
+
for (const files of createBatches(dashScript, 10)) {
|
|
609
|
+
await Promise.all(
|
|
610
|
+
files.map(async (file) => {
|
|
611
|
+
const filepath = path.join(
|
|
612
|
+
creationDirectory,
|
|
613
|
+
`./src/${file.name}`
|
|
614
|
+
);
|
|
615
|
+
const directory = dirname(filepath);
|
|
616
|
+
|
|
617
|
+
await mkdir(directory, { recursive: true });
|
|
618
|
+
await writeFile(filepath, file.stream() as ReadableStream);
|
|
619
|
+
})
|
|
620
|
+
);
|
|
621
|
+
}
|
|
598
622
|
|
|
599
623
|
await writePackageJsonScriptsAndUpdateWranglerToml({
|
|
600
624
|
isWritingScripts: shouldWritePackageJsonScripts,
|
|
@@ -868,6 +892,10 @@ async function getWorkerConfig(
|
|
|
868
892
|
new Date().toISOString().substring(0, 10),
|
|
869
893
|
...routeOrRoutesToConfig,
|
|
870
894
|
usage_model: serviceEnvMetadata.script.usage_model,
|
|
895
|
+
placement:
|
|
896
|
+
serviceEnvMetadata.script.placement_mode === "smart"
|
|
897
|
+
? { mode: "smart" }
|
|
898
|
+
: undefined,
|
|
871
899
|
...(durableObjectClassNames.length
|
|
872
900
|
? {
|
|
873
901
|
migrations: [
|
|
@@ -888,6 +916,7 @@ async function getWorkerConfig(
|
|
|
888
916
|
return { ...envObj, [environment]: {} };
|
|
889
917
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
890
918
|
}, {} as RawConfig["env"]),
|
|
919
|
+
tail_consumers: serviceEnvMetadata.script.tail_consumers,
|
|
891
920
|
...mappedBindings,
|
|
892
921
|
};
|
|
893
922
|
}
|
|
@@ -942,6 +971,13 @@ export function mapBindings(bindings: WorkerMetadataBinding[]): RawConfig {
|
|
|
942
971
|
};
|
|
943
972
|
}
|
|
944
973
|
break;
|
|
974
|
+
case "browser":
|
|
975
|
+
{
|
|
976
|
+
configObj.browser = {
|
|
977
|
+
binding: binding.name,
|
|
978
|
+
};
|
|
979
|
+
}
|
|
980
|
+
break;
|
|
945
981
|
case "r2_bucket":
|
|
946
982
|
{
|
|
947
983
|
configObj.r2_buckets = [
|
|
@@ -1030,3 +1066,9 @@ export function mapBindings(bindings: WorkerMetadataBinding[]): RawConfig {
|
|
|
1030
1066
|
}, {} as RawConfig)
|
|
1031
1067
|
);
|
|
1032
1068
|
}
|
|
1069
|
+
|
|
1070
|
+
function* createBatches<T>(array: T[], size: number): IterableIterator<T[]> {
|
|
1071
|
+
for (let i = 0; i < array.length; i += size) {
|
|
1072
|
+
yield array.slice(i, i + size);
|
|
1073
|
+
}
|
|
1074
|
+
}
|
package/src/inspect.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { readFileSync } from "fs";
|
|
1
2
|
import { readFile } from "fs/promises";
|
|
2
3
|
import assert from "node:assert";
|
|
3
4
|
import { createServer } from "node:http";
|
|
4
5
|
import os from "node:os";
|
|
5
6
|
import { URL } from "node:url";
|
|
6
|
-
|
|
7
|
+
import path from "path";
|
|
7
8
|
import open from "open";
|
|
8
9
|
import { useEffect, useRef, useState } from "react";
|
|
9
10
|
import { SourceMapConsumer } from "source-map";
|
|
@@ -40,6 +41,13 @@ import type { MessageEvent } from "ws";
|
|
|
40
41
|
* - handle more methods from console
|
|
41
42
|
*/
|
|
42
43
|
|
|
44
|
+
// Information about Wrangler's bundling process that needs passsed through
|
|
45
|
+
// for DevTools sourcemap transformation
|
|
46
|
+
export interface SourceMapMetadata {
|
|
47
|
+
tmpDir: string;
|
|
48
|
+
entryDirectory: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
43
51
|
interface InspectorProps {
|
|
44
52
|
/**
|
|
45
53
|
* The port that the local proxy server should listen on.
|
|
@@ -58,9 +66,13 @@ interface InspectorProps {
|
|
|
58
66
|
/**
|
|
59
67
|
* Sourcemap path, so that stacktraces can be interpretted
|
|
60
68
|
*/
|
|
61
|
-
sourceMapPath
|
|
69
|
+
sourceMapPath: string | undefined;
|
|
70
|
+
|
|
71
|
+
sourceMapMetadata: SourceMapMetadata | undefined;
|
|
62
72
|
|
|
63
73
|
host?: string;
|
|
74
|
+
|
|
75
|
+
name?: string;
|
|
64
76
|
}
|
|
65
77
|
|
|
66
78
|
export default function useInspector(props: InspectorProps) {
|
|
@@ -493,6 +505,65 @@ export default function useInspector(props: InspectorProps) {
|
|
|
493
505
|
|
|
494
506
|
/** Send a message from the local websocket to the remote websocket */
|
|
495
507
|
function sendMessageToRemoteWebSocket(event: MessageEvent) {
|
|
508
|
+
try {
|
|
509
|
+
// Intercept Network.loadNetworkResource to load sourcemaps
|
|
510
|
+
const message = JSON.parse(event.data as string);
|
|
511
|
+
if (
|
|
512
|
+
message.method === "Network.loadNetworkResource" &&
|
|
513
|
+
props.sourceMapPath !== undefined &&
|
|
514
|
+
props.sourceMapMetadata !== undefined
|
|
515
|
+
) {
|
|
516
|
+
// Read the generated source map from esbuild
|
|
517
|
+
const sourceMap = JSON.parse(
|
|
518
|
+
readFileSync(props.sourceMapPath, "utf-8")
|
|
519
|
+
);
|
|
520
|
+
|
|
521
|
+
// The source root is a temporary directory (`tmpDir`), and so shouldn't be user-visible
|
|
522
|
+
// It provides no useful info to the user
|
|
523
|
+
sourceMap.sourceRoot = "";
|
|
524
|
+
|
|
525
|
+
const tmpDir = props.sourceMapMetadata.tmpDir;
|
|
526
|
+
|
|
527
|
+
// See https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.mt2g20loc2ct
|
|
528
|
+
// The above link documents the x_google_ignoreList property, which is intended to mark code that shouldn't be visible in DevTools
|
|
529
|
+
// Here we use it to indicate specifically Wrangler-injected code (facades & middleware)
|
|
530
|
+
sourceMap.x_google_ignoreList = sourceMap.sources
|
|
531
|
+
// Filter anything in the generated tmpDir, and anything from Wrangler's templates
|
|
532
|
+
// This should cover facades and middleware, but intentionally doesn't include all non-user code e.g. node_modules
|
|
533
|
+
.map((s: string, idx: number) =>
|
|
534
|
+
s.includes(tmpDir) || s.includes("wrangler/templates")
|
|
535
|
+
? idx
|
|
536
|
+
: null
|
|
537
|
+
)
|
|
538
|
+
.filter((i: number | null) => i !== null);
|
|
539
|
+
|
|
540
|
+
const entryDirectory = props.sourceMapMetadata.entryDirectory;
|
|
541
|
+
|
|
542
|
+
sourceMap.sources = sourceMap.sources.map(
|
|
543
|
+
(s: string) =>
|
|
544
|
+
// These are never loaded by Wrangler or DevTools. However, the presence of a scheme is required for DevTools to show the path as folders in the Sources view
|
|
545
|
+
// The scheme is intentially not the same as for the sourceMappingURL
|
|
546
|
+
// Without this difference in scheme, DevTools will not strip prefix `../` path elements from top level folders (../node_modules -> node_modules, for instance)
|
|
547
|
+
`worker://${props.name}/${path.relative(entryDirectory, s)}`
|
|
548
|
+
);
|
|
549
|
+
|
|
550
|
+
sendMessageToLocalWebSocket({
|
|
551
|
+
data: JSON.stringify({
|
|
552
|
+
id: message.id,
|
|
553
|
+
result: {
|
|
554
|
+
resource: {
|
|
555
|
+
success: true,
|
|
556
|
+
text: JSON.stringify(sourceMap),
|
|
557
|
+
},
|
|
558
|
+
},
|
|
559
|
+
}),
|
|
560
|
+
});
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
} catch (e) {
|
|
564
|
+
logger.debug(e);
|
|
565
|
+
// Ignore errors, fallthrough to the remote inspector
|
|
566
|
+
}
|
|
496
567
|
try {
|
|
497
568
|
assert(
|
|
498
569
|
remoteWebSocket,
|
|
@@ -517,11 +588,28 @@ export default function useInspector(props: InspectorProps) {
|
|
|
517
588
|
}
|
|
518
589
|
|
|
519
590
|
/** Send a message from the local websocket to the remote websocket */
|
|
520
|
-
function sendMessageToLocalWebSocket(event: MessageEvent) {
|
|
591
|
+
function sendMessageToLocalWebSocket(event: Pick<MessageEvent, "data">) {
|
|
521
592
|
assert(
|
|
522
593
|
localWebSocket,
|
|
523
594
|
"Trying to send a message to an undefined `localWebSocket`"
|
|
524
595
|
);
|
|
596
|
+
try {
|
|
597
|
+
// Intercept Debugger.scriptParsed responses to inject URL schemes
|
|
598
|
+
const message = JSON.parse(event.data as string);
|
|
599
|
+
if (message.method === "Debugger.scriptParsed") {
|
|
600
|
+
// Add the worker:// scheme conditionally, since some module types already have schemes (e.g. wasm)
|
|
601
|
+
message.params.url = new URL(
|
|
602
|
+
message.params.url,
|
|
603
|
+
`worker://${props.name}`
|
|
604
|
+
).href;
|
|
605
|
+
localWebSocket.send(JSON.stringify(message));
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
} catch (e) {
|
|
609
|
+
logger.debug(e);
|
|
610
|
+
// Ignore errors, fallthrough to the local websocket
|
|
611
|
+
}
|
|
612
|
+
|
|
525
613
|
localWebSocket.send(event.data);
|
|
526
614
|
}
|
|
527
615
|
|
|
@@ -555,7 +643,13 @@ export default function useInspector(props: InspectorProps) {
|
|
|
555
643
|
);
|
|
556
644
|
}
|
|
557
645
|
};
|
|
558
|
-
}, [
|
|
646
|
+
}, [
|
|
647
|
+
localWebSocket,
|
|
648
|
+
remoteWebSocket,
|
|
649
|
+
props.name,
|
|
650
|
+
props.sourceMapMetadata,
|
|
651
|
+
props.sourceMapPath,
|
|
652
|
+
]);
|
|
559
653
|
}
|
|
560
654
|
|
|
561
655
|
// Credit: https://stackoverflow.com/a/2117523
|
|
@@ -744,8 +838,15 @@ function logConsoleMessage(evt: Protocol.Runtime.ConsoleAPICalledEvent): void {
|
|
|
744
838
|
/**
|
|
745
839
|
* Opens the chrome debugger
|
|
746
840
|
*/
|
|
747
|
-
export const openInspector = async (
|
|
748
|
-
|
|
841
|
+
export const openInspector = async (
|
|
842
|
+
inspectorPort: number,
|
|
843
|
+
worker: string | undefined
|
|
844
|
+
) => {
|
|
845
|
+
const query = new URLSearchParams();
|
|
846
|
+
query.set("theme", "systemPreferred");
|
|
847
|
+
query.set("ws", `localhost:${inspectorPort}/ws`);
|
|
848
|
+
if (worker) query.set("domain", worker);
|
|
849
|
+
const url = `https://devtools.devprod.cloudflare.dev/js_app?${query.toString()}`;
|
|
749
850
|
const errorMessage =
|
|
750
851
|
"Failed to open inspector.\nInspector depends on having a Chromium-based browser installed, maybe you need to install one?";
|
|
751
852
|
|