wrangler 0.0.0-e322475 → 0.0.0-e33294b0

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 (324) hide show
  1. package/README.md +24 -4
  2. package/bin/wrangler.js +170 -62
  3. package/miniflare-dist/index.mjs +1499 -34
  4. package/package.json +193 -156
  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__/config-cache-without-cache-dir.test.ts +38 -0
  10. package/src/__tests__/config-cache.test.ts +30 -24
  11. package/src/__tests__/configuration.test.ts +4222 -3537
  12. package/src/__tests__/d1/d1.test.ts +82 -0
  13. package/src/__tests__/d1/execute.test.ts +64 -0
  14. package/src/__tests__/d1/migrate.test.ts +155 -0
  15. package/src/__tests__/d1/splitter.test.ts +255 -0
  16. package/src/__tests__/delete.test.ts +266 -0
  17. package/src/__tests__/deployments.test.ts +129 -0
  18. package/src/__tests__/dev.test.tsx +1560 -1028
  19. package/src/__tests__/generate.test.ts +238 -0
  20. package/src/__tests__/get-host-from-url.test.ts +16 -0
  21. package/src/__tests__/guess-worker-format.test.ts +68 -68
  22. package/src/__tests__/helpers/cmd-shim.d.ts +6 -6
  23. package/src/__tests__/helpers/end-event-loop.ts +6 -0
  24. package/src/__tests__/helpers/mock-account-id.ts +24 -24
  25. package/src/__tests__/helpers/mock-auth-domain.ts +20 -0
  26. package/src/__tests__/helpers/mock-bin.ts +20 -20
  27. package/src/__tests__/helpers/mock-console.ts +51 -42
  28. package/src/__tests__/helpers/mock-dialogs.ts +88 -102
  29. package/src/__tests__/helpers/mock-get-pages-upload-token.ts +25 -0
  30. package/src/__tests__/helpers/mock-get-zone-from-host.ts +11 -0
  31. package/src/__tests__/helpers/mock-http-server.ts +30 -30
  32. package/src/__tests__/helpers/mock-istty.ts +65 -18
  33. package/src/__tests__/helpers/mock-known-routes.ts +12 -0
  34. package/src/__tests__/helpers/mock-kv.ts +41 -28
  35. package/src/__tests__/helpers/mock-oauth-flow.ts +241 -233
  36. package/src/__tests__/helpers/mock-process.ts +23 -13
  37. package/src/__tests__/helpers/mock-set-timeout.ts +16 -0
  38. package/src/__tests__/helpers/mock-stdin.ts +82 -77
  39. package/src/__tests__/helpers/mock-web-socket.ts +21 -21
  40. package/src/__tests__/helpers/msw/blob-worker.cjs +19 -0
  41. package/src/__tests__/helpers/msw/handlers/access.ts +13 -0
  42. package/src/__tests__/helpers/msw/handlers/deployments.ts +93 -0
  43. package/src/__tests__/helpers/msw/handlers/namespaces.ts +81 -0
  44. package/src/__tests__/helpers/msw/handlers/oauth.ts +31 -0
  45. package/src/__tests__/helpers/msw/handlers/r2.ts +60 -0
  46. package/src/__tests__/helpers/msw/handlers/script.ts +56 -0
  47. package/src/__tests__/helpers/msw/handlers/user.ts +52 -0
  48. package/src/__tests__/helpers/msw/handlers/zones.ts +20 -0
  49. package/src/__tests__/helpers/msw/index.ts +50 -0
  50. package/src/__tests__/helpers/msw/read-file-sync.js +61 -0
  51. package/src/__tests__/helpers/run-in-tmp.ts +27 -28
  52. package/src/__tests__/helpers/run-wrangler.ts +8 -8
  53. package/src/__tests__/helpers/string-dynamic-values-matcher.ts +28 -0
  54. package/src/__tests__/helpers/worker-scripts/child-wrangler.toml +1 -0
  55. package/src/__tests__/helpers/worker-scripts/hello-world-worker.js +5 -0
  56. package/src/__tests__/helpers/worker-scripts/hello-world-wrangler.toml +1 -0
  57. package/src/__tests__/helpers/worker-scripts/parent-worker.js +8 -0
  58. package/src/__tests__/helpers/worker-scripts/parent-wrangler.toml +5 -0
  59. package/src/__tests__/helpers/write-worker-source.ts +16 -16
  60. package/src/__tests__/helpers/write-wrangler-toml.ts +9 -9
  61. package/src/__tests__/https-options.test.ts +142 -109
  62. package/src/__tests__/index.test.ts +254 -238
  63. package/src/__tests__/init.test.ts +3097 -1925
  64. package/src/__tests__/jest.setup.ts +143 -75
  65. package/src/__tests__/kv.test.ts +1788 -1509
  66. package/src/__tests__/logger.test.ts +96 -96
  67. package/src/__tests__/logout.test.ts +47 -0
  68. package/src/__tests__/metrics.test.ts +493 -0
  69. package/src/__tests__/middleware.scheduled.test.ts +145 -0
  70. package/src/__tests__/middleware.test.ts +815 -0
  71. package/src/__tests__/mtls-certificates.test.ts +585 -0
  72. package/src/__tests__/package-manager.test.ts +303 -303
  73. package/src/__tests__/pages/deployment-list.test.ts +78 -0
  74. package/src/__tests__/pages/functions-build.test.ts +402 -0
  75. package/src/__tests__/pages/pages.test.ts +81 -0
  76. package/src/__tests__/pages/project-create.test.ts +63 -0
  77. package/src/__tests__/pages/project-list.test.ts +108 -0
  78. package/src/__tests__/pages/project-upload.test.ts +481 -0
  79. package/src/__tests__/pages/publish.test.ts +2745 -0
  80. package/src/__tests__/pages-deployment-tail.test.ts +955 -0
  81. package/src/__tests__/parse.test.ts +358 -252
  82. package/src/__tests__/paths.test.ts +39 -0
  83. package/src/__tests__/publish.test.ts +8002 -6010
  84. package/src/__tests__/pubsub.test.ts +493 -0
  85. package/src/__tests__/queues.test.ts +529 -0
  86. package/src/__tests__/r2.test.ts +369 -228
  87. package/src/__tests__/route.test.ts +18 -18
  88. package/src/__tests__/secret.test.ts +681 -469
  89. package/src/__tests__/tail.test.ts +835 -567
  90. package/src/__tests__/test-old-node-version.js +31 -0
  91. package/src/__tests__/tsconfig-sanity.ts +12 -0
  92. package/src/__tests__/tsconfig.json +8 -0
  93. package/src/__tests__/tsconfig.tsbuildinfo +1 -0
  94. package/src/__tests__/type-generation.test.ts +233 -0
  95. package/src/__tests__/user.test.ts +107 -121
  96. package/src/__tests__/utils-collectKeyValues.test.ts +47 -0
  97. package/src/__tests__/validate-dev-props.test.ts +56 -0
  98. package/src/__tests__/version.test.ts +35 -0
  99. package/src/__tests__/whoami.test.tsx +165 -132
  100. package/src/__tests__/worker-namespace.test.ts +339 -0
  101. package/src/abort.d.ts +1 -1
  102. package/src/api/dev.ts +328 -0
  103. package/src/api/index.ts +11 -0
  104. package/src/api/mtls-certificate.ts +148 -0
  105. package/src/api/pages/create-worker-bundle-contents.ts +75 -0
  106. package/src/api/pages/index.ts +5 -0
  107. package/src/api/pages/publish.tsx +368 -0
  108. package/src/bundle-reporter.ts +68 -0
  109. package/src/bundle.ts +839 -167
  110. package/src/cfetch/index.ts +120 -83
  111. package/src/cfetch/internal.ts +208 -92
  112. package/src/cli.ts +23 -8
  113. package/src/config/config.ts +244 -205
  114. package/src/config/diagnostics.ts +61 -61
  115. package/src/config/environment.ts +523 -357
  116. package/src/config/index.ts +346 -196
  117. package/src/config/validation-helpers.ts +379 -366
  118. package/src/config/validation.ts +2020 -1402
  119. package/src/config-cache.ts +81 -41
  120. package/src/create-worker-preview.ts +239 -142
  121. package/src/create-worker-upload-form.ts +318 -238
  122. package/src/d1/backups.tsx +215 -0
  123. package/src/d1/constants.ts +2 -0
  124. package/src/d1/create.tsx +64 -0
  125. package/src/d1/delete.ts +53 -0
  126. package/src/d1/execute.tsx +354 -0
  127. package/src/d1/formatTimeAgo.ts +14 -0
  128. package/src/d1/index.ts +100 -0
  129. package/src/d1/list.tsx +60 -0
  130. package/src/d1/migrations/apply.tsx +206 -0
  131. package/src/d1/migrations/create.tsx +76 -0
  132. package/src/d1/migrations/helpers.ts +172 -0
  133. package/src/d1/migrations/index.ts +3 -0
  134. package/src/d1/migrations/list.tsx +92 -0
  135. package/src/d1/migrations/options.ts +23 -0
  136. package/src/d1/options.ts +22 -0
  137. package/src/d1/splitter.ts +161 -0
  138. package/src/d1/types.ts +25 -0
  139. package/src/d1/utils.ts +49 -0
  140. package/src/delete.ts +100 -0
  141. package/src/deployments.ts +116 -0
  142. package/src/deprecated/index.ts +144 -0
  143. package/src/dev/dev-vars.ts +20 -17
  144. package/src/dev/dev.tsx +530 -329
  145. package/src/dev/get-local-persistence-path.ts +31 -0
  146. package/src/dev/local.tsx +903 -301
  147. package/src/dev/remote.tsx +619 -236
  148. package/src/dev/start-server.ts +538 -0
  149. package/src/dev/use-esbuild.ts +184 -91
  150. package/src/dev/validate-dev-props.ts +31 -0
  151. package/src/dev-registry.ts +201 -0
  152. package/src/dev.tsx +914 -0
  153. package/src/dialogs.ts +136 -0
  154. package/src/dispatch-namespace.ts +211 -0
  155. package/src/docs/index.ts +97 -0
  156. package/src/durable.ts +87 -87
  157. package/src/entry.ts +236 -236
  158. package/src/environment-variables/factory.ts +88 -0
  159. package/src/environment-variables/misc-variables.ts +30 -0
  160. package/src/errors.ts +6 -6
  161. package/src/generate/index.ts +298 -0
  162. package/src/git-client.ts +112 -19
  163. package/src/global-wrangler-config-path.ts +26 -0
  164. package/src/https-options.ts +84 -80
  165. package/src/index.ts +705 -0
  166. package/src/init.ts +1022 -0
  167. package/src/inspect.ts +698 -593
  168. package/src/intl-polyfill.d.ts +123 -123
  169. package/src/is-ci.ts +14 -0
  170. package/src/is-interactive.ts +16 -0
  171. package/src/jest.d.ts +4 -0
  172. package/src/kv/helpers.ts +430 -0
  173. package/src/kv/index.ts +594 -0
  174. package/src/logger.ts +77 -46
  175. package/src/metrics/index.ts +5 -0
  176. package/src/metrics/metrics-config.ts +239 -0
  177. package/src/metrics/metrics-dispatcher.ts +96 -0
  178. package/src/metrics/metrics-usage-headers.ts +24 -0
  179. package/src/metrics/send-event.ts +98 -0
  180. package/src/miniflare-cli/assets.ts +250 -0
  181. package/src/miniflare-cli/index.ts +202 -33
  182. package/src/miniflare-cli/request-context.ts +18 -18
  183. package/src/miniflare-cli/tsconfig.json +9 -0
  184. package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -0
  185. package/src/miniflare-cli/types.ts +11 -0
  186. package/src/module-collection.ts +221 -212
  187. package/src/mtls-certificate/cli.ts +155 -0
  188. package/src/open-in-browser.ts +4 -4
  189. package/src/package-manager.ts +173 -128
  190. package/src/pages/build.ts +232 -0
  191. package/src/pages/buildFunctions.ts +130 -0
  192. package/src/pages/constants.ts +18 -0
  193. package/src/pages/deployment-tails.ts +281 -0
  194. package/src/pages/deployments.tsx +86 -0
  195. package/src/pages/dev.ts +716 -0
  196. package/src/pages/errors.ts +66 -0
  197. package/src/pages/functions/buildPlugin.ts +90 -0
  198. package/src/pages/functions/buildWorker.ts +288 -0
  199. package/{pages → src/pages}/functions/filepath-routing.test.ts +113 -113
  200. package/src/pages/functions/filepath-routing.ts +189 -0
  201. package/src/pages/functions/identifiers.ts +78 -0
  202. package/src/pages/functions/routes-consolidation.test.ts +250 -0
  203. package/src/pages/functions/routes-consolidation.ts +73 -0
  204. package/src/pages/functions/routes-transformation.test.ts +282 -0
  205. package/src/pages/functions/routes-transformation.ts +115 -0
  206. package/src/pages/functions/routes-validation.test.ts +403 -0
  207. package/src/pages/functions/routes-validation.ts +202 -0
  208. package/src/pages/functions/routes.ts +151 -0
  209. package/src/pages/functions/tsconfig.json +8 -0
  210. package/src/pages/functions/tsconfig.tsbuildinfo +1 -0
  211. package/src/pages/functions.ts +86 -0
  212. package/src/pages/hash.ts +13 -0
  213. package/src/pages/index.ts +102 -0
  214. package/src/pages/projects.tsx +162 -0
  215. package/src/pages/prompt-select-project.tsx +31 -0
  216. package/src/pages/publish.tsx +276 -0
  217. package/src/pages/types.ts +46 -0
  218. package/src/pages/upload.tsx +449 -0
  219. package/src/pages/utils.ts +23 -0
  220. package/src/parse.ts +225 -139
  221. package/src/paths.ts +53 -8
  222. package/src/proxy.ts +623 -405
  223. package/src/publish/index.ts +274 -0
  224. package/src/publish/publish.ts +1065 -0
  225. package/src/pubsub/index.ts +286 -0
  226. package/src/pubsub/pubsub-commands.ts +623 -0
  227. package/src/queues/cli/commands/consumer/add.ts +65 -0
  228. package/src/queues/cli/commands/consumer/index.ts +19 -0
  229. package/src/queues/cli/commands/consumer/remove.ts +31 -0
  230. package/src/queues/cli/commands/create.ts +25 -0
  231. package/src/queues/cli/commands/delete.ts +26 -0
  232. package/src/queues/cli/commands/index.ts +35 -0
  233. package/src/queues/cli/commands/list.ts +25 -0
  234. package/src/queues/client.ts +135 -0
  235. package/src/queues/utils.ts +18 -0
  236. package/src/r2/constants.ts +4 -0
  237. package/src/r2/helpers.ts +131 -0
  238. package/src/r2/index.ts +289 -0
  239. package/src/routes.ts +140 -0
  240. package/src/secret/index.ts +375 -0
  241. package/src/selfsigned.d.ts +23 -23
  242. package/src/sites.ts +372 -0
  243. package/src/tail/createTail.ts +406 -0
  244. package/src/tail/filters.ts +109 -111
  245. package/src/tail/index.ts +208 -296
  246. package/src/tail/printing.ts +101 -46
  247. package/src/tsconfig-sanity.ts +16 -0
  248. package/src/type-generation.ts +181 -0
  249. package/src/update-check.ts +11 -11
  250. package/src/user/access.ts +68 -0
  251. package/src/user/auth-variables.ts +113 -0
  252. package/src/user/choose-account.tsx +39 -0
  253. package/src/user/generate-auth-url.ts +33 -0
  254. package/src/user/generate-random-state.ts +16 -0
  255. package/src/user/index.ts +2 -0
  256. package/src/user/user.ts +1233 -0
  257. package/src/utils/collectKeyValues.ts +14 -0
  258. package/src/whoami.ts +135 -0
  259. package/src/worker.ts +183 -107
  260. package/src/yargs-types.ts +37 -0
  261. package/src/zones.ts +158 -40
  262. package/templates/__tests__/pages-dev-util.test.ts +128 -0
  263. package/templates/__tests__/tsconfig-sanity.ts +12 -0
  264. package/templates/__tests__/tsconfig.json +8 -0
  265. package/templates/__tests__/tsconfig.tsbuildinfo +1 -0
  266. package/templates/checked-fetch.js +23 -0
  267. package/templates/d1-beta-facade.js +241 -0
  268. package/templates/facade.d.ts +14 -0
  269. package/templates/first-party-worker-module-facade.ts +19 -0
  270. package/templates/format-dev-errors.ts +34 -0
  271. package/templates/init-tests/test-jest-new-worker.js +23 -0
  272. package/templates/init-tests/test-vitest-new-worker.js +24 -0
  273. package/templates/init-tests/test-vitest-new-worker.ts +25 -0
  274. package/templates/middleware/common.ts +62 -0
  275. package/templates/middleware/loader-modules.ts +84 -0
  276. package/templates/middleware/loader-sw.ts +233 -0
  277. package/templates/middleware/middleware-miniflare3-json-error.ts +20 -0
  278. package/templates/middleware/middleware-pretty-error.ts +40 -0
  279. package/templates/middleware/middleware-scheduled.ts +15 -0
  280. package/templates/new-worker-scheduled.js +3 -3
  281. package/templates/new-worker-scheduled.ts +15 -15
  282. package/templates/new-worker.js +3 -3
  283. package/templates/new-worker.ts +18 -15
  284. package/templates/no-op-worker.js +8 -8
  285. package/templates/pages-dev-pipeline.ts +31 -0
  286. package/templates/pages-dev-util.ts +52 -0
  287. package/templates/pages-shim.ts +12 -0
  288. package/templates/pages-template-plugin.ts +176 -0
  289. package/templates/pages-template-worker.ts +189 -0
  290. package/templates/serve-static-assets.ts +66 -0
  291. package/templates/service-bindings-module-facade.js +55 -0
  292. package/templates/service-bindings-sw-facade.js +42 -0
  293. package/templates/tsconfig-sanity.ts +11 -0
  294. package/templates/tsconfig.init.json +106 -0
  295. package/templates/tsconfig.json +6 -103
  296. package/templates/tsconfig.tsbuildinfo +1 -0
  297. package/wrangler-dist/cli.d.ts +1108 -0
  298. package/wrangler-dist/cli.js +131192 -112380
  299. package/wrangler-dist/wasm-sync.wasm +0 -0
  300. package/pages/functions/buildPlugin.ts +0 -105
  301. package/pages/functions/buildWorker.ts +0 -151
  302. package/pages/functions/filepath-routing.ts +0 -189
  303. package/pages/functions/identifiers.ts +0 -78
  304. package/pages/functions/routes.ts +0 -156
  305. package/pages/functions/template-plugin.ts +0 -147
  306. package/pages/functions/template-worker.ts +0 -143
  307. package/src/__tests__/helpers/faye-websocket.d.ts +0 -6
  308. package/src/__tests__/helpers/mock-cfetch.ts +0 -211
  309. package/src/__tests__/pages.test.ts +0 -754
  310. package/src/bundle-reporter.tsx +0 -29
  311. package/src/dialogs.tsx +0 -135
  312. package/src/environment-variables.ts +0 -35
  313. package/src/generate-auth-url.ts +0 -33
  314. package/src/generate-random-state.ts +0 -16
  315. package/src/index.tsx +0 -2896
  316. package/src/kv.ts +0 -408
  317. package/src/miniflare-cli/enum-keys.ts +0 -17
  318. package/src/pages.tsx +0 -2093
  319. package/src/publish.ts +0 -739
  320. package/src/r2.ts +0 -50
  321. package/src/sites.tsx +0 -368
  322. package/src/user.tsx +0 -1202
  323. package/src/whoami.tsx +0 -71
  324. package/templates/static-asset-facade.js +0 -43
