wrangler 0.0.0-e88a54e → 0.0.0-e8e684c7

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 (222) hide show
  1. package/Cloudflare_CA.pem +18 -0
  2. package/README.md +51 -14
  3. package/bin/wrangler.js +161 -29
  4. package/kv-asset-handler.js +1 -0
  5. package/miniflare-dist/index.mjs +5484 -21
  6. package/package.json +173 -143
  7. package/src/__tests__/config-cache-without-cache-dir.test.ts +38 -0
  8. package/src/__tests__/config-cache.test.ts +42 -0
  9. package/src/__tests__/configuration.test.ts +4016 -2786
  10. package/src/__tests__/dev.test.tsx +1305 -483
  11. package/src/__tests__/generate.test.ts +91 -0
  12. package/src/__tests__/guess-worker-format.test.ts +75 -48
  13. package/src/__tests__/helpers/cmd-shim.d.ts +6 -6
  14. package/src/__tests__/helpers/mock-account-id.ts +24 -24
  15. package/src/__tests__/helpers/mock-bin.ts +20 -20
  16. package/src/__tests__/helpers/mock-cfetch.ts +182 -93
  17. package/src/__tests__/helpers/mock-console.ts +59 -32
  18. package/src/__tests__/helpers/mock-dialogs.ts +121 -33
  19. package/src/__tests__/helpers/mock-get-zone-from-host.ts +8 -0
  20. package/src/__tests__/helpers/mock-http-server.ts +46 -0
  21. package/src/__tests__/helpers/mock-istty.ts +74 -0
  22. package/src/__tests__/helpers/mock-known-routes.ts +7 -0
  23. package/src/__tests__/helpers/mock-kv.ts +26 -26
  24. package/src/__tests__/helpers/mock-oauth-flow.ts +250 -0
  25. package/src/__tests__/helpers/mock-process.ts +39 -0
  26. package/src/__tests__/helpers/mock-stdin.ts +82 -77
  27. package/src/__tests__/helpers/mock-web-socket.ts +21 -21
  28. package/src/__tests__/helpers/run-in-tmp.ts +28 -22
  29. package/src/__tests__/helpers/run-wrangler.ts +8 -8
  30. package/src/__tests__/helpers/write-worker-source.ts +31 -0
  31. package/src/__tests__/helpers/write-wrangler-toml.ts +9 -9
  32. package/src/__tests__/https-options.test.ts +144 -108
  33. package/src/__tests__/index.test.ts +229 -975
  34. package/src/__tests__/init.test.ts +2170 -0
  35. package/src/__tests__/jest.setup.ts +122 -34
  36. package/src/__tests__/kv.test.ts +1376 -1087
  37. package/src/__tests__/logger.test.ts +141 -0
  38. package/src/__tests__/metrics.test.ts +450 -0
  39. package/src/__tests__/package-manager.test.ts +312 -165
  40. package/src/__tests__/pages.test.ts +1270 -39
  41. package/src/__tests__/parse.test.ts +253 -245
  42. package/src/__tests__/publish.test.ts +6878 -2627
  43. package/src/__tests__/pubsub.test.ts +367 -0
  44. package/src/__tests__/r2.test.ts +328 -190
  45. package/src/__tests__/route.test.ts +22 -22
  46. package/src/__tests__/secret.test.ts +474 -407
  47. package/src/__tests__/tail.test.ts +679 -441
  48. package/src/__tests__/test-old-node-version.js +31 -0
  49. package/src/__tests__/user.test.ts +155 -0
  50. package/src/__tests__/validate-dev-props.test.ts +56 -0
  51. package/src/__tests__/version.test.ts +35 -0
  52. package/src/__tests__/whoami.test.tsx +276 -87
  53. package/src/__tests__/worker-namespace.test.ts +329 -0
  54. package/src/abort.d.ts +3 -0
  55. package/src/api/dev.ts +93 -0
  56. package/src/api/index.ts +1 -0
  57. package/src/bundle-reporter.tsx +29 -0
  58. package/src/bundle.ts +441 -110
  59. package/src/cfetch/index.ts +83 -66
  60. package/src/cfetch/internal.ts +251 -92
  61. package/src/cli.ts +22 -14
  62. package/src/config/README.md +1 -1
  63. package/src/config/config.ts +224 -179
  64. package/src/config/diagnostics.ts +61 -61
  65. package/src/config/environment.ts +430 -311
  66. package/src/config/index.ts +227 -38
  67. package/src/config/validation-helpers.ts +414 -303
  68. package/src/config/validation.ts +1745 -973
  69. package/src/config-cache.ts +85 -0
  70. package/src/create-worker-preview.ts +209 -118
  71. package/src/create-worker-upload-form.ts +275 -201
  72. package/src/dev/dev-vars.ts +36 -0
  73. package/src/dev/dev.tsx +488 -307
  74. package/src/dev/local.tsx +427 -210
  75. package/src/dev/remote.tsx +407 -188
  76. package/src/dev/use-esbuild.ts +156 -78
  77. package/src/dev/validate-dev-props.ts +31 -0
  78. package/src/dev-registry.tsx +160 -0
  79. package/src/dev.tsx +696 -0
  80. package/src/dialogs.tsx +115 -57
  81. package/src/dispatch-namespace.ts +206 -0
  82. package/src/durable.ts +102 -0
  83. package/src/entry.ts +267 -147
  84. package/src/environment-variables.ts +25 -23
  85. package/src/errors.ts +11 -0
  86. package/src/faye-websocket.d.ts +6 -0
  87. package/src/generate.ts +131 -0
  88. package/src/git-client.ts +42 -0
  89. package/src/global-wrangler-config-path.ts +26 -0
  90. package/src/https-options.ts +85 -80
  91. package/src/index.tsx +2191 -2304
  92. package/src/init.ts +622 -0
  93. package/src/inspect.ts +687 -557
  94. package/src/intl-polyfill.d.ts +139 -0
  95. package/src/is-ci.ts +14 -0
  96. package/src/is-interactive.ts +12 -0
  97. package/src/kv.ts +353 -242
  98. package/src/logger.ts +73 -0
  99. package/src/metrics/index.ts +5 -0
  100. package/src/metrics/metrics-config.ts +239 -0
  101. package/src/metrics/metrics-dispatcher.ts +96 -0
  102. package/src/metrics/metrics-usage-headers.ts +24 -0
  103. package/src/metrics/send-event.ts +92 -0
  104. package/src/miniflare-cli/assets.ts +554 -0
  105. package/src/miniflare-cli/enum-keys.ts +8 -8
  106. package/src/miniflare-cli/index.ts +199 -29
  107. package/src/miniflare-cli/request-context.ts +40 -0
  108. package/src/module-collection.ts +213 -213
  109. package/src/open-in-browser.ts +8 -16
  110. package/src/package-manager.ts +183 -90
  111. package/src/pages/build.tsx +238 -0
  112. package/src/pages/constants.ts +12 -0
  113. package/src/pages/deployments.tsx +106 -0
  114. package/src/pages/dev.tsx +528 -0
  115. package/src/pages/errors.ts +22 -0
  116. package/src/pages/functions/buildPlugin.ts +109 -0
  117. package/src/pages/functions/buildWorker.ts +155 -0
  118. package/src/pages/functions/filepath-routing.test.ts +234 -0
  119. package/src/pages/functions/filepath-routing.ts +189 -0
  120. package/src/pages/functions/identifiers.ts +78 -0
  121. package/src/pages/functions/routes-consolidation.test.ts +250 -0
  122. package/src/pages/functions/routes-consolidation.ts +73 -0
  123. package/src/pages/functions/routes-transformation.test.ts +271 -0
  124. package/src/pages/functions/routes-transformation.ts +122 -0
  125. package/src/pages/functions/routes.ts +151 -0
  126. package/src/pages/functions.tsx +96 -0
  127. package/src/pages/index.tsx +94 -0
  128. package/src/pages/projects.tsx +169 -0
  129. package/src/pages/publish.tsx +391 -0
  130. package/src/pages/types.ts +49 -0
  131. package/src/pages/upload.tsx +413 -0
  132. package/src/pages/utils.ts +12 -0
  133. package/src/parse.ts +224 -121
  134. package/src/paths.ts +6 -6
  135. package/src/preview.ts +31 -0
  136. package/src/proxy.ts +416 -370
  137. package/src/publish.ts +796 -321
  138. package/src/pubsub/index.ts +286 -0
  139. package/src/pubsub/pubsub-commands.tsx +623 -0
  140. package/src/r2.ts +100 -19
  141. package/src/selfsigned.d.ts +23 -23
  142. package/src/sites.tsx +281 -189
  143. package/src/tail/filters.ts +111 -109
  144. package/src/tail/index.ts +230 -217
  145. package/src/tail/printing.ts +92 -47
  146. package/src/update-check.ts +19 -0
  147. package/src/user/choose-account.tsx +69 -0
  148. package/src/user/env-vars.ts +46 -0
  149. package/src/user/generate-auth-url.ts +33 -0
  150. package/src/user/generate-random-state.ts +16 -0
  151. package/src/user/index.ts +3 -0
  152. package/src/user/user.tsx +1191 -0
  153. package/src/whoami.tsx +142 -42
  154. package/src/worker.ts +135 -94
  155. package/src/zones.ts +167 -0
  156. package/templates/checked-fetch.js +17 -0
  157. package/templates/first-party-worker-module-facade.ts +18 -0
  158. package/templates/format-dev-errors.ts +32 -0
  159. package/templates/gitignore +171 -0
  160. package/templates/new-worker-scheduled.js +17 -0
  161. package/templates/new-worker-scheduled.ts +32 -0
  162. package/templates/new-worker.js +3 -3
  163. package/templates/new-worker.ts +18 -3
  164. package/templates/no-op-worker.js +10 -0
  165. package/templates/pages-shim.ts +9 -0
  166. package/templates/pages-template-plugin.ts +167 -0
  167. package/templates/pages-template-worker.ts +172 -0
  168. package/templates/serve-static-assets.ts +63 -0
  169. package/templates/service-bindings-module-facade.js +54 -0
  170. package/templates/service-bindings-sw-facade.js +42 -0
  171. package/templates/tsconfig.json +95 -95
  172. package/wrangler-dist/cli.d.ts +338 -0
  173. package/wrangler-dist/cli.js +124611 -112403
  174. package/miniflare-dist/index.mjs.map +0 -7
  175. package/pages/functions/buildWorker.ts +0 -62
  176. package/pages/functions/filepath-routing.test.ts +0 -223
  177. package/pages/functions/filepath-routing.ts +0 -181
  178. package/pages/functions/identifiers.ts +0 -78
  179. package/pages/functions/routes.ts +0 -151
  180. package/pages/functions/template-worker.ts +0 -130
  181. package/src/__tests__/dev2.test.tsx +0 -154
  182. package/src/__tests__/helpers/faye-websocket.d.ts +0 -6
  183. package/src/__tests__/logout.test.ts +0 -52
  184. package/src/__tests__/sentry.test.ts +0 -146
  185. package/src/pages.tsx +0 -1047
  186. package/src/reporting.ts +0 -131
  187. package/src/user.tsx +0 -1118
  188. package/templates/static-asset-facade.js +0 -47
  189. package/vendor/@cloudflare/kv-asset-handler/CHANGELOG.md +0 -332
  190. package/vendor/@cloudflare/kv-asset-handler/LICENSE_APACHE +0 -176
  191. package/vendor/@cloudflare/kv-asset-handler/LICENSE_MIT +0 -25
  192. package/vendor/@cloudflare/kv-asset-handler/README.md +0 -245
  193. package/vendor/@cloudflare/kv-asset-handler/dist/index.d.ts +0 -32
  194. package/vendor/@cloudflare/kv-asset-handler/dist/index.js +0 -354
  195. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.d.ts +0 -13
  196. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.js +0 -148
  197. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.d.ts +0 -1
  198. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.js +0 -436
  199. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.d.ts +0 -1
  200. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.js +0 -40
  201. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.d.ts +0 -1
  202. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.js +0 -42
  203. package/vendor/@cloudflare/kv-asset-handler/dist/types.d.ts +0 -26
  204. package/vendor/@cloudflare/kv-asset-handler/dist/types.js +0 -31
  205. package/vendor/@cloudflare/kv-asset-handler/package.json +0 -52
  206. package/vendor/@cloudflare/kv-asset-handler/src/index.ts +0 -296
  207. package/vendor/@cloudflare/kv-asset-handler/src/mocks.ts +0 -136
  208. package/vendor/@cloudflare/kv-asset-handler/src/test/getAssetFromKV.ts +0 -464
  209. package/vendor/@cloudflare/kv-asset-handler/src/test/mapRequestToAsset.ts +0 -33
  210. package/vendor/@cloudflare/kv-asset-handler/src/test/serveSinglePageApp.ts +0 -42
  211. package/vendor/@cloudflare/kv-asset-handler/src/types.ts +0 -39
  212. package/vendor/wrangler-mime/CHANGELOG.md +0 -289
  213. package/vendor/wrangler-mime/LICENSE +0 -21
  214. package/vendor/wrangler-mime/Mime.js +0 -97
  215. package/vendor/wrangler-mime/README.md +0 -187
  216. package/vendor/wrangler-mime/cli.js +0 -46
  217. package/vendor/wrangler-mime/index.js +0 -4
  218. package/vendor/wrangler-mime/lite.js +0 -4
  219. package/vendor/wrangler-mime/package.json +0 -52
  220. package/vendor/wrangler-mime/types/other.js +0 -1
  221. package/vendor/wrangler-mime/types/standard.js +0 -1
  222. package/wrangler-dist/cli.js.map +0 -7
