wrangler 2.1.5 → 2.1.7

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.
Files changed (55) hide show
  1. package/miniflare-dist/index.mjs +5 -20
  2. package/package.json +13 -3
  3. package/src/__tests__/api-dev.test.ts +20 -0
  4. package/src/__tests__/configuration.test.ts +128 -22
  5. package/src/__tests__/dev.test.tsx +0 -2
  6. package/src/__tests__/helpers/mock-oauth-flow.ts +4 -2
  7. package/src/__tests__/index.test.ts +2 -0
  8. package/src/__tests__/init.test.ts +72 -0
  9. package/src/__tests__/paths.test.ts +23 -1
  10. package/src/__tests__/publish.test.ts +65 -11
  11. package/src/__tests__/user.test.ts +4 -4
  12. package/src/__tests__/whoami.test.tsx +0 -1
  13. package/src/__tests__/worker-namespace.test.ts +102 -112
  14. package/src/api/dev.ts +12 -11
  15. package/src/bundle.ts +48 -0
  16. package/src/cfetch/internal.ts +37 -21
  17. package/src/config/config.ts +12 -0
  18. package/src/config/environment.ts +20 -0
  19. package/src/config/index.ts +32 -0
  20. package/src/config/validation.ts +68 -0
  21. package/src/config-cache.ts +1 -1
  22. package/src/create-worker-upload-form.ts +12 -2
  23. package/src/d1/backups.tsx +212 -0
  24. package/src/d1/create.tsx +54 -0
  25. package/src/d1/delete.tsx +56 -0
  26. package/src/d1/execute.tsx +294 -0
  27. package/src/d1/formatTimeAgo.ts +14 -0
  28. package/src/d1/index.ts +75 -0
  29. package/src/d1/list.tsx +48 -0
  30. package/src/d1/options.ts +12 -0
  31. package/src/d1/types.tsx +14 -0
  32. package/src/d1/utils.ts +39 -0
  33. package/src/dev/dev.tsx +26 -3
  34. package/src/dev/get-local-persistence-path.tsx +31 -0
  35. package/src/dev/local.tsx +8 -8
  36. package/src/dev/remote.tsx +1 -1
  37. package/src/dev/start-server.ts +2 -3
  38. package/src/dev/use-esbuild.ts +8 -1
  39. package/src/dev.tsx +28 -25
  40. package/src/dialogs.tsx +4 -0
  41. package/src/environment-variables.ts +17 -2
  42. package/src/index.tsx +26 -17
  43. package/src/init.ts +3 -1
  44. package/src/logger.ts +11 -4
  45. package/src/miniflare-cli/index.ts +11 -16
  46. package/src/pages/dev.tsx +13 -9
  47. package/src/paths.ts +30 -4
  48. package/src/proxy.ts +21 -1
  49. package/src/publish.ts +9 -1
  50. package/src/user/user.tsx +1 -0
  51. package/src/worker.ts +31 -1
  52. package/templates/d1-beta-facade.js +174 -0
  53. package/wrangler-dist/cli.d.ts +438 -6
  54. package/wrangler-dist/cli.js +10947 -3227
  55. package/src/miniflare-cli/enum-keys.ts +0 -17
@@ -739,7 +739,6 @@ import {
739
739
  } from "@miniflare/durable-objects";
740
740
  import {
741
741
  Log,
742
- LogLevel,
743
742
  Miniflare,
744
743
  Response as MiniflareResponse3,
745
744
  Request as MiniflareRequest3
@@ -6118,18 +6117,6 @@ var invalidAssetsFetch = () => {
6118
6117
  );
6119
6118
  };
6120
6119
 
6121
- // src/miniflare-cli/enum-keys.ts
6122
- var enumObject = (e) => {
6123
- const copy = { ...e };
6124
- Object.values(e).forEach(
6125
- (value) => typeof value === "number" && delete copy[value]
6126
- );
6127
- return copy;
6128
- };
6129
- var enumKeys = (e) => {
6130
- return Object.keys(enumObject(e));
6131
- };
6132
-
6133
6120
  // src/miniflare-cli/request-context.ts
6134
6121
  var getRequestContextCheckOptions = async () => {
6135
6122
  let hasAsyncLocalStorage = true;
@@ -6158,18 +6145,16 @@ var NoOpLog = class extends Log {
6158
6145
  }
6159
6146
  };