@@ -1,45 +1,85 @@
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 { CI } from "./is-ci";
5
+ import isInteractive from "./is-interactive";
6
+ import { logger } from "./logger";
3
7
 
4
8
  let cacheMessageShown = false;
5
9
 
6
- const cacheFolder = "node_modules/.cache/wrangler";
7
-
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;
14
- }
15
- };
16
-
17
- export const getConfigCache = <T>(fileName: string): Partial<T> => {
18
- try {
19
- const configCacheLocation = join(cacheFolder, fileName);
20
- const configCache = JSON.parse(readFileSync(configCacheLocation, "utf-8"));
21
- showCacheMessage();
22
- return configCache;
23
- } catch {
24
- return {};
25
- }
26
- };
27
-
28
- export const saveToConfigCache = <T>(
29
- fileName: string,
30
- 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
- showCacheMessage();
41
- };
42
-
43
- export const purgeConfigCaches = () => {
44
- rmSync(cacheFolder, { recursive: true, force: true });
45
- };
10
+ let __cacheFolder: string | null | undefined;
11
+ function getCacheFolder() {
12
+ if (__cacheFolder || __cacheFolder === null) return __cacheFolder;
13
+
14
+ const closestNodeModulesDirectory = findUpSync("node_modules", {
15
+ type: "directory",
16
+ });
17
+ __cacheFolder = closestNodeModulesDirectory
18
+ ? path.join(closestNodeModulesDirectory, ".cache/wrangler")
19
+ : null;
20
+
21
+ if (!__cacheFolder) {
22
+ logger.debug("No folder available to cache configuration");
23
+ }
24
+ return __cacheFolder;
25
+ }
26
+
27
+ const arrayFormatter = new Intl.ListFormat("en", {
28
+ style: "long",
29
+ type: "conjunction",
30
+ });
31
+
32
+ function showCacheMessage(fields: string[], folder: string) {
33
+ if (!cacheMessageShown && isInteractive() && !CI.isCI()) {
34
+ if (fields.length > 0) {
35
+ logger.debug(
36
+ `Retrieving cached values for ${arrayFormatter.format(
37
+ fields
38
+ )} from ${path.relative(process.cwd(), folder)}`
39
+ );
40
+ cacheMessageShown = true;
41
+ }
42
+ }
43
+ }
44
+
45
+ export function getConfigCache<T>(fileName: string): Partial<T> {
46
+ try {
47
+ const cacheFolder = getCacheFolder();
48
+ if (cacheFolder) {
49
+ const configCacheLocation = path.join(cacheFolder, fileName);
50
+ const configCache = JSON.parse(
51
+ readFileSync(configCacheLocation, "utf-8")
52
+ );
53
+ showCacheMessage(Object.keys(configCache), cacheFolder);
54
+ return configCache;
55
+ } else return {};
56
+ } catch (err) {
57
+ return {};
58
+ }
59
+ }
60
+
61
+ export function saveToConfigCache<T>(
62
+ fileName: string,
63
+ newValues: Partial<T>
64
+ ): void {
65
+ const cacheFolder = getCacheFolder();
66
+ if (cacheFolder) {
67
+ logger.debug(`Saving to cache: ${JSON.stringify(newValues)}`);
68
+ const configCacheLocation = path.join(cacheFolder, fileName);
69
+ const existingValues = getConfigCache(fileName);
70
+
71
+ mkdirSync(path.dirname(configCacheLocation), { recursive: true });
72
+ writeFileSync(
73
+ configCacheLocation,
74
+ JSON.stringify({ ...existingValues, ...newValues }, null, 2)
75
+ );
76
+ }
77
+ }
78
+
79
+ export function purgeConfigCaches() {
80
+ const cacheFolder = getCacheFolder();
81
+ if (cacheFolder) {
82
+ rmSync(cacheFolder, { recursive: true, force: true });
83
+ }
84
+ __cacheFolder = undefined;
85
+ }
@@ -3,7 +3,50 @@ import { fetch } from "undici";
3
3
  import { fetchResult } from "./cfetch";
