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/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
- getNamespaceId,
26
- listNamespaces,
27
- listNamespaceKeys,
28
- putKeyValue,
29
- putBulkKeyValue,
30
- deleteBulkKeyValue,
31
- createNamespace,
32
- isValidNamespaceBinding,
33
- getKeyValue,
34
- isKeyValue,
35
- unexpectedKeyValueProps,
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
- const isGitInstalled = (await execa("git", ["--version"])).exitCode === 0;
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://github.com/cloudflare/wrangler2/blob/main/docs/deprecations.md#build for alternatives"
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://github.com/cloudflare/wrangler2/blob/main/docs/deprecations.md#config for alternatives"
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 builtins and globals. This is experimental and has serious tradeoffs. Please see https://github.com/ionic-team/rollup-plugin-node-polyfills/ for more details."
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 || config.dev?.port || (await getPort({ port: 8787 }))
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={config.dev?.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://github.com/cloudflare/wrangler2/blob/main/docs/deprecations.md#subdomain for alternatives"
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 (!isValidNamespaceBinding(args.namespace)) {
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 createNamespace(accountId, title);
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 listNamespaces(accountId), null, " ")
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 = getNamespaceId(args, config);
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 fetchResult<{ id: string }>(
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 = getNamespaceId(args, config);
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 putKeyValue(accountId, namespaceId, {
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 = getNamespaceId(args, config);
2169
+ const namespaceId = getKVNamespaceId(args, config);
2136
2170
 
2137
2171
  const accountId = await requireAuth(config);
2138
2172
 
2139
- const results = await listNamespaceKeys(
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 = getNamespaceId(args, config);
2221
+ const namespaceId = getKVNamespaceId(args, config);
2188
2222
 
2189
2223
  const accountId = await requireAuth(config);
2190
2224
 
2191
- logger.log(await getKeyValue(accountId, namespaceId, key));
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 = getNamespaceId(args, config);
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 fetchResult(
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 = getNamespaceId(args, config);
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 (!isKeyValue(keyValue)) {
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 = unexpectedKeyValueProps(keyValue);
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 putBulkKeyValue(
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 = getNamespaceId(args, config);
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 deleteBulkKeyValue(
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
- .option("legacy-env", {
2609
- type: "boolean",
2610
- describe: "Use legacy environments",
2611
- })
2612
- .option("config", {
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", "legacy-env"], "Flags:");
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 createNamespace(
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 listNamespaces(
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 listNamespaceKeys(
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 isKeyValue(keyValue: object): keyValue is KeyValue {
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 unexpectedKeyValueProps(keyValue: KeyValue): string[] {
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 putKeyValue(
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/${keyValue.key}`,
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 getKeyValue(
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 putBulkKeyValue(
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 deleteBulkKeyValue(
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 getNamespaceId(
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 isValidNamespaceBinding(
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
- default: "functions",
808
- description: "The directory of Pages Functions",
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
- "The branch of the project you want to list deployments for",
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: dirname(outfile),
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
- createNamespace,
7
- listNamespaceKeys,
8
- listNamespaces,
9
- putBulkKeyValue,
10
- deleteBulkKeyValue,
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 listNamespaces(accountId);
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 createNamespace(accountId, title);
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 listNamespaceKeys(accountId, namespace);
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
- putBulkKeyValue(accountId, namespace, toUpload, () => {}),
188
+ putKVBulkKeyValue(accountId, namespace, toUpload, () => {}),
189
189
  // delete all the unused assets
190
- deleteBulkKeyValue(
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
  /**