wrangler 0.0.0-e1c615f → 0.0.0-e3cab74

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 (85) hide show
  1. package/bin/wrangler.js +2 -2
  2. package/package.json +28 -13
  3. package/pages/functions/buildWorker.ts +6 -1
  4. package/pages/functions/filepath-routing.test.ts +112 -28
  5. package/pages/functions/filepath-routing.ts +88 -131
  6. package/pages/functions/routes.ts +11 -18
  7. package/pages/functions/template-worker.ts +21 -28
  8. package/src/__tests__/configuration.test.ts +2185 -0
  9. package/src/__tests__/dev.test.tsx +56 -9
  10. package/src/__tests__/guess-worker-format.test.ts +66 -0
  11. package/src/__tests__/{clipboardy-mock.js → helpers/clipboardy-mock.js} +0 -0
  12. package/src/__tests__/helpers/cmd-shim.d.ts +11 -0
  13. package/src/__tests__/helpers/faye-websocket.d.ts +6 -0
  14. package/src/__tests__/helpers/mock-account-id.ts +30 -0
  15. package/src/__tests__/helpers/mock-bin.ts +36 -0
  16. package/src/__tests__/{mock-cfetch.ts → helpers/mock-cfetch.ts} +53 -17
  17. package/src/__tests__/helpers/mock-console.ts +62 -0
  18. package/src/__tests__/{mock-dialogs.ts → helpers/mock-dialogs.ts} +1 -1
  19. package/src/__tests__/helpers/mock-kv.ts +40 -0
  20. package/src/__tests__/helpers/mock-user.ts +27 -0
  21. package/src/__tests__/helpers/mock-web-socket.ts +29 -0
  22. package/src/__tests__/helpers/run-in-tmp.ts +29 -0
  23. package/src/__tests__/helpers/run-wrangler.ts +16 -0
  24. package/src/__tests__/helpers/write-wrangler-toml.ts +17 -0
  25. package/src/__tests__/index.test.ts +655 -76
  26. package/src/__tests__/jest.setup.ts +37 -2
  27. package/src/__tests__/kv.test.ts +441 -398
  28. package/src/__tests__/logout.test.ts +50 -0
  29. package/src/__tests__/package-manager.test.ts +206 -0
  30. package/src/__tests__/parse.test.ts +322 -0
  31. package/src/__tests__/publish.test.ts +2406 -0
  32. package/src/__tests__/r2.test.ts +198 -0
  33. package/src/__tests__/secret.test.ts +326 -0
  34. package/src/__tests__/sentry.test.ts +146 -0
  35. package/src/__tests__/tail.test.ts +564 -0
  36. package/src/__tests__/whoami.test.tsx +86 -0
  37. package/src/api/form_data.ts +112 -26
  38. package/src/api/preview.ts +34 -15
  39. package/src/api/worker.ts +58 -27
  40. package/src/bundle.ts +133 -0
  41. package/src/cfetch/index.ts +21 -19
  42. package/src/cfetch/internal.ts +85 -21
  43. package/src/cli.ts +10 -0
  44. package/src/config/README.md +107 -0
  45. package/src/config/config.ts +265 -0
  46. package/src/config/diagnostics.ts +80 -0
  47. package/src/config/environment.ts +305 -0
  48. package/src/config/index.ts +52 -0
  49. package/src/config/validation-helpers.ts +370 -0
  50. package/src/config/validation.ts +1017 -0
  51. package/src/dev.tsx +455 -368
  52. package/src/dialogs.tsx +2 -2
  53. package/src/entry.ts +57 -0
  54. package/src/environment-variables.ts +33 -0
  55. package/src/guess-worker-format.ts +68 -0
  56. package/src/index.tsx +1044 -646
  57. package/src/inspect.ts +609 -0
  58. package/src/kv.tsx +47 -39
  59. package/src/module-collection.ts +142 -36
  60. package/src/open-in-browser.ts +13 -0
  61. package/src/package-manager.ts +126 -0
  62. package/src/pages.tsx +139 -62
  63. package/src/parse.ts +183 -0
  64. package/src/paths.ts +26 -0
  65. package/src/proxy.ts +350 -77
  66. package/src/publish.ts +307 -289
  67. package/src/r2.ts +50 -0
  68. package/src/reporting.ts +115 -0
  69. package/src/sites.tsx +183 -56
  70. package/src/tail/filters.ts +279 -0
  71. package/src/tail/index.ts +299 -0
  72. package/src/tail/printing.ts +62 -0
  73. package/src/user.tsx +137 -110
  74. package/src/whoami.tsx +69 -0
  75. package/templates/new-worker.js +15 -0
  76. package/templates/new-worker.ts +15 -0
  77. package/{static-asset-facade.js → templates/static-asset-facade.js} +0 -0
  78. package/templates/tsconfig.json +105 -0
  79. package/wrangler-dist/cli.js +127861 -111486
  80. package/wrangler-dist/cli.js.map +3 -3
  81. package/src/__tests__/run-in-tmp.ts +0 -19
  82. package/src/__tests__/run-wrangler.ts +0 -32
  83. package/src/api/inspect.ts +0 -430
  84. package/src/config.ts +0 -131
  85. package/src/tail.tsx +0 -73