4
4
  import { createWorkerUploadForm } from "./create-worker-upload-form";
5
5
  import { logger } from "./logger";
6
+ import { parseJSON } from "./parse";
7
+ import { getAccessToken } from "./user/access";
6
8
  import type { CfAccount, CfWorkerContext, CfWorkerInit } from "./worker";
9
+ import type { HeadersInit } from "undici";
10
+
11
+ /**
12
+ * A Preview Session on the edge
13
+ */
14
+ export interface CfPreviewSession {
15
+ /**
16
+ * A randomly generated id for this session
17
+ */
18
+ id: string;
19
+ /**
20
+ * A value to use when creating a worker preview under a session
21
+ */
22
+ value: string;
23
+ /**
24
+ * The host where the session is available.
25
+ */
26
+ host: string;
27
+ /**
28
+ * A websocket url to a DevTools inspector.
29
+ *
30
+ * Workers does not have a fully-featured implementation
31
+ * of the Chrome DevTools protocol, but supports the following:
32
+ * * `console.log()` output.
33
+ * * `Error` stack traces.
34
+ * * `fetch()` events.
35
+ *
36
+ * There is no support for breakpoints, but we want to implement
37
+ * this eventually.
38
+ *
39
+ * @link https://chromedevtools.github.io/devtools-protocol/
40
+ */
41
+ inspectorUrl: URL;
42
+ /**
43
+ * A url to prewarm the preview session.
44
+ *
45
+ * @example
46
+ * fetch(prewarmUrl, { method: 'POST' })
47
+ */
48
+ prewarmUrl: URL;
49
+ }
7
50
 
