wrangler 0.0.0-bb8dc5c → 0.0.0-bcb29aa

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wrangler",
3
- "version": "0.0.0-bb8dc5c",
3
+ "version": "0.0.0-bcb29aa",
4
4
  "author": "wrangler@cloudflare.com",
5
5
  "description": "Command-line interface for all things Cloudflare Workers",
6
6
  "bin": {
@@ -36,11 +36,13 @@
36
36
  "cli"
37
37
  ],
38
38
  "dependencies": {
39
- "@cloudflare/pages-functions-compiler": "0.3.5",
40
- "esbuild": "0.13.12",
41
- "miniflare": "2.0.0-rc.2",
39
+ "@cloudflare/pages-functions-compiler": "0.3.8",
40
+ "esbuild": "0.14.1",
41
+ "miniflare": "2.0.0-rc.3",
42
42
  "semiver": "^1.1.0",
43
- "serve": "^13.0.2"
43
+ "serve": "^13.0.2",
44
+ "@esbuild-plugins/node-globals-polyfill": "^0.1.1",
45
+ "@esbuild-plugins/node-modules-polyfill": "^0.1.2"
44
46
  },
45
47
  "optionalDependencies": {
46
48
  "fsevents": "~2.3.2"
@@ -49,13 +51,13 @@
49
51
  "@iarna/toml": "^2.2.5",
50
52
  "@types/cloudflare": "^2.7.6",
51
53
  "@types/express": "^4.17.13",
52
- "@types/react": "^17.0.34",
54
+ "@types/react": "^17.0.37",
53
55
  "@types/signal-exit": "^3.0.1",
54
- "@types/ws": "^8.2.0",
55
- "@types/yargs": "^17.0.5",
56
+ "@types/ws": "^8.2.1",
57
+ "@types/yargs": "^17.0.7",
56
58
  "clipboardy": "^3.0.0",
57
59
  "command-exists": "^1.2.9",
58
- "execa": "^5.1.1",
60
+ "execa": "^6.0.0",
59
61
  "express": "^4.17.1",
60
62
  "finalhandler": "^1.1.2",
61
63
  "find-up": "^6.2.0",
@@ -63,18 +65,18 @@
63
65
  "http-proxy": "^1.18.1",
64
66
  "http-proxy-middleware": "^2.0.1",
65
67
  "ink": "^3.2.0",
66
- "ink-select-input": "^4.2.0",
68
+ "ink-select-input": "^4.2.1",
67
69
  "ink-table": "^3.0.0",
68
- "ink-text-input": "^4.0.1",
70
+ "ink-text-input": "^4.0.2",
69
71
  "node-fetch": "^3.1.0",
70
72
  "open": "^8.4.0",
71
73
  "path-to-regexp": "^6.2.0",
72
74
  "react": "^17.0.2",
73
75
  "serve-static": "^1.14.1",
74
- "signal-exit": "^3.0.5",
76
+ "signal-exit": "^3.0.6",
75
77
  "tmp-promise": "^3.0.3",
76
- "ws": "^8.2.3",
77
- "yargs": "^17.2.1"
78
+ "ws": "^8.3.0",
79
+ "yargs": "^17.3.0"
78
80
  },
