wrangler 0.0.0-e178d6fb → 0.0.0-e1c2f5b9

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 (239) hide show
  1. package/README.md +16 -2
  2. package/bin/wrangler.js +31 -11
  3. package/miniflare-dist/index.mjs +1340 -330
  4. package/package.json +40 -13
  5. package/src/__tests__/access.test.ts +25 -0
  6. package/src/__tests__/api-dev.test.ts +238 -0
  7. package/src/__tests__/api-devregistry.test.js +64 -0
  8. package/src/__tests__/api.test.ts +80 -0
  9. package/src/__tests__/configuration.test.ts +683 -470
  10. package/src/__tests__/d1.test.ts +123 -0
  11. package/src/__tests__/delete.test.ts +263 -0
  12. package/src/__tests__/deployments.test.ts +105 -0
  13. package/src/__tests__/dev.test.tsx +453 -70
  14. package/src/__tests__/dialogs.test.tsx +40 -0
  15. package/src/__tests__/generate.test.ts +235 -0
  16. package/src/__tests__/get-host-from-url.test.ts +16 -0
  17. package/src/__tests__/helpers/mock-auth-domain.ts +20 -0
  18. package/src/__tests__/helpers/mock-cfetch.ts +92 -26
  19. package/src/__tests__/helpers/mock-console.ts +11 -2
  20. package/src/__tests__/helpers/mock-dialogs.ts +1 -1
  21. package/src/__tests__/helpers/mock-get-zone-from-host.ts +8 -0
  22. package/src/__tests__/helpers/mock-known-routes.ts +7 -0
  23. package/src/__tests__/helpers/mock-kv.ts +1 -1
  24. package/src/__tests__/helpers/mock-oauth-flow.ts +74 -53
  25. package/src/__tests__/helpers/mock-process.ts +8 -13
  26. package/src/__tests__/helpers/msw/handlers/access.ts +13 -0
  27. package/src/__tests__/helpers/msw/handlers/deployments.ts +59 -0
  28. package/src/__tests__/helpers/msw/handlers/namespaces.ts +104 -0
  29. package/src/__tests__/helpers/msw/handlers/oauth.ts +31 -0
  30. package/src/__tests__/helpers/msw/handlers/r2.ts +80 -0
  31. package/src/__tests__/helpers/msw/handlers/script.ts +75 -0
  32. package/src/__tests__/helpers/msw/handlers/user.ts +63 -0
  33. package/src/__tests__/helpers/msw/handlers/zones.ts +22 -0
  34. package/src/__tests__/helpers/msw/index.ts +21 -0
  35. package/src/__tests__/helpers/worker-scripts/child-wrangler.toml +1 -0
  36. package/src/__tests__/helpers/worker-scripts/hello-world-worker.js +5 -0
  37. package/src/__tests__/helpers/worker-scripts/hello-world-wrangler.toml +1 -0
  38. package/src/__tests__/helpers/worker-scripts/parent-worker.js +8 -0
  39. package/src/__tests__/helpers/worker-scripts/parent-wrangler.toml +5 -0
  40. package/src/__tests__/index.test.ts +103 -97
  41. package/src/__tests__/init.test.ts +1484 -382
  42. package/src/__tests__/jest.setup.ts +88 -5
  43. package/src/__tests__/kv.test.ts +655 -540
  44. package/src/__tests__/logout.test.ts +47 -0
  45. package/src/__tests__/metrics.test.ts +95 -45
  46. package/src/__tests__/middleware.scheduled.test.ts +145 -0
  47. package/src/__tests__/middleware.test.ts +750 -0
  48. package/src/__tests__/pages-deployment-tail.test.ts +884 -0
  49. package/src/__tests__/pages.test.ts +1301 -119
  50. package/src/__tests__/paths.test.ts +39 -0
  51. package/src/__tests__/publish.test.ts +2266 -1180
  52. package/src/__tests__/pubsub.test.ts +211 -88
  53. package/src/__tests__/queues.test.ts +522 -0
  54. package/src/__tests__/r2.test.ts +363 -203
  55. package/src/__tests__/secret.test.ts +261 -59
  56. package/src/__tests__/tail.test.ts +352 -151
  57. package/src/__tests__/test-old-node-version.js +3 -3
  58. package/src/__tests__/tsconfig-sanity.ts +12 -0
  59. package/src/__tests__/tsconfig.json +8 -0
  60. package/src/__tests__/tsconfig.tsbuildinfo +1 -0
  61. package/src/__tests__/type-generation.test.ts +233 -0
  62. package/src/__tests__/user.test.ts +59 -73
  63. package/src/__tests__/utils-collectKeyValues.test.ts +47 -0
  64. package/src/__tests__/validate-dev-props.test.ts +56 -0
  65. package/src/__tests__/whoami.test.tsx +114 -66
  66. package/src/__tests__/worker-namespace.test.ts +154 -155
  67. package/src/api/dev.ts +170 -38
  68. package/src/api/index.ts +1 -0
  69. package/src/bundle-reporter.tsx +41 -2
  70. package/src/bundle.ts +668 -81
  71. package/src/cfetch/index.ts +40 -3
  72. package/src/cfetch/internal.ts +144 -32
  73. package/src/cli.ts +4 -3
  74. package/src/config/config.ts +27 -3
  75. package/src/config/environment.ts +131 -7
  76. package/src/config/index.ts +128 -8
  77. package/src/config/validation-helpers.ts +19 -6
  78. package/src/config/validation.ts +411 -14
  79. package/src/config-cache.ts +3 -2
  80. package/src/create-worker-preview.ts +31 -6
  81. package/src/create-worker-upload-form.ts +84 -22
  82. package/src/d1/backups.tsx +223 -0
  83. package/src/d1/constants.ts +2 -0
  84. package/src/d1/create.tsx +63 -0
  85. package/src/d1/delete.tsx +56 -0
  86. package/src/d1/execute.tsx +352 -0
  87. package/src/d1/formatTimeAgo.ts +14 -0
  88. package/src/d1/index.ts +101 -0
  89. package/src/d1/list.tsx +48 -0
  90. package/src/d1/migrations/apply.tsx +196 -0
  91. package/src/d1/migrations/create.tsx +77 -0
  92. package/src/d1/migrations/helpers.ts +147 -0
  93. package/src/d1/migrations/index.tsx +3 -0
  94. package/src/d1/migrations/list.tsx +79 -0
  95. package/src/d1/migrations/options.ts +18 -0
  96. package/src/d1/options.ts +22 -0
  97. package/src/d1/types.tsx +24 -0
  98. package/src/d1/utils.ts +48 -0
  99. package/src/delete.ts +108 -0
  100. package/src/deployments.ts +83 -0
  101. package/src/deprecated/index.ts +145 -0
  102. package/src/dev/dev-vars.ts +11 -8
  103. package/src/dev/dev.tsx +220 -58
  104. package/src/dev/get-local-persistence-path.tsx +31 -0
  105. package/src/dev/local.tsx +740 -181
  106. package/src/dev/remote.tsx +340 -123
  107. package/src/dev/start-server.ts +543 -0
  108. package/src/dev/use-esbuild.ts +61 -7
  109. package/src/dev/validate-dev-props.ts +31 -0
  110. package/src/dev-registry.tsx +201 -0
  111. package/src/dev.tsx +614 -258
  112. package/src/dialogs.tsx +41 -8
  113. package/src/{worker-namespace.ts → dispatch-namespace.ts} +23 -22
  114. package/src/docs/index.ts +97 -0
  115. package/src/entry.ts +3 -2
  116. package/src/environment-variables/factory.ts +88 -0
  117. package/src/environment-variables/misc-variables.ts +30 -0
  118. package/src/generate/index.ts +300 -0
  119. package/src/git-client.ts +100 -7
  120. package/src/index.tsx +249 -1560
  121. package/src/init.ts +626 -150
  122. package/src/inspect.ts +137 -32
  123. package/src/{metrics/is-ci.ts → is-ci.ts} +0 -0
  124. package/src/is-interactive.ts +4 -0
  125. package/src/jest.d.ts +4 -0
  126. package/src/{kv.ts → kv/helpers.ts} +3 -3
  127. package/src/kv/index.ts +596 -0
  128. package/src/logger.ts +27 -8
  129. package/src/metrics/index.ts +1 -0
  130. package/src/metrics/metrics-config.ts +4 -4
  131. package/src/metrics/metrics-dispatcher.ts +1 -0
  132. package/src/metrics/metrics-usage-headers.ts +24 -0
  133. package/src/metrics/send-event.ts +13 -8
  134. package/src/miniflare-cli/assets.ts +172 -465
  135. package/src/miniflare-cli/index.ts +149 -24
  136. package/src/miniflare-cli/tsconfig.json +9 -0
  137. package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -0
  138. package/src/miniflare-cli/types.ts +11 -0
  139. package/src/module-collection.ts +12 -3
  140. package/src/pages/build.tsx +108 -42
  141. package/src/pages/constants.ts +11 -0
  142. package/src/pages/deployment-tails.tsx +284 -0
  143. package/src/pages/deployments.tsx +9 -31
  144. package/src/pages/dev.tsx +417 -108
  145. package/src/pages/errors.ts +66 -0
  146. package/src/pages/functions/buildPlugin.ts +86 -84
  147. package/src/pages/functions/buildWorker.ts +121 -106
  148. package/src/pages/functions/routes-consolidation.test.ts +250 -0
  149. package/src/pages/functions/routes-consolidation.ts +73 -0
  150. package/src/pages/functions/routes-transformation.test.ts +282 -0
  151. package/src/pages/functions/routes-transformation.ts +115 -0
  152. package/src/pages/functions/routes-validation.test.ts +403 -0
  153. package/src/pages/functions/routes-validation.ts +202 -0
  154. package/src/pages/functions/tsconfig.json +8 -0
  155. package/src/pages/functions/tsconfig.tsbuildinfo +1 -0
  156. package/src/pages/functions.tsx +82 -0
  157. package/src/pages/hash.tsx +13 -0
  158. package/src/pages/index.tsx +73 -55
  159. package/src/pages/projects.tsx +9 -3
  160. package/src/pages/prompt-select-project.tsx +31 -0
  161. package/src/pages/publish.tsx +183 -60
  162. package/src/pages/types.ts +1 -0
  163. package/src/pages/upload.tsx +107 -56
  164. package/src/pages/utils.ts +13 -2
  165. package/src/paths.ts +49 -4
  166. package/src/proxy.ts +375 -157
  167. package/src/publish/index.ts +270 -0
  168. package/src/{publish.ts → publish/publish.ts} +431 -188
  169. package/src/pubsub/pubsub-commands.tsx +4 -3
  170. package/src/queues/cli/commands/consumer/add.ts +71 -0
  171. package/src/queues/cli/commands/consumer/index.ts +22 -0
  172. package/src/queues/cli/commands/consumer/remove.ts +38 -0
  173. package/src/queues/cli/commands/create.ts +25 -0
  174. package/src/queues/cli/commands/delete.ts +26 -0
  175. package/src/queues/cli/commands/index.ts +36 -0
  176. package/src/queues/cli/commands/list.ts +25 -0
  177. package/src/queues/client.ts +135 -0
  178. package/src/queues/utils.ts +18 -0
  179. package/src/r2/constants.ts +4 -0
  180. package/src/r2/helpers.ts +131 -0
  181. package/src/r2/index.ts +289 -0
  182. package/src/routes.ts +140 -0
  183. package/src/secret/index.ts +379 -0
  184. package/src/sites.tsx +3 -3
  185. package/src/tail/createTail.ts +379 -0
  186. package/src/tail/filters.ts +4 -6
  187. package/src/tail/index.ts +199 -284
  188. package/src/tail/printing.ts +43 -3
  189. package/src/tsconfig-sanity.ts +16 -0
  190. package/src/type-generation.ts +181 -0
  191. package/src/user/access.ts +68 -0
  192. package/src/user/auth-variables.ts +113 -0
  193. package/src/user/choose-account.tsx +1 -1
  194. package/src/user/index.ts +0 -1
  195. package/src/user/user.tsx +116 -49
  196. package/src/utils/collectKeyValues.ts +14 -0
  197. package/src/whoami.tsx +80 -2
  198. package/src/worker.ts +69 -9
  199. package/src/yargs-types.ts +24 -0
  200. package/src/zones.ts +124 -9
  201. package/templates/__tests__/pages-dev-util.test.ts +128 -0
  202. package/templates/__tests__/tsconfig-sanity.ts +12 -0
  203. package/templates/__tests__/tsconfig.json +8 -0
  204. package/templates/__tests__/tsconfig.tsbuildinfo +1 -0
  205. package/templates/d1-beta-facade.js +205 -0
  206. package/templates/facade.d.ts +14 -0
  207. package/templates/first-party-worker-module-facade.ts +19 -0
  208. package/templates/format-dev-errors.ts +33 -0
  209. package/templates/init-tests/test-jest-new-worker.js +23 -0
  210. package/templates/init-tests/test-vitest-new-worker.js +24 -0
  211. package/templates/init-tests/test-vitest-new-worker.ts +25 -0
  212. package/templates/middleware/common.ts +62 -0
  213. package/templates/middleware/loader-modules.ts +82 -0
  214. package/templates/middleware/loader-sw.ts +233 -0
  215. package/templates/middleware/middleware-miniflare3-json-error.ts +20 -0
  216. package/templates/middleware/middleware-pretty-error.ts +40 -0
  217. package/templates/middleware/middleware-scheduled.ts +15 -0
  218. package/templates/new-worker.js +1 -1
  219. package/templates/pages-dev-pipeline.ts +31 -0
  220. package/templates/pages-dev-util.ts +52 -0
  221. package/templates/pages-shim.ts +4 -1
  222. package/templates/pages-template-plugin.ts +21 -5
  223. package/templates/pages-template-worker.ts +37 -9
  224. package/templates/{static-asset-facade.js → serve-static-assets.ts} +23 -7
  225. package/templates/service-bindings-module-facade.js +54 -0
  226. package/templates/service-bindings-sw-facade.js +42 -0
  227. package/templates/tsconfig-sanity.ts +11 -0
  228. package/templates/tsconfig.init.json +106 -0
  229. package/templates/tsconfig.json +5 -102
  230. package/templates/tsconfig.tsbuildinfo +1 -0
  231. package/wrangler-dist/cli.d.ts +621 -42
  232. package/wrangler-dist/cli.js +144441 -102606
  233. package/src/environment-variables.ts +0 -35
  234. package/src/faye-websocket.d.ts +0 -6
  235. package/src/generate.ts +0 -33
  236. package/src/miniflare-cli/enum-keys.ts +0 -17
  237. package/src/preview.ts +0 -31
  238. package/src/r2.ts +0 -50
  239. package/src/user/env-vars.ts +0 -46