8
51
  /**
9
52
  * A preview mode.
@@ -17,145 +60,177 @@ type CfPreviewMode = { workers_dev: boolean } | { routes: string[] };
17
60
  * A preview token.
18
61
  */
19
62
  export interface CfPreviewToken {
20
- /**
21
- * The header value required to trigger a preview.
22
- *
23
- * @example
24
- * const headers = { 'cf-workers-preview-token': value }
25
- * const response = await fetch('https://' + host, { headers })
26
- */
27
- value: string;
28
- /**
29
- * The host where the preview is available.
30
- */
31
- host: string;
32
- /**
33
- * A websocket url to a DevTools inspector.
34
- *
35
- * Workers does not have a fully-featured implementation
36
- * of the Chrome DevTools protocol, but supports the following:
37
- * * `console.log()` output.
38
- * * `Error` stack traces.
39
- * * `fetch()` events.
40
- *
41
- * There is no support for breakpoints, but we want to implement
42
- * this eventually.
43
- *
44
- * @link https://chromedevtools.github.io/devtools-protocol/
45
- */
46
- inspectorUrl: URL;
47
- /**
48
- * A url to prewarm the preview session.
49
- *
50
- * @example
51
- * fetch(prewarmUrl, { method: 'POST' })
52
- */
53
- prewarmUrl: URL;
63
+ /**
64
+ * The header value required to trigger a preview.
65
+ *
66
+ * @example
67
+ * const headers = { 'cf-workers-preview-token': value }
68
+ * const response = await fetch('https://' + host, { headers })
69
+ */
70
+ value: string;
71
+ /**
72
+ * The host where the preview is available.
73
+ */
74
+ host: string;
75
+ /**
76
+ * A websocket url to a DevTools inspector.
77
+ *
78
+ * Workers does not have a fully-featured implementation
79
+ * of the Chrome DevTools protocol, but supports the following:
80
+ * * `console.log()` output.
81
+ * * `Error` stack traces.
82
+ * * `fetch()` events.
83
+ *
84
+ * There is no support for breakpoints, but we want to implement
85
+ * this eventually.
86
+ *
87
+ * @link https://chromedevtools.github.io/devtools-protocol/
88
+ */
89
+ inspectorUrl: URL;
90
+ /**
91
+ * A url to prewarm the preview session.
92
+ *
93
+ * @example
94
+ * fetch(prewarmUrl, { method: 'POST',
95
+ * headers: {
96
+ * "cf-workers-preview-token": (preview)token.value,
97
+ * }
98
+ * })
99
+ */
100
+ prewarmUrl: URL;
101
+ }
102
+
103
+ // Credit: https://stackoverflow.com/a/2117523
104
+ function randomId(): string {
105
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
106
+ const r = (Math.random() * 16) | 0,
107
+ v = c == "x" ? r : (r & 0x3) | 0x8;
108
+ return v.toString(16);
109
+ });
54
110
  }