6160
6147
  async function main() {
6161
- const args = await yargs_default(hideBin(process.argv)).help(false).version(false).option("log", {
6162
- choices: enumKeys(LogLevel)
6163
- }).argv;
6164
- const logLevel = LogLevel[args.log ?? "INFO"];
6148
+ const args = await yargs_default(hideBin(process.argv)).help(false).version(false).argv;
6165
6149
  const requestContextCheckOptions = await getRequestContextCheckOptions();
6166
6150
  const config = {
6167
6151
  ...JSON.parse(args._[0] ?? "{}"),
6168
6152
  ...requestContextCheckOptions
6169
6153
  };
6170
- config.log = config.disableLogs ? new NoOpLog() : new Log(logLevel, config.logOptions);
6171
- if (logLevel > LogLevel.INFO) {
6172
- console.log("OPTIONS:\n", JSON.stringify(config, null, 2));
6154
+ const logLevel = config.logLevel.toUpperCase();
6155
+ config.log = config.logLevel === "none" ? new NoOpLog() : new Log(logLevel, config.logOptions);
6156
+ if (logLevel === "DEBUG" || logLevel === "VERBOSE") {
6157
+ console.log("MINIFLARE OPTIONS:\n", JSON.stringify(config, null, 2));
6173
6158
  }
6174
6159
  config.bindings = {
6175
6160
  ...config.bindings,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wrangler",
3
- "version": "2.1.5",
3
+ "version": "2.1.7",
4
4
  "description": "Command-line interface for all things Cloudflare Workers",
5
5
  "keywords": [
6
6
  "wrangler",
@@ -87,17 +87,20 @@
87
87
  ]
88
88
  },
89
89
  "transformIgnorePatterns": [
90
- "node_modules/(?!find-up|locate-path|p-locate|p-limit|p-timeout|p-queue|yocto-queue|path-exists|execa|strip-final-newline|npm-run-path|path-key|onetime|mimic-fn|human-signals|is-stream|get-port|supports-color|pretty-bytes)"
90
+ "node_modules/(?!find-up|locate-path|p-locate|p-limit|p-timeout|p-queue|yocto-queue|path-exists|execa|strip-final-newline|npm-run-path|path-key|onetime|mimic-fn|human-signals|is-stream|get-port|supports-color|pretty-bytes|npx-import)"
91
91
  ]
92
92
  },
93
93
  "dependencies": {
94
94
  "@cloudflare/kv-asset-handler": "^0.2.0",
95
95
  "@esbuild-plugins/node-globals-polyfill": "^0.1.1",
96
96
  "@esbuild-plugins/node-modules-polyfill": "^0.1.4",
97
+ "@miniflare/core": "2.9.0",
98
+ "@miniflare/d1": "2.9.0",
99
+ "@miniflare/durable-objects": "2.9.0",
97
100
  "blake3-wasm": "^2.1.5",
98
101
  "chokidar": "^3.5.3",
99
102
  "esbuild": "0.14.51",
100
- "miniflare": "^2.8.1",
103
+ "miniflare": "2.9.0",
101
104
  "nanoid": "^3.3.3",
102
105
  "path-to-regexp": "^6.2.0",
103
106
  "selfsigned": "^2.0.1",
@@ -105,12 +108,16 @@
105
108
  "xxhash-wasm": "^1.0.1"
106
109
  },
107
110
  "devDependencies": {
111
+ "@databases/split-sql-query": "^1.0.3",
112
+ "@databases/sql": "^3.2.0",
108
113
  "@iarna/toml": "^3.0.0",
109
114
  "@microsoft/api-extractor": "^7.28.3",
115
+ "@types/better-sqlite3": "^7.6.0",
110
116
  "@types/busboy": "^1.5.0",
111
117
  "@types/command-exists": "^1.2.0",
112
118
  "@types/express": "^4.17.13",
113
119
  "@types/glob-to-regexp": "0.4.1",
120
+ "@types/javascript-time-ago": "^2.0.3",
114
121
  "@types/mime": "^2.0.3",
115
122
  "@types/prompts": "^2.0.14",
116
123
  "@types/react": "^17.0.37",
@@ -145,16 +152,19 @@
145
152
  "ink-testing-library": "^2.1.0",
146
153
  "ink-text-input": "^4.0.3",
147
154
  "is-ci": "^3.0.1",
155
+ "javascript-time-ago": "^2.5.4",
148
156
  "jest-fetch-mock": "^3.0.3",
149
157
  "jest-websocket-mock": "^2.3.0",
150
158
  "mime": "^3.0.0",
151
159
  "msw": "^0.47.1",
160
+ "npx-import": "^1.0.2",
152
161
  "open": "^8.4.0",
153
162
  "p-queue": "^7.2.0",
154
163
  "pretty-bytes": "^6.0.0",
155
164
  "prompts": "^2.4.2",
156
165
  "react": "^17.0.2",
157
166
  "react-error-boundary": "^3.1.4",
167
+ "remove-accents-esm": "^0.0.1",
158
168
  "serve-static": "^1.15.0",
159
169
  "signal-exit": "^3.0.7",
160
170
  "supports-color": "^9.2.2",
@@ -19,6 +19,26 @@ describe("unstable_dev", () => {
19
19
  }
20
20
  await worker.stop();
21
21
  });
22
+
23
+ it("should return the port that the server started on (1)", async () => {
24
+ const worker = await unstable_dev(
25
+ "src/__tests__/helpers/worker-scripts/hello-world-worker.js",
26
+ {},
27
+ { disableExperimentalWarning: true }
28
+ );
29
+ expect(worker.port).toBeGreaterThan(0);
30
+ await worker.stop();
31
+ });
32
+
33
+ it("should return the port that the server started on (2)", async () => {
34
+ const worker = await unstable_dev(
35
+ "src/__tests__/helpers/worker-scripts/hello-world-worker.js",
36
+ { port: 9191 },
37
+ { disableExperimentalWarning: true }
38
+ );
39
+ expect(worker.port).toBe(9191);
40
+ await worker.stop();
41
+ });
22
42
  });