@@ -0,0 +1,40 @@
1
+ jest.unmock("../dialogs");
2
+ import { fromDashMessagePrompt } from "../dialogs";
3
+ import { CI } from "../is-ci";
4
+
5
+ describe("fromDashMessagePrompt", () => {
6
+ it("should return undefined in CI when last deployed from api", async () => {
7
+ //in CI
8
+ jest.spyOn(CI, "isCI").mockReturnValue(true);
9
+ const result = await fromDashMessagePrompt("api");
10
+ expect(result).toBe(undefined);
11
+ });
12
+
13
+ it("should return undefined in CI when last deployed from wrangler", async () => {
14
+ //in CI
15
+ jest.spyOn(CI, "isCI").mockReturnValue(true);
16
+ const result = await fromDashMessagePrompt("wrangler");
17
+ expect(result).toBe(undefined);
18
+ });
19
+
20
+ it("should return true in CI when last deployed from dash", async () => {
21
+ //in CI
22
+ jest.spyOn(CI, "isCI").mockReturnValue(true);
23
+ const result = await fromDashMessagePrompt("dash");
24
+ expect(result).toBe(true);
25
+ });
26
+
27
+ it("should return undefined when last deployed from api", async () => {
28
+ //not in CI
29
+ jest.spyOn(CI, "isCI").mockReturnValue(false);
30
+ const result = await fromDashMessagePrompt("api");
31
+ expect(result).toBe(undefined);
32
+ });
33
+
34
+ it("should return undefined when last deployed from wrangler", async () => {
35
+ //not in CI
36
+ jest.spyOn(CI, "isCI").mockReturnValue(false);
37
+ const result = await fromDashMessagePrompt("wrangler");
38
+ expect(result).toBe(undefined);
39
+ });
40
+ });
@@ -0,0 +1,235 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { mockConsoleMethods } from "./helpers/mock-console";
4
+ import { mockConfirm, clearConfirmMocks } from "./helpers/mock-dialogs";
5
+ import { runInTempDir } from "./helpers/run-in-tmp";
6
+ import { runWrangler } from "./helpers/run-wrangler";
7
+
8
+ describe("generate", () => {
9
+ runInTempDir();
10
+ const std = mockConsoleMethods();
11
+
12
+ describe("cli functionality", () => {
13
+ afterEach(() => {
14
+ clearConfirmMocks();
15
+ });
16
+
17
+ it("defers to `wrangler init` when no template is given", async () => {
18
+ mockConfirm(
19
+ {
20
+ text: "Would you like to use git to manage this Worker?",
21
+ result: false,
22
+ },
23
+ {
24
+ text: "No package.json found. Would you like to create one?",
25
+ result: false,
26
+ }
27
+ );
28
+ await runWrangler("generate no-template");
29
+ expect(std.out).toMatchInlineSnapshot(
30
+ `"✨ Created no-template/wrangler.toml"`
31
+ );
32
+ });
33
+
34
+ it("complains when given the --type argument", async () => {
35
+ await expect(
36
+ runWrangler("generate worker-name worker-template --type rust")
37
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
38
+ `"The --type option is no longer supported."`
39
+ );
40
+ });
41
+
42
+ it("complains when given the --site argument", async () => {
43
+ await expect(runWrangler("generate worker-name worker-template --site"))
44
+ .rejects.toThrowErrorMatchingInlineSnapshot(`
45
+ "The --site option is no longer supported.
46
+ If you wish to create a brand new Worker Sites project then clone the \`worker-sites-template\` starter repository:
47
+
48
+ \`\`\`
49
+ git clone --depth=1 --branch=wrangler2 https://github.com/cloudflare/worker-sites-template worker-name
50
+ cd worker-name
51
+ \`\`\`
52
+
53
+ Find out more about how to create and maintain Sites projects at https://developers.cloudflare.com/workers/platform/sites.
54
+ Have you considered using Cloudflare Pages instead? See https://pages.cloudflare.com/."
55
+ `);
56
+ });
57
+
58
+ it.skip("auto-increments the worker directory name", async () => {
59
+ fs.mkdirSync("my-worker");
60
+
61
+ expect(fs.existsSync("my-worker-1")).toBe(false);
62
+
63
+ await expect(
64
+ runWrangler("generate my-worker worker-typescript")
65
+ ).resolves.toBeUndefined();
66
+
67
+ expect(std.out).toStrictEqual(expect.stringContaining("my-worker-1"));
68
+
69
+ expect(readDirectory("my-worker-1")).toMatchObject<Directory>({
70
+ ".git": expect.any(Object),
71
+ ".gitignore": expect.any(String),
72
+ "README.md": expect.stringContaining("Template: worker-typescript"),
73
+ "jest.config.json": expect.any(String),
74
+ "package.json": expect.stringContaining("@cloudflare/workers-types"),
75
+ src: expect.objectContaining({ "index.ts": expect.any(String) }),
76
+ test: expect.objectContaining({
77
+ "index.test.ts": expect.any(String),
78
+ }),
79
+ "tsconfig.json": expect.any(String),
80
+ "wrangler.toml": expect.any(String),
81
+ });
82
+ expect(fs.existsSync("my-worker-2")).toBe(false);
83
+
84
+ await expect(
85
+ runWrangler("generate my-worker worker-typescript")
86
+ ).resolves.toBeUndefined();
87
+
88
+ expect(std.out).toStrictEqual(expect.stringContaining("my-worker-2"));
89
+
90
+ expect(readDirectory("my-worker-2")).toMatchObject<Directory>({
91
+ ".git": expect.any(Object),
92
+ ".gitignore": expect.any(String),
93
+ "README.md": expect.stringContaining("Template: worker-typescript"),
94
+ "jest.config.json": expect.any(String),
95
+ "package.json": expect.stringContaining("@cloudflare/workers-types"),
96
+ src: expect.objectContaining({ "index.ts": expect.any(String) }),
97
+ test: expect.objectContaining({
98
+ "index.test.ts": expect.any(String),
99
+ }),
100
+ "tsconfig.json": expect.any(String),
101
+ "wrangler.toml": expect.any(String),
102
+ });
103
+ });
104
+ });
105
+
106
+ describe("cloning", () => {
107
+ it.skip("clones a cloudflare template with sparse checkouts", async () => {
108
+ await expect(
109
+ runWrangler("generate my-worker worker-typescript")
110
+ ).resolves.toBeUndefined();
111
+
112
+ expect(readDirectory("my-worker")).toMatchObject<Directory>({
113
+ ".git": expect.any(Object),
114
+ ".gitignore": expect.any(String),
115
+ "README.md": expect.stringContaining("Template: worker-typescript"),
116
+ "jest.config.json": expect.any(String),
117
+ "package.json": expect.stringContaining("@cloudflare/workers-types"),
118
+ src: expect.objectContaining({ "index.ts": expect.any(String) }),
119
+ test: expect.objectContaining({
120
+ "index.test.ts": expect.any(String),
121
+ }),
122
+ "tsconfig.json": expect.any(String),
123
+ "wrangler.toml": expect.any(String),
124
+ });
125
+ });
126
+
127
+ // mocking out calls to either `isGitInstalled` or `execa("git", ["--version"])`
128
+ // was harder than i thought, leaving this for now.
129
+ it.todo("clones a cloudflare template with full checkouts");
130
+
131
+ it("clones a user/repo template", async () => {
132
+ await expect(
133
+ runWrangler("generate my-worker caass/wrangler-generate-test-template")
134
+ ).resolves.toBeUndefined();
135
+
136
+ expect(readDirectory("my-worker")).toMatchObject<Directory>({
137
+ ".git": expect.any(Object),
138
+ ".gitignore": expect.any(String),
139
+ "package.json": expect.stringContaining("@cloudflare/workers-types"),
140
+ src: expect.objectContaining({ "index.ts": expect.any(String) }),
141
+ "tsconfig.json": expect.any(String),
142
+ "wrangler.toml": expect.any(String),
143
+ });
144
+ });
145
+
146
+ it.skip("clones a user/repo/path/to/subdirectory template", async () => {
147
+ await expect(
148
+ runWrangler("generate my-worker cloudflare/templates/worker-typescript")
149
+ ).resolves.toBeUndefined();
150
+
151
+ expect(readDirectory("my-worker")).toMatchObject<Directory>({
152
+ ".git": expect.any(Object),
153
+ ".gitignore": expect.any(String),
154
+ "README.md": expect.stringContaining("Template: worker-typescript"),
155
+ "jest.config.json": expect.any(String),
156
+ "package.json": expect.stringContaining("@cloudflare/workers-types"),
157
+ src: expect.objectContaining({ "index.ts": expect.any(String) }),
158
+ test: expect.objectContaining({
159
+ "index.test.ts": expect.any(String),
160
+ }),
161
+ "tsconfig.json": expect.any(String),
162
+ "wrangler.toml": expect.any(String),
163
+ });
164
+ });
165
+
166
+ it.skip("clones a git@github.com/user/repo template", async () => {
167
+ await expect(
168
+ runWrangler(
169
+ "generate my-worker git@github.com:caass/wrangler-generate-test-template"
170
+ )
171
+ ).resolves.toBeUndefined();
172
+
173
+ expect(readDirectory("my-worker")).toMatchObject<Directory>({
174
+ ".git": expect.any(Object),
175
+ ".gitignore": expect.any(String),
176
+ "package.json": expect.stringContaining("@cloudflare/workers-types"),
177
+ src: expect.objectContaining({ "index.ts": expect.any(String) }),
178
+ "tsconfig.json": expect.any(String),
179
+ "wrangler.toml": expect.any(String),
180
+ });
181
+ });
182
+
183
+ it.skip("clones a git@github.com/user/repo/path/to/subdirectory template", async () => {
184
+ await expect(
185
+ runWrangler(
186
+ "generate my-worker git@github.com:cloudflare/templates/worker-typescript"
187
+ )
188
+ ).resolves.toBeUndefined();
189
+
190
+ expect(readDirectory("my-worker")).toMatchObject<Directory>({
191
+ ".git": expect.any(Object),
192
+ ".gitignore": expect.any(String),
193
+ "README.md": expect.stringContaining("Template: worker-typescript"),
194
+ "jest.config.json": expect.any(String),
195
+ "package.json": expect.stringContaining("@cloudflare/workers-types"),
196
+ src: expect.objectContaining({ "index.ts": expect.any(String) }),
197
+ test: expect.objectContaining({
198
+ "index.test.ts": expect.any(String),
199
+ }),
200
+ "tsconfig.json": expect.any(String),
201
+ "wrangler.toml": expect.any(String),
202
+ });
203
+ });
204
+ });
205
+ });
206
+
207
+ type FileName = string;
208
+ type FileContents = string;
209
+ type Directory = { [key: FileName]: FileContents | Directory };
210
+
211
+ function readDirectory(directoryPath: string): Directory {
212
+ if (!fs.existsSync(directoryPath)) {
213
+ throw new Error(`${directoryPath} does not exist!`);
214
+ }
215
+
216
+ if (!fs.lstatSync(directoryPath).isDirectory()) {
217
+ throw new Error(`${directoryPath} is not a directory!`);
218
+ }
219
+
220
+ return fs
221
+ .readdirSync(directoryPath, { withFileTypes: true })
222
+ .reduce((output, child) => {
223
+ const childPath = path.join(directoryPath, child.name);
224
+
225
+ if (child.isDirectory()) {
226
+ output[child.name] = readDirectory(childPath);
227
+ } else if (child.isFile()) {
228
+ output[child.name] = fs.readFileSync(childPath, { encoding: "utf-8" });
229
+ } else {
230
+ throw new Error(`${childPath} was not a file or directory!`);
231
+ }
232
+
233
+ return output;
234
+ }, {} as Directory);
235
+ }
@@ -0,0 +1,16 @@
1
+ import { getHostFromUrl } from "../zones";
2
+
3
+ //return the host given a url-like string
4
+ describe("getHostFromUrl", () => {
5
+ it("should return the host from a url", () => {
6
+ expect(getHostFromUrl("https://www.example.com")).toBe("www.example.com");
7
+ });
8
+
9
+ it("should return the host from a url using wildcard *.", () => {
10
+ expect(getHostFromUrl("*.example.com")).toBe("example.com");
11
+ });
12
+
13
+ it("should return the host from a url using wildcard *", () => {
14
+ expect(getHostFromUrl("*example.com")).toBe("example.com");
15
+ });
16
+ });
@@ -0,0 +1,20 @@
1
+ const ORIGINAL_WRANGLER_AUTH_DOMAIN = process.env.WRANGLER_AUTH_DOMAIN;
2
+
3
+ /**
4
+ * Mock the Auth URL domain so that we can control where we attempt to login.
5
+ *
6
+ * Note that you can remove any API token from the environment by setting the value to `null`.
7
+ * This is useful if a higher `describe()` block has already called `mockAuthDomain()`.
8
+ */
9
+ export function mockAuthDomain({ domain }: { domain: string | null }) {
10
+ beforeEach(() => {
11
+ if (domain === null) {
12
+ delete process.env.WRANGLER_AUTH_DOMAIN;
13
+ } else {
14
+ process.env.WRANGLER_AUTH_DOMAIN = domain;
15
+ }
16
+ });
17
+ afterEach(() => {
18
+ process.env.WRANGLER_AUTH_DOMAIN = ORIGINAL_WRANGLER_AUTH_DOMAIN;
19
+ });
20
+ }
@@ -1,8 +1,36 @@
1
+ import { Readable } from "node:stream";
1
2
  import { URL, URLSearchParams } from "node:url";
