wrangler 0.0.0-ea7ee45 → 0.0.0-eab9542

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.
@@ -832,6 +832,7 @@ function normalizeAndValidateEnvironment(
832
832
 
833
833
  experimental(diagnostics, rawEnv, "unsafe");
834
834
  experimental(diagnostics, rawEnv, "services");
835
+ experimental(diagnostics, rawEnv, "worker_namespaces");
835
836
 
836
837
  const route = normalizeAndValidateRoute(diagnostics, topLevelEnv, rawEnv);
837
838
 
@@ -1017,6 +1018,16 @@ function normalizeAndValidateEnvironment(
1017
1018
  validateBindingArray(envName, validateServiceBinding),
1018
1019
  []
1019
1020
  ),
1021
+ worker_namespaces: notInheritable(
1022
+ diagnostics,
1023
+ topLevelEnv,
1024
+ rawConfig,
1025
+ rawEnv,
1026
+ envName,
1027
+ "worker_namespaces",
1028
+ validateBindingArray(envName, validateWorkerNamespaceBinding),
1029
+ []
1030
+ ),
1020
1031
  unsafe: notInheritable(
1021
1032
  diagnostics,
1022
1033
  topLevelEnv,
@@ -1030,6 +1041,14 @@ function normalizeAndValidateEnvironment(
1030
1041
  }
1031
1042
  ),
1032
1043
  zone_id: rawEnv.zone_id,
1044
+ no_bundle: inheritable(
1045
+ diagnostics,
1046
+ topLevelEnv,
1047
+ rawEnv,
1048
+ "no_bundle",
1049
+ isBoolean,
1050
+ undefined
1051
+ ),
1033
1052
  minify: inheritable(
1034
1053
  diagnostics,
1035
1054
  topLevelEnv,
@@ -1656,6 +1675,7 @@ const validateBindingsHaveUniqueNames = (
1656
1675
 
1657
1676
  return !hasDuplicates;
1658
1677
  };
1678
+
1659
1679
  const validateServiceBinding: ValidatorFn = (diagnostics, field, value) => {
1660
1680
  if (typeof value !== "object" || value === null) {
1661
1681
  diagnostics.errors.push(
@@ -1691,3 +1711,35 @@ const validateServiceBinding: ValidatorFn = (diagnostics, field, value) => {
1691
1711
  }
1692
1712
  return isValid;
1693
1713
  };
1714
+
1715
+ const validateWorkerNamespaceBinding: ValidatorFn = (
1716
+ diagnostics,
1717
+ field,
1718
+ value
1719
+ ) => {
1720
+ if (typeof value !== "object" || value === null) {
1721
+ diagnostics.errors.push(
1722
+ `"${field}" binding should be objects, but got ${JSON.stringify(value)}`
1723
+ );
1724
+ return false;
1725
+ }
1726
+ let isValid = true;
1727
+ // Worker namespace bindings must have a binding, and a namespace.
1728
+ if (!isRequiredProperty(value, "binding", "string")) {
1729
+ diagnostics.errors.push(
1730
+ `"${field}" should have a string "binding" field but got ${JSON.stringify(
1731
+ value
1732
+ )}.`
1733
+ );
1734
+ isValid = false;
1735
+ }
1736
+ if (!isRequiredProperty(value, "namespace", "string")) {
1737
+ diagnostics.errors.push(
1738
+ `"${field}" should have a string "namespace" field but got ${JSON.stringify(
1739
+ value
1740
+ )}.`
1741
+ );
1742
+ isValid = false;
1743
+ }
1744
+ return isValid;
1745
+ };
@@ -1,44 +1,83 @@
1
1
  import { mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
2
- import { dirname, join } from "path";
2
+ import * as path from "path";
3
+ import { findUpSync } from "find-up";
4
+ import isInteractive from "./is-interactive";
5
+ import { logger } from "./logger";
3
6
 
4
7
  let cacheMessageShown = false;
5
8
 
6
- const cacheFolder = "node_modules/.cache/wrangler";
9
+ let __cacheFolder: string | null;
10
+ function getCacheFolder() {
11
+ if (__cacheFolder || __cacheFolder === null) return __cacheFolder;
7
12
 
8
- const showCacheMessage = () => {
9
- if (!cacheMessageShown) {
10
- console.log(
11
- `Using cached values in '${cacheFolder}'. This is used as a temporary store to improve the developer experience for some commands. It may be purged at any time. It doesn't contain any sensitive information, but it should not be commited into source control.`
12
- );
13
- cacheMessageShown = true;
13
+ const closestNodeModulesDirectory = findUpSync("node_modules", {
14
+ type: "directory",
15
+ });
16
+ __cacheFolder = closestNodeModulesDirectory
17
+ ? path.join(closestNodeModulesDirectory, ".cache/wrangler")
18
+ : null;
19
+
20
+ if (!__cacheFolder) {
21
+ logger.debug("No folder available to cache configuration");
22
+ }
23
+ return __cacheFolder;
24
+ }
25
+
26
+ const arrayFormatter = new Intl.ListFormat("en", {
27
+ style: "long",
28
+ type: "conjunction",
29
+ });
30
+
31
+ function showCacheMessage(fields: string[], folder: string) {
32
+ if (!cacheMessageShown && isInteractive()) {
33
+ if (fields.length > 0) {
34
+ logger.log(
35
+ `Retrieving cached values for ${arrayFormatter.format(
36
+ fields
37
+ )} from ${path.relative(process.cwd(), folder)}`
38
+ );
39
+ cacheMessageShown = true;
40
+ }
14
41
  }
15
- };
42
+ }
16
43
 
17
- export const getConfigCache = <T>(fileName: string): Partial<T> => {
44
+ export function getConfigCache<T>(fileName: string): Partial<T> {
18
45
  try {
19
- const configCacheLocation = join(cacheFolder, fileName);
20
- const configCache = JSON.parse(readFileSync(configCacheLocation, "utf-8"));
21
- showCacheMessage();
22
- return configCache;
23
- } catch {
46
+ const cacheFolder = getCacheFolder();
47
+ if (cacheFolder) {
48
+ const configCacheLocation = path.join(cacheFolder, fileName);
49
+ const configCache = JSON.parse(
50
+ readFileSync(configCacheLocation, "utf-8")
51
+ );
52
+ showCacheMessage(Object.keys(configCache), cacheFolder);
53
+ return configCache;
54
+ } else return {};
55
+ } catch (err) {
24
56
  return {};
25
57
  }
26
- };
58
+ }
27
59
 
28
- export const saveToConfigCache = <T>(
60
+ export function saveToConfigCache<T>(
29
61
  fileName: string,
30
62
  newValues: Partial<T>
31
- ) => {
32
- const configCacheLocation = join(cacheFolder, fileName);
33
- const existingValues = getConfigCache(fileName);
34
-
35
- mkdirSync(dirname(configCacheLocation), { recursive: true });
36
- writeFileSync(
37
- configCacheLocation,
38
- JSON.stringify({ ...existingValues, ...newValues }, null, 2)
39
- );
40
- };
41
-
42
- export const purgeConfigCaches = () => {
43
- rmSync(cacheFolder, { recursive: true, force: true });
44
- };
63
+ ): void {
64
+ const cacheFolder = getCacheFolder();
65
+ if (cacheFolder) {
66
+ logger.debug(`Saving to cache: ${JSON.stringify(newValues)}`);
67
+ const configCacheLocation = path.join(cacheFolder, fileName);
68
+ const existingValues = getConfigCache(fileName);
69
+
70
+ mkdirSync(path.dirname(configCacheLocation), { recursive: true });
71
+ writeFileSync(
72
+ configCacheLocation,
73
+ JSON.stringify({ ...existingValues, ...newValues }, null, 2)
74
+ );
75
+ }
76
+ }
77
+
78
+ export function purgeConfigCaches() {
79
+ const cacheFolder = getCacheFolder();
80
+ if (cacheFolder) {
81
+ rmSync(cacheFolder, { recursive: true, force: true });
82
+ }
83
+ }
@@ -50,6 +50,7 @@ export interface WorkerMetadata {
50
50
  }
51
51
  | { type: "r2_bucket"; name: string; bucket_name: string }
52
52
  | { type: "service"; name: string; service: string; environment?: string }
53
+ | { type: "namespace"; name: string; namespace: string }
53
54
  )[];
54
55
  }
55
56
 
@@ -116,6 +117,14 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
116
117
  });
117
118
  });
