wrangler 2.0.1 → 2.0.5
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 +1 -1
- package/src/__tests__/dev.test.tsx +77 -10
- package/src/__tests__/index.test.ts +51 -58
- package/src/__tests__/jest.setup.ts +8 -0
- package/src/__tests__/kv.test.ts +75 -48
- package/src/__tests__/pages.test.ts +12 -14
- package/src/__tests__/publish.test.ts +127 -6
- package/src/__tests__/r2.test.ts +12 -16
- package/src/bundle.ts +1 -1
- package/src/cfetch/internal.ts +3 -0
- package/src/config/config.ts +1 -1
- package/src/config/validation.ts +1 -1
- package/src/dev/dev.tsx +5 -2
- package/src/entry.ts +64 -9
- package/src/index.tsx +81 -55
- package/src/kv.ts +38 -13
- package/src/pages.tsx +19 -12
- package/src/sites.tsx +10 -10
- package/src/user.tsx +11 -1
- package/wrangler-dist/cli.js +1022 -791
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 ?? [];
|
|
@@ -406,7 +409,17 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
406
409
|
const isInsideGitProject = Boolean(
|
|
407
410
|
await findUp(".git", { cwd: creationDirectory, type: "directory" })
|
|
408
411
|
);
|
|
409
|
-
|
|
412
|
+
let isGitInstalled;
|
|
413
|
+
try {
|
|
414
|
+
isGitInstalled = (await execa("git", ["--version"])).exitCode === 0;
|
|
415
|
+
} catch (err) {
|
|
416
|
+
if ((err as { code: string | undefined }).code !== "ENOENT") {
|
|
417
|
+
// only throw if the error is not because git is not installed
|
|
418
|
+
throw err;
|
|
419
|
+
} else {
|
|
420
|
+
isGitInstalled = false;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
410
423
|
if (!isInsideGitProject && isGitInstalled) {
|
|
411
424
|
const shouldInitGit =
|
|
412
425
|
yesFlag ||
|
|
@@ -712,7 +725,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
712
725
|
() => {
|
|
713
726
|
// "[DEPRECATED] 🦀 Build your project (if applicable)",
|
|
714
727
|
throw new DeprecationError(
|
|
715
|
-
"`wrangler build` has been deprecated, please refer to https://
|
|
728
|
+
"`wrangler build` has been deprecated, please refer to https://developers.cloudflare.com/workers/wrangler/migration/deprecations/#build for alternatives"
|
|
716
729
|
);
|
|
717
730
|
}
|
|
718
731
|
);
|
|
@@ -725,7 +738,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
725
738
|
() => {
|
|
726
739
|
// "🕵️ Authenticate Wrangler with a Cloudflare API Token",
|
|
727
740
|
throw new DeprecationError(
|
|
728
|
-
"`wrangler config` has been deprecated, please refer to https://
|
|
741
|
+
"`wrangler config` has been deprecated, please refer to https://developers.cloudflare.com/workers/wrangler/migration/deprecations/#config for alternatives"
|
|
729
742
|
);
|
|
730
743
|
}
|
|
731
744
|
);
|
|
@@ -869,6 +882,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
869
882
|
describe: "Enable dev tools",
|
|
870
883
|
type: "boolean",
|
|
871
884
|
deprecated: true,
|
|
885
|
+
})
|
|
886
|
+
.option("legacy-env", {
|
|
887
|
+
type: "boolean",
|
|
888
|
+
describe: "Use legacy environments",
|
|
889
|
+
hidden: true,
|
|
872
890
|
});
|
|
873
891
|
},
|
|
874
892
|
async (args) => {
|
|
@@ -995,7 +1013,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
995
1013
|
const nodeCompat = args.nodeCompat ?? config.node_compat;
|
|
996
1014
|
if (nodeCompat) {
|
|
997
1015
|
logger.warn(
|
|
998
|
-
"Enabling node.js compatibility mode for
|
|
1016
|
+
"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
1017
|
);
|
|
1000
1018
|
}
|
|
1001
1019
|
|
|
@@ -1027,7 +1045,9 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1027
1045
|
args.siteExclude
|
|
1028
1046
|
)}
|
|
1029
1047
|
port={
|
|
1030
|
-
args.port ||
|
|
1048
|
+
args.port ||
|
|
1049
|
+
config.dev.port ||
|
|
1050
|
+
(await getPort({ port: DEFAULT_LOCAL_PORT }))
|
|
1031
1051
|
}
|
|
1032
1052
|
ip={args.ip || config.dev.ip}
|
|
1033
1053
|
inspectorPort={
|
|
@@ -1206,6 +1226,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1206
1226
|
.option("dry-run", {
|
|
1207
1227
|
describe: "Don't actually publish",
|
|
1208
1228
|
type: "boolean",
|
|
1229
|
+
})
|
|
1230
|
+
.option("legacy-env", {
|
|
1231
|
+
type: "boolean",
|
|
1232
|
+
describe: "Use legacy environments",
|
|
1233
|
+
hidden: true,
|
|
1209
1234
|
});
|
|
1210
1235
|
},
|
|
1211
1236
|
async (args) => {
|
|
@@ -1327,6 +1352,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1327
1352
|
default: false,
|
|
1328
1353
|
describe:
|
|
1329
1354
|
"If a log would have been filtered out, send it through anyway alongside the filter which would have blocked it.",
|
|
1355
|
+
})
|
|
1356
|
+
.option("legacy-env", {
|
|
1357
|
+
type: "boolean",
|
|
1358
|
+
describe: "Use legacy environments",
|
|
1359
|
+
hidden: true,
|
|
1330
1360
|
});
|
|
1331
1361
|
},
|
|
1332
1362
|
async (args) => {
|
|
@@ -1476,7 +1506,9 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1476
1506
|
enableLocalPersistence={false}
|
|
1477
1507
|
accountId={accountId}
|
|
1478
1508
|
assetPaths={undefined}
|
|
1479
|
-
port={
|
|
1509
|
+
port={
|
|
1510
|
+
config.dev.port || (await getPort({ port: DEFAULT_LOCAL_PORT }))
|
|
1511
|
+
}
|
|
1480
1512
|
ip={config.dev.ip}
|
|
1481
1513
|
public={undefined}
|
|
1482
1514
|
compatibilityDate={getDevCompatibilityDate(config)}
|
|
@@ -1623,7 +1655,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1623
1655
|
},
|
|
1624
1656
|
() => {
|
|
1625
1657
|
throw new DeprecationError(
|
|
1626
|
-
"`wrangler subdomain` has been deprecated, please refer to https://
|
|
1658
|
+
"`wrangler subdomain` has been deprecated, please refer to https://developers.cloudflare.com/workers/wrangler/migration/deprecations/#subdomain for alternatives"
|
|
1627
1659
|
);
|
|
1628
1660
|
}
|
|
1629
1661
|
);
|
|
@@ -1635,6 +1667,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1635
1667
|
(secretYargs) => {
|
|
1636
1668
|
return secretYargs
|
|
1637
1669
|
.command(subHelp)
|
|
1670
|
+
.option("legacy-env", {
|
|
1671
|
+
type: "boolean",
|
|
1672
|
+
describe: "Use legacy environments",
|
|
1673
|
+
hidden: true,
|
|
1674
|
+
})
|
|
1638
1675
|
.command(
|
|
1639
1676
|
"put <key>",
|
|
1640
1677
|
"Create or update a secret variable for a script",
|
|
@@ -1884,7 +1921,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1884
1921
|
async (args) => {
|
|
1885
1922
|
await printWranglerBanner();
|
|
1886
1923
|
|
|
1887
|
-
if (!
|
|
1924
|
+
if (!isValidKVNamespaceBinding(args.namespace)) {
|
|
1888
1925
|
throw new CommandLineArgsError(
|
|
1889
1926
|
`The namespace binding name "${args.namespace}" is invalid. It can only have alphanumeric and _ characters, and cannot begin with a number.`
|
|
1890
1927
|
);
|
|
@@ -1907,7 +1944,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1907
1944
|
// TODO: generate a binding name stripping non alphanumeric chars
|
|
1908
1945
|
|
|
1909
1946
|
logger.log(`🌀 Creating namespace with title "${title}"`);
|
|
1910
|
-
const namespaceId = await
|
|
1947
|
+
const namespaceId = await createKVNamespace(accountId, title);
|
|
1911
1948
|
|
|
1912
1949
|
logger.log("✨ Success!");
|
|
1913
1950
|
const envString = args.env ? ` under [env.${args.env}]` : "";
|
|
@@ -1934,7 +1971,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1934
1971
|
// TODO: we should show bindings if they exist for given ids
|
|
1935
1972
|
|
|
1936
1973
|
logger.log(
|
|
1937
|
-
JSON.stringify(await
|
|
1974
|
+
JSON.stringify(await listKVNamespaces(accountId), null, " ")
|
|
1938
1975
|
);
|
|
1939
1976
|
}
|
|
1940
1977
|
)
|
|
@@ -1971,7 +2008,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1971
2008
|
|
|
1972
2009
|
let id;
|
|
1973
2010
|
try {
|
|
1974
|
-
id =
|
|
2011
|
+
id = getKVNamespaceId(args, config);
|
|
1975
2012
|
} catch (e) {
|
|
1976
2013
|
throw new CommandLineArgsError(
|
|
1977
2014
|
"Not able to delete namespace.\n" + ((e as Error).message ?? e)
|
|
@@ -1980,10 +2017,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
1980
2017
|
|
|
1981
2018
|
const accountId = await requireAuth(config);
|
|
1982
2019
|
|
|
1983
|
-
await
|
|
1984
|
-
`/accounts/${accountId}/storage/kv/namespaces/${id}`,
|
|
1985
|
-
{ method: "DELETE" }
|
|
1986
|
-
);
|
|
2020
|
+
await deleteKVNamespace(accountId, id);
|
|
1987
2021
|
|
|
1988
2022
|
// TODO: recommend they remove it from wrangler.toml
|
|
1989
2023
|
|
|
@@ -2068,7 +2102,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2068
2102
|
async ({ key, ttl, expiration, ...args }) => {
|
|
2069
2103
|
await printWranglerBanner();
|
|
2070
2104
|
const config = readConfig(args.config as ConfigPath, args);
|
|
2071
|
-
const namespaceId =
|
|
2105
|
+
const namespaceId = getKVNamespaceId(args, config);
|
|
2072
2106
|
// One of `args.path` and `args.value` must be defined
|
|
2073
2107
|
const value = args.path
|
|
2074
2108
|
? readFileSync(args.path)
|
|
@@ -2087,7 +2121,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2087
2121
|
|
|
2088
2122
|
const accountId = await requireAuth(config);
|
|
2089
2123
|
|
|
2090
|
-
await
|
|
2124
|
+
await putKVKeyValue(accountId, namespaceId, {
|
|
2091
2125
|
key,
|
|
2092
2126
|
value,
|
|
2093
2127
|
expiration,
|
|
@@ -2132,11 +2166,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2132
2166
|
async ({ prefix, ...args }) => {
|
|
2133
2167
|
// TODO: support for limit+cursor (pagination)
|
|
2134
2168
|
const config = readConfig(args.config as ConfigPath, args);
|
|
2135
|
-
const namespaceId =
|
|
2169
|
+
const namespaceId = getKVNamespaceId(args, config);
|
|
2136
2170
|
|
|
2137
2171
|
const accountId = await requireAuth(config);
|
|
2138
2172
|
|
|
2139
|
-
const results = await
|
|
2173
|
+
const results = await listKVNamespaceKeys(
|
|
2140
2174
|
accountId,
|
|
2141
2175
|
namespaceId,
|
|
2142
2176
|
prefix
|
|
@@ -2184,11 +2218,11 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2184
2218
|
},
|
|
2185
2219
|
async ({ key, ...args }) => {
|
|
2186
2220
|
const config = readConfig(args.config as ConfigPath, args);
|
|
2187
|
-
const namespaceId =
|
|
2221
|
+
const namespaceId = getKVNamespaceId(args, config);
|
|
2188
2222
|
|
|
2189
2223
|
const accountId = await requireAuth(config);
|
|
2190
2224
|
|
|
2191
|
-
logger.log(await
|
|
2225
|
+
logger.log(await getKVKeyValue(accountId, namespaceId, key));
|
|
2192
2226
|
}
|
|
2193
2227
|
)
|
|
2194
2228
|
.command(
|
|
@@ -2226,7 +2260,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2226
2260
|
async ({ key, ...args }) => {
|
|
2227
2261
|
await printWranglerBanner();
|
|
2228
2262
|
const config = readConfig(args.config as ConfigPath, args);
|
|
2229
|
-
const namespaceId =
|
|
2263
|
+
const namespaceId = getKVNamespaceId(args, config);
|
|
2230
2264
|
|
|
2231
2265
|
logger.log(
|
|
2232
2266
|
`Deleting the key "${key}" on namespace ${namespaceId}.`
|
|
@@ -2234,10 +2268,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2234
2268
|
|
|
2235
2269
|
const accountId = await requireAuth(config);
|
|
2236
2270
|
|
|
2237
|
-
await
|
|
2238
|
-
`/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${key}`,
|
|
2239
|
-
{ method: "DELETE" }
|
|
2240
|
-
);
|
|
2271
|
+
await deleteKVKeyValue(accountId, namespaceId, key);
|
|
2241
2272
|
}
|
|
2242
2273
|
);
|
|
2243
2274
|
}
|
|
@@ -2289,7 +2320,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2289
2320
|
// but we'll do that in the future if needed.
|
|
2290
2321
|
|
|
2291
2322
|
const config = readConfig(args.config as ConfigPath, args);
|
|
2292
|
-
const namespaceId =
|
|
2323
|
+
const namespaceId = getKVNamespaceId(args, config);
|
|
2293
2324
|
const content = parseJSON(readFileSync(filename), filename);
|
|
2294
2325
|
|
|
2295
2326
|
if (!Array.isArray(content)) {
|
|
@@ -2309,12 +2340,12 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2309
2340
|
keyValue
|
|
2310
2341
|
)}`
|
|
2311
2342
|
);
|
|
2312
|
-
} else if (!
|
|
2343
|
+
} else if (!isKVKeyValue(keyValue)) {
|
|
2313
2344
|
errors.push(
|
|
2314
2345
|
`The item at index ${i} is ${JSON.stringify(keyValue)}`
|
|
2315
2346
|
);
|
|
2316
2347
|
} else {
|
|
2317
|
-
const props =
|
|
2348
|
+
const props = unexpectedKVKeyValueProps(keyValue);
|
|
2318
2349
|
if (props.length > 0) {
|
|
2319
2350
|
warnings.push(
|
|
2320
2351
|
`The item at index ${i} contains unexpected properties: ${JSON.stringify(
|
|
@@ -2347,7 +2378,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2347
2378
|
}
|
|
2348
2379
|
|
|
2349
2380
|
const accountId = await requireAuth(config);
|
|
2350
|
-
await
|
|
2381
|
+
await putKVBulkKeyValue(
|
|
2351
2382
|
accountId,
|
|
2352
2383
|
namespaceId,
|
|
2353
2384
|
content,
|
|
@@ -2399,7 +2430,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2399
2430
|
async ({ filename, ...args }) => {
|
|
2400
2431
|
await printWranglerBanner();
|
|
2401
2432
|
const config = readConfig(args.config as ConfigPath, args);
|
|
2402
|
-
const namespaceId =
|
|
2433
|
+
const namespaceId = getKVNamespaceId(args, config);
|
|
2403
2434
|
|
|
2404
2435
|
if (!args.force) {
|
|
2405
2436
|
const result = await confirm(
|
|
@@ -2444,7 +2475,7 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2444
2475
|
|
|
2445
2476
|
const accountId = await requireAuth(config);
|
|
2446
2477
|
|
|
2447
|
-
await
|
|
2478
|
+
await deleteKVBulkKeyValue(
|
|
2448
2479
|
accountId,
|
|
2449
2480
|
namespaceId,
|
|
2450
2481
|
content,
|
|
@@ -2604,19 +2635,14 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
2604
2635
|
}
|
|
2605
2636
|
);
|
|
2606
2637
|
|
|
2607
|
-
wrangler
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
alias: "c",
|
|
2614
|
-
describe: "Path to .toml configuration file",
|
|
2615
|
-
type: "string",
|
|
2616
|
-
requiresArg: true,
|
|
2617
|
-
});
|
|
2638
|
+
wrangler.option("config", {
|
|
2639
|
+
alias: "c",
|
|
2640
|
+
describe: "Path to .toml configuration file",
|
|
2641
|
+
type: "string",
|
|
2642
|
+
requiresArg: true,
|
|
2643
|
+
});
|
|
2618
2644
|
|
|
2619
|
-
wrangler.group(["config", "help", "version"
|
|
2645
|
+
wrangler.group(["config", "help", "version"], "Flags:");
|
|
2620
2646
|
wrangler.help().alias("h", "help");
|
|
2621
2647
|
wrangler.version(wranglerVersion).alias("v", "version");
|
|
2622
2648
|
wrangler.exitProcess(false);
|
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,7 +129,7 @@ const KeyValueKeys = new Set([
|
|
|
119
129
|
/**
|
|
120
130
|
* Is the given object a valid `KeyValue` type?
|
|
121
131
|
*/
|
|
122
|
-
export function
|
|
132
|
+
export function isKVKeyValue(keyValue: object): keyValue is KeyValue {
|
|
123
133
|
const props = Object.keys(keyValue);
|
|
124
134
|
if (!props.includes("key") || !props.includes("value")) {
|
|
125
135
|
return false;
|
|
@@ -130,12 +140,12 @@ export function isKeyValue(keyValue: object): keyValue is KeyValue {
|
|
|
130
140
|
/**
|
|
131
141
|
* Get all the properties on the `keyValue` that are not expected.
|
|
132
142
|
*/
|
|
133
|
-
export function
|
|
143
|
+
export function unexpectedKVKeyValueProps(keyValue: KeyValue): string[] {
|
|
134
144
|
const props = Object.keys(keyValue);
|
|
135
145
|
return props.filter((prop) => !KeyValueKeys.has(prop));
|
|
136
146
|
}
|
|
137
147
|
|
|
138
|
-
export async function
|
|
148
|
+
export async function putKVKeyValue(
|
|
139
149
|
accountId: string,
|
|
140
150
|
namespaceId: string,
|
|
141
151
|
keyValue: KeyValue
|
|
@@ -151,21 +161,36 @@ export async function putKeyValue(
|
|
|
151
161
|
}
|
|
152
162
|
}
|
|
153
163
|
return await fetchResult(
|
|
154
|
-
`/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${
|
|
164
|
+
`/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${encodeURIComponent(
|
|
165
|
+
keyValue.key
|
|
166
|
+
)}`,
|
|
155
167
|
{ method: "PUT", body: keyValue.value },
|
|
156
168
|
searchParams
|
|
157
169
|
);
|
|
158
170
|
}
|
|
159
171
|
|
|
160
|
-
export async function
|
|
172
|
+
export async function getKVKeyValue(
|
|
161
173
|
accountId: string,
|
|
162
174
|
namespaceId: string,
|
|
163
175
|
key: string
|
|
164
176
|
): Promise<string> {
|
|
165
|
-
return await fetchKVGetValue(accountId, namespaceId, key);
|
|
177
|
+
return await fetchKVGetValue(accountId, namespaceId, encodeURIComponent(key));
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export async function deleteKVKeyValue(
|
|
181
|
+
accountId: string,
|
|
182
|
+
namespaceId: string,
|
|
183
|
+
key: string
|
|
184
|
+
) {
|
|
185
|
+
return await fetchResult(
|
|
186
|
+
`/accounts/${accountId}/storage/kv/namespaces/${namespaceId}/values/${encodeURIComponent(
|
|
187
|
+
key
|
|
188
|
+
)}`,
|
|
189
|
+
{ method: "DELETE" }
|
|
190
|
+
);
|
|
166
191
|
}
|
|
167
192
|
|
|
168
|
-
export async function
|
|
193
|
+
export async function putKVBulkKeyValue(
|
|
169
194
|
accountId: string,
|
|
170
195
|
namespaceId: string,
|
|
171
196
|
keyValues: KeyValue[],
|
|
@@ -190,7 +215,7 @@ export async function putBulkKeyValue(
|
|
|
190
215
|
}
|
|
191
216
|
}
|
|
192
217
|
|
|
193
|
-
export async function
|
|
218
|
+
export async function deleteKVBulkKeyValue(
|
|
194
219
|
accountId: string,
|
|
195
220
|
namespaceId: string,
|
|
196
221
|
keys: string[],
|
|
@@ -215,7 +240,7 @@ export async function deleteBulkKeyValue(
|
|
|
215
240
|
}
|
|
216
241
|
}
|
|
217
242
|
|
|
218
|
-
export function
|
|
243
|
+
export function getKVNamespaceId(
|
|
219
244
|
{ preview, binding, "namespace-id": namespaceId }: KvArgs,
|
|
220
245
|
config: Config
|
|
221
246
|
): string {
|
|
@@ -310,7 +335,7 @@ export function getNamespaceId(
|
|
|
310
335
|
/**
|
|
311
336
|
* KV namespace binding names must be valid JS identifiers.
|
|
312
337
|
*/
|
|
313
|
-
export function
|
|
338
|
+
export function isValidKVNamespaceBinding(
|
|
314
339
|
binding: string | undefined
|
|
315
340
|
): binding is string {
|
|
316
341
|
return (
|
package/src/pages.tsx
CHANGED
|
@@ -804,34 +804,30 @@ const createDeployment: CommandModule<
|
|
|
804
804
|
return yargs
|
|
805
805
|
.positional("directory", {
|
|
806
806
|
type: "string",
|
|
807
|
-
|
|
808
|
-
description: "The directory of
|
|
807
|
+
demandOption: true,
|
|
808
|
+
description: "The directory of static files to upload",
|
|
809
809
|
})
|
|
810
810
|
.options({
|
|
811
811
|
"project-name": {
|
|
812
812
|
type: "string",
|
|
813
|
-
description:
|
|
814
|
-
"The name of the project you want to list deployments for",
|
|
813
|
+
description: "The name of the project you want to deploy to",
|
|
815
814
|
},
|
|
816
815
|
branch: {
|
|
817
816
|
type: "string",
|
|
818
|
-
description:
|
|
819
|
-
"The branch of the project you want to list deployments for",
|
|
817
|
+
description: "The name of the branch you want to deploy to",
|
|
820
818
|
},
|
|
821
819
|
"commit-hash": {
|
|
822
820
|
type: "string",
|
|
823
|
-
description:
|
|
824
|
-
"The branch of the project you want to list deployments for",
|
|
821
|
+
description: "The SHA to attach to this deployment",
|
|
825
822
|
},
|
|
826
823
|
"commit-message": {
|
|
827
824
|
type: "string",
|
|
828
|
-
description:
|
|
829
|
-
"The branch of the project you want to list deployments for",
|
|
825
|
+
description: "The commit message to attach to this deployment",
|
|
830
826
|
},
|
|
831
827
|
"commit-dirty": {
|
|
832
828
|
type: "boolean",
|
|
833
829
|
description:
|
|
834
|
-
"
|
|
830
|
+
"Whether or not the workspace should be considered dirty for this deployment",
|
|
835
831
|
},
|
|
836
832
|
})
|
|
837
833
|
.epilogue(pagesBetaWarning);
|
|
@@ -844,6 +840,10 @@ const createDeployment: CommandModule<
|
|
|
844
840
|
commitMessage,
|
|
845
841
|
commitDirty,
|
|
846
842
|
}) => {
|
|
843
|
+
if (!directory) {
|
|
844
|
+
throw new FatalError("Must specify a directory.", 1);
|
|
845
|
+
}
|
|
846
|
+
|
|
847
847
|
const config = getConfigCache<PagesConfigCache>(
|
|
848
848
|
PAGES_CONFIG_CACHE_FILENAME
|
|
849
849
|
);
|
|
@@ -1576,6 +1576,10 @@ export const pages: BuilderCallback<unknown, unknown> = (yargs) => {
|
|
|
1576
1576
|
default: false,
|
|
1577
1577
|
description: "Build a plugin rather than a Worker script",
|
|
1578
1578
|
},
|
|
1579
|
+
"build-output-directory": {
|
|
1580
|
+
type: "string",
|
|
1581
|
+
description: "The directory to output static assets to",
|
|
1582
|
+
},
|
|
1579
1583
|
})
|
|
1580
1584
|
.epilogue(pagesBetaWarning),
|
|
1581
1585
|
async ({
|
|
@@ -1587,12 +1591,15 @@ export const pages: BuilderCallback<unknown, unknown> = (yargs) => {
|
|
|
1587
1591
|
fallbackService,
|
|
1588
1592
|
watch,
|
|
1589
1593
|
plugin,
|
|
1594
|
+
"build-output-directory": buildOutputDirectory,
|
|
1590
1595
|
}) => {
|
|
1591
1596
|
if (!isInPagesCI) {
|
|
1592
1597
|
// Beta message for `wrangler pages <commands>` usage
|
|
1593
1598
|
logger.log(pagesBetaWarning);
|
|
1594
1599
|
}
|
|
1595
1600
|
|
|
1601
|
+
buildOutputDirectory ??= dirname(outfile);
|
|
1602
|
+
|
|
1596
1603
|
await buildFunctions({
|
|
1597
1604
|
outfile,
|
|
1598
1605
|
outputConfigPath,
|
|
@@ -1602,7 +1609,7 @@ export const pages: BuilderCallback<unknown, unknown> = (yargs) => {
|
|
|
1602
1609
|
fallbackService,
|
|
1603
1610
|
watch,
|
|
1604
1611
|
plugin,
|
|
1605
|
-
buildOutputDirectory
|
|
1612
|
+
buildOutputDirectory,
|
|
1606
1613
|
});
|
|
1607
1614
|
}
|
|
1608
1615
|
)
|
package/src/sites.tsx
CHANGED
|
@@ -3,11 +3,11 @@ import * as path from "node:path";
|
|
|
3
3
|
import ignore from "ignore";
|
|
4
4
|
import xxhash from "xxhash-wasm";
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
createKVNamespace,
|
|
7
|
+
listKVNamespaceKeys,
|
|
8
|
+
listKVNamespaces,
|
|
9
|
+
putKVBulkKeyValue,
|
|
10
|
+
deleteKVBulkKeyValue,
|
|
11
11
|
} from "./kv";
|
|
12
12
|
import { logger } from "./logger";
|
|
13
13
|
import type { Config } from "./config";
|
|
@@ -75,14 +75,14 @@ async function createKVNamespaceIfNotAlreadyExisting(
|
|
|
75
75
|
) {
|
|
76
76
|
// check if it already exists
|
|
77
77
|
// TODO: this is super inefficient, should be made better
|
|
78
|
-
const namespaces = await
|
|
78
|
+
const namespaces = await listKVNamespaces(accountId);
|
|
79
79
|
const found = namespaces.find((x) => x.title === title);
|
|
80
80
|
if (found) {
|
|
81
81
|
return { created: false, id: found.id };
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
// else we make the namespace
|
|
85
|
-
const id = await
|
|
85
|
+
const id = await createKVNamespace(accountId, title);
|
|
86
86
|
logger.log(`🌀 Created namespace for Workers Site "${title}"`);
|
|
87
87
|
|
|
88
88
|
return {
|
|
@@ -131,7 +131,7 @@ export async function syncAssets(
|
|
|
131
131
|
);
|
|
132
132
|
|
|
133
133
|
// let's get all the keys in this namespace
|
|
134
|
-
const namespaceKeysResponse = await
|
|
134
|
+
const namespaceKeysResponse = await listKVNamespaceKeys(accountId, namespace);
|
|
135
135
|
const namespaceKeys = new Set(namespaceKeysResponse.map((x) => x.name));
|
|
136
136
|
|
|
137
137
|
const manifest: Record<string, string> = {};
|
|
@@ -185,9 +185,9 @@ export async function syncAssets(
|
|
|
185
185
|
|
|
186
186
|
await Promise.all([
|
|
187
187
|
// upload all the new assets
|
|
188
|
-
|
|
188
|
+
putKVBulkKeyValue(accountId, namespace, toUpload, () => {}),
|
|
189
189
|
// delete all the unused assets
|
|
190
|
-
|
|
190
|
+
deleteKVBulkKeyValue(
|
|
191
191
|
accountId,
|
|
192
192
|
namespace,
|
|
193
193
|
Array.from(namespaceKeys),
|
package/src/user.tsx
CHANGED
|
@@ -214,6 +214,7 @@ import path from "node:path";
|
|
|
214
214
|
import url from "node:url";
|
|
215
215
|
import { TextEncoder } from "node:util";
|
|
216
216
|
import TOML from "@iarna/toml";
|
|
217
|
+
import { HostURL } from "@webcontainer/env";
|
|
217
218
|
import { render, Text } from "ink";
|
|
218
219
|
import SelectInput from "ink-select-input";
|
|
219
220
|
import Table from "ink-table";
|
|
@@ -339,9 +340,18 @@ export function validateScopeKeys(
|
|
|
339
340
|
const CLIENT_ID = "54d11594-84e4-41aa-b438-e81b8fa78ee7";
|
|
340
341
|
const AUTH_URL = "https://dash.cloudflare.com/oauth2/auth";
|
|
341
342
|
const TOKEN_URL = "https://dash.cloudflare.com/oauth2/token";
|
|
342
|
-
const CALLBACK_URL = "http://localhost:8976/oauth/callback";
|
|
343
343
|
const REVOKE_URL = "https://dash.cloudflare.com/oauth2/revoke";
|
|
344
344
|
|
|
345
|
+
/**
|
|
346
|
+
* To allow OAuth callbacks in environments such as WebContainer we need to
|
|
347
|
+
* create a host URL which only resolves `localhost` to a WebContainer
|
|
348
|
+
* hostname if the process is running in a WebContainer. On local this will
|
|
349
|
+
* be a no-op and it leaves the URL unmodified.
|
|
350
|
+
*
|
|
351
|
+
* @see https://www.npmjs.com/package/@webcontainer/env
|
|
352
|
+
*/
|
|
353
|
+
const CALLBACK_URL = HostURL.parse("http://localhost:8976/oauth/callback").href;
|
|
354
|
+
|
|
345
355
|
let LocalState: State = getAuthTokens();
|
|
346
356
|
|
|
347
357
|
/**
|