2
3
  import { pathToRegexp } from "path-to-regexp";
3
- import { getCloudflareApiBaseUrl } from "../../cfetch";
4
+ import { Response } from "undici";
5
+ import { getCloudflareApiBaseUrl } from "../../environment-variables/misc-variables";
4
6
  import type { FetchResult, FetchError } from "../../cfetch";
5
- import type { RequestInit } from "undici";
7
+ import type {
8
+ fetchInternal,
9
+ fetchR2Objects,
10
+ performApiFetch,
11
+ } from "../../cfetch/internal";
12
+ import type { RequestInit, BodyInit, HeadersInit } from "undici";
13
+
14
+ /**
15
+ * When the custom mocks fallthrough in tests because they aren't set, instead of throwing an error,
16
+ * we use real fetch to make the request which will use Mock Service Workers.
17
+ */
18
+ const {
19
+ fetchInternal: realFetchInternal,
20
+ }: { fetchInternal: typeof fetchInternal } = jest.requireActual(
21
+ "../../cfetch/internal"
22
+ );
23
+ const {
24
+ fetchR2Objects: realFetchR2Objects,
25
+ }: { fetchR2Objects: typeof fetchR2Objects } = jest.requireActual(
26
+ "../../cfetch/internal"
27
+ );
28
+
29
+ const {
30
+ performApiFetch: realPerformApiFetch,
31
+ }: { performApiFetch: typeof performApiFetch } = jest.requireActual(
32
+ "../../cfetch/internal"
33
+ );
6
34
 