55
111
 
56
112
  /**
57
113
  * Generates a preview session token.
58
114
  */
59
- async function sessionToken(
60
- account: CfAccount,
61
- ctx: CfWorkerContext,
62
- abortSignal: AbortSignal
63
- ): Promise<CfPreviewToken> {
64
- const { accountId } = account;
65
- const initUrl = ctx.zone
66
- ? `/zones/${ctx.zone}/workers/edge-preview`
67
- : `/accounts/${accountId}/workers/subdomain/edge-preview`;
68
-
69
- const { exchange_url } = await fetchResult<{ exchange_url: string }>(
70
- initUrl,
71
- undefined,
72
- undefined,
73
- abortSignal
74
- );
75
- const { inspector_websocket, prewarm, token } = (await (
76
- await fetch(exchange_url, { signal: abortSignal })
77
- ).json()) as { inspector_websocket: string; token: string; prewarm: string };
78
- const { host } = new URL(inspector_websocket);
79
- const query = `cf_workers_preview_token=${token}`;
80
-
81
- return {
82
- value: token,
83
- host,
84
- inspectorUrl: new URL(`${inspector_websocket}?${query}`),
85
- prewarmUrl: new URL(prewarm),
86
- };
87
- }
115
+ export async function createPreviewSession(
116
+ account: CfAccount,
117
+ ctx: CfWorkerContext,
118
+ abortSignal: AbortSignal
119
+ ): Promise<CfPreviewSession> {
120
+ const { accountId } = account;
121
+ const initUrl = ctx.zone
122
+ ? `/zones/${ctx.zone}/workers/edge-preview`
123
+ : `/accounts/${accountId}/workers/subdomain/edge-preview`;
88
124
 
89
- // Credit: https://stackoverflow.com/a/2117523
90
- function randomId(): string {
91
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
92
- const r = (Math.random() * 16) | 0,
93
- v = c == "x" ? r : (r & 0x3) | 0x8;
94
- return v.toString(16);
95
- });
125
+ const { exchange_url } = await fetchResult<{ exchange_url: string }>(
126
+ initUrl,
127
+ undefined,
128
+ undefined,
129
+ abortSignal
130
+ );
131
+
132
+ logger.debug(`-- START EXCHANGE API REQUEST: GET ${exchange_url}`);
133
+ logger.debug("-- END EXCHANGE API REQUEST");
134
+ const exchangeResponse = await fetch(exchange_url, { signal: abortSignal });
135
+ const bodyText = await exchangeResponse.text();
136
+ logger.debug(
137
+ "-- START EXCHANGE API RESPONSE:",
138
+ exchangeResponse.statusText,
139
+ exchangeResponse.status
140
+ );
141
+ logger.debug("HEADERS:", JSON.stringify(exchangeResponse.headers, null, 2));
142
+ logger.debug("RESPONSE:", bodyText);
143
+ logger.debug("-- END EXCHANGE API RESPONSE");
144
+
145
+ const { inspector_websocket, prewarm, token } = parseJSON<{
146
+ inspector_websocket: string;
147
+ token: string;
148
+ prewarm: string;
149
+ }>(bodyText);
150
+
151
+ const { host } = new URL(inspector_websocket);
152
+ const query = `cf_workers_preview_token=${token}`;
153
+
154
+ return {
155
+ id: randomId(),
156
+ value: token,
157
+ host,
158
+ inspectorUrl: new URL(`${inspector_websocket}?${query}`),
159
+ prewarmUrl: new URL(prewarm),
160
+ };
96
161
  }
