From 01f44e5d958745c020786bc639daf2e5535641b3 Mon Sep 17 00:00:00 2001 From: Cahllagerfeld <43843195+Cahllagerfeld@users.noreply.github.com> Date: Mon, 21 Aug 2023 07:07:23 +0200 Subject: [PATCH] Refactor create-webstone-app (#388) * refactor: move build to tsup * feat: new template * refactor: remove listr2 and execa * feat: init new script * refactor: move plugin structure * feat: add new entry * refactor: further adjustments * chore: add changeset * fix: small fixes * feat: init copy function * feat: use create-svelte * feat: update dev deps * fix: deepmerge * refactor: remove plugin template * feat: copy files * fix: last updates for package.json * refactor: conditionally adjust plugin * refactor: remove unusded code * chore: package for distribution * feat: parse args * refactor: remove command-line-args * Update packages/create-webstone-app/templates/plugin-structure/build-cli.js Co-authored-by: Mike Nikles <788827+mikenikles@users.noreply.github.com> * test: add tests * test: add new tests * test: remove old tests * test: add test --------- Co-authored-by: Mike Nikles <788827+mikenikles@users.noreply.github.com> --- .changeset/fifty-onions-film.md | 5 + .vscode/settings.json | 9 + devbox.json | 2 +- devbox.lock | 8 +- package.json | 2 +- packages/cli/package.json | 2 +- packages/create-webstone-app/bin.js | 2 +- packages/create-webstone-app/package.json | 44 +- packages/create-webstone-app/scripts/build.js | 49 +- packages/create-webstone-app/src/bin.ts | 99 ++++ .../create-webstone-app/src/functions.spec.ts | 288 +++++++++++ packages/create-webstone-app/src/functions.ts | 141 ++++++ packages/create-webstone-app/src/helpers.ts | 71 +-- packages/create-webstone-app/src/index.ts | 26 +- packages/create-webstone-app/src/package.ts | 39 ++ .../src/tasks/0-determine-context/index.ts | 86 ---- .../src/tasks/1-create-directory/index.ts | 34 -- .../src/tasks/2-setup-project/application.ts | 25 - .../src/tasks/2-setup-project/index.ts | 23 - .../src/tasks/2-setup-project/plugin.ts | 148 ------ .../src/tasks/3-configure-app/application.ts | 43 -- .../src/tasks/3-configure-app/index.ts | 25 - .../src/tasks/3-configure-app/plugin.ts | 65 --- .../create-webstone-app/src/tasks/index.ts | 25 - .../templates/application/README.md | 5 - .../templates/plugin-structure/build-cli.js | 37 ++ .../templates/plugin-structure/command.ts | 16 + .../templates/plugin-structure/extension.ts | 11 + .../template.ejs | 0 .../plugin/structure/.changeset/README.md | 8 - .../plugin/structure/.changeset/config.json | 11 - .../structure/.github/workflows/changeset.yml | 40 -- .../templates/plugin/structure/.gitignore | 8 - .../templates/plugin/structure/.prettierrc | 6 - .../templates/plugin/structure/README.md | 62 --- .../templates/plugin/structure/package.json | 28 -- .../plugin/structure/packages/cli/.prettierrc | 6 - .../plugin/structure/packages/cli/README.md | 25 - .../structure/packages/cli/package.json | 42 -- .../src/commands/placeholder/hello-world.ts | 16 - .../cli/src/extensions/placeholder/hello.ts | 11 - .../structure/packages/cli/tsconfig.json | 18 - .../plugin/structure/packages/web/.gitkeep | 0 .../plugin/structure/packages/web/README.md | 23 - .../plugin/structure/pnpm-workspace.yaml | 2 - .../tests/helpers/configure-app.ts | 29 -- .../tests/helpers/create-app-dir.ts | 183 ------- .../tests/helpers/display-next-steps.ts | 36 -- .../tests/helpers/display-welcome.ts | 29 -- .../tests/helpers/setup-plugin.ts | 93 ---- packages/create-webstone-app/types/index.ts | 6 + pnpm-lock.yaml | 454 ++++-------------- 52 files changed, 818 insertions(+), 1648 deletions(-) create mode 100644 .changeset/fifty-onions-film.md create mode 100644 .vscode/settings.json mode change 100644 => 100755 packages/create-webstone-app/bin.js create mode 100644 packages/create-webstone-app/src/bin.ts create mode 100644 packages/create-webstone-app/src/functions.spec.ts create mode 100644 packages/create-webstone-app/src/functions.ts create mode 100644 packages/create-webstone-app/src/package.ts delete mode 100644 packages/create-webstone-app/src/tasks/0-determine-context/index.ts delete mode 100644 packages/create-webstone-app/src/tasks/1-create-directory/index.ts delete mode 100644 packages/create-webstone-app/src/tasks/2-setup-project/application.ts delete mode 100644 packages/create-webstone-app/src/tasks/2-setup-project/index.ts delete mode 100644 packages/create-webstone-app/src/tasks/2-setup-project/plugin.ts delete mode 100644 packages/create-webstone-app/src/tasks/3-configure-app/application.ts delete mode 100644 packages/create-webstone-app/src/tasks/3-configure-app/index.ts delete mode 100644 packages/create-webstone-app/src/tasks/3-configure-app/plugin.ts delete mode 100644 packages/create-webstone-app/src/tasks/index.ts delete mode 100644 packages/create-webstone-app/templates/application/README.md create mode 100644 packages/create-webstone-app/templates/plugin-structure/build-cli.js create mode 100644 packages/create-webstone-app/templates/plugin-structure/command.ts create mode 100644 packages/create-webstone-app/templates/plugin-structure/extension.ts rename packages/create-webstone-app/templates/{plugin/structure/packages/cli/src/templates => plugin-structure}/template.ejs (100%) delete mode 100644 packages/create-webstone-app/templates/plugin/structure/.changeset/README.md delete mode 100644 packages/create-webstone-app/templates/plugin/structure/.changeset/config.json delete mode 100644 packages/create-webstone-app/templates/plugin/structure/.github/workflows/changeset.yml delete mode 100644 packages/create-webstone-app/templates/plugin/structure/.gitignore delete mode 100644 packages/create-webstone-app/templates/plugin/structure/.prettierrc delete mode 100644 packages/create-webstone-app/templates/plugin/structure/README.md delete mode 100644 packages/create-webstone-app/templates/plugin/structure/package.json delete mode 100644 packages/create-webstone-app/templates/plugin/structure/packages/cli/.prettierrc delete mode 100644 packages/create-webstone-app/templates/plugin/structure/packages/cli/README.md delete mode 100644 packages/create-webstone-app/templates/plugin/structure/packages/cli/package.json delete mode 100644 packages/create-webstone-app/templates/plugin/structure/packages/cli/src/commands/placeholder/hello-world.ts delete mode 100644 packages/create-webstone-app/templates/plugin/structure/packages/cli/src/extensions/placeholder/hello.ts delete mode 100644 packages/create-webstone-app/templates/plugin/structure/packages/cli/tsconfig.json delete mode 100644 packages/create-webstone-app/templates/plugin/structure/packages/web/.gitkeep delete mode 100644 packages/create-webstone-app/templates/plugin/structure/packages/web/README.md delete mode 100644 packages/create-webstone-app/templates/plugin/structure/pnpm-workspace.yaml delete mode 100644 packages/create-webstone-app/tests/helpers/configure-app.ts delete mode 100644 packages/create-webstone-app/tests/helpers/create-app-dir.ts delete mode 100644 packages/create-webstone-app/tests/helpers/display-next-steps.ts delete mode 100644 packages/create-webstone-app/tests/helpers/display-welcome.ts delete mode 100644 packages/create-webstone-app/tests/helpers/setup-plugin.ts create mode 100644 packages/create-webstone-app/types/index.ts diff --git a/.changeset/fifty-onions-film.md b/.changeset/fifty-onions-film.md new file mode 100644 index 00000000..bac564e8 --- /dev/null +++ b/.changeset/fifty-onions-film.md @@ -0,0 +1,5 @@ +--- +"create-webstone-app": minor +--- + +refactor create-webstone-app to use new flow & new plugin template diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..c34a4162 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "terminal.integrated.profiles.osx": { + "devboxCompatibleShell": { + "path": "/bin/zsh", + "args": [] + } + }, + "terminal.integrated.defaultProfile.osx": "devboxCompatibleShell" +} diff --git a/devbox.json b/devbox.json index 2f871bbe..63142708 100644 --- a/devbox.json +++ b/devbox.json @@ -1,5 +1,5 @@ { - "packages": ["nodejs@latest", "nodePackages.pnpm@latest"], + "packages": ["nodejs@latest", "nodePackages_latest.pnpm@latest"], "shell": { "init_hook": ["sh ./.config/devbox/init.sh"], "scripts": { diff --git a/devbox.lock b/devbox.lock index 999898c6..dac79a74 100644 --- a/devbox.lock +++ b/devbox.lock @@ -1,11 +1,11 @@ { "lockfile_version": "1", "packages": { - "nodePackages.pnpm@latest": { - "last_modified": "2023-07-23T03:35:12Z", - "resolved": "github:NixOS/nixpkgs/af8cd5ded7735ca1df1a1174864daab75feeb64a#nodePackages.pnpm", + "nodePackages_latest.pnpm@latest": { + "last_modified": "2023-08-08T03:07:33Z", + "resolved": "github:NixOS/nixpkgs/844ffa82bbe2a2779c86ab3a72ff1b4176cec467#nodePackages_latest.pnpm", "source": "devbox-search", - "version": "8.6.9" + "version": "8.6.11" }, "nodejs@latest": { "last_modified": "2023-07-23T03:35:12Z", diff --git a/package.json b/package.json index f93421cb..06de0d4b 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Start your next web application with Webstone Plugins and configure it as you go.", "private": true, "engines": { - "node": ">=v20.5.1" + "node": ">=v20" }, "scripts": { "build": "pnpm --recursive --parallel build", diff --git a/packages/cli/package.json b/packages/cli/package.json index e9df3505..ca84d953 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -4,7 +4,7 @@ "description": "The Webstone command line interface", "types": "build/types/types.d.ts", "engines": { - "node": ">=v20.5.1" + "node": ">=v20" }, "bin": { "webstone": "./bin", diff --git a/packages/create-webstone-app/bin.js b/packages/create-webstone-app/bin.js old mode 100644 new mode 100755 index f26742ed..e74bbd67 --- a/packages/create-webstone-app/bin.js +++ b/packages/create-webstone-app/bin.js @@ -1,2 +1,2 @@ #!/usr/bin/env node -import("./dist/index.js"); +import("./dist/bin.js"); diff --git a/packages/create-webstone-app/package.json b/packages/create-webstone-app/package.json index 033b308f..b6c0e515 100644 --- a/packages/create-webstone-app/package.json +++ b/packages/create-webstone-app/package.json @@ -2,43 +2,43 @@ "name": "create-webstone-app", "version": "0.7.0", "description": "Start your next web application with Webstone and configure it as you go.", + "keywords": [ + "svelte", + "sveltekit", + "boilerplate", + "starterkit", + "web app", + "graphql" + ], + "license": "MIT", "author": "Mike Nikles, @mikenikles", "type": "module", + "exports": { + ".": "./dist/index.js" + }, + "types": "./dist/index.d.ts", "bin": "./bin.js", "scripts": { "build": "node ./scripts/build.js build", "clean": "rm -fr ./dist", "dev": "node ./scripts/build.js dev", - "prepublishOnly": "pnpm build", "prepare": "pnpm build", - "test": "pnpm test:unit", + "prepublishOnly": "pnpm build", + "test": "node --loader tsx --test src/*.spec.ts", "test:unit": "c8 --all --include=src --reporter=html pnpm test:unit:only", "test:unit:only": "NODE_OPTIONS='--loader tsx' uvu tests" }, - "keywords": [ - "svelte", - "sveltekit", - "boilerplate", - "starterkit", - "web app", - "graphql" - ], - "license": "MIT", - "devDependencies": { - "@types/command-line-args": "^5.2.0", - "@types/node": "20.4.10", - "esbuild": "^0.19.1", - "esbuild-node-externals": "^1.8.0", - "typescript": "^5.1.6" - }, "dependencies": { "chalk": "5.3.0", - "command-line-args": "^5.2.1", "create-svelte": "^5.0.5", "enquirer": "2.4.1", - "execa": "7.2.0", "fs-extra": "11.1.1", - "json5": "^2.2.3", - "listr2": "6.6.1" + "ts-deepmerge": "^6.2.0" + }, + "devDependencies": { + "@types/node": "20.4.10", + "tsup": "^6.7.0", + "type-fest": "^4.2.0", + "typescript": "^5.1.6" } } diff --git a/packages/create-webstone-app/scripts/build.js b/packages/create-webstone-app/scripts/build.js index b1e0277b..75237f7b 100644 --- a/packages/create-webstone-app/scripts/build.js +++ b/packages/create-webstone-app/scripts/build.js @@ -1,40 +1,25 @@ -import esbuild from "esbuild"; -import { nodeExternalsPlugin } from "esbuild-node-externals"; - -/** - * @type {Object.} - */ -const config = { - format: "esm", - target: "esnext", - plugins: [nodeExternalsPlugin()], - banner: { - js: "#!/usr/bin/env node", - }, - bundle: true, - entryPoints: ["./src/index.ts"], - logLevel: "info", - minify: true, - outfile: "./dist/index.js", - platform: "node", -}; +import { defineConfig, build } from "tsup"; /** * @type {"build" | "dev"} */ + const mode = process.argv[2]; -if (!mode) { - console.error("Usage: node ./scripts/esbuild.js build|dev"); + +// check if mode is valid +if (!["build", "dev"].includes(mode)) { + console.log("Usage: node ./scripts/build.js build|dev"); process.exit(1); } -switch (mode) { - case "build": - await esbuild.build(config).catch(() => process.exit(1)); - break; - case "dev": { - const context = await esbuild.context(config).catch(() => process.exit(1)); - await context.watch(); - break; - } -} +const config = defineConfig({ + entry: ["src/index.ts", "src/bin.ts"], + target: "esnext", + format: "esm", + treeshake: true, + minify: true, + dts: true, + watch: mode === "dev" ? ["src"] : false, +}); + +await build(config); diff --git a/packages/create-webstone-app/src/bin.ts b/packages/create-webstone-app/src/bin.ts new file mode 100644 index 00000000..777506e2 --- /dev/null +++ b/packages/create-webstone-app/src/bin.ts @@ -0,0 +1,99 @@ +import fs from "fs-extra"; +import chalk from "chalk"; +import enquirer from "enquirer"; +import { displayNextSteps, displayWelcome } from "./helpers"; +import { createWebstone } from "./index"; +import { parseArgs } from "node:util"; + +// argparsing +const { values: argValues } = parseArgs({ + allowPositionals: true, + options: { + type: { + type: "string", + alias: "t", + }, + "extend-cli": { + type: "boolean", + }, + }, +}); + +let extendCLI = argValues["extend-cli"] || false; +let type: "app" | "plugin" | null = null; +if (argValues.type && ["app", "plugin"].includes(argValues.type)) { + type = argValues.type as "app" | "plugin"; +} + +const { version } = JSON.parse( + fs.readFileSync(new URL("../package.json", import.meta.url), "utf-8"), +); + +let cwd = + process.argv[2] && !process.argv[2].startsWith("--") ? process.argv[2] : "."; + +displayWelcome(); +console.log(chalk.bold(`create-webstone v${version}`)); + +if (cwd === ".") { + const dir: { dir: string } = await enquirer.prompt({ + type: "text", + name: "dir", + message: + "Where should we create your project? (Hit enter to use current directory)", + initial: ".", + }); + + cwd = dir.dir; +} + +if (fs.existsSync(cwd)) { + if (fs.readdirSync(cwd).length > 0) { + const forceCreate: { forceCreate: boolean } = await enquirer.prompt({ + type: "confirm", + name: "forceCreate", + message: `The ./${cwd} directory is not empty. Do you want to continue?`, + initial: false, + }); + + if (!forceCreate.forceCreate) { + console.log( + chalk.red( + `Exiting, please empty the ./${cwd} directory or choose a different one to create the Webstone app.`, + ), + ); + process.exit(1); + } + } +} + +if (!type) { + const promptType: { type: "Webstone App" | "Webstone Plugin" } = + await enquirer.prompt({ + type: "select", + name: "type", + message: "What type of Webstone project do you want to create?", + choices: ["Webstone App", "Webstone Plugin"], + }); + + const typeMap = { + "Webstone App": "app", + "Webstone Plugin": "plugin", + } as const; + + type = typeMap[promptType.type]; +} + +if (type === "plugin" && !extendCLI) { + const extendCLIAnswer: { extendCLI: boolean } = await enquirer.prompt({ + type: "confirm", + name: "extendCLI", + message: "Does your plugin extend the Webstone CLI?", + initial: false, + }); + extendCLI = extendCLIAnswer.extendCLI; +} + +await createWebstone(cwd, { type, extendCLI }); + +displayNextSteps(cwd); diff --git a/packages/create-webstone-app/src/functions.spec.ts b/packages/create-webstone-app/src/functions.spec.ts new file mode 100644 index 00000000..4cab13ef --- /dev/null +++ b/packages/create-webstone-app/src/functions.spec.ts @@ -0,0 +1,288 @@ +import { it, describe } from "node:test"; +import { deepEqual, deepStrictEqual, strictEqual } from "node:assert"; +import path from "node:path"; +import { + sortKeys, + toValidPackageName, + getAppName, + getRawAppName, + updatePackageJSON, + copyBuildScript, + copyCLIExtension, +} from "./functions"; +import { WebstoneAppType } from "../types"; +import fs from "fs-extra"; + +describe("sortKeys", () => { + it("should sort keys of an object in ascending order", () => { + const input = { c: 3, a: 1, b: 2 }; + const expectedOutput = { a: 1, b: 2, c: 3 }; + const result = sortKeys(input); + deepStrictEqual(result, expectedOutput); + }); + + it("should handle an empty object", () => { + const input = {}; + const expectedOutput = {}; + const result = sortKeys(input); + deepStrictEqual(result, expectedOutput); + }); + + it("should handle an object with a single key", () => { + const input = { z: 26 }; + const expectedOutput = { z: 26 }; + const result = sortKeys(input); + deepStrictEqual(result, expectedOutput); + }); + + it("should handle an object with string and number keys", () => { + const input = { b: 2, a: 1, 2: "value", 1: "value" }; + const expectedOutput = { "1": "value", "2": "value", a: 1, b: 2 }; + const result = sortKeys(input); + deepStrictEqual(result, expectedOutput); + }); + + it("should handle an object with nested objects", () => { + const input = { b: { c: 3, a: 1 }, a: 2 }; + const expectedOutput = { a: 2, b: { a: 1, c: 3 } }; + const result = sortKeys(input); + deepStrictEqual(result, expectedOutput); + }); +}); + +describe("toValidPackageName", () => { + it("should convert a valid name to a valid package name", () => { + const input = " My Package Name "; + const expectedOutput = "my-package-name"; + const result = toValidPackageName(input); + deepStrictEqual(result, expectedOutput); + }); + + it("should handle a name with leading periods and underscores", () => { + const input = ".__my_package_name"; + const expectedOutput = "-my-package-name"; + const result = toValidPackageName(input); + deepStrictEqual(result, expectedOutput); + }); + + it("should handle a name with non-alphanumeric characters", () => { + const input = "!@#$My_Package%^Name*"; + const expectedOutput = "-my-package-name-"; + const result = toValidPackageName(input); + deepStrictEqual(result, expectedOutput); + }); + + it("should handle an already valid package name", () => { + const input = "already-valid-package-name"; + const expectedOutput = "already-valid-package-name"; + const result = toValidPackageName(input); + deepStrictEqual(result, expectedOutput); + }); + + it("should handle an empty name", () => { + const input = ""; + const expectedOutput = ""; + const result = toValidPackageName(input); + deepStrictEqual(result, expectedOutput); + }); +}); + +describe("getAppName", () => { + it("should generate a valid app name for app type", () => { + const cwd = "dummy"; + const type: WebstoneAppType = "app"; + const expectedOutput = "dummy"; + const result = getAppName(cwd, type); + deepStrictEqual(result, expectedOutput); + }); + + it("should generate a valid app name for plugin type", () => { + const cwd = "dummy"; + const type: WebstoneAppType = "plugin"; + const expectedOutput = "webstone-plugin-dummy"; + const result = getAppName(cwd, type); + deepStrictEqual(result, expectedOutput); + }); + + it("should handle leading periods and underscores in app name", () => { + const cwd = "__my_app"; + const type: WebstoneAppType = "app"; + const expectedOutput = "-my-app"; + const result = getAppName(cwd, type); + deepStrictEqual(result, expectedOutput); + }); + + it("should handle plugin type and special characters", () => { + const cwd = "/dummy"; + const type = "plugin"; + const expectedOutput = "webstone-plugin--dummy"; + const result = getAppName(cwd, type); + deepStrictEqual(result, expectedOutput); + }); +}); + +describe("getRawAppName", () => { + it('should return the current dir when cwd is "."', (ctx) => { + const cwdMock = ctx.mock.fn(process.cwd, () => "dummy-dir"); + ctx.mock.method(process, "cwd", cwdMock); + const cwd = "."; + const expectedOutput = "dummy-dir"; + const result = getRawAppName(cwd); + deepStrictEqual(result, expectedOutput); + }); + + it("should handle a single-character cwd", () => { + const cwd = "/a"; + const expectedOutput = "/a"; + const result = getRawAppName(cwd); + deepStrictEqual(result, expectedOutput); + }); +}); + +describe("updatePackageJson", () => { + it("should update the package.json properly for type app", (ctx) => { + const mockReadJsonSync = ctx.mock.fn(fs.readJSONSync, () => { + return {}; + }); + const mockWriteJsonSync = ctx.mock.fn(fs.writeJsonSync, () => {}); + const mockPathResolve = ctx.mock.fn(path.resolve, (cwd: string) => cwd); + ctx.mock.method(fs, "readJSONSync", mockReadJsonSync); + ctx.mock.method(fs, "writeJsonSync", mockWriteJsonSync); + ctx.mock.method(path, "resolve", mockPathResolve); + const cwd = "dummy"; + updatePackageJSON(cwd, { extendCLI: false, type: "app" }); + strictEqual(mockReadJsonSync.mock.callCount(), 1); + strictEqual(mockWriteJsonSync.mock.callCount(), 1); + deepStrictEqual(mockWriteJsonSync.mock.calls[0].arguments, [ + "dummy/package.json", + { + devDependencies: { + "@webstone/cli": "^0.12.0", + }, + }, + { + encoding: "utf-8", + spaces: "\t", + }, + ]); + }); + + it("should update the package.json properly for type plugin that does extend the cli", (ctx) => { + const mockReadJsonSync = ctx.mock.fn(fs.readJSONSync, () => { + return {}; + }); + const mockWriteJsonSync = ctx.mock.fn(fs.writeJsonSync, () => {}); + const mockPathResolve = ctx.mock.fn(path.resolve, (cwd: string) => cwd); + ctx.mock.method(fs, "readJSONSync", mockReadJsonSync); + ctx.mock.method(fs, "writeJsonSync", mockWriteJsonSync); + ctx.mock.method(path, "resolve", mockPathResolve); + const cwd = "dummy"; + updatePackageJSON(cwd, { extendCLI: false, type: "plugin" }); + strictEqual(mockReadJsonSync.mock.callCount(), 1); + strictEqual(mockWriteJsonSync.mock.callCount(), 1); + deepStrictEqual(mockWriteJsonSync.mock.calls[0].arguments, [ + "dummy/package.json", + {}, + { + encoding: "utf-8", + spaces: "\t", + }, + ]); + }); + + it("should update the package.json properly for type plugin that doesn't extend the cli", (ctx) => { + const mockReadJsonSync = ctx.mock.fn(fs.readJSONSync, () => { + return {}; + }); + const mockWriteJsonSync = ctx.mock.fn(fs.writeJsonSync, () => {}); + const mockPathResolve = ctx.mock.fn(path.resolve, (cwd: string) => cwd); + ctx.mock.method(fs, "readJSONSync", mockReadJsonSync); + ctx.mock.method(fs, "writeJsonSync", mockWriteJsonSync); + ctx.mock.method(path, "resolve", mockPathResolve); + const cwd = "dummy"; + updatePackageJSON(cwd, { extendCLI: true, type: "plugin" }); + strictEqual(mockReadJsonSync.mock.callCount(), 1); + strictEqual(mockWriteJsonSync.mock.callCount(), 1); + deepStrictEqual(mockWriteJsonSync.mock.calls[0].arguments, [ + "dummy/package.json", + { + scripts: { + build: + "npm run clean:build && npm run cli:build && npm run web:build", + "clean:build": "rimraf ./dist", + "cli:build": + "node scripts/build-cli.js build && npm run templates:copy", + "cli:dev": "node scripts/build-cli.js dev", + dev: "npm run clean:build && npm-run-all --parallel cli:dev web:dev templates:dev", + package: "svelte-kit sync && svelte-package -o ./dist/web && publint", + "templates:copy": "cp -a ./src/cli/templates ./dist/cli", + "templates:dev": + "nodemon --watch src/cli/templates --ext '.ejs' --exec 'npm run templates:copy'", + "web:build": "vite build && npm run package", + "web:dev": "vite dev", + }, + devDependencies: { + "@webstone/gluegun": "0.0.5", + "fs-jetpack": "^5.1.0", + nodemon: "^3.0.1", + "npm-run-all": "^4.1.5", + rimraf: "^3.0.2", + tsup: "^6.7.0", + }, + svelte: "./dist/web/index.js", + types: "./dist/web/index.d.ts", + exports: { + ".": { + types: "./dist/web/index.d.ts", + svelte: "./dist/web/index.js", + }, + }, + }, + { + encoding: "utf-8", + spaces: "\t", + }, + ]); + }); +}); + +describe("copyBuildScript", () => { + it("should copy the build script properly", (ctx) => { + const mockCopySync = ctx.mock.fn(fs.copySync, () => {}); + ctx.mock.method(fs, "copySync", mockCopySync); + copyBuildScript("dummy"); + strictEqual(mockCopySync.mock.callCount(), 1); + deepEqual( + // TODO find a solution for import.meta.url + mockCopySync.mock.calls[0].arguments[1], + "dummy/scripts/build-cli.js", + ); + }); +}); + +describe("copyCLIExtension", () => { + it("should copy the CLI extension properly", (ctx) => { + const mockCopySync = ctx.mock.fn(fs.copySync, () => {}); + ctx.mock.method(fs, "copySync", mockCopySync); + copyCLIExtension("dummy"); + strictEqual(mockCopySync.mock.callCount(), 3); + + //Commands + deepStrictEqual( + mockCopySync.mock.calls[0].arguments[1], + "dummy/src/cli/commands/dummy/hello-world.ts", + ); + + // Extensions + deepStrictEqual( + mockCopySync.mock.calls[1].arguments[1], + "dummy/src/cli/extensions/hello-world.ts", + ); + + // Templates + deepStrictEqual( + mockCopySync.mock.calls[2].arguments[1], + "dummy/src/cli/templates/template.ejs", + ); + }); +}); diff --git a/packages/create-webstone-app/src/functions.ts b/packages/create-webstone-app/src/functions.ts new file mode 100644 index 00000000..8371c666 --- /dev/null +++ b/packages/create-webstone-app/src/functions.ts @@ -0,0 +1,141 @@ +import fs from "fs-extra"; +import path from "node:path"; +import { PackageJson } from "type-fest"; +import { appPackageJson, pluginPackageJson } from "./package"; +import merge from "ts-deepmerge"; +import { create } from "create-svelte"; +import { WebstoneAppType } from "../types"; + +export function getRawAppName(cwd: string) { + let appName: string = cwd; + if (cwd === ".") { + appName = process.cwd().split("/").pop() || "webstone-project"; + } + return appName; +} + +export function getAppName(cwd: string, type: WebstoneAppType) { + let appName = getRawAppName(cwd); + if (type === "plugin") { + appName = `webstone-plugin-${appName}`; + return toValidPackageName(appName); + } + return toValidPackageName(appName); +} + +export function toValidPackageName(name: string) { + return name + .trim() + .toLowerCase() + .replace(/\s+/g, "-") + .replace(/^[._]/, "") + .replace(/[^a-z0-9~.-]+/g, "-"); +} + +export function createBaseApp( + cwd: string, + options: { type: WebstoneAppType; appName: string }, +) { + const { appName, type } = options; + create(cwd, { + name: appName, + template: type === "app" ? "skeleton" : "skeletonlib", + types: "typescript", + eslint: true, + prettier: true, + playwright: true, + vitest: true, + }); +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function sortKeys(obj: any) { + if (typeof obj !== "object" || obj === null) + throw new Error("Invalid object"); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const sortedObj: Record = {}; + Object.keys(obj) + .sort() + .forEach((key) => { + sortedObj[key] = obj[key]; + }); + return sortedObj; +} + +export function updatePackageJSON( + cwd: string, + options: { type: WebstoneAppType; extendCLI: boolean }, +) { + const { type, extendCLI } = options; + const pkg: PackageJson = fs.readJSONSync(path.resolve(`${cwd}/package.json`)); + let newPkg: PackageJson = pkg; + if (type === "app") { + newPkg = deepMergeWithSortedKeys(pkg, appPackageJson); + } + if (type === "plugin" && extendCLI) { + newPkg = deepMergeWithSortedKeys(pkg, pluginPackageJson); + } + + fs.writeJsonSync(path.resolve(`${cwd}/package.json`), newPkg, { + encoding: "utf-8", + spaces: "\t", + }); +} + +function deepMergeWithSortedKeys( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + target: Record, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + source: Record, + // eslint-disable-next-line @typescript-eslint/no-explicit-any +): Record { + const merged = merge(target, source); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + function recursiveSort(obj: Record): Record { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const sortedObj: Record = {}; + + Object.keys(obj).forEach((key) => { + if (["dependencies", "devDependencies", "scripts"].includes(key)) { + sortedObj[key] = sortKeys(obj[key]); + } else { + sortedObj[key] = obj[key]; + } + }); + + return sortedObj; + } + + return recursiveSort(merged); +} + +export function copyBuildScript(cwd: string) { + fs.copySync( + new URL("../templates/plugin-structure/build-cli.js", import.meta.url) + .pathname, + `${cwd}/scripts/build-cli.js`, + ); +} + +export function copyCLIExtension(cwd: string) { + // copy command + fs.copySync( + new URL("../templates/plugin-structure/command.ts", import.meta.url) + .pathname, + `${cwd}/src/cli/commands/${getRawAppName(cwd)}/hello-world.ts`, + ); + + //copy extension + fs.copySync( + new URL("../templates/plugin-structure/extension.ts", import.meta.url) + .pathname, + `${cwd}/src/cli/extensions/hello-world.ts`, + ); + + // copy templates + fs.copySync( + new URL("../templates/plugin-structure/template.ejs", import.meta.url) + .pathname, + `${cwd}/src/cli/templates/template.ejs`, + ); +} diff --git a/packages/create-webstone-app/src/helpers.ts b/packages/create-webstone-app/src/helpers.ts index 82e48319..45fa6053 100644 --- a/packages/create-webstone-app/src/helpers.ts +++ b/packages/create-webstone-app/src/helpers.ts @@ -1,51 +1,8 @@ import chalk from "chalk"; -import { ListrTaskWrapper, ListrRenderer } from "listr2/dist/index"; - -export interface Ctx { - appDir: string; - type: "application" | "plugin"; -} - -type PackageManagers = "npm" | "pnpm" | "yarn"; -export type WebstoneTask = ListrTaskWrapper; - -/** - * If you modify this function, also change it in - * webstone/packages/cli/src/determine-package-manager.ts - */ -export const determinePackageManager = (): PackageManagers => { - if (process.env.npm_execpath?.endsWith("npm-cli.js")) { - return "npm"; - } else if (process.env.npm_execpath?.endsWith("pnpm.cjs")) { - return "pnpm"; - } else if (process.env.npm_execpath?.endsWith("yarn.js")) { - return "yarn"; - } else { - console.warn( - `Could not determine package manager based on "process.env.npm_execpath". Value for env variable: ${process.env.npm_execpath}. Using npm as a fallback. Please report this as a bug, we'd love to make it more resilient.`, - ); - return "npm"; - } -}; - -export const getAppName = (appDir: string, isPlugin = false) => { - if (appDir === ".") { - const appName = process.cwd().split("/").pop(); - if (appName) { - return appName.startsWith("plugin-") - ? appName.substring("plugin-".length) - : appName; - } - return isPlugin ? "webstone-plugin" : "webstone-app"; - } - return appDir; -}; - -export const displayWelcome = () => - new Promise((resolve) => { - // https://textfancy.com/ascii-art/ - console.log(` +export const displayWelcome = () => { + // https://textfancy.com/ascii-art/ + console.log(` ▄ ▄ ▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄ ▄ ▄▄▄▄▄▄▄ █ █ ▄ █ █ █ ▄ █ █ █ █ █ █ █ █ █ ██ ██ █ ▄▄▄█ █▄█ █ ▄▄▄▄▄█▄ ▄█ ▄ █ █▄█ █ ▄▄▄█ @@ -55,16 +12,9 @@ export const displayWelcome = () => █▄▄█ █▄▄█▄▄▄▄▄▄▄█▄▄▄▄▄▄▄█▄▄▄▄▄▄▄█ █▄▄▄█ █▄▄▄▄▄▄▄█▄█ █▄▄█▄▄▄▄▄▄▄█ `); - resolve(); - }); - -export const displayNextSteps = async (ctx: Ctx) => { - const wsDevCommandPerPackageManager = { - npm: "npx ws dev", - pnpm: "pnpm ws dev", - yarn: "yarn ws dev", - }; +}; +export const displayNextSteps = async (cwd: string) => { console.log(` =================================================== Congratulations 🎉! Your Webstone project is ready. @@ -73,12 +23,11 @@ To contribute: https://github.com/WebstoneHQ/webstone To chat & get in touch: https://discord.gg/NJRm6eRs -Thank you for your interest in Webstone, I'd love to hear your feedback 🙏. +Thank you for your interest in Webstone, We'd love to hear your feedback 🙏. + +Next steps: -Next steps: - - ${chalk.bold(chalk.cyan(`cd ${ctx.appDir.split("/").pop()}`))} - - ${chalk.bold( - chalk.cyan(wsDevCommandPerPackageManager[determinePackageManager()]), - )} + - ${chalk.bold(chalk.cyan(`cd ${cwd.split("/").pop()}`))} + - ${chalk.bold.cyan("npm install")} (or pnpm install, etc...) `); }; diff --git a/packages/create-webstone-app/src/index.ts b/packages/create-webstone-app/src/index.ts index 6f03dab8..4cac4356 100644 --- a/packages/create-webstone-app/src/index.ts +++ b/packages/create-webstone-app/src/index.ts @@ -1,6 +1,22 @@ -import { displayWelcome, displayNextSteps } from "./helpers"; -import { tasks } from "./tasks/index"; +import { CreateWebstoneOptions } from "../types"; +import { + copyBuildScript, + copyCLIExtension, + createBaseApp, + getAppName, + updatePackageJSON, +} from "./functions"; -displayWelcome(); -const context = await tasks.run(); -displayNextSteps(context); +export async function createWebstone( + cwd: string, + options: CreateWebstoneOptions, +) { + const { type, extendCLI } = options; + const appName = getAppName(cwd, type); + createBaseApp(cwd, { type, appName }); + updatePackageJSON(cwd, { type, extendCLI }); + if (type === "plugin" && extendCLI) { + copyBuildScript(cwd); + copyCLIExtension(cwd); + } +} diff --git a/packages/create-webstone-app/src/package.ts b/packages/create-webstone-app/src/package.ts new file mode 100644 index 00000000..d11842ac --- /dev/null +++ b/packages/create-webstone-app/src/package.ts @@ -0,0 +1,39 @@ +import { PackageJson } from "type-fest"; + +export const appPackageJson: PackageJson = { + devDependencies: { + "@webstone/cli": "^0.12.0", + }, +}; + +export const pluginPackageJson: PackageJson = { + scripts: { + build: "npm run clean:build && npm run cli:build && npm run web:build", + "clean:build": "rimraf ./dist", + "cli:build": "node scripts/build-cli.js build && npm run templates:copy", + "cli:dev": "node scripts/build-cli.js dev", + dev: "npm run clean:build && npm-run-all --parallel cli:dev web:dev templates:dev", + package: "svelte-kit sync && svelte-package -o ./dist/web && publint", + "templates:copy": "cp -a ./src/cli/templates ./dist/cli", + "templates:dev": + "nodemon --watch src/cli/templates --ext '.ejs' --exec 'npm run templates:copy'", + "web:build": "vite build && npm run package", + "web:dev": "vite dev", + }, + devDependencies: { + "@webstone/gluegun": "0.0.5", + "fs-jetpack": "^5.1.0", + nodemon: "^3.0.1", + "npm-run-all": "^4.1.5", + rimraf: "^3.0.2", + tsup: "^6.7.0", + }, + svelte: "./dist/web/index.js", + types: "./dist/web/index.d.ts", + exports: { + ".": { + types: "./dist/web/index.d.ts", + svelte: "./dist/web/index.js", + }, + }, +}; diff --git a/packages/create-webstone-app/src/tasks/0-determine-context/index.ts b/packages/create-webstone-app/src/tasks/0-determine-context/index.ts deleted file mode 100644 index 1fb54587..00000000 --- a/packages/create-webstone-app/src/tasks/0-determine-context/index.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { ListrTask } from "listr2/dist/index"; -import CommandLineArgs from "command-line-args"; -import { execa } from "execa"; - -import { Ctx, WebstoneTask } from "../../helpers"; - -const optionDefinitons: CommandLineArgs.OptionDefinition[] = [ - { - name: "type", - alias: "t", - type: String, - }, -]; - -const determineAppDirName = async (ctx: Ctx, task: WebstoneTask) => { - let appName = ""; - if (process.argv[2] && process.argv[2].startsWith("--")) { - appName = "."; - } - if (!appName) { - appName = process.argv[2]; - console.warn("No app name provided, using current directory"); - } - ctx.appDir = appName ? appName.toLowerCase().replace(/\s/g, "-") : "."; - - task.output = `App directory name: ${ctx.appDir}`; - task.output = ctx.appDir; - return; -}; - -const checkPnpm = async () => { - const pnpmVersion = await execa("pnpm", ["-v"]); - if (pnpmVersion.failed) { - throw new Error( - "pnpm is not installed, please install it first (npm i -g pnpm)", - ); - } -}; - -const getMetadata = async (ctx: Ctx, task: WebstoneTask) => { - let type: "application" | "plugin"; - const optionDefinitions = CommandLineArgs(optionDefinitons, { - partial: true, - }); - - if ( - optionDefinitions.type === "application" || - optionDefinitions.type === "plugin" - ) { - type = optionDefinitions.type; - } else { - type = await task.prompt({ - type: "Select", - message: "What's the type of the project", - choices: ["application", "plugin"], - }); - } - - ctx.type = type; - return { type }; -}; - -const contextTasks: ListrTask[] = [ - { - task: determineAppDirName, - title: "Determining app directory name", - }, - { - task: getMetadata, - title: "Detecting project type", - }, - { - task: checkPnpm, - title: "Checking for pnpm", - enabled: (ctx: Ctx) => ctx.type === "plugin", - }, -]; - -export const tasks: ListrTask[] = [ - { - title: "Determining application context", - task(_, task) { - return task.newListr(contextTasks); - }, - }, -]; diff --git a/packages/create-webstone-app/src/tasks/1-create-directory/index.ts b/packages/create-webstone-app/src/tasks/1-create-directory/index.ts deleted file mode 100644 index 44ee9280..00000000 --- a/packages/create-webstone-app/src/tasks/1-create-directory/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -import fs from "fs-extra"; -import { ListrTask } from "listr2/dist/index"; - -import { Ctx, WebstoneTask } from "../../helpers"; - -export const createAppDir = async (ctx: Ctx, task: WebstoneTask) => { - const appDir = ctx.appDir; - - if (fs.existsSync(appDir)) { - if (fs.readdirSync(appDir).length > 0) { - const response = await task.prompt({ - type: "confirm", - message: `The ./${appDir} directory is not empty. Do you want to continue?`, - initial: false, - }); - - if (!response) { - throw new Error( - `Exiting, please empty the ./${appDir} directory or choose a different one to create the Webstone app.`, - ); - } - } - } - task.output = appDir; - fs.mkdirSync(appDir, { recursive: true }); - return appDir; -}; - -export const tasks: ListrTask[] = [ - { - task: createAppDir, - title: "Creating the directory", - }, -]; diff --git a/packages/create-webstone-app/src/tasks/2-setup-project/application.ts b/packages/create-webstone-app/src/tasks/2-setup-project/application.ts deleted file mode 100644 index 87eeb229..00000000 --- a/packages/create-webstone-app/src/tasks/2-setup-project/application.ts +++ /dev/null @@ -1,25 +0,0 @@ -//@ts-ignore this package doesn't provide a declaration file -import { create } from "create-svelte"; -import { Ctx, getAppName } from "../../helpers"; - -export const initWebApp = async (ctx: Ctx) => { - try { - await createApplication(ctx.appDir); - return; - } catch (error) { - console.error(error); - process.exit(1); - } -}; - -const createApplication = async (appDir: string) => { - return await create(appDir, { - name: getAppName(appDir), - template: "skeleton", - types: "typescript", - prettier: true, - eslint: true, - playwright: true, - vitest: false, - }); -}; diff --git a/packages/create-webstone-app/src/tasks/2-setup-project/index.ts b/packages/create-webstone-app/src/tasks/2-setup-project/index.ts deleted file mode 100644 index 7ad60825..00000000 --- a/packages/create-webstone-app/src/tasks/2-setup-project/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ListrTask } from "listr2"; -import { Ctx } from "../../helpers"; -import { initWebApp } from "./application"; -import { configurePlugin } from "./plugin"; - -export const setupTasks: ListrTask[] = [ - { - enabled(ctx: Ctx) { - return ctx.type === "application"; - }, - task: initWebApp, - title: "Initializing new Webstone application", - }, - { - enabled(ctx: Ctx) { - return ctx.type === "plugin"; - }, - task(_, task) { - return task.newListr(configurePlugin); - }, - title: "Initializing new Webstone plugin", - }, -]; diff --git a/packages/create-webstone-app/src/tasks/2-setup-project/plugin.ts b/packages/create-webstone-app/src/tasks/2-setup-project/plugin.ts deleted file mode 100644 index 97218d39..00000000 --- a/packages/create-webstone-app/src/tasks/2-setup-project/plugin.ts +++ /dev/null @@ -1,148 +0,0 @@ -//@ts-ignore this package doesn't provide a declaration file -import { create } from "create-svelte"; -import { Ctx, getAppName } from "../../helpers"; -import path, { dirname } from "path"; -import fs from "fs-extra"; -import { fileURLToPath } from "url"; -import { ListrTask } from "listr2"; - -const __dirname = dirname(fileURLToPath(import.meta.url)); - -export const copyTemplate = (ctx: Ctx) => { - const appDir = ctx.appDir; - fs.copySync( - path.join(__dirname, "..", "templates", "plugin", "structure"), - appDir, - ); -}; - -export const renameCliPackage = (ctx: Ctx) => { - const cliPackageJson = fs.readJSONSync( - path.join(ctx.appDir, "packages", "cli", "package.json"), - ); - cliPackageJson.name = `webstone-plugin-${getAppName(ctx.appDir)}-cli`; - fs.writeJSONSync( - path.join(ctx.appDir, "packages", "cli", "package.json"), - cliPackageJson, - { - spaces: "\t", - }, - ); -}; - -export const renameMainPackage = (ctx: Ctx) => { - const packageJson = fs.readJSONSync(path.join(ctx.appDir, "package.json")); - packageJson.name = `webstone-plugin-${getAppName(ctx.appDir)}`; - fs.writeJSONSync(path.join(ctx.appDir, "package.json"), packageJson, { - spaces: "\t", - }); -}; - -export const renamePackages = async (ctx: Ctx) => { - renameCliPackage(ctx); - renameMainPackage(ctx); -}; - -export const createCliNamespace = (ctx: Ctx) => { - fs.renameSync( - path.join(ctx.appDir, "packages", "cli", "src", "commands", "placeholder"), - path.join( - ctx.appDir, - "packages", - "cli", - "src", - "commands", - getAppName(ctx.appDir), - ), - ); - fs.renameSync( - path.join( - ctx.appDir, - "packages", - "cli", - "src", - "extensions", - "placeholder", - ), - path.join( - ctx.appDir, - "packages", - "cli", - "src", - "extensions", - getAppName(ctx.appDir), - ), - ); -}; - -const setWebPackagePrivateTrue = (ctx: Ctx) => { - const packageJson = fs.readJSONSync( - path.join(ctx.appDir, "packages", "web", "package.json"), - ); - packageJson.private = true; - fs.writeJSONSync( - path.join(ctx.appDir, "packages", "web", "package.json"), - packageJson, - { - spaces: "\t", - }, - ); -}; - -const createSveltekitPackage = async (ctx: Ctx) => { - fs.removeSync(path.join(ctx.appDir, "packages", "web", ".gitkeep")); - await create(path.join(ctx.appDir, "packages", "web"), { - name: `webstone-plugin-${getAppName(ctx.appDir)}-web`, - template: "skeletonlib", - types: "typescript", - prettier: true, - eslint: true, - playwright: true, - vitest: false, - }); -}; - -const copyWebPackageReadme = async (ctx: Ctx) => { - // NOTE: This has to happen after `createSveltekitPackage`, otherwise the README.md - // gets replaced by the default SvelteKit README.md. - fs.copySync( - path.join( - __dirname, - "..", - "templates", - "plugin", - "structure", - "packages", - "web", - "README.md", - ), - path.join(ctx.appDir, "packages", "web", "README.md"), - ); -}; - -export const configurePlugin: ListrTask[] = [ - { - task: copyTemplate, - title: "Setting up Plugin Structure", - }, - { - task: renamePackages, - title: "Setting package names", - }, - { - task: createCliNamespace, - title: "Creating CLI Namespace", - }, - { - task: createSveltekitPackage, - title: "Creating SvelteKit Package", - }, - { - task: copyWebPackageReadme, - title: "Copying the web package readme file", - }, - { - task: setWebPackagePrivateTrue, - title: "Set web package to private:true", - }, -]; diff --git a/packages/create-webstone-app/src/tasks/3-configure-app/application.ts b/packages/create-webstone-app/src/tasks/3-configure-app/application.ts deleted file mode 100644 index a1281f9f..00000000 --- a/packages/create-webstone-app/src/tasks/3-configure-app/application.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { execa } from "execa"; -import fs from "fs-extra"; -import { ListrTask } from "listr2"; -import path, { dirname } from "path"; -import { fileURLToPath } from "url"; -import { Ctx, determinePackageManager } from "../../helpers"; - -const __dirname = dirname(fileURLToPath(import.meta.url)); - -export const installCLI = async (ctx: Ctx) => { - const installProcess = execa( - determinePackageManager(), - ["add", "-D", "@webstone/cli"], - { - shell: true, - cwd: ctx.appDir, - }, - ); - - return installProcess.stdout; -}; - -export const copyReadme = async (ctx: Ctx) => { - const templateDir = path.join( - __dirname, - "..", - "templates", - "application", - "README.md", - ); - fs.copySync(templateDir, `${ctx.appDir}/README.md`); -}; - -export const configureApp: ListrTask[] = [ - { - task: copyReadme, - title: "Configuring Readme", - }, - { - task: installCLI, - title: "Install dependencies", - }, -]; diff --git a/packages/create-webstone-app/src/tasks/3-configure-app/index.ts b/packages/create-webstone-app/src/tasks/3-configure-app/index.ts deleted file mode 100644 index b2833124..00000000 --- a/packages/create-webstone-app/src/tasks/3-configure-app/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ListrTask } from "listr2"; -import { Ctx } from "../../helpers"; -import { configureApp } from "./application"; -import { configurePlugin } from "./plugin"; - -export const configureTasks: ListrTask[] = [ - { - enabled(ctx: Ctx) { - return ctx.type === "application"; - }, - task(_, task) { - return task.newListr(configureApp); - }, - title: "Configuring your Webstone application", - }, - { - enabled(ctx: Ctx) { - return ctx.type === "plugin"; - }, - task(_, task) { - return task.newListr(configurePlugin); - }, - title: "Configuring your Webstone plugin", - }, -]; diff --git a/packages/create-webstone-app/src/tasks/3-configure-app/plugin.ts b/packages/create-webstone-app/src/tasks/3-configure-app/plugin.ts deleted file mode 100644 index 96cf84bf..00000000 --- a/packages/create-webstone-app/src/tasks/3-configure-app/plugin.ts +++ /dev/null @@ -1,65 +0,0 @@ -import fs from "fs-extra"; -import { execa } from "execa"; -import path from "path"; -import { ListrTask } from "listr2"; -import { Ctx, getAppName } from "../../helpers"; - -export const installDeps = async (ctx: Ctx) => { - const installProcess = execa("pnpm", ["install"], { - shell: true, - cwd: ctx.appDir, - }); - - return installProcess.stdout; -}; - -const installWebDevDependencies = async (ctx: Ctx) => { - const installCliPluginProcess = execa( - "pnpm", - [ - "add", - "-D", - `webstone-plugin-${getAppName(ctx.appDir)}-cli`, - "@webstone/cli", - ], - { - shell: true, - cwd: path.join(ctx.appDir, "packages", "web"), - }, - ); - - return installCliPluginProcess.stdout; -}; - -const configureWebPrepublishOnlyScript = async (ctx: Ctx) => { - const prepublishOnlyCommands = [ - `pnpm remove webstone-plugin-${getAppName(ctx.appDir)}-cli @webstone/cli`, - "pnpm package", - ]; - const packageJson = fs.readJSONSync( - path.join(ctx.appDir, "packages", "web", "package.json"), - ); - packageJson.scripts.prepublishOnly = prepublishOnlyCommands.join(" && "); - fs.writeJSONSync( - path.join(ctx.appDir, "packages", "web", "package.json"), - packageJson, - { - spaces: "\t", - }, - ); -}; - -export const configurePlugin: ListrTask[] = [ - { - task: installDeps, - title: "Installing dependencies", - }, - { - task: installWebDevDependencies, - title: "Installing `web` dev dependencies", - }, - { - task: configureWebPrepublishOnlyScript, - title: "Configuring the `prepublishOnly` script for the web directory", - }, -]; diff --git a/packages/create-webstone-app/src/tasks/index.ts b/packages/create-webstone-app/src/tasks/index.ts deleted file mode 100644 index 84dc1923..00000000 --- a/packages/create-webstone-app/src/tasks/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Listr } from "listr2"; -import Enquirer from "enquirer"; - -const enquirer = new Enquirer(); - -import { Ctx } from "../helpers"; -import { tasks as metadataTasks } from "./0-determine-context"; -import { tasks as createAppDirectoryTasks } from "./1-create-directory/index"; -import { setupTasks } from "./2-setup-project/index"; -import { configureTasks } from "./3-configure-app"; - -export const tasks = new Listr( - [ - ...metadataTasks, - ...createAppDirectoryTasks, - ...setupTasks, - ...configureTasks, - ], - { - injectWrapper: { enquirer }, - rendererOptions: { - collapse: false, - }, - }, -); diff --git a/packages/create-webstone-app/templates/application/README.md b/packages/create-webstone-app/templates/application/README.md deleted file mode 100644 index 9321bc39..00000000 --- a/packages/create-webstone-app/templates/application/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Webstone - -TODO: This is the default `README` applied to all new Webstone projects. - -TODO: Document how to use it, how to add/remove modules, etc. diff --git a/packages/create-webstone-app/templates/plugin-structure/build-cli.js b/packages/create-webstone-app/templates/plugin-structure/build-cli.js new file mode 100644 index 00000000..dcebb67d --- /dev/null +++ b/packages/create-webstone-app/templates/plugin-structure/build-cli.js @@ -0,0 +1,37 @@ +import { defineConfig, build } from "tsup"; +import jetpack from "fs-jetpack"; + +/** + * @type {"build" | "dev"} + */ +const mode = process.argv[2]; + +// check if mode is valid +if (!["build", "dev"].includes(mode)) { + console.log("Usage: node ./scripts/build-cli.js build|dev"); + process.exit(1); +} + +const config = defineConfig({ + entry: ["src/cli/**/*.ts"], + outDir: "dist/cli", + splitting: true, + target: "es6", + format: "cjs", + clean: true, + treeshake: true, + tsconfig: "./tsconfig.json", + bundle: false, + minify: true, + watch: mode === "dev" ? ["src/cli"] : false, +}); + +const tsFiles = jetpack + .cwd("src/cli") + .find({ matching: "*.ts", recursive: true }); +const tsFilesCount = tsFiles.length; +if (tsFilesCount === 0) { + console.log("No files to build"); + process.exit(1); +} +await build(config); diff --git a/packages/create-webstone-app/templates/plugin-structure/command.ts b/packages/create-webstone-app/templates/plugin-structure/command.ts new file mode 100644 index 00000000..707f1c98 --- /dev/null +++ b/packages/create-webstone-app/templates/plugin-structure/command.ts @@ -0,0 +1,16 @@ +import type { GluegunCommand } from "@webstone/gluegun"; + +const command: GluegunCommand = { + name: "hello", + alias: ["h"], + description: "Hello World Command", + hidden: false, + dashed: false, + run: async (toolbox) => { + const { print } = toolbox; + + print.info(`Hello World`); + }, +}; + +export default command; diff --git a/packages/create-webstone-app/templates/plugin-structure/extension.ts b/packages/create-webstone-app/templates/plugin-structure/extension.ts new file mode 100644 index 00000000..201711ef --- /dev/null +++ b/packages/create-webstone-app/templates/plugin-structure/extension.ts @@ -0,0 +1,11 @@ +import type { GluegunToolbox } from "@webstone/gluegun"; + +const extension = (toolbox: GluegunToolbox) => { + const { print } = toolbox; + + toolbox.sayhello = () => { + print.info("Hello from an extension!"); + }; +}; + +export default extension; diff --git a/packages/create-webstone-app/templates/plugin/structure/packages/cli/src/templates/template.ejs b/packages/create-webstone-app/templates/plugin-structure/template.ejs similarity index 100% rename from packages/create-webstone-app/templates/plugin/structure/packages/cli/src/templates/template.ejs rename to packages/create-webstone-app/templates/plugin-structure/template.ejs diff --git a/packages/create-webstone-app/templates/plugin/structure/.changeset/README.md b/packages/create-webstone-app/templates/plugin/structure/.changeset/README.md deleted file mode 100644 index e5b6d8d6..00000000 --- a/packages/create-webstone-app/templates/plugin/structure/.changeset/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Changesets - -Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works -with multi-package repos, or single-package repos to help you version and publish your code. You can -find the full documentation for it [in our repository](https://github.com/changesets/changesets) - -We have a quick list of common questions to get you started engaging with this project in -[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) diff --git a/packages/create-webstone-app/templates/plugin/structure/.changeset/config.json b/packages/create-webstone-app/templates/plugin/structure/.changeset/config.json deleted file mode 100644 index 56a5582f..00000000 --- a/packages/create-webstone-app/templates/plugin/structure/.changeset/config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "https://unpkg.com/@changesets/config@2.2.0/schema.json", - "changelog": "@changesets/cli/changelog", - "commit": false, - "fixed": [], - "linked": [], - "access": "restricted", - "baseBranch": "main", - "updateInternalDependencies": "patch", - "ignore": [] -} diff --git a/packages/create-webstone-app/templates/plugin/structure/.github/workflows/changeset.yml b/packages/create-webstone-app/templates/plugin/structure/.github/workflows/changeset.yml deleted file mode 100644 index 57207f87..00000000 --- a/packages/create-webstone-app/templates/plugin/structure/.github/workflows/changeset.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Release - -on: - push: - branches: - - main - -jobs: - release: - name: Release - runs-on: ubuntu-latest - steps: - - name: Checkout Repo - uses: actions/checkout@master - with: - # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits - fetch-depth: 0 - - - name: Setup Node.js - uses: actions/setup-node@v3 - with: - node-version: 16 - - - name: Install pnpm globally - run: npm install -g pnpm - - - name: Install Dependencies - run: pnpm install --frozen-lockfile - - - name: Create Release Pull Request or Publish to npm - id: changesets - uses: changesets/action@v1 - with: - # This expects you to have a script called release which does a build for your packages and calls changeset publish - publish: pnpm release - commit: 'chore: update versions' - title: 'chore: update versions' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/packages/create-webstone-app/templates/plugin/structure/.gitignore b/packages/create-webstone-app/templates/plugin/structure/.gitignore deleted file mode 100644 index 5c3339a0..00000000 --- a/packages/create-webstone-app/templates/plugin/structure/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -.pnpm-debug.log -coverage -node_modules -package-lock.json -yarn.lock -packages/**/dist -packages/**/build -tests/e2e/test-results diff --git a/packages/create-webstone-app/templates/plugin/structure/.prettierrc b/packages/create-webstone-app/templates/plugin/structure/.prettierrc deleted file mode 100644 index ff2677ef..00000000 --- a/packages/create-webstone-app/templates/plugin/structure/.prettierrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "useTabs": true, - "singleQuote": true, - "trailingComma": "none", - "printWidth": 100 -} diff --git a/packages/create-webstone-app/templates/plugin/structure/README.md b/packages/create-webstone-app/templates/plugin/structure/README.md deleted file mode 100644 index 0e6da93e..00000000 --- a/packages/create-webstone-app/templates/plugin/structure/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# Webstone Plugin - -This is a monorepo managed by [pnpm](https://pnpm.io/) that contains two optional, independent parts that make up a [Webstone](https://github.com/WebstoneHQ/webstone/) plugin: - -- `packages/cli` ([docs](#cli)) -- `packages/web` ([docs](#web)) - -Your plugin could only extend the Webstone CLI, only extend the web aspect of Webstone Plugins, or both. - -## CLI - -Webstone Plugins provides a `webstone` CLI used by developers to enhance their projects. You can extend this CLI with `packages/cli`. - -Please refer to the [gluegun documentation](https://infinitered.github.io/gluegun/#/?id=quick-start) for instructions on how to develop commands and extensions. - -## Web - -In many cases, you want to create a Webstone Plugin to provide UI components, actions, or other web-based functionality. This is where `packages/web` comes into play. It is a basic SvelteKit `skeletonlib` project ([docs](https://kit.svelte.dev/docs/packaging)). Developers working on a SvelteKit application will be able to import your UI components as regular Svelte components. The same is true for actions or other web-based functionality your plugin provides. - -## Development - -Please make sure you have [pnpm](https://pnpm.io/) installed: - -``` -npm i -g pnpm -``` - -Start the development scripts for both packages: - -``` -pnpm dev -``` - -Alternatively, you can start the development script for either package as follows: - -``` -pnpm --filter ./packages/[cli|web] -``` - -## Publish to NPM - -Each package, `packages/cli` and `packages/web`, is deployed to NPM as independent package. Before you proceed, please open the `package.json` file for the package(s) you want to publish to NPM and set the `private` property to `false`. - -```diff -{ -- "private": true, -+ "private: false, -} -``` - -### Changesets - -To simplify the publishing process, we configured [Changesets](https://github.com/changesets/changesets). - -When you are ready to publish your package(s), please run `pnpm changeset` from the root of this project. Follow the instructions in the terminal and commit your changes. Once you pushed your commits, watch out for a new pull request titled "Version Packages". When you merge that PR, the package(s) will be published to NPM automatically. - -**`NPM_TOKEN` required** - -To make the publish process described above work automatically, please configure a NPM_TOKEN accessible in your GitHub Actions. - -- [Docs on how to create a new NPM token](https://docs.npmjs.com/creating-and-viewing-access-tokens) -- [Docs on how to create a `NPM_TOKEN` encrypted secret on GitHub](https://docs.github.com/en/actions/security-guides/encrypted-secrets) diff --git a/packages/create-webstone-app/templates/plugin/structure/package.json b/packages/create-webstone-app/templates/plugin/structure/package.json deleted file mode 100644 index 05fb06fe..00000000 --- a/packages/create-webstone-app/templates/plugin/structure/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "webstone-template-plugin", - "version": "0.0.1", - "description": "Template Plugin for Webstone - PLEASE UPDATE THIS", - "private": true, - "engines": { - "node": ">=v20.5.1" - }, - "scripts": { - "build": "pnpm --recursive --parallel build", - "changeset": "changeset && pnpm install", - "clean": "pnpm --recursive --parallel clean", - "dev": "pnpm --recursive --parallel dev", - "format": "pnpm --recursive format", - "preinstall": "npx only-allow pnpm", - "release": "changeset publish" - }, - "keywords": [ - "webstone", - "plugin" - ], - "author": "Cahllagerfeld", - "license": "MIT", - "devDependencies": { - "@changesets/cli": "^2.26.0", - "rimraf": "^3.0.2" - } -} diff --git a/packages/create-webstone-app/templates/plugin/structure/packages/cli/.prettierrc b/packages/create-webstone-app/templates/plugin/structure/packages/cli/.prettierrc deleted file mode 100644 index ff2677ef..00000000 --- a/packages/create-webstone-app/templates/plugin/structure/packages/cli/.prettierrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "useTabs": true, - "singleQuote": true, - "trailingComma": "none", - "printWidth": 100 -} diff --git a/packages/create-webstone-app/templates/plugin/structure/packages/cli/README.md b/packages/create-webstone-app/templates/plugin/structure/packages/cli/README.md deleted file mode 100644 index 8e183ca6..00000000 --- a/packages/create-webstone-app/templates/plugin/structure/packages/cli/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# `xyz` (CLI) - Webstone Plugin - -> **_Search & replace `XYZ` in this file with your plugin name._** - -## About - -> **What is this package about? What challenges does it solve?** - -## Installation - -Install this plugin with the following command: - -```shell -npm install -D webstone-plugin-XYZ-cli -``` - -That's it. Your project's `webstone` CLI is now extended with this plugin's functionality. - -## Usage - -Run `webstone --help` in your project and look for the help output of the XYZ command. - -## Learn more about Webstone Plugins - -This plugin is part of a wider ecosystem called [Webstone Plugins](https://github.com/WebstoneHQ/webstone). diff --git a/packages/create-webstone-app/templates/plugin/structure/packages/cli/package.json b/packages/create-webstone-app/templates/plugin/structure/packages/cli/package.json deleted file mode 100644 index 98220fe7..00000000 --- a/packages/create-webstone-app/templates/plugin/structure/packages/cli/package.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "webstone-plugin-template-cli", - "version": "0.0.1", - "description": "", - "private": true, - "engines": { - "node": ">=v20.5.1" - }, - "scripts": { - "clean": "rimraf build", - "copy-templates": "copyfiles -u 2 ./src/templates/* ./src/templates/**/* build/templates", - "format": "prettier --plugin-search-dir . --write .", - "build": "npm run clean && run-s build:cli copy-templates", - "build:cli": "tsc -p tsconfig.json", - "dev": "pnpm clean && pnpm copy-templates && run-p dev:watch-src dev:watch-templates", - "dev:watch-src": "tsc -p tsconfig.json --watch", - "dev:watch-templates": "npm-watch copy-templates" - }, - "keywords": [ - "webstone", - "plugin", - "template" - ], - "watch": { - "copy-templates": { - "patterns": [ - "src/templates" - ], - "extensions": "ejs" - } - }, - "author": "Cahllagerfeld", - "license": "MIT", - "devDependencies": { - "copyfiles": "^2.4.1", - "gluegun": "^5.1.2", - "npm-run-all": "^4.1.5", - "npm-watch": "^0.11.0", - "prettier": "^2.8.8", - "typescript": "^4.7.4" - } -} diff --git a/packages/create-webstone-app/templates/plugin/structure/packages/cli/src/commands/placeholder/hello-world.ts b/packages/create-webstone-app/templates/plugin/structure/packages/cli/src/commands/placeholder/hello-world.ts deleted file mode 100644 index 4b8a0db1..00000000 --- a/packages/create-webstone-app/templates/plugin/structure/packages/cli/src/commands/placeholder/hello-world.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { GluegunCommand } from 'gluegun'; - -const command: GluegunCommand = { - name: 'hello', - alias: ['h'], - description: 'Hello World Command', - hidden: false, - dashed: false, - run: async (toolbox) => { - const { print } = toolbox; - - print.info(`Hello World`); - } -}; - -export default command; diff --git a/packages/create-webstone-app/templates/plugin/structure/packages/cli/src/extensions/placeholder/hello.ts b/packages/create-webstone-app/templates/plugin/structure/packages/cli/src/extensions/placeholder/hello.ts deleted file mode 100644 index c2f7ce17..00000000 --- a/packages/create-webstone-app/templates/plugin/structure/packages/cli/src/extensions/placeholder/hello.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { GluegunToolbox } from 'gluegun'; - -const extension = (toolbox: GluegunToolbox) => { - const { print } = toolbox; - - toolbox.sayhello = () => { - print.info('Hello from an extension!'); - }; -}; - -export default extension; diff --git a/packages/create-webstone-app/templates/plugin/structure/packages/cli/tsconfig.json b/packages/create-webstone-app/templates/plugin/structure/packages/cli/tsconfig.json deleted file mode 100644 index 7022e856..00000000 --- a/packages/create-webstone-app/templates/plugin/structure/packages/cli/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "target": "ES6", - "outDir": "./build", - "module": "commonjs", - "forceConsistentCasingInFileNames": true, - "strict": true, - "allowSyntheticDefaultImports": true, - "experimentalDecorators": true, - "skipLibCheck": true, - "declaration": true, - "moduleResolution": "Node", - "rootDir": "src", - "declarationDir": "./build/types" - }, - "include": ["src/**/*.ts"], - "exclude": ["src/fixtures", "src/**/*.test.ts"] -} diff --git a/packages/create-webstone-app/templates/plugin/structure/packages/web/.gitkeep b/packages/create-webstone-app/templates/plugin/structure/packages/web/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/create-webstone-app/templates/plugin/structure/packages/web/README.md b/packages/create-webstone-app/templates/plugin/structure/packages/web/README.md deleted file mode 100644 index 1068ae92..00000000 --- a/packages/create-webstone-app/templates/plugin/structure/packages/web/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# `xyz` (Web) - Webstone Plugin - -> **_Search & replace `XYZ` in this file with your plugin name._** - -## About - -> **What is this package about? What challenges does it solve?** - -## Installation - -Install this plugin with the following command: - -```shell -npm install -D webstone-plugin-XYZ-web -``` - -## Usage - -> **_Document how developers can use this plugin. Do they import a Svelte component? Is there a Svelte action they can use?_** - -## Learn more about Webstone Plugins - -This plugin is part of a wider ecosystem called [Webstone Plugins](https://github.com/WebstoneHQ/webstone-plugins). diff --git a/packages/create-webstone-app/templates/plugin/structure/pnpm-workspace.yaml b/packages/create-webstone-app/templates/plugin/structure/pnpm-workspace.yaml deleted file mode 100644 index 600b4bb4..00000000 --- a/packages/create-webstone-app/templates/plugin/structure/pnpm-workspace.yaml +++ /dev/null @@ -1,2 +0,0 @@ -packages: - - 'packages/**' diff --git a/packages/create-webstone-app/tests/helpers/configure-app.ts b/packages/create-webstone-app/tests/helpers/configure-app.ts deleted file mode 100644 index 7120f3a4..00000000 --- a/packages/create-webstone-app/tests/helpers/configure-app.ts +++ /dev/null @@ -1,29 +0,0 @@ -import fs from "fs-extra"; -import sinon from "sinon"; -import { test } from "uvu"; -import * as assert from "uvu/assert"; -import { Ctx } from "../../src/helpers"; -import { copyReadme } from "../../src/tasks/3-configure-app/application"; - -test.after.each(() => { - sinon.restore(); -}); - -test("Check if Readme gets replaced", async () => { - const fakeCopySync = sinon.fake(); - sinon.replace(fs, "copySync", fakeCopySync); - - const fakeContext: Ctx = { - appDir: "test-app", - type: "application", - }; - - await copyReadme(fakeContext); - - assert.is(fakeCopySync.callCount, 1); - assert.ok( - (fakeCopySync.firstCall.args[0] as string).includes( - "templates/application/README.md", - ), - ); -}); diff --git a/packages/create-webstone-app/tests/helpers/create-app-dir.ts b/packages/create-webstone-app/tests/helpers/create-app-dir.ts deleted file mode 100644 index 86207c15..00000000 --- a/packages/create-webstone-app/tests/helpers/create-app-dir.ts +++ /dev/null @@ -1,183 +0,0 @@ -import fs from "fs-extra"; -import sinon from "sinon"; -import { test } from "uvu"; -import * as assert from "uvu/assert"; -import { Ctx, WebstoneTask } from "../../src/helpers"; -import { createAppDir } from "../../src/tasks/1-create-directory"; - -test.before.each(() => { - sinon.replace(console, "log", sinon.fake()); -}); - -test.after.each(() => { - sinon.restore(); -}); - -test("app dir does not exist, no app dir provided", async () => { - const fakeListrTask: Partial = { - output: "", - }; - - const fakeContext: Ctx = { - type: "application", - appDir: ".", - }; - - const fakeFsExistsSync = sinon.fake.returns(false); - sinon.replace(fs, "existsSync", fakeFsExistsSync); - - const fakeFsMkdirSync = sinon.fake(); - sinon.replace(fs, "mkdirSync", fakeFsMkdirSync); - - const originalProcessArgv2 = process.argv[2]; - process.argv[2] = undefined; - - try { - const appDir = await createAppDir( - fakeContext, - fakeListrTask as WebstoneTask, - ); - assert.is(appDir, "."); - } finally { - process.argv[2] = originalProcessArgv2; - } - - assert.is(fakeFsExistsSync.firstCall.firstArg, "."); - assert.is(fakeFsMkdirSync.firstCall.firstArg, "."); - assert.equal(fakeFsMkdirSync.firstCall.lastArg, { recursive: true }); -}); - -test("app dir does not exist, app dir with space", async () => { - const fakeListrTask: Partial = { - output: "", - }; - - const fakeContext: Ctx = { - type: "application", - appDir: "test-app", - }; - const fakeFsExistsSync = sinon.fake.returns(false); - sinon.replace(fs, "existsSync", fakeFsExistsSync); - - const fakeFsMkdirSync = sinon.fake(); - sinon.replace(fs, "mkdirSync", fakeFsMkdirSync); - - const appDir = await createAppDir(fakeContext, fakeListrTask as WebstoneTask); - assert.is(appDir, "test-app"); - assert.is(fakeFsExistsSync.firstCall.firstArg, "test-app"); - assert.is(fakeFsMkdirSync.firstCall.firstArg, "test-app"); - assert.equal(fakeFsMkdirSync.firstCall.lastArg, { recursive: true }); -}); - -test("app dir does not exist", async () => { - const fakeListrTask: Partial = { - output: "", - }; - - const fakeContext: Ctx = { - appDir: "test-app", - }; - - const fakeFsExistsSync = sinon.fake.returns(false); - sinon.replace(fs, "existsSync", fakeFsExistsSync); - - const fakeFsMkdirSync = sinon.fake(); - sinon.replace(fs, "mkdirSync", fakeFsMkdirSync); - - const appDir = await createAppDir(fakeContext, fakeListrTask as WebstoneTask); - assert.is(appDir, "test-app"); - assert.is(fakeFsExistsSync.firstCall.firstArg, "test-app"); - assert.is(fakeFsMkdirSync.firstCall.firstArg, "test-app"); - assert.equal(fakeFsMkdirSync.firstCall.lastArg, { recursive: true }); -}); - -test("app dir exists and is empty", async () => { - const fakeListrTask: Partial = { - output: "", - }; - - const fakeContext: Ctx = { - type: "application", - appDir: "test-app", - }; - - const fakeFsExistsSync = sinon.fake.returns(true); - sinon.replace(fs, "existsSync", fakeFsExistsSync); - - const fakeFsReaddirSync = sinon.fake.returns([]); - sinon.replace(fs, "readdirSync", fakeFsReaddirSync); - - const fakeFsMkdirSync = sinon.fake(); - sinon.replace(fs, "mkdirSync", fakeFsMkdirSync); - - const appDir = await createAppDir(fakeContext, fakeListrTask as WebstoneTask); - assert.is(appDir, "test-app"); - assert.is(fakeFsReaddirSync.firstCall.firstArg, "test-app"); - assert.is(fakeFsMkdirSync.firstCall.firstArg, "test-app"); - assert.equal(fakeFsMkdirSync.firstCall.lastArg, { recursive: true }); -}); - -test("app dir exists and is not empty, continue?", async () => { - const fakeListrPrompt = sinon.fake.returns(true); - const fakeListrTask: Partial = { - output: "", - prompt: fakeListrPrompt, - }; - - const fakeContext: Ctx = { - type: "application", - appDir: "test-app", - }; - const fakeFsExistsSync = sinon.fake.returns(true); - sinon.replace(fs, "existsSync", fakeFsExistsSync); - - const fakeFsReaddirSync = sinon.fake.returns([ - "dummy-file-to-fake-a-non-empty-directory", - ]); - sinon.replace(fs, "readdirSync", fakeFsReaddirSync); - - const fakeFsMkdirSync = sinon.fake(); - sinon.replace(fs, "mkdirSync", fakeFsMkdirSync); - - const appDir = await createAppDir(fakeContext, fakeListrTask as WebstoneTask); - assert.is(appDir, "test-app"); - assert.equal(fakeListrPrompt.firstCall.firstArg, { - type: "confirm", - message: `The ./test-app directory is not empty. Do you want to continue?`, - initial: false, - }); - assert.is(fakeFsMkdirSync.firstCall.firstArg, "test-app"); - assert.equal(fakeFsMkdirSync.firstCall.lastArg, { recursive: true }); -}); - -test("app dir exists and is not empty, do not continue", async () => { - const fakeListrPrompt = sinon.fake.returns(false); - const fakeListrTask: Partial = { - output: "", - prompt: fakeListrPrompt, - }; - - const fakeContext: Ctx = { - type: "application", - appDir: "test-app", - }; - const fakeFsExistsSync = sinon.fake.returns(true); - sinon.replace(fs, "existsSync", fakeFsExistsSync); - - const fakeFsReaddirSync = sinon.fake.returns([ - "dummy-file-to-fake-a-non-empty-directory", - ]); - sinon.replace(fs, "readdirSync", fakeFsReaddirSync); - - try { - await createAppDir(fakeContext, fakeListrTask as WebstoneTask); - assert.unreachable(); - } catch (error) { - assert.is( - error.message, - `Exiting, please empty the ./test-app directory or choose a different one to create the Webstone app.`, - ); - } -}); - -test.run(); diff --git a/packages/create-webstone-app/tests/helpers/display-next-steps.ts b/packages/create-webstone-app/tests/helpers/display-next-steps.ts deleted file mode 100644 index af4e5bca..00000000 --- a/packages/create-webstone-app/tests/helpers/display-next-steps.ts +++ /dev/null @@ -1,36 +0,0 @@ -import sinon from "sinon"; -import { test } from "uvu"; -import * as assert from "uvu/assert"; -import { Ctx, displayNextSteps } from "../../src/helpers"; - -const context: Ctx = { - appDir: "test-dir", - type: "application", -}; - -test.after(() => { - sinon.restore(); -}); - -test("displayNextSteps", async () => { - const fakeConsoleLog = sinon.fake(); - sinon.replace(console, "log", fakeConsoleLog); - - await displayNextSteps(context); - assert.ok(fakeConsoleLog.calledOnce); - assert.ok( - (fakeConsoleLog.firstCall.firstArg as string).includes( - "https://github.com/WebstoneHQ/webstone", - ), - ); - assert.ok( - (fakeConsoleLog.firstCall.firstArg as string).includes( - "https://discord.gg/NJRm6eRs", - ), - ); - assert.ok( - (fakeConsoleLog.firstCall.firstArg as string).includes("cd test-dir"), - ); -}); - -test.run(); diff --git a/packages/create-webstone-app/tests/helpers/display-welcome.ts b/packages/create-webstone-app/tests/helpers/display-welcome.ts deleted file mode 100644 index 79ed4f2a..00000000 --- a/packages/create-webstone-app/tests/helpers/display-welcome.ts +++ /dev/null @@ -1,29 +0,0 @@ -import sinon from "sinon"; -import { test } from "uvu"; -import * as assert from "uvu/assert"; -import { displayWelcome } from "../../src/helpers"; - -test.after(() => { - sinon.restore(); -}); - -test("displayWelcome", async () => { - const fakeConsoleLog = sinon.fake(); - sinon.replace(console, "log", fakeConsoleLog); - - await displayWelcome(); - assert.ok( - fakeConsoleLog.calledOnceWith(` - ▄ ▄ ▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄ ▄ ▄▄▄▄▄▄▄ - █ █ ▄ █ █ █ ▄ █ █ █ █ █ █ █ █ - █ ██ ██ █ ▄▄▄█ █▄█ █ ▄▄▄▄▄█▄ ▄█ ▄ █ █▄█ █ ▄▄▄█ - █ █ █▄▄▄█ █ █▄▄▄▄▄ █ █ █ █ █ █ █ █▄▄▄ - █ █ ▄▄▄█ ▄ ██▄▄▄▄▄ █ █ █ █ █▄█ █ ▄ █ ▄▄▄█ - █ ▄ █ █▄▄▄█ █▄█ █▄▄▄▄▄█ █ █ █ █ █ █ █ █ █▄▄▄ - █▄▄█ █▄▄█▄▄▄▄▄▄▄█▄▄▄▄▄▄▄█▄▄▄▄▄▄▄█ █▄▄▄█ █▄▄▄▄▄▄▄█▄█ █▄▄█▄▄▄▄▄▄▄█ - - `), - ); -}); - -test.run(); diff --git a/packages/create-webstone-app/tests/helpers/setup-plugin.ts b/packages/create-webstone-app/tests/helpers/setup-plugin.ts deleted file mode 100644 index eb0cfcfd..00000000 --- a/packages/create-webstone-app/tests/helpers/setup-plugin.ts +++ /dev/null @@ -1,93 +0,0 @@ -import sinon from "sinon"; -import { test } from "uvu"; -import fs from "fs-extra"; -import * as assert from "uvu/assert"; -import { - copyTemplate, - renameCliPackage, - renameMainPackage, -} from "../../src/tasks/2-setup-project/plugin"; - -import { Ctx } from "../../src/helpers"; - -test.after.each(() => { - sinon.restore(); -}); - -test("Check if the plugin template gets copied properly", async () => { - const fakeContext: Ctx = { - appDir: "dummy", - type: "plugin", - }; - const fakeCopySync = sinon.fake(); - sinon.replace(fs, "copySync", fakeCopySync); - - copyTemplate(fakeContext); - - assert.is(fakeCopySync.callCount, 1); - assert.ok( - (fakeCopySync.firstCall.args[0] as string).includes( - "templates/plugin/structure", - ), - ); -}); - -test("Check if the cli package gets renamed properly", async () => { - const fakeContext: Ctx = { - appDir: "dummy", - type: "plugin", - }; - const fakeReadJSONSync = sinon.fake.returns({ - name: "webstone-plugin-placeholder-cli", - }); - const fakeWriteJSONSync = sinon.fake(); - sinon.replace(fs, "readJSONSync", fakeReadJSONSync); - sinon.replace(fs, "writeJSONSync", fakeWriteJSONSync); - - renameCliPackage(fakeContext); - - assert.is(fakeReadJSONSync.callCount, 1); - assert.ok( - (fakeReadJSONSync.firstCall.args[0] as string).includes( - "packages/cli/package.json", - ), - ); - assert.is(fakeWriteJSONSync.callCount, 1); - assert.ok( - (fakeWriteJSONSync.firstCall.args[0] as string).includes( - "packages/cli/package.json", - ), - ); - assert.is( - fakeWriteJSONSync.firstCall.args[1].name, - "webstone-plugin-dummy-cli", - ); -}); - -test("Check if the main package gets renamed properly", async () => { - const fakeContext: Ctx = { - appDir: "dummy", - type: "plugin", - }; - const fakeReadJSONSync = sinon.fake.returns({ - name: "webstone-plugin-placeholder", - }); - const fakeWriteJSONSync = sinon.fake(); - - sinon.replace(fs, "readJSONSync", fakeReadJSONSync); - sinon.replace(fs, "writeJSONSync", fakeWriteJSONSync); - - renameMainPackage(fakeContext); - - assert.is(fakeReadJSONSync.callCount, 1); - assert.ok( - (fakeReadJSONSync.firstCall.args[0] as string).includes("package.json"), - ); - assert.is(fakeWriteJSONSync.callCount, 1); - assert.ok( - (fakeWriteJSONSync.firstCall.args[0] as string).includes("package.json"), - ); - assert.is(fakeWriteJSONSync.firstCall.args[1].name, "webstone-plugin-dummy"); -}); - -test.run(); diff --git a/packages/create-webstone-app/types/index.ts b/packages/create-webstone-app/types/index.ts new file mode 100644 index 00000000..e717e169 --- /dev/null +++ b/packages/create-webstone-app/types/index.ts @@ -0,0 +1,6 @@ +export type CreateWebstoneOptions = { + type: WebstoneAppType; + extendCLI: boolean; +}; + +export type WebstoneAppType = "app" | "plugin"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 680b89eb..624ba2fe 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -91,40 +91,28 @@ importers: chalk: specifier: 5.3.0 version: 5.3.0 - command-line-args: - specifier: ^5.2.1 - version: 5.2.1 create-svelte: specifier: ^5.0.5 version: 5.0.5 enquirer: specifier: 2.4.1 version: 2.4.1 - execa: - specifier: 7.2.0 - version: 7.2.0 fs-extra: specifier: 11.1.1 version: 11.1.1 - json5: - specifier: ^2.2.3 - version: 2.2.3 - listr2: - specifier: 6.6.1 - version: 6.6.1(enquirer@2.4.1) + ts-deepmerge: + specifier: ^6.2.0 + version: 6.2.0 devDependencies: - '@types/command-line-args': - specifier: ^5.2.0 - version: 5.2.0 '@types/node': specifier: 20.4.10 version: 20.4.10 - esbuild: - specifier: ^0.19.1 - version: 0.19.1 - esbuild-node-externals: - specifier: ^1.8.0 - version: 1.8.0(esbuild@0.19.1) + tsup: + specifier: ^6.7.0 + version: 6.7.0(typescript@5.1.6) + type-fest: + specifier: ^4.2.0 + version: 4.2.0 typescript: specifier: ^5.1.6 version: 5.1.6 @@ -688,15 +676,6 @@ packages: dev: true optional: true - /@esbuild/android-arm64@0.19.1: - resolution: {integrity: sha512-CqhrKvDSt76I0so/5afqgKrMv41FjbfUKFrcZddMnrZKqJU70I1MWLVJrImJuYMaY4Yb9rn4UKfF7oZ0BOleVw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-arm@0.17.19: resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} engines: {node: '>=12'} @@ -715,15 +694,6 @@ packages: dev: true optional: true - /@esbuild/android-arm@0.19.1: - resolution: {integrity: sha512-yjTucwcOua52z14RL30JMwmCdylsQ5WrErGkAb6VL0MWPbnwJyLejydaRcUqkPO6g0MowlzavdxrR7AcfCW+yA==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-x64@0.17.19: resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} engines: {node: '>=12'} @@ -742,15 +712,6 @@ packages: dev: true optional: true - /@esbuild/android-x64@0.19.1: - resolution: {integrity: sha512-VA29h01MrPkymIL1bFtvL2L4WPogiMGW2N/M+vXZHHOv6LgA9vjzVskTt0v5LjeCjx1PFDcR0ASKy8Y7Gm+iIA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/darwin-arm64@0.17.19: resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} engines: {node: '>=12'} @@ -769,15 +730,6 @@ packages: dev: true optional: true - /@esbuild/darwin-arm64@0.19.1: - resolution: {integrity: sha512-Be4Cf6WDH7QkLHEpfzQOlBOFdqmqYTSqw2yG3SVmzB3++wy3K7wiNGedezL+q6Jb4weqT9tchO5kkLDC08Jnzg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - /@esbuild/darwin-x64@0.17.19: resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} engines: {node: '>=12'} @@ -796,15 +748,6 @@ packages: dev: true optional: true - /@esbuild/darwin-x64@0.19.1: - resolution: {integrity: sha512-SewtenJi6zCEfZRSUchb+LgJ/IQw8QvnKECPu/qHII1fLQKnVPUVR+VH2IuS03DD9WWnAi3yfOvBNwtrp3WXtg==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - /@esbuild/freebsd-arm64@0.17.19: resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} engines: {node: '>=12'} @@ -823,15 +766,6 @@ packages: dev: true optional: true - /@esbuild/freebsd-arm64@0.19.1: - resolution: {integrity: sha512-TadKO0AaTDAPV2RyGZQ0AaiDTVYg7RsgNaA6OJjXXmoLbTs++NwHtzAmVFBq8Q/P9A11wgkv36HeyAYhWHbW1w==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/freebsd-x64@0.17.19: resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} engines: {node: '>=12'} @@ -850,15 +784,6 @@ packages: dev: true optional: true - /@esbuild/freebsd-x64@0.19.1: - resolution: {integrity: sha512-DrFMGLF0/aAcZgwhtZr1cby7aHlalpFjLCe5CiI8mm0Kqhhc8gyNZKreaZzvir8CQe0H17p9xx6M9ben5R3r0g==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-arm64@0.17.19: resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} engines: {node: '>=12'} @@ -877,15 +802,6 @@ packages: dev: true optional: true - /@esbuild/linux-arm64@0.19.1: - resolution: {integrity: sha512-6ku/R2EzsdjyBaqQn+xGOPbv+BBYBXQYzlA04/46YQLmXkdApi0GYyUwiCXYBxm578iyywzGmM0rep1/q8tuFQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-arm@0.17.19: resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} engines: {node: '>=12'} @@ -904,15 +820,6 @@ packages: dev: true optional: true - /@esbuild/linux-arm@0.19.1: - resolution: {integrity: sha512-lCWDVPpQO/Dt5MEqctKujgtUVmwQx7J2Q83EqX/9BejN7BIX4fGJ0QKMiIyy21PFh+/64ArN+Ovh1tzYkTt2wg==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-ia32@0.17.19: resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} engines: {node: '>=12'} @@ -931,15 +838,6 @@ packages: dev: true optional: true - /@esbuild/linux-ia32@0.19.1: - resolution: {integrity: sha512-8AKFBk9v/zBDsADvK/0BWZUxkjEc0QDwO8rvbHJKqAZx6DF/VSeBxTRmqWeecrJmx+n3kemEwML9z0eD9IHweQ==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-loong64@0.17.19: resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} engines: {node: '>=12'} @@ -958,15 +856,6 @@ packages: dev: true optional: true - /@esbuild/linux-loong64@0.19.1: - resolution: {integrity: sha512-6mOS5CxTGD8qOymp2y4KoM4ir+/REgjdJQFYpwP+WqjrWBo+PUevDGeHHjzCdw/R19PkFqS1bRzv8cTCmB/5kA==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-mips64el@0.17.19: resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} engines: {node: '>=12'} @@ -985,15 +874,6 @@ packages: dev: true optional: true - /@esbuild/linux-mips64el@0.19.1: - resolution: {integrity: sha512-Bzmv6rRMzR4ErG2k/jwfj5jKNzVMVEI1tThuirFdAoE+duUv+jlDnlwxsN3s1eqMzADTOV2sSIcUUOfgv++Dgg==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-ppc64@0.17.19: resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} engines: {node: '>=12'} @@ -1012,15 +892,6 @@ packages: dev: true optional: true - /@esbuild/linux-ppc64@0.19.1: - resolution: {integrity: sha512-mPOxA7bd3nmx8TkuO/9M/tE0fnvmuX0wlpwnTL6DPLgkb/Z/KkupexSIw4cLfznn/fPzD89y17VWBjlVNyrpCQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-riscv64@0.17.19: resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} engines: {node: '>=12'} @@ -1039,15 +910,6 @@ packages: dev: true optional: true - /@esbuild/linux-riscv64@0.19.1: - resolution: {integrity: sha512-znYb2Mhe9xKIDeIYuTD6vCcUltvYzRT5Yq6sVcdhPrGu8DRdsNZS04B2tSeM+j7T03jL4yY+7/G/jxSJJ9LX2A==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-s390x@0.17.19: resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} engines: {node: '>=12'} @@ -1066,15 +928,6 @@ packages: dev: true optional: true - /@esbuild/linux-s390x@0.19.1: - resolution: {integrity: sha512-BBIE32cyqAYhMOQ42/jnecoF5P/S5lMob2vXSUiFpD3xCFbXOFkjP1OjfFKnalSO9+B5emvPTQFfNQXuLeVGEw==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-x64@0.17.19: resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} engines: {node: '>=12'} @@ -1093,15 +946,6 @@ packages: dev: true optional: true - /@esbuild/linux-x64@0.19.1: - resolution: {integrity: sha512-PoCvKdHTIbnHmVJ5OEdewGMSw40HDFRTrC/imwh8vrp695RbSUpOqBqNBT45neK0FQleGFbSE/A9X6HlXPDhqA==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/netbsd-x64@0.17.19: resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} engines: {node: '>=12'} @@ -1120,15 +964,6 @@ packages: dev: true optional: true - /@esbuild/netbsd-x64@0.19.1: - resolution: {integrity: sha512-4OrGMPorHCq9h52VLtyyyAmPjC2ZlANx54VDYyCrqXUOi+k0qxnPKXKKprVES67w2mE7TZJx9qZmT+jHeiZbHQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/openbsd-x64@0.17.19: resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} engines: {node: '>=12'} @@ -1147,15 +982,6 @@ packages: dev: true optional: true - /@esbuild/openbsd-x64@0.19.1: - resolution: {integrity: sha512-3a7ZYMjBC4P3FKdTmUZHJw7Mhzp71m+iSFFhX1PnLZ03qmyaB2K+vJZCk4PjRjAvm5lSupJQQtM/AFMyLgKlxQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/sunos-x64@0.17.19: resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} engines: {node: '>=12'} @@ -1174,15 +1000,6 @@ packages: dev: true optional: true - /@esbuild/sunos-x64@0.19.1: - resolution: {integrity: sha512-29yWBN5XfEjXT8yoeVb8cXfN1jAQLB+uskog1vBMhFR+YWOYvsrwPnh4hspETC/JnF95J+iETrvxgOUlICTWIw==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-arm64@0.17.19: resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} engines: {node: '>=12'} @@ -1201,15 +1018,6 @@ packages: dev: true optional: true - /@esbuild/win32-arm64@0.19.1: - resolution: {integrity: sha512-9Hb/WUXgyXlL55w3iNVyLkN9gq9x+agv3kk80foWbfpOwe7Qw4Vx6JGB+XQdsIfvvP1kShVQPIvBgVj0TxLlVw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-ia32@0.17.19: resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} engines: {node: '>=12'} @@ -1228,15 +1036,6 @@ packages: dev: true optional: true - /@esbuild/win32-ia32@0.19.1: - resolution: {integrity: sha512-VGdtEcXX/f01NgoM8emDnpdOyrZCQ7VTwLv89MOl3mvJ5fbCOBMNCa8t7RZS4lf12RS87qOuJFX7Bh9aLTbSxg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-x64@0.17.19: resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} engines: {node: '>=12'} @@ -1255,15 +1054,6 @@ packages: dev: true optional: true - /@esbuild/win32-x64@0.19.1: - resolution: {integrity: sha512-H6u8OHmJkKJubLbukVOyi9yA5lzK8VE4TFEkZj2vgusTUPvFeMQ8YnWviVc9F6PuKS6ZIpOvi2/sfiW8tQZQ2g==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.46.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1605,10 +1395,6 @@ packages: resolution: {integrity: sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==} dev: true - /@types/command-line-args@5.2.0: - resolution: {integrity: sha512-UuKzKpJJ/Ief6ufIaIzr3A/0XnluX7RvFgwkV89Yzvm77wCh1kFaFmqN8XEnGcN62EuHdedQjEMb8mYxFLGPyA==} - dev: true - /@types/cookie@0.5.1: resolution: {integrity: sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g==} dev: true @@ -2089,13 +1875,6 @@ packages: type-fest: 0.21.3 dev: true - /ansi-escapes@5.0.0: - resolution: {integrity: sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==} - engines: {node: '>=12'} - dependencies: - type-fest: 1.4.0 - dev: false - /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -2103,6 +1882,7 @@ packages: /ansi-regex@6.0.1: resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} engines: {node: '>=12'} + dev: true /ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} @@ -2124,6 +1904,7 @@ packages: /ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + dev: true /any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} @@ -2168,11 +1949,6 @@ packages: dequal: 2.0.3 dev: true - /array-back@3.1.0: - resolution: {integrity: sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==} - engines: {node: '>=6'} - dev: false - /array-buffer-byte-length@1.0.0: resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} dependencies: @@ -2468,13 +2244,6 @@ packages: dependencies: restore-cursor: 3.1.0 - /cli-cursor@4.0.0: - resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - restore-cursor: 4.0.0 - dev: false - /cli-spinners@2.6.1: resolution: {integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==} engines: {node: '>=6'} @@ -2501,6 +2270,7 @@ packages: dependencies: slice-ansi: 5.0.0 string-width: 5.1.2 + dev: true /cli-width@3.0.0: resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} @@ -2569,21 +2339,12 @@ packages: /colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + dev: true /colors@1.4.0: resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} engines: {node: '>=0.1.90'} - /command-line-args@5.2.1: - resolution: {integrity: sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==} - engines: {node: '>=4.0.0'} - dependencies: - array-back: 3.1.0 - find-replace: 3.0.0 - lodash.camelcase: 4.3.0 - typical: 4.0.0 - dev: false - /commander@10.0.1: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} engines: {node: '>=14'} @@ -2908,6 +2669,7 @@ packages: /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: true /ejs@3.1.8: resolution: {integrity: sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==} @@ -2921,6 +2683,7 @@ packages: /emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true /enquirer@2.3.6: resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} @@ -3013,17 +2776,6 @@ packages: resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} dev: true - /esbuild-node-externals@1.8.0(esbuild@0.19.1): - resolution: {integrity: sha512-pYslmT8Bl383UnfxzHQQRpCgBNIOwAzDaYheuIeI4CODxelsN/eQroVn5STDow5QOpRalMgWUR+R8LfSgUROcw==} - engines: {node: '>=12'} - peerDependencies: - esbuild: 0.12 - 0.18 - dependencies: - esbuild: 0.19.1 - find-up: 5.0.0 - tslib: 2.6.1 - dev: true - /esbuild@0.17.19: resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==} engines: {node: '>=12'} @@ -3084,36 +2836,6 @@ packages: '@esbuild/win32-x64': 0.18.20 dev: true - /esbuild@0.19.1: - resolution: {integrity: sha512-IknHHwV4B/H4imOAu+416fuCvPfRjdncoyGi7eunhSvHuHkdNs50sLWan2LEG2Mym07TuW6gJUIyRS9G1miHEg==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/android-arm': 0.19.1 - '@esbuild/android-arm64': 0.19.1 - '@esbuild/android-x64': 0.19.1 - '@esbuild/darwin-arm64': 0.19.1 - '@esbuild/darwin-x64': 0.19.1 - '@esbuild/freebsd-arm64': 0.19.1 - '@esbuild/freebsd-x64': 0.19.1 - '@esbuild/linux-arm': 0.19.1 - '@esbuild/linux-arm64': 0.19.1 - '@esbuild/linux-ia32': 0.19.1 - '@esbuild/linux-loong64': 0.19.1 - '@esbuild/linux-mips64el': 0.19.1 - '@esbuild/linux-ppc64': 0.19.1 - '@esbuild/linux-riscv64': 0.19.1 - '@esbuild/linux-s390x': 0.19.1 - '@esbuild/linux-x64': 0.19.1 - '@esbuild/netbsd-x64': 0.19.1 - '@esbuild/openbsd-x64': 0.19.1 - '@esbuild/sunos-x64': 0.19.1 - '@esbuild/win32-arm64': 0.19.1 - '@esbuild/win32-ia32': 0.19.1 - '@esbuild/win32-x64': 0.19.1 - dev: true - /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -3283,10 +3005,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - dev: false - /execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -3314,6 +3032,7 @@ packages: onetime: 6.0.0 signal-exit: 3.0.7 strip-final-newline: 3.0.0 + dev: true /expand-tilde@2.0.2: resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} @@ -3394,13 +3113,6 @@ packages: merge: 2.1.1 dev: true - /find-replace@3.0.0: - resolution: {integrity: sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==} - engines: {node: '>=4.0.0'} - dependencies: - array-back: 3.1.0 - dev: false - /find-root@1.1.0: resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} dev: true @@ -3778,6 +3490,7 @@ packages: /human-signals@4.3.1: resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} engines: {node: '>=14.18.0'} + dev: true /husky@8.0.3: resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} @@ -3944,6 +3657,7 @@ packages: /is-fullwidth-code-point@4.0.0: resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} engines: {node: '>=12'} + dev: true /is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} @@ -4008,6 +3722,7 @@ packages: /is-stream@3.0.0: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true /is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} @@ -4147,12 +3862,6 @@ packages: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} dev: true - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - dev: false - /jsonc-parser@3.2.0: resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} dev: true @@ -4245,24 +3954,6 @@ packages: wrap-ansi: 7.0.0 dev: true - /listr2@6.6.1(enquirer@2.4.1): - resolution: {integrity: sha512-+rAXGHh0fkEWdXBmX+L6mmfmXmXvDGEKzkjxO+8mP3+nI/r/CWznVBvsibXdxda9Zz0OW2e2ikphN3OwCT/jSg==} - engines: {node: '>=16.0.0'} - peerDependencies: - enquirer: '>= 2.3.0 < 3' - peerDependenciesMeta: - enquirer: - optional: true - dependencies: - cli-truncate: 3.1.0 - colorette: 2.0.20 - enquirer: 2.4.1 - eventemitter3: 5.0.1 - log-update: 5.0.1 - rfdc: 1.3.0 - wrap-ansi: 8.1.0 - dev: false - /load-json-file@4.0.0: resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==} engines: {node: '>=4'} @@ -4410,17 +4101,6 @@ packages: wrap-ansi: 6.2.0 dev: true - /log-update@5.0.1: - resolution: {integrity: sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - ansi-escapes: 5.0.0 - cli-cursor: 4.0.0 - slice-ansi: 5.0.0 - strip-ansi: 7.1.0 - wrap-ansi: 8.1.0 - dev: false - /longest@2.0.1: resolution: {integrity: sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==} engines: {node: '>=0.10.0'} @@ -4544,6 +4224,7 @@ packages: /mimic-fn@4.0.0: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} + dev: true /min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} @@ -4782,6 +4463,7 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: path-key: 4.0.0 + dev: true /npm-watch@0.11.0: resolution: {integrity: sha512-wAOd0moNX2kSA2FNvt8+7ORwYaJpQ1ZoWjUYdb1bBCxq4nkWuU0IiJa9VpVxrj5Ks+FGXQd62OC/Bjk0aSr+dg==} @@ -4832,6 +4514,7 @@ packages: engines: {node: '>=12'} dependencies: mimic-fn: 4.0.0 + dev: true /optionator@0.9.3: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} @@ -4988,6 +4671,7 @@ packages: /path-key@4.0.0: resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} engines: {node: '>=12'} + dev: true /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} @@ -5085,6 +4769,22 @@ packages: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} + /postcss-load-config@3.1.4: + resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} + engines: {node: '>= 10'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + dependencies: + lilconfig: 2.1.0 + yaml: 1.10.2 + dev: true + /postcss-load-config@3.1.4(postcss@8.4.27)(ts-node@10.9.1): resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} engines: {node: '>= 10'} @@ -5384,20 +5084,13 @@ packages: onetime: 5.1.2 signal-exit: 3.0.7 - /restore-cursor@4.0.0: - resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - dev: false - /reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} /rfdc@1.3.0: resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} + dev: true /rimraf@2.7.1: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} @@ -5623,6 +5316,7 @@ packages: dependencies: ansi-styles: 6.2.1 is-fullwidth-code-point: 4.0.0 + dev: true /smartwrap@2.0.2: resolution: {integrity: sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==} @@ -5743,6 +5437,7 @@ packages: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 strip-ansi: 7.1.0 + dev: true /string.prototype.padend@3.1.4: resolution: {integrity: sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==} @@ -5804,6 +5499,7 @@ packages: engines: {node: '>=12'} dependencies: ansi-regex: 6.0.1 + dev: true /strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} @@ -5822,6 +5518,7 @@ packages: /strip-final-newline@3.0.0: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} + dev: true /strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} @@ -6115,6 +5812,11 @@ packages: typescript: 5.1.6 dev: true + /ts-deepmerge@6.2.0: + resolution: {integrity: sha512-2qxI/FZVDPbzh63GwWIZYE7daWKtwXZYuyc8YNq0iTmMUwn4mL0jRLsp6hfFlgbdRSR4x2ppe+E86FnvEpN7Nw==} + engines: {node: '>=14.13.1'} + dev: false + /ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} dev: true @@ -6232,6 +5934,42 @@ packages: - ts-node dev: true + /tsup@6.7.0(typescript@5.1.6): + resolution: {integrity: sha512-L3o8hGkaHnu5TdJns+mCqFsDBo83bJ44rlK7e6VdanIvpea4ArPcU3swWGsLVbXak1PqQx/V+SSmFPujBK+zEQ==} + engines: {node: '>=14.18'} + hasBin: true + peerDependencies: + '@swc/core': ^1 + postcss: ^8.4.12 + typescript: '>=4.1.0' + peerDependenciesMeta: + '@swc/core': + optional: true + postcss: + optional: true + typescript: + optional: true + dependencies: + bundle-require: 4.0.1(esbuild@0.17.19) + cac: 6.7.14 + chokidar: 3.5.3 + debug: 4.3.4 + esbuild: 0.17.19 + execa: 5.1.1 + globby: 11.1.0 + joycon: 3.1.1 + postcss-load-config: 3.1.4 + resolve-from: 5.0.0 + rollup: 3.28.0 + source-map: 0.8.0-beta.0 + sucrase: 3.28.0 + tree-kill: 1.2.2 + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + - ts-node + dev: true + /tsx@3.12.7: resolution: {integrity: sha512-C2Ip+jPmqKd1GWVQDvz/Eyc6QJbGfE7NrR3fx5BpEHMZsEHoIxHL1j+lKdGobr8ovEyqeNkPLSKp6SCSOt7gmw==} hasBin: true @@ -6294,10 +6032,10 @@ packages: engines: {node: '>=8'} dev: true - /type-fest@1.4.0: - resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} - engines: {node: '>=10'} - dev: false + /type-fest@4.2.0: + resolution: {integrity: sha512-5zknd7Dss75pMSED270A1RQS3KloqRJA9XbXLe0eCxyw7xXFb3rd+9B0UQ/0E+LQT6lnrLviEolYORlRWamn4w==} + engines: {node: '>=16'} + dev: true /typed-array-buffer@1.0.0: resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} @@ -6349,11 +6087,6 @@ packages: hasBin: true dev: true - /typical@4.0.0: - resolution: {integrity: sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==} - engines: {node: '>=8'} - dev: false - /ufo@1.2.0: resolution: {integrity: sha512-RsPyTbqORDNDxqAdQPQBpgqhWle1VcTSou/FraClYlHf6TZnQcGslpLcAphNR+sQW4q5lLWLbOsRlh9j24baQg==} dev: true @@ -6663,15 +6396,6 @@ packages: strip-ansi: 6.0.1 dev: true - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 - dev: false - /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} dev: true