@baton-dx/cli 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -0
- package/dist/agent-detection-BW5-jGuR.mjs +4 -0
- package/dist/agent-detection-C5gaTtah.mjs +501 -0
- package/dist/agent-detection-C5gaTtah.mjs.map +1 -0
- package/dist/chunk-BbwQpWto.mjs +33 -0
- package/dist/context-detection-mMNLg_4F.mjs +9841 -0
- package/dist/context-detection-mMNLg_4F.mjs.map +1 -0
- package/dist/{create-CqfUSGj7.mjs → create-Diqnd3ci.mjs} +15 -15
- package/dist/create-Diqnd3ci.mjs.map +1 -0
- package/dist/esm-BagM-kVd.mjs +4526 -0
- package/dist/esm-BagM-kVd.mjs.map +1 -0
- package/dist/esm-CuRZ1S4C.mjs +4 -0
- package/dist/execa-RdtdAT4S.mjs +6343 -0
- package/dist/execa-RdtdAT4S.mjs.map +1 -0
- package/dist/index.mjs +290 -291
- package/dist/index.mjs.map +1 -1
- package/dist/{list-o76RXPxE.mjs → list-B5xUVBTU.mjs} +9 -10
- package/dist/{list-o76RXPxE.mjs.map → list-B5xUVBTU.mjs.map} +1 -1
- package/dist/prompt-CPT4cDau.mjs +849 -0
- package/dist/prompt-CPT4cDau.mjs.map +1 -0
- package/dist/{remove-BB883RDx.mjs → remove-6S8F9xcE.mjs} +15 -17
- package/dist/remove-6S8F9xcE.mjs.map +1 -0
- package/dist/src-Dh0ZvHbV.mjs +14434 -0
- package/dist/src-Dh0ZvHbV.mjs.map +1 -0
- package/package.json +5 -3
- package/dist/context-detection-0m8_Fp0j.mjs +0 -45
- package/dist/context-detection-0m8_Fp0j.mjs.map +0 -1
- package/dist/create-CqfUSGj7.mjs.map +0 -1
- package/dist/remove-BB883RDx.mjs.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@baton-dx/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "CLI for Baton - the package manager for Developer Experience & AI configuration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.mjs",
|
|
@@ -22,9 +22,11 @@
|
|
|
22
22
|
],
|
|
23
23
|
"scripts": {
|
|
24
24
|
"build": "tsdown",
|
|
25
|
-
"typecheck": "tsc --noEmit"
|
|
25
|
+
"typecheck": "tsc --noEmit",
|
|
26
|
+
"prepack": "cp ../../README.md ."
|
|
26
27
|
},
|
|
27
|
-
"dependencies": {
|
|
28
|
+
"dependencies": {},
|
|
29
|
+
"devDependencies": {
|
|
28
30
|
"@baton-dx/agent-paths": "workspace:*",
|
|
29
31
|
"@baton-dx/core": "workspace:*",
|
|
30
32
|
"@clack/prompts": "^1.0.1",
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { access } from "node:fs/promises";
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
4
|
-
|
|
5
|
-
//#region src/utils/context-detection.ts
|
|
6
|
-
/**
|
|
7
|
-
* Check if the current directory is a source repository
|
|
8
|
-
* A source repository contains a baton.source.yaml file in the root
|
|
9
|
-
* @param cwd - Current working directory (defaults to process.cwd())
|
|
10
|
-
* @returns true if baton.source.yaml exists in cwd, false otherwise
|
|
11
|
-
*/
|
|
12
|
-
async function isInSourceRepo(cwd = process.cwd()) {
|
|
13
|
-
const manifestPath = join(cwd, "baton.source.yaml");
|
|
14
|
-
try {
|
|
15
|
-
await access(manifestPath);
|
|
16
|
-
return true;
|
|
17
|
-
} catch {
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Find the source repository root by searching upwards from cwd
|
|
23
|
-
* Checks the current directory and all parent directories for baton.source.yaml
|
|
24
|
-
* @param cwd - Starting directory (defaults to process.cwd())
|
|
25
|
-
* @param options.fallbackToStart - If true, return cwd instead of null when not found
|
|
26
|
-
* @returns The absolute path to the source root, or null (or cwd) if not found
|
|
27
|
-
*/
|
|
28
|
-
async function findSourceRoot(cwd = process.cwd(), options) {
|
|
29
|
-
let current = cwd;
|
|
30
|
-
while (true) {
|
|
31
|
-
const manifestPath = join(current, "baton.source.yaml");
|
|
32
|
-
try {
|
|
33
|
-
await access(manifestPath);
|
|
34
|
-
return current;
|
|
35
|
-
} catch {
|
|
36
|
-
const parent = dirname(current);
|
|
37
|
-
if (parent === current) return options?.fallbackToStart ? cwd : null;
|
|
38
|
-
current = parent;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
//#endregion
|
|
44
|
-
export { isInSourceRepo as n, findSourceRoot as t };
|
|
45
|
-
//# sourceMappingURL=context-detection-0m8_Fp0j.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"context-detection-0m8_Fp0j.mjs","names":[],"sources":["../src/utils/context-detection.ts"],"sourcesContent":["import { access } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\n/**\n * Check if the current directory is a source repository\n * A source repository contains a baton.source.yaml file in the root\n * @param cwd - Current working directory (defaults to process.cwd())\n * @returns true if baton.source.yaml exists in cwd, false otherwise\n */\nexport async function isInSourceRepo(cwd: string = process.cwd()): Promise<boolean> {\n const manifestPath = join(cwd, \"baton.source.yaml\");\n\n try {\n await access(manifestPath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Find the source repository root by searching upwards from cwd\n * Checks the current directory and all parent directories for baton.source.yaml\n * @param cwd - Starting directory (defaults to process.cwd())\n * @param options.fallbackToStart - If true, return cwd instead of null when not found\n * @returns The absolute path to the source root, or null (or cwd) if not found\n */\nexport async function findSourceRoot(\n cwd: string = process.cwd(),\n options?: { fallbackToStart?: boolean },\n): Promise<string | null> {\n let current = cwd;\n\n while (true) {\n const manifestPath = join(current, \"baton.source.yaml\");\n try {\n await access(manifestPath);\n return current;\n } catch {\n const parent = dirname(current);\n if (parent === current) {\n return options?.fallbackToStart ? cwd : null;\n }\n current = parent;\n }\n }\n}\n"],"mappings":";;;;;;;;;;;AASA,eAAsB,eAAe,MAAc,QAAQ,KAAK,EAAoB;CAClF,MAAM,eAAe,KAAK,KAAK,oBAAoB;AAEnD,KAAI;AACF,QAAM,OAAO,aAAa;AAC1B,SAAO;SACD;AACN,SAAO;;;;;;;;;;AAWX,eAAsB,eACpB,MAAc,QAAQ,KAAK,EAC3B,SACwB;CACxB,IAAI,UAAU;AAEd,QAAO,MAAM;EACX,MAAM,eAAe,KAAK,SAAS,oBAAoB;AACvD,MAAI;AACF,SAAM,OAAO,aAAa;AAC1B,UAAO;UACD;GACN,MAAM,SAAS,QAAQ,QAAQ;AAC/B,OAAI,WAAW,QACb,QAAO,SAAS,kBAAkB,MAAM;AAE1C,aAAU"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"create-CqfUSGj7.mjs","names":[],"sources":["../src/commands/profile/create.ts"],"sourcesContent":["import { mkdir, readFile, readdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { KEBAB_CASE_REGEX } from \"@baton-dx/core\";\nimport * as p from \"@clack/prompts\";\nimport { defineCommand } from \"citty\";\nimport Handlebars from \"handlebars\";\nimport { findSourceRoot } from \"../../utils/context-detection.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nexport const createCommand = defineCommand({\n meta: {\n name: \"create\",\n description: \"Create a new profile in your source repository\",\n },\n args: {\n name: {\n type: \"positional\",\n description: \"Profile name (kebab-case)\",\n required: false,\n },\n },\n async run({ args }) {\n p.intro(\"Create Profile\");\n\n // Check for baton.source.yaml in current or parent directories\n const sourceRoot = await findSourceRoot();\n if (!sourceRoot) {\n p.cancel(\"This command must be run inside a source directory (baton.source.yaml not found)\");\n process.exit(1);\n }\n\n // Get profile name — from argument or wizard prompt\n let name = args.name as string | undefined;\n\n if (!name) {\n const nameInput = await p.text({\n message: \"Profile name (kebab-case)\",\n placeholder: \"e.g., backend, frontend, my-profile\",\n validate(value) {\n if (!value || value.trim().length === 0) {\n return \"Profile name is required\";\n }\n if (!KEBAB_CASE_REGEX.test(value.trim())) {\n return \"Profile name must be in kebab-case (e.g., my-profile, backend, frontend)\";\n }\n },\n });\n\n if (p.isCancel(nameInput)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n name = (nameInput as string).trim();\n }\n\n // Validate name format (kebab-case)\n if (!KEBAB_CASE_REGEX.test(name)) {\n p.cancel(\"Profile name must be in kebab-case (e.g., my-profile, backend, frontend)\");\n process.exit(1);\n }\n\n // Check if profile already exists in profiles/ directory\n const targetDir = join(sourceRoot, \"profiles\", name);\n try {\n await readdir(targetDir);\n p.cancel(`Profile '${name}' already exists in profiles/${name}/`);\n process.exit(1);\n } catch {\n // Directory doesn't exist - good to proceed\n }\n\n // Create profile directory\n await mkdir(targetDir, { recursive: true });\n\n // Copy minimal template files\n const templateDir = join(__dirname, \"../src/templates/profile\", \"minimal\");\n await copyProfileTemplate(templateDir, targetDir, { name });\n\n p.outro(`Profile '${name}' created in profiles/${name}/`);\n },\n});\n\n/**\n * Recursively copy profile template with variable substitution\n */\nasync function copyProfileTemplate(\n sourceDir: string,\n targetDir: string,\n variables: { name: string },\n): Promise<void> {\n const entries = await readdir(sourceDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const sourcePath = join(sourceDir, entry.name);\n const targetPath = join(targetDir, entry.name);\n\n if (entry.isDirectory()) {\n await mkdir(targetPath, { recursive: true });\n await copyProfileTemplate(sourcePath, targetPath, variables);\n } else {\n // Read file content\n const content = await readFile(sourcePath, \"utf-8\");\n\n // Apply Handlebars substitution for text files\n const processed = Handlebars.compile(content, { noEscape: true })(variables);\n\n // Write processed content\n await writeFile(targetPath, processed, \"utf-8\");\n }\n }\n}\n"],"mappings":";;;;;;;;;;;AASA,MAAM,YAAY,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;AAEzD,MAAa,gBAAgB,cAAc;CACzC,MAAM;EACJ,MAAM;EACN,aAAa;EACd;CACD,MAAM,EACJ,MAAM;EACJ,MAAM;EACN,aAAa;EACb,UAAU;EACX,EACF;CACD,MAAM,IAAI,EAAE,QAAQ;AAClB,IAAE,MAAM,iBAAiB;EAGzB,MAAM,aAAa,MAAM,gBAAgB;AACzC,MAAI,CAAC,YAAY;AACf,KAAE,OAAO,mFAAmF;AAC5F,WAAQ,KAAK,EAAE;;EAIjB,IAAI,OAAO,KAAK;AAEhB,MAAI,CAAC,MAAM;GACT,MAAM,YAAY,MAAM,EAAE,KAAK;IAC7B,SAAS;IACT,aAAa;IACb,SAAS,OAAO;AACd,SAAI,CAAC,SAAS,MAAM,MAAM,CAAC,WAAW,EACpC,QAAO;AAET,SAAI,CAAC,iBAAiB,KAAK,MAAM,MAAM,CAAC,CACtC,QAAO;;IAGZ,CAAC;AAEF,OAAI,EAAE,SAAS,UAAU,EAAE;AACzB,MAAE,OAAO,aAAa;AACtB,YAAQ,KAAK,EAAE;;AAGjB,UAAQ,UAAqB,MAAM;;AAIrC,MAAI,CAAC,iBAAiB,KAAK,KAAK,EAAE;AAChC,KAAE,OAAO,2EAA2E;AACpF,WAAQ,KAAK,EAAE;;EAIjB,MAAM,YAAY,KAAK,YAAY,YAAY,KAAK;AACpD,MAAI;AACF,SAAM,QAAQ,UAAU;AACxB,KAAE,OAAO,YAAY,KAAK,+BAA+B,KAAK,GAAG;AACjE,WAAQ,KAAK,EAAE;UACT;AAKR,QAAM,MAAM,WAAW,EAAE,WAAW,MAAM,CAAC;AAI3C,QAAM,oBADc,KAAK,WAAW,4BAA4B,UAAU,EACnC,WAAW,EAAE,MAAM,CAAC;AAE3D,IAAE,MAAM,YAAY,KAAK,wBAAwB,KAAK,GAAG;;CAE5D,CAAC;;;;AAKF,eAAe,oBACb,WACA,WACA,WACe;CACf,MAAM,UAAU,MAAM,QAAQ,WAAW,EAAE,eAAe,MAAM,CAAC;AAEjE,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,aAAa,KAAK,WAAW,MAAM,KAAK;EAC9C,MAAM,aAAa,KAAK,WAAW,MAAM,KAAK;AAE9C,MAAI,MAAM,aAAa,EAAE;AACvB,SAAM,MAAM,YAAY,EAAE,WAAW,MAAM,CAAC;AAC5C,SAAM,oBAAoB,YAAY,YAAY,UAAU;SACvD;GAEL,MAAM,UAAU,MAAM,SAAS,YAAY,QAAQ;AAMnD,SAAM,UAAU,YAHE,WAAW,QAAQ,SAAS,EAAE,UAAU,MAAM,CAAC,CAAC,UAAU,EAGrC,QAAQ"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"remove-BB883RDx.mjs","names":["parseYaml","stringifyYaml"],"sources":["../src/commands/profile/remove.ts"],"sourcesContent":["import { readFile, readdir, rm, writeFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { defineCommand } from \"citty\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { findSourceRoot } from \"../../utils/context-detection.js\";\n\n/**\n * Recursively collect all file paths in a directory (relative to baseDir)\n */\nasync function collectFiles(dir: string, baseDir: string): Promise<string[]> {\n const files: string[] = [];\n const entries = await readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n files.push(...(await collectFiles(fullPath, baseDir)));\n } else {\n files.push(relative(baseDir, fullPath));\n }\n }\n\n return files;\n}\n\n/**\n * Remove a profile entry from baton.source.yaml if it exists in the profiles array\n */\nasync function removeProfileFromSourceManifest(\n sourceRoot: string,\n profileName: string,\n): Promise<void> {\n const manifestPath = join(sourceRoot, \"baton.source.yaml\");\n\n try {\n const content = await readFile(manifestPath, \"utf-8\");\n const manifest = parseYaml(content);\n\n if (manifest?.profiles && Array.isArray(manifest.profiles)) {\n const originalLength = manifest.profiles.length;\n manifest.profiles = manifest.profiles.filter(\n (profile: { name?: string; path?: string }) =>\n profile.name !== profileName && profile.path !== `profiles/${profileName}`,\n );\n\n if (manifest.profiles.length < originalLength) {\n // Remove empty profiles array\n if (manifest.profiles.length === 0) {\n manifest.profiles = undefined;\n }\n await writeFile(manifestPath, stringifyYaml(manifest), \"utf-8\");\n }\n }\n } catch {\n // If manifest can't be read/written, skip — the directory removal is the primary action\n }\n}\n\nexport const profileRemoveCommand = defineCommand({\n meta: {\n name: \"remove\",\n description: \"Remove a profile from the source repository\",\n },\n args: {\n name: {\n type: \"positional\",\n description: \"Profile name to remove\",\n required: true,\n },\n },\n async run({ args }) {\n p.intro(\"Remove Profile\");\n\n // Check for baton.source.yaml in current or parent directories\n const sourceRoot = await findSourceRoot();\n if (!sourceRoot) {\n p.cancel(\"This command must be run inside a source directory (baton.source.yaml not found)\");\n process.exit(1);\n }\n\n const profileName = args.name as string;\n const profileDir = join(sourceRoot, \"profiles\", profileName);\n\n // Check if profile directory exists\n let files: string[];\n try {\n files = await collectFiles(profileDir, sourceRoot);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n p.cancel(`Profile \"${profileName}\" does not exist in profiles/${profileName}/`);\n process.exit(1);\n }\n throw error;\n }\n\n // Warn about files that will be deleted\n if (files.length > 0) {\n p.log.warn(\"The following files will be deleted:\");\n for (const file of files) {\n p.log.info(` ${file}`);\n }\n } else {\n p.log.warn(`Directory profiles/${profileName}/ will be deleted.`);\n }\n\n // Confirm before removing\n const confirmed = await p.confirm({\n message: `Are you sure you want to remove profile \"${profileName}\"?`,\n initialValue: false,\n });\n\n if (p.isCancel(confirmed) || !confirmed) {\n p.cancel(\"Operation cancelled.\");\n process.exit(0);\n }\n\n // Remove the profile directory\n await rm(profileDir, { recursive: true, force: true });\n\n // Remove entry from baton.source.yaml if present\n await removeProfileFromSourceManifest(sourceRoot, profileName);\n\n p.outro(`Profile \"${profileName}\" removed from profiles/${profileName}/`);\n },\n});\n"],"mappings":";;;;;;;;;;;;AAUA,eAAe,aAAa,KAAa,SAAoC;CAC3E,MAAM,QAAkB,EAAE;CAC1B,MAAM,UAAU,MAAM,QAAQ,KAAK,EAAE,eAAe,MAAM,CAAC;AAE3D,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,WAAW,KAAK,KAAK,MAAM,KAAK;AACtC,MAAI,MAAM,aAAa,CACrB,OAAM,KAAK,GAAI,MAAM,aAAa,UAAU,QAAQ,CAAE;MAEtD,OAAM,KAAK,SAAS,SAAS,SAAS,CAAC;;AAI3C,QAAO;;;;;AAMT,eAAe,gCACb,YACA,aACe;CACf,MAAM,eAAe,KAAK,YAAY,oBAAoB;AAE1D,KAAI;EAEF,MAAM,WAAWA,MADD,MAAM,SAAS,cAAc,QAAQ,CAClB;AAEnC,MAAI,UAAU,YAAY,MAAM,QAAQ,SAAS,SAAS,EAAE;GAC1D,MAAM,iBAAiB,SAAS,SAAS;AACzC,YAAS,WAAW,SAAS,SAAS,QACnC,YACC,QAAQ,SAAS,eAAe,QAAQ,SAAS,YAAY,cAChE;AAED,OAAI,SAAS,SAAS,SAAS,gBAAgB;AAE7C,QAAI,SAAS,SAAS,WAAW,EAC/B,UAAS,WAAW;AAEtB,UAAM,UAAU,cAAcC,UAAc,SAAS,EAAE,QAAQ;;;SAG7D;;AAKV,MAAa,uBAAuB,cAAc;CAChD,MAAM;EACJ,MAAM;EACN,aAAa;EACd;CACD,MAAM,EACJ,MAAM;EACJ,MAAM;EACN,aAAa;EACb,UAAU;EACX,EACF;CACD,MAAM,IAAI,EAAE,QAAQ;AAClB,IAAE,MAAM,iBAAiB;EAGzB,MAAM,aAAa,MAAM,gBAAgB;AACzC,MAAI,CAAC,YAAY;AACf,KAAE,OAAO,mFAAmF;AAC5F,WAAQ,KAAK,EAAE;;EAGjB,MAAM,cAAc,KAAK;EACzB,MAAM,aAAa,KAAK,YAAY,YAAY,YAAY;EAG5D,IAAI;AACJ,MAAI;AACF,WAAQ,MAAM,aAAa,YAAY,WAAW;WAC3C,OAAO;AACd,OAAK,MAAgC,SAAS,UAAU;AACtD,MAAE,OAAO,YAAY,YAAY,+BAA+B,YAAY,GAAG;AAC/E,YAAQ,KAAK,EAAE;;AAEjB,SAAM;;AAIR,MAAI,MAAM,SAAS,GAAG;AACpB,KAAE,IAAI,KAAK,uCAAuC;AAClD,QAAK,MAAM,QAAQ,MACjB,GAAE,IAAI,KAAK,KAAK,OAAO;QAGzB,GAAE,IAAI,KAAK,sBAAsB,YAAY,oBAAoB;EAInE,MAAM,YAAY,MAAM,EAAE,QAAQ;GAChC,SAAS,4CAA4C,YAAY;GACjE,cAAc;GACf,CAAC;AAEF,MAAI,EAAE,SAAS,UAAU,IAAI,CAAC,WAAW;AACvC,KAAE,OAAO,uBAAuB;AAChC,WAAQ,KAAK,EAAE;;AAIjB,QAAM,GAAG,YAAY;GAAE,WAAW;GAAM,OAAO;GAAM,CAAC;AAGtD,QAAM,gCAAgC,YAAY,YAAY;AAE9D,IAAE,MAAM,YAAY,YAAY,0BAA0B,YAAY,GAAG;;CAE5E,CAAC"}
|