wrangler 2.0.2 → 2.0.6
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/Cloudflare_CA.pem +18 -0
- package/bin/wrangler.js +23 -3
- package/package.json +4 -2
- package/pages/functions/buildWorker.ts +1 -1
- package/pages/functions/template-plugin.ts +3 -2
- package/src/__tests__/configuration.test.ts +205 -28
- package/src/__tests__/dev.test.tsx +137 -17
- package/src/__tests__/index.test.ts +55 -63
- package/src/__tests__/jest.setup.ts +8 -0
- package/src/__tests__/kv.test.ts +157 -130
- package/src/__tests__/pages.test.ts +34 -13
- package/src/__tests__/publish.test.ts +362 -14
- package/src/__tests__/r2.test.ts +55 -36
- package/src/__tests__/secret.test.ts +35 -0
- package/src/bundle.ts +32 -1
- package/src/cfetch/internal.ts +3 -0
- package/src/config/config.ts +1 -1
- package/src/config/environment.ts +40 -14
- package/src/config/validation.ts +103 -36
- package/src/create-worker-upload-form.ts +22 -8
- package/src/dev/dev.tsx +5 -2
- package/src/dev/local.tsx +6 -0
- package/src/entry.ts +64 -9
- package/src/index.tsx +119 -68
- package/src/kv.ts +55 -15
- package/src/pages.tsx +11 -5
- package/src/publish.ts +210 -21
- package/src/sites.tsx +13 -11
- package/src/user.tsx +11 -1
- package/src/worker.ts +8 -0
- package/wrangler-dist/cli.js +1430 -1004
package/src/index.tsx
CHANGED
|
@@ -22,17 +22,19 @@ import { confirm, prompt } from "./dialogs";
|
|
|
22
22
|
import { getEntry } from "./entry";
|
|
23
23
|
import { DeprecationError } from "./errors";
|
|
24
24
|
import {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
25
|
+
getKVNamespaceId,
|
|
26
|
+
listKVNamespaces,
|
|
27
|
+
listKVNamespaceKeys,
|
|
28
|
+
putKVKeyValue,
|
|
29
|
+
putKVBulkKeyValue,
|
|
30
|
+
deleteKVBulkKeyValue,
|
|
31
|
+
createKVNamespace,
|
|
32
|
+
isValidKVNamespaceBinding,
|
|
33
|
+
getKVKeyValue,
|
|
34
|
+
isKVKeyValue,
|
|
35
|
+
unexpectedKVKeyValueProps,
|
|
36
|
+
deleteKVNamespace,
|
|
37
|
+
deleteKVKeyValue,
|
|
36
38
|
} from "./kv";
|
|
37
39
|
import { logger } from "./logger";
|
|
38
40
|
import { getPackageManager } from "./package-manager";
|
|
@@ -73,6 +75,7 @@ type ConfigPath = string | undefined;
|
|
|
73
75
|
|
|
74
76
|
const resetColor = "\x1b[0m";
|
|
75
77
|
const fgGreenColor = "\x1b[32m";
|
|
78
|
+
const DEFAULT_LOCAL_PORT = 8787;
|
|
76
79
|
|
|
77
80
|
function getRules(config: Config): Config["rules"] {
|
|
78
81
|
const rules = config.rules ?? config.build?.upload?.rules ?? [];
|
|
@@ -203,9 +206,17 @@ function demandOneOfOption(...options: string[]) {
|
|
|
203
206
|
};
|
|
204
207
|
}
|
|
205
208
|
|
|
209
|
+
/**
|
|
210
|
+
* Remove trailing white space from inputs.
|
|
211
|
+
* Matching Wrangler legacy behavior with handling inputs
|
|
212
|
+
*/
|
|
213
|
+
function trimTrailingWhitespace(str: string) {
|
|
214
|
+
return str.trimEnd();
|
|
215
|
+
}
|
|
216
|
+
|
|
206
217
|
class CommandLineArgsError extends Error {}
|
|
207
218
|
|
|
208
|
-
|
|
219
|
+
function createCLIParser(argv: string[]) {
|
|
209
220
|
const wrangler = makeCLI(argv)
|
|
210
221
|
.strict()
|
|
211
222
|
// We handle errors ourselves in a try-catch around `yargs.parse`.
|
|
@@ -406,7 +417,12 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
406
417
|
const isInsideGitProject = Boolean(
|
|
407
418
|
await findUp(".git", { cwd: creationDirectory, type: "directory" })
|
|
408
419
|
);
|
|
409
|
-
|
|
420
|
+
let isGitInstalled;
|
|
421
|
+
try {
|
|
422
|
+
isGitInstalled = (await execa("git", ["--version"])).exitCode === 0;
|
|
423
|
+
} catch (err) {
|
|
424
|
+
isGitInstalled = false;
|
|
425
|
+
}
|
|
410
426
|
if (!isInsideGitProject && isGitInstalled) {
|
|
411
427
|
const shouldInitGit =
|
|
412
428
|
yesFlag ||
|
|
@@ -712,7 +728,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
712
728
|
() => {
|
|
713
729
|
// "[DEPRECATED] 🦀 Build your project (if applicable)",
|
|
714
730
|
throw new DeprecationError(
|
|
715
|
-
"`wrangler build` has been deprecated, please refer to https://
|
|
731
|
+
"`wrangler build` has been deprecated, please refer to https://developers.cloudflare.com/workers/wrangler/migration/deprecations/#build for alternatives"
|
|
716
732
|
);
|
|
717
733
|
}
|
|
718
734
|
);
|
|
@@ -725,7 +741,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
725
741
|
() => {
|
|
726
742
|
// "🕵️ Authenticate Wrangler with a Cloudflare API Token",
|
|
727
743
|
throw new DeprecationError(
|
|
728
|
-
"`wrangler config` has been deprecated, please refer to https://
|
|
744
|
+
"`wrangler config` has been deprecated, please refer to https://developers.cloudflare.com/workers/wrangler/migration/deprecations/#config for alternatives"
|
|
729
745
|
);
|
|
730
746
|
}
|
|
731
747
|
);
|
|
@@ -869,6 +885,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
869
885
|
describe: "Enable dev tools",
|
|
870
886
|
type: "boolean",
|
|
871
887
|
deprecated: true,
|
|
888
|
+
})
|
|
889
|
+
.option("legacy-env", {
|
|
890
|
+
type: "boolean",
|
|
891
|
+
describe: "Use legacy environments",
|
|
892
|
+
hidden: true,
|
|
872
893
|
});
|
|
873
894
|
},
|
|
874
895
|
async (args) => {
|
|
@@ -879,6 +900,19 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
879
900
|
const config = readConfig(configPath, args);
|
|
880
901
|
const entry = await getEntry(args, config, "dev");
|
|
881
902
|
|
|
903
|
+
if (config.services && config.services.length > 0) {
|
|
904
|
+
logger.warn(
|
|
905
|
+
`This worker is bound to live services: ${config.services
|
|
906
|
+
.map(
|
|
907
|
+
(service) =>
|
|
908
|
+
`${service.binding} (${service.service}${
|
|
909
|
+
service.environment ? `@${service.environment}` : ""
|
|
910
|
+
})`
|
|
911
|
+
)
|
|
912
|
+
.join(", ")}`
|
|
913
|
+
);
|
|
914
|
+
}
|
|
915
|
+
|
|
882
916
|
if (args.inspect) {
|
|
883
917
|
logger.warn(
|
|
884
918
|
"Passing --inspect is unnecessary, now you can always connect to devtools."
|
|
@@ -916,6 +950,9 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
916
950
|
* try to extract a host from it
|
|
917
951
|
*/
|
|
918
952
|
function getHost(urlLike: string): string | undefined {
|
|
953
|
+
// strip leading * / *.
|
|
954
|
+
urlLike = urlLike.replace(/^\*(\.)?/g, "");
|
|
955
|
+
|
|
919
956
|
if (
|
|
920
957
|
!(urlLike.startsWith("http://") || urlLike.startsWith("https://"))
|
|
921
958
|
) {
|
|
@@ -995,7 +1032,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
995
1032
|
const nodeCompat = args.nodeCompat ?? config.node_compat;
|
|
996
1033
|
if (nodeCompat) {
|
|
997
1034
|
logger.warn(
|
|
998
|
-
"Enabling node.js compatibility mode for
|
|
1035
|
+
"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."
|
|
999
1036
|
);
|
|
1000
1037
|
}
|
|
1001
1038
|
|
|
@@ -1027,7 +1064,9 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1027
1064
|
args.siteExclude
|
|
1028
1065
|
)}
|
|
1029
1066
|
port={
|
|
1030
|
-
args.port ||
|
|
1067
|
+
args.port ||
|
|
1068
|
+
config.dev.port ||
|
|
1069
|
+
(await getPort({ port: DEFAULT_LOCAL_PORT }))
|
|
1031
1070
|
}
|
|
1032
1071
|
ip={args.ip || config.dev.ip}
|
|
1033
1072
|
inspectorPort={
|
|
@@ -1084,6 +1123,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1084
1123
|
};
|
|
1085
1124
|
}
|
|
1086
1125
|
),
|
|
1126
|
+
services: config.services,
|
|
1087
1127
|
unsafe: config.unsafe?.bindings,
|
|
1088
1128
|
}}
|
|
1089
1129
|
crons={config.triggers.crons}
|
|
@@ -1206,6 +1246,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1206
1246
|
.option("dry-run", {
|
|
1207
1247
|
describe: "Don't actually publish",
|
|
1208
1248
|
type: "boolean",
|
|
1249
|
+
})
|
|
1250
|
+
.option("legacy-env", {
|
|
1251
|
+
type: "boolean",
|
|
1252
|
+
describe: "Use legacy environments",
|
|
1253
|
+
hidden: true,
|
|
1209
1254
|
});
|
|
1210
1255
|
},
|
|
1211
1256
|
async (args) => {
|
|
@@ -1233,7 +1278,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1233
1278
|
);
|
|
1234
1279
|
}
|
|
1235
1280
|
|
|
1236
|
-
const accountId = await requireAuth(config);
|
|
1281
|
+
const accountId = args.dryRun ? undefined : await requireAuth(config);
|
|
1237
1282
|
|
|
1238
1283
|
const assetPaths = getAssetPaths(
|
|
1239
1284
|
config,
|
|
@@ -1327,6 +1372,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1327
1372
|
default: false,
|
|
1328
1373
|
describe:
|
|
1329
1374
|
"If a log would have been filtered out, send it through anyway alongside the filter which would have blocked it.",
|
|
1375
|
+
})
|
|
1376
|
+
.option("legacy-env", {
|
|
1377
|
+
type: "boolean",
|
|
1378
|
+
describe: "Use legacy environments",
|
|
1379
|
+
hidden: true,
|
|
1330
1380
|
});
|
|
1331
1381
|
},
|
|
1332
1382
|
async (args) => {
|
|
@@ -1476,7 +1526,9 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1476
1526
|
enableLocalPersistence={false}
|
|
1477
1527
|
accountId={accountId}
|
|
1478
1528
|
assetPaths={undefined}
|
|
1479
|
-
port={
|
|
1529
|
+
port={
|
|
1530
|
+
config.dev.port || (await getPort({ port: DEFAULT_LOCAL_PORT }))
|
|
1531
|
+
}
|
|
1480
1532
|
ip={config.dev.ip}
|
|
1481
1533
|
public={undefined}
|
|
1482
1534
|
compatibilityDate={getDevCompatibilityDate(config)}
|
|
@@ -1524,6 +1576,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1524
1576
|
};
|
|
1525
1577
|
}
|
|
1526
1578
|
),
|
|
1579
|
+
services: config.services,
|
|
1527
1580
|
unsafe: config.unsafe?.bindings,
|
|
1528
1581
|
}}
|
|
1529
1582
|
crons={config.triggers.crons}
|
|
@@ -1623,7 +1676,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1623
1676
|
},
|
|
1624
1677
|
() => {
|
|
1625
1678
|
throw new DeprecationError(
|
|
1626
|
-
"`wrangler subdomain` has been deprecated, please refer to https://
|
|
1679
|
+
"`wrangler subdomain` has been deprecated, please refer to https://developers.cloudflare.com/workers/wrangler/migration/deprecations/#subdomain for alternatives"
|
|
1627
1680
|
);
|
|
1628
1681
|
}
|
|
1629
1682
|
);
|
|
@@ -1635,6 +1688,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1635
1688
|
(secretYargs) => {
|
|
1636
1689
|
return secretYargs
|
|
1637
1690
|
.command(subHelp)
|
|
1691
|
+
.option("legacy-env", {
|
|
1692
|
+
type: "boolean",
|
|
1693
|
+
describe: "Use legacy environments",
|
|
1694
|
+
hidden: true,
|
|
1695
|
+
})
|
|
1638
1696
|
.command(
|
|
1639
1697
|
"put <key>",
|
|
1640
1698
|
"Create or update a secret variable for a script",
|
|
@@ -1669,9 +1727,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1669
1727
|
const accountId = await requireAuth(config);
|
|
1670
1728
|
|
|
1671
1729
|
const isInteractive = process.stdin.isTTY;
|
|
1672
|
-
const secretValue =
|
|
1673
|
-
|
|
1674
|
-
|
|
1730
|
+
const secretValue = trimTrailingWhitespace(
|
|
1731
|
+
isInteractive
|
|
1732
|
+
? await prompt("Enter a secret value:", "password")
|
|
1733
|
+
: await readFromStdin()
|
|
1734
|
+
);
|
|
1675
1735
|
|
|
1676
1736
|
logger.log(
|
|
1677
1737
|
`🌀 Creating the secret for script ${scriptName} ${
|
|
@@ -1716,6 +1776,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1716
1776
|
vars: {},
|
|
1717
1777
|
durable_objects: { bindings: [] },
|
|
1718
1778
|
r2_buckets: [],
|
|
1779
|
+
services: [],
|
|
1719
1780
|
wasm_modules: {},
|
|
1720
1781
|
text_blobs: {},
|
|
1721
1782
|
data_blobs: {},
|
|
@@ -1884,7 +1945,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1884
1945
|
async (args) => {
|
|
1885
1946
|
await printWranglerBanner();
|
|
1886
1947
|
|
|
1887
|
-
if (!
|
|
1948
|
+
if (!isValidKVNamespaceBinding(args.namespace)) {
|
|
1888
1949
|
throw new CommandLineArgsError(
|
|
1889
1950
|
`The namespace binding name "${args.namespace}" is invalid. It can only have alphanumeric and _ characters, and cannot begin with a number.`
|
|
1890
1951
|
);
|
|
@@ -1907,7 +1968,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1907
1968
|
// TODO: generate a binding name stripping non alphanumeric chars
|
|
1908
1969
|
|
|
1909
1970
|
logger.log(`🌀 Creating namespace with title "${title}"`);
|
|
1910
|
-
const namespaceId = await
|
|
1971
|
+
const namespaceId = await createKVNamespace(accountId, title);
|
|
1911
1972
|
|
|
1912
1973
|
logger.log("✨ Success!");
|
|
1913
1974
|
const envString = args.env ? ` under [env.${args.env}]` : "";
|
|
@@ -1934,7 +1995,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1934
1995
|
// TODO: we should show bindings if they exist for given ids
|
|
1935
1996
|
|
|
1936
1997
|
logger.log(
|
|
1937
|
-
JSON.stringify(await
|
|
1998
|
+
JSON.stringify(await listKVNamespaces(accountId), null, " ")
|
|
1938
1999
|
);
|
|
1939
2000
|
}
|
|
1940
2001
|
)
|
|
@@ -1971,7 +2032,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1971
2032
|
|
|
1972
2033
|
let id;
|
|
1973
2034
|
try {
|
|
1974
|
-
id =
|
|
2035
|
+
id = getKVNamespaceId(args, config);
|
|
1975
2036
|
} catch (e) {
|
|
1976
2037
|
throw new CommandLineArgsError(
|
|
1977
2038
|
"Not able to delete namespace.\n" + ((e as Error).message ?? e)
|
|
@@ -1980,10 +2041,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1980
2041
|
|
|
1981
2042
|
const accountId = await requireAuth(config);
|
|
1982
2043
|
|
|
1983
|
-
await
|
|
1984
|
-
`/accounts/${accountId}/storage/kv/namespaces/${id}`,
|
|
1985
|
-
{ method: "DELETE" }
|
|
1986
|
-
);
|
|
2044
|
+
await deleteKVNamespace(accountId, id);
|
|
1987
2045
|
|
|
1988
2046
|
// TODO: recommend they remove it from wrangler.toml
|
|
1989
2047
|
|
|
@@ -2068,7 +2126,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2068
2126
|
async ({ key, ttl, expiration, ...args }) => {
|
|
2069
2127
|
await printWranglerBanner();
|
|
2070
2128
|
const config = readConfig(args.config as ConfigPath, args);
|
|
2071
|
-
const namespaceId =
|
|
2129
|
+
const namespaceId = getKVNamespaceId(args, config);
|
|
2072
2130
|
// One of `args.path` and `args.value` must be defined
|
|
2073
2131
|
const value = args.path
|
|
2074
2132
|
? readFileSync(args.path)
|
|
@@ -2087,7 +2145,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2087
2145
|
|
|
2088
2146
|
const accountId = await requireAuth(config);
|
|
2089
2147
|
|
|
2090
|
-
await
|
|
2148
|
+
await putKVKeyValue(accountId, namespaceId, {
|
|
2091
2149
|
key,
|
|
2092
2150
|
value,
|
|
2093
2151
|
expiration,
|
|
@@ -2132,11 +2190,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2132
2190
|
async ({ prefix, ...args }) => {
|
|
2133
2191
|
// TODO: support for limit+cursor (pagination)
|
|
2134
2192
|
const config = readConfig(args.config as ConfigPath, args);
|
|
2135
|
-
const namespaceId =
|
|
2193
|
+
const namespaceId = getKVNamespaceId(args, config);
|
|
2136
2194
|
|
|
2137
2195
|
const accountId = await requireAuth(config);
|
|
2138
2196
|
|
|
2139
|
-
const results = await
|
|
2197
|
+
const results = await listKVNamespaceKeys(
|
|
2140
2198
|
accountId,
|
|
2141
2199
|
namespaceId,
|
|
2142
2200
|
prefix
|
|
@@ -2184,11 +2242,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2184
2242
|
},
|
|
2185
2243
|
async ({ key, ...args }) => {
|
|
2186
2244
|
const config = readConfig(args.config as ConfigPath, args);
|
|
2187
|
-
const namespaceId =
|
|
2245
|
+
const namespaceId = getKVNamespaceId(args, config);
|
|
2188
2246
|
|
|
2189
2247
|
const accountId = await requireAuth(config);
|
|
2190
2248
|
|
|
2191
|
-
logger.log(await
|
|
2249
|
+
logger.log(await getKVKeyValue(accountId, namespaceId, key));
|
|
2192
2250
|
}
|
|
2193
2251
|
)
|
|
2194
2252
|
.command(
|
|
@@ -2226,7 +2284,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2226
2284
|
async ({ key, ...args }) => {
|
|
2227
2285
|
await printWranglerBanner();
|
|
2228
2286
|
const config = readConfig(args.config as ConfigPath, args);
|
|
2229
|
-
const namespaceId =
|
|
2287
|
+
const namespaceId = getKVNamespaceId(args, config);
|
|
2230
2288
|
|
|
2231
2289
|
logger.log(
|
|
2232
2290
|
`Deleting the key "${key}" on namespace ${namespaceId}.`
|
|
@@ -2234,10 +2292,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2234
2292
|
|
|
2235
2293
|
const accountId = await requireAuth(config);
|
|
2236
2294
|
|
|
2237
|
-
await
|
|
2238
|
-
`/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${key}`,
|
|
2239
|
-
{ method: "DELETE" }
|
|
2240
|
-
);
|
|
2295
|
+
await deleteKVKeyValue(accountId, namespaceId, key);
|
|
2241
2296
|
}
|
|
2242
2297
|
);
|
|
2243
2298
|
}
|
|
@@ -2289,7 +2344,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2289
2344
|
// but we'll do that in the future if needed.
|
|
2290
2345
|
|
|
2291
2346
|
const config = readConfig(args.config as ConfigPath, args);
|
|
2292
|
-
const namespaceId =
|
|
2347
|
+
const namespaceId = getKVNamespaceId(args, config);
|
|
2293
2348
|
const content = parseJSON(readFileSync(filename), filename);
|
|
2294
2349
|
|
|
2295
2350
|
if (!Array.isArray(content)) {
|
|
@@ -2303,18 +2358,12 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2303
2358
|
const warnings: string[] = [];
|
|
2304
2359
|
for (let i = 0; i < content.length; i++) {
|
|
2305
2360
|
const keyValue = content[i];
|
|
2306
|
-
if (
|
|
2307
|
-
errors.push(
|
|
2308
|
-
`The item at index ${i} is type: "${typeof keyValue}" - ${JSON.stringify(
|
|
2309
|
-
keyValue
|
|
2310
|
-
)}`
|
|
2311
|
-
);
|
|
2312
|
-
} else if (!isKeyValue(keyValue)) {
|
|
2361
|
+
if (!isKVKeyValue(keyValue)) {
|
|
2313
2362
|
errors.push(
|
|
2314
2363
|
`The item at index ${i} is ${JSON.stringify(keyValue)}`
|
|
2315
2364
|
);
|
|
2316
2365
|
} else {
|
|
2317
|
-
const props =
|
|
2366
|
+
const props = unexpectedKVKeyValueProps(keyValue);
|
|
2318
2367
|
if (props.length > 0) {
|
|
2319
2368
|
warnings.push(
|
|
2320
2369
|
`The item at index ${i} contains unexpected properties: ${JSON.stringify(
|
|
@@ -2347,7 +2396,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2347
2396
|
}
|
|
2348
2397
|
|
|
2349
2398
|
const accountId = await requireAuth(config);
|
|
2350
|
-
await
|
|
2399
|
+
await putKVBulkKeyValue(
|
|
2351
2400
|
accountId,
|
|
2352
2401
|
namespaceId,
|
|
2353
2402
|
content,
|
|
@@ -2399,7 +2448,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2399
2448
|
async ({ filename, ...args }) => {
|
|
2400
2449
|
await printWranglerBanner();
|
|
2401
2450
|
const config = readConfig(args.config as ConfigPath, args);
|
|
2402
|
-
const namespaceId =
|
|
2451
|
+
const namespaceId = getKVNamespaceId(args, config);
|
|
2403
2452
|
|
|
2404
2453
|
if (!args.force) {
|
|
2405
2454
|
const result = await confirm(
|
|
@@ -2444,7 +2493,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2444
2493
|
|
|
2445
2494
|
const accountId = await requireAuth(config);
|
|
2446
2495
|
|
|
2447
|
-
await
|
|
2496
|
+
await deleteKVBulkKeyValue(
|
|
2448
2497
|
accountId,
|
|
2449
2498
|
namespaceId,
|
|
2450
2499
|
content,
|
|
@@ -2604,31 +2653,33 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2604
2653
|
}
|
|
2605
2654
|
);
|
|
2606
2655
|
|
|
2607
|
-
wrangler
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
alias: "c",
|
|
2614
|
-
describe: "Path to .toml configuration file",
|
|
2615
|
-
type: "string",
|
|
2616
|
-
requiresArg: true,
|
|
2617
|
-
});
|
|
2656
|
+
wrangler.option("config", {
|
|
2657
|
+
alias: "c",
|
|
2658
|
+
describe: "Path to .toml configuration file",
|
|
2659
|
+
type: "string",
|
|
2660
|
+
requiresArg: true,
|
|
2661
|
+
});
|
|
2618
2662
|
|
|
2619
|
-
wrangler.group(["config", "help", "version"
|
|
2663
|
+
wrangler.group(["config", "help", "version"], "Flags:");
|
|
2620
2664
|
wrangler.help().alias("h", "help");
|
|
2621
2665
|
wrangler.version(wranglerVersion).alias("v", "version");
|
|
2622
2666
|
wrangler.exitProcess(false);
|
|
2623
2667
|
|
|
2668
|
+
return wrangler;
|
|
2669
|
+
}
|
|
2670
|
+
|
|
2671
|
+
export async function main(argv: string[]): Promise<void> {
|
|
2672
|
+
const wrangler = createCLIParser(argv);
|
|
2624
2673
|
try {
|
|
2625
2674
|
await wrangler.parse();
|
|
2626
2675
|
} catch (e) {
|
|
2627
2676
|
logger.log(""); // Just adds a bit of space
|
|
2628
2677
|
if (e instanceof CommandLineArgsError) {
|
|
2629
|
-
wrangler.showHelp("error");
|
|
2630
|
-
logger.log(""); // Add a bit of space.
|
|
2631
2678
|
logger.error(e.message);
|
|
2679
|
+
// We are not able to ask the `wrangler` CLI parser to show help for a subcommand programmatically.
|
|
2680
|
+
// The workaround is to re-run the parsing with an additional `--help` flag, which will result in the correct help message being displayed.
|
|
2681
|
+
// The `wrangler` object is "frozen"; we cannot reuse that with different args, so we must create a new CLI parser to generate the help message.
|
|
2682
|
+
await createCLIParser([...argv, "--help"]).parse();
|
|
2632
2683
|
} else if (e instanceof ParseError) {
|
|
2633
2684
|
e.notes.push({
|
|
2634
2685
|
text: "\nIf you think this is a bug, please open an issue at: https://github.com/cloudflare/wrangler2/issues/new",
|
package/src/kv.ts
CHANGED
|
@@ -19,7 +19,7 @@ type KvArgs = {
|
|
|
19
19
|
*
|
|
20
20
|
* @returns the generated id of the created namespace.
|
|
21
21
|
*/
|
|
22
|
-
export async function
|
|
22
|
+
export async function createKVNamespace(
|
|
23
23
|
accountId: string,
|
|
24
24
|
title: string
|
|
25
25
|
): Promise<string> {
|
|
@@ -51,7 +51,7 @@ export interface KVNamespaceInfo {
|
|
|
51
51
|
/**
|
|
52
52
|
* Fetch a list of all the namespaces under the given `accountId`.
|
|
53
53
|
*/
|
|
54
|
-
export async function
|
|
54
|
+
export async function listKVNamespaces(
|
|
55
55
|
accountId: string
|
|
56
56
|
): Promise<KVNamespaceInfo[]> {
|
|
57
57
|
const pageSize = 100;
|
|
@@ -83,7 +83,7 @@ export interface NamespaceKeyInfo {
|
|
|
83
83
|
metadata?: { [key: string]: unknown };
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
export async function
|
|
86
|
+
export async function listKVNamespaceKeys(
|
|
87
87
|
accountId: string,
|
|
88
88
|
namespaceId: string,
|
|
89
89
|
prefix = ""
|
|
@@ -95,6 +95,16 @@ export async function listNamespaceKeys(
|
|
|
95
95
|
);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
export async function deleteKVNamespace(
|
|
99
|
+
accountId: string,
|
|
100
|
+
namespaceId: string
|
|
101
|
+
) {
|
|
102
|
+
return await fetchResult<{ id: string }>(
|
|
103
|
+
`/accounts/${accountId}/storage/kv/namespaces/${namespaceId}`,
|
|
104
|
+
{ method: "DELETE" }
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
98
108
|
/**
|
|
99
109
|
* Information about a key-value pair, including its "metadata" fields.
|
|
100
110
|
*/
|
|
@@ -119,9 +129,24 @@ const KeyValueKeys = new Set([
|
|
|
119
129
|
/**
|
|
120
130
|
* Is the given object a valid `KeyValue` type?
|
|
121
131
|
*/
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
132
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
133
|
+
export function isKVKeyValue(keyValue: any): keyValue is KeyValue {
|
|
134
|
+
// (keyValue could indeed be any-thing)
|
|
135
|
+
if (
|
|
136
|
+
typeof keyValue !== "object" ||
|
|
137
|
+
typeof keyValue.key !== "string" ||
|
|
138
|
+
typeof keyValue.value !== "string" ||
|
|
139
|
+
!(
|
|
140
|
+
keyValue.expiration === undefined ||
|
|
141
|
+
typeof keyValue.expiration === "number"
|
|
142
|
+
) ||
|
|
143
|
+
!(
|
|
144
|
+
keyValue.expiration_ttl === undefined ||
|
|
145
|
+
typeof keyValue.expiration_ttl === "number"
|
|
146
|
+
) ||
|
|
147
|
+
!(keyValue.base64 === undefined || typeof keyValue.base64 === "boolean") ||
|
|
148
|
+
!(keyValue.metadata === undefined || typeof keyValue.metadata === "object")
|
|
149
|
+
) {
|
|
125
150
|
return false;
|
|
126
151
|
}
|
|
127
152
|
return true;
|
|
@@ -130,12 +155,12 @@ export function isKeyValue(keyValue: object): keyValue is KeyValue {
|
|
|
130
155
|
/**
|
|
131
156
|
* Get all the properties on the `keyValue` that are not expected.
|
|
132
157
|
*/
|
|
133
|
-
export function
|
|
158
|
+
export function unexpectedKVKeyValueProps(keyValue: KeyValue): string[] {
|
|
134
159
|
const props = Object.keys(keyValue);
|
|
135
160
|
return props.filter((prop) => !KeyValueKeys.has(prop));
|
|
136
161
|
}
|
|
137
162
|
|
|
138
|
-
export async function
|
|
163
|
+
export async function putKVKeyValue(
|
|
139
164
|
accountId: string,
|
|
140
165
|
namespaceId: string,
|
|
141
166
|
keyValue: KeyValue
|
|
@@ -151,21 +176,36 @@ export async function putKeyValue(
|
|
|
151
176
|
}
|
|
152
177
|
}
|
|
153
178
|
return await fetchResult(
|
|
154
|
-
`/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${
|
|
179
|
+
`/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${encodeURIComponent(
|
|
180
|
+
keyValue.key
|
|
181
|
+
)}`,
|
|
155
182
|
{ method: "PUT", body: keyValue.value },
|
|
156
183
|
searchParams
|
|
157
184
|
);
|
|
158
185
|
}
|
|
159
186
|
|
|
160
|
-
export async function
|
|
187
|
+
export async function getKVKeyValue(
|
|
161
188
|
accountId: string,
|
|
162
189
|
namespaceId: string,
|
|
163
190
|
key: string
|
|
164
191
|
): Promise<string> {
|
|
165
|
-
return await fetchKVGetValue(accountId, namespaceId, key);
|
|
192
|
+
return await fetchKVGetValue(accountId, namespaceId, encodeURIComponent(key));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export async function deleteKVKeyValue(
|
|
196
|
+
accountId: string,
|
|
197
|
+
namespaceId: string,
|
|
198
|
+
key: string
|
|
199
|
+
) {
|
|
200
|
+
return await fetchResult(
|
|
201
|
+
`/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${encodeURIComponent(
|
|
202
|
+
key
|
|
203
|
+
)}`,
|
|
204
|
+
{ method: "DELETE" }
|
|
205
|
+
);
|
|
166
206
|
}
|
|
167
207
|
|
|
168
|
-
export async function
|
|
208
|
+
export async function putKVBulkKeyValue(
|
|
169
209
|
accountId: string,
|
|
170
210
|
namespaceId: string,
|
|
171
211
|
keyValues: KeyValue[],
|
|
@@ -190,7 +230,7 @@ export async function putBulkKeyValue(
|
|
|
190
230
|
}
|
|
191
231
|
}
|
|
192
232
|
|
|
193
|
-
export async function
|
|
233
|
+
export async function deleteKVBulkKeyValue(
|
|
194
234
|
accountId: string,
|
|
195
235
|
namespaceId: string,
|
|
196
236
|
keys: string[],
|
|
@@ -215,7 +255,7 @@ export async function deleteBulkKeyValue(
|
|
|
215
255
|
}
|
|
216
256
|
}
|
|
217
257
|
|
|
218
|
-
export function
|
|
258
|
+
export function getKVNamespaceId(
|
|
219
259
|
{ preview, binding, "namespace-id": namespaceId }: KvArgs,
|
|
220
260
|
config: Config
|
|
221
261
|
): string {
|
|
@@ -310,7 +350,7 @@ export function getNamespaceId(
|
|
|
310
350
|
/**
|
|
311
351
|
* KV namespace binding names must be valid JS identifiers.
|
|
312
352
|
*/
|
|
313
|
-
export function
|
|
353
|
+
export function isValidKVNamespaceBinding(
|
|
314
354
|
binding: string | undefined
|
|
315
355
|
): binding is string {
|
|
316
356
|
return (
|
package/src/pages.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import { execSync, spawn } from "node:child_process";
|
|
|
4
4
|
import { existsSync, lstatSync, readFileSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { readdir, readFile, stat } from "node:fs/promises";
|
|
6
6
|
import { tmpdir } from "node:os";
|
|
7
|
-
import { dirname, join, sep } from "node:path";
|
|
7
|
+
import { dirname, join, sep, extname, basename } from "node:path";
|
|
8
8
|
import { cwd } from "node:process";
|
|
9
9
|
import { URL } from "node:url";
|
|
10
10
|
import { hash } from "blake3-wasm";
|
|
@@ -1079,8 +1079,7 @@ const createDeployment: CommandModule<
|
|
|
1079
1079
|
const fileContent = await readFile(filepath);
|
|
1080
1080
|
|
|
1081
1081
|
const base64Content = fileContent.toString("base64");
|
|
1082
|
-
const extension =
|
|
1083
|
-
name.split(".").length > 1 ? name.split(".").at(-1) || "" : "";
|
|
1082
|
+
const extension = extname(basename(name)).substring(1);
|
|
1084
1083
|
|
|
1085
1084
|
const content = base64Content + extension;
|
|
1086
1085
|
|
|
@@ -1244,7 +1243,7 @@ const createDeployment: CommandModule<
|
|
|
1244
1243
|
export const pages: BuilderCallback<unknown, unknown> = (yargs) => {
|
|
1245
1244
|
return yargs
|
|
1246
1245
|
.command(
|
|
1247
|
-
"dev [directory] [-- command]",
|
|
1246
|
+
"dev [directory] [-- command..]",
|
|
1248
1247
|
"🧑💻 Develop your full-stack Pages application locally",
|
|
1249
1248
|
(yargs) => {
|
|
1250
1249
|
return yargs
|
|
@@ -1576,6 +1575,10 @@ export const pages: BuilderCallback<unknown, unknown> = (yargs) => {
|
|
|
1576
1575
|
default: false,
|
|
1577
1576
|
description: "Build a plugin rather than a Worker script",
|
|
1578
1577
|
},
|
|
1578
|
+
"build-output-directory": {
|
|
1579
|
+
type: "string",
|
|
1580
|
+
description: "The directory to output static assets to",
|
|
1581
|
+
},
|
|
1579
1582
|
})
|
|
1580
1583
|
.epilogue(pagesBetaWarning),
|
|
1581
1584
|
async ({
|
|
@@ -1587,12 +1590,15 @@ export const pages: BuilderCallback<unknown, unknown> = (yargs) => {
|
|
|
1587
1590
|
fallbackService,
|
|
1588
1591
|
watch,
|
|
1589
1592
|
plugin,
|
|
1593
|
+
"build-output-directory": buildOutputDirectory,
|
|
1590
1594
|
}) => {
|
|
1591
1595
|
if (!isInPagesCI) {
|
|
1592
1596
|
// Beta message for `wrangler pages <commands>` usage
|
|
1593
1597
|
logger.log(pagesBetaWarning);
|
|
1594
1598
|
}
|
|
1595
1599
|
|
|
1600
|
+
buildOutputDirectory ??= dirname(outfile);
|
|
1601
|
+
|
|
1596
1602
|
await buildFunctions({
|
|
1597
1603
|
outfile,
|
|
1598
1604
|
outputConfigPath,
|
|
@@ -1602,7 +1608,7 @@ export const pages: BuilderCallback<unknown, unknown> = (yargs) => {
|
|
|
1602
1608
|
fallbackService,
|
|
1603
1609
|
watch,
|
|
1604
1610
|
plugin,
|
|
1605
|
-
buildOutputDirectory
|
|
1611
|
+
buildOutputDirectory,
|
|
1606
1612
|
});
|
|
1607
1613
|
}
|
|
1608
1614
|
)
|