wrangler
Advanced tools
Comparing version 0.0.0-973b8f2 to 0.0.0-998c12d
{ | ||
"name": "wrangler", | ||
"version": "0.0.0-973b8f2", | ||
"version": "0.0.0-998c12d", | ||
"author": "wrangler@cloudflare.com", | ||
@@ -39,5 +39,5 @@ "description": "Command-line interface for all things Cloudflare Workers", | ||
"dependencies": { | ||
"@cloudflare/pages-functions-compiler": "0.3.8", | ||
"esbuild": "0.14.1", | ||
"miniflare": "^2.0.0-rc.4", | ||
"miniflare": "2.0.0-rc.4", | ||
"path-to-regexp": "^6.2.0", | ||
"semiver": "^1.1.0" | ||
@@ -54,2 +54,3 @@ }, | ||
"@types/yargs": "^17.0.7", | ||
"acorn": "^8.6.0", | ||
"chokidar": "^3.5.2", | ||
@@ -69,3 +70,2 @@ "clipboardy": "^3.0.0", | ||
"open": "^8.4.0", | ||
"path-to-regexp": "^6.2.0", | ||
"react": "^17.0.2", | ||
@@ -83,2 +83,3 @@ "react-error-boundary": "^3.1.4", | ||
"bin", | ||
"lib", | ||
"miniflare-config-stubs", | ||
@@ -116,4 +117,7 @@ "wrangler-dist", | ||
] | ||
} | ||
}, | ||
"setupFilesAfterEnv": [ | ||
"<rootDir>/src/__tests__/jest.setup.ts" | ||
] | ||
} | ||
} |
@@ -8,37 +8,6 @@ import * as fs from "node:fs"; | ||
import { setMock, unsetAllMocks } from "./mock-cfetch"; | ||
import { confirm } from "../dialogs"; | ||
import { mockConfirm } from "./mock-dialogs"; | ||
jest.mock("../cfetch", () => jest.requireActual("./mock-cfetch")); | ||
jest.mock("../dialogs", () => { | ||
return { | ||
...jest.requireActual<object>("../dialogs"), | ||
confirm: jest | ||
.fn() | ||
.mockName("confirmMock") | ||
.mockImplementation(() => { | ||
// By default (if not configured by mockConfirm()) calls to `confirm()` should throw. | ||
throw new Error("Unexpected call to `confirm()`."); | ||
}), | ||
}; | ||
}); | ||
/** | ||
* Mock the implementation of `confirm()` that will respond with configured results | ||
* for configured confirmation text messages. | ||
* | ||
* If there is a call to `confirm()` that does not match any of the expectations | ||
* then an error is thrown. | ||
*/ | ||
function mockConfirm(...expectations: { text: string; result: boolean }[]) { | ||
(confirm as jest.Mock).mockImplementation((text: string) => { | ||
for (const { text: expectedText, result } of expectations) { | ||
if (text === expectedText) { | ||
return result; | ||
} | ||
} | ||
throw new Error(`Unexpected confirmation message: ${text}`); | ||
}); | ||
} | ||
async function w(cmd?: string) { | ||
@@ -150,2 +119,4 @@ const logSpy = jest.spyOn(console, "log").mockImplementation(); | ||
expect(typeof parsed.compatibility_date).toBe("string"); | ||
expect(fs.existsSync("./package.json")).toBe(false); | ||
expect(fs.existsSync("./tsconfig.json")).toBe(false); | ||
}); | ||
@@ -183,2 +154,140 @@ | ||
it("should create a package.json if none is found and user confirms", async () => { | ||
mockConfirm( | ||
{ | ||
text: "No package.json found. Would you like to create one?", | ||
result: true, | ||
}, | ||
{ | ||
text: "Would you like to use typescript?", | ||
result: false, | ||
} | ||
); | ||
await w("init"); | ||
expect(fs.existsSync("./package.json")).toBe(true); | ||
const packageJson = JSON.parse( | ||
fs.readFileSync("./package.json", "utf-8") | ||
); | ||
expect(packageJson.name).toEqual("worker"); // TODO: should we infer the name from the directory? | ||
expect(packageJson.version).toEqual("0.0.1"); | ||
expect(fs.existsSync("./tsconfig.json")).toBe(false); | ||
}); | ||
it("should not touch an existing package.json in the same directory", async () => { | ||
mockConfirm({ | ||
text: "Would you like to use typescript?", | ||
result: false, | ||
}); | ||
fs.writeFileSync( | ||
"./package.json", | ||
JSON.stringify({ name: "test", version: "1.0.0" }), | ||
"utf-8" | ||
); | ||
await w("init"); | ||
const packageJson = JSON.parse( | ||
fs.readFileSync("./package.json", "utf-8") | ||
); | ||
expect(packageJson.name).toEqual("test"); | ||
expect(packageJson.version).toEqual("1.0.0"); | ||
}); | ||
it("should not touch an existing package.json in an ancestor directory", async () => { | ||
mockConfirm({ | ||
text: "Would you like to use typescript?", | ||
result: false, | ||
}); | ||
fs.writeFileSync( | ||
"./package.json", | ||
JSON.stringify({ name: "test", version: "1.0.0" }), | ||
"utf-8" | ||
); | ||
fs.mkdirSync("./sub-1/sub-2", { recursive: true }); | ||
process.chdir("./sub-1/sub-2"); | ||
await w("init"); | ||
expect(fs.existsSync("./package.json")).toBe(false); | ||
expect(fs.existsSync("../../package.json")).toBe(true); | ||
const packageJson = JSON.parse( | ||
fs.readFileSync("../../package.json", "utf-8") | ||
); | ||
expect(packageJson.name).toEqual("test"); | ||
expect(packageJson.version).toEqual("1.0.0"); | ||
}); | ||
it("should create a tsconfig.json and install `workers-types` if none is found and user confirms", async () => { | ||
mockConfirm( | ||
{ | ||
text: "No package.json found. Would you like to create one?", | ||
result: true, | ||
}, | ||
{ | ||
text: "Would you like to use typescript?", | ||
result: true, | ||
} | ||
); | ||
await w("init"); | ||
expect(fs.existsSync("./tsconfig.json")).toBe(true); | ||
const tsconfigJson = JSON.parse( | ||
fs.readFileSync("./tsconfig.json", "utf-8") | ||
); | ||
expect(tsconfigJson.compilerOptions.types).toEqual([ | ||
"@cloudflare/workers-types", | ||
]); | ||
const packageJson = JSON.parse( | ||
fs.readFileSync("./package.json", "utf-8") | ||
); | ||
expect(packageJson.devDependencies).toEqual({ | ||
"@cloudflare/workers-types": expect.any(String), | ||
}); | ||
}); | ||
it("should not touch an existing tsconfig.json in the same directory", async () => { | ||
fs.writeFileSync( | ||
"./package.json", | ||
JSON.stringify({ name: "test", version: "1.0.0" }), | ||
"utf-8" | ||
); | ||
fs.writeFileSync( | ||
"./tsconfig.json", | ||
JSON.stringify({ compilerOptions: {} }), | ||
"utf-8" | ||
); | ||
await w("init"); | ||
const tsconfigJson = JSON.parse( | ||
fs.readFileSync("./tsconfig.json", "utf-8") | ||
); | ||
expect(tsconfigJson.compilerOptions).toEqual({}); | ||
}); | ||
it("should not touch an existing package.json in an ancestor directory", async () => { | ||
fs.writeFileSync( | ||
"./package.json", | ||
JSON.stringify({ name: "test", version: "1.0.0" }), | ||
"utf-8" | ||
); | ||
fs.writeFileSync( | ||
"./tsconfig.json", | ||
JSON.stringify({ compilerOptions: {} }), | ||
"utf-8" | ||
); | ||
fs.mkdirSync("./sub-1/sub-2", { recursive: true }); | ||
process.chdir("./sub-1/sub-2"); | ||
await w("init"); | ||
expect(fs.existsSync("./tsconfig.json")).toBe(false); | ||
expect(fs.existsSync("../../tsconfig.json")).toBe(true); | ||
const tsconfigJson = JSON.parse( | ||
fs.readFileSync("../../tsconfig.json", "utf-8") | ||
); | ||
expect(tsconfigJson.compilerOptions).toEqual({}); | ||
}); | ||
it("should error if `--type` is used", async () => { | ||
@@ -215,12 +324,16 @@ const noValue = await w("init --type"); | ||
describe("kv:namespace", () => { | ||
afterAll(() => { | ||
afterEach(() => { | ||
unsetAllMocks(); | ||
}); | ||
let KVNamespaces: { title: string; id: string }[] = []; | ||
it("can create a namespace", async () => { | ||
const KVNamespaces: { title: string; id: string }[] = []; | ||
setMock("/accounts/:accountId/storage/kv/namespaces", (uri, init) => { | ||
expect(init.method === "POST"); | ||
const body = JSON.parse(init.body); | ||
expect(body.title).toBe("worker-UnitTestNamespace"); | ||
KVNamespaces.push({ title: body.title, id: "some-namespace-id" }); | ||
expect(uri[0]).toEqual( | ||
"/accounts/some-account-id/storage/kv/namespaces" | ||
); | ||
const { title } = JSON.parse(init.body); | ||
expect(title).toEqual("worker-UnitTestNamespace"); | ||
KVNamespaces.push({ title, id: "some-namespace-id" }); | ||
return { id: "some-namespace-id" }; | ||
@@ -230,12 +343,26 @@ }); | ||
await w("kv:namespace create UnitTestNamespace"); | ||
expect( | ||
KVNamespaces.find((ns) => ns.title === `worker-UnitTestNamespace`) | ||
).toBeTruthy(); | ||
expect(KVNamespaces).toEqual([ | ||
{ | ||
title: "worker-UnitTestNamespace", | ||
id: "some-namespace-id", | ||
}, | ||
]); | ||
}); | ||
let createdNamespace: { id: string; title: string }; | ||
it("can list namespaces", async () => { | ||
const KVNamespaces: { title: string; id: string }[] = [ | ||
{ title: "title-1", id: "id-1" }, | ||
{ title: "title-2", id: "id-2" }, | ||
]; | ||
setMock( | ||
"/accounts/:accountId/storage/kv/namespaces\\?:qs", | ||
(uri, init) => { | ||
expect(uri[0]).toContain( | ||
"/accounts/some-account-id/storage/kv/namespaces" | ||
); | ||
expect(uri[2]).toContain("per_page=100"); | ||
expect(uri[2]).toContain("order=title"); | ||
expect(uri[2]).toContain("direction=asc"); | ||
expect(uri[2]).toContain("page=1"); | ||
expect(init).toBe(undefined); | ||
@@ -246,26 +373,25 @@ return KVNamespaces; | ||
const { stdout } = await w("kv:namespace list"); | ||
const namespaces = JSON.parse(stdout); | ||
createdNamespace = namespaces.find( | ||
(ns) => ns.title === "worker-UnitTestNamespace" | ||
); | ||
expect(createdNamespace.title).toBe("worker-UnitTestNamespace"); | ||
const namespaces = JSON.parse(stdout) as { id: string; title: string }[]; | ||
expect(namespaces).toEqual(KVNamespaces); | ||
}); | ||
it("can delete a namespace", async () => { | ||
const namespaceIdToDelete = createdNamespace.id; | ||
let accountId = ""; | ||
let namespaceId = ""; | ||
setMock( | ||
"/accounts/:accountId/storage/kv/namespaces/:namespaceId", | ||
(uri, init) => { | ||
accountId = uri[1]; | ||
namespaceId = uri[2]; | ||
expect(uri[0]).toEqual( | ||
"/accounts/some-account-id/storage/kv/namespaces/some-namespace-id" | ||
); | ||
expect(init.method).toBe("DELETE"); | ||
KVNamespaces = KVNamespaces.filter( | ||
(ns) => ns.id !== namespaceIdToDelete | ||
); | ||
} | ||
); | ||
await w(`kv:namespace delete --namespace-id ${namespaceIdToDelete}`); | ||
expect(KVNamespaces.find((ns) => ns.id === namespaceIdToDelete)).toBe( | ||
undefined | ||
); | ||
await w(`kv:namespace delete --namespace-id some-namespace-id`); | ||
expect(accountId).toEqual("some-account-id"); | ||
expect(namespaceId).toEqual("some-namespace-id"); | ||
}); | ||
}); | ||
}); |
@@ -13,4 +13,7 @@ // This file mocks ../cfetch.ts | ||
for (const { regexp, handler } of mocks) { | ||
if (regexp.test(resource)) { | ||
return handler(resource, init); // should we have some kind of fallthrough system? we'll see. | ||
// The `resource` regular expression will extract the labelled groups from the URL. | ||
// Let's pass these through to the handler, to allow it to do additional checks or behaviour. | ||
const uri = regexp.exec(resource); | ||
if (uri !== null) { | ||
return handler(uri, init); // TODO: should we have some kind of fallthrough system? we'll see. | ||
} | ||
@@ -17,0 +20,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
12489463
71
10129
+ Addedpath-to-regexp@^6.2.0
+ Added@miniflare/cache@2.0.0-rc.4(transitive)
+ Added@miniflare/cli-parser@2.0.0-rc.4(transitive)
+ Added@miniflare/core@2.0.0-rc.4(transitive)
+ Added@miniflare/durable-objects@2.0.0-rc.4(transitive)
+ Added@miniflare/html-rewriter@2.0.0-rc.4(transitive)
+ Added@miniflare/http-server@2.0.0-rc.4(transitive)
+ Added@miniflare/kv@2.0.0-rc.4(transitive)
+ Added@miniflare/runner-vm@2.0.0-rc.4(transitive)
+ Added@miniflare/scheduler@2.0.0-rc.4(transitive)
+ Added@miniflare/shared@2.0.0-rc.4(transitive)
+ Added@miniflare/sites@2.0.0-rc.4(transitive)
+ Added@miniflare/storage-file@2.0.0-rc.4(transitive)
+ Added@miniflare/storage-memory@2.0.0-rc.4(transitive)
+ Added@miniflare/watcher@2.0.0-rc.4(transitive)
+ Added@miniflare/web-sockets@2.0.0-rc.4(transitive)
+ Addedbusboy@0.3.1(transitive)
+ Addeddicer@0.3.0(transitive)
+ Addedhtml-rewriter-wasm@0.3.2(transitive)
+ Addedignore@5.3.2(transitive)
+ Addedminiflare@2.0.0-rc.4(transitive)
+ Addednode-forge@0.10.0(transitive)
+ Addedselfsigned@1.10.14(transitive)
+ Addedstreamsearch@0.1.2(transitive)
+ Addedundici@4.16.0(transitive)
- Removed@cloudflare/pages-functions-compiler@0.3.8(transitive)
- Removed@fastify/busboy@2.1.1(transitive)
- Removed@miniflare/cache@2.14.4(transitive)
- Removed@miniflare/cli-parser@2.14.4(transitive)
- Removed@miniflare/core@2.14.4(transitive)
- Removed@miniflare/d1@2.14.4(transitive)
- Removed@miniflare/durable-objects@2.14.4(transitive)
- Removed@miniflare/html-rewriter@2.14.4(transitive)
- Removed@miniflare/http-server@2.14.4(transitive)
- Removed@miniflare/kv@2.14.4(transitive)
- Removed@miniflare/queues@2.14.4(transitive)
- Removed@miniflare/r2@2.14.4(transitive)
- Removed@miniflare/runner-vm@2.14.4(transitive)
- Removed@miniflare/scheduler@2.14.4(transitive)
- Removed@miniflare/shared@2.14.4(transitive)
- Removed@miniflare/sites@2.14.4(transitive)
- Removed@miniflare/storage-file@2.14.4(transitive)
- Removed@miniflare/storage-memory@2.14.4(transitive)
- Removed@miniflare/watcher@2.14.4(transitive)
- Removed@miniflare/web-sockets@2.14.4(transitive)
- Removed@types/better-sqlite3@7.6.12(transitive)
- Removed@types/node@22.10.7(transitive)
- Removed@types/node-forge@1.3.11(transitive)
- Removedacorn@8.14.0(transitive)
- Removedacorn-walk@8.3.4(transitive)
- Removedbuiltins@5.1.0(transitive)
- Removedbusboy@1.6.0(transitive)
- Removedcommander@8.3.0(transitive)
- Removedcross-spawn@7.0.6(transitive)
- Removedexeca@6.1.0(transitive)
- Removedget-stream@6.0.1(transitive)
- Removedhtml-rewriter-wasm@0.4.1(transitive)
- Removedhuman-signals@3.0.1(transitive)
- Removedis-stream@3.0.0(transitive)
- Removedisexe@2.0.0(transitive)
- Removedmerge-stream@2.0.0(transitive)
- Removedmimic-fn@4.0.0(transitive)
- Removedminiflare@2.14.4(transitive)
- Removednode-forge@1.3.1(transitive)
- Removednpm-run-path@5.3.0(transitive)
- Removednpx-import@1.1.4(transitive)
- Removedonetime@6.0.0(transitive)
- Removedparse-package-name@1.0.0(transitive)
- Removedpath-key@3.1.14.0.0(transitive)
- Removedpicomatch@2.3.1(transitive)
- Removedselfsigned@2.4.1(transitive)
- Removedsemver@7.6.3(transitive)
- Removedshebang-command@2.0.0(transitive)
- Removedshebang-regex@3.0.0(transitive)
- Removedsignal-exit@3.0.7(transitive)
- Removedstreamsearch@1.1.0(transitive)
- Removedstrip-final-newline@3.0.0(transitive)
- Removedundici@5.28.4(transitive)
- Removedundici-types@6.20.0(transitive)
- Removedurlpattern-polyfill@4.0.3(transitive)
- Removedvalidate-npm-package-name@4.0.0(transitive)
- Removedwhich@2.0.2(transitive)
Updatedminiflare@2.0.0-rc.4