From 4d92e0b6583a56ea360d8a95f5c04ea56cef1b8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Somhairle=20MacLe=C3=B2id?= Date: Fri, 6 Dec 2024 19:00:05 +0000 Subject: [PATCH] `--local` by default for `wrangler kv` & `wrangler r2` (#7392) --- .changeset/funny-pets-punch.md | 5 + .../wrangler/e2e/dev-with-resources.test.ts | 7 +- packages/wrangler/e2e/r2.test.ts | 10 +- .../wrangler/src/__tests__/kv.local.test.ts | 52 ++- packages/wrangler/src/__tests__/kv.test.ts | 340 +++++++++++------- .../wrangler/src/__tests__/r2.local.test.ts | 33 +- packages/wrangler/src/__tests__/r2.test.ts | 16 +- packages/wrangler/src/kv/index.ts | 42 ++- packages/wrangler/src/r2/object.ts | 29 +- 9 files changed, 340 insertions(+), 194 deletions(-) create mode 100644 .changeset/funny-pets-punch.md diff --git a/.changeset/funny-pets-punch.md b/.changeset/funny-pets-punch.md new file mode 100644 index 000000000000..99acf8cd6def --- /dev/null +++ b/.changeset/funny-pets-punch.md @@ -0,0 +1,5 @@ +--- +"wrangler": major +--- + +Use `--local` by default for KV & R2 diff --git a/packages/wrangler/e2e/dev-with-resources.test.ts b/packages/wrangler/e2e/dev-with-resources.test.ts index 793995073aca..9df479061632 100644 --- a/packages/wrangler/e2e/dev-with-resources.test.ts +++ b/packages/wrangler/e2e/dev-with-resources.test.ts @@ -234,8 +234,7 @@ describe.sequential.each(RUNTIMES)("Core: $flags", ({ runtime, flags }) => { describe.sequential.each(RUNTIMES)("Bindings: $flags", ({ runtime, flags }) => { const isLocal = runtime === "local"; - const resourceFlags = isLocal ? "--local" : ""; - const d1ResourceFlags = isLocal ? "" : "--remote"; + const resourceFlags = isLocal ? "" : "--remote"; let helper: WranglerE2ETestHelper; beforeEach(() => { @@ -478,7 +477,7 @@ describe.sequential.each(RUNTIMES)("Bindings: $flags", ({ runtime, flags }) => { }); const result = await helper.run( - `wrangler d1 execute ${d1ResourceFlags} DB --file schema.sql` + `wrangler d1 execute ${resourceFlags} DB --file schema.sql` ); // D1 defaults to `--local`, so we deliberately use `flags`, not `resourceFlags` const worker = helper.runLongLived(`wrangler dev ${flags}`); @@ -490,7 +489,7 @@ describe.sequential.each(RUNTIMES)("Bindings: $flags", ({ runtime, flags }) => { } const result2 = await helper.run( - `wrangler d1 execute ${d1ResourceFlags} DB --command "SELECT * FROM entries WHERE key = 'key2'"` + `wrangler d1 execute ${resourceFlags} DB --command "SELECT * FROM entries WHERE key = 'key2'"` ); expect(result2.stdout).toContain("value2"); if (isLocal) { diff --git a/packages/wrangler/e2e/r2.test.ts b/packages/wrangler/e2e/r2.test.ts index 0e3d9b838499..77bff310cb22 100644 --- a/packages/wrangler/e2e/r2.test.ts +++ b/packages/wrangler/e2e/r2.test.ts @@ -39,7 +39,7 @@ describe("r2", () => { "test-r2.txt": fileContents, }); const output = await helper.run( - `wrangler r2 object put ${bucketName}/testr2 --file test-r2.txt --content-type text/html` + `wrangler r2 object put ${bucketName}/testr2 --file test-r2.txt --content-type text/html --remote` ); expect(normalize(output.stdout)).toMatchInlineSnapshot(` "Creating object "testr2" in bucket "tmp-e2e-r2-00000000-0000-0000-0000-000000000000". @@ -49,7 +49,7 @@ describe("r2", () => { it("download object", async () => { const output = await helper.run( - `wrangler r2 object get ${bucketName}/testr2 --file test-r2o.txt` + `wrangler r2 object get ${bucketName}/testr2 --file test-r2o.txt --remote` ); expect(normalize(output.stdout)).toMatchInlineSnapshot(` "Downloading "testr2" from "tmp-e2e-r2-00000000-0000-0000-0000-000000000000". @@ -64,7 +64,7 @@ describe("r2", () => { it("delete object", async () => { const output = await helper.run( - `wrangler r2 object delete ${bucketName}/testr2` + `wrangler r2 object delete ${bucketName}/testr2 --remote` ); expect(normalize(output.stdout)).toMatchInlineSnapshot(` "Deleting object "testr2" from bucket "tmp-e2e-r2-00000000-0000-0000-0000-000000000000". @@ -74,7 +74,7 @@ describe("r2", () => { it("check object deleted", async () => { const output = await helper.run( - `wrangler r2 object get ${bucketName}/testr2 --file test-r2o.txt` + `wrangler r2 object get ${bucketName}/testr2 --file test-r2o.txt --remote` ); expect(output.stderr).toContain("The specified key does not exist"); }); @@ -92,7 +92,7 @@ describe("r2", () => { "test-r2.txt": fileContents, }); const output = await helper.run( - `wrangler r2 object put ${bucketName}/testr2 --file test-r2.txt --content-type text/html` + `wrangler r2 object put ${bucketName}/testr2 --file test-r2.txt --content-type text/html --remote` ); expect(output.stderr).toContain("The specified bucket does not exist"); }); diff --git a/packages/wrangler/src/__tests__/kv.local.test.ts b/packages/wrangler/src/__tests__/kv.local.test.ts index e70ec49a5413..3a91556e9e5b 100644 --- a/packages/wrangler/src/__tests__/kv.local.test.ts +++ b/packages/wrangler/src/__tests__/kv.local.test.ts @@ -13,12 +13,12 @@ describe("wrangler", () => { describe("local", () => { it("should put local kv storage", async () => { await runWrangler( - `kv key get val --namespace-id some-namespace-id --local --text` + `kv key get val --namespace-id some-namespace-id --text` ); expect(std.out).toMatchInlineSnapshot(`"Value not found"`); await runWrangler( - `kv key put val value --namespace-id some-namespace-id --local` + `kv key put val value --namespace-id some-namespace-id ` ); expect(std.out).toMatchInlineSnapshot(` "Value not found @@ -26,7 +26,7 @@ describe("wrangler", () => { `); await runWrangler( - `kv key get val --namespace-id some-namespace-id --local --text` + `kv key get val --namespace-id some-namespace-id --text` ); expect(std.out).toMatchInlineSnapshot(` "Value not found @@ -36,7 +36,7 @@ describe("wrangler", () => { }); it("should list local kv storage", async () => { - await runWrangler(`kv key list --namespace-id some-namespace-id --local`); + await runWrangler(`kv key list --namespace-id some-namespace-id`); expect(std.out).toMatchInlineSnapshot(`"[]"`); const keyValues = [ { @@ -58,10 +58,10 @@ describe("wrangler", () => { ]; writeFileSync("./keys.json", JSON.stringify(keyValues)); await runWrangler( - `kv bulk put keys.json --namespace-id some-namespace-id --local` + `kv bulk put keys.json --namespace-id some-namespace-id` ); - await runWrangler(`kv key list --namespace-id some-namespace-id --local`); + await runWrangler(`kv key list --namespace-id some-namespace-id`); expect(std.out).toMatchInlineSnapshot(` "[] Success! @@ -82,13 +82,13 @@ describe("wrangler", () => { `); await runWrangler( - `kv key list --namespace-id some-namespace-id --local --prefix a` + `kv key list --namespace-id some-namespace-id --prefix a` ); await runWrangler( - `kv key list --namespace-id some-namespace-id --local --prefix a/b` + `kv key list --namespace-id some-namespace-id --prefix a/b` ); await runWrangler( - `kv key list --namespace-id some-namespace-id --local --prefix abc` + `kv key list --namespace-id some-namespace-id --prefix abc` ); expect(std.out).toMatchInlineSnapshot(` @@ -130,18 +130,16 @@ describe("wrangler", () => { it("should delete local kv storage", async () => { await runWrangler( - `kv key put val value --namespace-id some-namespace-id --local` + `kv key put val value --namespace-id some-namespace-id` ); await runWrangler( - `kv key get val --namespace-id some-namespace-id --local --text` + `kv key get val --namespace-id some-namespace-id --text` ); expect(std.out).toMatchInlineSnapshot(` "Writing the value \\"value\\" to key \\"val\\" on namespace some-namespace-id. value" `); - await runWrangler( - `kv key delete val --namespace-id some-namespace-id --local` - ); + await runWrangler(`kv key delete val --namespace-id some-namespace-id`); expect(std.out).toMatchInlineSnapshot(` "Writing the value \\"value\\" to key \\"val\\" on namespace some-namespace-id. value @@ -149,7 +147,7 @@ describe("wrangler", () => { `); await runWrangler( - `kv key get val --namespace-id some-namespace-id --local --text` + `kv key get val --namespace-id some-namespace-id --text` ); expect(std.out).toMatchInlineSnapshot(` "Writing the value \\"value\\" to key \\"val\\" on namespace some-namespace-id. @@ -160,7 +158,7 @@ describe("wrangler", () => { }); it("should put local bulk kv storage", async () => { - await runWrangler(`kv key list --namespace-id bulk-namespace-id --local`); + await runWrangler(`kv key list --namespace-id bulk-namespace-id`); expect(std.out).toMatchInlineSnapshot(`"[]"`); const keyValues = [ @@ -175,7 +173,7 @@ describe("wrangler", () => { ]; writeFileSync("./keys.json", JSON.stringify(keyValues)); await runWrangler( - `kv bulk put keys.json --namespace-id bulk-namespace-id --local` + `kv bulk put keys.json --namespace-id bulk-namespace-id` ); expect(std.out).toMatchInlineSnapshot(` "[] @@ -183,7 +181,7 @@ describe("wrangler", () => { `); await runWrangler( - `kv key get test --namespace-id bulk-namespace-id --local --text` + `kv key get test --namespace-id bulk-namespace-id --text` ); expect(std.out).toMatchInlineSnapshot(` "[] @@ -191,7 +189,7 @@ describe("wrangler", () => { value" `); - await runWrangler(`kv key list --namespace-id bulk-namespace-id --local`); + await runWrangler(`kv key list --namespace-id bulk-namespace-id`); expect(std.out).toMatchInlineSnapshot(` "[] Success! @@ -220,9 +218,9 @@ describe("wrangler", () => { ]; writeFileSync("./keys.json", JSON.stringify(keyValues)); await runWrangler( - `kv bulk put keys.json --namespace-id bulk-namespace-id --local` + `kv bulk put keys.json --namespace-id bulk-namespace-id` ); - await runWrangler(`kv key list --namespace-id bulk-namespace-id --local`); + await runWrangler(`kv key list --namespace-id bulk-namespace-id`); expect(std.out).toMatchInlineSnapshot(` "Success! [ @@ -237,7 +235,7 @@ describe("wrangler", () => { const keys = ["hello", "test"]; writeFileSync("./keys.json", JSON.stringify(keys)); await runWrangler( - `kv bulk delete keys.json --namespace-id bulk-namespace-id --local --force` + `kv bulk delete keys.json --namespace-id bulk-namespace-id --force` ); expect(std.out).toMatchInlineSnapshot(` "Success! @@ -252,7 +250,7 @@ describe("wrangler", () => { Success!" `); - await runWrangler(`kv key list --namespace-id bulk-namespace-id --local`); + await runWrangler(`kv key list --namespace-id bulk-namespace-id`); expect(std.out).toMatchInlineSnapshot(` "Success! [ @@ -270,11 +268,11 @@ describe("wrangler", () => { it("should follow persist-to for local kv storage", async () => { await runWrangler( - `kv key put val value --namespace-id some-namespace-id --local` + `kv key put val value --namespace-id some-namespace-id` ); await runWrangler( - `kv key put val persistValue --namespace-id some-namespace-id --local --persist-to ./persistdir` + `kv key put val persistValue --namespace-id some-namespace-id --persist-to ./persistdir` ); expect(std.out).toMatchInlineSnapshot(` "Writing the value \\"value\\" to key \\"val\\" on namespace some-namespace-id. @@ -282,7 +280,7 @@ describe("wrangler", () => { `); await runWrangler( - `kv key get val --namespace-id some-namespace-id --local --text` + `kv key get val --namespace-id some-namespace-id --text` ); expect(std.out).toMatchInlineSnapshot(` "Writing the value \\"value\\" to key \\"val\\" on namespace some-namespace-id. @@ -291,7 +289,7 @@ describe("wrangler", () => { `); await runWrangler( - `kv key get val --namespace-id some-namespace-id --local --text --persist-to ./persistdir` + `kv key get val --namespace-id some-namespace-id --text --persist-to ./persistdir` ); expect(std.out).toMatchInlineSnapshot(` "Writing the value \\"value\\" to key \\"val\\" on namespace some-namespace-id. diff --git a/packages/wrangler/src/__tests__/kv.test.ts b/packages/wrangler/src/__tests__/kv.test.ts index 164a6ed1bcee..e853fdbc8c08 100644 --- a/packages/wrangler/src/__tests__/kv.test.ts +++ b/packages/wrangler/src/__tests__/kv.test.ts @@ -433,7 +433,7 @@ describe("wrangler", () => { }); await runWrangler( - "kv key put my-key my-value --namespace-id some-namespace-id" + "kv key put --remote my-key my-value --namespace-id some-namespace-id" ); expect(requests.count).toEqual(1); @@ -449,7 +449,9 @@ describe("wrangler", () => { value: "my-value", }); - await runWrangler("kv key put /my-key my-value --namespace-id DS9"); + await runWrangler( + "kv key put --remote /my-key my-value --namespace-id DS9" + ); expect(requests.count).toEqual(1); expect(std.out).toMatchInlineSnapshot( @@ -465,7 +467,7 @@ describe("wrangler", () => { value: "my-value", }); await runWrangler( - "kv key put my-key my-value --binding someBinding --preview false" + "kv key put --remote my-key my-value --binding someBinding --preview false" ); expect(std.out).toMatchInlineSnapshot( @@ -483,7 +485,7 @@ describe("wrangler", () => { }); await runWrangler( - "kv key put my-key my-value --binding someBinding --preview" + "kv key put --remote my-key my-value --binding someBinding --preview" ); expect(std.out).toMatchInlineSnapshot( @@ -501,7 +503,7 @@ describe("wrangler", () => { expiration_ttl: 20, }); await runWrangler( - "kv key put my-key my-value --namespace-id some-namespace-id --expiration 10 --ttl 20" + "kv key put --remote my-key my-value --namespace-id some-namespace-id --expiration 10 --ttl 20" ); expect(requests.count).toEqual(1); expect(std.out).toMatchInlineSnapshot( @@ -517,7 +519,7 @@ describe("wrangler", () => { value: "my-value", }); await runWrangler( - "kv key put my-key my-value --binding someBinding --env some-environment --preview false" + "kv key put --remote my-key my-value --binding someBinding --env some-environment --preview false" ); expect(std.out).toMatchInlineSnapshot( `"Writing the value \\"my-value\\" to key \\"my-key\\" on namespace env-bound-id."` @@ -534,7 +536,7 @@ describe("wrangler", () => { value: buf, }); await runWrangler( - "kv key put my-key --namespace-id some-namespace-id --path foo.txt" + "kv key put --remote my-key --namespace-id some-namespace-id --path foo.txt" ); expect(std.out).toMatchInlineSnapshot( `"Writing the contents of foo.txt to the key \\"my-key\\" on namespace some-namespace-id."` @@ -554,7 +556,7 @@ describe("wrangler", () => { value: buf, }); await runWrangler( - "kv key put my-key --namespace-id another-namespace-id --path test.png" + "kv key put --remote my-key --namespace-id another-namespace-id --path test.png" ); expect(std.out).toMatchInlineSnapshot( `"Writing the contents of test.png to the key \\"my-key\\" on namespace another-namespace-id."` @@ -572,7 +574,7 @@ describe("wrangler", () => { }, }); await runWrangler( - `kv key put dKey dVal --namespace-id some-namespace-id --metadata '{"mKey":"mValue"}'` + `kv key put --remote dKey dVal --namespace-id some-namespace-id --metadata '{"mKey":"mValue"}'` ); expect(requests.count).toEqual(1); expect(std.out).toMatchInlineSnapshot( @@ -595,7 +597,7 @@ describe("wrangler", () => { }, }); await runWrangler( - `kv key put another-my-key --namespace-id some-namespace-id --path test.png --metadata '{"mKey":"mValue"}'` + `kv key put --remote another-my-key --namespace-id some-namespace-id --path test.png --metadata '{"mKey":"mValue"}'` ); expect(requests.count).toEqual(1); expect(std.out).toMatchInlineSnapshot( @@ -636,6 +638,7 @@ describe("wrangler", () => { --metadata Arbitrary JSON that is associated with a key [string] --path Read value from the file at a given path [string] --local Interact with local storage [boolean] + --remote Interact with remote storage [boolean] --persist-to Directory for local persistence [string]" `); expect(std.err).toMatchInlineSnapshot(` @@ -647,7 +650,7 @@ describe("wrangler", () => { it("should error if no binding nor namespace is provided", async () => { await expect( - runWrangler("kv key put foo bar") + runWrangler("kv key put --remote foo bar") ).rejects.toThrowErrorMatchingInlineSnapshot( `[Error: Exactly one of the arguments binding and namespace-id is required]` ); @@ -677,6 +680,7 @@ describe("wrangler", () => { --metadata Arbitrary JSON that is associated with a key [string] --path Read value from the file at a given path [string] --local Interact with local storage [boolean] + --remote Interact with remote storage [boolean] --persist-to Directory for local persistence [string]" `); expect(std.err).toMatchInlineSnapshot(` @@ -688,7 +692,9 @@ describe("wrangler", () => { it("should error if both binding and namespace is provided", async () => { await expect( - runWrangler("kv key put foo bar --binding x --namespace-id y") + runWrangler( + "kv key put --remote foo bar --binding x --namespace-id y" + ) ).rejects.toThrowErrorMatchingInlineSnapshot( `[Error: Arguments binding and namespace-id are mutually exclusive]` ); @@ -718,6 +724,7 @@ describe("wrangler", () => { --metadata Arbitrary JSON that is associated with a key [string] --path Read value from the file at a given path [string] --local Interact with local storage [boolean] + --remote Interact with remote storage [boolean] --persist-to Directory for local persistence [string]" `); expect(std.err).toMatchInlineSnapshot(` @@ -729,7 +736,7 @@ describe("wrangler", () => { it("should error if no value nor path is provided", async () => { await expect( - runWrangler("kv key put key --namespace-id 12345") + runWrangler("kv key put --remote key --namespace-id 12345") ).rejects.toThrowErrorMatchingInlineSnapshot( `[Error: Exactly one of the arguments value and path is required]` ); @@ -759,6 +766,7 @@ describe("wrangler", () => { --metadata Arbitrary JSON that is associated with a key [string] --path Read value from the file at a given path [string] --local Interact with local storage [boolean] + --remote Interact with remote storage [boolean] --persist-to Directory for local persistence [string]" `); expect(std.err).toMatchInlineSnapshot(` @@ -768,9 +776,53 @@ describe("wrangler", () => { `); }); + it("should error if both --local and --remote are provided", async () => { + await expect( + runWrangler("kv key put --remote --local key value") + ).rejects.toThrowErrorMatchingInlineSnapshot( + `[Error: Arguments remote and local are mutually exclusive]` + ); + + expect(std.out).toMatchInlineSnapshot(` + " + wrangler kv key put [value] + + Write a single key/value pair to the given namespace + + POSITIONALS + key The key to write to [string] [required] + value The value to write [string] + + GLOBAL FLAGS + -c, --config Path to Wrangler configuration file [string] + -e, --env Environment to use for operations and .env files [string] + -h, --help Show help [boolean] + -v, --version Show version number [boolean] + + OPTIONS + --binding The binding of the namespace to write to [string] + --namespace-id The id of the namespace to write to [string] + --preview Interact with a preview namespace [boolean] + --ttl Time for which the entries should be visible [number] + --expiration Time since the UNIX epoch after which the entry expires [number] + --metadata Arbitrary JSON that is associated with a key [string] + --path Read value from the file at a given path [string] + --local Interact with local storage [boolean] + --remote Interact with remote storage [boolean] + --persist-to Directory for local persistence [string]" + `); + expect(std.err).toMatchInlineSnapshot(` + "X [ERROR] Arguments remote and local are mutually exclusive + + " + `); + }); + it("should error if both value and path is provided", async () => { await expect( - runWrangler("kv key put key value --path xyz --namespace-id 12345") + runWrangler( + "kv key put --remote key value --path xyz --namespace-id 12345" + ) ).rejects.toThrowErrorMatchingInlineSnapshot( `[Error: Arguments value and path are mutually exclusive]` ); @@ -800,6 +852,7 @@ describe("wrangler", () => { --metadata Arbitrary JSON that is associated with a key [string] --path Read value from the file at a given path [string] --local Interact with local storage [boolean] + --remote Interact with remote storage [boolean] --persist-to Directory for local persistence [string]" `); expect(std.err).toMatchInlineSnapshot(` @@ -812,7 +865,7 @@ describe("wrangler", () => { it("should error if a given binding name is not in the configured kv namespaces", async () => { writeWranglerKVConfig(); await expect( - runWrangler("kv key put key value --binding otherBinding") + runWrangler("kv key put --remote key value --binding otherBinding") ).rejects.toThrowErrorMatchingInlineSnapshot( `[Error: A namespace with binding name "otherBinding" was not found in the configured "kv_namespaces".]` ); @@ -832,7 +885,9 @@ describe("wrangler", () => { value: "my-value", }); await expect( - runWrangler("kv key put my-key my-value --binding someBinding") + runWrangler( + "kv key put --remote my-key my-value --binding someBinding" + ) ).rejects.toThrowErrorMatchingInlineSnapshot( `[Error: someBinding has both a namespace ID and a preview ID. Specify "--preview" or "--preview false" to avoid writing data to the wrong namespace.]` ); @@ -854,23 +909,25 @@ describe("wrangler", () => { { name: "key-3", expiration_ttl: 666 }, ]; mockKeyListRequest("some-namespace-id", keys); - await runWrangler("kv key list --namespace-id some-namespace-id"); + await runWrangler( + "kv key list --remote --namespace-id some-namespace-id" + ); expect(std.err).toMatchInlineSnapshot(`""`); expect(std.out).toMatchInlineSnapshot(` - "[ - { - \\"name\\": \\"key-1\\" - }, - { - \\"name\\": \\"key-2\\", - \\"expiration\\": 123456789 - }, - { - \\"name\\": \\"key-3\\", - \\"expiration_ttl\\": 666 - } - ]" - `); + "[ + { + \\"name\\": \\"key-1\\" + }, + { + \\"name\\": \\"key-2\\", + \\"expiration\\": 123456789 + }, + { + \\"name\\": \\"key-3\\", + \\"expiration_ttl\\": 666 + } + ]" + `); }); it("should list the keys of a namespace specified by binding", async () => { @@ -878,42 +935,44 @@ describe("wrangler", () => { const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }]; mockKeyListRequest("bound-id", keys); - await runWrangler("kv key list --binding someBinding"); + await runWrangler("kv key list --remote --binding someBinding"); expect(std.err).toMatchInlineSnapshot(`""`); expect(std.out).toMatchInlineSnapshot(` - "[ - { - \\"name\\": \\"key-1\\" - }, - { - \\"name\\": \\"key-2\\" - }, - { - \\"name\\": \\"key-3\\" - } - ]" - `); + "[ + { + \\"name\\": \\"key-1\\" + }, + { + \\"name\\": \\"key-2\\" + }, + { + \\"name\\": \\"key-3\\" + } + ]" + `); }); it("should list the keys of a preview namespace specified by binding", async () => { writeWranglerKVConfig(); const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }]; mockKeyListRequest("preview-bound-id", keys); - await runWrangler("kv key list --binding someBinding --preview"); + await runWrangler( + "kv key list --remote --binding someBinding --preview" + ); expect(std.err).toMatchInlineSnapshot(`""`); expect(std.out).toMatchInlineSnapshot(` - "[ - { - \\"name\\": \\"key-1\\" - }, - { - \\"name\\": \\"key-2\\" - }, - { - \\"name\\": \\"key-3\\" - } - ]" - `); + "[ + { + \\"name\\": \\"key-1\\" + }, + { + \\"name\\": \\"key-2\\" + }, + { + \\"name\\": \\"key-3\\" + } + ]" + `); }); it("should list the keys of a namespace specified by binding, in a given environment", async () => { @@ -921,22 +980,22 @@ describe("wrangler", () => { const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }]; mockKeyListRequest("env-bound-id", keys); await runWrangler( - "kv key list --binding someBinding --env some-environment" + "kv key list --remote --binding someBinding --env some-environment" ); expect(std.err).toMatchInlineSnapshot(`""`); expect(std.out).toMatchInlineSnapshot(` - "[ - { - \\"name\\": \\"key-1\\" - }, - { - \\"name\\": \\"key-2\\" - }, - { - \\"name\\": \\"key-3\\" - } - ]" - `); + "[ + { + \\"name\\": \\"key-1\\" + }, + { + \\"name\\": \\"key-2\\" + }, + { + \\"name\\": \\"key-3\\" + } + ]" + `); }); it("should list the keys of a preview namespace specified by binding, in a given environment", async () => { @@ -944,22 +1003,22 @@ describe("wrangler", () => { const keys = [{ name: "key-1" }, { name: "key-2" }, { name: "key-3" }]; mockKeyListRequest("preview-env-bound-id", keys); await runWrangler( - "kv key list --binding someBinding --preview --env some-environment" + "kv key list --remote --binding someBinding --preview --env some-environment" ); expect(std.err).toMatchInlineSnapshot(`""`); expect(std.out).toMatchInlineSnapshot(` - "[ - { - \\"name\\": \\"key-1\\" - }, - { - \\"name\\": \\"key-2\\" - }, - { - \\"name\\": \\"key-3\\" - } - ]" - `); + "[ + { + \\"name\\": \\"key-1\\" + }, + { + \\"name\\": \\"key-2\\" + }, + { + \\"name\\": \\"key-3\\" + } + ]" + `); }); // We'll run the next test with variations on the cursor @@ -984,7 +1043,9 @@ describe("wrangler", () => { 100, blankCursorValue ); - await runWrangler("kv key list --namespace-id some-namespace-id"); + await runWrangler( + "kv key list --remote --namespace-id some-namespace-id" + ); expect(std.err).toEqual(""); expect(JSON.parse(std.out)).toEqual(keys); expect(requests.count).toEqual(6); @@ -995,7 +1056,7 @@ describe("wrangler", () => { it("should error if a given binding name is not in the configured kv namespaces", async () => { writeWranglerKVConfig(); await expect( - runWrangler("kv key list --binding otherBinding") + runWrangler("kv key list --remote --binding otherBinding") ).rejects.toThrowErrorMatchingInlineSnapshot( `[Error: A namespace with binding name "otherBinding" was not found in the configured "kv_namespaces".]` ); @@ -1017,7 +1078,9 @@ describe("wrangler", () => { "my-value" ); - await runWrangler("kv key get my-key --namespace-id some-namespace-id"); + await runWrangler( + "kv key get --remote my-key --namespace-id some-namespace-id" + ); expect(proc.write).toEqual(Buffer.from("my-value")); expect(std.err).toMatchInlineSnapshot(`""`); @@ -1031,18 +1094,18 @@ describe("wrangler", () => { "my-value" ); await runWrangler( - "kv key get my-key --text --namespace-id some-namespace-id" + "kv key get --remote my-key --text --namespace-id some-namespace-id" ); expect(proc.write).not.toEqual(Buffer.from("my-value")); expect(std).toMatchInlineSnapshot(` - Object { - "debug": "", - "err": "", - "info": "", - "out": "my-value", - "warn": "", - } - `); + Object { + "debug": "", + "err": "", + "info": "", + "out": "my-value", + "warn": "", + } + `); }); it("should get a binary and decode as utf8 text, resulting in improper decoding", async () => { @@ -1057,7 +1120,7 @@ describe("wrangler", () => { buf ); await runWrangler( - "kv key get my-key --text --namespace-id some-namespace-id" + "kv key get --remote my-key --text --namespace-id some-namespace-id" ); expect(proc.write).not.toEqual(buf); expect(JSON.stringify(std)).toMatchInlineSnapshot( @@ -1076,7 +1139,9 @@ describe("wrangler", () => { "my-key", buf ); - await runWrangler("kv key get my-key --namespace-id some-namespace-id"); + await runWrangler( + "kv key get --remote my-key --namespace-id some-namespace-id" + ); expect(proc.write).toEqual(buf); expect(std.err).toMatchInlineSnapshot(`""`); }); @@ -1090,7 +1155,7 @@ describe("wrangler", () => { "my-value" ); await runWrangler( - "kv key get my-key --binding someBinding --preview false" + "kv key get --remote my-key --binding someBinding --preview false" ); expect(proc.write).toEqual(Buffer.from("my-value")); expect(std.err).toMatchInlineSnapshot(`""`); @@ -1104,7 +1169,9 @@ describe("wrangler", () => { "my-key", "my-value" ); - await runWrangler("kv key get my-key --binding someBinding --preview"); + await runWrangler( + "kv key get --remote my-key --binding someBinding --preview" + ); expect(proc.write).toEqual(Buffer.from("my-value")); expect(std.err).toMatchInlineSnapshot(`""`); }); @@ -1118,7 +1185,7 @@ describe("wrangler", () => { "my-value" ); await runWrangler( - "kv key get my-key --binding someBinding --env some-environment --preview false" + "kv key get --remote my-key --binding someBinding --env some-environment --preview false" ); expect(proc.write).toEqual(Buffer.from("my-value")); expect(std.err).toMatchInlineSnapshot(`""`); @@ -1133,7 +1200,7 @@ describe("wrangler", () => { ); await runWrangler( - "kv key get /my,key --namespace-id some-namespace-id" + "kv key get --remote /my,key --namespace-id some-namespace-id" ); expect(proc.write).toEqual(Buffer.from("my-value")); expect(std.err).toMatchInlineSnapshot(`""`); @@ -1166,6 +1233,7 @@ describe("wrangler", () => { --preview Interact with a preview namespace [boolean] [default: false] --text Decode the returned value as a utf8 string [boolean] [default: false] --local Interact with local storage [boolean] + --remote Interact with remote storage [boolean] --persist-to Directory for local persistence [string]" `); expect(std.err).toMatchInlineSnapshot(` @@ -1177,7 +1245,7 @@ describe("wrangler", () => { it("should error if no binding nor namespace is provided", async () => { await expect( - runWrangler("kv key get foo") + runWrangler("kv key get --remote foo") ).rejects.toThrowErrorMatchingInlineSnapshot( `[Error: Exactly one of the arguments binding and namespace-id is required]` ); @@ -1202,6 +1270,7 @@ describe("wrangler", () => { --preview Interact with a preview namespace [boolean] [default: false] --text Decode the returned value as a utf8 string [boolean] [default: false] --local Interact with local storage [boolean] + --remote Interact with remote storage [boolean] --persist-to Directory for local persistence [string]" `); expect(std.err).toMatchInlineSnapshot(` @@ -1213,7 +1282,7 @@ describe("wrangler", () => { it("should error if both binding and namespace is provided", async () => { await expect( - runWrangler("kv key get foo --binding x --namespace-id y") + runWrangler("kv key get --remote foo --binding x --namespace-id y") ).rejects.toThrowErrorMatchingInlineSnapshot( `[Error: Arguments binding and namespace-id are mutually exclusive]` ); @@ -1239,6 +1308,7 @@ describe("wrangler", () => { --preview Interact with a preview namespace [boolean] [default: false] --text Decode the returned value as a utf8 string [boolean] [default: false] --local Interact with local storage [boolean] + --remote Interact with remote storage [boolean] --persist-to Directory for local persistence [string]" `); expect(std.err).toMatchInlineSnapshot(` @@ -1251,7 +1321,7 @@ describe("wrangler", () => { it("should error if a given binding name is not in the configured kv namespaces", async () => { writeWranglerKVConfig(); await expect( - runWrangler("kv key get key --binding otherBinding") + runWrangler("kv key get --remote key --binding otherBinding") ).rejects.toThrowErrorMatchingInlineSnapshot( `[Error: A namespace with binding name "otherBinding" was not found in the configured "kv_namespaces".]` ); @@ -1272,8 +1342,9 @@ describe("wrangler", () => { { id: "yyy", account: { id: "2", name: "two" } }, ]); setIsTTY({ stdin: false, stdout: true }); - await expect(runWrangler("kv key get key --namespace-id=xxxx")) - .rejects.toThrowErrorMatchingInlineSnapshot(` + await expect( + runWrangler("kv key get --remote key --namespace-id=xxxx") + ).rejects.toThrowErrorMatchingInlineSnapshot(` [Error: More than one account available but unable to select one in non-interactive mode. Please set the appropriate \`account_id\` in your Wrangler configuration file. Available accounts are (\`\`: \`\`): @@ -1288,8 +1359,9 @@ describe("wrangler", () => { { id: "yyy", account: { id: "2", name: "two" } }, ]); setIsTTY({ stdin: true, stdout: false }); - await expect(runWrangler("kv key get key --namespace-id=xxxx")) - .rejects.toThrowErrorMatchingInlineSnapshot(` + await expect( + runWrangler("kv key get --remote key --namespace-id=xxxx") + ).rejects.toThrowErrorMatchingInlineSnapshot(` [Error: More than one account available but unable to select one in non-interactive mode. Please set the appropriate \`account_id\` in your Wrangler configuration file. Available accounts are (\`\`: \`\`): @@ -1316,8 +1388,9 @@ describe("wrangler", () => { { once: true } ) ); - await expect(runWrangler("kv key get key --namespace-id=xxxx")) - .rejects.toThrowErrorMatchingInlineSnapshot(` + await expect( + runWrangler("kv key get --remote key --namespace-id=xxxx") + ).rejects.toThrowErrorMatchingInlineSnapshot(` [Error: Failed to automatically retrieve account IDs for the logged in user. You may have incorrect permissions on your API token. You can skip this account check by adding an \`account_id\` in your Wrangler configuration file, or by setting the value of CLOUDFLARE_ACCOUNT_ID"] `); @@ -1329,8 +1402,9 @@ describe("wrangler", () => { { id: "yyy", account: { id: "2", name: "two" } }, ]); setIsTTY(false); - await expect(runWrangler("kv key get key --namespace-id=xxxx")) - .rejects.toThrowErrorMatchingInlineSnapshot(` + await expect( + runWrangler("kv key get --remote key --namespace-id=xxxx") + ).rejects.toThrowErrorMatchingInlineSnapshot(` [Error: More than one account available but unable to select one in non-interactive mode. Please set the appropriate \`account_id\` in your Wrangler configuration file. Available accounts are (\`\`: \`\`): @@ -1368,14 +1442,16 @@ describe("wrangler", () => { it("should delete a key in a namespace specified by id", async () => { const requests = mockDeleteRequest("some-namespace-id", "someKey"); await runWrangler( - `kv key delete --namespace-id some-namespace-id someKey` + `kv key delete --remote --namespace-id some-namespace-id someKey` ); expect(requests.count).toEqual(1); }); it("should encode the key in the api request to delete a value", async () => { const requests = mockDeleteRequest("voyager", "/NCC-74656"); - await runWrangler(`kv key delete --namespace-id voyager /NCC-74656`); + await runWrangler( + `kv key delete --remote --namespace-id voyager /NCC-74656` + ); expect(requests.count).toEqual(1); expect(std.out).toMatchInlineSnapshot( @@ -1388,7 +1464,7 @@ describe("wrangler", () => { writeWranglerKVConfig(); const requests = mockDeleteRequest("bound-id", "someKey"); await runWrangler( - `kv key delete --binding someBinding --preview false someKey` + `kv key delete --remote --binding someBinding --preview false someKey` ); expect(requests.count).toEqual(1); }); @@ -1397,7 +1473,7 @@ describe("wrangler", () => { writeWranglerKVConfig(); const requests = mockDeleteRequest("preview-bound-id", "someKey"); await runWrangler( - `kv key delete --binding someBinding --preview someKey` + `kv key delete --remote --binding someBinding --preview someKey` ); expect(requests.count).toEqual(1); }); @@ -1405,7 +1481,7 @@ describe("wrangler", () => { it("should error if a given binding name is not in the configured kv namespaces", async () => { writeWranglerKVConfig(); await expect( - runWrangler(`kv key delete --binding otherBinding someKey`) + runWrangler(`kv key delete --remote --binding otherBinding someKey`) ).rejects.toThrowErrorMatchingInlineSnapshot( `[Error: A namespace with binding name "otherBinding" was not found in the configured "kv_namespaces".]` ); @@ -1421,7 +1497,7 @@ describe("wrangler", () => { writeWranglerKVConfig(); const requests = mockDeleteRequest("env-bound-id", "someKey"); await runWrangler( - `kv key delete --binding someBinding --env some-environment --preview false someKey` + `kv key delete --remote --binding someBinding --env some-environment --preview false someKey` ); expect(std.out).toMatchInlineSnapshot( `"Deleting the key \\"someKey\\" on namespace env-bound-id."` @@ -1434,7 +1510,7 @@ describe("wrangler", () => { writeWranglerKVConfig(); const requests = mockDeleteRequest("preview-env-bound-id", "someKey"); await runWrangler( - `kv key delete --binding someBinding --env some-environment --preview someKey` + `kv key delete --remote --binding someBinding --env some-environment --preview someKey` ); expect(requests.count).toEqual(1); }); @@ -1480,7 +1556,7 @@ describe("wrangler", () => { writeFileSync("./keys.json", JSON.stringify(keyValues)); const requests = mockPutRequest("some-namespace-id", keyValues); await runWrangler( - `kv bulk put --namespace-id some-namespace-id keys.json` + `kv bulk put --remote --namespace-id some-namespace-id keys.json` ); expect(requests.count).toEqual(1); expect(std.out).toMatchInlineSnapshot(`"Success!"`); @@ -1496,7 +1572,7 @@ describe("wrangler", () => { writeFileSync("./keys.json", JSON.stringify(keyValues)); const requests = mockPutRequest("some-namespace-id", keyValues); await runWrangler( - `kv bulk put --namespace-id some-namespace-id keys.json` + `kv bulk put --remote --namespace-id some-namespace-id keys.json` ); expect(requests.count).toEqual(12); expect(std.out).toMatchInlineSnapshot(` @@ -1523,7 +1599,9 @@ describe("wrangler", () => { const keyValues = { key: "someKey1", value: "someValue1" }; writeFileSync("./keys.json", JSON.stringify(keyValues)); await expect( - runWrangler(`kv bulk put --namespace-id some-namespace-id keys.json`) + runWrangler( + `kv bulk put --remote --namespace-id some-namespace-id keys.json` + ) ).rejects.toThrowErrorMatchingInlineSnapshot(` [Error: Unexpected JSON input from "keys.json". Expected an array of key-value objects but got type "object".] @@ -1560,7 +1638,9 @@ describe("wrangler", () => { ]; writeFileSync("./keys.json", JSON.stringify(keyValues)); await expect( - runWrangler(`kv bulk put --namespace-id some-namespace-id keys.json`) + runWrangler( + `kv bulk put --remote --namespace-id some-namespace-id keys.json` + ) ).rejects.toThrowErrorMatchingInlineSnapshot(` [Error: Unexpected JSON input from "keys.json". Each item in the array should be an object that matches: @@ -1638,7 +1718,7 @@ describe("wrangler", () => { }); const requests = mockDeleteRequest("some-namespace-id", keys); await runWrangler( - `kv bulk delete --namespace-id some-namespace-id keys.json` + `kv bulk delete --remote --namespace-id some-namespace-id keys.json` ); expect(requests.count).toEqual(1); expect(std.out).toMatchInlineSnapshot(`"Success!"`); @@ -1655,7 +1735,7 @@ describe("wrangler", () => { }); const requests = mockDeleteRequest("some-namespace-id", keys); await runWrangler( - `kv bulk delete --namespace-id some-namespace-id keys.json` + `kv bulk delete --remote --namespace-id some-namespace-id keys.json` ); expect(requests.count).toEqual(12); expect(std.out).toMatchInlineSnapshot(` @@ -1686,7 +1766,7 @@ describe("wrangler", () => { result: false, }); await runWrangler( - `kv bulk delete --namespace-id some-namespace-id keys.json` + `kv bulk delete --remote --namespace-id some-namespace-id keys.json` ); expect(std.out).toMatchInlineSnapshot( `"Not deleting keys read from \\"keys.json\\"."` @@ -1700,7 +1780,7 @@ describe("wrangler", () => { writeFileSync("./keys.json", JSON.stringify(keys)); const requests = mockDeleteRequest("some-namespace-id", keys); await runWrangler( - `kv bulk delete --namespace-id some-namespace-id keys.json --force` + `kv bulk delete --remote --namespace-id some-namespace-id keys.json --force` ); expect(requests.count).toEqual(1); expect(std.out).toMatchInlineSnapshot(`"Success!"`); @@ -1713,7 +1793,7 @@ describe("wrangler", () => { writeFileSync("./keys.json", JSON.stringify(keys)); const requests = mockDeleteRequest("some-namespace-id", keys); await runWrangler( - `kv bulk delete --namespace-id some-namespace-id keys.json -f` + `kv bulk delete --remote --namespace-id some-namespace-id keys.json -f` ); expect(requests.count).toEqual(1); expect(std.out).toMatchInlineSnapshot(`"Success!"`); @@ -1730,7 +1810,7 @@ describe("wrangler", () => { }); await expect( runWrangler( - `kv bulk delete --namespace-id some-namespace-id keys.json` + `kv bulk delete --remote --namespace-id some-namespace-id keys.json` ) ).rejects.toThrowErrorMatchingInlineSnapshot(` [Error: Unexpected JSON input from "keys.json". @@ -1750,7 +1830,7 @@ describe("wrangler", () => { }); await expect( runWrangler( - `kv bulk delete --namespace-id some-namespace-id keys.json` + `kv bulk delete --remote --namespace-id some-namespace-id keys.json` ) ).rejects.toThrowErrorMatchingInlineSnapshot(` [Error: Unexpected JSON input from "keys.json". diff --git a/packages/wrangler/src/__tests__/r2.local.test.ts b/packages/wrangler/src/__tests__/r2.local.test.ts index cc8642fa502e..952b89149baf 100644 --- a/packages/wrangler/src/__tests__/r2.local.test.ts +++ b/packages/wrangler/src/__tests__/r2.local.test.ts @@ -17,15 +17,21 @@ describe("r2", () => { it("should put R2 object from local bucket", async () => { await expect(() => runWrangler( - `r2 object get bucketName-object-test/wormhole-img.png --file ./wormhole-img.png --local` + `r2 object get bucketName-object-test/wormhole-img.png --file ./wormhole-img.png ` ) ).rejects.toThrowErrorMatchingInlineSnapshot( `[Error: The specified key does not exist.]` ); + expect(std.warn).toMatchInlineSnapshot(` + "▲ [WARNING] By default, \`wrangler r2\` commands access a local simulator of your R2 bucket, the same as that used by \`wrangler dev\`. To access your remote R2 bucket, re-run the command with the --remote flag + + " + `); + fs.writeFileSync("wormhole-img.png", "passageway"); await runWrangler( - `r2 object put bucketName-object-test/wormhole-img.png --file ./wormhole-img.png --local` + `r2 object put bucketName-object-test/wormhole-img.png --file ./wormhole-img.png ` ); expect(std.out).toMatchInlineSnapshot(` "Downloading \\"wormhole-img.png\\" from \\"bucketName-object-test\\". @@ -35,7 +41,7 @@ describe("r2", () => { `); await runWrangler( - `r2 object get bucketName-object-test/wormhole-img.png --file ./wormhole-img.png --local` + `r2 object get bucketName-object-test/wormhole-img.png --file ./wormhole-img.png ` ); expect(std.out).toMatchInlineSnapshot(` "Downloading \\"wormhole-img.png\\" from \\"bucketName-object-test\\". @@ -50,11 +56,16 @@ describe("r2", () => { it("should delete R2 object from local bucket", async () => { fs.writeFileSync("wormhole-img.png", "passageway"); await runWrangler( - `r2 object put bucketName-object-test/wormhole-img.png --file ./wormhole-img.png --local` + `r2 object put bucketName-object-test/wormhole-img.png --file ./wormhole-img.png ` ); + expect(std.warn).toMatchInlineSnapshot(` + "▲ [WARNING] By default, \`wrangler r2\` commands access a local simulator of your R2 bucket, the same as that used by \`wrangler dev\`. To access your remote R2 bucket, re-run the command with the --remote flag + + " + `); await runWrangler( - `r2 object get bucketName-object-test/wormhole-img.png --file ./wormhole-img.png --local` + `r2 object get bucketName-object-test/wormhole-img.png --file ./wormhole-img.png ` ); expect(std.out).toMatchInlineSnapshot(` "Creating object \\"wormhole-img.png\\" in bucket \\"bucketName-object-test\\". @@ -64,7 +75,7 @@ describe("r2", () => { `); await runWrangler( - `r2 object delete bucketName-object-test/wormhole-img.png --local` + `r2 object delete bucketName-object-test/wormhole-img.png ` ); expect(std.out).toMatchInlineSnapshot(` "Creating object \\"wormhole-img.png\\" in bucket \\"bucketName-object-test\\". @@ -77,7 +88,7 @@ describe("r2", () => { await expect(() => runWrangler( - `r2 object get bucketName-object-test/wormhole-img.png --file ./wormhole-img.png --local` + `r2 object get bucketName-object-test/wormhole-img.png --file ./wormhole-img.png ` ) ).rejects.toThrowErrorMatchingInlineSnapshot( `[Error: The specified key does not exist.]` @@ -87,23 +98,23 @@ describe("r2", () => { it("should follow persist-to for object bucket", async () => { fs.writeFileSync("wormhole-img.png", "passageway"); await runWrangler( - `r2 object put bucketName-object-test/file-one --file ./wormhole-img.png --local` + `r2 object put bucketName-object-test/file-one --file ./wormhole-img.png ` ); await runWrangler( - `r2 object put bucketName-object-test/file-two --file ./wormhole-img.png --local --persist-to ./different-dir` + `r2 object put bucketName-object-test/file-two --file ./wormhole-img.png --persist-to ./different-dir` ); await expect(() => runWrangler( - `r2 object get bucketName-object-test/file-one --file ./wormhole-img.png --local --persist-to ./different-dir` + `r2 object get bucketName-object-test/file-one --file ./wormhole-img.png --persist-to ./different-dir` ) ).rejects.toThrowErrorMatchingInlineSnapshot( `[Error: The specified key does not exist.]` ); await runWrangler( - `r2 object get bucketName-object-test/file-two --file ./wormhole-img.png --local --persist-to ./different-dir` + `r2 object get bucketName-object-test/file-two --file ./wormhole-img.png --persist-to ./different-dir` ); expect(std.out).toMatchInlineSnapshot(` "Creating object \\"file-one\\" in bucket \\"bucketName-object-test\\". diff --git a/packages/wrangler/src/__tests__/r2.test.ts b/packages/wrangler/src/__tests__/r2.test.ts index afbd9bccbb42..9c0da9092288 100644 --- a/packages/wrangler/src/__tests__/r2.test.ts +++ b/packages/wrangler/src/__tests__/r2.test.ts @@ -2085,7 +2085,7 @@ describe("r2", () => { it("should download R2 object from bucket", async () => { await runWrangler( - `r2 object get bucketName-object-test/wormhole-img.png --file ./wormhole-img.png` + `r2 object get --remote bucketName-object-test/wormhole-img.png --file ./wormhole-img.png` ); expect(std.out).toMatchInlineSnapshot(` @@ -2096,7 +2096,7 @@ describe("r2", () => { it("should download R2 object from bucket into directory", async () => { await runWrangler( - `r2 object get bucketName-object-test/wormhole-img.png --file ./a/b/c/wormhole-img.png` + `r2 object get --remote bucketName-object-test/wormhole-img.png --file ./a/b/c/wormhole-img.png` ); expect(fs.readFileSync("a/b/c/wormhole-img.png", "utf8")).toBe( "wormhole-img.png" @@ -2106,7 +2106,7 @@ describe("r2", () => { it("should upload R2 object to bucket", async () => { fs.writeFileSync("wormhole-img.png", "passageway"); await runWrangler( - `r2 object put bucketName-object-test/wormhole-img.png --file ./wormhole-img.png` + `r2 object put --remote bucketName-object-test/wormhole-img.png --file ./wormhole-img.png` ); expect(std.out).toMatchInlineSnapshot(` @@ -2118,7 +2118,7 @@ describe("r2", () => { it("should upload R2 object with storage class to bucket", async () => { fs.writeFileSync("wormhole-img.png", "passageway"); await runWrangler( - `r2 object put bucketName-object-test/wormhole-img.png --file ./wormhole-img.png -s InfrequentAccess` + `r2 object put --remote bucketName-object-test/wormhole-img.png --file ./wormhole-img.png -s InfrequentAccess` ); expect(std.out).toMatchInlineSnapshot(` @@ -2132,7 +2132,7 @@ describe("r2", () => { fs.writeFileSync("wormhole-img.png", Buffer.alloc(TOO_BIG_FILE_SIZE)); await expect( runWrangler( - `r2 object put bucketName-object-test/wormhole-img.png --file ./wormhole-img.png` + `r2 object put --remote bucketName-object-test/wormhole-img.png --file ./wormhole-img.png` ) ).rejects.toThrowErrorMatchingInlineSnapshot(` [Error: Error: Wrangler only supports uploading files up to 300 MiB in size @@ -2182,7 +2182,7 @@ describe("r2", () => { "--ct content-type-mock --cd content-disposition-mock --ce content-encoding-mock --cl content-lang-mock --cc cache-control-mock --e expire-time-mock"; await runWrangler( - `r2 object put bucketName-object-test/wormhole-img.png ${flags} --file wormhole-img.png` + `r2 object put --remote bucketName-object-test/wormhole-img.png ${flags} --file wormhole-img.png` ); expect(std.out).toMatchInlineSnapshot(` @@ -2193,7 +2193,7 @@ describe("r2", () => { it("should delete R2 object from bucket", async () => { await runWrangler( - `r2 object delete bucketName-object-test/wormhole-img.png` + `r2 object delete --remote bucketName-object-test/wormhole-img.png` ); expect(std.out).toMatchInlineSnapshot(` @@ -2206,7 +2206,7 @@ describe("r2", () => { fs.writeFileSync("wormhole-img.png", "passageway"); await expect( runWrangler( - `r2 object put bucketName-object-test/wormhole-img.png --pipe --file wormhole-img.png` + `r2 object put --remote bucketName-object-test/wormhole-img.png --pipe --file wormhole-img.png` ) ).rejects.toThrowErrorMatchingInlineSnapshot( `[Error: Arguments pipe and file are mutually exclusive]` diff --git a/packages/wrangler/src/kv/index.ts b/packages/wrangler/src/kv/index.ts index 2dad974d857e..f9ffbf6be55d 100644 --- a/packages/wrangler/src/kv/index.ts +++ b/packages/wrangler/src/kv/index.ts @@ -291,6 +291,11 @@ defineCommand({ type: "boolean", describe: "Interact with local storage", }, + remote: { + type: "boolean", + describe: "Interact with remote storage", + conflicts: "local", + }, "persist-to": { type: "string", describe: "Directory for local persistence", @@ -325,7 +330,7 @@ defineCommand({ } let metricEvent: EventNames; - if (args.local) { + if (!args.remote) { await usingLocalNamespace( args.persistTo, config.configPath, @@ -394,6 +399,11 @@ defineCommand({ type: "boolean", describe: "Interact with local storage", }, + remote: { + type: "boolean", + describe: "Interact with remote storage", + conflicts: "local", + }, "persist-to": { type: "string", describe: "Directory for local persistence", @@ -411,7 +421,7 @@ defineCommand({ let result: NamespaceKeyInfo[]; let metricEvent: EventNames; - if (args.local) { + if (!args.remote) { const listResult = await usingLocalNamespace( args.persistTo, config.configPath, @@ -476,6 +486,11 @@ defineCommand({ type: "boolean", describe: "Interact with local storage", }, + remote: { + type: "boolean", + describe: "Interact with remote storage", + conflicts: "local", + }, "persist-to": { type: "string", describe: "Directory for local persistence", @@ -492,7 +507,7 @@ defineCommand({ let bufferKVValue; let metricEvent: EventNames; - if (args.local) { + if (!args.remote) { const val = await usingLocalNamespace( args.persistTo, config.configPath, @@ -566,6 +581,11 @@ defineCommand({ type: "boolean", describe: "Interact with local storage", }, + remote: { + type: "boolean", + describe: "Interact with remote storage", + conflicts: "local", + }, "persist-to": { type: "string", describe: "Directory for local persistence", @@ -579,7 +599,7 @@ defineCommand({ logger.log(`Deleting the key "${key}" on namespace ${namespaceId}.`); let metricEvent: EventNames; - if (args.local) { + if (!args.remote) { await usingLocalNamespace( args.persistTo, config.configPath, @@ -651,6 +671,11 @@ defineCommand({ type: "boolean", describe: "Interact with local storage", }, + remote: { + type: "boolean", + describe: "Interact with remote storage", + conflicts: "local", + }, "persist-to": { type: "string", describe: "Directory for local persistence", @@ -713,7 +738,7 @@ defineCommand({ } let metricEvent: EventNames; - if (args.local) { + if (!args.remote) { await usingLocalNamespace( args.persistTo, config.configPath, @@ -783,6 +808,11 @@ defineCommand({ type: "boolean", describe: "Interact with local storage", }, + remote: { + type: "boolean", + describe: "Interact with remote storage", + conflicts: "local", + }, "persist-to": { type: "string", describe: "Directory for local persistence", @@ -833,7 +863,7 @@ defineCommand({ } let metricEvent: EventNames; - if (args.local) { + if (!args.remote) { await usingLocalNamespace( args.persistTo, config.configPath, diff --git a/packages/wrangler/src/r2/object.ts b/packages/wrangler/src/r2/object.ts index 35a85e651b7d..d7f2698c4b03 100644 --- a/packages/wrangler/src/r2/object.ts +++ b/packages/wrangler/src/r2/object.ts @@ -19,6 +19,9 @@ import { } from "./helpers"; import type { R2PutOptions } from "@cloudflare/workers-types/experimental"; +const remoteFlagWarning = + "By default, `wrangler r2` commands access a local simulator of your R2 bucket, the same as that used by `wrangler dev`. To access your remote R2 bucket, re-run the command with the --remote flag"; + defineNamespace({ command: "wrangler r2 object", metadata: { @@ -59,6 +62,11 @@ defineCommand({ type: "boolean", describe: "Interact with local storage", }, + remote: { + type: "boolean", + describe: "Interact with remote storage", + conflicts: "local", + }, "persist-to": { type: "string", describe: "Directory for local persistence", @@ -94,7 +102,10 @@ defineCommand({ } else { output = process.stdout; } - if (objectGetYargs.local) { + if (!objectGetYargs.remote) { + if (!pipe) { + logger.warn(remoteFlagWarning); + } await usingLocalBucket( objectGetYargs.persistTo, config.configPath, @@ -191,6 +202,11 @@ defineCommand({ type: "boolean", describe: "Interact with local storage", }, + remote: { + type: "boolean", + describe: "Interact with remote storage", + conflicts: "local", + }, "persist-to": { type: "string", describe: "Directory for local persistence", @@ -213,12 +229,12 @@ defineCommand({ objectPath, file, pipe, - local, persistTo, jurisdiction, storageClass, ...options } = objectPutYargs; + const local = !objectPutYargs.remote; const { bucket, key } = bucketAndKeyFromObjectPath(objectPath); if (!file && !pipe) { throw new CommandLineArgsError( @@ -275,6 +291,7 @@ defineCommand({ ); if (local) { + logger.warn(remoteFlagWarning); await usingLocalBucket( persistTo, config.configPath, @@ -357,6 +374,11 @@ defineCommand({ type: "boolean", describe: "Interact with local storage", }, + remote: { + type: "boolean", + describe: "Interact with remote storage", + conflicts: "local", + }, "persist-to": { type: "string", describe: "Directory for local persistence", @@ -379,7 +401,8 @@ defineCommand({ logger.log(`Deleting object "${key}" from bucket "${fullBucketName}".`); - if (args.local) { + if (!args.remote) { + logger.warn(remoteFlagWarning); await usingLocalBucket( args.persistTo, config.configPath,