97
162
 
98
163
  /**
99
164
  * Creates a preview token.
100
165
  */
101
166
  async function createPreviewToken(
102
- account: CfAccount,
103
- worker: CfWorkerInit,
104
- ctx: CfWorkerContext,
105
- abortSignal: AbortSignal
167
+ account: CfAccount,
168
+ worker: CfWorkerInit,
169
+ ctx: CfWorkerContext,
170
+ session: CfPreviewSession,
171
+ abortSignal: AbortSignal
106
172
  ): Promise<CfPreviewToken> {
107
- const { value, host, inspectorUrl, prewarmUrl } = await sessionToken(
108
- account,
109
- ctx,
110
- abortSignal
111
- );
112
-
113
- const { accountId } = account;
114
- const scriptId = worker.name || (ctx.zone ? randomId() : host.split(".")[0]);
115
- const url =
116
- ctx.env && !ctx.legacyEnv
117
- ? `/accounts/${accountId}/workers/services/${scriptId}/environments/${ctx.env}/edge-preview`
118
- : `/accounts/${accountId}/workers/scripts/${scriptId}/edge-preview`;
119
-
120
- const mode: CfPreviewMode = ctx.zone
121
- ? { routes: ["*/*"] } // TODO: should we support routes here? how?
122
- : { workers_dev: true };
123
-
124
- const formData = createWorkerUploadForm(worker);
125
- formData.set("wrangler-session-config", JSON.stringify(mode));
126
-
127
- const { preview_token } = await fetchResult<{ preview_token: string }>(
128
- url,
129
- {
130
- method: "POST",
131
- body: formData,
132
- headers: {
133
- "cf-preview-upload-config-token": value,
134
- },
135
- },
136
- undefined,
137
- abortSignal
138
- );
139
-
140
- return {
141
- value: preview_token,
142
- host:
143
- ctx.host ??
144
- (worker.name
145
- ? `${
146
- worker.name
147
- // TODO: this should also probably have the env prefix
148
- // but it doesn't appear to work yet, instead giving us the
149
- // "There is nothing here yet" screen
150
- // ctx.env && !ctx.legacyEnv
151
- // ? `${ctx.env}.${worker.name}`
152
- // : worker.name
153
- }.${host.split(".").slice(1).join(".")}`
154
- : host),
155
-
156
- inspectorUrl,
157
- prewarmUrl,
158
- };
173
+ const { value, host, inspectorUrl, prewarmUrl } = session;
174
+ const { accountId } = account;
175
+ const scriptId = worker.name || (ctx.zone ? session.id : host.split(".")[0]);
176
+ const url =
177
+ ctx.env && !ctx.legacyEnv
178
+ ? `/accounts/${accountId}/workers/services/${scriptId}/environments/${ctx.env}/edge-preview`
179
+ : `/accounts/${accountId}/workers/scripts/${scriptId}/edge-preview`;
180
+
181
+ const mode: CfPreviewMode = ctx.zone
182
+ ? {
183
+ routes: ctx.routes
184
+ ? // extract all the route patterns
185
+ ctx.routes.map((route) => {
186
+ if (typeof route === "string") {
187
+ return route;
188
+ }
189
+ if (route.custom_domain) {
190
+ return `${route.pattern}/*`;
191
+ }
192
+ return route.pattern;
193
+ })
194
+ : // if there aren't any patterns, then just match on all routes
195
+ ["*/*"],
196
+ }
197
+ : { workers_dev: true };
198
+
199
+ const formData = createWorkerUploadForm(worker);
200
+ formData.set("wrangler-session-config", JSON.stringify(mode));
201
+
202
+ const { preview_token } = await fetchResult<{ preview_token: string }>(
203
+ url,
204
+ {
205
+ method: "POST",
206
+ body: formData,
207
+ headers: {
208
+ "cf-preview-upload-config-token": value,
209
+ },
210
+ },
211
+ undefined,
212
+ abortSignal
213
+ );
214
+
215
+ return {
216
+ value: preview_token,
217
+ host:
218
+ ctx.host ??
219
+ (worker.name
220
+ ? `${
221
+ worker.name
222
+ // TODO: this should also probably have the env prefix
223
+ // but it doesn't appear to work yet, instead giving us the
224
+ // "There is nothing here yet" screen
225
+ // ctx.env && !ctx.legacyEnv
226
+ // ? `${ctx.env}.${worker.name}`
227
+ // : worker.name
228
+ }.${host.split(".").slice(1).join(".")}`
229
+ : host),
230
+
231
+ inspectorUrl,
232
+ prewarmUrl,
233
+ };
159
234
  }