7
35
  /**
8
36
  * The signature of the function that will handle a mock request.
@@ -32,7 +60,7 @@ const mocks: MockFetch<unknown>[] = [];
32
60
  export async function mockFetchInternal(
33
61
  resource: string,
34
62
  init: RequestInit = {},
35
- queryParams: URLSearchParams = new URLSearchParams()
63
+ queryParams: URLSearchParams | undefined
36
64
  ) {
37
65
  for (const { regexp, method, handler } of mocks) {
38
66
  const resourcePath = new URL(resource, getCloudflareApiBaseUrl()).pathname;
@@ -41,14 +69,22 @@ export async function mockFetchInternal(
41
69
  if (uri !== null && (!method || method === (init.method ?? "GET"))) {
42
70
  // The `resource` regular expression will extract the labelled groups from the URL.
43
71
  // These are passed through to the `handler` call, to allow it to do additional checks or behaviour.
44
- return await handler(uri, init, queryParams); // TODO: should we have some kind of fallthrough system? we'll see.
72
+ return await handler(uri, init, queryParams ?? new URLSearchParams()); // TODO: should we have some kind of fallthrough system? we'll see.
45
73
  }
46
74
  }
47
- throw new Error(
48
- `no mocks found for ${init.method ?? "any HTTP"} request to ${resource}`
49
- );
75
+
76
+ // let it fall through to mock-service-worker
77
+ // (do a real, unmocked fetch)
78
+ return await realFetchInternal(resource, init, queryParams);
50
79
  }
51
80
 
81
+ /**
82
+ * We don't have loads of infrastructure around performApiFetch
83
+ * the same way we do for cfetch, so we'll just pass off the real
84
+ * deal to avoid getting it auto-mocked, so that msw can catch it.
85
+ */
86
+ export const mockPerformApiFetch = realPerformApiFetch;
87
+
52
88
  /**
53
89
  * Specify an expected resource path that is to be handled, resulting in a raw JSON response.
54
90
  *
@@ -180,32 +216,62 @@ export function unsetAllMocks() {
180
216
  */
