wrangler 2.0.19 → 2.0.23
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 +464 -4
- package/package.json +11 -3
- package/src/__tests__/dev.test.tsx +136 -4
- package/src/__tests__/kv.test.ts +80 -59
- package/src/__tests__/metrics.test.ts +30 -0
- package/src/__tests__/publish.test.ts +76 -0
- package/src/__tests__/version.test.ts +35 -0
- package/src/api/dev.ts +43 -9
- package/src/bundle.ts +30 -4
- package/src/config/config.ts +7 -0
- package/src/config/validation.ts +9 -1
- package/src/create-worker-preview.ts +3 -1
- package/src/dev/dev.tsx +55 -20
- package/src/dev/local.tsx +29 -10
- package/src/dev/remote.tsx +5 -5
- package/src/dev.tsx +84 -30
- package/src/index.tsx +63 -26
- package/src/metrics/is-ci.ts +14 -0
- package/src/metrics/metrics-config.ts +32 -15
- package/src/metrics/metrics-dispatcher.ts +27 -25
- package/src/metrics/send-event.ts +27 -15
- package/src/miniflare-cli/assets.ts +543 -0
- package/src/miniflare-cli/index.ts +36 -4
- package/src/pages/build.tsx +1 -1
- package/src/pages/deployments.tsx +5 -2
- package/src/pages/dev.tsx +81 -640
- package/src/pages/projects.tsx +6 -3
- package/src/pages/publish.tsx +2 -2
- package/src/publish.ts +13 -0
- package/src/pubsub/pubsub-commands.tsx +19 -16
- package/src/user/choose-account.tsx +20 -11
- package/src/user/user.tsx +2 -1
- package/src/whoami.tsx +2 -1
- package/src/worker-namespace.ts +5 -5
- package/templates/pages-shim.ts +9 -0
- package/wrangler-dist/cli.d.ts +32 -3
- package/wrangler-dist/cli.js +1077 -5934
package/src/dev.tsx
CHANGED
|
@@ -22,10 +22,12 @@ import {
|
|
|
22
22
|
getDevCompatibilityDate,
|
|
23
23
|
getRules,
|
|
24
24
|
isLegacyEnv,
|
|
25
|
+
DEFAULT_INSPECTOR_PORT,
|
|
25
26
|
} from "./index";
|
|
26
27
|
|
|
27
28
|
import type { Config } from "./config";
|
|
28
29
|
import type { Route } from "./config/environment";
|
|
30
|
+
import type { EnablePagesAssetsServiceBindingOptions } from "./miniflare-cli";
|
|
29
31
|
import type { CfWorkerInit } from "./worker";
|
|
30
32
|
import type { RequestInit } from "undici";
|
|
31
33
|
import type { Argv, ArgumentsCamelCase } from "yargs";
|
|
@@ -63,8 +65,10 @@ interface DevArgs {
|
|
|
63
65
|
minify?: boolean;
|
|
64
66
|
"node-compat"?: boolean;
|
|
65
67
|
"experimental-enable-local-persistence"?: boolean;
|
|
68
|
+
"live-reload"?: boolean;
|
|
66
69
|
onReady?: () => void;
|
|
67
70
|
logLevel?: "none" | "error" | "log" | "warn" | "debug";
|
|
71
|
+
logPrefix?: string;
|
|
68
72
|
showInteractiveDevSession?: boolean;
|
|
69
73
|
}
|
|
70
74
|
|
|
@@ -225,6 +229,12 @@ export function devOptions(yargs: Argv): Argv<DevArgs> {
|
|
|
225
229
|
describe: "Enable persistence for this session (only for local mode)",
|
|
226
230
|
type: "boolean",
|
|
227
231
|
})
|
|
232
|
+
.option("live-reload", {
|
|
233
|
+
// TODO: Add back in once we have remote `--live-reload`
|
|
234
|
+
hidden: true,
|
|
235
|
+
// describe: "Auto reload HTML pages when change is detected",
|
|
236
|
+
type: "boolean",
|
|
237
|
+
})
|
|
228
238
|
.option("inspect", {
|
|
229
239
|
describe: "Enable dev tools",
|
|
230
240
|
type: "boolean",
|
|
@@ -250,7 +260,28 @@ export async function devHandler(args: ArgumentsCamelCase<DevArgs>) {
|
|
|
250
260
|
}
|
|
251
261
|
}
|
|
252
262
|
|
|
253
|
-
|
|
263
|
+
type StartDevOptions = ArgumentsCamelCase<DevArgs> & {
|
|
264
|
+
// These options can be passed in directly when called with the `wrangler.dev()` API.
|
|
265
|
+
// They aren't exposed as CLI arguments.
|
|
266
|
+
vars?: {
|
|
267
|
+
[key: string]: unknown;
|
|
268
|
+
};
|
|
269
|
+
kv?: {
|
|
270
|
+
binding: string;
|
|
271
|
+
id: string;
|
|
272
|
+
preview_id?: string;
|
|
273
|
+
}[];
|
|
274
|
+
durableObjects?: {
|
|
275
|
+
name: string;
|
|
276
|
+
class_name: string;
|
|
277
|
+
script_name?: string | undefined;
|
|
278
|
+
environment?: string | undefined;
|
|
279
|
+
}[];
|
|
280
|
+
forceLocal?: boolean;
|
|
281
|
+
enablePagesAssetsServiceBinding?: EnablePagesAssetsServiceBindingOptions;
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
export async function startDev(args: StartDevOptions) {
|
|
254
285
|
let watcher: ReturnType<typeof watch> | undefined;
|
|
255
286
|
let rerender: (node: React.ReactNode) => void | undefined;
|
|
256
287
|
try {
|
|
@@ -265,7 +296,7 @@ export async function startDev(args: ArgumentsCamelCase<DevArgs>) {
|
|
|
265
296
|
((args.script &&
|
|
266
297
|
findWranglerToml(path.dirname(args.script))) as ConfigPath);
|
|
267
298
|
let config = readConfig(configPath, args);
|
|
268
|
-
metrics.sendMetricsEvent(
|
|
299
|
+
await metrics.sendMetricsEvent(
|
|
269
300
|
"run dev",
|
|
270
301
|
{ local: args.local },
|
|
271
302
|
{ sendMetrics: config.send_metrics, offline: args.local }
|
|
@@ -351,6 +382,10 @@ export async function startDev(args: ArgumentsCamelCase<DevArgs>) {
|
|
|
351
382
|
const routes: Route[] | undefined =
|
|
352
383
|
args.routes || (config.route && [config.route]) || config.routes;
|
|
353
384
|
|
|
385
|
+
if (args.forceLocal) {
|
|
386
|
+
args.local = true;
|
|
387
|
+
}
|
|
388
|
+
|
|
354
389
|
if (!args.local) {
|
|
355
390
|
if (host) {
|
|
356
391
|
zoneId = await getZoneIdFromHost(host);
|
|
@@ -370,7 +405,7 @@ export async function startDev(args: ArgumentsCamelCase<DevArgs>) {
|
|
|
370
405
|
}
|
|
371
406
|
}
|
|
372
407
|
|
|
373
|
-
const nodeCompat = args
|
|
408
|
+
const nodeCompat = args.nodeCompat ?? config.node_compat;
|
|
374
409
|
if (nodeCompat) {
|
|
375
410
|
logger.warn(
|
|
376
411
|
"Enabling node.js compatibility mode for built-ins and globals. This is experimental and has serious tradeoffs. Please see https://github.com/ionic-team/rollup-plugin-node-polyfills/ for more details."
|
|
@@ -382,33 +417,44 @@ export async function startDev(args: ArgumentsCamelCase<DevArgs>) {
|
|
|
382
417
|
configParam: Config
|
|
383
418
|
): Promise<CfWorkerInit["bindings"]> {
|
|
384
419
|
return {
|
|
385
|
-
kv_namespaces:
|
|
386
|
-
(
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
420
|
+
kv_namespaces: [
|
|
421
|
+
...(configParam.kv_namespaces || []).map(
|
|
422
|
+
({ binding, preview_id, id: _id }) => {
|
|
423
|
+
// In `dev`, we make folks use a separate kv namespace called
|
|
424
|
+
// `preview_id` instead of `id` so that they don't
|
|
425
|
+
// break production data. So here we check that a `preview_id`
|
|
426
|
+
// has actually been configured.
|
|
427
|
+
// This whole block of code will be obsoleted in the future
|
|
428
|
+
// when we have copy-on-write for previews on edge workers.
|
|
429
|
+
if (!preview_id) {
|
|
430
|
+
// TODO: This error has to be a _lot_ better, ideally just asking
|
|
431
|
+
// to create a preview namespace for the user automatically
|
|
432
|
+
throw new Error(
|
|
433
|
+
`In development, you should use a separate kv namespace than the one you'd use in production. Please create a new kv namespace with "wrangler kv:namespace create <name> --preview" and add its id as preview_id to the kv_namespace "${binding}" in your wrangler.toml`
|
|
434
|
+
); // Ugh, I really don't like this message very much
|
|
435
|
+
}
|
|
436
|
+
return {
|
|
437
|
+
binding,
|
|
438
|
+
id: preview_id,
|
|
439
|
+
};
|
|
399
440
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
};
|
|
404
|
-
}
|
|
405
|
-
),
|
|
441
|
+
),
|
|
442
|
+
...(args.kv || []),
|
|
443
|
+
],
|
|
406
444
|
// Use a copy of combinedVars since we're modifying it later
|
|
407
|
-
vars:
|
|
445
|
+
vars: {
|
|
446
|
+
...getVarsForDev(configParam),
|
|
447
|
+
...args.vars,
|
|
448
|
+
},
|
|
408
449
|
wasm_modules: configParam.wasm_modules,
|
|
409
450
|
text_blobs: configParam.text_blobs,
|
|
410
451
|
data_blobs: configParam.data_blobs,
|
|
411
|
-
durable_objects:
|
|
452
|
+
durable_objects: {
|
|
453
|
+
bindings: [
|
|
454
|
+
...(configParam.durable_objects || { bindings: [] }).bindings,
|
|
455
|
+
...(args.durableObjects || []),
|
|
456
|
+
],
|
|
457
|
+
},
|
|
412
458
|
r2_buckets: configParam.r2_buckets?.map(
|
|
413
459
|
({ binding, preview_bucket_name, bucket_name: _bucket_name }) => {
|
|
414
460
|
// same idea as kv namespace preview id,
|
|
@@ -431,7 +477,7 @@ export async function startDev(args: ArgumentsCamelCase<DevArgs>) {
|
|
|
431
477
|
}
|
|
432
478
|
|
|
433
479
|
const getLocalPort = memoizeGetPort(DEFAULT_LOCAL_PORT);
|
|
434
|
-
const getInspectorPort = memoizeGetPort(
|
|
480
|
+
const getInspectorPort = memoizeGetPort(DEFAULT_INSPECTOR_PORT);
|
|
435
481
|
|
|
436
482
|
// eslint-disable-next-line no-inner-declarations
|
|
437
483
|
async function getDevReactElement(configParam: Config) {
|
|
@@ -483,16 +529,21 @@ export async function startDev(args: ArgumentsCamelCase<DevArgs>) {
|
|
|
483
529
|
jsxFragment={args["jsx-fragment"] || config.jsx_fragment}
|
|
484
530
|
tsconfig={args.tsconfig ?? config.tsconfig}
|
|
485
531
|
upstreamProtocol={upstreamProtocol}
|
|
486
|
-
localProtocol={args
|
|
532
|
+
localProtocol={args.localProtocol || config.dev.local_protocol}
|
|
487
533
|
localUpstream={args["local-upstream"] || host}
|
|
488
534
|
enableLocalPersistence={
|
|
489
|
-
args
|
|
535
|
+
args.experimentalEnableLocalPersistence || false
|
|
490
536
|
}
|
|
537
|
+
liveReload={args.liveReload || false}
|
|
491
538
|
accountId={config.account_id || getAccountFromCache()?.id}
|
|
492
539
|
assetPaths={assetPaths}
|
|
493
540
|
port={args.port || config.dev.port || (await getLocalPort())}
|
|
494
541
|
ip={args.ip || config.dev.ip}
|
|
495
|
-
inspectorPort={
|
|
542
|
+
inspectorPort={
|
|
543
|
+
args["inspector-port"] ||
|
|
544
|
+
config.dev.inspector_port ||
|
|
545
|
+
(await getInspectorPort())
|
|
546
|
+
}
|
|
496
547
|
isWorkersSite={Boolean(args.site || config.site)}
|
|
497
548
|
compatibilityDate={getDevCompatibilityDate(
|
|
498
549
|
config,
|
|
@@ -505,9 +556,12 @@ export async function startDev(args: ArgumentsCamelCase<DevArgs>) {
|
|
|
505
556
|
bindings={bindings}
|
|
506
557
|
crons={config.triggers.crons}
|
|
507
558
|
logLevel={args.logLevel}
|
|
559
|
+
logPrefix={args.logPrefix}
|
|
508
560
|
onReady={args.onReady}
|
|
509
|
-
inspect={args.inspect}
|
|
561
|
+
inspect={args.inspect ?? true}
|
|
510
562
|
showInteractiveDevSession={args.showInteractiveDevSession}
|
|
563
|
+
forceLocal={args.forceLocal}
|
|
564
|
+
enablePagesAssetsServiceBinding={args.enablePagesAssetsServiceBinding}
|
|
511
565
|
/>
|
|
512
566
|
);
|
|
513
567
|
}
|
package/src/index.tsx
CHANGED
|
@@ -76,6 +76,7 @@ export type ConfigPath = string | undefined;
|
|
|
76
76
|
const resetColor = "\x1b[0m";
|
|
77
77
|
const fgGreenColor = "\x1b[32m";
|
|
78
78
|
export const DEFAULT_LOCAL_PORT = 8787;
|
|
79
|
+
export const DEFAULT_INSPECTOR_PORT = 9229;
|
|
79
80
|
|
|
80
81
|
const proxy =
|
|
81
82
|
process.env.https_proxy ||
|
|
@@ -258,11 +259,22 @@ function createCLIParser(argv: string[]) {
|
|
|
258
259
|
["*"],
|
|
259
260
|
false,
|
|
260
261
|
() => {},
|
|
261
|
-
(args) => {
|
|
262
|
+
async (args) => {
|
|
262
263
|
if (args._.length > 0) {
|
|
263
264
|
throw new CommandLineArgsError(`Unknown command: ${args._}.`);
|
|
264
265
|
} else {
|
|
265
|
-
|
|
266
|
+
// args.v will exist and be true in the case that no command is called, and the -v
|
|
267
|
+
// option is present. This is to allow for running asynchronous printWranglerBanner
|
|
268
|
+
// in the version command.
|
|
269
|
+
if (args.v) {
|
|
270
|
+
if (process.stdout.isTTY) {
|
|
271
|
+
await printWranglerBanner();
|
|
272
|
+
} else {
|
|
273
|
+
logger.log(wranglerVersion);
|
|
274
|
+
}
|
|
275
|
+
} else {
|
|
276
|
+
wrangler.showHelp("log");
|
|
277
|
+
}
|
|
266
278
|
}
|
|
267
279
|
}
|
|
268
280
|
);
|
|
@@ -501,7 +513,7 @@ function createCLIParser(argv: string[]) {
|
|
|
501
513
|
(args.config as ConfigPath) ||
|
|
502
514
|
(args.script && findWranglerToml(path.dirname(args.script)));
|
|
503
515
|
const config = readConfig(configPath, args);
|
|
504
|
-
metrics.sendMetricsEvent("deploy worker script", {
|
|
516
|
+
await metrics.sendMetricsEvent("deploy worker script", {
|
|
505
517
|
sendMetrics: config.send_metrics,
|
|
506
518
|
});
|
|
507
519
|
const entry = await getEntry(args, config, "publish");
|
|
@@ -644,7 +656,7 @@ function createCLIParser(argv: string[]) {
|
|
|
644
656
|
await printWranglerBanner();
|
|
645
657
|
}
|
|
646
658
|
const config = readConfig(args.config as ConfigPath, args);
|
|
647
|
-
metrics.sendMetricsEvent("begin log stream", {
|
|
659
|
+
await metrics.sendMetricsEvent("begin log stream", {
|
|
648
660
|
sendMetrics: config.send_metrics,
|
|
649
661
|
});
|
|
650
662
|
|
|
@@ -692,7 +704,7 @@ function createCLIParser(argv: string[]) {
|
|
|
692
704
|
onExit(async () => {
|
|
693
705
|
tail.terminate();
|
|
694
706
|
await deleteTail();
|
|
695
|
-
metrics.sendMetricsEvent("end log stream", {
|
|
707
|
+
await metrics.sendMetricsEvent("end log stream", {
|
|
696
708
|
sendMetrics: config.send_metrics,
|
|
697
709
|
});
|
|
698
710
|
});
|
|
@@ -711,7 +723,7 @@ function createCLIParser(argv: string[]) {
|
|
|
711
723
|
await setTimeout(100);
|
|
712
724
|
break;
|
|
713
725
|
case tail.CLOSED:
|
|
714
|
-
metrics.sendMetricsEvent("end log stream", {
|
|
726
|
+
await metrics.sendMetricsEvent("end log stream", {
|
|
715
727
|
sendMetrics: config.send_metrics,
|
|
716
728
|
});
|
|
717
729
|
throw new Error(
|
|
@@ -727,7 +739,7 @@ function createCLIParser(argv: string[]) {
|
|
|
727
739
|
tail.on("close", async () => {
|
|
728
740
|
tail.terminate();
|
|
729
741
|
await deleteTail();
|
|
730
|
-
metrics.sendMetricsEvent("end log stream", {
|
|
742
|
+
await metrics.sendMetricsEvent("end log stream", {
|
|
731
743
|
sendMetrics: config.send_metrics,
|
|
732
744
|
});
|
|
733
745
|
});
|
|
@@ -960,7 +972,7 @@ function createCLIParser(argv: string[]) {
|
|
|
960
972
|
|
|
961
973
|
try {
|
|
962
974
|
await submitSecret();
|
|
963
|
-
metrics.sendMetricsEvent("create encrypted variable", {
|
|
975
|
+
await metrics.sendMetricsEvent("create encrypted variable", {
|
|
964
976
|
sendMetrics: config.send_metrics,
|
|
965
977
|
});
|
|
966
978
|
} catch (e) {
|
|
@@ -1035,7 +1047,7 @@ function createCLIParser(argv: string[]) {
|
|
|
1035
1047
|
: `/accounts/${accountId}/workers/services/${scriptName}/environments/${args.env}/secrets`;
|
|
1036
1048
|
|
|
1037
1049
|
await fetchResult(`${url}/${args.key}`, { method: "DELETE" });
|
|
1038
|
-
metrics.sendMetricsEvent("delete encrypted variable", {
|
|
1050
|
+
await metrics.sendMetricsEvent("delete encrypted variable", {
|
|
1039
1051
|
sendMetrics: config.send_metrics,
|
|
1040
1052
|
});
|
|
1041
1053
|
logger.log(`✨ Success! Deleted secret ${args.key}`);
|
|
@@ -1078,7 +1090,7 @@ function createCLIParser(argv: string[]) {
|
|
|
1078
1090
|
: `/accounts/${accountId}/workers/services/${scriptName}/environments/${args.env}/secrets`;
|
|
1079
1091
|
|
|
1080
1092
|
logger.log(JSON.stringify(await fetchResult(url), null, " "));
|
|
1081
|
-
metrics.sendMetricsEvent("list encrypted variables", {
|
|
1093
|
+
await metrics.sendMetricsEvent("list encrypted variables", {
|
|
1082
1094
|
sendMetrics: config.send_metrics,
|
|
1083
1095
|
});
|
|
1084
1096
|
}
|
|
@@ -1142,7 +1154,7 @@ function createCLIParser(argv: string[]) {
|
|
|
1142
1154
|
|
|
1143
1155
|
logger.log(`🌀 Creating namespace with title "${title}"`);
|
|
1144
1156
|
const namespaceId = await createKVNamespace(accountId, title);
|
|
1145
|
-
metrics.sendMetricsEvent("create kv namespace", {
|
|
1157
|
+
await metrics.sendMetricsEvent("create kv namespace", {
|
|
1146
1158
|
sendMetrics: config.send_metrics,
|
|
1147
1159
|
});
|
|
1148
1160
|
|
|
@@ -1173,7 +1185,7 @@ function createCLIParser(argv: string[]) {
|
|
|
1173
1185
|
logger.log(
|
|
1174
1186
|
JSON.stringify(await listKVNamespaces(accountId), null, " ")
|
|
1175
1187
|
);
|
|
1176
|
-
metrics.sendMetricsEvent("list kv namespaces", {
|
|
1188
|
+
await metrics.sendMetricsEvent("list kv namespaces", {
|
|
1177
1189
|
sendMetrics: config.send_metrics,
|
|
1178
1190
|
});
|
|
1179
1191
|
}
|
|
@@ -1220,8 +1232,10 @@ function createCLIParser(argv: string[]) {
|
|
|
1220
1232
|
|
|
1221
1233
|
const accountId = await requireAuth(config);
|
|
1222
1234
|
|
|
1235
|
+
logger.log(`Deleting KV namespace ${id}.`);
|
|
1223
1236
|
await deleteKVNamespace(accountId, id);
|
|
1224
|
-
|
|
1237
|
+
logger.log(`Deleted KV namespace ${id}.`);
|
|
1238
|
+
await metrics.sendMetricsEvent("delete kv namespace", {
|
|
1225
1239
|
sendMetrics: config.send_metrics,
|
|
1226
1240
|
});
|
|
1227
1241
|
|
|
@@ -1347,7 +1361,7 @@ function createCLIParser(argv: string[]) {
|
|
|
1347
1361
|
expiration_ttl: ttl,
|
|
1348
1362
|
metadata: metadata as KeyValue["metadata"],
|
|
1349
1363
|
});
|
|
1350
|
-
metrics.sendMetricsEvent("write kv key-value", {
|
|
1364
|
+
await metrics.sendMetricsEvent("write kv key-value", {
|
|
1351
1365
|
sendMetrics: config.send_metrics,
|
|
1352
1366
|
});
|
|
1353
1367
|
}
|
|
@@ -1399,7 +1413,7 @@ function createCLIParser(argv: string[]) {
|
|
|
1399
1413
|
prefix
|
|
1400
1414
|
);
|
|
1401
1415
|
logger.log(JSON.stringify(results, undefined, 2));
|
|
1402
|
-
metrics.sendMetricsEvent("list kv keys", {
|
|
1416
|
+
await metrics.sendMetricsEvent("list kv keys", {
|
|
1403
1417
|
sendMetrics: config.send_metrics,
|
|
1404
1418
|
});
|
|
1405
1419
|
}
|
|
@@ -1462,7 +1476,7 @@ function createCLIParser(argv: string[]) {
|
|
|
1462
1476
|
} else {
|
|
1463
1477
|
process.stdout.write(bufferKVValue);
|
|
1464
1478
|
}
|
|
1465
|
-
metrics.sendMetricsEvent("read kv value", {
|
|
1479
|
+
await metrics.sendMetricsEvent("read kv value", {
|
|
1466
1480
|
sendMetrics: config.send_metrics,
|
|
1467
1481
|
});
|
|
1468
1482
|
}
|
|
@@ -1511,7 +1525,7 @@ function createCLIParser(argv: string[]) {
|
|
|
1511
1525
|
const accountId = await requireAuth(config);
|
|
1512
1526
|
|
|
1513
1527
|
await deleteKVKeyValue(accountId, namespaceId, key);
|
|
1514
|
-
metrics.sendMetricsEvent("delete kv key-value", {
|
|
1528
|
+
await metrics.sendMetricsEvent("delete kv key-value", {
|
|
1515
1529
|
sendMetrics: config.send_metrics,
|
|
1516
1530
|
});
|
|
1517
1531
|
}
|
|
@@ -1618,7 +1632,7 @@ function createCLIParser(argv: string[]) {
|
|
|
1618
1632
|
|
|
1619
1633
|
const accountId = await requireAuth(config);
|
|
1620
1634
|
await putKVBulkKeyValue(accountId, namespaceId, content);
|
|
1621
|
-
metrics.sendMetricsEvent("write kv key-values (bulk)", {
|
|
1635
|
+
await metrics.sendMetricsEvent("write kv key-values (bulk)", {
|
|
1622
1636
|
sendMetrics: config.send_metrics,
|
|
1623
1637
|
});
|
|
1624
1638
|
|
|
@@ -1711,7 +1725,7 @@ function createCLIParser(argv: string[]) {
|
|
|
1711
1725
|
const accountId = await requireAuth(config);
|
|
1712
1726
|
|
|
1713
1727
|
await deleteKVBulkKeyValue(accountId, namespaceId, content);
|
|
1714
|
-
metrics.sendMetricsEvent("delete kv key-values (bulk)", {
|
|
1728
|
+
await metrics.sendMetricsEvent("delete kv key-values (bulk)", {
|
|
1715
1729
|
sendMetrics: config.send_metrics,
|
|
1716
1730
|
});
|
|
1717
1731
|
|
|
@@ -1753,7 +1767,7 @@ function createCLIParser(argv: string[]) {
|
|
|
1753
1767
|
logger.log(`Creating bucket ${args.name}.`);
|
|
1754
1768
|
await createR2Bucket(accountId, args.name);
|
|
1755
1769
|
logger.log(`Created bucket ${args.name}.`);
|
|
1756
|
-
metrics.sendMetricsEvent("create r2 bucket", {
|
|
1770
|
+
await metrics.sendMetricsEvent("create r2 bucket", {
|
|
1757
1771
|
sendMetrics: config.send_metrics,
|
|
1758
1772
|
});
|
|
1759
1773
|
}
|
|
@@ -1765,7 +1779,7 @@ function createCLIParser(argv: string[]) {
|
|
|
1765
1779
|
const accountId = await requireAuth(config);
|
|
1766
1780
|
|
|
1767
1781
|
logger.log(JSON.stringify(await listR2Buckets(accountId), null, 2));
|
|
1768
|
-
metrics.sendMetricsEvent("list r2 buckets", {
|
|
1782
|
+
await metrics.sendMetricsEvent("list r2 buckets", {
|
|
1769
1783
|
sendMetrics: config.send_metrics,
|
|
1770
1784
|
});
|
|
1771
1785
|
});
|
|
@@ -1790,7 +1804,7 @@ function createCLIParser(argv: string[]) {
|
|
|
1790
1804
|
logger.log(`Deleting bucket ${args.name}.`);
|
|
1791
1805
|
await deleteR2Bucket(accountId, args.name);
|
|
1792
1806
|
logger.log(`Deleted bucket ${args.name}.`);
|
|
1793
|
-
metrics.sendMetricsEvent("delete r2 bucket", {
|
|
1807
|
+
await metrics.sendMetricsEvent("delete r2 bucket", {
|
|
1794
1808
|
sendMetrics: config.send_metrics,
|
|
1795
1809
|
});
|
|
1796
1810
|
}
|
|
@@ -1862,7 +1876,7 @@ function createCLIParser(argv: string[]) {
|
|
|
1862
1876
|
}
|
|
1863
1877
|
await login();
|
|
1864
1878
|
const config = readConfig(args.config as ConfigPath, args);
|
|
1865
|
-
metrics.sendMetricsEvent("login user", {
|
|
1879
|
+
await metrics.sendMetricsEvent("login user", {
|
|
1866
1880
|
sendMetrics: config.send_metrics,
|
|
1867
1881
|
});
|
|
1868
1882
|
|
|
@@ -1882,7 +1896,7 @@ function createCLIParser(argv: string[]) {
|
|
|
1882
1896
|
await printWranglerBanner();
|
|
1883
1897
|
await logout();
|
|
1884
1898
|
const config = readConfig(undefined, {});
|
|
1885
|
-
metrics.sendMetricsEvent("logout user", {
|
|
1899
|
+
await metrics.sendMetricsEvent("logout user", {
|
|
1886
1900
|
sendMetrics: config.send_metrics,
|
|
1887
1901
|
});
|
|
1888
1902
|
}
|
|
@@ -1897,12 +1911,35 @@ function createCLIParser(argv: string[]) {
|
|
|
1897
1911
|
await printWranglerBanner();
|
|
1898
1912
|
await whoami();
|
|
1899
1913
|
const config = readConfig(undefined, {});
|
|
1900
|
-
metrics.sendMetricsEvent("view accounts", {
|
|
1914
|
+
await metrics.sendMetricsEvent("view accounts", {
|
|
1901
1915
|
sendMetrics: config.send_metrics,
|
|
1902
1916
|
});
|
|
1903
1917
|
}
|
|
1904
1918
|
);
|
|
1905
1919
|
|
|
1920
|
+
// This set to false to allow overwrite of default behaviour
|
|
1921
|
+
wrangler.version(false);
|
|
1922
|
+
|
|
1923
|
+
// version
|
|
1924
|
+
wrangler.command(
|
|
1925
|
+
"version",
|
|
1926
|
+
false,
|
|
1927
|
+
() => {},
|
|
1928
|
+
async () => {
|
|
1929
|
+
if (process.stdout.isTTY) {
|
|
1930
|
+
await printWranglerBanner();
|
|
1931
|
+
} else {
|
|
1932
|
+
logger.log(wranglerVersion);
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
);
|
|
1936
|
+
|
|
1937
|
+
wrangler.option("v", {
|
|
1938
|
+
describe: "Show version number",
|
|
1939
|
+
alias: "version",
|
|
1940
|
+
type: "boolean",
|
|
1941
|
+
});
|
|
1942
|
+
|
|
1906
1943
|
wrangler.option("config", {
|
|
1907
1944
|
alias: "c",
|
|
1908
1945
|
describe: "Path to .toml configuration file",
|
|
@@ -1912,7 +1949,7 @@ function createCLIParser(argv: string[]) {
|
|
|
1912
1949
|
|
|
1913
1950
|
wrangler.group(["config", "help", "version"], "Flags:");
|
|
1914
1951
|
wrangler.help().alias("h", "help");
|
|
1915
|
-
|
|
1952
|
+
|
|
1916
1953
|
wrangler.exitProcess(false);
|
|
1917
1954
|
|
|
1918
1955
|
return wrangler;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import isCI from "is-ci";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Use this object to find out if we are currently running in a continuous integration environment.
|
|
5
|
+
*
|
|
6
|
+
* The isCI constant imported above cannot be easily mocked for testing.
|
|
7
|
+
* By wrapping this up in a method on an object, it results in clean and testable code.
|
|
8
|
+
*/
|
|
9
|
+
export const CI = {
|
|
10
|
+
/** Is Wrangler currently running in a CI? */
|
|
11
|
+
isCI() {
|
|
12
|
+
return isCI;
|
|
13
|
+
},
|
|
14
|
+
};
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import {
|
|
2
|
+
import { readFileSync, mkdirSync, writeFileSync } from "node:fs";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { fetchResult } from "../cfetch";
|
|
6
6
|
import { getConfigCache, saveToConfigCache } from "../config-cache";
|
|
7
7
|
import { confirm } from "../dialogs";
|
|
8
|
+
import { getEnvironmentVariableFactory } from "../environment-variables";
|
|
8
9
|
import isInteractive from "../is-interactive";
|
|
9
10
|
import { logger } from "../logger";
|
|
10
11
|
import { getAPIToken } from "../user";
|
|
12
|
+
import { CI } from "./is-ci";
|
|
11
13
|
|
|
12
14
|
/**
|
|
13
15
|
* The date that the metrics being gathered was last updated in a way that would require
|
|
@@ -21,6 +23,10 @@ import { getAPIToken } from "../user";
|
|
|
21
23
|
export const CURRENT_METRICS_DATE = new Date(2022, 6, 4);
|
|
22
24
|
export const USER_ID_CACHE_PATH = "user-id.json";
|
|
23
25
|
|
|
26
|
+
export const getWranglerSendMetricsFromEnv = getEnvironmentVariableFactory({
|
|
27
|
+
variableName: "WRANGLER_SEND_METRICS",
|
|
28
|
+
});
|
|
29
|
+
|
|
24
30
|
export interface MetricsConfigOptions {
|
|
25
31
|
/**
|
|
26
32
|
* Defines whether to send metrics to Cloudflare:
|
|
@@ -66,10 +72,21 @@ export async function getMetricsConfig({
|
|
|
66
72
|
sendMetrics,
|
|
67
73
|
offline = false,
|
|
68
74
|
}: MetricsConfigOptions): Promise<MetricsConfig> {
|
|
69
|
-
const config =
|
|
70
|
-
const deviceId =
|
|
75
|
+
const config = readMetricsConfig();
|
|
76
|
+
const deviceId = getDeviceId(config);
|
|
71
77
|
const userId = await getUserId(offline);
|
|
72
78
|
|
|
79
|
+
// If the WRANGLER_SEND_METRICS environment variable has been set use that
|
|
80
|
+
// and ignore everything else.
|
|
81
|
+
const sendMetricsEnv = getWranglerSendMetricsFromEnv();
|
|
82
|
+
if (sendMetricsEnv !== undefined) {
|
|
83
|
+
return {
|
|
84
|
+
enabled: sendMetricsEnv.toLowerCase() === "true",
|
|
85
|
+
deviceId,
|
|
86
|
+
userId,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
73
90
|
// If the project is explicitly set the `send_metrics` options in `wrangler.toml`
|
|
74
91
|
// then use that and ignore any user preference.
|
|
75
92
|
if (sendMetrics !== undefined) {
|
|
@@ -89,8 +106,8 @@ export async function getMetricsConfig({
|
|
|
89
106
|
}
|
|
90
107
|
|
|
91
108
|
// We couldn't get the metrics permission from the project-level nor the user-level config.
|
|
92
|
-
// If we are not interactive then just bail out.
|
|
93
|
-
if (!isInteractive()) {
|
|
109
|
+
// If we are not interactive or in a CI build then just bail out.
|
|
110
|
+
if (!isInteractive() || CI.isCI()) {
|
|
94
111
|
return { enabled: false, deviceId, userId };
|
|
95
112
|
}
|
|
96
113
|
|
|
@@ -107,7 +124,7 @@ export async function getMetricsConfig({
|
|
|
107
124
|
" - to disable sending metrics for a project: `send_metrics = false`\n" +
|
|
108
125
|
" - to enable sending metrics for a project: `send_metrics = true`"
|
|
109
126
|
);
|
|
110
|
-
|
|
127
|
+
writeMetricsConfig({
|
|
111
128
|
permission: {
|
|
112
129
|
enabled,
|
|
113
130
|
date: CURRENT_METRICS_DATE,
|
|
@@ -120,9 +137,9 @@ export async function getMetricsConfig({
|
|
|
120
137
|
/**
|
|
121
138
|
* Stringify and write the given info to the metrics config file.
|
|
122
139
|
*/
|
|
123
|
-
export
|
|
124
|
-
|
|
125
|
-
|
|
140
|
+
export function writeMetricsConfig(config: MetricsConfigFile) {
|
|
141
|
+
mkdirSync(path.dirname(getMetricsConfigPath()), { recursive: true });
|
|
142
|
+
writeFileSync(
|
|
126
143
|
getMetricsConfigPath(),
|
|
127
144
|
JSON.stringify(
|
|
128
145
|
config,
|
|
@@ -135,11 +152,11 @@ export async function writeMetricsConfig(config: MetricsConfigFile) {
|
|
|
135
152
|
/**
|
|
136
153
|
* Read and parse the metrics config file.
|
|
137
154
|
*/
|
|
138
|
-
export
|
|
155
|
+
export function readMetricsConfig(): MetricsConfigFile {
|
|
139
156
|
try {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
157
|
+
const config = readFileSync(getMetricsConfigPath(), "utf8");
|
|
158
|
+
return JSON.parse(config, (key, value) =>
|
|
159
|
+
key === "date" ? new Date(value) : value
|
|
143
160
|
);
|
|
144
161
|
} catch {
|
|
145
162
|
return {};
|
|
@@ -172,12 +189,12 @@ export interface MetricsConfigFile {
|
|
|
172
189
|
*
|
|
173
190
|
* Once created this ID is stored in the metrics config file.
|
|
174
191
|
*/
|
|
175
|
-
|
|
192
|
+
function getDeviceId(config: MetricsConfigFile) {
|
|
176
193
|
// Get or create the deviceId.
|
|
177
194
|
const deviceId = config.deviceId ?? randomUUID();
|
|
178
195
|
if (config.deviceId === undefined) {
|
|
179
196
|
// We had to create a new deviceID so store it now.
|
|
180
|
-
|
|
197
|
+
writeMetricsConfig({ ...config, deviceId });
|
|
181
198
|
}
|
|
182
199
|
return deviceId;
|
|
183
200
|
}
|
|
@@ -47,6 +47,8 @@ export async function getMetricsDispatcher(options: MetricsConfigOptions) {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
// Lazily get the config for this dispatcher only when an event is being dispatched.
|
|
50
|
+
// We must await this since it might trigger user interaction that would break other UI
|
|
51
|
+
// in Wrangler if it was allowed to run in parallel.
|
|
50
52
|
const metricsConfig = await getMetricsConfig(options);
|
|
51
53
|
if (!metricsConfig.enabled) {
|
|
52
54
|
logger.debug(
|
|
@@ -57,36 +59,36 @@ export async function getMetricsDispatcher(options: MetricsConfigOptions) {
|
|
|
57
59
|
return;
|
|
58
60
|
}
|
|
59
61
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
});
|
|
62
|
+
logger.debug(`Metrics dispatcher: Posting data ${JSON.stringify(event)}`);
|
|
63
|
+
const body = JSON.stringify({
|
|
64
|
+
deviceId: metricsConfig.deviceId,
|
|
65
|
+
userId: metricsConfig.userId,
|
|
66
|
+
event: event.name,
|
|
67
|
+
properties: {
|
|
68
|
+
category: "Workers",
|
|
69
|
+
wranglerVersion,
|
|
70
|
+
...event.properties,
|
|
71
|
+
},
|
|
72
|
+
});
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
74
|
+
// Do not await this fetch call.
|
|
75
|
+
// Just fire-and-forget, otherwise we might slow down the rest of Wrangler.
|
|
76
|
+
fetch(`${SPARROW_URL}/api/v1/${event.type}`, {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: {
|
|
79
|
+
Accept: "*/*",
|
|
80
|
+
"Content-Type": "application/json",
|
|
81
|
+
"Sparrow-Source-Key": SPARROW_SOURCE_KEY,
|
|
82
|
+
},
|
|
83
|
+
mode: "cors",
|
|
84
|
+
keepalive: true,
|
|
85
|
+
body,
|
|
86
|
+
}).catch((e) => {
|
|
85
87
|
logger.debug(
|
|
86
88
|
"Metrics dispatcher: Failed to send request:",
|
|
87
89
|
(e as Error).message
|
|
88
90
|
);
|
|
89
|
-
}
|
|
91
|
+
});
|
|
90
92
|
}
|
|
91
93
|
}
|
|
92
94
|
|