160
235
 
161
236
  /**
@@ -165,21 +240,43 @@ async function createPreviewToken(
165
240
  * const {value, host} = await createWorker(init, acct);
166
241
  */
167
242
  export async function createWorkerPreview(
168
- init: CfWorkerInit,
169
- account: CfAccount,
170
- ctx: CfWorkerContext,
171
- abortSignal: AbortSignal
243
+ init: CfWorkerInit,
244
+ account: CfAccount,
245
+ ctx: CfWorkerContext,
246
+ session: CfPreviewSession,
247
+ abortSignal: AbortSignal
172
248
  ): Promise<CfPreviewToken> {
173
- const token = await createPreviewToken(account, init, ctx, abortSignal);
174
- const response = await fetch(token.prewarmUrl.href, {
175
- method: "POST",
176
- signal: abortSignal,
177
- headers: {
178
- "cf-workers-preview-token": token.value,
179
- },
180
- });
181
- if (!response.ok) {
182
- logger.warn("worker failed to prewarm: ", response.statusText);
183
- }
184
- return token;
249
+ const token = await createPreviewToken(
250
+ account,
251
+ init,
252
+ ctx,
253
+ session,
254
+ abortSignal
255
+ );
256
+ const accessToken = await getAccessToken(token.prewarmUrl.hostname);
257
+
258
+ const headers: HeadersInit = { "cf-workers-preview-token": token.value };
259
+ if (accessToken) {
260
+ headers.cookie = `CF_Authorization=${accessToken}`;
261
+ }
262
+
263
+ // fire and forget the prewarm call
264
+ fetch(token.prewarmUrl.href, {
265
+ method: "POST",
266
+ signal: abortSignal,
267
+ headers,
268
+ }).then(
269
+ (response) => {
270
+ if (!response.ok) {
271
+ logger.warn("worker failed to prewarm: ", response.statusText);
272
+ }
273
+ },
274
+ (err) => {
275
+ if ((err as { code: string }).code !== "ABORT_ERR") {
276
+ logger.warn("worker failed to prewarm: ", err);
277
+ }
278
+ }
279
+ );
280
+
281
+ return token;
185
282
  }