@@ -1,19 +0,0 @@
1
- import * as os from "node:os";
2
- import * as path from "node:path";
3
- import * as fs from "fs";
4
-
5
- const originalCwd = process.cwd();
6
-
7
- export function runInTempDir() {
8
- let tmpDir: string;
9
-
10
- beforeEach(() => {
11
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "wrangler-tests"));
12
- process.chdir(tmpDir);
13
- });
14
-
15
- afterEach(() => {
16
- process.chdir(originalCwd);
17
- fs.rmSync(tmpDir, { recursive: true });
18
- });
19
- }
@@ -1,32 +0,0 @@
1
- import { main } from "../index";
2
-
3
- /**
4
- * Run the wrangler CLI tool in tests, capturing the logging output.
5
- */
6
- export async function runWrangler(cmd?: string) {
7
- const logSpy = jest.spyOn(console, "log").mockImplementation();
8
- const errorSpy = jest.spyOn(console, "error").mockImplementation();
9
- const warnSpy = jest.spyOn(console, "warn").mockImplementation();
10
- try {
11
- let error: unknown = undefined;
12
- try {
13
- await main(cmd?.split(" ") ?? []);
14
- } catch (e) {
15
- error = e;
16
- }
17
- return {
18
- error,
19
- stdout: captureCalls(logSpy),
20
- stderr: captureCalls(errorSpy),
21
- warnings: captureCalls(warnSpy),
22
- };
23
- } finally {
24
- logSpy.mockRestore();
25
- errorSpy.mockRestore();
26
- warnSpy.mockRestore();
27
- }
28
- }
29
-
30
- function captureCalls(spy: jest.SpyInstance): string {
31
- return spy.mock.calls.flat(2).join("\n");
32
- }
@@ -1,430 +0,0 @@
1
- import { Response, Request, Headers } from "node-fetch";
2
- import type { MessageEvent } from "ws";
3
- import WebSocket, { WebSocketServer } from "ws";
4
- import type { IncomingMessage, ServerResponse } from "http";
5
- import { createServer } from "http";
6
-
7
- /**
8
- * A call frame.
9
- *
10
- * @link https://chromedevtools.github.io/devtools-protocol/1-3/Runtime/#type-CallFrame
11
- */
12
- export interface DtCallFrame {
13
- /**
14
- * The module path.
15
- *
16
- * @example
17
- * 'worker.js'
18
- */
19
- url: string;
20
- /**
21
- * The function name.
22
- */
23
- functionName?: string;
24
- /**
25
- * The line number. (0-based)
26
- */
27
- lineNumber: number;
28
- /**
29
- * The column number. (0-based)
30
- */
31
- columnNumber: number;
32
- }
33
-
34
- /**
35
- * A stack trace.
36
- *
37
- * @link https://chromedevtools.github.io/devtools-protocol/1-3/Runtime/#type-StackTrace
38
- */
39
- export interface DtStackTrace {
40
- /**
41
- * A description of the stack, only present in certain contexts.
42
- */
43
- description?: string;
44
- /**
45
- * The call frames.
46
- */
47
- callFrames: DtCallFrame[];
48
- /**
49
- * The parent stack trace.
50
- */
51
- parent?: DtStackTrace;
52
- }
53
-
54
- /**
55
- * A JavaScript object type.
56
- */
57
- export type DtRemoteObjectType =
58
- | "object"
59
- | "function"
60
- | "undefined"
61
- | "string"
62
- | "number"
63
- | "boolean"
64
- | "symbol"
65
- | "bigint";
66
-
67
- /**
68
- * A view of a remote JavaScript object.
69
- *
70
- * @link https://chromedevtools.github.io/devtools-protocol/1-3/Runtime/#type-RemoteObject
71
- */
72
- export interface DtRemoteObject<T> {
73
- /**
74
- * The object type.
75
- *
76
- * @example
77
- * 'string'
78
- */
79
- type: DtRemoteObjectType;
80
- /**
81
- * The specific object type, if the type is `object`.
82
- *
83
- * @example
84
- * 'arraybuffer'
85
- */
86
- subtype?: string;
87
- /**
88
- * The class name, if the type if `object`.
89
- */
90
- className?: string;
91
- /**
92
- * The object as a string.
93
- *
94
- * @example
95
- * 'Array(1)'
96
- * 'TypeError: Oops!\n at worker.js:5:15'
97
- */
98
- description?: string;
99
- /**
100
- * The object.
101
- */
102
- value?: T;
103
- // TODO(soon): add a preview field for more complex types
104
- }
105
-
106
- /**
107
- * An event when `console.log()` is invoked.
108
- *
109
- * @link https://chromedevtools.github.io/devtools-protocol/1-3/Runtime/#event-consoleAPICalled
110
- */
111
- export interface DtLogEvent {
112
- timestamp: number;
113
- type: string;
114
- args: DtRemoteObject<unknown>[];
115
- stackTrace?: DtStackTrace;
116
- }
117
-
118
- /**
119
- * An event when an uncaught `Error` is thrown.
120
- *
121
- * @link https://chromedevtools.github.io/devtools-protocol/1-3/Runtime/#event-exceptionThrown
122
- */
123
- export interface DtExceptionEvent {
124
- timestamp: number;
125
- exceptionDetails: {
126
- lineNumber: number;
127
- columnNumber: number;
128
- exception: DtRemoteObject<Error>;
129
- stackTrace: DtStackTrace;
130
- };
131
- }
132
-
133
- /**
134
- * A DevTools event.
135
- */
136
- export type DtEvent = DtLogEvent | DtExceptionEvent;
137
-
138
- /**
139
- * A listener that receives DevTools events.
140
- */
141
- export type DtListener = (event: DtEvent) => void;
142
-
143
- /**
144
- * A DevTools inspector that listens to logs and debug events from a Worker.
145
- *
146
- * @example
147
- * const worker: CfWorker
148
- * const inspector: DtInspector = await worker.inspect()
149
- *
150
- * @link https://chromedevtools.github.io/devtools-protocol/
151
- */
152
- export class DtInspector {
153
- #webSocket: WebSocket;
154
- #keepAlive?: NodeJS.Timer;
155
-
156
- constructor(url: string) {
157
- // this.#events = [];
158
- // this.#listeners = [];
159
- this.#webSocket = new WebSocket(url);
160
- this.#webSocket.onopen = () => {
161
- this.enable();
162
- };
163
- this.#webSocket.onclose = () => {
164
- this.disable();
165
- };
166
- this.#webSocket.on("unexpected-response", () => {
167
- console.log("504??"); // TODO: refactor this class to start again
168
- });
169
- this.#webSocket.onmessage = (event: MessageEvent) => {
170
- // TODO: this seems unnecessary, unless we're planning
171
- // on logging to console. We'll see.
172
- if (typeof event.data === "string") {
173
- // this.recv(JSON.parse(event.data));
174
- } else {
175
- // ??
176
- }
177
- };
178
- }
179
-
180
- /**
181
- * Exposes a websocket proxy on a localhost port.
182
- */
183
- proxyTo(port: number): AbortController {
184
- return bind(new DtInspectorBridge(this.#webSocket, port), port);
185
- }
186
-
187
- /**
188
- * If the inspector is closed.
189
- */
190
- get closed(): boolean {
191
- return this.#webSocket.readyState === WebSocket.CLOSED;
192
- }
193
-
194
- /**
195
- * Closes the inspector.
196
- */
197
- close(): void {
198
- if (!this.closed) {
199
- try {
200
- this.#webSocket.close();
201
- } catch (err) {
202
- // Closing before the websocket is ready will throw an error.
203
- }
204
- }
205
- // this.#events = [];
206
- }
207
-
208
- private send(event: Record<string, unknown>): void {
209
- if (!this.closed) {
210
- this.#webSocket.send(JSON.stringify(event));
211
- }
212
- }
213
-
214
- private enable(): void {
215
- let id = 1;
216
- this.send({ method: "Runtime.enable", id });
217
- this.#keepAlive = setInterval(() => {
218
- this.send({ method: "Runtime.getIsolateId", id: id++ });
219
- }, 10_000);
220
- }
221
-
222
- private disable(): void {
223
- if (this.#keepAlive) {
224
- clearInterval(this.#keepAlive);
225
- this.#keepAlive = undefined;
226
- }
227
- }
228
- }
229
-
230
- /**
231
- * A HTTP server that responds to `fetch()` requests.
232
- */
233
- interface FetchServer {
234
- /**
235
- * Responds to a request.
236
- */
237
- fetch(request: Request): Promise<Response>;
238
- /**
239
- * Accepts a websocket connection.
240
- */
241
- upgrade?(webSocket: WebSocket): void;
242
- }
243
-
244
- /**
245
- * A bridge between a remote DevTools inspector and Chrome.
246
- *
247
- * Exposes a localhost HTTP server that responds to informational requests
248
- * from Chrome about the DevTools inspector. Then, when it receives a
249
- * WebSocket upgrade, forwards the connection to the remote inspector.
250
- */
251
- class DtInspectorBridge implements FetchServer {
252
- #webSocket: WebSocket;
253
- #localPort: number;
254
- #connected: boolean;
255
-
256
- constructor(webSocket: WebSocket, localPort?: number) {
257
- this.#webSocket = webSocket;
258
- this.#localPort = localPort;
259
- this.#connected = false;
260
- }
261
-
262
- async fetch(request: Request): Promise<Response> {
263
- const { url } = request;
264
- const { pathname } = new URL(url);
265
- switch (pathname) {
266
- case "/json/version":
267
- return this.version;
268
- case "/json":
269
- case "/json/list":
270
- return this.location;
271
- default:
272
- break;
273
- }
274
- return new Response("Not Found", { status: 404 });
275
- }
276
-
277
- upgrade(webSocket: WebSocket): void {
278
- if (this.#connected) {
279
- webSocket.close(
280
- 1013,
281
- "Too many clients; only one can be connected at a time"
282
- );
283
- } else {
284
- this.#connected = true;
285
- webSocket.addEventListener("close", () => (this.#connected = false));
286
- proxyWebSocket(webSocket, this.#webSocket);
287
- }
288
- }
289
-
290
- private get version(): Response {
291
- const headers = { "Content-Type": "application/json" };
292
- const body = {
293
- Browser: "workers-run/v0.0.0", // TODO: this should pick up version from package.json
294
- // TODO: (someday): The DevTools protocol should match that of edgeworker.
295
- // This could be exposed by the preview API.
296
- "Protocol-Version": "1.3",
297
- };
298
- return new Response(JSON.stringify(body), { headers });
299
- }
300
-
301
- private get location(): Response {
302
- const headers = { "Content-Type": "application/json" };
303
- const localHost = `localhost:${this.#localPort}/ws`;
304
- const devtoolsFrontendUrl = `devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=${localHost}`;
305
- const devtoolsFrontendUrlCompat = `devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=${localHost}`;
306
- const body = [
307
- {
308
- id: randomId(),
309
- type: "node",
310
- description: "workers",
311
- webSocketDebuggerUrl: `ws://${localHost}`,
312
- devtoolsFrontendUrl,
313
- devtoolsFrontendUrlCompat,
314
- // Below are fields that are visible in the DevTools UI.
315
- title: "Cloudflare Worker",
316
- faviconUrl: "https://workers.cloudflare.com/favicon.ico",
317
- url: "https://" + new URL(this.#webSocket.url).host,
318
- },
319
- ];
320
- return new Response(JSON.stringify(body), { headers });
321
- }
322
- }
323
-
324
- function bind(fetcher: FetchServer, port?: number): AbortController {
325
- const controller = new AbortController();
326
-
327
- const server = createServer(
328
- (input: IncomingMessage, output: ServerResponse) =>
329
- toRequest(input)
330
- .then((request) => fetcher.fetch(request))
331
- .then((response) => toResponse(response, output))
332
- .catch((error) => console.error(error))
333
- );
334
-
335
- if (fetcher.upgrade) {
336
- const webSocket = new WebSocketServer({ server });
337
- webSocket.on("connection", (ws: WebSocket) => fetcher.upgrade(ws));
338
- }
339
-
340
- const socket = server.listen({ port });
341
- controller.signal.onabort = () => {
342
- server.close();
343
- socket.close();
344
- };
345
- return controller;
346
- }
347
-
348
- /**
349
- * Converts a Node.js request to a Web standard `Request`.
350
- */
351
- async function toRequest(request: IncomingMessage): Promise<Request> {
352
- const host = request.headers.host ?? "localhost";
353
- const { href } = new URL(request.url, "http://" + host);
354
-
355
- const { rawHeaders, method } = request;
356
- const headers = new Headers();
357
- for (let i = 0; i < rawHeaders.length; i += 2) {
358
- headers.append(rawHeaders[i], rawHeaders[i + 1]);
359
- }
360
-
361
- return new Promise((resolve, reject) => {
362
- const chunks = [];
363
- request.on("data", (chunk) => chunks.push(chunk));
364
- request.on("error", (error) => reject(error));
365
- request.on("end", () => {
366
- const buffer = Buffer.concat(chunks);
367
- const body = buffer.length === 0 ? undefined : buffer;
368
- resolve(new Request(href, { method, headers, body }));
369
- });
370
- });
371
- }
372
-
373
- /**
374
- * Converts a Web standard `Response` into a Node.js response.
375
- */
376
- async function toResponse(
377
- input: Response,
378
- response: ServerResponse
379
- ): Promise<void> {
380
- const { status, statusText, headers, body: hasBody } = input;
381
-
382
- for (const [name, value] of headers.entries()) {
383
- response.setHeader(name, value);
384
- }
385
-
386
- let body: Uint8Array;
387
- if (hasBody) {
388
- body = new Uint8Array(await input.arrayBuffer());
389
- response.setHeader("Content-Length", body.byteLength);
390
- }
391
-
392
- response.writeHead(status, statusText);
393
- response.write(body);
394
- }
395
-
396
- /**
397
- * Creates a proxy bridge between two websockets.
398
- */
399
- function proxyWebSocket(webSocket: WebSocket, otherSocket: WebSocket): void {
400
- webSocket.addEventListener("message", (event: MessageEvent) => {
401
- try {
402
- otherSocket.send(event.data);
403
- } catch (e) {
404
- if (e.message !== "WebSocket is not open: readyState 0 (CONNECTING)") {
405
- // this just means we haven't opened a websocket yet
406
- // usually happens until there's at least one request
407
- // which is weird, because we may miss something that happens on
408
- // the first request
409
- console.error(e);
410
- }
411
- }
412
- });
413
- otherSocket.addEventListener("message", (event: MessageEvent) =>
414
- webSocket.send(event.data)
415
- );
416
-
417
- // Some close codes are marked as 'reserved' and will throw an error if used.
418
- // Therefore, it's not worth the effort to passthrough the close code and reason.
419
- webSocket.addEventListener("close", () => otherSocket.close());
420
- otherSocket.addEventListener("close", () => webSocket.close());
421
- }
422
-
423
- // Credit: https://stackoverflow.com/a/2117523
424
- function randomId(): string {
425
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
426
- const r = (Math.random() * 16) | 0,
427
- v = c == "x" ? r : (r & 0x3) | 0x8;
428
- return v.toString(16);
429
- });
430
- }
package/src/config.ts DELETED
@@ -1,131 +0,0 @@
1
- // we're going to manually write both the type definition AND
2
- // the validator for the config, so that we can give better error messages
3
-
4
- type DurableObjectMigration = {
5
- tag: string;
6
- new_classes?: string[];
7
- renamed_classes?: string[];
8
- deleted_classes?: string[];
9
- };
10
-
11
- type Project = "webpack" | "javascript" | "rust";
12
-
13
- type Site = {
14
- // inherited
15
- bucket: string;
16
- "entry-point": string;
17
- include?: string[];
18
- exclude?: string[];
19
- };
20
-
21
- type Dev = {
22
- ip?: string;
23
- port?: number;
24
- local_protocol?: string;
25
- upstream_protocol?: string;
26
- };
27
-
28
- export type Vars = { [key: string]: string };
29
-
30
- type Cron = string; // TODO: we should be able to parse a cron pattern with ts
31
-
32
- type KVNamespace = {
33
- binding: string;
34
- preview_id?: string;
35
- id: string;
36
- };
37
-
38
- type DurableObject = {
39
- name: string;
40
- class_name: string;
41
- script_name?: string;
42
- };
43
-
44
- type Service = {
45
- name: string;
46
- service: string;
47
- environment: string;
48
- };
49
-
50
- type Build = {
51
- command?: string;
52
- cwd?: string;
53
- watch_dir?: string;
54
- } & (
55
- | {
56
- upload?: {
57
- format: "service-worker";
58
- main: string;
59
- };
60
- }
61
- | {
62
- upload?: {
63
- format: "modules";
64
- dir?: string;
65
- main?: string;
66
- rules?: {
67
- type: "ESModule" | "CommonJS" | "Text" | "Data" | "CompiledWasm";
68
- globs: string[]; // can we use typescript for these patterns?
69
- fallthrough?: boolean;
70
- };
71
- };
72
- }
73
- );
74
-
75
- type UsageModel = "bundled" | "unbound";
76
-
77
- type Env = {
78
- name?: string; // inherited
79
- account_id?: string; // inherited
80
- workers_dev?: boolean; // inherited
81
- compatibility_date?: string; // inherited
82
- compatibility_flags?: string[]; // inherited
83
- zone_id?: string; // inherited
84
- routes?: string[]; // inherited
85
- route?: string; // inherited
86
- webpack_config?: string; // inherited
87
- site?: Site;
88
- jsx_factory?: string; // inherited
89
- jsx_fragment?: string; // inherited
90
- // we should use typescript to parse cron patterns
91
- triggers?: { crons: Cron[] }; // inherited
92
- vars?: Vars;
93
- durable_objects?: { bindings: DurableObject[] };
94
- kv_namespaces?: KVNamespace[];
95
- experimental_services?: Service[];
96
- migrations?: DurableObjectMigration[];
97
- usage_model?: UsageModel; // inherited
98
- };
99
-
100
- export type Config = {
101
- name?: string; // inherited
102
- account_id?: string; // inherited
103
- // @deprecated Don't use this
104
- type?: Project; // top level
105
- compatibility_date?: string; // inherited
106
- compatibility_flags?: string[]; // inherited
107
- // -- there's some mutually exclusive logic for this next block,
108
- // but I didn't bother for now
109
- workers_dev?: boolean; // inherited
110
- zone_id?: string; // inherited
111
- routes?: string[]; // inherited
112
- route?: string; // inherited
113
- // -- end mutually exclusive stuff
114
- // @deprecated Don't use this
115
- webpack_config?: string; // inherited
116
- jsx_factory?: string; // inherited
117
- jsx_fragment?: string; // inherited
118
- vars?: Vars;
119
- durable_objects?: { bindings: DurableObject[] };
120
- kv_namespaces?: KVNamespace[];
121
- experimental_services?: Service[];
122
- migrations?: DurableObjectMigration[];
123
- site?: Site; // inherited
124
- // we should use typescript to parse cron patterns
125
- triggers?: { crons: Cron[] }; // inherited
126
- dev?: Dev;
127
- usage_model?: UsageModel; // inherited
128
- // top level
129
- build?: Build;
130
- env?: { [envName: string]: void | Env };
131
- };
package/src/tail.tsx DELETED
@@ -1,73 +0,0 @@
1
- import WebSocket from "ws";
2
- import { version as packageVersion } from "../package.json";
3
- import { fetchResult } from "./cfetch";
4
-
5
- export type TailApiResponse = {
6
- id: string;
7
- url: string;
8
- expires_at: Date;
9
- };
10
-
11
- function makeCreateTailUrl(accountId: string, workerName: string): string {
12
- return `/accounts/${accountId}/workers/scripts/${workerName}/tails`;
13
- }
14
-
15
- function makeDeleteTailUrl(
16
- accountId: string,
17
- workerName: string,
18
- tailId: string
19
- ): string {
20
- return `/accounts/${accountId}/workers/scripts/${workerName}/tails/${tailId}`;
21
- }
22
-
23
- /// Creates a tail, but doesn't connect to it.
24
- async function createTailButDontConnect(
25
- accountId: string,
26
- workerName: string
27
- ): Promise<TailApiResponse> {
28
- const createTailUrl = makeCreateTailUrl(accountId, workerName);
29
- /// https://api.cloudflare.com/#worker-tail-logs-start-tail
30
- return await fetchResult<TailApiResponse>(createTailUrl, {
31
- method: "POST",
32
- });
33
- }
34
-
35
- export async function createTail(
36
- accountId: string,
37
- workerName: string,
38
- _filters: Filters
39
- ): Promise<{
40
- tail: WebSocket;
41
- expiration: Date;
42
- deleteTail: () => Promise<void>;
43
- }> {
44
- const {
45
- id: tailId,
46
- url: websocketUrl,
47
- expires_at: expiration,
48
- } = await createTailButDontConnect(accountId, workerName);
49
- const deleteUrl = makeDeleteTailUrl(accountId, workerName, tailId);
50
-
51
- // deletes the tail
52
- async function deleteTail() {
53
- await fetchResult(deleteUrl, { method: "DELETE" });
54
- }
55
-
56
- const tail = new WebSocket(websocketUrl, "trace-v1", {
57
- headers: {
58
- "Sec-WebSocket-Protocol": "trace-v1", // needs to be `trace-v1` to be accepted
59
- "User-Agent": `wrangler-js/${packageVersion}`,
60
- },
61
- });
62
-
63
- // TODO: send filters as well
64
- return { tail, expiration, deleteTail };
65
- }
66
-
67
- export type Filters = {
68
- status?: "ok" | "error" | "canceled";
69
- header?: string;
70
- method?: string;
71
- "sampling-rate"?: number;
72
- search?: string;
73
- };