Skip to content

Commit 2f706d1

Browse files
committed
fix KV namespace ID
1 parent 8b942f3 commit 2f706d1

File tree

3 files changed

+56
-13
lines changed

3 files changed

+56
-13
lines changed

packages/wrangler/src/deployment-bundle/bindings.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ export async function provisionBindings(
543543
}
544544
}
545545

546-
function getSettings(
546+
export function getSettings(
547547
complianceConfig: ComplianceConfig,
548548
accountId: string,
549549
scriptName: string

packages/wrangler/src/kv/helpers.ts

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1+
import assert from "node:assert";
12
import { Blob } from "node:buffer";
23
import { URLSearchParams } from "node:url";
34
import { type KVNamespace } from "@cloudflare/workers-types/experimental";
45
import { Miniflare } from "miniflare";
56
import { FormData } from "undici";
67
import { fetchKVGetValue, fetchListResult, fetchResult } from "../cfetch";
8+
import { getSettings } from "../deployment-bundle/bindings";
79
import { getLocalPersistencePath } from "../dev/get-local-persistence-path";
810
import { getDefaultPersistRoot } from "../dev/miniflare";
911
import { UserError } from "../errors";
12+
import { getFlag } from "../experimental-flags";
1013
import { logger } from "../logger";
14+
import { requireAuth } from "../user";
1115
import type { Config } from "../config";
1216
import type { ComplianceConfig } from "../environment-variables/misc-variables";
1317
import type { ReplaceWorkersTypes } from "miniflare";
@@ -420,10 +424,38 @@ export async function deleteKVBulkKeyValue(
420424
}
421425
}
422426

423-
export function getKVNamespaceId(
427+
async function getIdFromSettings(
428+
config: Config,
429+
binding: string,
430+
isLocal: boolean
431+
) {
432+
// Don't do any network stuff when local, instead respect what
433+
// Wrangler dev does, which is to use the binding name as a fallback
434+
// for the namespace ID
435+
if (isLocal) {
436+
return binding;
437+
}
438+
const accountId = await requireAuth(config);
439+
if (!config.name) {
440+
throw new UserError("No Worker name found in config");
441+
}
442+
const settings = await getSettings(config, accountId, config.name);
443+
const existingKV = settings?.bindings.find(
444+
(existing) => existing.type === "kv_namespace" && existing.name === binding
445+
);
446+
if (!existingKV || !("namespace_id" in existingKV)) {
447+
throw new UserError(
448+
`No namespace ID found for binding "${binding}". Add one to your wrangler config file or pass it via \`--namespace-id\`.`
449+
);
450+
}
451+
return existingKV.namespace_id as string;
452+
}
453+
454+
export async function getKVNamespaceId(
424455
{ preview, binding, "namespace-id": namespaceId }: KvArgs,
425-
config: Config
426-
): string {
456+
config: Config,
457+
isLocal: boolean
458+
): Promise<string> {
427459
// nice
428460
if (namespaceId) {
429461
return namespaceId;
@@ -483,8 +515,12 @@ export function getKVNamespaceId(
483515
// We don't want to execute code below if preview is set to true, so we just return. Otherwise we can get error!
484516
return namespaceId;
485517
} else if (previewIsDefined) {
518+
if (getFlag("RESOURCES_PROVISION")) {
519+
assert(binding);
520+
return getIdFromSettings(config, binding, isLocal);
521+
}
486522
throw new UserError(
487-
`No namespace ID found for ${binding}. Add one to your wrangler config file to use a separate namespace for previewing your worker.`
523+
`No namespace ID found for ${binding}. Add one to your wrangler config file or pass it via \`--namespace-id\`.`
488524
);
489525
}
490526

@@ -494,6 +530,13 @@ export function getKVNamespaceId(
494530
(!namespace.id && namespace.preview_id);
495531
if (bindingHasOnlyOneId) {
496532
namespaceId = namespace.id || namespace.preview_id;
533+
} else if (
534+
getFlag("RESOURCES_PROVISION") &&
535+
!namespace.id &&
536+
!namespace.preview_id
537+
) {
538+
assert(binding);
539+
return getIdFromSettings(config, binding, isLocal);
497540
} else {
498541
throw new UserError(
499542
`${binding} has both a namespace ID and a preview ID. Specify "--preview" or "--preview false" to avoid writing data to the wrong namespace.`

packages/wrangler/src/kv/index.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ export const kvNamespaceDeleteCommand = createCommand({
179179
printResourceLocation("remote");
180180
let id;
181181
try {
182-
id = getKVNamespaceId(args, config);
182+
id = await getKVNamespaceId(args, config, false);
183183
} catch (e) {
184184
throw new CommandLineArgsError(
185185
"Not able to delete namespace.\n" + ((e as Error).message ?? e)
@@ -374,7 +374,7 @@ export const kvKeyPutCommand = createCommand({
374374
async handler({ key, ttl, expiration, metadata, ...args }) {
375375
const localMode = isLocal(args);
376376
const config = readConfig(args);
377-
const namespaceId = getKVNamespaceId(args, config);
377+
const namespaceId = await getKVNamespaceId(args, config, localMode);
378378
// One of `args.path` and `args.value` must be defined
379379
const value = args.path
380380
? readFileSyncToBuffer(args.path)
@@ -486,7 +486,7 @@ export const kvKeyListCommand = createCommand({
486486
const localMode = isLocal(args);
487487
// TODO: support for limit+cursor (pagination)
488488
const config = readConfig(args);
489-
const namespaceId = getKVNamespaceId(args, config);
489+
const namespaceId = await getKVNamespaceId(args, config, localMode);
490490

491491
let result: NamespaceKeyInfo[];
492492
let metricEvent: EventNames;
@@ -577,7 +577,7 @@ export const kvKeyGetCommand = createCommand({
577577
async handler({ key, ...args }) {
578578
const localMode = isLocal(args);
579579
const config = readConfig(args);
580-
const namespaceId = getKVNamespaceId(args, config);
580+
const namespaceId = await getKVNamespaceId(args, config, localMode);
581581

582582
let bufferKVValue;
583583
let metricEvent: EventNames;
@@ -669,7 +669,7 @@ export const kvKeyDeleteCommand = createCommand({
669669
async handler({ key, ...args }) {
670670
const localMode = isLocal(args);
671671
const config = readConfig(args);
672-
const namespaceId = getKVNamespaceId(args, config);
672+
const namespaceId = await getKVNamespaceId(args, config, localMode);
673673

674674
logger.log(`Deleting the key "${key}" on namespace ${namespaceId}.`);
675675

@@ -744,7 +744,7 @@ export const kvBulkGetCommand = createCommand({
744744
async handler({ filename, ...args }) {
745745
const localMode = isLocal(args);
746746
const config = readConfig(args);
747-
const namespaceId = getKVNamespaceId(args, config);
747+
const namespaceId = await getKVNamespaceId(args, config, localMode);
748748

749749
const content = parseJSON(readFileSync(filename), filename) as (
750750
| string
@@ -886,7 +886,7 @@ export const kvBulkPutCommand = createCommand({
886886
// but we'll do that in the future if needed.
887887

888888
const config = readConfig(args);
889-
const namespaceId = getKVNamespaceId(args, config);
889+
const namespaceId = await getKVNamespaceId(args, config, localMode);
890890
const content = parseJSON(readFileSync(filename), filename);
891891

892892
if (!Array.isArray(content)) {
@@ -1036,7 +1036,7 @@ export const kvBulkDeleteCommand = createCommand({
10361036
async handler({ filename, ...args }) {
10371037
const localMode = isLocal(args);
10381038
const config = readConfig(args);
1039-
const namespaceId = getKVNamespaceId(args, config);
1039+
const namespaceId = await getKVNamespaceId(args, config, localMode);
10401040

10411041
if (!args.force) {
10421042
const result = await confirm(

0 commit comments

Comments
 (0)