wrangler 0.0.0-e98613f8 → 0.0.0-e9a45766c
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.
- package/README.md +10 -4
- package/bin/wrangler.js +10 -2
- package/miniflare-dist/index.mjs +257 -132
- package/package.json +26 -19
- package/src/__tests__/api-dev.test.ts +65 -36
- package/src/__tests__/api-devregistry.test.ts +121 -0
- package/src/__tests__/api.test.ts +27 -5
- package/src/__tests__/configuration.test.ts +575 -39
- package/src/__tests__/constellation.test.ts +371 -0
- package/src/__tests__/d1/d1.test.ts +82 -0
- package/src/__tests__/d1/execute.test.ts +66 -0
- package/src/__tests__/d1/migrate.test.ts +257 -0
- package/src/__tests__/d1/splitter.test.ts +255 -0
- package/src/__tests__/delete.test.ts +11 -2
- package/src/__tests__/deployments.test.ts +330 -52
- package/src/__tests__/dev.test.tsx +146 -82
- package/src/__tests__/generate.test.ts +10 -8
- package/src/__tests__/guess-worker-format.test.ts +35 -0
- package/src/__tests__/helpers/end-event-loop.ts +6 -0
- package/src/__tests__/helpers/mock-auth-domain.ts +20 -0
- package/src/__tests__/helpers/mock-console.ts +6 -0
- package/src/__tests__/helpers/mock-dialogs.ts +71 -85
- package/src/__tests__/helpers/mock-get-pages-upload-token.ts +25 -0
- package/src/__tests__/helpers/mock-get-zone-from-host.ts +8 -5
- package/src/__tests__/helpers/mock-known-routes.ts +7 -2
- package/src/__tests__/helpers/mock-kv.ts +29 -16
- package/src/__tests__/helpers/mock-oauth-flow.ts +99 -92
- package/src/__tests__/helpers/mock-process.ts +8 -13
- package/src/__tests__/helpers/mock-set-timeout.ts +16 -0
- package/src/__tests__/helpers/msw/blob-worker.cjs +19 -0
- package/src/__tests__/helpers/msw/handlers/deployments.ts +127 -26
- package/src/__tests__/helpers/msw/handlers/namespaces.ts +18 -41
- package/src/__tests__/helpers/msw/handlers/r2.ts +14 -34
- package/src/__tests__/helpers/msw/handlers/script.ts +9 -28
- package/src/__tests__/helpers/msw/handlers/user.ts +13 -24
- package/src/__tests__/helpers/msw/handlers/zones.ts +6 -8
- package/src/__tests__/helpers/msw/index.ts +32 -1
- package/src/__tests__/helpers/msw/read-file-sync.js +61 -0
- package/src/__tests__/helpers/string-dynamic-values-matcher.ts +28 -0
- package/src/__tests__/helpers/worker-scripts/parent-worker.js +4 -1
- package/src/__tests__/index.test.ts +92 -74
- package/src/__tests__/init.test.ts +909 -628
- package/src/__tests__/jest.setup.ts +19 -42
- package/src/__tests__/kv.test.ts +355 -231
- package/src/__tests__/logger.test.ts +68 -2
- package/src/__tests__/logout.test.ts +1 -1
- package/src/__tests__/metrics.test.ts +93 -50
- package/src/__tests__/middleware.scheduled.test.ts +42 -32
- package/src/__tests__/middleware.test.ts +212 -122
- package/src/__tests__/mtls-certificates.test.ts +589 -0
- package/src/__tests__/pages/deployment-list.test.ts +80 -0
- package/src/__tests__/pages/functions-build.test.ts +528 -0
- package/src/__tests__/pages/pages.test.ts +81 -0
- package/src/__tests__/pages/project-create.test.ts +63 -0
- package/src/__tests__/pages/project-list.test.ts +110 -0
- package/src/__tests__/pages/project-upload.test.ts +500 -0
- package/src/__tests__/pages/publish.test.ts +2864 -0
- package/src/__tests__/pages-deployment-tail.test.ts +239 -102
- package/src/__tests__/parse.test.ts +106 -0
- package/src/__tests__/publish.test.ts +2218 -1002
- package/src/__tests__/pubsub.test.ts +226 -100
- package/src/__tests__/queues.test.ts +42 -32
- package/src/__tests__/r2.test.ts +37 -56
- package/src/__tests__/secret.test.ts +179 -130
- package/src/__tests__/tail.test.ts +113 -23
- package/src/__tests__/test-old-node-version.js +3 -3
- package/src/__tests__/traverse-module-graph.test.ts +220 -0
- package/src/__tests__/tsconfig-sanity.ts +12 -0
- package/src/__tests__/tsconfig.json +8 -0
- package/src/__tests__/tsconfig.tsbuildinfo +1 -0
- package/src/__tests__/type-generation.test.ts +8 -0
- package/src/__tests__/user.test.ts +7 -18
- package/src/__tests__/whoami.test.tsx +8 -114
- package/src/__tests__/worker-namespace.test.ts +83 -69
- package/src/api/dev.ts +172 -61
- package/src/api/index.ts +10 -1
- package/src/api/mtls-certificate.ts +148 -0
- package/src/api/pages/create-worker-bundle-contents.ts +77 -0
- package/src/api/pages/index.ts +5 -0
- package/src/api/pages/publish.tsx +371 -0
- package/src/bundle.ts +139 -33
- package/src/cfetch/index.ts +0 -2
- package/src/cfetch/internal.ts +16 -21
- package/src/cli.ts +4 -4
- package/src/config/config.ts +14 -7
- package/src/config/environment.ts +80 -16
- package/src/config/index.ts +99 -30
- package/src/config/validation-helpers.ts +1 -1
- package/src/config/validation.ts +275 -9
- package/src/constellation/createProject.tsx +51 -0
- package/src/constellation/deleteProject.ts +51 -0
- package/src/constellation/deleteProjectModel.ts +68 -0
- package/src/constellation/index.ts +75 -0
- package/src/constellation/listCatalog.tsx +35 -0
- package/src/constellation/listModel.tsx +41 -0
- package/src/constellation/listProject.tsx +28 -0
- package/src/constellation/listRuntime.tsx +28 -0
- package/src/constellation/options.ts +17 -0
- package/src/constellation/types.ts +17 -0
- package/src/constellation/uploadModel.tsx +64 -0
- package/src/constellation/utils.ts +90 -0
- package/src/create-worker-preview.ts +19 -8
- package/src/create-worker-upload-form.ts +52 -5
- package/src/d1/backups.tsx +40 -44
- package/src/d1/create.tsx +50 -43
- package/src/d1/{delete.tsx → delete.ts} +8 -11
- package/src/d1/execute.tsx +171 -166
- package/src/d1/index.ts +5 -6
- package/src/d1/list.tsx +27 -13
- package/src/d1/migrations/apply.tsx +92 -64
- package/src/d1/migrations/create.tsx +31 -29
- package/src/d1/migrations/helpers.ts +66 -44
- package/src/d1/migrations/list.tsx +47 -31
- package/src/d1/migrations/options.ts +7 -2
- package/src/d1/options.ts +3 -3
- package/src/d1/splitter.ts +161 -0
- package/src/d1/{types.tsx → types.ts} +1 -0
- package/src/d1/utils.ts +2 -1
- package/src/delete.ts +8 -16
- package/src/deployments.ts +333 -42
- package/src/deprecated/index.ts +8 -302
- package/src/dev/dev.tsx +13 -22
- package/src/dev/local.tsx +131 -69
- package/src/dev/remote.tsx +35 -3
- package/src/dev/start-server.ts +83 -77
- package/src/dev/use-esbuild.ts +63 -52
- package/src/dev/validate-dev-props.ts +9 -0
- package/src/{dev-registry.tsx → dev-registry.ts} +9 -8
- package/src/dev.tsx +131 -110
- package/src/dialogs.ts +136 -0
- package/src/dispatch-namespace.ts +21 -17
- package/src/docs/helpers.ts +50 -0
- package/src/docs/index.ts +54 -0
- package/src/entry.ts +26 -11
- package/src/environment-variables/factory.ts +89 -0
- package/src/environment-variables/misc-variables.ts +30 -0
- package/src/generate/index.ts +298 -0
- package/src/{index.tsx → index.ts} +137 -56
- package/src/init.ts +254 -187
- package/src/inspect.ts +170 -9
- package/src/jest.d.ts +4 -0
- package/src/kv/helpers.ts +7 -4
- package/src/kv/index.ts +15 -17
- package/src/logger.ts +36 -5
- package/src/metrics/metrics-config.ts +1 -1
- package/src/metrics/send-event.ts +4 -1
- package/src/miniflare-cli/assets.ts +66 -31
- package/src/miniflare-cli/index.ts +5 -8
- package/src/miniflare-cli/tsconfig.json +9 -0
- package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -0
- package/src/miniflare-cli/types.ts +11 -0
- package/src/module-collection.ts +92 -26
- package/src/mtls-certificate/cli.ts +155 -0
- package/src/pages/build.ts +423 -0
- package/src/pages/buildFunctions.ts +140 -0
- package/src/pages/{deployment-tails.tsx → deployment-tails.ts} +7 -10
- package/src/pages/deployments.tsx +9 -9
- package/src/pages/{dev.tsx → dev.ts} +167 -139
- package/src/pages/errors.ts +1 -0
- package/src/pages/functions/buildPlugin.ts +61 -54
- package/src/pages/functions/buildWorker.ts +217 -33
- package/src/pages/functions/tsconfig.json +8 -0
- package/src/pages/functions/tsconfig.tsbuildinfo +1 -0
- package/src/pages/{functions.tsx → functions.ts} +8 -4
- package/src/pages/{index.tsx → index.ts} +3 -3
- package/src/pages/projects.tsx +12 -22
- package/src/pages/publish.tsx +43 -227
- package/src/pages/types.ts +5 -0
- package/src/pages/upload.tsx +57 -14
- package/src/pages/utils.ts +1 -1
- package/src/parse.ts +23 -1
- package/src/paths.ts +1 -1
- package/src/publish/index.ts +20 -16
- package/src/publish/publish.ts +76 -46
- package/src/pubsub/{pubsub-commands.tsx → pubsub-commands.ts} +19 -20
- package/src/queues/cli/commands/consumer/add.ts +24 -24
- package/src/queues/cli/commands/consumer/index.ts +3 -6
- package/src/queues/cli/commands/consumer/remove.ts +11 -18
- package/src/queues/cli/commands/create.ts +8 -8
- package/src/queues/cli/commands/delete.ts +8 -8
- package/src/queues/cli/commands/index.ts +3 -4
- package/src/queues/cli/commands/list.ts +8 -8
- package/src/queues/client.ts +1 -0
- package/src/r2/helpers.ts +1 -0
- package/src/r2/index.ts +28 -28
- package/src/secret/index.ts +15 -16
- package/src/{sites.tsx → sites.ts} +165 -53
- package/src/tail/createTail.ts +37 -1
- package/src/tail/filters.ts +1 -1
- package/src/tail/index.ts +8 -11
- package/src/tail/printing.ts +25 -0
- package/src/traverse-module-graph.ts +54 -0
- package/src/tsconfig-sanity.ts +16 -0
- package/src/type-generation.ts +11 -3
- package/src/user/access.ts +0 -1
- package/src/user/auth-variables.ts +113 -0
- package/src/user/choose-account.tsx +1 -31
- package/src/user/index.ts +0 -1
- package/src/user/{user.tsx → user.ts} +114 -77
- package/src/utils/render.ts +93 -0
- package/src/{whoami.tsx → whoami.ts} +37 -71
- package/src/worker.ts +35 -1
- package/src/yargs-types.ts +18 -5
- package/templates/__tests__/tsconfig-sanity.ts +12 -0
- package/templates/__tests__/tsconfig.json +8 -0
- package/templates/__tests__/tsconfig.tsbuildinfo +1 -0
- package/templates/checked-fetch.js +9 -3
- package/templates/d1-beta-facade.js +42 -3
- package/templates/facade.d.ts +14 -0
- package/templates/first-party-worker-module-facade.ts +4 -3
- package/templates/format-dev-errors.ts +8 -6
- package/templates/gitignore +1 -0
- package/templates/init-tests/test-jest-new-worker.js +3 -5
- package/templates/init-tests/test-vitest-new-worker.js +3 -5
- package/templates/init-tests/test-vitest-new-worker.ts +25 -0
- package/templates/middleware/loader-modules.ts +2 -2
- package/templates/middleware/loader-sw.ts +6 -0
- package/templates/middleware/middleware-miniflare3-json-error.ts +17 -5
- package/templates/new-worker.ts +3 -0
- package/templates/pages-dev-pipeline.ts +4 -1
- package/templates/pages-shim.ts +4 -1
- package/templates/pages-template-plugin.ts +19 -10
- package/templates/serve-static-assets.ts +17 -14
- package/templates/service-bindings-module-facade.js +1 -0
- package/templates/tsconfig-sanity.ts +11 -0
- package/templates/tsconfig.init.json +105 -0
- package/templates/tsconfig.json +5 -103
- package/templates/tsconfig.tsbuildinfo +1 -0
- package/wrangler-dist/cli.d.ts +871 -73
- package/wrangler-dist/cli.js +80512 -90686
- package/wrangler-dist/wasm-sync.wasm +0 -0
- package/src/__tests__/api-devregistry.test.js +0 -56
- package/src/__tests__/d1.test.ts +0 -80
- package/src/__tests__/dialogs.test.tsx +0 -40
- package/src/__tests__/helpers/mock-cfetch.ts +0 -333
- package/src/__tests__/pages.test.ts +0 -2442
- package/src/dialogs.tsx +0 -168
- package/src/environment-variables.ts +0 -50
- package/src/pages/build.tsx +0 -270
- package/src/user/env-vars.ts +0 -46
- /package/src/{bundle-reporter.tsx → bundle-reporter.ts} +0 -0
- /package/src/d1/migrations/{index.tsx → index.ts} +0 -0
- /package/src/dev/{get-local-persistence-path.tsx → get-local-persistence-path.ts} +0 -0
- /package/src/pages/{hash.tsx → hash.ts} +0 -0
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { normalizeSlashes } from "./mock-console";
|
|
1
|
+
import prompts from "prompts";
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* The expected values for a confirmation request.
|
|
@@ -7,6 +6,8 @@ import { normalizeSlashes } from "./mock-console";
|
|
|
7
6
|
export interface ConfirmExpectation {
|
|
8
7
|
/** The text expected to be seen in the confirmation dialog. */
|
|
9
8
|
text: string;
|
|
9
|
+
|
|
10
|
+
options?: { defaultValue: boolean };
|
|
10
11
|
/** The mock response send back from the confirmation dialog. */
|
|
11
12
|
result: boolean;
|
|
12
13
|
}
|
|
@@ -19,35 +20,22 @@ export interface ConfirmExpectation {
|
|
|
19
20
|
* then an error is thrown.
|
|
20
21
|
*/
|
|
21
22
|
export function mockConfirm(...expectations: ConfirmExpectation[]) {
|
|
22
|
-
(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
throw new Error(
|
|
34
|
-
"The following expected confirmation dialogs were not used:\n" +
|
|
35
|
-
expectations.map((e) => `- "${e.text}"`).join("\n")
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
}
|
|
23
|
+
for (const expectation of expectations) {
|
|
24
|
+
(prompts as unknown as jest.Mock).mockImplementationOnce(
|
|
25
|
+
({ type, name, message, initial }) => {
|
|
26
|
+
expect({ type, name, message }).toStrictEqual({
|
|
27
|
+
type: "confirm",
|
|
28
|
+
name: "value",
|
|
29
|
+
message: expectation.text,
|
|
30
|
+
});
|
|
31
|
+
if (expectation.options) {
|
|
32
|
+
expect(initial).toStrictEqual(expectation.options?.defaultValue);
|
|
33
|
+
}
|
|
40
34
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
// Because confirm was originally a spy, calling mockReset will simply reset
|
|
44
|
-
// it as a function with no return value (!), so we need to accitionally reset
|
|
45
|
-
// the mock implementation to the one that throws (from jest.setup.js).
|
|
46
|
-
(confirm as jest.Mock).mockImplementation((text: string) => {
|
|
47
|
-
throw new Error(
|
|
48
|
-
`Unexpected call to \`confirm("${text}")\`.\nYou should use \`mockConfirm()\` to mock calls to \`confirm()\` with expectations. Search the codebase for \`mockConfirm\` to learn more.`
|
|
35
|
+
return Promise.resolve({ value: expectation.result });
|
|
36
|
+
}
|
|
49
37
|
);
|
|
50
|
-
}
|
|
38
|
+
}
|
|
51
39
|
}
|
|
52
40
|
|
|
53
41
|
/**
|
|
@@ -57,7 +45,10 @@ export interface PromptExpectation {
|
|
|
57
45
|
/** The text expected to be seen in the prompt dialog. */
|
|
58
46
|
text: string;
|
|
59
47
|
/** The type of the prompt. */
|
|
60
|
-
|
|
48
|
+
options?: {
|
|
49
|
+
defaultValue?: string;
|
|
50
|
+
isSecret?: boolean;
|
|
51
|
+
};
|
|
61
52
|
/** The mock response send back from the prompt dialog. */
|
|
62
53
|
result: string;
|
|
63
54
|
}
|
|
@@ -70,45 +61,44 @@ export interface PromptExpectation {
|
|
|
70
61
|
* then an error is thrown.
|
|
71
62
|
*/
|
|
72
63
|
export function mockPrompt(...expectations: PromptExpectation[]) {
|
|
73
|
-
(
|
|
74
|
-
(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
64
|
+
for (const expectation of expectations) {
|
|
65
|
+
(prompts as unknown as jest.Mock).mockImplementationOnce(
|
|
66
|
+
({ type, name, message, initial, style }) => {
|
|
67
|
+
expect({ type, name, message }).toStrictEqual({
|
|
68
|
+
type: "text",
|
|
69
|
+
name: "value",
|
|
70
|
+
message: expectation.text,
|
|
71
|
+
});
|
|
72
|
+
if (expectation.options) {
|
|
73
|
+
expect(initial).toStrictEqual(expectation.options?.defaultValue);
|
|
74
|
+
expect(style).toStrictEqual(
|
|
75
|
+
expectation.options?.isSecret ? "password" : "default"
|
|
76
|
+
);
|
|
79
77
|
}
|
|
78
|
+
return Promise.resolve({ value: expectation.result });
|
|
80
79
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
);
|
|
84
|
-
return () => {
|
|
85
|
-
if (expectations.length > 0) {
|
|
86
|
-
throw new Error(
|
|
87
|
-
"The following expected prompt dialogs were not used:\n" +
|
|
88
|
-
expectations.map((e) => `- "${e.text}"`).join("\n")
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
|
-
};
|
|
80
|
+
);
|
|
81
|
+
}
|
|
92
82
|
}
|
|
93
83
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
// it as a function with no return value (!), so we need to accitionally reset
|
|
98
|
-
// the mock implementation to the one that throws (from jest.setup.js).
|
|
99
|
-
(prompt as jest.Mock).mockImplementation((text: string) => {
|
|
100
|
-
throw new Error(
|
|
101
|
-
`Unexpected call to \`prompt(${text}, ...)\`.\nYou should use \`mockPrompt()\` to mock calls to \`prompt()\` with expectations. Search the codebase for \`mockPrompt\` to learn more.`
|
|
102
|
-
);
|
|
103
|
-
});
|
|
84
|
+
interface SelectOptions<Values> {
|
|
85
|
+
choices: SelectOption<Values>[];
|
|
86
|
+
defaultOption?: number;
|
|
104
87
|
}
|
|
105
88
|
|
|
89
|
+
interface SelectOption<Values> {
|
|
90
|
+
title: string;
|
|
91
|
+
description?: string;
|
|
92
|
+
value: Values;
|
|
93
|
+
}
|
|
106
94
|
/**
|
|
107
95
|
* The expected values for a select request.
|
|
108
96
|
*/
|
|
109
|
-
export interface SelectExpectation {
|
|
97
|
+
export interface SelectExpectation<Values> {
|
|
110
98
|
/** The text expected to be seen in the select dialog. */
|
|
111
99
|
text: string;
|
|
100
|
+
|
|
101
|
+
options?: SelectOptions<Values>;
|
|
112
102
|
/** The mock response send back from the select dialog. */
|
|
113
103
|
result: string;
|
|
114
104
|
}
|
|
@@ -120,34 +110,30 @@ export interface SelectExpectation {
|
|
|
120
110
|
* If there is a call to `select()` that does not match any of the expectations
|
|
121
111
|
* then an error is thrown.
|
|
122
112
|
*/
|
|
123
|
-
export function mockSelect(
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
113
|
+
export function mockSelect<Values>(
|
|
114
|
+
...expectations: SelectExpectation<Values>[]
|
|
115
|
+
) {
|
|
116
|
+
for (const expectation of expectations) {
|
|
117
|
+
(prompts as unknown as jest.Mock).mockImplementationOnce(
|
|
118
|
+
({ type, name, message, choices, initial }) => {
|
|
119
|
+
expect({ type, name, message }).toStrictEqual({
|
|
120
|
+
type: "select",
|
|
121
|
+
name: "value",
|
|
122
|
+
message: expectation.text,
|
|
123
|
+
});
|
|
124
|
+
if (expectation.options) {
|
|
125
|
+
expect(choices).toStrictEqual(expectation.options?.choices);
|
|
126
|
+
expect(initial).toStrictEqual(expectation.options?.defaultOption);
|
|
127
|
+
}
|
|
128
|
+
return Promise.resolve({ value: expectation.result });
|
|
129
129
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
});
|
|
133
|
-
return () => {
|
|
134
|
-
if (expectations.length > 0) {
|
|
135
|
-
throw new Error(
|
|
136
|
-
"The following expected select dialogs were not used:\n" +
|
|
137
|
-
expectations.map((e) => `- "${e.text}"`).join("\n")
|
|
138
|
-
);
|
|
139
|
-
}
|
|
140
|
-
};
|
|
130
|
+
);
|
|
131
|
+
}
|
|
141
132
|
}
|
|
142
133
|
|
|
143
|
-
export function
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
(select as jest.Mock).mockImplementation((text: string) => {
|
|
149
|
-
throw new Error(
|
|
150
|
-
`Unexpected call to \`select("${text}")\`.\nYou should use \`mockSelect()\` to mock calls to \`select()\` with expectations. Search the codebase for \`mockSelect\` to learn more.`
|
|
151
|
-
);
|
|
152
|
-
});
|
|
134
|
+
export function clearDialogs() {
|
|
135
|
+
// No dialog mocks should be left after each test, and so calling the dialog methods should throw
|
|
136
|
+
expect(() => prompts({ type: "select", name: "unknown" })).toThrow(
|
|
137
|
+
"Unexpected call to "
|
|
138
|
+
);
|
|
153
139
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
import { msw } from "./msw";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Mocks the `/accounts/:accountId/pages/projects/:projectName/upload-token` GET request
|
|
6
|
+
*/
|
|
7
|
+
export function mockGetUploadTokenRequest(
|
|
8
|
+
jwt: string,
|
|
9
|
+
accountId: string,
|
|
10
|
+
projectName: string
|
|
11
|
+
) {
|
|
12
|
+
msw.use(
|
|
13
|
+
rest.get(
|
|
14
|
+
`*/accounts/:accountId/pages/projects/${projectName}/upload-token`,
|
|
15
|
+
(req, res, ctx) => {
|
|
16
|
+
expect(req.params.accountId).toEqual(accountId);
|
|
17
|
+
|
|
18
|
+
return res(
|
|
19
|
+
ctx.status(200),
|
|
20
|
+
ctx.json({ success: true, errors: [], messages: [], result: { jwt } })
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
)
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
import { msw, createFetchResult } from "./msw";
|
|
2
3
|
|
|
3
4
|
export function mockGetZoneFromHostRequest(host: string, zone?: string) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
msw.use(
|
|
6
|
+
rest.get("*/zones", (req, res, ctx) => {
|
|
7
|
+
expect(req.url.searchParams.get("name")).toEqual(host);
|
|
8
|
+
return res(ctx.json(createFetchResult(zone ? [{ id: zone }] : [])));
|
|
9
|
+
})
|
|
10
|
+
);
|
|
8
11
|
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
import { createFetchResult, msw } from "./msw";
|
|
2
3
|
|
|
3
4
|
export function mockCollectKnownRoutesRequest(
|
|
4
5
|
routes: { pattern: string; script: string }[]
|
|
5
6
|
) {
|
|
6
|
-
|
|
7
|
+
msw.use(
|
|
8
|
+
rest.get(`*/zones/:zoneId/workers/routes`, (_, res, ctx) =>
|
|
9
|
+
res.once(ctx.json(createFetchResult(routes)))
|
|
10
|
+
)
|
|
11
|
+
);
|
|
7
12
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
import { createFetchResult, msw } from "./msw";
|
|
2
3
|
import type { NamespaceKeyInfo } from "../../kv/helpers";
|
|
3
4
|
|
|
4
5
|
export function mockKeyListRequest(
|
|
@@ -9,25 +10,37 @@ export function mockKeyListRequest(
|
|
|
9
10
|
) {
|
|
10
11
|
const requests = { count: 0 };
|
|
11
12
|
// See https://api.cloudflare.com/#workers-kv-namespace-list-a-namespace-s-keys
|
|
13
|
+
msw.use(
|
|
14
|
+
rest.get(
|
|
15
|
+
"*/accounts/:accountId/storage/kv/namespaces/:namespaceId/keys",
|
|
16
|
+
(req, res, ctx) => {
|
|
17
|
+
requests.count++;
|
|
18
|
+
expect(req.params.accountId).toEqual("some-account-id");
|
|
19
|
+
expect(req.params.namespaceId).toEqual(expectedNamespaceId);
|
|
20
|
+
let response: undefined | NamespaceKeyInfo[];
|
|
21
|
+
if (expectedKeys.length <= keysPerRequest) {
|
|
22
|
+
response = expectedKeys;
|
|
23
|
+
}
|
|
12
24
|
|
|
13
|
-
|
|
14
|
-
"/accounts/:accountId/storage/kv/namespaces/:namespaceId/keys",
|
|
15
|
-
"GET",
|
|
16
|
-
([_url, accountId, namespaceId], _init, query) => {
|
|
17
|
-
requests.count++;
|
|
18
|
-
expect(accountId).toEqual("some-account-id");
|
|
19
|
-
expect(namespaceId).toEqual(expectedNamespaceId);
|
|
20
|
-
if (expectedKeys.length <= keysPerRequest) {
|
|
21
|
-
return createFetchResult(expectedKeys);
|
|
22
|
-
} else {
|
|
23
|
-
const start = parseInt(query.get("cursor") ?? "0") || 0;
|
|
25
|
+
const start = parseInt(req.url.searchParams.get("cursor") ?? "0") || 0;
|
|
24
26
|
const end = start + keysPerRequest;
|
|
25
27
|
const cursor = end < expectedKeys.length ? end : blankCursorValue;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
|
|
29
|
+
return res(
|
|
30
|
+
ctx.json(
|
|
31
|
+
createFetchResult(
|
|
32
|
+
response ? response : expectedKeys.slice(start, end),
|
|
33
|
+
true,
|
|
34
|
+
[],
|
|
35
|
+
[],
|
|
36
|
+
{
|
|
37
|
+
cursor,
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
)
|
|
41
|
+
);
|
|
29
42
|
}
|
|
30
|
-
|
|
43
|
+
)
|
|
31
44
|
);
|
|
32
45
|
return requests;
|
|
33
46
|
}
|
|
@@ -1,40 +1,34 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { rest } from "msw";
|
|
2
2
|
import { Request } from "undici";
|
|
3
3
|
import openInBrowser from "../../open-in-browser";
|
|
4
|
-
import {
|
|
5
|
-
createFetchResult,
|
|
6
|
-
setMockRawResponse,
|
|
7
|
-
setMockResponse,
|
|
8
|
-
} from "./mock-cfetch";
|
|
9
4
|
import { mockHttpServer } from "./mock-http-server";
|
|
5
|
+
import { createFetchResult, msw } from "./msw";
|
|
10
6
|
|
|
11
7
|
export function mockGetMemberships(
|
|
12
8
|
accounts: { id: string; account: { id: string; name: string } }[]
|
|
13
9
|
) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
msw.use(
|
|
11
|
+
rest.get("*/memberships", (_, res, ctx) => {
|
|
12
|
+
return res.once(ctx.json(createFetchResult(accounts)));
|
|
13
|
+
})
|
|
14
|
+
);
|
|
17
15
|
}
|
|
18
|
-
|
|
19
16
|
export function mockGetMembershipsFail() {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
msw.use(
|
|
18
|
+
rest.get("*/memberships", (_, res, ctx) => {
|
|
19
|
+
return res.once(ctx.json(createFetchResult([], false)));
|
|
20
|
+
})
|
|
21
|
+
);
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
// the response to send when wrangler wants an oauth grant
|
|
26
|
-
let oauthGrantResponse: GrantResponseOptions | "timeout" = {};
|
|
27
|
-
|
|
28
24
|
/**
|
|
29
25
|
* Functions to help with mocking various parts of the OAuth Flow
|
|
30
26
|
*/
|
|
31
27
|
export const mockOAuthFlow = () => {
|
|
28
|
+
// the response to send when wrangler wants an oauth grant
|
|
29
|
+
let oauthGrantResponse: GrantResponseOptions | "timeout" = {};
|
|
32
30
|
const fetchHttp = mockHttpServer();
|
|
33
31
|
|
|
34
|
-
afterEach(() => {
|
|
35
|
-
fetchMock.resetMocks();
|
|
36
|
-
});
|
|
37
|
-
|
|
38
32
|
/**
|
|
39
33
|
* Mock out the callback from a browser to our HttpServer.
|
|
40
34
|
*
|
|
@@ -71,7 +65,7 @@ export const mockOAuthFlow = () => {
|
|
|
71
65
|
});
|
|
72
66
|
};
|
|
73
67
|
|
|
74
|
-
//
|
|
68
|
+
// Handled in `mockOAuthServerCallback`
|
|
75
69
|
const mockGrantAuthorization = ({
|
|
76
70
|
respondWith,
|
|
77
71
|
}: {
|
|
@@ -92,97 +86,110 @@ export const mockOAuthFlow = () => {
|
|
|
92
86
|
}
|
|
93
87
|
};
|
|
94
88
|
|
|
95
|
-
const mockRevokeAuthorization = () => {
|
|
96
|
-
const outcome = {
|
|
97
|
-
actual: new Request("https://example.org"),
|
|
98
|
-
expected: new Request("https://dash.cloudflare.com/oauth2/revoke", {
|
|
99
|
-
method: "POST",
|
|
100
|
-
}),
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
fetchMock.mockIf(outcome.expected.url, async (req) => {
|
|
104
|
-
// TODO: update Miniflare typings to match full undici Request
|
|
105
|
-
outcome.actual = req as unknown as Request;
|
|
106
|
-
return "";
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
return outcome;
|
|
110
|
-
};
|
|
111
|
-
|
|
112
89
|
const mockGrantAccessToken = ({
|
|
113
90
|
respondWith,
|
|
91
|
+
domain = "dash.cloudflare.com",
|
|
114
92
|
}: {
|
|
115
93
|
respondWith: MockTokenResponse;
|
|
94
|
+
domain?: string;
|
|
116
95
|
}) => {
|
|
117
96
|
const outcome = {
|
|
118
|
-
actual:
|
|
119
|
-
expected:
|
|
120
|
-
method: "POST",
|
|
121
|
-
}),
|
|
97
|
+
actual: "https://example.org",
|
|
98
|
+
expected: `https://${domain}/oauth2/token`,
|
|
122
99
|
};
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
100
|
+
msw.use(
|
|
101
|
+
rest.post(outcome.expected, async (req, res, ctx) => {
|
|
102
|
+
// TODO: update Miniflare typings to match full undici Request
|
|
103
|
+
outcome.actual = req.url.toString();
|
|
104
|
+
return res.once(ctx.json(makeTokenResponse(respondWith)));
|
|
105
|
+
})
|
|
106
|
+
);
|
|
129
107
|
|
|
130
108
|
return outcome;
|
|
131
109
|
};
|
|
132
110
|
|
|
133
|
-
|
|
134
|
-
|
|
111
|
+
function mockDomainUsesAccess({
|
|
112
|
+
usesAccess,
|
|
113
|
+
domain = "dash.cloudflare.com",
|
|
135
114
|
}: {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
token_type: "bearer",
|
|
151
|
-
}),
|
|
152
|
-
};
|
|
153
|
-
case "refreshError":
|
|
154
|
-
return {
|
|
155
|
-
status: 400,
|
|
156
|
-
body: JSON.stringify({
|
|
157
|
-
error: "invalid_request",
|
|
158
|
-
error_description: "error_description_mock",
|
|
159
|
-
error_hint: "error_hint_mock",
|
|
160
|
-
error_verbose: "error_verbose_mock",
|
|
161
|
-
status_code: 400,
|
|
162
|
-
}),
|
|
163
|
-
};
|
|
164
|
-
case "badResponse":
|
|
165
|
-
return {
|
|
166
|
-
status: 400,
|
|
167
|
-
body: `<html> <body> This shouldn't be sent, but should be handled </body> </html>`,
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
default:
|
|
171
|
-
return "Not a respondWith option for `mockExchangeRefreshTokenForAccessToken`";
|
|
115
|
+
usesAccess: boolean;
|
|
116
|
+
domain?: string;
|
|
117
|
+
}) {
|
|
118
|
+
// If the domain relies upon Cloudflare Access, then a request to the domain
|
|
119
|
+
// will result in a redirect to the `cloudflareaccess.com` domain.
|
|
120
|
+
msw.use(
|
|
121
|
+
rest.get(`https://${domain}/`, (_, res, ctx) => {
|
|
122
|
+
let status = 200;
|
|
123
|
+
let headers: Record<string, string> = {
|
|
124
|
+
"Content-Type": "application/json",
|
|
125
|
+
};
|
|
126
|
+
if (usesAccess) {
|
|
127
|
+
status = 302;
|
|
128
|
+
headers = { location: "cloudflareaccess.com" };
|
|
172
129
|
}
|
|
173
|
-
|
|
130
|
+
return res.once(ctx.status(status), ctx.set(headers));
|
|
131
|
+
})
|
|
174
132
|
);
|
|
175
|
-
}
|
|
133
|
+
}
|
|
176
134
|
|
|
177
135
|
return {
|
|
136
|
+
mockHttpServer,
|
|
137
|
+
mockDomainUsesAccess,
|
|
178
138
|
mockGrantAccessToken,
|
|
179
|
-
mockGrantAuthorization,
|
|
180
139
|
mockOAuthServerCallback,
|
|
181
|
-
mockRevokeAuthorization,
|
|
182
140
|
mockExchangeRefreshTokenForAccessToken,
|
|
183
141
|
};
|
|
184
142
|
};
|
|
185
143
|
|
|
144
|
+
export function mockExchangeRefreshTokenForAccessToken({
|
|
145
|
+
respondWith,
|
|
146
|
+
domain = "dash.cloudflare.com",
|
|
147
|
+
}: {
|
|
148
|
+
respondWith: "refreshSuccess" | "refreshError" | "badResponse";
|
|
149
|
+
domain?: string;
|
|
150
|
+
}) {
|
|
151
|
+
msw.use(
|
|
152
|
+
rest.post(`https://${domain}/oauth2/token`, async (_, res, ctx) => {
|
|
153
|
+
switch (respondWith) {
|
|
154
|
+
case "refreshSuccess":
|
|
155
|
+
return res.once(
|
|
156
|
+
ctx.status(200),
|
|
157
|
+
ctx.json({
|
|
158
|
+
access_token: "access_token_success_mock",
|
|
159
|
+
expires_in: 1701,
|
|
160
|
+
refresh_token: "refresh_token_success_mock",
|
|
161
|
+
scope: "scope_success_mock",
|
|
162
|
+
token_type: "bearer",
|
|
163
|
+
})
|
|
164
|
+
);
|
|
165
|
+
case "refreshError":
|
|
166
|
+
return res.once(
|
|
167
|
+
ctx.status(400),
|
|
168
|
+
ctx.json({
|
|
169
|
+
error: "invalid_request",
|
|
170
|
+
error_description: "error_description_mock",
|
|
171
|
+
error_hint: "error_hint_mock",
|
|
172
|
+
error_verbose: "error_verbose_mock",
|
|
173
|
+
status_code: 400,
|
|
174
|
+
})
|
|
175
|
+
);
|
|
176
|
+
case "badResponse":
|
|
177
|
+
return res.once(
|
|
178
|
+
ctx.status(400),
|
|
179
|
+
ctx.text(
|
|
180
|
+
`<html> <body> This shouldn't be sent, but should be handled </body> </html>`
|
|
181
|
+
)
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
default:
|
|
185
|
+
throw new Error(
|
|
186
|
+
"Not a respondWith option for `mockExchangeRefreshTokenForAccessToken`"
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
})
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
186
193
|
type GrantResponseOptions = {
|
|
187
194
|
code?: string;
|
|
188
195
|
error?: ErrorType | ErrorType[];
|
|
@@ -234,7 +241,7 @@ type MockTokenResponse =
|
|
|
234
241
|
error: ErrorType;
|
|
235
242
|
};
|
|
236
243
|
|
|
237
|
-
const makeTokenResponse = (partialResponse: MockTokenResponse)
|
|
244
|
+
const makeTokenResponse = (partialResponse: MockTokenResponse) => {
|
|
238
245
|
let fullResponse: MockTokenResponse;
|
|
239
246
|
|
|
240
247
|
if (partialResponse === "ok") {
|
|
@@ -252,5 +259,5 @@ const makeTokenResponse = (partialResponse: MockTokenResponse): string => {
|
|
|
252
259
|
fullResponse = partialResponse;
|
|
253
260
|
}
|
|
254
261
|
|
|
255
|
-
return
|
|
262
|
+
return fullResponse;
|
|
256
263
|
};
|
|
@@ -5,22 +5,17 @@
|
|
|
5
5
|
|
|
6
6
|
let writeSpy: jest.SpyInstance;
|
|
7
7
|
|
|
8
|
-
function captureLastWriteCall(spy: jest.SpyInstance): Buffer {
|
|
8
|
+
function captureLastWriteCall(spy: jest.SpyInstance): Buffer | undefined {
|
|
9
9
|
const calls = spy.mock.calls;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
|
|
11
|
+
// Loop through and find the buffer in calls
|
|
12
|
+
// (we don't know the index of the buffer in the calls array)
|
|
13
|
+
const buffer = calls
|
|
14
|
+
.map((call) => call[0])
|
|
15
|
+
.find((call) => call instanceof Buffer);
|
|
16
|
+
|
|
16
17
|
if (buffer instanceof Buffer) {
|
|
17
18
|
return buffer;
|
|
18
|
-
} else {
|
|
19
|
-
throw new Error(
|
|
20
|
-
`Unexpected non-Buffer passed to \`stdout.write()\`: "${JSON.stringify(
|
|
21
|
-
buffer
|
|
22
|
-
)}"`
|
|
23
|
-
);
|
|
24
19
|
}
|
|
25
20
|
}
|
|
26
21
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
let setTimeoutSpy: jest.SpyInstance;
|
|
2
|
+
|
|
3
|
+
export function mockSetTimeout() {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
setTimeoutSpy = jest
|
|
6
|
+
.spyOn(global, "setTimeout")
|
|
7
|
+
// @ts-expect-error we're using a very simple setTimeout mock here
|
|
8
|
+
.mockImplementation((fn, _period) => {
|
|
9
|
+
setImmediate(fn);
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
setTimeoutSpy.mockRestore();
|
|
15
|
+
});
|
|
16
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/*! Read blob sync in NodeJS. MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource>
|
|
2
|
+
* Special Thanks to Jimmy Wärting helping in https://github.com/nodejs/undici/issues/1830
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const { workerData } = require("worker_threads");
|
|
6
|
+
|
|
7
|
+
const { signal, port, blob } = workerData;
|
|
8
|
+
|
|
9
|
+
blob.arrayBuffer().then((ab) => {
|
|
10
|
+
// Post the result back to the main thread before unlocking 'signal'
|
|
11
|
+
port.postMessage(ab, [ab]);
|
|
12
|
+
port.close();
|
|
13
|
+
|
|
14
|
+
// Change the value of signal[0] to 1
|
|
15
|
+
Atomics.store(signal, 0, 1);
|
|
16
|
+
|
|
17
|
+
// This will unlock the main thread when we notify it
|
|
18
|
+
Atomics.notify(signal, 0);
|
|
19
|
+
});
|