diff --git a/.yarnrc.yml b/.yarnrc.yml index 8287ab6d..99f42fa6 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -9,5 +9,7 @@ plugins: spec: "@yarnpkg/plugin-workspace-tools" - path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs spec: "@yarnpkg/plugin-interactive-tools" + - path: .yarn/plugins/@yarnpkg/plugin-typescript.cjs + spec: "@yarnpkg/plugin-typescript" yarnPath: .yarn/releases/yarn-3.3.0.cjs diff --git a/README.md b/README.md index a6b936d5..d3bd001e 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ yarn moker add --template cra client - [`cra` _repo or workspace_](#cra-_repo-or-workspace_) - [`express` _repo or workspace_](#express-_repo-or-workspace_) - [`lib` _repo or workspace_](#lib-_repo-or-workspace_) +- [Commands](#commands) - [Contributing](#contributing) - [Roadmap](#roadmap) - [Development](#development) @@ -287,6 +288,10 @@ Scaffolds a simple [express](https://expressjs.com) HTTP app with the A plain shared library template with the [typescript](#typescript-workspace) and [jest](#jest-workspace) plugins. +# Commands + +See `moker --help` for a list of available commands. + # Contributing Contributions are very welcome! diff --git a/TODO.md b/TODO.md index 9a2b9a10..e505dad8 100644 --- a/TODO.md +++ b/TODO.md @@ -1,7 +1,6 @@ ### TODOs -| Filename | line # | TODO | -| :------------------------------------------------------------------------- | :----: | :------------------------------------------------------------ | -| [packages/core/src/yarnrc.ts](packages/core/src/yarnrc.ts#L23) | 23 | etc, fix later | -| [packages/cli/src/commands/list.ts](packages/cli/src/commands/list.ts#L19) | 19 | list workspaces using https://yarnpkg.com/cli/workspaces/list | -| [packages/plugins/src/jest/jest.ts](packages/plugins/src/jest/jest.ts#L31) | 31 | install jest without ts-jest | +| Filename | line # | TODO | +| :------------------------------------------------------------------------- | :----: | :--------------------------- | +| [packages/core/src/yarnrc.ts](packages/core/src/yarnrc.ts#L23) | 23 | etc, fix later | +| [packages/plugins/src/jest/jest.ts](packages/plugins/src/jest/jest.ts#L31) | 31 | install jest without ts-jest | diff --git a/packages/cli/package.json b/packages/cli/package.json index 9f9fc5db..08880d75 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -15,7 +15,7 @@ ], "scripts": { "start": "node moker.js", - "prepublish": "yarn clean && yarn build && cp ../../README.md .", + "prepublish": "yarn build && cp ../../README.md .", "clean": "rm -rf dist && rm -rf types", "build": "yarn clean && tsc", "build:watch": "tsc --watch" @@ -27,7 +27,12 @@ "bandersnatch": "1.11.1" }, "devDependencies": { - "@types/node": "18.11.12", + "@types/node": "18.11.13", "typescript": "4.9.4" + }, + "moker": { + "plugins": [ + "typescript" + ] } } diff --git a/packages/cli/src/commands/add.ts b/packages/cli/src/commands/add.ts index 8b950732..b5468aae 100644 --- a/packages/cli/src/commands/add.ts +++ b/packages/cli/src/commands/add.ts @@ -1,13 +1,12 @@ -import { - addWorkspace, - applyTemplate, - installPlugin, - isMonorepo, - loadAllPlugins, - runDependencyQueues, - task, -} from "@mokr/core"; +import { addWorkspace, applyTemplate, isMonorepo, task } from "@mokr/core"; import { command } from "bandersnatch"; +import { resolve } from "node:path"; +import { + addPlugin, + format, + loadPlugins, + updateDependencies, +} from "../tasks.js"; export const add = command("add") .description("Add a workspace to a monorepo") @@ -30,14 +29,16 @@ export const add = command("add") default: process.cwd(), }) .action(async ({ name, template, plugin, cwd }) => { - if (!(await isMonorepo({ directory: cwd }))) { + const directory = resolve(cwd); + + if (!(await isMonorepo({ directory }))) { throw new Error("Execute this command from within a monorepo"); } for (const workspaceName of name) { const workspaceDirectory = await task( `Add workspace ${workspaceName}`, - () => addWorkspace({ directory: cwd, name: workspaceName }) + () => addWorkspace({ directory, name: workspaceName }) ); if (template) { @@ -47,25 +48,13 @@ export const add = command("add") } for (const name of plugin) { - await task(`Add plugin ${name}`, () => - installPlugin({ directory: workspaceDirectory, name }) - ); + await addPlugin({ directory: workspaceDirectory, name }); } - await task(`Load plugins`, () => - loadAllPlugins({ directory: workspaceDirectory }) - ); - await task(`Update dependencies`, () => - runDependencyQueues({ directory: workspaceDirectory }) - ); + await loadPlugins({ directory: workspaceDirectory }); + + await updateDependencies({ directory: workspaceDirectory }); } - // await asyncForEach(name, async (name) => { - // const directory = path.join(monorepo.directory, "packages", name); - // const spinner = ora(`Creating workspace ${name}...`).start(); - // await new Workspace(monorepo, directory).create( - // workspace[template as keyof typeof workspace] - // ); - // spinner.succeed(`Created workspace ${name}`); - // }); + await format({ directory }); }); diff --git a/packages/cli/src/commands/create.ts b/packages/cli/src/commands/create.ts index d9bd7c28..3a9b079c 100644 --- a/packages/cli/src/commands/create.ts +++ b/packages/cli/src/commands/create.ts @@ -5,14 +5,17 @@ import { DEFAULT_LICENSE, DEFAULT_SCOPED, DEFAULT_WORKSPACES_DIRECTORY, - installPlugin, isReadableAndWritableDirectory, - loadAllPlugins, - runDependencyQueues, task, } from "@mokr/core"; import { command } from "bandersnatch"; import { resolve } from "node:path"; +import { + addPlugin, + format, + loadPlugins, + updateDependencies, +} from "../tasks.js"; export const create = command("create") .description("Create a new repo") @@ -73,11 +76,12 @@ export const create = command("create") } for (const name of plugin) { - await task(`Add plugin ${name}`, () => - installPlugin({ directory, name }) - ); + await addPlugin({ directory, name }); } - await task(`Load plugins`, () => loadAllPlugins({ directory })); - await task(`Update dependencies`, () => runDependencyQueues({ directory })); + await loadPlugins({ directory }); + + await updateDependencies({ directory }); + + await format({ directory }); }); diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index 32971c4d..da81e40a 100644 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -1,6 +1,7 @@ export * from "./add.js"; export * from "./create.js"; export * from "./list.js"; +export * from "./reinstall.js"; export * from "./reload.js"; export * from "./remove.js"; export * from "./use.js"; diff --git a/packages/cli/src/commands/list.ts b/packages/cli/src/commands/list.ts index 4a1c5700..ebd2bd1e 100644 --- a/packages/cli/src/commands/list.ts +++ b/packages/cli/src/commands/list.ts @@ -1,5 +1,6 @@ -import { getPlugins, listWorkspaces } from "@mokr/core"; +import { getPlugins, getWorkspaces } from "@mokr/core"; import { command } from "bandersnatch"; +import { resolve } from "node:path"; export const list = command("list") .description("List plugins and workspaces in a monorepo") @@ -8,15 +9,16 @@ export const list = command("list") default: process.cwd(), }) .action(async ({ cwd }) => { - const plugins = await getPlugins({ directory: cwd }); - const workspaces = await listWorkspaces({ directory: cwd }); + const directory = resolve(cwd); + + const plugins = await getPlugins({ directory }); + const workspaces = await getWorkspaces({ directory }); console.log( `Plugins: ${plugins.map((plugin) => `- ${plugin}\n`).join("")}` ); - // @todo: list workspaces using https://yarnpkg.com/cli/workspaces/list console.log( `Workspaces: ${workspaces.map(({ location, name }) => `- ${name} (${location})\n`).join("")}` diff --git a/packages/cli/src/commands/reinstall.ts b/packages/cli/src/commands/reinstall.ts new file mode 100644 index 00000000..8979a794 --- /dev/null +++ b/packages/cli/src/commands/reinstall.ts @@ -0,0 +1,70 @@ +import { + getPlugins, + getWorkspaces, + installPlugin, + isMonorepo, + loadAllPlugins, + logWarning, + task, +} from "@mokr/core"; +import { command } from "bandersnatch"; +import { resolve } from "node:path"; +import { REINSTALL_WARNING } from "../constants.js"; +import { format, updateDependencies } from "../tasks.js"; + +export const reinstall = command("reinstall") + .hidden() + .description("Reinstalls all plugins in the current directory") + .option("all", { + type: "boolean", + description: "Also reinstalls plugins of all workspaces in a monorepo", + }) + .option("cwd", { + description: "Directory to use as the current working directory", + default: process.cwd(), + }) + .action(async ({ all, cwd }) => { + const directory = resolve(cwd); + const plugins = await getPlugins({ directory }); + + for (const name of plugins) { + await task(`Reinstall plugin ${name}`, async () => { + await installPlugin({ directory, name }); + }); + } + + await task(`Load plugins`, () => loadAllPlugins({ directory })); + + if (all && (await isMonorepo({ directory }))) { + const workspaces = await getWorkspaces({ directory }); + + for (const workspace of workspaces) { + const workspaceDirectory = resolve(directory, workspace.location); + const plugins = await getPlugins({ directory: workspaceDirectory }); + + // Skip root + if (workspaceDirectory === directory) { + continue; + } + + for (const name of plugins) { + await task( + `Reinstall plugin ${name} of ${workspace.name}`, + async () => { + await installPlugin({ directory: workspaceDirectory, name }); + } + ); + } + + await task(`Load plugins of ${workspace.name}`, () => + loadAllPlugins({ directory }) + ); + } + } + + await updateDependencies({ directory }); + + await format({ directory }); + + logWarning(REINSTALL_WARNING); + }); diff --git a/packages/cli/src/commands/reload.ts b/packages/cli/src/commands/reload.ts index 48f9b19c..57d919a2 100644 --- a/packages/cli/src/commands/reload.ts +++ b/packages/cli/src/commands/reload.ts @@ -1,5 +1,6 @@ -import { loadAllPlugins, runDependencyQueues, task } from "@mokr/core"; import { command } from "bandersnatch"; +import { resolve } from "node:path"; +import { format, loadPlugins, updateDependencies } from "../tasks.js"; export const reload = command("reload") .hidden() @@ -9,8 +10,11 @@ export const reload = command("reload") default: process.cwd(), }) .action(async ({ cwd }) => { - await task(`Load plugins`, () => loadAllPlugins({ directory: cwd })); - await task(`Update dependencies`, () => - runDependencyQueues({ directory: cwd }) - ); + const directory = resolve(cwd); + + await loadPlugins({ directory }); + + await updateDependencies({ directory }); + + await format({ directory }); }); diff --git a/packages/cli/src/commands/remove/plugin.ts b/packages/cli/src/commands/remove/plugin.ts index 866a7b74..e8acc623 100644 --- a/packages/cli/src/commands/remove/plugin.ts +++ b/packages/cli/src/commands/remove/plugin.ts @@ -1,10 +1,7 @@ -import { - loadAllPlugins, - removePlugin, - runDependencyQueues, - task, -} from "@mokr/core"; +import { removePlugin, task } from "@mokr/core"; import { command } from "bandersnatch"; +import { resolve } from "node:path"; +import { format, loadPlugins, updateDependencies } from "../../tasks.js"; export const remove = command("plugin") .description("Remove a plugin from the monorepo or workspace") @@ -17,14 +14,17 @@ export const remove = command("plugin") default: process.cwd(), }) .action(async ({ name, cwd }) => { + const directory = resolve(cwd); + for (const pluginName of name) { await task(`Remove plugin ${pluginName}`, () => - removePlugin({ directory: cwd, name: pluginName }) + removePlugin({ directory, name: pluginName }) ); } - await task(`Load plugins`, () => loadAllPlugins({ directory: cwd })); - await task(`Update dependencies`, () => - runDependencyQueues({ directory: cwd }) - ); + await loadPlugins({ directory }); + + await updateDependencies({ directory }); + + await format({ directory }); }); diff --git a/packages/cli/src/commands/use.ts b/packages/cli/src/commands/use.ts index c4aa5566..3d053c73 100644 --- a/packages/cli/src/commands/use.ts +++ b/packages/cli/src/commands/use.ts @@ -1,14 +1,11 @@ -import { - hasPlugin, - installPlugin, - loadAllPlugins, - runDependencyQueues, - task, -} from "@mokr/core"; +import { hasPlugin, installPlugin, logWarning, task } from "@mokr/core"; import { command } from "bandersnatch"; +import { resolve } from "node:path"; +import { REINSTALL_WARNING } from "../constants.js"; +import { format, loadPlugins, updateDependencies } from "../tasks.js"; export const use = command("use") - .description("Add plugin to monorepo or workspace") + .description("Install plugin in repo or workspace") .argument("plugin", { description: "Plugin name", variadic: true, @@ -22,18 +19,25 @@ export const use = command("use") default: process.cwd(), }) .action(async ({ plugin, reinstall, cwd }) => { + const directory = resolve(cwd); + for (const name of plugin) { await task(`Add plugin ${name}`, async () => { - if (!reinstall && (await hasPlugin({ directory: cwd, name }))) { + if (!reinstall && (await hasPlugin({ directory, name }))) { throw new Error(`Plugin ${name} is already installed`); } - await installPlugin({ directory: cwd, name }); + await installPlugin({ directory, name }); }); } - await task(`Load plugins`, () => loadAllPlugins({ directory: cwd })); - await task(`Update dependencies`, () => - runDependencyQueues({ directory: cwd }) - ); + await loadPlugins({ directory }); + + await updateDependencies({ directory }); + + await format({ directory }); + + if (reinstall) { + logWarning(REINSTALL_WARNING); + } }); diff --git a/packages/cli/src/constants.ts b/packages/cli/src/constants.ts new file mode 100644 index 00000000..026d2007 --- /dev/null +++ b/packages/cli/src/constants.ts @@ -0,0 +1,2 @@ +export const REINSTALL_WARNING = + "Please verify the changes made by reinstalling the plugin(s) as they may have reverted changes you've made to the plugins defaults."; diff --git a/packages/cli/src/tasks.ts b/packages/cli/src/tasks.ts new file mode 100644 index 00000000..69671f2c --- /dev/null +++ b/packages/cli/src/tasks.ts @@ -0,0 +1,35 @@ +import { + exec, + hasPlugin, + installPlugin, + loadAllPlugins, + runDependencyQueues, + task, +} from "@mokr/core"; + +type DirOption = { + directory: string; +}; + +export async function format({ directory }: DirOption) { + if (await hasPlugin({ directory, name: "prettier" })) { + await task(`Format code`, () => + exec("yarn", ["format"], { cwd: directory }) + ); + } +} + +export async function addPlugin({ + directory, + name, +}: DirOption & { name: string }) { + await task(`Add plugin ${name}`, () => installPlugin({ directory, name })); +} + +export async function loadPlugins({ directory }: DirOption) { + await task(`Load plugins`, () => loadAllPlugins({ directory })); +} + +export async function updateDependencies({ directory }: DirOption) { + await task(`Update dependencies`, () => runDependencyQueues({ directory })); +} diff --git a/packages/core/package.json b/packages/core/package.json index 125cc8b2..b45a4a0c 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -32,14 +32,15 @@ }, "devDependencies": { "@types/jest": "29.2.4", - "@types/node": "18.11.12", + "@types/node": "18.11.13", "jest": "29.3.1", "ts-jest": "29.0.3", "typescript": "4.9.4" }, "moker": { "plugins": [ - "jest" + "jest", + "typescript" ] } } diff --git a/packages/core/src/yarn.ts b/packages/core/src/yarn.ts index 5da50d86..876f129b 100644 --- a/packages/core/src/yarn.ts +++ b/packages/core/src/yarn.ts @@ -176,7 +176,7 @@ export async function runDependencyQueues({ directory }: DirOption) { } } -export async function listWorkspaces({ directory }: DirOption) { +export async function getWorkspaces({ directory }: DirOption) { const { stdout } = await exec("yarn", ["workspaces", "list", "--json"], { cwd: directory, }); diff --git a/packages/plugins/src/typescript/typescript.ts b/packages/plugins/src/typescript/typescript.ts index 4e93169a..77837f00 100644 --- a/packages/plugins/src/typescript/typescript.ts +++ b/packages/plugins/src/typescript/typescript.ts @@ -73,10 +73,10 @@ async function install({ directory }: PluginArgs) { types: "types/index.d.ts", files: ["dist", "types"], scripts: { - prepublish: "yarn build", clean: "rm -rf dist && rm -rf types", build: "yarn clean && tsc", "build:watch": "tsc --watch", + prepublish: "yarn build", }, }, }); diff --git a/yarn.lock b/yarn.lock index edf9e52c..0e182b61 100644 --- a/yarn.lock +++ b/yarn.lock @@ -736,7 +736,7 @@ __metadata: resolution: "@mokr/core@workspace:packages/core" dependencies: "@types/jest": 29.2.4 - "@types/node": 18.11.12 + "@types/node": 18.11.13 chalk: 5.2.0 deepmerge: 4.2.2 jest: 29.3.1 @@ -1659,6 +1659,13 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:18.11.13": + version: 18.11.13 + resolution: "@types/node@npm:18.11.13" + checksum: b0c1aa3bd2f5df8240e61096a49d6d4be600109b824d23408ec4ba1ec057dc0c60588e09f73b8a60455ad26d367e9c5562fad8403099f885cbc7b4cace83ec4c + languageName: node + linkType: hard + "@types/normalize-package-data@npm:^2.4.0, @types/normalize-package-data@npm:^2.4.1": version: 2.4.1 resolution: "@types/normalize-package-data@npm:2.4.1" @@ -5921,7 +5928,7 @@ __metadata: "@mokr/core": "workspace:*" "@mokr/plugins": "workspace:*" "@mokr/templates": "workspace:*" - "@types/node": 18.11.12 + "@types/node": 18.11.13 bandersnatch: 1.11.1 typescript: 4.9.4 bin: