wrangler 0.0.0-e64812e → 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 (214) hide show
  1. package/README.md +27 -3
  2. package/bin/wrangler.js +150 -62
  3. package/kv-asset-handler.js +1 -0
  4. package/miniflare-dist/index.mjs +663 -7
  5. package/package.json +173 -152
  6. package/src/__tests__/config-cache-without-cache-dir.test.ts +38 -0
  7. package/src/__tests__/config-cache.test.ts +30 -24
  8. package/src/__tests__/configuration.test.ts +4015 -3363
  9. package/src/__tests__/dev.test.tsx +1290 -952
  10. package/src/__tests__/generate.test.ts +91 -0
  11. package/src/__tests__/guess-worker-format.test.ts +68 -68
  12. package/src/__tests__/helpers/cmd-shim.d.ts +6 -6
  13. package/src/__tests__/helpers/mock-account-id.ts +24 -24
  14. package/src/__tests__/helpers/mock-bin.ts +20 -20
  15. package/src/__tests__/helpers/mock-cfetch.ts +179 -94
  16. package/src/__tests__/helpers/mock-console.ts +49 -39
  17. package/src/__tests__/helpers/mock-dialogs.ts +94 -71
  18. package/src/__tests__/helpers/mock-get-zone-from-host.ts +8 -0
  19. package/src/__tests__/helpers/mock-http-server.ts +30 -30
  20. package/src/__tests__/helpers/mock-istty.ts +65 -18
  21. package/src/__tests__/helpers/mock-known-routes.ts +7 -0
  22. package/src/__tests__/helpers/mock-kv.ts +26 -26
  23. package/src/__tests__/helpers/mock-oauth-flow.ts +223 -228
  24. package/src/__tests__/helpers/mock-process.ts +39 -0
  25. package/src/__tests__/helpers/mock-stdin.ts +82 -77
  26. package/src/__tests__/helpers/mock-web-socket.ts +21 -21
  27. package/src/__tests__/helpers/run-in-tmp.ts +27 -28
  28. package/src/__tests__/helpers/run-wrangler.ts +8 -8
  29. package/src/__tests__/helpers/write-worker-source.ts +16 -16
  30. package/src/__tests__/helpers/write-wrangler-toml.ts +9 -9
  31. package/src/__tests__/https-options.test.ts +142 -109
  32. package/src/__tests__/index.test.ts +222 -233
  33. package/src/__tests__/init.test.ts +2139 -1603
  34. package/src/__tests__/jest.setup.ts +114 -34
  35. package/src/__tests__/kv.test.ts +1222 -1032
  36. package/src/__tests__/logger.test.ts +100 -74
  37. package/src/__tests__/metrics.test.ts +450 -0
  38. package/src/__tests__/package-manager.test.ts +303 -303
  39. package/src/__tests__/pages.test.ts +1173 -652
  40. package/src/__tests__/parse.test.ts +252 -252
  41. package/src/__tests__/publish.test.ts +6788 -5301
  42. package/src/__tests__/pubsub.test.ts +367 -0
  43. package/src/__tests__/r2.test.ts +328 -225
  44. package/src/__tests__/route.test.ts +18 -18
  45. package/src/__tests__/secret.test.ts +470 -459
  46. package/src/__tests__/tail.test.ts +676 -564
  47. package/src/__tests__/test-old-node-version.js +31 -0
  48. package/src/__tests__/user.test.ts +136 -112
  49. package/src/__tests__/validate-dev-props.test.ts +56 -0
  50. package/src/__tests__/version.test.ts +35 -0
  51. package/src/__tests__/whoami.test.tsx +267 -83
  52. package/src/__tests__/worker-namespace.test.ts +329 -0
  53. package/src/abort.d.ts +1 -1
  54. package/src/api/dev.ts +93 -0
  55. package/src/api/index.ts +1 -0
  56. package/src/bundle-reporter.tsx +29 -0
  57. package/src/bundle.ts +430 -157
  58. package/src/cfetch/index.ts +80 -80
  59. package/src/cfetch/internal.ts +244 -91
  60. package/src/cli.ts +21 -7
  61. package/src/config/config.ts +224 -195
  62. package/src/config/diagnostics.ts +61 -61
  63. package/src/config/environment.ts +422 -357
  64. package/src/config/index.ts +219 -193
  65. package/src/config/validation-helpers.ts +379 -357
  66. package/src/config/validation.ts +1690 -1367
  67. package/src/config-cache.ts +81 -41
  68. package/src/create-worker-preview.ts +208 -136
  69. package/src/create-worker-upload-form.ts +275 -238
  70. package/src/dev/dev-vars.ts +13 -13
  71. package/src/dev/dev.tsx +477 -351
  72. package/src/dev/local.tsx +426 -295
  73. package/src/dev/remote.tsx +406 -211
  74. package/src/dev/use-esbuild.ts +154 -94
  75. package/src/dev/validate-dev-props.ts +31 -0
  76. package/src/dev-registry.tsx +160 -0
  77. package/src/dev.tsx +696 -0
  78. package/src/dialogs.tsx +97 -97
  79. package/src/dispatch-namespace.ts +206 -0
  80. package/src/durable.ts +87 -87
  81. package/src/entry.ts +234 -228
  82. package/src/environment-variables.ts +23 -23
  83. package/src/errors.ts +6 -6
  84. package/src/faye-websocket.d.ts +6 -0
  85. package/src/generate.ts +131 -0
  86. package/src/git-client.ts +42 -0
  87. package/src/global-wrangler-config-path.ts +26 -0
  88. package/src/https-options.ts +84 -80
  89. package/src/index.tsx +2164 -2768
  90. package/src/init.ts +622 -0
  91. package/src/inspect.ts +678 -593
  92. package/src/intl-polyfill.d.ts +123 -123
  93. package/src/is-ci.ts +14 -0
  94. package/src/is-interactive.ts +12 -0
  95. package/src/kv.ts +299 -277
  96. package/src/logger.ts +46 -39
  97. package/src/metrics/index.ts +5 -0
  98. package/src/metrics/metrics-config.ts +239 -0
  99. package/src/metrics/metrics-dispatcher.ts +96 -0
  100. package/src/metrics/metrics-usage-headers.ts +24 -0
  101. package/src/metrics/send-event.ts +92 -0
  102. package/src/miniflare-cli/assets.ts +554 -0
  103. package/src/miniflare-cli/enum-keys.ts +8 -8
  104. package/src/miniflare-cli/index.ts +198 -32
  105. package/src/miniflare-cli/request-context.ts +18 -18
  106. package/src/module-collection.ts +212 -212
  107. package/src/open-in-browser.ts +4 -6
  108. package/src/package-manager.ts +173 -128
  109. package/src/pages/build.tsx +238 -0
  110. package/src/pages/constants.ts +12 -0
  111. package/src/pages/deployments.tsx +106 -0
  112. package/src/pages/dev.tsx +528 -0
  113. package/src/pages/errors.ts +22 -0
  114. package/src/pages/functions/buildPlugin.ts +109 -0
  115. package/src/pages/functions/buildWorker.ts +155 -0
  116. package/{pages → src/pages}/functions/filepath-routing.test.ts +113 -113
  117. package/src/pages/functions/filepath-routing.ts +189 -0
  118. package/src/pages/functions/identifiers.ts +78 -0
  119. package/src/pages/functions/routes-consolidation.test.ts +250 -0
  120. package/src/pages/functions/routes-consolidation.ts +73 -0
  121. package/src/pages/functions/routes-transformation.test.ts +271 -0
  122. package/src/pages/functions/routes-transformation.ts +122 -0
  123. package/src/pages/functions/routes.ts +151 -0
  124. package/src/pages/functions.tsx +96 -0
  125. package/src/pages/index.tsx +94 -0
  126. package/src/pages/projects.tsx +169 -0
  127. package/src/pages/publish.tsx +391 -0
  128. package/src/pages/types.ts +49 -0
  129. package/src/pages/upload.tsx +413 -0
  130. package/src/pages/utils.ts +12 -0
  131. package/src/parse.ts +209 -125
  132. package/src/paths.ts +6 -6
  133. package/src/preview.ts +31 -0
  134. package/src/proxy.ts +410 -389
  135. package/src/publish.ts +773 -534
  136. package/src/pubsub/index.ts +286 -0
  137. package/src/pubsub/pubsub-commands.tsx +623 -0
  138. package/src/r2.ts +100 -19
  139. package/src/selfsigned.d.ts +23 -23
  140. package/src/sites.tsx +278 -201
  141. package/src/tail/filters.ts +111 -109
  142. package/src/tail/index.ts +230 -217
  143. package/src/tail/printing.ts +86 -46
  144. package/src/update-check.ts +11 -11
  145. package/src/user/choose-account.tsx +69 -0
  146. package/src/user/env-vars.ts +46 -0
  147. package/src/user/generate-auth-url.ts +33 -0
  148. package/src/user/generate-random-state.ts +16 -0
  149. package/src/user/index.ts +3 -0
  150. package/src/user/user.tsx +1191 -0
  151. package/src/whoami.tsx +141 -42
  152. package/src/worker.ts +123 -99
  153. package/src/zones.ts +167 -0
  154. package/templates/checked-fetch.js +17 -0
  155. package/templates/first-party-worker-module-facade.ts +18 -0
  156. package/templates/format-dev-errors.ts +32 -0
  157. package/templates/new-worker-scheduled.js +3 -3
  158. package/templates/new-worker-scheduled.ts +15 -15
  159. package/templates/new-worker.js +3 -3
  160. package/templates/new-worker.ts +15 -15
  161. package/templates/no-op-worker.js +10 -0
  162. package/templates/pages-shim.ts +9 -0
  163. package/templates/pages-template-plugin.ts +167 -0
  164. package/templates/pages-template-worker.ts +172 -0
  165. package/templates/serve-static-assets.ts +63 -0
  166. package/templates/service-bindings-module-facade.js +54 -0
  167. package/templates/service-bindings-sw-facade.js +42 -0
  168. package/templates/tsconfig.json +95 -95
  169. package/wrangler-dist/cli.d.ts +338 -0
  170. package/wrangler-dist/cli.js +95449 -67524
  171. package/pages/functions/buildPlugin.ts +0 -105
  172. package/pages/functions/buildWorker.ts +0 -151
  173. package/pages/functions/filepath-routing.ts +0 -189
  174. package/pages/functions/identifiers.ts +0 -78
  175. package/pages/functions/routes.ts +0 -156
  176. package/pages/functions/template-plugin.ts +0 -147
  177. package/pages/functions/template-worker.ts +0 -143
  178. package/src/__tests__/helpers/faye-websocket.d.ts +0 -6
  179. package/src/pages.tsx +0 -2038
  180. package/src/user.tsx +0 -1203
  181. package/templates/static-asset-facade.js +0 -47
  182. package/vendor/@cloudflare/kv-asset-handler/CHANGELOG.md +0 -332
  183. package/vendor/@cloudflare/kv-asset-handler/LICENSE_APACHE +0 -176
  184. package/vendor/@cloudflare/kv-asset-handler/LICENSE_MIT +0 -25
  185. package/vendor/@cloudflare/kv-asset-handler/README.md +0 -245
  186. package/vendor/@cloudflare/kv-asset-handler/dist/index.d.ts +0 -32
  187. package/vendor/@cloudflare/kv-asset-handler/dist/index.js +0 -354
  188. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.d.ts +0 -13
  189. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.js +0 -148
  190. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.d.ts +0 -1
  191. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.js +0 -436
  192. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.d.ts +0 -1
  193. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.js +0 -40
  194. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.d.ts +0 -1
  195. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.js +0 -42
  196. package/vendor/@cloudflare/kv-asset-handler/dist/types.d.ts +0 -26
  197. package/vendor/@cloudflare/kv-asset-handler/dist/types.js +0 -31
  198. package/vendor/@cloudflare/kv-asset-handler/package.json +0 -52
  199. package/vendor/@cloudflare/kv-asset-handler/src/index.ts +0 -296
  200. package/vendor/@cloudflare/kv-asset-handler/src/mocks.ts +0 -136
  201. package/vendor/@cloudflare/kv-asset-handler/src/test/getAssetFromKV.ts +0 -464
  202. package/vendor/@cloudflare/kv-asset-handler/src/test/mapRequestToAsset.ts +0 -33
  203. package/vendor/@cloudflare/kv-asset-handler/src/test/serveSinglePageApp.ts +0 -42
  204. package/vendor/@cloudflare/kv-asset-handler/src/types.ts +0 -39
  205. package/vendor/wrangler-mime/CHANGELOG.md +0 -289
  206. package/vendor/wrangler-mime/LICENSE +0 -21
  207. package/vendor/wrangler-mime/Mime.js +0 -97
  208. package/vendor/wrangler-mime/README.md +0 -187
  209. package/vendor/wrangler-mime/cli.js +0 -46
  210. package/vendor/wrangler-mime/index.js +0 -4
  211. package/vendor/wrangler-mime/lite.js +0 -4
  212. package/vendor/wrangler-mime/package.json +0 -52
  213. package/vendor/wrangler-mime/types/other.js +0 -1
  214. package/vendor/wrangler-mime/types/standard.js +0 -1