118
119
 
120
+ bindings.worker_namespaces?.forEach(({ binding, namespace }) => {
121
+ metadataBindings.push({
122
+ name: binding,
123
+ type: "namespace",
124
+ namespace,
125
+ });
126
+ });
127
+
119
128
  for (const [name, filePath] of Object.entries(bindings.wasm_modules || {})) {
120
129
  metadataBindings.push({
121
130
  name,
package/src/dev/dev.tsx CHANGED
@@ -24,7 +24,7 @@ import type { CfWorkerInit } from "../worker";
24
24
 
25
25
  export type DevProps = {
26
26
  name: string | undefined;
27
- noBuild: boolean;
27
+ noBundle: boolean;
28
28
  entry: Entry;
29
29
  port: number;
30
30
  ip: string;
@@ -155,7 +155,7 @@ function DevSession(props: DevSessionProps) {
155
155
  minify: props.minify,
156
156
  nodeCompat: props.nodeCompat,
157
157
  define: props.define,
158
- noBuild: props.noBuild,
158
+ noBundle: props.noBundle,
159
159
  });
160
160
 
161
161
  return props.local ? (
package/src/dev/local.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import { spawn } from "node:child_process";
1
+ import { fork } from "node:child_process";
2
2
  import { realpathSync } from "node:fs";
3
3
  import { writeFile } from "node:fs/promises";
4
4
  import path from "node:path";
@@ -13,7 +13,7 @@ import type { AssetPaths } from "../sites";
13
13
  import type { CfWorkerInit, CfScriptFormat } from "../worker";
14
14
  import type { EsbuildBundle } from "./use-esbuild";
15
15
  import type { MiniflareOptions } from "miniflare";
16
-
16
+ import type { ChildProcess } from "node:child_process";
17
17
  interface LocalProps {
18
18
  name: string | undefined;
19
19
  bundle: EsbuildBundle | undefined;
@@ -67,7 +67,7 @@ function useLocalWorker({
67
67
  logLevel,
68
68
  }: LocalProps) {
69
69
  // TODO: pass vars via command line
70
- const local = useRef<ReturnType<typeof spawn>>();
70
+ const local = useRef<ChildProcess>();
71
71
  const removeSignalExitListener = useRef<() => void>();
72
72
  const [inspectorUrl, setInspectorUrl] = useState<string | undefined>();
73
73
  // if we're using local persistence for data, we should use the cwd
@@ -236,43 +236,45 @@ function useLocalWorker({
236
236
  __dirname,
237
237
  "../miniflare-dist/index.mjs"
238
238
  );
239
- const optionsArg = JSON.stringify(options, null);
239
+ const miniflareOptions = JSON.stringify(options, null);
240
240
 
241
241
  logger.log("⎔ Starting a local server...");
242
- const localServerOptions = [
242
+ const nodeOptions = [
243
243
  "--experimental-vm-modules", // ensures that Miniflare can run ESM Workers
244
244
  "--no-warnings", // hide annoying Node warnings
245
- miniflareCLIPath,
246
- optionsArg,
247
245
  // "--log=VERBOSE", // uncomment this to Miniflare to log "everything"!
248
246
  ];
249
247
  if (inspect) {
250
- localServerOptions.push("--inspect"); // start Miniflare listening for a debugger to attach
248
+ nodeOptions.push("--inspect"); // start Miniflare listening for a debugger to attach
251
249
  }
252
- // spawn isn't technically synchronous here
253
- local.current = spawn("node", localServerOptions, {
254
- cwd: path.dirname(scriptPath),
250
+ const child = (local.current = fork(
251
+ miniflareCLIPath,
252
+ [miniflareOptions],
253
+ {
254
+ cwd: path.dirname(scriptPath),
255
+ execArgv: nodeOptions,
256
+ }
257
+ ));
258
+ child.on("message", (message) => {
259
+ if (message === "ready") {
260
+ onReady?.();
261
+ }
255
262
  });
256
- //TODO: instead of being lucky with spawn's timing, have miniflare-cli notify wrangler that it's ready in packages/wrangler/src/miniflare-cli/index.ts, after the mf.startScheduler promise resolves
257
- if (onReady) {
258
- await new Promise((resolve) => setTimeout(resolve, 200));
259
- onReady();
260
- }
261
263
 
262
- local.current.on("close", (code) => {
264
+ child.on("close", (code) => {
263
265
  if (code) {
264
266
  logger.log(`Miniflare process exited with code ${code}`);
265
267
  }
266
268
  });
267
269
 
268
- local.current.stdout?.on("data", (data: Buffer) => {
270
+ child.stdout?.on("data", (data: Buffer) => {
269
271
  process.stdout.write(data);
270
272
  });
271
273
 
272
274
  // parse the node inspector url (which may be received in chunks) from stderr
273
275
  let stderrData = "";
274
276
  let inspectorUrlFound = false;
275
- local.current.stderr?.on("data", (data: Buffer) => {
277
+ child.stderr?.on("data", (data: Buffer) => {
276
278
  if (!inspectorUrlFound) {
277
279
  stderrData += data.toString();
278
280
  const matches =
@@ -288,20 +290,20 @@ function useLocalWorker({
288
290
  process.stderr.write(data);
289
291
  });
290
292
 
291
- local.current.on("exit", (code) => {
293
+ child.on("exit", (code) => {
292
294
  if (code) {
293
295
  logger.error(`Miniflare process exited with code ${code}`);
294
296
  }
295
297
  });
296
298
 
297
- local.current.on("error", (error: Error) => {
299
+ child.on("error", (error: Error) => {
298
300
  logger.error(`Miniflare process failed to spawn`);
299
301
  logger.error(error);
300
302
  });
301
303
 
302
304
  removeSignalExitListener.current = onExit((_code, _signal) => {
303
305
  logger.log("⎔ Shutting down local server.");
304
- local.current?.kill();
306
+ child.kill();
305
307
  local.current = undefined;
306
308
  });
307
309
  }
@@ -11,7 +11,12 @@ import useInspector from "../inspect";
11
11
  import { logger } from "../logger";
12
12
  import { usePreviewServer } from "../proxy";
13
13
  import { syncAssets } from "../sites";
14
- import { ChooseAccount, getAccountChoices, requireApiToken } from "../user";
14
+ import {
15
+ ChooseAccount,
16
+ getAccountChoices,
17
+ requireApiToken,
18
+ saveAccountToCache,
19
+ } from "../user";
15
20
  import type { Route } from "../config/environment";
16
21
  import type {
17
22
  CfPreviewToken,
@@ -48,7 +53,7 @@ export function Remote(props: {
48
53
  zone: string | undefined;
49
54
  host: string | undefined;
50
55
  routes: Route[] | undefined;
51
- onReady?: () => void;
56
+ onReady?: (() => void) | undefined;
52
57
  }) {
53
58
  const [accountId, setAccountId] = useState(props.accountId);
54
59
  const accountChoicesRef = useRef<Promise<ChooseAccountItem[]>>();
@@ -96,13 +101,20 @@ export function Remote(props: {
96
101
  // This effect handles the async step of fetching the available accounts for the current user.
97
102
  // If only one account is available then it is just used by calling `setAccountId()`.
98
103
  useEffect(() => {
99
- if (accountChoicesRef.current !== undefined) {
104
+ if (
105
+ accountChoicesRef.current !== undefined ||
106
+ props.accountId !== undefined
107
+ ) {
100
108
  return;
101
109
  }
102
110
  accountChoicesRef.current = getAccountChoices();
103
111
  accountChoicesRef.current.then(
104
112
  (accounts) => {
105
113
  if (accounts.length === 1) {
114
+ saveAccountToCache({
115
+ id: accounts[0].id,
116
+ name: accounts[0].name,
117
+ });
106
118
  setAccountId(accounts[0].id);
107
119
  } else {
108
120
  setAccountChoices(accounts);
@@ -119,7 +131,10 @@ export function Remote(props: {
119
131
  return accountId === undefined && accountChoices !== undefined ? (
120
132
  <ChooseAccount
121
133
  accounts={accountChoices}
122
- onSelect={(selectedAccountId) => setAccountId(selectedAccountId)}
134
+ onSelect={(selectedAccount) => {
135
+ saveAccountToCache(selectedAccount);
136
+ setAccountId(selectedAccount.id);
137
+ }}
123
138
  onError={(err) => errorHandler(err)}
124
139
  ></ChooseAccount>
125
140
  ) : null;
@@ -143,7 +158,7 @@ export function useWorker(props: {
143
158
  zone: string | undefined;
144
159
  host: string | undefined;
145
160
  routes: Route[] | undefined;
146
- onReady?: () => void;
161
+ onReady: (() => void) | undefined;
147
162
  }): CfPreviewToken | undefined {
148
163
  const {
149
164
  name,
@@ -28,7 +28,7 @@ export function useEsbuild({
28
28
  minify,
29
29
  nodeCompat,
30
30
  define,
31
- noBuild,
31
+ noBundle,
32
32
  }: {
33
33
  entry: Entry;
34
34
  destination: string | undefined;
@@ -40,7 +40,7 @@ export function useEsbuild({
40
40
  tsconfig: string | undefined;
41
41
  minify: boolean | undefined;
42
42
  nodeCompat: boolean | undefined;
43
- noBuild: boolean;
43
+ noBundle: boolean;
44
44
  }): EsbuildBundle | undefined {
45
45
  const [bundle, setBundle] = useState<EsbuildBundle>();
46
46
  const { exit } = useApp();
@@ -76,7 +76,7 @@ export function useEsbuild({
76
76
  bundleType,
77
77
  modules,
78
78
  stop,
79
- }: Awaited<ReturnType<typeof bundleWorker>> = noBuild
79
+ }: Awaited<ReturnType<typeof bundleWorker>> = noBundle
80
80
  ? {
81
81
  modules: [],
82
82
  resolvedEntryPointPath: entry.file,
@@ -99,9 +99,9 @@ export function useEsbuild({
99
99
  // Capture the `stop()` method to use as the `useEffect()` destructor.
100
100
  stopWatching = stop;
101
101
 
102
- // if "noBuild" is true, then we need to manually watch the entry point and
102
+ // if "noBundle" is true, then we need to manually watch the entry point and
103
103
  // trigger "builds" when it changes
104
- if (noBuild) {
104
+ if (noBundle) {
105
105
  const watcher = watch(entry.file, {
106
106
  persistent: true,
107
107
  }).on("change", async (_event) => {
@@ -141,7 +141,7 @@ export function useEsbuild({
141
141
  rules,
142
142
  tsconfig,
143
143
  exit,
144
- noBuild,
144
+ noBundle,
145
145
  minify,
146
146
  nodeCompat,
147
147
  define,
package/src/dev.tsx CHANGED
@@ -3,6 +3,7 @@ import { watch } from "chokidar";
3
3
  import getPort from "get-port";
4
4
  import { render } from "ink";
5
5
  import React from "react";
6
+ import { fetch } from "undici";
6
7
  import { findWranglerToml, printBindings, readConfig } from "./config";
7
8
  import Dev from "./dev/dev";
8
9
  import { getVarsForDev } from "./dev/dev-vars";
@@ -10,6 +11,7 @@ import { getVarsForDev } from "./dev/dev-vars";
10
11
  import { getEntry } from "./entry";
11
12
  import { logger } from "./logger";
12
13
  import { getAssetPaths, getSiteAssetPaths } from "./sites";
14
+ import { getAccountFromCache } from "./user";
13
15
  import { getZoneIdFromHost, getZoneForRoute, getHostFromRoute } from "./zones";
14
16
  import {
15
17
  printWranglerBanner,
@@ -23,12 +25,15 @@ import {
23
25
 
24
26
  import type { Config } from "./config";
25
27
  import type { Route } from "./config/environment";
28
+ import type { CfWorkerInit } from "./worker";
29
+ import type { RequestInit } from "undici";
26
30
  import type { Argv, ArgumentsCamelCase } from "yargs";
27
31
 
28
32
  interface DevArgs {
29
33
  config?: string;
30
34
  script?: string;
31
35
  name?: string;
36
+ bundle?: boolean;
32
37
  build?: boolean;
33
38
  format?: string;
34
39
  env?: string;
@@ -74,17 +79,16 @@ export function devOptions(yargs: Argv): Argv<DevArgs> {
74
79
  type: "string",
75
80
  requiresArg: true,
76
81
  })
77
- // We want to have a --no-build flag, but yargs requires that
78
- // we also have a --build flag (that it adds the --no to by itself)
79
- // So we make a --build flag, but hide it, and then add a --no-build flag
82
+ // We want to have a --no-bundle flag, but yargs requires that
83
+ // we also have a --bundle flag (that it adds the --no to by itself)
84
+ // So we make a --bundle flag, but hide it, and then add a --no-bundle flag
80
85
  // that's visible to the user but doesn't "do" anything.
81
- .option("build", {
86
+ .option("bundle", {
82
87
  describe: "Run wrangler's compilation step before publishing",
83
88
  type: "boolean",
84
- default: true,
85
89
  hidden: true,
86
90
  })
87
- .option("no-build", {
91
+ .option("no-bundle", {
88
92
  describe: "Skip internal build steps and directly publish script",
89
93
  type: "boolean",
90
94
  default: false,
@@ -368,7 +372,9 @@ export async function startDev(args: ArgumentsCamelCase<DevArgs>) {
368
372
  }
369
373
 
370
374
  // eslint-disable-next-line no-inner-declarations
371
- async function getBindings(configParam: Config) {
375
+ async function getBindings(
376
+ configParam: Config
377
+ ): Promise<CfWorkerInit["bindings"]> {
372
378
  return {
373
379
  kv_namespaces: configParam.kv_namespaces?.map(
374
380
  ({ binding, preview_id, id: _id }) => {
@@ -412,6 +418,7 @@ export async function startDev(args: ArgumentsCamelCase<DevArgs>) {
412
418
  };
413
419
  }
414
420
  ),
421
+ worker_namespaces: configParam.worker_namespaces,
415
422
  services: configParam.services,
416
423
  unsafe: configParam.unsafe?.bindings,
417
424
  };
@@ -453,7 +460,7 @@ export async function startDev(args: ArgumentsCamelCase<DevArgs>) {
453
460
  return (
454
461
  <Dev
455
462
  name={getScriptName({ name: args.name, env: args.env }, config)}
456
- noBuild={!args.build}
463
+ noBundle={!(args.bundle ?? !config.no_bundle)}
457
464
  entry={entry}
458
465
  env={args.env}
459
466
  zone={zoneId}
@@ -475,7 +482,7 @@ export async function startDev(args: ArgumentsCamelCase<DevArgs>) {
475
482
  enableLocalPersistence={
476
483
  args["experimental-enable-local-persistence"] || false
477
484
  }
478
- accountId={config.account_id}
485
+ accountId={config.account_id || getAccountFromCache()?.id}
479
486
  assetPaths={assetPaths}
480
487
  port={args.port || config.dev.port || (await getLocalPort())}
481
488
  ip={args.ip || config.dev.ip}
@@ -505,9 +512,14 @@ export async function startDev(args: ArgumentsCamelCase<DevArgs>) {
505
512
  watcher,
506
513
  stop: async () => {
507
514
  devReactElement.unmount();
508
- await devReactElement.waitUntilExit();
509
515
  await watcher?.close();
510
- process.exit(0);
516
+ },
517
+ fetch: async (init?: RequestInit) => {
518
+ //TODO: we are not guaranteed to be assigned this port, we should fix this ASAP
519
+ const port = args.port || config.dev.port || (await getLocalPort());
520
+ const address = args.ip || config.dev.ip || "localhost";
521
+
522
+ return await fetch(`http://${address}:${port}/`, init);
511
523
  },
512
524
  };
513
525
  } finally {
package/src/index.tsx CHANGED
@@ -372,17 +372,16 @@ function createCLIParser(argv: string[]) {
372
372
  type: "string",
373
373
  requiresArg: true,
374
374
  })
375
- // We want to have a --no-build flag, but yargs requires that
376
- // we also have a --build flag (that it adds the --no to by itself)
377
- // So we make a --build flag, but hide it, and then add a --no-build flag
375
+ // We want to have a --no-bundle flag, but yargs requires that
376
+ // we also have a --bundle flag (that it adds the --no to by itself)
377
+ // So we make a --bundle flag, but hide it, and then add a --no-bundle flag
378
378
  // that's visible to the user but doesn't "do" anything.
379
- .option("build", {
379
+ .option("bundle", {
380
380
  describe: "Run wrangler's compilation step before publishing",
381
381
  type: "boolean",
382
- default: true,
383
382
  hidden: true,
384
383
  })
385
- .option("no-build", {
384
+ .option("no-bundle", {
386
385
  describe: "Skip internal build steps and directly publish script",
387
386
  type: "boolean",
388
387
  default: false,
@@ -564,7 +563,7 @@ function createCLIParser(argv: string[]) {
564
563
  isWorkersSite: Boolean(args.site || config.site),
565
564
  outDir: args.outdir,
566
565
  dryRun: args.dryRun,
567
- noBuild: !args.build,
566
+ noBundle: !(args.bundle ?? !config.no_bundle),
568
567
  });
569
568
  }
570
569
  );
@@ -917,6 +916,7 @@ function createCLIParser(argv: string[]) {
917
916
  wasm_modules: {},
918
917
  text_blobs: {},
919
918
  data_blobs: {},
919
+ worker_namespaces: [],
920
920
  unsafe: [],
921
921
  },
922
922
  modules: [],
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Test whether the process is "interactive".
3
+ * Reasons it may not be interactive: it could be running in CI,
4
+ * or you're piping values from / to another process, etc
5
+ */
6
+ export default function isInteractive(): boolean {
7
+ try {
8
+ return Boolean(process.stdin.isTTY && process.stdout.isTTY);
9
+ } catch {
10
+ return false;
11
+ }
12
+ }
@@ -41,6 +41,7 @@ async function main() {
41
41
  // Start Miniflare development server
42
42
  await mf.startServer();
43
43
  await mf.startScheduler();
44
+ process.send && process.send("ready");
44
45
  } catch (e) {
45
46
  mf.log.error(e as Error);
46
47
  process.exitCode = 1;
package/src/publish.ts CHANGED
@@ -46,7 +46,7 @@ type Props = {
46
46
  nodeCompat: boolean | undefined;
47
47
  outDir: string | undefined;
48
48
  dryRun: boolean | undefined;
49
- noBuild: boolean | undefined;
49
+ noBundle: boolean | undefined;
50
50
  };
51
51
 
52
52
  type RouteObject = ZoneIdRoute | ZoneNameRoute | CustomDomainRoute;
@@ -341,7 +341,7 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
341
341
  );
342
342
  }
343
343
  try {
344
- if (props.noBuild) {
344
+ if (props.noBundle) {
345
345
  // if we're not building, let's just copy the entry to the destination directory
346
346
  const destinationDir =
347
347
  typeof destination === "string" ? destination : destination.path;
@@ -356,7 +356,7 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
356
356
  modules,
357
357
  resolvedEntryPointPath,
358
358
  bundleType,
359
- }: Awaited<ReturnType<typeof bundleWorker>> = props.noBuild
359
+ }: Awaited<ReturnType<typeof bundleWorker>> = props.noBundle
360
360
  ? // we can skip the whole bundling step and mock a bundle here
361
361
  {
362
362
  modules: [],
@@ -426,6 +426,7 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m
426
426
  durable_objects: config.durable_objects,
427
427
  r2_buckets: config.r2_buckets,
428
428
  services: config.services,
429
+ worker_namespaces: config.worker_namespaces,
429
430
  unsafe: config.unsafe?.bindings,
430
431
  };
431
432