@@ -1,100 +1,178 @@
1
1
  import assert from "node:assert";
2
+ import { watch } from "chokidar";
3
+ import { useApp } from "ink";
2
4
  import { useState, useEffect } from "react";
3
5
  import { bundleWorker } from "../bundle";
6
+ import { logger } from "../logger";
4
7
  import type { Config } from "../config";
8
+ import type { WorkerRegistry } from "../dev-registry";
5
9
  import type { Entry } from "../entry";
6
10
  import type { CfModule } from "../worker";
7
11
  import type { WatchMode } from "esbuild";
8
12
 
9
13
  export type EsbuildBundle = {
10
- id: number;
11
- path: string;
12
- entry: Entry;
13
- type: "esm" | "commonjs";
14
- modules: CfModule[];
15
- serveAssetsFromWorker: boolean;
14
+ id: number;
15
+ path: string;
16
+ entry: Entry;
17
+ type: "esm" | "commonjs";
18
+ modules: CfModule[];
19
+ sourceMapPath: string | undefined;
16
20
  };
17
21
 
18
22
  export function useEsbuild({
19
- entry,
20
- destination,
21
- staticRoot,
22
- jsxFactory,
23
- jsxFragment,
24
- rules,
25
- serveAssetsFromWorker,
23
+ entry,
24
+ destination,
25
+ jsxFactory,
26
+ jsxFragment,
27
+ rules,
28
+ assets,
29
+ serveAssetsFromWorker,
30
+ tsconfig,
31
+ minify,
32
+ nodeCompat,
33
+ define,
34
+ noBundle,
35
+ workerDefinitions,
36
+ services,
37
+ durableObjects,
38
+ firstPartyWorkerDevFacade,
26
39
  }: {
27
- entry: Entry;
28
- destination: string | undefined;
29
- staticRoot: undefined | string;
30
- jsxFactory: string | undefined;
31
- jsxFragment: string | undefined;
32
- rules: Config["rules"];
33
- serveAssetsFromWorker: boolean;
40
+ entry: Entry;
41
+ destination: string | undefined;
42
+ jsxFactory: string | undefined;
43
+ jsxFragment: string | undefined;
44
+ rules: Config["rules"];
45
+ assets: Config["assets"];
46
+ define: Config["define"];
47
+ services: Config["services"];
48
+ serveAssetsFromWorker: boolean;
49
+ tsconfig: string | undefined;
50
+ minify: boolean | undefined;
51
+ nodeCompat: boolean | undefined;
52
+ noBundle: boolean;
53
+ workerDefinitions: WorkerRegistry;
54
+ durableObjects: Config["durable_objects"];
55
+ firstPartyWorkerDevFacade: boolean | undefined;
34
56
  }): EsbuildBundle | undefined {
35
- const [bundle, setBundle] = useState<EsbuildBundle>();
36
- useEffect(() => {
37
- let stopWatching: (() => void) | undefined = undefined;
57
+ const [bundle, setBundle] = useState<EsbuildBundle>();
58
+ const { exit } = useApp();
59
+ useEffect(() => {
60
+ let stopWatching: (() => void) | undefined = undefined;
38
61
 
39
- const watchMode: WatchMode = {
40
- async onRebuild(error) {
41
- if (error) console.error("watch build failed:", error);
42
- else {
43
- // nothing really changes here, so let's increment the id
44
- // to change the return object's identity
45
- setBundle((previousBundle) => {
46
- assert(
47
- previousBundle,
48
- "Rebuild triggered with no previous build available"
49
- );
50
- return { ...previousBundle, id: previousBundle.id + 1 };
51
- });
52
- }
53
- },
54
- };
62
+ function updateBundle() {
63
+ // nothing really changes here, so let's increment the id
64
+ // to change the return object's identity
65
+ setBundle((previousBundle) => {
66
+ assert(
67
+ previousBundle,
68
+ "Rebuild triggered with no previous build available"
69
+ );
70
+ return { ...previousBundle, id: previousBundle.id + 1 };
71
+ });
72
+ }
55
73
 
56
- async function build() {
57
- if (!destination) return;
74
+ const watchMode: WatchMode = {
75
+ async onRebuild(error) {
76
+ if (error) logger.error("Watch build failed:", error);
77
+ else {
78
+ updateBundle();
79
+ }
80
+ },
81
+ };
58
82
 
59
- const { resolvedEntryPointPath, bundleType, modules, stop } =
60
- await bundleWorker(entry, destination, {
61
- // In dev, we serve assets from the local proxy before we send the request to the worker.
62
- serveAssetsFromWorker: false,
63
- jsxFactory,
64
- jsxFragment,
65
- rules,
66
- watch: watchMode,
67
- });
83
+ async function build() {
84
+ if (!destination) return;
68
85
 
69
- // Capture the `stop()` method to use as the `useEffect()` destructor.
70
- stopWatching = stop;
86
+ const {
87
+ resolvedEntryPointPath,
88
+ bundleType,
89
+ modules,
90
+ stop,
91
+ sourceMapPath,
92
+ }: Awaited<ReturnType<typeof bundleWorker>> = noBundle
93
+ ? {
94
+ modules: [],
95
+ resolvedEntryPointPath: entry.file,
96
+ bundleType: entry.format === "modules" ? "esm" : "commonjs",
97
+ stop: undefined,
98
+ sourceMapPath: undefined,
99
+ }
100
+ : await bundleWorker(entry, destination, {
101
+ serveAssetsFromWorker,
102
+ jsxFactory,
103
+ jsxFragment,
104
+ rules,
105
+ watch: watchMode,
106
+ tsconfig,
107
+ minify,
108
+ nodeCompat,
109
+ define,
110
+ checkFetch: true,
111
+ assets: assets && {
112
+ ...assets,
113
+ // disable the cache in dev
114
+ bypassCache: true,
115
+ },
116
+ workerDefinitions,
117
+ services,
118
+ firstPartyWorkerDevFacade,
119
+ });
71
120
 
72
- setBundle({
73
- id: 0,
74
- entry,
75
- path: resolvedEntryPointPath,
76
- type: bundleType,
77
- modules,
78
- serveAssetsFromWorker,
79
- });
80
- }
121
+ // Capture the `stop()` method to use as the `useEffect()` destructor.
122
+ stopWatching = stop;
81
123
 
82
- build().catch(() => {
83
- // esbuild already logs errors to stderr and we don't want to end the process
84
- // on build errors anyway so this is a no-op error handler
85
- });
124
+ // if "noBundle" is true, then we need to manually watch the entry point and
125
+ // trigger "builds" when it changes
126
+ if (noBundle) {
127
+ const watcher = watch(entry.file, {
128
+ persistent: true,
129
+ }).on("change", async (_event) => {
130
+ updateBundle();
131
+ });
86
132
 
87
- return () => {
88
- stopWatching?.();
89
- };
90
- }, [
91
- entry,
92
- destination,
93
- staticRoot,
94
- jsxFactory,
95
- jsxFragment,
96
- serveAssetsFromWorker,
97
- rules,
98
- ]);
99
- return bundle;
133
+ stopWatching = () => {
134
+ watcher.close();
135
+ };
136
+ }
137
+
138
+ setBundle({
139
+ id: 0,
140
+ entry,
141
+ path: resolvedEntryPointPath,
142
+ type: bundleType,
143
+ modules,
144
+ sourceMapPath,
145
+ });
146
+ }
147
+
148
+ build().catch((err) => {
149
+ // If esbuild fails on first run, we want to quit the process
150
+ // since we can't recover from here
151
+ // related: https://github.com/evanw/esbuild/issues/1037
152
+ exit(err);
153
+ });
154
+
155
+ return () => {
156
+ stopWatching?.();
157
+ };
158
+ }, [
159
+ entry,
160
+ destination,
161
+ jsxFactory,
162
+ jsxFragment,
163
+ serveAssetsFromWorker,
164
+ rules,
165
+ tsconfig,
166
+ exit,
167
+ noBundle,
168
+ minify,
169
+ nodeCompat,
170
+ define,
171
+ assets,
172
+ services,
173
+ durableObjects,
174
+ workerDefinitions,
175
+ firstPartyWorkerDevFacade,
176
+ ]);
177
+ return bundle;
100
178
  }
