diff --git a/bun.lockb b/bun.lockb index 8ee27b9..82e44da 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/lib/main.ts b/lib/main.ts index 966e94e..2554d2e 100644 --- a/lib/main.ts +++ b/lib/main.ts @@ -1,6 +1,7 @@ import { relative, resolve } from "node:path"; +import { basename } from "node:path"; import { select } from "@inquirer/prompts"; -import { $ } from "bun"; +import { $, main as entrypoint } from "bun"; import chalk from "chalk"; import { capitalCase } from "change-case"; import yargs from "yargs"; @@ -17,65 +18,116 @@ import { createGenerator } from "./utils/generator"; import { labelElementByName } from "./utils/labels"; import { getWorkspaceJson, getWorkspacePath } from "./utils/workspace"; -const args = await yargs(hideBin(process.argv)) - .version("version", "Show current tool version", pkg.version) - .usage( - `${capitalCase( - pkg.name, - )}: Create a Structurizr DSL scaffolding in seconds!`, - ) - .option("dest", { - default: ".", - desc: "Target architecture folder", - }) - .option("export", { - alias: "e", - type: "boolean", - default: false, - desc: "Use structurizr-cli to export the workspace to JSON", - }).argv; - -console.log( - chalk.bold(` -Welcome to ${chalk.cyan(capitalCase(pkg.name))} +type CLIArguments = { + dest: string; + version?: boolean; + export?: boolean; +}; + +async function main(args: CLIArguments = { dest: "." }) { + console.log( + chalk.bold(` +Welcome to ${chalk.cyan(capitalCase(pkg.name.replace(/@[a-z-]*\//, "")))} Create a Structurizr DSL scaffolding in seconds! `), -); + ); -const destPath = resolve(process.cwd(), args.dest); -const workspacePath = getWorkspacePath(destPath); + const destPath = resolve(process.cwd(), args.dest); + const workspacePath = getWorkspacePath(destPath); -const exportWorkspace = async (path: string) => { - if (!args.export) return; - const workspacePath = getWorkspacePath(path); - if (!workspacePath) return; + const exportWorkspace = async (path: string) => { + if (!args.export) return; + const workspacePath = getWorkspacePath(path); + if (!workspacePath) return; - // TODO: Make it compatible for Windows - return $`structurizr-cli export -w ${workspacePath}/workspace.dsl -f json -o ${workspacePath} || true`; -}; + // TODO: Make it compatible for Windows + return $`structurizr-cli export -w ${workspacePath}/workspace.dsl -f json -o ${workspacePath} || true`; + }; -const { workspaceGenerator, ...otherGenerators } = generators; + const { workspaceGenerator, ...otherGenerators } = generators; -if (!workspacePath) { - console.log(`${chalk.yellow( - 'It seems the folder you selected does not have a "workspace.dsl" file.', - )} + if (!workspacePath) { + console.log(`${chalk.yellow( + 'It seems the folder you selected does not have a "workspace.dsl" file.', + )} Destination folder: ${chalk.blue( - relative(process.cwd(), destPath) || process.cwd(), - )} + relative(process.cwd(), destPath) || process.cwd(), + )} Let's create a new one by answering the questions below. `); + try { + const generator: Generator> = + { + ...workspaceGenerator, + templates, + destPath, + }; + + await createGenerator(generator); + await exportWorkspace( + relative(process.cwd(), destPath) || process.cwd(), + ); + process.exit(0); + } catch (err) { + console.error(err); + process.exit(1); + } + } + + const workspaceInfo = await getWorkspaceJson( + getWorkspacePath(workspacePath), + ); + + console.log( + chalk.gray(`Workspace name: ${chalk.cyan(workspaceInfo?.name)}`), + ); + console.log( + chalk.gray( + `Architecture folder: ${chalk.cyan( + relative(process.cwd(), workspacePath), + )}\n`, + ), + ); + + const DEFAULT_GENERATOR_SORTING = [ + "Workspace", + "Constant", + "System", + "Person", + "External System", + "Container", + "Component", + "View", + "Relationship", + ]; + + const element = await select({ + message: "Create a new element:", + choices: Object.values(otherGenerators) + .map((g) => ({ + name: `${labelElementByName(g.name)} ${g.name}`, + value: g, + })) + .toReversed() + .toSorted((a, b) => { + const aIndex = DEFAULT_GENERATOR_SORTING.indexOf(a.value.name); + const bIndex = DEFAULT_GENERATOR_SORTING.indexOf(b.value.name); + + return aIndex - bIndex; + }), + }); + + type GeneratorAnswers = GetAnswers; + try { - const generator: Generator> = { - ...workspaceGenerator, + const generator: Generator = { + ...(element as GeneratorDefinition), templates, destPath, }; await createGenerator(generator); - await exportWorkspace( - relative(process.cwd(), destPath) || process.cwd(), - ); + await exportWorkspace(relative(process.cwd(), workspacePath)); process.exit(0); } catch (err) { console.error(err); @@ -83,58 +135,26 @@ Let's create a new one by answering the questions below. } } -const workspaceInfo = await getWorkspaceJson(getWorkspacePath(workspacePath)); - -console.log(chalk.gray(`Workspace name: ${chalk.cyan(workspaceInfo?.name)}`)); -console.log( - chalk.gray( - `Architecture folder: ${chalk.cyan( - relative(process.cwd(), workspacePath), - )}\n`, - ), -); - -const DEFAULT_GENERATOR_SORTING = [ - "Workspace", - "Constant", - "System", - "Person", - "External System", - "Container", - "Component", - "View", - "Relationship", -]; - -const element = await select({ - message: "Create a new element:", - choices: Object.values(otherGenerators) - .map((g) => ({ - name: `${labelElementByName(g.name)} ${g.name}`, - value: g, - })) - .toReversed() - .toSorted((a, b) => { - const aIndex = DEFAULT_GENERATOR_SORTING.indexOf(a.value.name); - const bIndex = DEFAULT_GENERATOR_SORTING.indexOf(b.value.name); - - return aIndex - bIndex; - }), -}); - -type GeneratorAnswers = GetAnswers; - -try { - const generator: Generator = { - ...(element as GeneratorDefinition), - templates, - destPath, - }; - - await createGenerator(generator); - await exportWorkspace(relative(process.cwd(), workspacePath)); - process.exit(0); -} catch (err) { - console.error(err); - process.exit(1); +export default main; + +if (["main.ts", "scfz"].includes(basename(entrypoint))) { + const args: CLIArguments = await yargs(hideBin(process.argv)) + .version("version", "Show current tool version", pkg.version) + .usage( + `${capitalCase( + pkg.name, + )}: Create a Structurizr DSL scaffolding in seconds!`, + ) + .option("dest", { + default: ".", + desc: "Target architecture folder", + }) + .option("export", { + alias: "e", + type: "boolean", + default: false, + desc: "Use structurizr-cli to export the workspace to JSON", + }).argv; + + main(args); } diff --git a/package.json b/package.json index 73df29b..3120769 100644 --- a/package.json +++ b/package.json @@ -8,14 +8,14 @@ }, "scripts": { "build:dev": "bun build ./lib/main.ts --compile --watch --outfile ./dist/scfz", - "test:dev": "bun test --watch --coverage", + "test:dev": "bun test --watch", "test": "bun test", "test:ci": "bun test --coverage", "prepare": "husky" }, "trustedDependencies": [".", "@biomejs/biome"], "dependencies": { - "@inquirer/prompts": "^6.0.1", + "@inquirer/prompts": "^7.0.0", "chalk": "^5.3.0", "change-case": "^5.4.4", "handlebars": "^4.7.8", @@ -26,6 +26,7 @@ "@biomejs/biome": "^1.9.3", "@commitlint/cli": "^19.5.0", "@commitlint/config-conventional": "^19.4.1", + "@inquirer/testing": "^2.1.37", "@inquirer/type": "^1.5.5", "@types/bun": "^1.1.10", "@types/inquirer": "^9.0.7",