wrangler 2.0.12 → 2.0.16
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 +7 -1
- package/bin/wrangler.js +111 -57
- package/miniflare-dist/index.mjs +9 -2
- package/package.json +156 -154
- package/src/__tests__/config-cache-without-cache-dir.test.ts +38 -0
- package/src/__tests__/config-cache.test.ts +30 -24
- package/src/__tests__/configuration.test.ts +3935 -3476
- package/src/__tests__/dev.test.tsx +1128 -979
- package/src/__tests__/guess-worker-format.test.ts +68 -68
- package/src/__tests__/helpers/cmd-shim.d.ts +6 -6
- package/src/__tests__/helpers/faye-websocket.d.ts +4 -4
- package/src/__tests__/helpers/mock-account-id.ts +24 -24
- package/src/__tests__/helpers/mock-bin.ts +20 -20
- package/src/__tests__/helpers/mock-cfetch.ts +92 -92
- package/src/__tests__/helpers/mock-console.ts +49 -39
- package/src/__tests__/helpers/mock-dialogs.ts +94 -71
- package/src/__tests__/helpers/mock-http-server.ts +30 -30
- package/src/__tests__/helpers/mock-istty.ts +65 -18
- package/src/__tests__/helpers/mock-kv.ts +26 -26
- package/src/__tests__/helpers/mock-oauth-flow.ts +223 -228
- package/src/__tests__/helpers/mock-process.ts +39 -0
- package/src/__tests__/helpers/mock-stdin.ts +82 -77
- package/src/__tests__/helpers/mock-web-socket.ts +21 -21
- package/src/__tests__/helpers/run-in-tmp.ts +27 -27
- package/src/__tests__/helpers/run-wrangler.ts +8 -8
- package/src/__tests__/helpers/write-worker-source.ts +16 -16
- package/src/__tests__/helpers/write-wrangler-toml.ts +9 -9
- package/src/__tests__/https-options.test.ts +104 -104
- package/src/__tests__/index.test.ts +239 -234
- package/src/__tests__/init.test.ts +1605 -1250
- package/src/__tests__/jest.setup.ts +63 -33
- package/src/__tests__/kv.test.ts +1128 -1011
- package/src/__tests__/logger.test.ts +100 -74
- package/src/__tests__/package-manager.test.ts +303 -303
- package/src/__tests__/pages.test.ts +1152 -652
- package/src/__tests__/parse.test.ts +252 -252
- package/src/__tests__/publish.test.ts +6371 -5622
- package/src/__tests__/pubsub.test.ts +367 -0
- package/src/__tests__/r2.test.ts +133 -133
- package/src/__tests__/route.test.ts +18 -18
- package/src/__tests__/secret.test.ts +382 -377
- package/src/__tests__/tail.test.ts +530 -530
- package/src/__tests__/user.test.ts +123 -111
- package/src/__tests__/whoami.test.tsx +198 -117
- package/src/__tests__/worker-namespace.test.ts +327 -0
- package/src/abort.d.ts +1 -1
- package/src/api/dev.ts +49 -0
- package/src/api/index.ts +1 -0
- package/src/bundle-reporter.tsx +29 -0
- package/src/bundle.ts +157 -149
- package/src/cfetch/index.ts +80 -80
- package/src/cfetch/internal.ts +90 -83
- package/src/cli.ts +21 -7
- package/src/config/config.ts +204 -195
- package/src/config/diagnostics.ts +61 -61
- package/src/config/environment.ts +390 -357
- package/src/config/index.ts +206 -193
- package/src/config/validation-helpers.ts +366 -366
- package/src/config/validation.ts +1573 -1376
- package/src/config-cache.ts +79 -41
- package/src/create-worker-preview.ts +206 -136
- package/src/create-worker-upload-form.ts +247 -238
- package/src/dev/dev-vars.ts +13 -13
- package/src/dev/dev.tsx +329 -307
- package/src/dev/local.tsx +304 -275
- package/src/dev/remote.tsx +366 -224
- package/src/dev/use-esbuild.ts +126 -91
- package/src/dev.tsx +538 -0
- package/src/dialogs.tsx +97 -97
- package/src/durable.ts +87 -87
- package/src/entry.ts +234 -228
- package/src/environment-variables.ts +23 -23
- package/src/errors.ts +6 -6
- package/src/generate.ts +33 -0
- package/src/git-client.ts +42 -0
- package/src/https-options.ts +79 -79
- package/src/index.tsx +1775 -2763
- package/src/init.ts +549 -0
- package/src/inspect.ts +593 -593
- package/src/intl-polyfill.d.ts +123 -123
- package/src/is-interactive.ts +12 -0
- package/src/kv.ts +277 -277
- package/src/logger.ts +46 -39
- package/src/miniflare-cli/enum-keys.ts +8 -8
- package/src/miniflare-cli/index.ts +42 -31
- package/src/miniflare-cli/request-context.ts +18 -18
- package/src/module-collection.ts +212 -212
- package/src/open-in-browser.ts +4 -6
- package/src/package-manager.ts +123 -123
- package/src/pages/build.tsx +202 -0
- package/src/pages/constants.ts +7 -0
- package/src/pages/deployments.tsx +101 -0
- package/src/pages/dev.tsx +964 -0
- package/src/pages/functions/buildPlugin.ts +105 -0
- package/src/pages/functions/buildWorker.ts +151 -0
- package/{pages → src/pages}/functions/filepath-routing.test.ts +113 -113
- package/src/pages/functions/filepath-routing.ts +189 -0
- package/src/pages/functions/identifiers.ts +78 -0
- package/src/pages/functions/routes.ts +151 -0
- package/src/pages/index.tsx +84 -0
- package/src/pages/projects.tsx +157 -0
- package/src/pages/publish.tsx +335 -0
- package/src/pages/types.ts +40 -0
- package/src/pages/upload.tsx +384 -0
- package/src/pages/utils.ts +12 -0
- package/src/parse.ts +202 -138
- package/src/paths.ts +6 -6
- package/src/preview.ts +31 -0
- package/src/proxy.ts +400 -402
- package/src/publish.ts +667 -621
- package/src/pubsub/index.ts +286 -0
- package/src/pubsub/pubsub-commands.tsx +577 -0
- package/src/r2.ts +19 -19
- package/src/selfsigned.d.ts +23 -23
- package/src/sites.tsx +271 -225
- package/src/tail/filters.ts +108 -108
- package/src/tail/index.ts +217 -217
- package/src/tail/printing.ts +45 -45
- package/src/update-check.ts +11 -11
- package/src/user/choose-account.tsx +60 -0
- package/src/user/env-vars.ts +46 -0
- package/src/user/generate-auth-url.ts +33 -0
- package/src/user/generate-random-state.ts +16 -0
- package/src/user/index.ts +3 -0
- package/src/user/user.tsx +1161 -0
- package/src/whoami.tsx +61 -42
- package/src/worker-namespace.ts +190 -0
- package/src/worker.ts +110 -100
- package/src/zones.ts +39 -36
- package/templates/checked-fetch.js +17 -0
- package/templates/new-worker-scheduled.js +3 -3
- package/templates/new-worker-scheduled.ts +15 -15
- package/templates/new-worker.js +3 -3
- package/templates/new-worker.ts +15 -15
- package/templates/no-op-worker.js +10 -0
- package/templates/pages-template-plugin.ts +155 -0
- package/templates/pages-template-worker.ts +161 -0
- package/templates/static-asset-facade.js +31 -31
- package/templates/tsconfig.json +95 -95
- package/wrangler-dist/cli.js +55383 -54138
- package/pages/functions/buildPlugin.ts +0 -105
- package/pages/functions/buildWorker.ts +0 -151
- package/pages/functions/filepath-routing.ts +0 -189
- package/pages/functions/identifiers.ts +0 -78
- package/pages/functions/routes.ts +0 -156
- package/pages/functions/template-plugin.ts +0 -147
- package/pages/functions/template-worker.ts +0 -143
- package/src/pages.tsx +0 -2093
- package/src/user.tsx +0 -1214
package/src/bundle.ts
CHANGED
|
@@ -11,10 +11,10 @@ import type { Entry } from "./entry";
|
|
|
11
11
|
import type { CfModule } from "./worker";
|
|
12
12
|
|
|
13
13
|
type BundleResult = {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
modules: CfModule[];
|
|
15
|
+
resolvedEntryPointPath: string;
|
|
16
|
+
bundleType: "esm" | "commonjs";
|
|
17
|
+
stop: (() => void) | undefined;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -23,135 +23,143 @@ type BundleResult = {
|
|
|
23
23
|
* Supports both regular node builtins, and the new "node:<MODULE>" format.
|
|
24
24
|
*/
|
|
25
25
|
const checkForNodeBuiltinsPlugin = {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
26
|
+
name: "checkForNodeBuiltins",
|
|
27
|
+
setup(build: esbuild.PluginBuild) {
|
|
28
|
+
build.onResolve(
|
|
29
|
+
{
|
|
30
|
+
filter: new RegExp(
|
|
31
|
+
"^(" +
|
|
32
|
+
builtinModules.join("|") +
|
|
33
|
+
"|" +
|
|
34
|
+
builtinModules.map((module) => "node:" + module).join("|") +
|
|
35
|
+
")$"
|
|
36
|
+
),
|
|
37
|
+
},
|
|
38
|
+
() => {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Detected a Node builtin module import while Node compatibility is disabled.\nAdd node_compat = true to your wrangler.toml file to enable Node compatibility.`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
},
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
48
|
* Generate a bundle for the worker identified by the arguments passed in.
|
|
49
49
|
*/
|
|
50
50
|
export async function bundleWorker(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
51
|
+
entry: Entry,
|
|
52
|
+
destination: string,
|
|
53
|
+
options: {
|
|
54
|
+
serveAssetsFromWorker: boolean;
|
|
55
|
+
jsxFactory: string | undefined;
|
|
56
|
+
jsxFragment: string | undefined;
|
|
57
|
+
rules: Config["rules"];
|
|
58
|
+
watch?: esbuild.WatchMode;
|
|
59
|
+
tsconfig: string | undefined;
|
|
60
|
+
minify: boolean | undefined;
|
|
61
|
+
nodeCompat: boolean | undefined;
|
|
62
|
+
define: Config["define"];
|
|
63
|
+
checkFetch: boolean;
|
|
64
|
+
}
|
|
63
65
|
): Promise<BundleResult> {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
66
|
+
const {
|
|
67
|
+
serveAssetsFromWorker,
|
|
68
|
+
jsxFactory,
|
|
69
|
+
jsxFragment,
|
|
70
|
+
rules,
|
|
71
|
+
watch,
|
|
72
|
+
tsconfig,
|
|
73
|
+
minify,
|
|
74
|
+
nodeCompat,
|
|
75
|
+
checkFetch,
|
|
76
|
+
} = options;
|
|
77
|
+
const entryDirectory = path.dirname(entry.file);
|
|
78
|
+
const moduleCollector = createModuleCollector({
|
|
79
|
+
wrangler1xlegacyModuleReferences: {
|
|
80
|
+
rootDirectory: entryDirectory,
|
|
81
|
+
fileNames: new Set(
|
|
82
|
+
fs
|
|
83
|
+
.readdirSync(entryDirectory, { withFileTypes: true })
|
|
84
|
+
.filter(
|
|
85
|
+
(dirEntry) =>
|
|
86
|
+
dirEntry.isFile() && dirEntry.name !== path.basename(entry.file)
|
|
87
|
+
)
|
|
88
|
+
.map((dirEnt) => dirEnt.name)
|
|
89
|
+
),
|
|
90
|
+
},
|
|
91
|
+
format: entry.format,
|
|
92
|
+
rules,
|
|
93
|
+
});
|
|
91
94
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
95
|
+
const result = await esbuild.build({
|
|
96
|
+
...getEntryPoint(entry.file, serveAssetsFromWorker),
|
|
97
|
+
bundle: true,
|
|
98
|
+
absWorkingDir: entry.directory,
|
|
99
|
+
outdir: destination,
|
|
100
|
+
inject: checkFetch
|
|
101
|
+
? [path.resolve(__dirname, "../templates/checked-fetch.js")]
|
|
102
|
+
: [],
|
|
103
|
+
external: ["__STATIC_CONTENT_MANIFEST"],
|
|
104
|
+
format: entry.format === "modules" ? "esm" : "iife",
|
|
105
|
+
target: "es2020",
|
|
106
|
+
sourcemap: true,
|
|
107
|
+
minify,
|
|
108
|
+
metafile: true,
|
|
109
|
+
conditions: ["worker", "browser"],
|
|
110
|
+
...(process.env.NODE_ENV && {
|
|
111
|
+
define: {
|
|
112
|
+
"process.env.NODE_ENV": `"${process.env.NODE_ENV}"`,
|
|
113
|
+
...(nodeCompat ? { global: "globalThis" } : {}),
|
|
114
|
+
...(checkFetch ? { fetch: "checkedFetch" } : {}),
|
|
115
|
+
...options.define,
|
|
116
|
+
},
|
|
117
|
+
}),
|
|
118
|
+
loader: {
|
|
119
|
+
".js": "jsx",
|
|
120
|
+
".mjs": "jsx",
|
|
121
|
+
".cjs": "jsx",
|
|
122
|
+
},
|
|
123
|
+
plugins: [
|
|
124
|
+
moduleCollector.plugin,
|
|
125
|
+
...(nodeCompat
|
|
126
|
+
? [NodeGlobalsPolyfills({ buffer: true }), NodeModulesPolyfills()]
|
|
127
|
+
: // we use checkForNodeBuiltinsPlugin to throw a nicer error
|
|
128
|
+
// if we find node builtins when nodeCompat isn't turned on
|
|
129
|
+
[checkForNodeBuiltinsPlugin]),
|
|
130
|
+
],
|
|
131
|
+
...(jsxFactory && { jsxFactory }),
|
|
132
|
+
...(jsxFragment && { jsxFragment }),
|
|
133
|
+
...(tsconfig && { tsconfig }),
|
|
134
|
+
watch,
|
|
135
|
+
});
|
|
128
136
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
137
|
+
const entryPointOutputs = Object.entries(result.metafile.outputs).filter(
|
|
138
|
+
([_path, output]) => output.entryPoint !== undefined
|
|
139
|
+
);
|
|
140
|
+
assert(
|
|
141
|
+
entryPointOutputs.length > 0,
|
|
142
|
+
`Cannot find entry-point "${entry.file}" in generated bundle.` +
|
|
143
|
+
listEntryPoints(entryPointOutputs)
|
|
144
|
+
);
|
|
145
|
+
assert(
|
|
146
|
+
entryPointOutputs.length < 2,
|
|
147
|
+
"More than one entry-point found for generated bundle." +
|
|
148
|
+
listEntryPoints(entryPointOutputs)
|
|
149
|
+
);
|
|
142
150
|
|
|
143
|
-
|
|
144
|
-
|
|
151
|
+
const entryPointExports = entryPointOutputs[0][1].exports;
|
|
152
|
+
const bundleType = entryPointExports.length > 0 ? "esm" : "commonjs";
|
|
145
153
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
154
|
+
return {
|
|
155
|
+
modules: moduleCollector.modules,
|
|
156
|
+
resolvedEntryPointPath: path.resolve(
|
|
157
|
+
entry.directory,
|
|
158
|
+
entryPointOutputs[0][0]
|
|
159
|
+
),
|
|
160
|
+
bundleType,
|
|
161
|
+
stop: result.stop,
|
|
162
|
+
};
|
|
155
163
|
}
|
|
156
164
|
|
|
157
165
|
type EntryPoint = { stdin: esbuild.StdinOptions } | { entryPoints: string[] };
|
|
@@ -164,41 +172,41 @@ type EntryPoint = { stdin: esbuild.StdinOptions } | { entryPoints: string[] };
|
|
|
164
172
|
* or delegate to the actual worker.
|
|
165
173
|
*/
|
|
166
174
|
function getEntryPoint(
|
|
167
|
-
|
|
168
|
-
|
|
175
|
+
entryFile: string,
|
|
176
|
+
serveAssetsFromWorker: boolean
|
|
169
177
|
): EntryPoint {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
178
|
+
if (serveAssetsFromWorker) {
|
|
179
|
+
return {
|
|
180
|
+
stdin: {
|
|
181
|
+
contents: fs
|
|
182
|
+
.readFileSync(
|
|
183
|
+
path.join(__dirname, "../templates/static-asset-facade.js"),
|
|
184
|
+
"utf8"
|
|
185
|
+
)
|
|
186
|
+
// on windows, escape backslashes in the path (`\`)
|
|
187
|
+
.replace("__ENTRY_POINT__", entryFile.replaceAll("\\", "\\\\"))
|
|
188
|
+
.replace(
|
|
189
|
+
"__KV_ASSET_HANDLER__",
|
|
190
|
+
path
|
|
191
|
+
.join(__dirname, "../kv-asset-handler.js")
|
|
192
|
+
.replaceAll("\\", "\\\\")
|
|
193
|
+
),
|
|
194
|
+
sourcefile: "static-asset-facade.js",
|
|
195
|
+
resolveDir: path.dirname(entryFile),
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
} else {
|
|
199
|
+
return { entryPoints: [entryFile] };
|
|
200
|
+
}
|
|
193
201
|
}
|
|
194
202
|
|
|
195
203
|
/**
|
|
196
204
|
* Generate a string that describes the entry-points that were identified by esbuild.
|
|
197
205
|
*/
|
|
198
206
|
function listEntryPoints(
|
|
199
|
-
|
|
207
|
+
outputs: [string, ValueOf<esbuild.Metafile["outputs"]>][]
|
|
200
208
|
): string {
|
|
201
|
-
|
|
209
|
+
return outputs.map(([_input, output]) => output.entryPoint).join("\n");
|
|
202
210
|
}
|
|
203
211
|
|
|
204
212
|
type ValueOf<T> = T[keyof T];
|
package/src/cfetch/index.ts
CHANGED
|
@@ -8,16 +8,16 @@ import type { RequestInit } from "undici";
|
|
|
8
8
|
export { getCloudflareAPIBaseURL as getCloudflareApiBaseUrl } from "./internal";
|
|
9
9
|
|
|
10
10
|
export interface FetchError {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
code: number;
|
|
12
|
+
message: string;
|
|
13
|
+
error_chain?: FetchError[];
|
|
14
14
|
}
|
|
15
15
|
export interface FetchResult<ResponseType = unknown> {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
success: boolean;
|
|
17
|
+
result: ResponseType;
|
|
18
|
+
errors: FetchError[];
|
|
19
|
+
messages: string[];
|
|
20
|
+
result_info?: unknown;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export { fetchKVGetValue } from "./internal";
|
|
@@ -26,22 +26,22 @@ export { fetchKVGetValue } from "./internal";
|
|
|
26
26
|
* Make a fetch request, and extract the `result` from the JSON response.
|
|
27
27
|
*/
|
|
28
28
|
export async function fetchResult<ResponseType>(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
resource: string,
|
|
30
|
+
init: RequestInit = {},
|
|
31
|
+
queryParams?: URLSearchParams,
|
|
32
|
+
abortSignal?: AbortSignal
|
|
33
33
|
): Promise<ResponseType> {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
const json = await fetchInternal<FetchResult<ResponseType>>(
|
|
35
|
+
resource,
|
|
36
|
+
init,
|
|
37
|
+
queryParams,
|
|
38
|
+
abortSignal
|
|
39
|
+
);
|
|
40
|
+
if (json.success) {
|
|
41
|
+
return json.result;
|
|
42
|
+
} else {
|
|
43
|
+
throwFetchError(resource, json);
|
|
44
|
+
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/**
|
|
@@ -50,72 +50,72 @@ export async function fetchResult<ResponseType>(
|
|
|
50
50
|
* and repeating the request if the results are paginated.
|
|
51
51
|
*/
|
|
52
52
|
export async function fetchListResult<ResponseType>(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
resource: string,
|
|
54
|
+
init: RequestInit = {},
|
|
55
|
+
queryParams?: URLSearchParams
|
|
56
56
|
): Promise<ResponseType[]> {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
57
|
+
const results: ResponseType[] = [];
|
|
58
|
+
let getMoreResults = true;
|
|
59
|
+
let cursor: string | undefined;
|
|
60
|
+
while (getMoreResults) {
|
|
61
|
+
if (cursor) {
|
|
62
|
+
queryParams = new URLSearchParams(queryParams);
|
|
63
|
+
queryParams.set("cursor", cursor);
|
|
64
|
+
}
|
|
65
|
+
const json = await fetchInternal<FetchResult<ResponseType[]>>(
|
|
66
|
+
resource,
|
|
67
|
+
init,
|
|
68
|
+
queryParams
|
|
69
|
+
);
|
|
70
|
+
if (json.success) {
|
|
71
|
+
results.push(...json.result);
|
|
72
|
+
if (hasCursor(json.result_info)) {
|
|
73
|
+
cursor = json.result_info?.cursor;
|
|
74
|
+
} else {
|
|
75
|
+
getMoreResults = false;
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
throwFetchError(resource, json);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return results;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
function throwFetchError(
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
resource: string,
|
|
86
|
+
response: FetchResult<unknown>
|
|
87
87
|
): never {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
88
|
+
const error = new ParseError({
|
|
89
|
+
text: `A request to the Cloudflare API (${resource}) failed.`,
|
|
90
|
+
notes: response.errors.map((err) => ({
|
|
91
|
+
text: renderError(err),
|
|
92
|
+
})),
|
|
93
|
+
});
|
|
94
|
+
// add the first error code directly to this error
|
|
95
|
+
// so consumers can use it for specific behaviour
|
|
96
|
+
const code = response.errors[0]?.code;
|
|
97
|
+
if (code) {
|
|
98
|
+
//@ts-expect-error non-standard property on Error
|
|
99
|
+
error.code = code;
|
|
100
|
+
}
|
|
101
|
+
throw error;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
function hasCursor(result_info: unknown): result_info is { cursor: string } {
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
const cursor = (result_info as { cursor: string } | undefined)?.cursor;
|
|
106
|
+
return cursor !== undefined && cursor !== null && cursor !== "";
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
function renderError(err: FetchError, level = 0): string {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
110
|
+
const chainedMessages =
|
|
111
|
+
err.error_chain
|
|
112
|
+
?.map(
|
|
113
|
+
(chainedError) =>
|
|
114
|
+
`\n${" ".repeat(level)}- ${renderError(chainedError, level + 1)}`
|
|
115
|
+
)
|
|
116
|
+
.join("\n") ?? "";
|
|
117
|
+
return (
|
|
118
|
+
(err.code ? `${err.message} [code: ${err.code}]` : err.message) +
|
|
119
|
+
chainedMessages
|
|
120
|
+
);
|
|
121
121
|
}
|