@@ -1,118 +1,178 @@
1
1
  import assert from "node:assert";
2
+ import { watch } from "chokidar";
2
3
  import { useApp } from "ink";
3
4
  import { useState, useEffect } from "react";
4
5
  import { bundleWorker } from "../bundle";
5
6
  import { logger } from "../logger";
6
7
  import type { Config } from "../config";
8
+ import type { WorkerRegistry } from "../dev-registry";
7
9
  import type { Entry } from "../entry";
8
10
  import type { CfModule } from "../worker";
9
11
  import type { WatchMode } from "esbuild";
10
12
 
11
13
  export type EsbuildBundle = {
12
- id: number;
13
- path: string;
14
- entry: Entry;
15
- type: "esm" | "commonjs";
16
- modules: CfModule[];
17
- serveAssetsFromWorker: boolean;
14
+ id: number;
15
+ path: string;
16
+ entry: Entry;
17
+ type: "esm" | "commonjs";
18
+ modules: CfModule[];
19
+ sourceMapPath: string | undefined;
18
20
  };
19
21
 
20
22
  export function useEsbuild({
21
- entry,
22
- destination,
23
- staticRoot,
24
- jsxFactory,
25
- jsxFragment,
26
- rules,
27
- serveAssetsFromWorker,
28
- tsconfig,
29
- minify,
30
- nodeCompat,
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,
31
39
  }: {
32
- entry: Entry;
33
- destination: string | undefined;
34
- staticRoot: string | undefined;
35
- jsxFactory: string | undefined;
36
- jsxFragment: string | undefined;
37
- rules: Config["rules"];
38
- serveAssetsFromWorker: boolean;
39
- tsconfig: string | undefined;
40
- minify: boolean | undefined;
41
- nodeCompat: boolean | undefined;
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;
42
56
  }): EsbuildBundle | undefined {
43
- const [bundle, setBundle] = useState<EsbuildBundle>();
44
- const { exit } = useApp();
45
- useEffect(() => {
46
- let stopWatching: (() => void) | undefined = undefined;
57
+ const [bundle, setBundle] = useState<EsbuildBundle>();
58
+ const { exit } = useApp();
59
+ useEffect(() => {
60
+ let stopWatching: (() => void) | undefined = undefined;
47
61
 
48
- const watchMode: WatchMode = {
49
- async onRebuild(error) {
50
- if (error) logger.error("Watch build failed:", error);
51
- else {
52
- // nothing really changes here, so let's increment the id
53
- // to change the return object's identity
54
- setBundle((previousBundle) => {
55
- assert(
56
- previousBundle,
57
- "Rebuild triggered with no previous build available"
58
- );
59
- return { ...previousBundle, id: previousBundle.id + 1 };
60
- });
61
- }
62
- },
63
- };
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
+ }
64
73
 
65
- async function build() {
66
- 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
+ };
67
82
 
68
- const { resolvedEntryPointPath, bundleType, modules, stop } =
69
- await bundleWorker(entry, destination, {
70
- // In dev, we serve assets from the local proxy before we send the request to the worker.
71
- serveAssetsFromWorker: false,
72
- jsxFactory,
73
- jsxFragment,
74
- rules,
75
- watch: watchMode,
76
- tsconfig,
77
- minify,
78
- nodeCompat,
79
- });
83
+ async function build() {
84
+ if (!destination) return;
80
85
 
81
- // Capture the `stop()` method to use as the `useEffect()` destructor.
82
- 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
+ });
83
120
 
84
- setBundle({
85
- id: 0,
86
- entry,
87
- path: resolvedEntryPointPath,
88
- type: bundleType,
89
- modules,
90
- serveAssetsFromWorker,
91
- });
92
- }
121
+ // Capture the `stop()` method to use as the `useEffect()` destructor.
122
+ stopWatching = stop;
93
123
 
94
- build().catch((err) => {
95
- // If esbuild fails on first run, we want to quit the process
96
- // since we can't recover from here
97
- // related: https://github.com/evanw/esbuild/issues/1037
98
- exit(err);
99
- });
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
+ });
100
132
 
101
- return () => {
102
- stopWatching?.();
103
- };
104
- }, [
105
- entry,
106
- destination,
107
- staticRoot,
108
- jsxFactory,
109
- jsxFragment,
110
- serveAssetsFromWorker,
111
- rules,
112
- tsconfig,
113
- exit,
114
- minify,
115
- nodeCompat,
116
- ]);
117
- 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;
118
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
+ }