@@ -0,0 +1,31 @@
1
+ import type { DevProps } from "./dev";
2
+
3
+ export function validateDevProps(props: DevProps) {
4
+ if (
5
+ !props.isWorkersSite &&
6
+ props.assetPaths &&
7
+ props.entry.format === "service-worker"
8
+ ) {
9
+ throw new Error(
10
+ "You cannot use the service-worker format with an `assets` directory yet. For information on how to migrate to the module-worker format, see: https://developers.cloudflare.com/workers/learning/migrating-to-module-workers/"
11
+ );
12
+ }
13
+
14
+ if (props.bindings.wasm_modules && props.entry.format === "modules") {
15
+ throw new Error(
16
+ "You cannot configure [wasm_modules] with an ES module worker. Instead, import the .wasm module directly in your code"
17
+ );
18
+ }
19
+
20
+ if (props.bindings.text_blobs && props.entry.format === "modules") {
21
+ throw new Error(
22
+ "You cannot configure [text_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure `[rules]` in your wrangler.toml"
23
+ );
24
+ }
25
+
26
+ if (props.bindings.data_blobs && props.entry.format === "modules") {
27
+ throw new Error(
28
+ "You cannot configure [data_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure `[rules]` in your wrangler.toml"
29
+ );
30
+ }
31
+ }
@@ -0,0 +1,160 @@
1
+ import http from "http";
2
+ import net from "net";
3
+ import bodyParser from "body-parser";
4
+ import express from "express";
5
+ import { createHttpTerminator } from "http-terminator";
6
+ import { fetch } from "undici";
7
+ import { logger } from "./logger";
8
+ import type { Server } from "http";
9
+ import type { HttpTerminator } from "http-terminator";
10
+
11
+ const DEV_REGISTRY_PORT = "6284";
12
+ const DEV_REGISTRY_HOST = `http://localhost:${DEV_REGISTRY_PORT}`;
13
+
14
+ let server: Server;
15
+ let terminator: HttpTerminator;
16
+
17
+ export type WorkerRegistry = Record<string, WorkerDefinition>;
18
+
19
+ type WorkerDefinition = {
20
+ port: number | undefined;
21
+ protocol: "http" | "https" | undefined;
22
+ host: string | undefined;
23
+ mode: "local" | "remote";
24
+ headers?: Record<string, string>;
25
+ durableObjects: { name: string; className: string }[];
26
+ durableObjectsHost?: string;
27
+ durableObjectsPort?: number;
28
+ };
29
+
30
+ /**
31
+ * A helper function to check whether our service registry is already running
32
+ */
33
+ async function isPortAvailable() {
34
+ return new Promise((resolve, reject) => {
35
+ const netServer = net
36
+ .createServer()
37
+ .once("error", (err) => {
38
+ netServer.close();
39
+ if ((err as unknown as { code: string }).code === "EADDRINUSE") {
40
+ resolve(false);
41
+ } else {
42
+ reject(err);
43
+ }
44
+ })
45
+ .once("listening", () => {
46
+ netServer.close();
47
+ resolve(true);
48
+ });
49
+ netServer.listen(DEV_REGISTRY_PORT);
50
+ });
51
+ }
52
+
53
+ const jsonBodyParser = bodyParser.json();
54
+
55
+ /**
56
+ * Start the service registry. It's a simple server
57
+ * that exposes endpoints for registering and unregistering
58
+ * services, as well as getting the state of the registry.
59
+ */
60
+ export async function startWorkerRegistry() {
61
+ if ((await isPortAvailable()) && !server) {
62
+ const app = express();
63
+
64
+ let workers: WorkerRegistry = {};
65
+ app
66
+ .get("/workers", async (req, res) => {
67
+ res.json(workers);
68
+ })
69
+ .post("/workers/:workerId", jsonBodyParser, async (req, res) => {
70
+ workers[req.params.workerId] = req.body;
71
+ res.json(null);
72
+ })
73
+ .delete(`/workers/:workerId`, async (req, res) => {
74
+ delete workers[req.params.workerId];
75
+ res.json(null);
76
+ })
77
+ .delete("/workers", async (req, res) => {
78
+ workers = {};
79
+ res.json(null);
80
+ });
81
+ server = http.createServer(app);
82
+ terminator = createHttpTerminator({ server });
83
+ server.listen(DEV_REGISTRY_PORT);
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Stop the service registry.
89
+ */
90
+ export async function stopWorkerRegistry() {
91
+ await terminator?.terminate();
92
+ }
93
+
94
+ /**
95
+ * Register a worker in the registry.
96
+ */
97
+ export async function registerWorker(
98
+ name: string,
99
+ definition: WorkerDefinition
100
+ ) {
101
+ try {
102
+ return await fetch(`${DEV_REGISTRY_HOST}/workers/${name}`, {
103
+ method: "POST",
104
+ headers: {
105
+ "Content-Type": "application/json",
106
+ },
107
+ body: JSON.stringify(definition),
108
+ });
109
+ } catch (e) {
110
+ if (
111
+ !["ECONNRESET", "ECONNREFUSED"].includes(
112
+ (e as unknown as { cause?: { code?: string } }).cause?.code || "___"
113
+ )
114
+ ) {
115
+ logger.error("Failed to register worker in local service registry", e);
116
+ } else {
117
+ logger.debug("Failed to register worker in local service registry", e);
118
+ }
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Unregister a worker from the registry.
124
+ */
125
+ export async function unregisterWorker(name: string) {
126
+ try {
127
+ await fetch(`${DEV_REGISTRY_HOST}/workers/${name}`, {
128
+ method: "DELETE",
129
+ });
130
+ } catch (e) {
131
+ if (
132
+ !["ECONNRESET", "ECONNREFUSED"].includes(
133
+ (e as unknown as { cause?: { code?: string } }).cause?.code || "___"
134
+ )
135
+ ) {
136
+ throw e;
137
+ // logger.error("failed to unregister worker", e);
138
+ }
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Get the state of the service registry.
144
+ */
145
+ export async function getRegisteredWorkers(): Promise<
146
+ WorkerRegistry | undefined
147
+ > {
148
+ try {
149
+ const response = await fetch(`${DEV_REGISTRY_HOST}/workers`);
150
+ return (await response.json()) as WorkerRegistry;
151
+ } catch (e) {
152
+ if (
153
+ !["ECONNRESET", "ECONNREFUSED"].includes(
154
+ (e as unknown as { cause?: { code?: string } }).cause?.code || "___"
155
+ )
156
+ ) {
157
+ throw e;
158
+ }
159
+ }
160
+ }