181
217
 
182
218
  const kvGetMocks = new Map<string, string | Buffer>();
219
+ const r2GetMocks = new Map<string, string | undefined>();
220
+ const dashScriptMocks = new Map<string, string | undefined>();
183
221
 
184
222
  /**
185
- * @mocked typeof fetchKVGetValue
223
+ * @mocked typeof fetchR2Objects
186
224
  */
187
- export function mockFetchKVGetValue(
188
- accountId: string,
189
- namespaceId: string,
190
- key: string
191
- ) {
192
- const mapKey = `${accountId}/${namespaceId}/${key}`;
193
- if (kvGetMocks.has(mapKey)) {
194
- const value = kvGetMocks.get(mapKey);
195
- if (value !== undefined) return Promise.resolve(value);
225
+ export async function mockFetchR2Objects(
226
+ resource: string,
227
+ bodyInit: {
228
+ body: BodyInit | Readable;
229
+ headers: HeadersInit | undefined;
230
+ method: "PUT" | "GET" | "DELETE";
231
+ }
232
+ ): Promise<Response> {
233
+ if (r2GetMocks.has(resource)) {
234
+ /**
235
+ * Here we destroy & removeListeners to "drain" the stream, for testing purposes
236
+ * mimicking the fetch request taking in the stream and draining it.
237
+ */
238
+ if (bodyInit.body instanceof Readable) {
239
+ bodyInit.body.destroy();
240
+ bodyInit.body.removeAllListeners();
241
+ }
242
+
243
+ const value = r2GetMocks.get(resource);
244
+
245
+ return new Response(value);
196
246
  }
197
- throw new Error(`no mock value found for \`kv:key get\` - ${mapKey}`);
247
+
248
+ // No mocks found for ${init.method ?? "any HTTP"} request to ${resource}
249
+ // let it fall through to Mock Service Worker with a real fetch.
250
+ return await realFetchR2Objects(resource, bodyInit);
198
251
  }
199
252
 
200
- export function setMockFetchKVGetValue(
201
- accountId: string,
202
- namespaceId: string,
203
- key: string,
204
- value: string | Buffer
205
- ) {
206
- kvGetMocks.set(`${accountId}/${namespaceId}/${key}`, value);
253
+ /**
254
+ * Mock setter for usage within test blocks, companion helper to `mockFetchR2Objects`
255
+ */
256
+ export function setMockFetchR2Objects({
257
+ accountId,
258
+ bucketName,
259
+ objectName,
260
+ mockResponse,
261
+ }: {
262
+ accountId: string;
263
+ bucketName: string;
264
+ objectName: string;
265
+ mockResponse?: string;
266
+ }) {
267
+ r2GetMocks.set(
268
+ `/accounts/${accountId}/r2/buckets/${bucketName}/objects/${objectName}`,
269
+ mockResponse
270
+ );
207
271
  }
208
272
 
209
- export function unsetMockFetchKVGetValues() {
273
+ export function unsetSpecialMockFns() {
210
274
  kvGetMocks.clear();
275
+ r2GetMocks.clear();
276
+ dashScriptMocks.clear();
211
277
  }
@@ -29,7 +29,9 @@ const std = {
29
29
  function normalizeOutput(spy: jest.SpyInstance): string {
30
30
  return normalizeErrorMarkers(
31
31
  replaceByte(
32
- stripTrailingWhitespace(normalizeSlashes(stripTimings(captureCalls(spy))))
32
+ stripTrailingWhitespace(
33
+ normalizeSlashes(normalizeTempDirs(stripTimings(captureCalls(spy))))
34
+ )
33
35
  )
34
36
  );
35
37
  }
@@ -93,5 +95,12 @@ export function stripTrailingWhitespace(str: string): string {
93
95
  * variation causing every few tests the value to change by ± .01
94
96
  */
95
97
  function replaceByte(stdout: string): string {
96
- return stdout.replaceAll(/.[0-9][0-9] KiB/g, "xx KiB");
98
+ return stdout.replaceAll(/\d+\.\d+ KiB/g, "xx KiB");
99
+ }
100
+
101
+ /**
102
+ * Temp directories are created with random names, so we replace all comments temp dirs in them
103
+ */
104
+ export function normalizeTempDirs(stdout: string): string {
105
+ return stdout.replaceAll(/\/\/.+\/tmp.+/g, "//tmpdir");
97
106
  }
@@ -78,7 +78,7 @@ export function mockPrompt(...expectations: PromptExpectation[]) {
78
78
  return Promise.resolve(expectation.result);
79
79
  }
80
80
  }
81
- throw new Error(`Unexpected confirmation message: ${text}`);
81
+ throw new Error(`Unexpected prompt message: ${text}`);
82
82
  }
83
83
  );
84
84
  return () => {
@@ -0,0 +1,8 @@
1
+ import { setMockResponse } from "./mock-cfetch";
2
+
3
+ export function mockGetZoneFromHostRequest(host: string, zone?: string) {
4
+ setMockResponse("/zones", (_uri, _init, queryParams) => {
5
+ expect(queryParams.get("name")).toEqual(host);
6
+ return zone ? [{ id: zone }] : [];
7
+ });
8
+ }
@@ -0,0 +1,7 @@
1
+ import { setMockResponse } from "./mock-cfetch";
2
+
3
+ export function mockCollectKnownRoutesRequest(
4
+ routes: { pattern: string; script: string }[]
5
+ ) {
6
+ setMockResponse(`/zones/:zoneId/workers/routes`, "GET", () => routes);
7
+ }
@@ -1,5 +1,5 @@
1
1
  import { createFetchResult, setMockRawResponse } from "./mock-cfetch";
2
- import type { NamespaceKeyInfo } from "../../kv";
2
+ import type { NamespaceKeyInfo } from "../../kv/helpers";
3
3
 
4
4
  export function mockKeyListRequest(
5
5
  expectedNamespaceId: string,