79
81
  "files": [
80
82
  "src",
@@ -98,7 +100,7 @@
98
100
  "jest": {
99
101
  "testRegex": ".*.(test|spec)\\.[jt]sx?$",
100
102
  "transformIgnorePatterns": [
101
- "node_modules/(?!node-fetch|fetch-blob|find-up|locate-path|p-locate|p-limit|yocto-queue|path-exists|data-uri-to-buffer|formdata-polyfill)"
103
+ "node_modules/(?!node-fetch|fetch-blob|find-up|locate-path|p-locate|p-limit|yocto-queue|path-exists|data-uri-to-buffer|formdata-polyfill|execa|strip-final-newline|npm-run-path|path-key|onetime|mimic-fn|human-signals|is-stream)"
102
104
  ],
103
105
  "moduleNameMapper": {
104
106
  "clipboardy": "<rootDir>/src/__tests__/clipboardy-mock.js"
@@ -110,7 +110,7 @@ describe("wrangler", () => {
110
110
  return { id: "some-namespace-id" };
111
111
  });
112
112
 
113
- await w('kv:namespace create "UnitTestNamespace"');
113
+ await w("kv:namespace create UnitTestNamespace");
114
114
  expect(
115
115
  KVNamespaces.find((ns) => ns.title === `worker-UnitTestNamespace`)
116
116
  ).toBeTruthy();
@@ -3,8 +3,6 @@ import type {
3
3
  CfModuleType,
4
4
  CfVariable,
5
5
  CfModule,
6
- CfKvNamespace,
7
- CfCryptoKey,
8
6
  } from "./worker.js";
9
7
  import { FormData, Blob } from "formdata-node";
10
8
 
@@ -27,12 +25,26 @@ function toBinding(
27
25
  return { name, type: "plain_text", text: variable };
28
26
  }
29
27
 
30
- const { namespaceId } = variable as CfKvNamespace;
31
- if (namespaceId) {
32
- return { name, type: "kv_namespace", namespace_id: namespaceId };
28
+ if ("namespaceId" in variable) {
29
+ return {
30
+ name,
31
+ type: "kv_namespace",
32
+ namespace_id: variable.namespaceId,
33
+ };
33
34
  }
34
35
 
35
- const { format, algorithm, usages, data } = variable as CfCryptoKey;
36
+ if ("class_name" in variable) {
37
+ return {
38
+ name,
39
+ type: "durable_object_namespace",
40
+ class_name: variable.class_name,
41
+ ...(variable.script_name && {
42
+ script_name: variable.script_name,
43
+ }),
44
+ };
45
+ }
46
+
47
+ const { format, algorithm, usages, data } = variable;
36
48
  if (format) {
37
49
  let key_base64;
38
50
  let key_jwk;
@@ -84,7 +96,15 @@ function toModule(module: CfModule, entryType?: CfModuleType): Blob {
84
96
  */
85
97
  export function toFormData(worker: CfWorkerInit): FormData {
86
98
  const formData = new FormData();
87
- const { main, modules, variables, usage_model, compatibility_date } = worker;
99
+ const {
100
+ main,
101
+ modules,
102
+ variables,
103
+ migrations,
104
+ usage_model,
105
+ compatibility_date,
106
+ compatibility_flags,
107
+ } = worker;
88
108
  const { name, type: mainType } = main;
89
109
 
90
110
  const bindings = [];
@@ -93,23 +113,36 @@ export function toFormData(worker: CfWorkerInit): FormData {
93
113
  bindings.push(binding);
94
114
  }
95
115
 
96
- const singleton = mainType === "commonjs";
97
- const metadata = {
98
- main_module: singleton ? undefined : name,
99
- body_part: singleton ? name : undefined,
100
- bindings,
101
- };
116
+ const metadata =
117
+ mainType !== "commonjs"
118
+ ? {
119
+ main_module: name,
120
+ bindings,
121
+ }
122
+ : {
123
+ body_part: name,
124
+ bindings,
125
+ };
102
126
  if (compatibility_date) {
103
127
  // @ts-expect-error - we should type metadata
104
128
  metadata.compatibility_date = compatibility_date;
105
129
  }
130
+ if (compatibility_flags) {
131
+ // @ts-expect-error - we should type metadata
132
+ metadata.compatibility_flags = compatibility_flags;
133
+ }
106
134
  if (usage_model) {
107
135
  // @ts-expect-error - we should type metadata
108
136
  metadata.usage_model = usage_model;
109
137
  }
138
+ if (migrations) {
139
+ // @ts-expect-error - we should type metadata
140
+ metadata.migrations = migrations;
141
+ }
142
+
110
143
  formData.set("metadata", JSON.stringify(metadata));
111
144
 
112
- if (singleton && modules && modules.length > 0) {
145
+ if (mainType === "commonjs" && modules && modules.length > 0) {
113
146
  throw new TypeError(
114
147
  "More than one module can only be specified when type = 'esm'"
115
148
  );
package/src/api/worker.ts CHANGED
@@ -72,6 +72,21 @@ export interface CfKvNamespace {
72
72
  namespaceId: string;
73
73
  }
74
74
 
75
+ export interface CfDurableObject {
76
+ class_name: string;
77
+ script_name?: string;
78
+ }
79
+
80
+ interface CfDOMigrations {
81
+ old_tag?: string;
82
+ new_tag: string;
83
+ steps: {
84
+ new_classes?: string[];
85
+ renamed_classes?: string[];
86
+ deleted_classes?: string[];
87
+ }[];
88
+ }
89
+
75
90
  /**
76
91
  * A `WebCrypto` key.
77
92
  *
@@ -99,12 +114,16 @@ export interface CfCryptoKey {
99
114
  /**
100
115
  * A variable (aka. environment variable).
101
116
  */
102
- export type CfVariable = string | CfKvNamespace | CfCryptoKey;
117
+ export type CfVariable = string | CfKvNamespace | CfCryptoKey | CfDurableObject;
103
118
 
104
119
  /**
105
120
  * Options for creating a `CfWorker`.
106
121
  */
107
122
  export interface CfWorkerInit {
123
+ /**
124
+ * The name of the worker.
125
+ */
126
+ name: string;
108
127
  /**
109
128
  * The entrypoint module.
110
129
  */
@@ -117,8 +136,10 @@ export interface CfWorkerInit {
117
136
  * The map of names to variables. (aka. environment variables)
118
137
  */
119
138
  variables?: { [name: string]: CfVariable };
120
- compatibility_date?: string;
121
- usage_model?: void | "bundled" | "unbound";
139
+ migrations: void | CfDOMigrations;
140
+ compatibility_date: string | void;
141
+ compatibility_flags: void | string[];
142
+ usage_model: void | "bundled" | "unbound";
122
143
  }
123
144
 
124
145
  /**
package/src/config.ts CHANGED
@@ -1,6 +1,13 @@
1
1
  // we're going to manually write both the type definition AND
2
2
  // the validator for the config, so that we can give better error messages
3
3
 
4
+ type DOMigration = {
5
+ tag: string;
6
+ new_classes?: string[];
7
+ renamed_classes?: string[];
8
+ deleted_classes?: string[];
9
+ };
10
+
4
11
  type Project = "webpack" | "javascript" | "rust";
5
12
 
6
13
  type Site = {
@@ -28,6 +35,12 @@ type KVNamespace = {
28
35
  id: string;
29
36
  };
30
37
 
38
+ type DurableObject = {
39
+ name: string;
40
+ class_name: string;
41
+ script_name?: string;
42
+ };
43
+
31
44
  type Build = {
32
45
  command?: string;
33
46
  cwd?: string;
@@ -59,16 +72,22 @@ type Env = {
59
72
  name?: string; // inherited
60
73
  account_id?: string; // inherited
61
74
  workers_dev?: boolean; // inherited
75
+ compatibility_date?: string; // inherited
76
+ compatibility_flags?: string[]; // inherited
62
77
  zone_id?: string; // inherited
63
78
  routes?: string[]; // inherited
64
79
  route?: string; // inherited
65
80
  webpack_config?: string; // inherited
66
81
  site?: Site;
67
- jsxFactory?: string; // inherited
68
- jsxFragment?: string; // inherited
82
+ jsx_factory?: string; // inherited
83
+ jsx_fragment?: string; // inherited
84
+ polyfill_node?: boolean; //inherited
69
85
  // we should use typescript to parse cron patterns
70
86
  triggers?: { crons: Cron[] }; // inherited
87
+ vars?: Vars;
88
+ durable_objects?: { bindings: DurableObject[] };
71
89
  kv_namespaces?: KVNamespace[];
90
+ usage_model?: UsageModel; // inherited
72
91
  };
73
92
 
74
93
  export type Config = {
@@ -76,6 +95,8 @@ export type Config = {
76
95
  account_id?: string; // inherited
77
96
  // @deprecated Don't use this
78
97
  type?: Project; // top level
98
+ compatibility_date?: string; // inherited
99
+ compatibility_flags?: string[]; // inherited
79
100
  // -- there's some mutually exclusive logic for this next block,
80
101
  // but I didn't bother for now
81
102
  workers_dev?: boolean; // inherited
@@ -85,9 +106,12 @@ export type Config = {
85
106
  // -- end mutually exclusive stuff
86
107
  // @deprecated Don't use this
87
108
  webpack_config?: string; // inherited
88
- jsxFactory?: string; // inherited
89
- jsxFragment?: string; // inherited
109
+ jsx_factory?: string; // inherited
110
+ jsx_fragment?: string; // inherited
111
+ polyfill_node?: boolean; //inherited
90
112
  vars?: Vars;
113
+ migrations?: DOMigration[];
114
+ durable_objects?: { bindings: DurableObject[] };
91
115
  kv_namespaces?: KVNamespace[];
92
116
  site?: Site; // inherited
93
117
  // we should use typescript to parse cron patterns
@@ -96,5 +120,5 @@ export type Config = {
96
120
  usage_model?: UsageModel; // inherited
97
121
  // top level
98
122
  build?: Build;
99
- env?: { [envName: string]: Env };
123
+ env?: { [envName: string]: void | Env };
100
124
  };
package/src/dev.tsx CHANGED
@@ -22,6 +22,8 @@ import commandExists from "command-exists";
22
22
  import assert from "assert";
23
23
  import { getAPIToken } from "./user";
24
24
  import fetch from "node-fetch";
25
+ import NodeModulesPolyfills from "@esbuild-plugins/node-modules-polyfill";
26
+ import NodeGlobalsPolyfills from "@esbuild-plugins/node-globals-polyfill";
25
27
 
26
28
  type CfScriptFormat = void | "modules" | "service-worker";
27
29
 
@@ -37,6 +39,10 @@ type Props = {
37
39
  variables: { [name: string]: CfVariable };
38
40
  public: void | string;
39
41
  site: void | string;
42
+ compatibilityDate: void | string;
43
+ compatibilityFlags: void | string[];
44
+ usageModel: void | "bundled" | "unbound";
45
+ polyfillNode: void | boolean;
40
46
  };
41
47
 
42
48
  export function Dev(props: Props): JSX.Element {
@@ -55,6 +61,7 @@ export function Dev(props: Props): JSX.Element {
55
61
  staticRoot: props.public,
56
62
  jsxFactory: props.jsxFactory,
57
63
  jsxFragment: props.jsxFragment,
64
+ polyfillNode: props.polyfillNode,
58
65
  });
59
66
  if (bundle && bundle.type === "commonjs" && !props.format && props.public) {
60
67
  throw new Error(
@@ -98,6 +105,9 @@ export function Dev(props: Props): JSX.Element {
98
105
  site={props.site}
99
106
  public={props.public}
100
107
  port={props.port}
108
+ compatibilityDate={props.compatibilityDate}
109
+ compatibilityFlags={props.compatibilityFlags}
110
+ usageModel={props.usageModel}
101
111
  />
102
112
  )}
103
113
  <Box borderStyle="round" paddingLeft={1} paddingRight={1}>
@@ -153,6 +163,9 @@ function Remote(props: {
153
163
  accountId: void | string;
154
164
  apiToken: void | string;
155
165
  variables: { [name: string]: CfVariable };
166
+ compatibilityDate: string | void;
167
+ compatibilityFlags: void | string[];
168
+ usageModel: void | "bundled" | "unbound";
156
169
  }) {
157
170
  assert(props.accountId, "accountId is required");
158
171
  assert(props.apiToken, "apiToken is required");
@@ -166,6 +179,9 @@ function Remote(props: {
166
179
  variables: props.variables,
167
180
  sitesFolder: props.site,
168
181
  port: props.port,
182
+ compatibilityDate: props.compatibilityDate,
183
+ compatibilityFlags: props.compatibilityFlags,
184
+ usageModel: props.usageModel,
169
185
  });
170
186
 
171
187
  useProxy({ token, publicRoot: props.public, port: props.port });
@@ -236,6 +252,7 @@ function useLocalWorker(props: {
236
252
  port.toString(),
237
253
  "--kv-persist",
238
254
  "--cache-persist",
255
+ "--do-persist",
239
256
  ...Object.entries(variables)
240
257
  .map(([varKey, varVal]) => {
241
258
  if (typeof varVal === "string") {
@@ -245,6 +262,8 @@ function useLocalWorker(props: {
245
262
  typeof varVal.namespaceId === "string"
246
263
  ) {
247
264
  return `--kv ${varKey}`;
265
+ } else if ("class_name" in varVal) {
266
+ return `--do ${varKey}=${varVal.class_name}`;
248
267
  }
249
268
  })
250
269
  .filter(Boolean),
@@ -262,7 +281,7 @@ function useLocalWorker(props: {
262
281
  }
263
282
  });
264
283
 
265
- local.current.stdout.on("data", (data: string) => {
284
+ local.current.stdout.on("data", (_data: string) => {
266
285
  // console.log(`stdout: ${data}`);
267
286
  });
268
287
 
@@ -277,7 +296,7 @@ function useLocalWorker(props: {
277
296
  }
278
297
  });
279
298
 
280
- removeSignalExitListener.current = onExit((code, signal) => {
299
+ removeSignalExitListener.current = onExit((_code, _signal) => {
281
300
  console.log("⎔ Shutting down local server.");
282
301
  local.current?.kill();
283
302
  local.current = undefined;
@@ -336,8 +355,16 @@ function useEsbuild(props: {
336
355
  staticRoot: void | string;
337
356
  jsxFactory: string | void;
338
357
  jsxFragment: string | void;
358
+ polyfillNode: boolean | void;
339
359
  }): EsbuildBundle | void {
340
- const { entry, destination, staticRoot, jsxFactory, jsxFragment } = props;
360
+ const {
361
+ entry,
362
+ destination,
363
+ staticRoot,
364
+ jsxFactory,
365
+ jsxFragment,
366
+ polyfillNode,
367
+ } = props;
341
368
  const [bundle, setBundle] = useState<EsbuildBundle>();
342
369
  useEffect(() => {
343
370
  let result: esbuild.BuildResult;
@@ -345,6 +372,9 @@ function useEsbuild(props: {
345
372
  if (!destination) return;
346
373
  result = await esbuild.build({
347
374
  entryPoints: [entry],
375
+ define: {
376
+ ...(polyfillNode && { global: "globalThis" }),
377
+ },
348
378
  bundle: true,
349
379
  outdir: destination,
350
380
  metafile: true,
@@ -353,6 +383,9 @@ function useEsbuild(props: {
353
383
  loader: {
354
384
  ".js": "jsx",
355
385
  },
386
+ plugins: polyfillNode
387
+ ? [NodeGlobalsPolyfills({ buffer: true }), NodeModulesPolyfills()]
388
+ : undefined,
356
389
  ...(jsxFactory && { jsxFactory }),
357
390
  ...(jsxFragment && { jsxFragment }),
358
391
  external: ["__STATIC_CONTENT_MANIFEST"],
@@ -385,7 +418,7 @@ function useEsbuild(props: {
385
418
  return () => {
386
419
  result?.stop();
387
420
  };
388
- }, [entry, destination, staticRoot]);
421
+ }, [entry, destination, staticRoot, jsxFactory, jsxFragment, polyfillNode]);
389
422
  return bundle;
390
423
  }
391
424
 
@@ -399,6 +432,9 @@ function useWorker(props: {
399
432
  variables: { [name: string]: CfVariable };
400
433
  sitesFolder: void | string;
401
434
  port: number;
435
+ compatibilityDate: string | void;
436
+ compatibilityFlags: string[] | void;
437
+ usageModel: void | "bundled" | "unbound";
402
438
  }): CfPreviewToken | void {
403
439
  const {
404
440
  name,
@@ -409,6 +445,9 @@ function useWorker(props: {
409
445
  apiToken,
410
446
  variables,
411
447
  sitesFolder,
448
+ compatibilityDate,
449
+ compatibilityFlags,
450
+ usageModel,
412
451
  port,
413
452
  } = props;
414
453
  const [token, setToken] = useState<CfPreviewToken>();
@@ -431,12 +470,11 @@ function useWorker(props: {
431
470
  } else {
432
471
  console.log("⎔ Starting server...");
433
472
  }
434
- const scriptName = path.basename(bundle.path);
435
473
 
436
474
  const assets = sitesFolder
437
475
  ? await syncAssets(
438
476
  accountId,
439
- scriptName,
477
+ path.basename(bundle.path),
440
478
  sitesFolder,
441
479
  true,
442
480
  undefined // TODO: env
@@ -447,15 +485,11 @@ function useWorker(props: {
447
485
  }; // TODO: cancellable?
448
486
 
449
487
  const content = await readFile(bundle.path, "utf-8");
450
- console.log(content);
451
488
  const init: CfWorkerInit = {
489
+ name: name || path.basename(bundle.path),
452
490
  main: {
453
- name: name || path.basename(bundle.path),
454
- type:
455
- format ||
456
- (bundle.type === "esm" ? "modules" : "service-worker") === "modules"
457
- ? "esm"
458
- : "commonjs",
491
+ name: path.basename(bundle.path),
492
+ type: format || bundle.type === "esm" ? "esm" : "commonjs",
459
493
  content,
460
494
  },
461
495
  modules: assets.manifest
@@ -471,6 +505,10 @@ function useWorker(props: {
471
505
  __STATIC_CONTENT: { namespaceId: assets.namespace },
472
506
  }
473
507
  : variables,
508
+ migrations: undefined, // no migrations in dev
509
+ compatibility_date: compatibilityDate,
510
+ compatibility_flags: compatibilityFlags,
511
+ usage_model: usageModel,
474
512
  };
475
513
  setToken(
476
514
  await createWorker(init, {
@@ -481,7 +519,18 @@ function useWorker(props: {
481
519
  console.log(`⬣ Listening at http://localhost:${port}`);
482
520
  }
483
521
  start();
484
- }, [name, bundle, format, accountId, apiToken, port, sitesFolder]);
522
+ }, [
523
+ name,
524
+ bundle,
525
+ format,
526
+ accountId,
527
+ apiToken,
528
+ port,
529
+ sitesFolder,
530
+ compatibilityDate,
531
+ compatibilityFlags,
532
+ usageModel,
533
+ ]);
485
534
  return token;
486
535
  }
487
536
 
@@ -606,7 +655,7 @@ function useTunnel(toggle: boolean) {
606
655
  }
607
656
  });
608
657
 
609
- removeSignalExitListener.current = onExit((code, signal) => {
658
+ removeSignalExitListener.current = onExit((_code, _signal) => {
610
659
  console.log("⎔ Shutting down local tunnel.");
611
660
  tunnel.current?.kill();
612
661
  tunnel.current = undefined;