From 83e79b447fc614ed62e34dfc03d4b3237861683d Mon Sep 17 00:00:00 2001 From: Corbin Crutchley Date: Mon, 10 Aug 2026 19:32:30 -0700 Subject: [PATCH] feat: add initial tempblot CLI --- packages/compiler/bin/tempblot.ts | 45 ++++++++++++++++++++++++ packages/compiler/package.json | 5 +++ packages/compiler/tsconfig.app.json | 2 +- packages/compiler/vite.config.ts | 14 ++++++-- pnpm-lock.yaml | 54 +++++++++++++++++++++++++++++ 5 files changed, 117 insertions(+), 3 deletions(-) create mode 100755 packages/compiler/bin/tempblot.ts diff --git a/packages/compiler/bin/tempblot.ts b/packages/compiler/bin/tempblot.ts new file mode 100755 index 0000000..6e45f16 --- /dev/null +++ b/packages/compiler/bin/tempblot.ts @@ -0,0 +1,45 @@ +#!/usr/bin/env node +import { cloneTemplate, spawnSafe } from "@tempblot/utils" +import t from '@bomb.sh/tab'; +import { parse } from "@bomb.sh/args"; +import { text, isCancel } from '@clack/prompts'; +import * as path from 'node:path'; +import * as fs from 'node:fs'; + +// tempblot get --url +const getCmd = t.command('get', 'Get a template from a git repository'); +getCmd.option('url', 'Specify the git repository URL', (complete) => { + complete('https://github.com/crutchcorn/tempblot.git', 'Default repository'); +}); + +const argv = process.argv.slice(2); +const args = parse(argv, { + string: ['url'], +}); + +const url = args.url || await text({ + message: 'What is the URL of the git repository?', + placeholder: 'https://github.com/crutchcorn/tempblot.git', +}) as string; + +if (isCancel(url)) { + console.log('Operation cancelled.'); + process.exit(0); +} + +const {tmpPath} = await cloneTemplate({ url }); + +const configPath = path.resolve(tmpPath, "tempblot.config.ts"); + +if (!fs.existsSync(configPath)) { + console.error(`Configuration file not found at ${configPath}`); + process.exit(1); +} + +const {new_child_process} = spawnSafe({file: configPath, defaultFSPaths: [process.cwd(), tmpPath]}) + +new_child_process.stdout.pipe(process.stdout); +new_child_process.stderr.pipe(process.stderr); +new_child_process.on('exit', (code) => { + process.exit(code || 0); +}); \ No newline at end of file diff --git a/packages/compiler/package.json b/packages/compiler/package.json index 448b733..7bbdd7f 100644 --- a/packages/compiler/package.json +++ b/packages/compiler/package.json @@ -10,6 +10,7 @@ "url": "git+https://github.com/crutchcorn/tempblot.git", "directory": "packages/compiler" }, + "bin": "dist/bin/tempblot.js", "funding": { "type": "github", "url": "https://github.com/sponsors/crutchcorn" @@ -33,7 +34,11 @@ "test:eslint": "eslint ." }, "dependencies": { + "@bomb.sh/args": "^0.3.1", + "@bomb.sh/tab": "^0.0.22", + "@clack/prompts": "^1.7.0", "@tempblot/parser": "workspace:^", + "@tempblot/utils": "workspace:^", "typescript": "^6.0.3" }, "devDependencies": { diff --git a/packages/compiler/tsconfig.app.json b/packages/compiler/tsconfig.app.json index f8e4107..28fd90a 100644 --- a/packages/compiler/tsconfig.app.json +++ b/packages/compiler/tsconfig.app.json @@ -1,4 +1,4 @@ { "extends": "@tempblot/config/tsconfig.json", - "include": ["src"] + "include": ["src", "bin"] } diff --git a/packages/compiler/vite.config.ts b/packages/compiler/vite.config.ts index a2bd9f5..ad82ffe 100644 --- a/packages/compiler/vite.config.ts +++ b/packages/compiler/vite.config.ts @@ -1,3 +1,4 @@ +import { chmodSync } from "node:fs"; import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; import { defineConfig } from "vite"; @@ -11,7 +12,14 @@ export default defineConfig(({ mode }) => ({ dts({ tsconfigPath: "tsconfig.app.json", entryRoot: "src", + include: ["src"], }), + { + name: "executable-bin", + closeBundle() { + chmodSync(resolve(__dirname, "dist/bin/tempblot.js"), 0o755); + }, + }, ], resolve: { alias: { @@ -21,8 +29,10 @@ export default defineConfig(({ mode }) => ({ build: { lib: { name: "Tempblot", - fileName: "index", - entry: resolve(__dirname, "src/index.ts"), + entry: { + index: resolve(__dirname, "src/index.ts"), + "bin/tempblot": resolve(__dirname, "bin/tempblot.ts"), + }, formats: ["es"], }, rollupOptions: { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 08ff39d..1db5f43 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -111,9 +111,21 @@ importers: packages/compiler: dependencies: + '@bomb.sh/args': + specifier: ^0.3.1 + version: 0.3.1 + '@bomb.sh/tab': + specifier: ^0.0.22 + version: 0.0.22 + '@clack/prompts': + specifier: ^1.7.0 + version: 1.7.0 '@tempblot/parser': specifier: workspace:^ version: link:../parser + '@tempblot/utils': + specifier: workspace:^ + version: link:../utils typescript: specifier: ^6.0.3 version: 6.0.3 @@ -473,6 +485,24 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} + '@bomb.sh/args@0.3.1': + resolution: {integrity: sha512-CwxKrfgcorUPP6KfYD59aRdBYWBTsfsxT+GmoLVnKo5Tmyoqbpo0UNcjngRMyU+6tiPbd18RuIYxhgAn44wU/Q==} + + '@bomb.sh/tab@0.0.22': + resolution: {integrity: sha512-l5IuWpV7szqG4MM6A7I+qPMmP2qPMq2TD4veIXaOH0sD53dV0Tv8WZPARp5O5Kp4+y4fnVCl3VL1HZKNghO1yg==} + hasBin: true + peerDependencies: + cac: ^6.7.14 || ^7.0.0 + citty: ^0.1.6 || ^0.2.0 + commander: ^13.1.0 || ^14.0.0 || ^15.0.0 + peerDependenciesMeta: + cac: + optional: true + citty: + optional: true + commander: + optional: true + '@braidai/lang@1.1.2': resolution: {integrity: sha512-qBcknbBufNHlui137Hft8xauQMTZDKdophmLFv05r2eNmdIv/MlPuP4TdUknHG68UdWLgVZwgxVe735HzJNIwA==} @@ -484,10 +514,18 @@ packages: resolution: {integrity: sha512-fT1qHVGAag4IEkrupZ6lRRbNCs1vS9P01KB/sG8zKgvUztbYtFBtQpjSITNwooDZ83tpsPzP0mRNs1/KVszCRA==} engines: {node: '>= 20.12.0'} + '@clack/core@1.4.3': + resolution: {integrity: sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ==} + engines: {node: '>= 20.12.0'} + '@clack/prompts@1.4.0': resolution: {integrity: sha512-S0My7XPGIgpRWMDG8uRqalbgT+a6FmCUdOW+HaIOVVpUPHOb7RrpvjTjiODadKp06fsrVDJZlIzc6yCTp4AnxA==} engines: {node: '>= 20.12.0'} + '@clack/prompts@1.7.0': + resolution: {integrity: sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A==} + engines: {node: '>= 20.12.0'} + '@colors/colors@1.5.0': resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} @@ -4889,6 +4927,10 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@bomb.sh/args@0.3.1': {} + + '@bomb.sh/tab@0.0.22': {} + '@braidai/lang@1.1.2': {} '@capsizecss/unpack@4.0.0': @@ -4900,6 +4942,11 @@ snapshots: fast-wrap-ansi: 0.2.0 sisteransi: 1.0.5 + '@clack/core@1.4.3': + dependencies: + fast-wrap-ansi: 0.2.0 + sisteransi: 1.0.5 + '@clack/prompts@1.4.0': dependencies: '@clack/core': 1.3.1 @@ -4907,6 +4954,13 @@ snapshots: fast-wrap-ansi: 0.2.0 sisteransi: 1.0.5 + '@clack/prompts@1.7.0': + dependencies: + '@clack/core': 1.4.3 + fast-string-width: 3.0.2 + fast-wrap-ansi: 0.2.0 + sisteransi: 1.0.5 + '@colors/colors@1.5.0': optional: true -- 2.51.2