23
43
 
24
44
  describe("unstable dev fetch input protocol", () => {
@@ -25,6 +25,7 @@ describe("normalizeAndValidateConfig()", () => {
25
25
  compatibility_date: undefined,
26
26
  compatibility_flags: [],
27
27
  configPath: undefined,
28
+ d1_databases: [],
28
29
  dev: {
29
30
  ip: "0.0.0.0",
30
31
  local_protocol: "http",
@@ -73,6 +74,7 @@ describe("normalizeAndValidateConfig()", () => {
73
74
  minify: undefined,
74
75
  node_compat: undefined,
75
76
  first_party_worker: undefined,
77
+ keep_vars: undefined,
76
78
  });
77
79
  expect(diagnostics.hasErrors()).toBe(false);
78
80
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -106,6 +108,7 @@ describe("normalizeAndValidateConfig()", () => {
106
108
  const expectedConfig = {
107
109
  legacy_env: "FOO",
108
110
  send_metrics: "BAD",
111
+ keep_vars: "NEVER",
109
112
  dev: {
110
113
  ip: 222,
111
114
  port: "FOO",
@@ -128,6 +131,7 @@ describe("normalizeAndValidateConfig()", () => {
128
131
  "Processing wrangler configuration:
129
132
  - Expected \\"legacy_env\\" to be of type boolean but got \\"FOO\\".
130
133
  - Expected \\"send_metrics\\" to be of type boolean but got \\"BAD\\".
134
+ - Expected \\"keep_vars\\" to be of type boolean but got \\"NEVER\\".
131
135
  - Expected \\"dev.ip\\" to be of type string but got 222.
132
136
  - Expected \\"dev.port\\" to be of type number but got \\"FOO\\".
133
137
  - Expected \\"dev.local_protocol\\" field to be one of [\\"http\\",\\"https\\"] but got \\"wss\\".
@@ -1661,6 +1665,108 @@ describe("normalizeAndValidateConfig()", () => {
1661
1665
  });
1662
1666
  });
1663
1667
 
1668
+ describe("[d1_databases]", () => {
1669
+ it("should error if d1_databases is an object", () => {
1670
+ const { config, diagnostics } = normalizeAndValidateConfig(
1671
+ { d1_databases: {} } as unknown as RawConfig,
1672
+ undefined,
1673
+ { env: undefined }
1674
+ );
1675
+
1676
+ expect(config).toEqual(
1677
+ expect.not.objectContaining({ d1_databases: expect.anything })
1678
+ );
1679
+ expect(diagnostics.hasWarnings()).toBe(false);
1680
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1681
+ "Processing wrangler configuration:
1682
+ - The field \\"d1_databases\\" should be an array but got {}."
1683
+ `);
1684
+ });
1685
+
1686
+ it("should error if d1_databases is a string", () => {
1687
+ const { config, diagnostics } = normalizeAndValidateConfig(
1688
+ { d1_databases: "BAD" } as unknown as RawConfig,
1689
+ undefined,
1690
+ { env: undefined }
1691
+ );
1692
+
1693
+ expect(config).toEqual(
1694
+ expect.not.objectContaining({ d1_databases: expect.anything })
1695
+ );
1696
+ expect(diagnostics.hasWarnings()).toBe(false);
1697
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1698
+ "Processing wrangler configuration:
1699
+ - The field \\"d1_databases\\" should be an array but got \\"BAD\\"."
1700
+ `);
1701
+ });
1702
+
1703
+ it("should error if d1_databases is a number", () => {
1704
+ const { config, diagnostics } = normalizeAndValidateConfig(
1705
+ { d1_databases: 999 } as unknown as RawConfig,
1706
+ undefined,
1707
+ { env: undefined }
1708
+ );
1709
+
1710
+ expect(config).toEqual(
1711
+ expect.not.objectContaining({ d1_databases: expect.anything })
1712
+ );
1713
+ expect(diagnostics.hasWarnings()).toBe(false);
1714
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1715
+ "Processing wrangler configuration:
1716
+ - The field \\"d1_databases\\" should be an array but got 999."
1717
+ `);
1718
+ });
1719
+
1720
+ it("should error if d1_databases is null", () => {
1721
+ const { config, diagnostics } = normalizeAndValidateConfig(
1722
+ { d1_databases: null } as unknown as RawConfig,
1723
+ undefined,
1724
+ { env: undefined }
1725
+ );
1726
+
1727
+ expect(config).toEqual(
1728
+ expect.not.objectContaining({ d1_databases: expect.anything })
1729
+ );
1730
+ expect(diagnostics.hasWarnings()).toBe(false);
1731
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1732
+ "Processing wrangler configuration:
1733
+ - The field \\"d1_databases\\" should be an array but got null."
1734
+ `);
1735
+ });
1736
+
1737
+ it("should error if d1_databases.bindings are not valid", () => {
1738
+ const { diagnostics } = normalizeAndValidateConfig(
1739
+ {
1740
+ d1_databases: [
1741
+ {},
1742
+ { binding: "VALID" },
1743
+ { binding: 2000, id: 2111 },
1744
+ {
1745
+ binding: "D1_BINDING_2",
1746
+ id: "my-db",
1747
+ preview_id: 2222,
1748
+ },
1749
+ { binding: "VALID", id: "" },
1750
+ ],
1751
+ } as unknown as RawConfig,
1752
+ undefined,
1753
+ { env: undefined }
1754
+ );
1755
+
1756
+ expect(diagnostics.hasWarnings()).toBe(false);
1757
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1758
+ "Processing wrangler configuration:
1759
+ - \\"d1_databases[0]\\" bindings should have a string \\"binding\\" field but got {}.
1760
+ - \\"d1_databases[0]\\" bindings must have a \\"database_id\\" field but got {}.
1761
+ - \\"d1_databases[1]\\" bindings must have a \\"database_id\\" field but got {\\"binding\\":\\"VALID\\"}.
1762
+ - \\"d1_databases[2]\\" bindings should have a string \\"binding\\" field but got {\\"binding\\":2000,\\"id\\":2111}.
1763
+ - \\"d1_databases[2]\\" bindings must have a \\"database_id\\" field but got {\\"binding\\":2000,\\"id\\":2111}.
1764
+ - \\"d1_databases[3]\\" bindings must have a \\"database_id\\" field but got {\\"binding\\":\\"D1_BINDING_2\\",\\"id\\":\\"my-db\\",\\"preview_id\\":2222}.
1765
+ - \\"d1_databases[4]\\" bindings must have a \\"database_id\\" field but got {\\"binding\\":\\"VALID\\",\\"id\\":\\"\\"}."
1766
+ `);
1767
+ });
1768
+ });
1769
+
1664
1770
  describe("[r2_buckets]", () => {
1665
1771
  it("should error if r2_buckets is an object", () => {
1666
1772
  const { config, diagnostics } = normalizeAndValidateConfig(
@@ -2661,28 +2767,28 @@ describe("normalizeAndValidateConfig()", () => {
2661
2767
  );
2662
2768
  expect(diagnostics.hasErrors()).toBe(false);
2663
2769
  expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
2664
- "Processing wrangler configuration:
2665
- - \\"unsafe\\" fields are experimental and may change or break at any time.
2666
- - \\"env.ENV1\\" environment configuration
2667
- - \\"vars\\" exists at the top level, but not on \\"env.ENV1\\".
2668
- This is not what you probably want, since \\"vars\\" is not inherited by environments.
2669
- Please add \\"vars\\" to \\"env.ENV1\\".
2670
- - \\"define\\" exists at the top level, but not on \\"env.ENV1\\".
2671
- This is not what you probably want, since \\"define\\" is not inherited by environments.
2672
- Please add \\"define\\" to \\"env.ENV1\\".
2673
- - \\"durable_objects\\" exists at the top level, but not on \\"env.ENV1\\".
2674
- This is not what you probably want, since \\"durable_objects\\" is not inherited by environments.
2675
- Please add \\"durable_objects\\" to \\"env.ENV1\\".
2676
- - \\"kv_namespaces\\" exists at the top level, but not on \\"env.ENV1\\".
2677
- This is not what you probably want, since \\"kv_namespaces\\" is not inherited by environments.
2678
- Please add \\"kv_namespaces\\" to \\"env.ENV1\\".
2679
- - \\"r2_buckets\\" exists at the top level, but not on \\"env.ENV1\\".
2680
- This is not what you probably want, since \\"r2_buckets\\" is not inherited by environments.
2681
- Please add \\"r2_buckets\\" to \\"env.ENV1\\".
2682
- - \\"unsafe\\" exists at the top level, but not on \\"env.ENV1\\".
2683
- This is not what you probably want, since \\"unsafe\\" is not inherited by environments.
2684
- Please add \\"unsafe\\" to \\"env.ENV1\\"."
2685
- `);
2770
+ "Processing wrangler configuration:
2771
+ - \\"unsafe\\" fields are experimental and may change or break at any time.
2772
+ - \\"env.ENV1\\" environment configuration
2773
+ - \\"vars\\" exists at the top level, but not on \\"env.ENV1\\".
2774
+ This is not what you probably want, since \\"vars\\" is not inherited by environments.
2775
+ Please add \\"vars\\" to \\"env.ENV1\\".
2776
+ - \\"define\\" exists at the top level, but not on \\"env.ENV1\\".
2777
+ This is not what you probably want, since \\"define\\" is not inherited by environments.
2778
+ Please add \\"define\\" to \\"env.ENV1\\".
2779
+ - \\"durable_objects\\" exists at the top level, but not on \\"env.ENV1\\".
2780
+ This is not what you probably want, since \\"durable_objects\\" is not inherited by environments.
2781
+ Please add \\"durable_objects\\" to \\"env.ENV1\\".
2782
+ - \\"kv_namespaces\\" exists at the top level, but not on \\"env.ENV1\\".
2783
+ This is not what you probably want, since \\"kv_namespaces\\" is not inherited by environments.
2784
+ Please add \\"kv_namespaces\\" to \\"env.ENV1\\".
2785
+ - \\"r2_buckets\\" exists at the top level, but not on \\"env.ENV1\\".
2786
+ This is not what you probably want, since \\"r2_buckets\\" is not inherited by environments.
2787
+ Please add \\"r2_buckets\\" to \\"env.ENV1\\".
2788
+ - \\"unsafe\\" exists at the top level, but not on \\"env.ENV1\\".
2789
+ This is not what you probably want, since \\"unsafe\\" is not inherited by environments.
2790
+ Please add \\"unsafe\\" to \\"env.ENV1\\"."
2791
+ `);
2686
2792
  });
2687
2793
 
2688
2794
  it("should error on invalid environment values", () => {
@@ -183,7 +183,6 @@ describe("wrangler dev", () => {
183
183
  );
184
184
  });
185
185
  });
186
-
187
186
  describe("host", () => {
188
187
  it("should resolve a host to its zone", async () => {
189
188
  writeWranglerToml({
@@ -1108,7 +1107,6 @@ describe("wrangler dev", () => {
1108
1107
  await runWrangler("dev --assets abc");
1109
1108
  expect((Dev as jest.Mock).mock.calls[2][0].isWorkersSite).toEqual(false);
1110
1109
  });
1111
-
1112
1110
  it("should warn if --assets is used", async () => {
1113
1111
  writeWranglerToml({
1114
1112
  main: "./index.js",
@@ -97,7 +97,8 @@ export const mockOAuthFlow = () => {
97
97
  };
98
98
 
99
99
  fetchMock.mockIf(outcome.expected.url, async (req) => {
100
- outcome.actual = req;
100
+ // TODO: update Miniflare typings to match full undici Request
101
+ outcome.actual = req as unknown as Request;
101
102
  return "";
102
103
  });
103
104
 
@@ -117,7 +118,8 @@ export const mockOAuthFlow = () => {
117
118
  };
118
119
 
119
120
  fetchMock.mockOnceIf(outcome.expected.url, async (req) => {
120
- outcome.actual = req;
121
+ // TODO: update Miniflare typings to match full undici Request
122
+ outcome.actual = req as unknown as Request;
121
123
  return makeTokenResponse(respondWith);
122
124
  });
123
125
 
@@ -43,6 +43,7 @@ describe("wrangler", () => {
43
43
  wrangler pages ⚡️ Configure Cloudflare Pages
44
44
  wrangler r2 📦 Interact with an R2 store
45
45
  wrangler dispatch-namespace 📦 Interact with a dispatch namespace
46
+ wrangler d1 🗄 Interact with a D1 database
46
47
  wrangler pubsub 📮 Interact and manage Pub/Sub Brokers
47
48
  wrangler login 🔓 Login to Cloudflare
48
49
  wrangler logout 🚪 Logout from Cloudflare
@@ -83,6 +84,7 @@ describe("wrangler", () => {
83
84
  wrangler pages ⚡️ Configure Cloudflare Pages
84
85
  wrangler r2 📦 Interact with an R2 store
85
86
  wrangler dispatch-namespace 📦 Interact with a dispatch namespace
87
+ wrangler d1 🗄 Interact with a D1 database
86
88
  wrangler pubsub 📮 Interact and manage Pub/Sub Brokers
87
89
  wrangler login 🔓 Login to Cloudflare
88
90
  wrangler logout 🚪 Logout from Cloudflare
@@ -2270,6 +2270,12 @@ describe("init", () => {
2270
2270
  expectedAccountId = "",
2271
2271
  expectedScriptName = "",
2272
2272
  expectedEnvironment = "",
2273
+ expectedCompatDate,
2274
+ }: {
2275
+ expectedAccountId: string;
2276
+ expectedScriptName: string;
2277
+ expectedEnvironment: string;
2278
+ expectedCompatDate: string | undefined;
2273
2279
  }) {
2274
2280
  setMockResponse(
2275
2281
  `/accounts/:accountId/workers/services/:scriptName`,
@@ -2278,6 +2284,9 @@ describe("init", () => {
2278
2284
  expect(accountId).toEqual(expectedAccountId);
2279
2285
  expect(scriptName).toEqual(expectedScriptName);
2280
2286
 
2287
+ if (expectedCompatDate === undefined)
2288
+ (mockServiceMetadata.default_environment.script
2289
+ .compatibility_date as unknown) = expectedCompatDate;
2281
2290
  return mockServiceMetadata;
2282
2291
  }
2283
2292
  );
@@ -2340,6 +2349,7 @@ describe("init", () => {
2340
2349
  expectedAccountId: "LCARS",
2341
2350
  expectedScriptName: "memory-crystal",
2342
2351
  expectedEnvironment: "test",
2352
+ expectedCompatDate: "1987-9-27",
2343
2353
  });
2344
2354
  setMockFetchDashScript({
2345
2355
  accountId: "LCARS",
@@ -2394,6 +2404,7 @@ describe("init", () => {
2394
2404
  expectedAccountId: "LCARS",
2395
2405
  expectedScriptName: "isolinear-optical-chip",
2396
2406
  expectedEnvironment: "test",
2407
+ expectedCompatDate: "1987-9-27",
2397
2408
  });
2398
2409
  setMockFetchDashScript({
2399
2410
  accountId: "LCARS",
@@ -2447,6 +2458,7 @@ describe("init", () => {
2447
2458
  expectedAccountId: "LCARS",
2448
2459
  expectedScriptName: "isolinear-optical-chip",
2449
2460
  expectedEnvironment: "test",
2461
+ expectedCompatDate: "1987-9-27",
2450
2462
  });
2451
2463
  setMockFetchDashScript({
2452
2464
  accountId: "LCARS",
@@ -2494,6 +2506,66 @@ describe("init", () => {
2494
2506
  },
2495
2507
  });
2496
2508
  });
2509
+
2510
+ it("should use fallback compatibility date if none is upstream", async () => {
2511
+ const mockDate = "1988-08-07";
2512
+ jest
2513
+ .spyOn(Date.prototype, "toISOString")
2514
+ .mockImplementation(() => `${mockDate}T00:00:00.000Z`);
2515
+
2516
+ mockSupportingDashRequests({
2517
+ expectedAccountId: "LCARS",
2518
+ expectedScriptName: "isolinear-optical-chip",
2519
+ expectedEnvironment: "test",
2520
+ expectedCompatDate: undefined,
2521
+ });
2522
+ setMockFetchDashScript({
2523
+ accountId: "LCARS",
2524
+ fromDashScriptName: "isolinear-optical-chip",
2525
+ environment: mockServiceMetadata.default_environment.environment,
2526
+ mockResponse: mockDashboardScript,
2527
+ });
2528
+ mockConfirm(
2529
+ {
2530
+ text: "Would you like to use git to manage this Worker?",
2531
+ result: false,
2532
+ },
2533
+ {
2534
+ text: "Would you like to use TypeScript?",
2535
+ result: true,
2536
+ },
2537
+ {
2538
+ text: "No package.json found. Would you like to create one?",
2539
+ result: true,
2540
+ },
2541
+ {
2542
+ text: "Would you like to install the type definitions for Workers into your package.json?",
2543
+ result: true,
2544
+ }
2545
+ );
2546
+
2547
+ await runWrangler("init --from-dash isolinear-optical-chip");
2548
+
2549
+ mockConfigExpected.compatibility_date = "1988-08-07";
2550
+ checkFiles({
2551
+ items: {
2552
+ "isolinear-optical-chip/src/index.ts": {
2553
+ contents: mockDashboardScript,
2554
+ },
2555
+ "isolinear-optical-chip/package.json": {
2556
+ contents: expect.objectContaining({
2557
+ name: "isolinear-optical-chip",
2558
+ }),
2559
+ },
2560
+ "isolinear-optical-chip/tsconfig.json": true,
2561
+ "isolinear-optical-chip/wrangler.toml": wranglerToml({
2562
+ ...mockConfigExpected,
2563
+ name: "isolinear-optical-chip",
2564
+ }),
2565
+ },
2566
+ });
2567
+ });
2568
+
2497
2569
  it("should throw an error to retry if a request fails", async () => {
2498
2570
  setMockResponse(
2499
2571
  `/accounts/:accountId/workers/services/:scriptName`,
@@ -1,5 +1,5 @@
1
1
  import * as path from "node:path";
2
- import { getBasePath } from "../paths";
2
+ import { getBasePath, readableRelative } from "../paths";
3
3
 
4
4
  describe("paths", () => {
5
5
  describe("getBasePath()", () => {
@@ -15,3 +15,25 @@ describe("paths", () => {
15
15
  });
16
16
  });
17
17
  });
18
+
19
+ describe("readableRelative", () => {
20
+ const base = process.cwd();
21
+
22
+ it("should leave paths to files in the current directory as-is", () => {
23
+ expect(readableRelative(path.join(base, "wrangler.toml"))).toBe(
24
+ `wrangler.toml`
25
+ );
26
+ });
27
+
28
+ it("should leave files in the parent directory as-is", () => {
29
+ expect(readableRelative(path.resolve(base, "../wrangler.toml"))).toMatch(
30
+ /^\..[/\\]wrangler.toml$/
31
+ );
32
+ });
33
+
34
+ it("should add ./ to nested paths", () => {
35
+ expect(
36
+ readableRelative(path.join(base, "subdir", "wrangler.toml"))
37
+ ).toMatch(/^\.[/\\]subdir[/\\]wrangler\.toml$/);
38
+ });
39
+ });
@@ -123,14 +123,14 @@ describe("publish", () => {
123
123
  );
124
124
 
125
125
  expect(std.out).toMatchInlineSnapshot(`
126
- "Attempting to login via OAuth...
127
- Opening a link in your default browser: https://dash.cloudflare.com/oauth2/auth?response_type=code&client_id=54d11594-84e4-41aa-b438-e81b8fa78ee7&redirect_uri=http%3A%2F%2Flocalhost%3A8976%2Foauth%2Fcallback&scope=account%3Aread%20user%3Aread%20workers%3Awrite%20workers_kv%3Awrite%20workers_routes%3Awrite%20workers_scripts%3Awrite%20workers_tail%3Aread%20pages%3Awrite%20zone%3Aread%20offline_access&state=MOCK_STATE_PARAM&code_challenge=MOCK_CODE_CHALLENGE&code_challenge_method=S256
128
- Successfully logged in.
129
- Total Upload: xx KiB / gzip: xx KiB
130
- Uploaded test-name (TIMINGS)
131
- Published test-name (TIMINGS)
132
- https://test-name.test-sub-domain.workers.dev"
133
- `);
126
+ "Attempting to login via OAuth...
127
+ Opening a link in your default browser: https://dash.cloudflare.com/oauth2/auth?response_type=code&client_id=54d11594-84e4-41aa-b438-e81b8fa78ee7&redirect_uri=http%3A%2F%2Flocalhost%3A8976%2Foauth%2Fcallback&scope=account%3Aread%20user%3Aread%20workers%3Awrite%20workers_kv%3Awrite%20workers_routes%3Awrite%20workers_scripts%3Awrite%20workers_tail%3Aread%20d1%3Awrite%20pages%3Awrite%20zone%3Aread%20offline_access&state=MOCK_STATE_PARAM&code_challenge=MOCK_CODE_CHALLENGE&code_challenge_method=S256
128
+ Successfully logged in.
129
+ Total Upload: xx KiB / gzip: xx KiB
130
+ Uploaded test-name (TIMINGS)
131
+ Published test-name (TIMINGS)
132
+ https://test-name.test-sub-domain.workers.dev"
133
+ `);
134
134
  expect(std.warn).toMatchInlineSnapshot(`""`);
135
135
  expect(std.err).toMatchInlineSnapshot(`""`);
136
136
  });
@@ -559,7 +559,6 @@ describe("publish", () => {
559
559
  }
560
560
  `);
561
561
  });
562
-
563
562
  it("should publish to a route with a pattern/{zone_id|zone_name} combo", async () => {
564
563
  writeWranglerToml({
565
564
  routes: [
@@ -3669,7 +3668,6 @@ addEventListener('fetch', event => {});`
3669
3668
  );
3670
3669
  });
3671
3670
  });
3672
-
3673
3671
  describe("custom builds", () => {
3674
3672
  beforeEach(() => {
3675
3673
  // @ts-expect-error disable the mock we'd setup earlier
@@ -6540,6 +6538,56 @@ addEventListener('fetch', event => {});`
6540
6538
  `A request to the Cloudflare API (/accounts/some-account-id/workers/services/test-name) failed`
6541
6539
  );
6542
6540
  });
6541
+
6542
+ describe("--keep-vars", () => {
6543
+ it("should send keepVars when keep-vars is passed in", async () => {
6544
+ process.env = {
6545
+ CLOUDFLARE_API_TOKEN: "hunter2",
6546
+ CLOUDFLARE_ACCOUNT_ID: "some-account-id",
6547
+ };
6548
+ setIsTTY(false);
6549
+ writeWranglerToml();
6550
+ writeWorkerSource();
6551
+ mockSubDomainRequest();
6552
+ mockUploadWorkerRequest({ keepVars: true });
6553
+ mockOAuthServerCallback();
6554
+ mockGetMemberships([]);
6555
+
6556
+ await runWrangler("publish index.js --keep-vars");
6557
+
6558
+ expect(std.out).toMatchInlineSnapshot(`
6559
+ "Total Upload: xx KiB / gzip: xx KiB
6560
+ Uploaded test-name (TIMINGS)
6561
+ Published test-name (TIMINGS)
6562
+ https://test-name.test-sub-domain.workers.dev"
6563
+ `);
6564
+ expect(std.err).toMatchInlineSnapshot(`""`);
6565
+ });
6566
+
6567
+ it("should not send keepVars by default", async () => {
6568
+ process.env = {
6569
+ CLOUDFLARE_API_TOKEN: "hunter2",
6570
+ CLOUDFLARE_ACCOUNT_ID: "some-account-id",
6571
+ };
6572
+ setIsTTY(false);
6573
+ writeWranglerToml();
6574
+ writeWorkerSource();
6575
+ mockSubDomainRequest();
6576
+ mockUploadWorkerRequest();
6577
+ mockOAuthServerCallback();
6578
+ mockGetMemberships([]);
6579
+
6580
+ await runWrangler("publish index.js");
6581
+
6582
+ expect(std.out).toMatchInlineSnapshot(`
6583
+ "Total Upload: xx KiB / gzip: xx KiB
6584
+ Uploaded test-name (TIMINGS)
6585
+ Published test-name (TIMINGS)
6586
+ https://test-name.test-sub-domain.workers.dev"
6587
+ `);
6588
+ expect(std.err).toMatchInlineSnapshot(`""`);
6589
+ });
6590
+ });
6543
6591
  });
6544
6592
 
6545
6593
  /** Write mock assets to the file system so they can be uploaded. */
@@ -6571,6 +6619,7 @@ function mockUploadWorkerRequest(
6571
6619
  env?: string;
6572
6620
  legacyEnv?: boolean;
6573
6621
  sendScriptIds?: boolean;
6622
+ keepVars?: boolean;
6574
6623
  } = {}
6575
6624
  ) {
6576
6625
  const {
@@ -6586,6 +6635,7 @@ function mockUploadWorkerRequest(
6586
6635
  legacyEnv = false,
6587
6636
  expectedMigrations,
6588
6637
  sendScriptIds,
6638
+ keepVars,
6589
6639
  } = options;
6590
6640
  setMockResponse(
6591
6641
  env && !legacyEnv
@@ -6617,7 +6667,11 @@ function mockUploadWorkerRequest(
6617
6667
  expect(metadata.body_part).toEqual("index.js");
6618
6668
  }
6619
6669
 
6620
- expect(metadata.keep_bindings).toEqual(["plain_text", "json"]);
6670
+ if (keepVars) {
6671
+ expect(metadata.keep_bindings).toEqual(["plain_text", "json"]);
6672
+ } else {
6673
+ expect(metadata.keep_bindings).toBeFalsy();
6674
+ }
6621
6675
 
6622
6676
  if ("expectedBindings" in options) {
6623
6677
  expect(metadata.bindings).toEqual(expectedBindings);