wrangler 2.1.0 → 2.1.3
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/miniflare-dist/index.mjs +1 -1
- package/package.json +2 -1
- package/src/__tests__/dev.test.tsx +2 -1
- package/src/__tests__/dialogs.test.tsx +40 -0
- package/src/__tests__/helpers/mock-cfetch.ts +35 -15
- package/src/__tests__/helpers/msw/handlers/index.ts +13 -0
- package/src/__tests__/helpers/msw/handlers/namespaces.ts +104 -0
- package/src/__tests__/helpers/msw/handlers/oauth.ts +36 -0
- package/src/__tests__/helpers/msw/handlers/r2.ts +80 -0
- package/src/__tests__/helpers/msw/handlers/user.ts +63 -0
- package/src/__tests__/helpers/msw/index.ts +4 -0
- package/src/__tests__/index.test.ts +2 -0
- package/src/__tests__/jest.setup.ts +16 -0
- package/src/__tests__/publish.test.ts +52 -0
- package/src/__tests__/r2.test.ts +128 -93
- package/src/__tests__/secret.test.ts +78 -0
- package/src/__tests__/whoami.test.tsx +49 -64
- package/src/api/dev.ts +2 -1
- package/src/dev/dev.tsx +2 -2
- package/src/dev/local.tsx +2 -12
- package/src/dev/start-server.ts +2 -13
- package/src/dev.tsx +39 -6
- package/src/dialogs.tsx +8 -1
- package/src/index.tsx +90 -0
- package/src/miniflare-cli/assets.ts +1 -1
- package/src/pages/dev.tsx +28 -4
- package/src/publish.ts +21 -13
- package/wrangler-dist/cli.d.ts +2 -1
- package/wrangler-dist/cli.js +188 -44
package/src/dev.tsx
CHANGED
|
@@ -24,7 +24,6 @@ import {
|
|
|
24
24
|
isLegacyEnv,
|
|
25
25
|
DEFAULT_INSPECTOR_PORT,
|
|
26
26
|
} from "./index";
|
|
27
|
-
|
|
28
27
|
import type { Config } from "./config";
|
|
29
28
|
import type { Route } from "./config/environment";
|
|
30
29
|
import type { EnablePagesAssetsServiceBindingOptions } from "./miniflare-cli";
|
|
@@ -66,6 +65,8 @@ interface DevArgs {
|
|
|
66
65
|
define?: string[];
|
|
67
66
|
"node-compat"?: boolean;
|
|
68
67
|
"experimental-enable-local-persistence"?: boolean;
|
|
68
|
+
persist?: boolean;
|
|
69
|
+
"persist-to"?: string;
|
|
69
70
|
"live-reload"?: boolean;
|
|
70
71
|
onReady?: (ip: string, port: number) => void;
|
|
71
72
|
logLevel?: "none" | "error" | "log" | "warn" | "debug";
|
|
@@ -239,8 +240,22 @@ export function devOptions(yargs: Argv): Argv<DevArgs> {
|
|
|
239
240
|
type: "boolean",
|
|
240
241
|
})
|
|
241
242
|
.option("experimental-enable-local-persistence", {
|
|
242
|
-
describe:
|
|
243
|
+
describe:
|
|
244
|
+
"Enable persistence for local mode (deprecated, use --persist)",
|
|
243
245
|
type: "boolean",
|
|
246
|
+
deprecated: true,
|
|
247
|
+
hidden: true,
|
|
248
|
+
})
|
|
249
|
+
.option("persist", {
|
|
250
|
+
describe:
|
|
251
|
+
"Enable persistence for local mode, using default path: .wrangler/state",
|
|
252
|
+
type: "boolean",
|
|
253
|
+
})
|
|
254
|
+
.option("persist-to", {
|
|
255
|
+
describe:
|
|
256
|
+
"Specify directory to use for local persistence (implies --persist)",
|
|
257
|
+
type: "string",
|
|
258
|
+
requiresArg: true,
|
|
244
259
|
})
|
|
245
260
|
.option("live-reload", {
|
|
246
261
|
// TODO: Add back in once we have remote `--live-reload`
|
|
@@ -342,6 +357,7 @@ export async function startDev(args: StartDevOptions) {
|
|
|
342
357
|
getLocalPort,
|
|
343
358
|
getInspectorPort,
|
|
344
359
|
cliDefines,
|
|
360
|
+
localPersistencePath,
|
|
345
361
|
} = await validateDevServerSettings(args, config);
|
|
346
362
|
|
|
347
363
|
await metrics.sendMetricsEvent(
|
|
@@ -382,9 +398,7 @@ export async function startDev(args: StartDevOptions) {
|
|
|
382
398
|
upstreamProtocol={upstreamProtocol}
|
|
383
399
|
localProtocol={args.localProtocol || configParam.dev.local_protocol}
|
|
384
400
|
localUpstream={args["local-upstream"] || host}
|
|
385
|
-
|
|
386
|
-
args.experimentalEnableLocalPersistence || false
|
|
387
|
-
}
|
|
401
|
+
localPersistencePath={localPersistencePath}
|
|
388
402
|
liveReload={args.liveReload || false}
|
|
389
403
|
accountId={configParam.account_id || getAccountFromCache()?.id}
|
|
390
404
|
assetPaths={assetPaths}
|
|
@@ -457,6 +471,7 @@ export async function startApiDev(args: StartDevOptions) {
|
|
|
457
471
|
getLocalPort,
|
|
458
472
|
getInspectorPort,
|
|
459
473
|
cliDefines,
|
|
474
|
+
localPersistencePath,
|
|
460
475
|
} = await validateDevServerSettings(args, config);
|
|
461
476
|
|
|
462
477
|
await metrics.sendMetricsEvent(
|
|
@@ -493,7 +508,7 @@ export async function startApiDev(args: StartDevOptions) {
|
|
|
493
508
|
upstreamProtocol: upstreamProtocol,
|
|
494
509
|
localProtocol: args.localProtocol || configParam.dev.local_protocol,
|
|
495
510
|
localUpstream: args["local-upstream"] || host,
|
|
496
|
-
|
|
511
|
+
localPersistencePath: localPersistencePath,
|
|
497
512
|
liveReload: args.liveReload || false,
|
|
498
513
|
accountId: configParam.account_id || getAccountFromCache()?.id,
|
|
499
514
|
assetPaths: assetPaths,
|
|
@@ -670,6 +685,23 @@ async function validateDevServerSettings(
|
|
|
670
685
|
);
|
|
671
686
|
}
|
|
672
687
|
|
|
688
|
+
if (args.experimentalEnableLocalPersistence) {
|
|
689
|
+
logger.warn(
|
|
690
|
+
`--experimental-enable-local-persistence is deprecated.\n` +
|
|
691
|
+
`Move any existing data to .wrangler/state and use --persist, or\n` +
|
|
692
|
+
`use --persist-to=./wrangler-local-state to keep using the old path.`
|
|
693
|
+
);
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
const localPersistencePath = args.persistTo
|
|
697
|
+
? // If path specified, always treat it as relative to cwd()
|
|
698
|
+
path.resolve(process.cwd(), args.persistTo)
|
|
699
|
+
: args.persist
|
|
700
|
+
? // If just flagged on, treat it as relative to wrangler.toml,
|
|
701
|
+
// if one can be found, otherwise cwd()
|
|
702
|
+
path.resolve(config.configPath || process.cwd(), ".wrangler/state")
|
|
703
|
+
: null;
|
|
704
|
+
|
|
673
705
|
const cliDefines =
|
|
674
706
|
args.define?.reduce<Record<string, string>>((collectDefines, d) => {
|
|
675
707
|
const [key, ...value] = d.split(":");
|
|
@@ -687,6 +719,7 @@ async function validateDevServerSettings(
|
|
|
687
719
|
host,
|
|
688
720
|
routes,
|
|
689
721
|
cliDefines,
|
|
722
|
+
localPersistencePath,
|
|
690
723
|
};
|
|
691
724
|
}
|
|
692
725
|
|
package/src/dialogs.tsx
CHANGED
|
@@ -4,7 +4,11 @@ import SelectInput from "ink-select-input";
|
|
|
4
4
|
import TextInput from "ink-text-input";
|
|
5
5
|
import * as React from "react";
|
|
6
6
|
import { useState } from "react";
|
|
7
|
+
|
|
8
|
+
import { CI } from "./is-ci";
|
|
9
|
+
import isInteractive from "./is-interactive";
|
|
7
10
|
import { logger } from "./logger";
|
|
11
|
+
|
|
8
12
|
type ConfirmProps = {
|
|
9
13
|
text: string;
|
|
10
14
|
onConfirm: (answer: boolean) => void;
|
|
@@ -135,13 +139,16 @@ export function select(
|
|
|
135
139
|
}
|
|
136
140
|
|
|
137
141
|
export async function fromDashMessagePrompt(
|
|
138
|
-
deploySource:
|
|
142
|
+
deploySource: "dash" | "wrangler" | "api"
|
|
139
143
|
): Promise<boolean | void> {
|
|
140
144
|
if (deploySource === "dash") {
|
|
141
145
|
logger.warn(
|
|
142
146
|
`You are about to publish a Workers Service that was last published via the Cloudflare Dashboard.
|
|
143
147
|
Edits that have been made via the dashboard will be overridden by your local code and config.`
|
|
144
148
|
);
|
|
149
|
+
|
|
150
|
+
if (!isInteractive() || CI.isCI()) return true;
|
|
151
|
+
|
|
145
152
|
return await confirm("Would you like to continue?");
|
|
146
153
|
}
|
|
147
154
|
}
|
package/src/index.tsx
CHANGED
|
@@ -1163,6 +1163,96 @@ function createCLIParser(argv: string[]) {
|
|
|
1163
1163
|
}
|
|
1164
1164
|
);
|
|
1165
1165
|
|
|
1166
|
+
wrangler.command(
|
|
1167
|
+
"secret:bulk <json>",
|
|
1168
|
+
"🗄️ Bulk upload secrets for a Worker",
|
|
1169
|
+
(yargs) => {
|
|
1170
|
+
return yargs
|
|
1171
|
+
.positional("json", {
|
|
1172
|
+
describe: `The JSON file of key-value pairs to upload, in form {"key": value, ...}`,
|
|
1173
|
+
type: "string",
|
|
1174
|
+
demandOption: "true",
|
|
1175
|
+
})
|
|
1176
|
+
.option("name", {
|
|
1177
|
+
describe: "Name of the Worker",
|
|
1178
|
+
type: "string",
|
|
1179
|
+
requiresArg: true,
|
|
1180
|
+
})
|
|
1181
|
+
.option("env", {
|
|
1182
|
+
type: "string",
|
|
1183
|
+
requiresArg: true,
|
|
1184
|
+
describe:
|
|
1185
|
+
"Binds the secret to the Worker of the specific environment.",
|
|
1186
|
+
alias: "e",
|
|
1187
|
+
});
|
|
1188
|
+
},
|
|
1189
|
+
async (secretBulkArgs) => {
|
|
1190
|
+
await printWranglerBanner();
|
|
1191
|
+
const config = readConfig(
|
|
1192
|
+
secretBulkArgs.config as ConfigPath,
|
|
1193
|
+
secretBulkArgs
|
|
1194
|
+
);
|
|
1195
|
+
|
|
1196
|
+
const scriptName = getLegacyScriptName(secretBulkArgs, config);
|
|
1197
|
+
if (!scriptName) {
|
|
1198
|
+
throw new Error(
|
|
1199
|
+
"Required Worker name missing. Please specify the Worker name in wrangler.toml, or pass it as an argument with `--name <worker-name>`"
|
|
1200
|
+
);
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
const accountId = await requireAuth(config);
|
|
1204
|
+
|
|
1205
|
+
logger.log(
|
|
1206
|
+
`🌀 Creating the secrets for the Worker "${scriptName}" ${
|
|
1207
|
+
secretBulkArgs.env && !isLegacyEnv(config)
|
|
1208
|
+
? `(${secretBulkArgs.env})`
|
|
1209
|
+
: ""
|
|
1210
|
+
}`
|
|
1211
|
+
);
|
|
1212
|
+
const jsonFilePath = path.resolve(secretBulkArgs.json);
|
|
1213
|
+
const content = parseJSON<Record<string, string>>(
|
|
1214
|
+
readFileSync(jsonFilePath),
|
|
1215
|
+
jsonFilePath
|
|
1216
|
+
);
|
|
1217
|
+
for (const key in content) {
|
|
1218
|
+
if (typeof content[key] !== "string") {
|
|
1219
|
+
throw new Error(
|
|
1220
|
+
`The value for ${key} in ${jsonFilePath} is not a string.`
|
|
1221
|
+
);
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
const url =
|
|
1226
|
+
!secretBulkArgs.env || isLegacyEnv(config)
|
|
1227
|
+
? `/accounts/${accountId}/workers/scripts/${scriptName}/secrets`
|
|
1228
|
+
: `/accounts/${accountId}/workers/services/${scriptName}/environments/${secretBulkArgs.env}/secrets`;
|
|
1229
|
+
// Until we have a bulk route for secrets, we need to make a request for each key/value pair
|
|
1230
|
+
await Promise.allSettled(
|
|
1231
|
+
Object.entries(content).map(async ([key, value]) => {
|
|
1232
|
+
return fetchResult(url, {
|
|
1233
|
+
method: "PUT",
|
|
1234
|
+
headers: { "Content-Type": "application/json" },
|
|
1235
|
+
body: JSON.stringify({
|
|
1236
|
+
name: key,
|
|
1237
|
+
text: value,
|
|
1238
|
+
type: "secret_text",
|
|
1239
|
+
}),
|
|
1240
|
+
})
|
|
1241
|
+
.then(() => {
|
|
1242
|
+
logger.log(`✨ Successfully created secret for key: ${key}`);
|
|
1243
|
+
})
|
|
1244
|
+
.catch((e) => {
|
|
1245
|
+
logger.error(
|
|
1246
|
+
`🚨 Error uploading secret for key: ${key}:
|
|
1247
|
+
${e.message}`
|
|
1248
|
+
);
|
|
1249
|
+
});
|
|
1250
|
+
})
|
|
1251
|
+
);
|
|
1252
|
+
return logger.log("✨ Finished processing secrets JSON file");
|
|
1253
|
+
}
|
|
1254
|
+
);
|
|
1255
|
+
|
|
1166
1256
|
// kv
|
|
1167
1257
|
// :namespace
|
|
1168
1258
|
wrangler.command(
|
package/src/pages/dev.tsx
CHANGED
|
@@ -116,9 +116,22 @@ export function Options(yargs: Argv) {
|
|
|
116
116
|
choices: ["http", "https"] as const,
|
|
117
117
|
},
|
|
118
118
|
"experimental-enable-local-persistence": {
|
|
119
|
+
describe:
|
|
120
|
+
"Enable persistence for local mode (deprecated, use --persist)",
|
|
119
121
|
type: "boolean",
|
|
120
|
-
|
|
121
|
-
|
|
122
|
+
deprecated: true,
|
|
123
|
+
hidden: true,
|
|
124
|
+
},
|
|
125
|
+
persist: {
|
|
126
|
+
describe:
|
|
127
|
+
"Enable persistence for local mode, using default path: .wrangler/state",
|
|
128
|
+
type: "boolean",
|
|
129
|
+
},
|
|
130
|
+
"persist-to": {
|
|
131
|
+
describe:
|
|
132
|
+
"Specify directory to use for local persistence (implies --persist)",
|
|
133
|
+
type: "string",
|
|
134
|
+
requiresArg: true,
|
|
122
135
|
},
|
|
123
136
|
"node-compat": {
|
|
124
137
|
describe: "Enable node.js compatibility",
|
|
@@ -151,7 +164,9 @@ export const Handler = async ({
|
|
|
151
164
|
r2: r2s = [],
|
|
152
165
|
"live-reload": liveReload,
|
|
153
166
|
"local-protocol": localProtocol,
|
|
154
|
-
|
|
167
|
+
experimentalEnableLocalPersistence,
|
|
168
|
+
persist,
|
|
169
|
+
persistTo,
|
|
155
170
|
"node-compat": nodeCompat,
|
|
156
171
|
config: config,
|
|
157
172
|
_: [_pages, _dev, ...remaining],
|
|
@@ -189,6 +204,14 @@ export const Handler = async ({
|
|
|
189
204
|
directory = resolve(directory);
|
|
190
205
|
}
|
|
191
206
|
|
|
207
|
+
if (experimentalEnableLocalPersistence) {
|
|
208
|
+
logger.warn(
|
|
209
|
+
`--experimental-enable-local-persistence is deprecated.\n` +
|
|
210
|
+
`Move any existing data to .wrangler/state and use --persist, or\n` +
|
|
211
|
+
`use --persist-to=./wrangler-local-state to keep using the old path.`
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
192
215
|
let scriptReadyResolve: () => void;
|
|
193
216
|
const scriptReadyPromise = new Promise<void>(
|
|
194
217
|
(promiseResolve) => (scriptReadyResolve = promiseResolve)
|
|
@@ -358,7 +381,8 @@ export const Handler = async ({
|
|
|
358
381
|
directory,
|
|
359
382
|
},
|
|
360
383
|
forceLocal: true,
|
|
361
|
-
|
|
384
|
+
persist,
|
|
385
|
+
persistTo,
|
|
362
386
|
showInteractiveDevSession: undefined,
|
|
363
387
|
inspect: true,
|
|
364
388
|
logLevel: "error",
|
package/src/publish.ts
CHANGED
|
@@ -220,21 +220,29 @@ export default async function publish(props: Props): Promise<void> {
|
|
|
220
220
|
// TODO: warn if git/hg has uncommitted changes
|
|
221
221
|
const { config, accountId, name } = props;
|
|
222
222
|
if (accountId && name) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
default_environment
|
|
228
|
-
|
|
223
|
+
try {
|
|
224
|
+
const serviceMetaData = await fetchResult(
|
|
225
|
+
`/accounts/${accountId}/workers/services/${name}`
|
|
226
|
+
);
|
|
227
|
+
const { default_environment } = serviceMetaData as {
|
|
228
|
+
default_environment: {
|
|
229
|
+
script: { last_deployed_from: "dash" | "wrangler" | "api" };
|
|
230
|
+
};
|
|
229
231
|
};
|
|
230
|
-
};
|
|
231
232
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
233
|
+
if (
|
|
234
|
+
(await fromDashMessagePrompt(
|
|
235
|
+
default_environment.script.last_deployed_from
|
|
236
|
+
)) === false
|
|
237
|
+
)
|
|
238
|
+
return;
|
|
239
|
+
} catch (e) {
|
|
240
|
+
// code: 10090, message: workers.api.error.service_not_found
|
|
241
|
+
// is thrown from the above fetchResult on the first publish of a Worker
|
|
242
|
+
if ((e as { code?: number }).code !== 10090) {
|
|
243
|
+
logger.error(e);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
238
246
|
}
|
|
239
247
|
|
|
240
248
|
if (!(props.compatibilityDate || config.compatibility_date)) {
|
package/wrangler-dist/cli.d.ts
CHANGED
|
@@ -52,7 +52,8 @@ declare interface DevOptions {
|
|
|
52
52
|
nodeCompat?: boolean;
|
|
53
53
|
compatibilityDate?: string;
|
|
54
54
|
compatibilityFlags?: string[];
|
|
55
|
-
|
|
55
|
+
persist?: boolean;
|
|
56
|
+
persistTo?: string;
|
|
56
57
|
liveReload?: boolean;
|
|
57
58
|
watch?: boolean;
|
|
58
59
|
vars?: {
|