@kidd-cli/bundler 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/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -49
- package/dist/index.js.map +1 -1
- package/package.json +7 -6
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/autoload-plugin.ts","../src/types.ts","../src/build.ts","../src/compile.ts","../src/generate-autoloader.ts","../src/map-config.ts","../src/resolve-config.ts","../src/scan-commands.ts","../src/watch.ts"],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/autoload-plugin.ts","../src/types.ts","../src/build.ts","../src/compile.ts","../src/generate-autoloader.ts","../src/map-config.ts","../src/resolve-config.ts","../src/scan-commands.ts","../src/watch.ts"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,6 @@ import { err, ok } from "@kidd-cli/utils/fp";
|
|
|
5
5
|
import { build as build$1 } from "tsdown";
|
|
6
6
|
import { existsSync, readdirSync, unlinkSync } from "node:fs";
|
|
7
7
|
import { execFile } from "node:child_process";
|
|
8
|
-
|
|
9
8
|
//#region src/generate-autoloader.ts
|
|
10
9
|
/**
|
|
11
10
|
* Generate JavaScript source code for a static autoloader virtual module.
|
|
@@ -247,7 +246,6 @@ function formatObject(entries) {
|
|
|
247
246
|
if (entries.length === 0) return "{}";
|
|
248
247
|
return `{\n${entries.map((entry) => ` ${entry},`).join("\n")}\n}`;
|
|
249
248
|
}
|
|
250
|
-
|
|
251
249
|
//#endregion
|
|
252
250
|
//#region src/scan-commands.ts
|
|
253
251
|
const VALID_EXTENSIONS = new Set([
|
|
@@ -353,14 +351,12 @@ function resolveIndexPath(dir, entry) {
|
|
|
353
351
|
if (!entry) return;
|
|
354
352
|
return join(dir, entry.name);
|
|
355
353
|
}
|
|
356
|
-
|
|
357
354
|
//#endregion
|
|
358
355
|
//#region src/autoload-plugin.ts
|
|
359
356
|
const VIRTUAL_MODULE_ID = "virtual:kidd-static-commands";
|
|
360
357
|
const RESOLVED_VIRTUAL_ID = `\0${VIRTUAL_MODULE_ID}`;
|
|
361
358
|
const AUTOLOADER_REGION_START = "//#region src/autoloader.ts";
|
|
362
359
|
const AUTOLOADER_REGION_END = "//#endregion";
|
|
363
|
-
const KIDD_DIST_PATTERN = /\/kidd\/dist\/index\.js$/;
|
|
364
360
|
/**
|
|
365
361
|
* Create a rolldown plugin that replaces the runtime autoloader with a static version.
|
|
366
362
|
*
|
|
@@ -394,8 +390,7 @@ function createAutoloadPlugin(params) {
|
|
|
394
390
|
if (source === VIRTUAL_MODULE_ID) return RESOLVED_VIRTUAL_ID;
|
|
395
391
|
return null;
|
|
396
392
|
},
|
|
397
|
-
transform(code,
|
|
398
|
-
if (!KIDD_DIST_PATTERN.test(id)) return null;
|
|
393
|
+
transform(code, _id) {
|
|
399
394
|
const regionStart = code.indexOf(AUTOLOADER_REGION_START);
|
|
400
395
|
if (regionStart === -1) return null;
|
|
401
396
|
const regionEnd = code.indexOf(AUTOLOADER_REGION_END, regionStart);
|
|
@@ -422,7 +417,6 @@ function buildStaticRegion() {
|
|
|
422
417
|
"//#endregion"
|
|
423
418
|
].join("\n");
|
|
424
419
|
}
|
|
425
|
-
|
|
426
420
|
//#endregion
|
|
427
421
|
//#region src/constants.ts
|
|
428
422
|
/**
|
|
@@ -430,34 +424,6 @@ function buildStaticRegion() {
|
|
|
430
424
|
*/
|
|
431
425
|
const SHEBANG = "#!/usr/bin/env node\n";
|
|
432
426
|
/**
|
|
433
|
-
* Default entry point for the CLI source.
|
|
434
|
-
*/
|
|
435
|
-
const DEFAULT_ENTRY = "./src/index.ts";
|
|
436
|
-
/**
|
|
437
|
-
* Default directory for CLI commands.
|
|
438
|
-
*/
|
|
439
|
-
const DEFAULT_COMMANDS = "./commands";
|
|
440
|
-
/**
|
|
441
|
-
* Default build output directory.
|
|
442
|
-
*/
|
|
443
|
-
const DEFAULT_OUT_DIR = "./dist";
|
|
444
|
-
/**
|
|
445
|
-
* Default Node.js target version for builds.
|
|
446
|
-
*/
|
|
447
|
-
const DEFAULT_TARGET = "node18";
|
|
448
|
-
/**
|
|
449
|
-
* Default minification setting.
|
|
450
|
-
*/
|
|
451
|
-
const DEFAULT_MINIFY = false;
|
|
452
|
-
/**
|
|
453
|
-
* Default source map generation setting.
|
|
454
|
-
*/
|
|
455
|
-
const DEFAULT_SOURCEMAP = true;
|
|
456
|
-
/**
|
|
457
|
-
* Default binary name for compiled SEA output.
|
|
458
|
-
*/
|
|
459
|
-
const DEFAULT_BINARY_NAME = "cli";
|
|
460
|
-
/**
|
|
461
427
|
* Default compile targets when none are explicitly configured.
|
|
462
428
|
*
|
|
463
429
|
* Covers Linux servers/CI, modern and Intel Macs, and Windows — roughly 95%
|
|
@@ -481,7 +447,6 @@ const ALWAYS_BUNDLE = [/^@?kidd/];
|
|
|
481
447
|
* Node.js builtin modules in both bare and `node:` prefixed forms.
|
|
482
448
|
*/
|
|
483
449
|
const NODE_BUILTINS = [...builtinModules, ...builtinModules.map((m) => `node:${m}`)];
|
|
484
|
-
|
|
485
450
|
//#endregion
|
|
486
451
|
//#region src/map-config.ts
|
|
487
452
|
/**
|
|
@@ -555,7 +520,6 @@ function buildExternals(userExternals) {
|
|
|
555
520
|
function resolveTagModulePath() {
|
|
556
521
|
return createRequire(import.meta.url).resolve("@kidd-cli/utils/tag");
|
|
557
522
|
}
|
|
558
|
-
|
|
559
523
|
//#endregion
|
|
560
524
|
//#region src/resolve-config.ts
|
|
561
525
|
/**
|
|
@@ -587,23 +551,23 @@ function normalizeCompileOptions(value) {
|
|
|
587
551
|
*/
|
|
588
552
|
function resolveConfig(params) {
|
|
589
553
|
const { config, cwd } = params;
|
|
590
|
-
const entry = resolve(cwd, config.entry ??
|
|
591
|
-
const commands = resolve(cwd, config.commands ??
|
|
554
|
+
const entry = resolve(cwd, config.entry ?? "./src/index.ts");
|
|
555
|
+
const commands = resolve(cwd, config.commands ?? "./commands");
|
|
592
556
|
const buildOpts = config.build ?? {};
|
|
593
557
|
const compileOpts = normalizeCompileOptions(config.compile);
|
|
594
|
-
const buildOutDir = resolve(cwd, buildOpts.out ??
|
|
595
|
-
const compileOutDir = resolve(cwd, compileOpts.out ??
|
|
558
|
+
const buildOutDir = resolve(cwd, buildOpts.out ?? "./dist");
|
|
559
|
+
const compileOutDir = resolve(cwd, compileOpts.out ?? "./dist");
|
|
596
560
|
return {
|
|
597
561
|
build: {
|
|
598
562
|
external: buildOpts.external ?? [],
|
|
599
|
-
minify: buildOpts.minify ??
|
|
600
|
-
sourcemap: buildOpts.sourcemap ??
|
|
601
|
-
target: buildOpts.target ??
|
|
563
|
+
minify: buildOpts.minify ?? false,
|
|
564
|
+
sourcemap: buildOpts.sourcemap ?? true,
|
|
565
|
+
target: buildOpts.target ?? "node18"
|
|
602
566
|
},
|
|
603
567
|
buildOutDir,
|
|
604
568
|
commands,
|
|
605
569
|
compile: {
|
|
606
|
-
name: compileOpts.name ??
|
|
570
|
+
name: compileOpts.name ?? "cli",
|
|
607
571
|
targets: compileOpts.targets ?? []
|
|
608
572
|
},
|
|
609
573
|
compileOutDir,
|
|
@@ -625,7 +589,6 @@ function resolveConfig(params) {
|
|
|
625
589
|
function detectBuildEntry(outDir) {
|
|
626
590
|
return ENTRY_CANDIDATES.map((name) => join(outDir, name)).find(existsSync);
|
|
627
591
|
}
|
|
628
|
-
|
|
629
592
|
//#endregion
|
|
630
593
|
//#region src/build.ts
|
|
631
594
|
/**
|
|
@@ -652,7 +615,6 @@ async function build(params) {
|
|
|
652
615
|
outDir: resolved.buildOutDir
|
|
653
616
|
});
|
|
654
617
|
}
|
|
655
|
-
|
|
656
618
|
//#endregion
|
|
657
619
|
//#region src/compile.ts
|
|
658
620
|
/**
|
|
@@ -819,7 +781,6 @@ function execBunBuild(args) {
|
|
|
819
781
|
function cleanBunBuildArtifacts(cwd) {
|
|
820
782
|
readdirSync(cwd).filter((name) => name.endsWith(".bun-build")).map((name) => join(cwd, name)).map(unlinkSync);
|
|
821
783
|
}
|
|
822
|
-
|
|
823
784
|
//#endregion
|
|
824
785
|
//#region src/watch.ts
|
|
825
786
|
/**
|
|
@@ -843,7 +804,7 @@ async function watch(params) {
|
|
|
843
804
|
}
|
|
844
805
|
return ok();
|
|
845
806
|
}
|
|
846
|
-
|
|
847
807
|
//#endregion
|
|
848
808
|
export { build, compile, createAutoloadPlugin, detectBuildEntry, generateAutoloaderParts, generateStaticAutoloader, mapToBuildConfig, mapToWatchConfig, normalizeCompileOptions, resolveConfig, resolveTargetLabel, scanCommandsDir, watch };
|
|
809
|
+
|
|
849
810
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["tsdownBuild","tsdownBuild"],"sources":["../src/generate-autoloader.ts","../src/scan-commands.ts","../src/autoload-plugin.ts","../src/constants.ts","../src/map-config.ts","../src/resolve-config.ts","../src/build.ts","../src/compile.ts","../src/watch.ts"],"sourcesContent":["import type { ScanResult, ScannedDir, ScannedFile } from './types.js'\n\n/**\n * Parameters for generating a static autoloader module.\n */\ninterface GenerateStaticAutoloaderParams {\n readonly scan: ScanResult\n readonly tagModulePath: string\n}\n\n/**\n * The two parts of a static autoloader transform: import statements to\n * prepend and the replacement code for the autoloader region.\n */\nexport interface StaticAutoloaderParts {\n readonly imports: string\n readonly region: string\n}\n\n/**\n * Generate JavaScript source code for a static autoloader virtual module.\n *\n * The generated module statically imports every discovered command file and\n * exports an `autoload()` function that returns the pre-built CommandMap.\n * Directory commands that merge a parent handler with subcommands are re-tagged\n * via `withTag` because the TAG symbol is non-enumerable and lost on spread.\n *\n * @param params - The scan result and path to the tag utility module.\n * @returns JavaScript source code for the static autoloader.\n */\nexport function generateStaticAutoloader(params: GenerateStaticAutoloaderParams): string {\n const imports = collectImports(params.scan)\n const importLines = buildImportStatements(imports, params.tagModulePath)\n const commandsObject = buildCommandsObject(params.scan)\n\n return [\n ...importLines,\n '',\n `const commands = ${commandsObject}`,\n '',\n 'export async function autoload() {',\n ' return commands',\n '}',\n '',\n ].join('\\n')\n}\n\n/**\n * Generate the two parts needed to transform kidd's bundled dist.\n *\n * Returns an empty imports string (no prepended imports needed) and a\n * replacement autoloader region that uses dynamic `import()` calls inside\n * the async `autoload()` function. This avoids circular dependency issues:\n * command files import `command` from `@kidd-cli/core`, so static imports would be\n * hoisted above kidd's own initialization code, causing `TAG` to be\n * accessed before initialization.\n *\n * By deferring to dynamic imports, kidd fully initializes first, then\n * command files are loaded when `autoload()` is called at CLI startup.\n *\n * @param params - The scan result and path to the tag utility module.\n * @returns Import statements (empty) and the replacement autoloader region.\n */\nexport function generateAutoloaderParts(\n params: GenerateStaticAutoloaderParams\n): StaticAutoloaderParts {\n const imports = collectImports(params.scan)\n\n if (imports.length === 0) {\n return {\n imports: '',\n region: buildEmptyAutoloaderRegion(),\n }\n }\n\n const commandsObject = buildCommandsObject(params.scan)\n const region = buildDynamicAutoloaderRegion(imports, commandsObject)\n\n return { imports: '', region }\n}\n\n// ---------------------------------------------------------------------------\n\n/**\n * A collected import entry with its identifier and absolute file path.\n *\n * @private\n */\ninterface ImportEntry {\n readonly identifier: string\n readonly filePath: string\n}\n\n/**\n * Collect all import entries from a scan result.\n *\n * @private\n * @param scan - The scan result to collect imports from.\n * @returns A flat array of all import entries.\n */\nfunction collectImports(scan: ScanResult): readonly ImportEntry[] {\n return [\n ...scan.files.map((file) => fileToImport(file, [])),\n ...scan.dirs.flatMap((dir) => collectDirImports(dir, [])),\n ]\n}\n\n/**\n * Recursively collect import entries from a scanned directory.\n *\n * @private\n * @param dir - The scanned directory.\n * @param parentPath - The path segments leading to this directory.\n * @returns A flat array of import entries for the directory and its children.\n */\nfunction collectDirImports(dir: ScannedDir, parentPath: readonly string[]): readonly ImportEntry[] {\n const currentPath = [...parentPath, dir.name]\n const indexImport: readonly ImportEntry[] = buildIndexImport(dir.index, currentPath)\n\n return [\n ...indexImport,\n ...dir.files.map((file) => fileToImport(file, currentPath)),\n ...dir.dirs.flatMap((sub) => collectDirImports(sub, currentPath)),\n ]\n}\n\n/**\n * Create an import entry for a leaf command file.\n *\n * @private\n * @param file - The scanned file.\n * @param parentPath - The path segments leading to the file's parent directory.\n * @returns An import entry with a generated identifier.\n */\nfunction fileToImport(file: ScannedFile, parentPath: readonly string[]): ImportEntry {\n return {\n filePath: file.filePath,\n identifier: toIdentifier([...parentPath, file.name]),\n }\n}\n\n/**\n * Convert a path segment array to a valid JavaScript identifier.\n *\n * Joins segments with underscores and prefixes with `_`.\n * Example: `['deploy', 'preview']` becomes `_deploy_preview`.\n *\n * @private\n * @param segments - The path segments to convert.\n * @returns A valid JavaScript identifier string.\n */\nfunction toIdentifier(segments: readonly string[]): string {\n return `_${segments.map((s) => s.replaceAll('-', '$')).join('_')}`\n}\n\n/**\n * Build the array of import statement lines.\n *\n * @private\n * @param imports - All collected import entries.\n * @param tagModulePath - Absolute path to the tag utility module.\n * @returns An array of import statement strings.\n */\nfunction buildImportStatements(\n imports: readonly ImportEntry[],\n tagModulePath: string\n): readonly string[] {\n const tagLine = buildTagImportLine(imports, tagModulePath)\n\n const importLines = imports.map((entry) => `import ${entry.identifier} from '${entry.filePath}'`)\n\n return [...tagLine, '', ...importLines]\n}\n\n/**\n * Build the JavaScript object literal string for the top-level commands map.\n *\n * @private\n * @param scan - The scan result.\n * @returns A string representation of the commands object literal.\n */\nfunction buildCommandsObject(scan: ScanResult): string {\n const entries = [\n ...scan.files.map((file) => buildFileEntry(file, [])),\n ...scan.dirs.map((dir) => buildDirEntry(dir, [])),\n ]\n\n return formatObject(entries)\n}\n\n/**\n * Build an object entry string for a leaf command file.\n *\n * @private\n * @param file - The scanned file.\n * @param parentPath - Path segments to the file's parent.\n * @returns A string like `'status': _status`.\n */\nfunction buildFileEntry(file: ScannedFile, parentPath: readonly string[]): string {\n const identifier = toIdentifier([...parentPath, file.name])\n return `'${file.name}': ${identifier}`\n}\n\n/**\n * Build an object entry string for a directory command (possibly with subcommands).\n *\n * @private\n * @param dir - The scanned directory.\n * @param parentPath - Path segments to the directory's parent.\n * @returns A string representing the directory command with withTag wrapping.\n */\nfunction buildDirEntry(dir: ScannedDir, parentPath: readonly string[]): string {\n const currentPath = [...parentPath, dir.name]\n const subEntries = [\n ...dir.files.map((file) => buildFileEntry(file, currentPath)),\n ...dir.dirs.map((sub) => buildDirEntry(sub, currentPath)),\n ]\n const commandsObj = formatObject(subEntries)\n\n if (dir.index) {\n const indexIdentifier = toIdentifier(currentPath)\n\n return `'${dir.name}': withTag({ ...${indexIdentifier}, commands: ${commandsObj} }, 'Command')`\n }\n\n return `'${dir.name}': withTag({ commands: ${commandsObj} }, 'Command')`\n}\n\n/**\n * Build the import entry for an index file, if present.\n *\n * @private\n * @param index - The absolute path to the index file, or undefined.\n * @param currentPath - The current path segments for identifier generation.\n * @returns An array with zero or one import entries.\n */\nfunction buildIndexImport(\n index: string | undefined,\n currentPath: readonly string[]\n): readonly ImportEntry[] {\n if (!index) {\n return []\n }\n return [{ filePath: index, identifier: toIdentifier(currentPath) }]\n}\n\n/**\n * Build the tag import line if any imports exist.\n *\n * @private\n * @param imports - The collected import entries.\n * @param tagModulePath - The absolute path to the tag module.\n * @returns An array with zero or one import statement strings.\n */\nfunction buildTagImportLine(\n imports: readonly ImportEntry[],\n tagModulePath: string\n): readonly string[] {\n if (imports.length === 0) {\n return []\n }\n return [`import { withTag } from '${tagModulePath}'`]\n}\n\n/**\n * Build the autoloader region for an empty scan result.\n *\n * @private\n * @returns A region string with an autoloader that returns an empty object.\n */\nfunction buildEmptyAutoloaderRegion(): string {\n return [\n '//#region src/autoloader.ts (static)',\n 'async function autoload() {',\n ' return {}',\n '}',\n '//#endregion',\n ].join('\\n')\n}\n\n/**\n * Build the autoloader region using dynamic `import()` calls.\n *\n * Uses `Promise.all` with array destructuring to load all command files\n * in parallel. The dynamic imports defer execution until `autoload()` is\n * called, avoiding circular dependency issues with kidd's own initialization.\n *\n * @private\n * @param imports - The collected import entries.\n * @param commandsObject - The commands object literal string.\n * @returns A region string with the full dynamic autoloader.\n */\nfunction buildDynamicAutoloaderRegion(\n imports: readonly ImportEntry[],\n commandsObject: string\n): string {\n const destructuring = imports.map((entry) => ` { default: ${entry.identifier} },`).join('\\n')\n\n const importCalls = imports.map((entry) => ` import('${entry.filePath}'),`).join('\\n')\n\n return [\n '//#region src/autoloader.ts (static)',\n 'async function autoload() {',\n ' const [',\n destructuring,\n ' ] = await Promise.all([',\n importCalls,\n ' ])',\n ` return ${commandsObject}`,\n '}',\n '//#endregion',\n ].join('\\n')\n}\n\n/**\n * Format an array of key-value strings as a JavaScript object literal.\n *\n * @private\n * @param entries - The key-value pair strings.\n * @returns A formatted object literal string.\n */\nfunction formatObject(entries: readonly string[]): string {\n if (entries.length === 0) {\n return '{}'\n }\n\n const body = entries.map((entry) => ` ${entry},`).join('\\n')\n return `{\\n${body}\\n}`\n}\n","import type { Dirent } from 'node:fs'\nimport { readdir } from 'node:fs/promises'\nimport { basename, extname, join } from 'node:path'\n\nimport type { ScanResult, ScannedDir, ScannedFile } from './types.js'\n\nconst VALID_EXTENSIONS = new Set(['.ts', '.js', '.mjs'])\nconst INDEX_NAME = 'index'\n\n/**\n * Scan a commands directory and produce a tree structure for static code generation.\n *\n * Mirrors the runtime autoloader's rules: valid extensions are `.ts`, `.js`, `.mjs`;\n * files and directories starting with `_` or `.` are skipped; `index` files in\n * subdirectories become parent command handlers.\n *\n * @param dir - Absolute path to the commands directory.\n * @returns A tree of scanned files and directories.\n */\nexport async function scanCommandsDir(dir: string): Promise<ScanResult> {\n const entries = await readdir(dir, { withFileTypes: true })\n\n const files = entries.filter(isCommandFile).map((entry) => toScannedFile(dir, entry))\n\n const dirs = await Promise.all(\n entries.filter(isCommandDir).map((entry) => scanSubDir(join(dir, entry.name)))\n )\n\n return { dirs, files }\n}\n\n// ---------------------------------------------------------------------------\n\n/**\n * Recursively scan a subdirectory into a ScannedDir.\n *\n * @private\n * @param dir - Absolute path to the subdirectory.\n * @returns A ScannedDir representing the directory and its contents.\n */\nasync function scanSubDir(dir: string): Promise<ScannedDir> {\n const name = basename(dir)\n const entries = await readdir(dir, { withFileTypes: true })\n const indexEntry = findIndexEntry(entries)\n\n const files = entries.filter(isCommandFile).map((entry) => toScannedFile(dir, entry))\n\n const dirs = await Promise.all(\n entries.filter(isCommandDir).map((entry) => scanSubDir(join(dir, entry.name)))\n )\n\n return {\n dirs,\n files,\n index: resolveIndexPath(dir, indexEntry),\n name,\n }\n}\n\n/**\n * Convert a directory entry into a ScannedFile.\n *\n * @private\n * @param dir - Parent directory absolute path.\n * @param entry - The directory entry for the file.\n * @returns A ScannedFile with name and absolute file path.\n */\nfunction toScannedFile(dir: string, entry: Dirent): ScannedFile {\n return {\n filePath: join(dir, entry.name),\n name: basename(entry.name, extname(entry.name)),\n }\n}\n\n/**\n * Find the index file entry among a list of directory entries.\n *\n * @private\n * @param entries - The directory entries to search.\n * @returns The Dirent for the index file, or undefined.\n */\nfunction findIndexEntry(entries: readonly Dirent[]): Dirent | undefined {\n return entries.find(\n (entry) =>\n entry.isFile() &&\n VALID_EXTENSIONS.has(extname(entry.name)) &&\n basename(entry.name, extname(entry.name)) === INDEX_NAME\n )\n}\n\n/**\n * Predicate: entry is a valid command file (not index, not hidden/private).\n *\n * @private\n * @param entry - The directory entry to check.\n * @returns True when the entry is a scannable command file.\n */\nfunction isCommandFile(entry: Dirent): boolean {\n if (!entry.isFile()) {\n return false\n }\n if (entry.name.startsWith('_') || entry.name.startsWith('.')) {\n return false\n }\n if (!VALID_EXTENSIONS.has(extname(entry.name))) {\n return false\n }\n return basename(entry.name, extname(entry.name)) !== INDEX_NAME\n}\n\n/**\n * Predicate: entry is a scannable command directory (not hidden/private).\n *\n * @private\n * @param entry - The directory entry to check.\n * @returns True when the entry is a scannable command directory.\n */\nfunction isCommandDir(entry: Dirent): boolean {\n if (!entry.isDirectory()) {\n return false\n }\n return !entry.name.startsWith('_') && !entry.name.startsWith('.')\n}\n\n/**\n * Resolve the absolute path to an index file entry, or undefined.\n *\n * @private\n * @param dir - The parent directory absolute path.\n * @param entry - The index file Dirent, or undefined.\n * @returns The absolute path to the index file, or undefined.\n */\nfunction resolveIndexPath(dir: string, entry: Dirent | undefined): string | undefined {\n if (!entry) {\n return undefined\n }\n return join(dir, entry.name)\n}\n","import type { Rolldown } from 'tsdown'\n\nimport { generateStaticAutoloader } from './generate-autoloader.js'\nimport { scanCommandsDir } from './scan-commands.js'\n\nconst VIRTUAL_MODULE_ID = 'virtual:kidd-static-commands'\nconst RESOLVED_VIRTUAL_ID = `\\0${VIRTUAL_MODULE_ID}`\n\nconst AUTOLOADER_REGION_START = '//#region src/autoloader.ts'\nconst AUTOLOADER_REGION_END = '//#endregion'\nconst KIDD_DIST_PATTERN = /\\/kidd\\/dist\\/index\\.js$/\n\n/**\n * Parameters for creating the autoload plugin.\n */\ninterface CreateAutoloadPluginParams {\n readonly commandsDir: string\n readonly tagModulePath: string\n}\n\n/**\n * Create a rolldown plugin that replaces the runtime autoloader with a static version.\n *\n * Uses a three-hook approach to break the circular dependency between kidd's\n * dist and user command files (which `import { command } from '@kidd-cli/core'`):\n *\n * 1. `transform` — detects kidd's pre-bundled dist and replaces the autoloader\n * region with a dynamic `import()` to a virtual module\n * 2. `resolveId` — resolves the virtual module identifier\n * 3. `load` — scans the commands directory and generates a static autoloader\n * module with all command imports pre-resolved\n *\n * The dynamic import ensures command files execute after kidd's code is fully\n * initialized, avoiding `ReferenceError` from accessing `TAG` before its\n * declaration.\n *\n * @param params - The commands directory and tag module path.\n * @returns A rolldown plugin for static autoloading.\n */\nexport function createAutoloadPlugin(params: CreateAutoloadPluginParams): Rolldown.Plugin {\n return {\n async load(id) {\n if (id !== RESOLVED_VIRTUAL_ID) {\n return null\n }\n\n const scan = await scanCommandsDir(params.commandsDir)\n\n return generateStaticAutoloader({\n scan,\n tagModulePath: params.tagModulePath,\n })\n },\n name: 'kidd-static-autoloader',\n resolveId(source) {\n if (source === VIRTUAL_MODULE_ID) {\n return RESOLVED_VIRTUAL_ID\n }\n\n return null\n },\n transform(code, id) {\n if (!KIDD_DIST_PATTERN.test(id)) {\n return null\n }\n\n const regionStart = code.indexOf(AUTOLOADER_REGION_START)\n if (regionStart === -1) {\n return null\n }\n\n const regionEnd = code.indexOf(AUTOLOADER_REGION_END, regionStart)\n if (regionEnd === -1) {\n return null\n }\n\n const before = code.slice(0, regionStart)\n const after = code.slice(regionEnd + AUTOLOADER_REGION_END.length)\n const staticRegion = buildStaticRegion()\n\n return `${before}${staticRegion}${after}`\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n\n/**\n * Build the replacement autoloader region that delegates to the virtual module.\n *\n * @private\n * @returns The replacement region string with dynamic import.\n */\nfunction buildStaticRegion(): string {\n return [\n '//#region src/autoloader.ts (static)',\n 'async function autoload() {',\n ` const mod = await import('${VIRTUAL_MODULE_ID}')`,\n ' return mod.autoload()',\n '}',\n '//#endregion',\n ].join('\\n')\n}\n","import { builtinModules } from 'node:module'\n\nimport type { CompileTarget } from '@kidd-cli/config'\n\n/**\n * Shebang line prepended to CLI entry files.\n */\nexport const SHEBANG = '#!/usr/bin/env node\\n'\n\n/**\n * Default entry point for the CLI source.\n */\nexport const DEFAULT_ENTRY = './src/index.ts'\n\n/**\n * Default directory for CLI commands.\n */\nexport const DEFAULT_COMMANDS = './commands'\n\n/**\n * Default build output directory.\n */\nexport const DEFAULT_OUT_DIR = './dist'\n\n/**\n * Default Node.js target version for builds.\n */\nexport const DEFAULT_TARGET = 'node18'\n\n/**\n * Default minification setting.\n */\nexport const DEFAULT_MINIFY = false\n\n/**\n * Default source map generation setting.\n */\nexport const DEFAULT_SOURCEMAP = true\n\n/**\n * Default binary name for compiled SEA output.\n */\nexport const DEFAULT_BINARY_NAME = 'cli'\n\n/**\n * Default compile targets when none are explicitly configured.\n *\n * Covers Linux servers/CI, modern and Intel Macs, and Windows — roughly 95%\n * of developer environments.\n */\nexport const DEFAULT_COMPILE_TARGETS: readonly CompileTarget[] = [\n 'darwin-arm64',\n 'darwin-x64',\n 'linux-x64',\n 'windows-x64',\n]\n\n/**\n * Packages that must always be bundled into the output.\n *\n * The `@kidd-cli/core` framework and its internal `@kidd-cli/*` packages must be inlined\n * so the autoload plugin can intercept and replace the runtime autoloader\n * with a static version for compiled binaries.\n */\nexport const ALWAYS_BUNDLE: RegExp[] = [/^@?kidd/]\n\n/**\n * Node.js builtin modules in both bare and `node:` prefixed forms.\n */\nexport const NODE_BUILTINS: readonly string[] = [\n ...builtinModules,\n ...builtinModules.map((m) => `node:${m}`),\n]\n","import { createRequire } from 'node:module'\n\nimport type { InlineConfig } from 'tsdown'\n\nimport { createAutoloadPlugin } from './autoload-plugin.js'\nimport { ALWAYS_BUNDLE, NODE_BUILTINS, SHEBANG } from './constants.js'\nimport type { ResolvedBundlerConfig } from './types.js'\n\n/**\n * Map a resolved bundler config to a tsdown InlineConfig for production builds.\n *\n * @param config - The fully resolved bundler config.\n * @returns A tsdown InlineConfig ready for `build()`.\n */\nexport function mapToBuildConfig(config: ResolvedBundlerConfig): InlineConfig {\n return {\n banner: SHEBANG,\n clean: true,\n config: false,\n cwd: config.cwd,\n deps: {\n alwaysBundle: ALWAYS_BUNDLE,\n neverBundle: buildExternals(config.build.external),\n },\n dts: false,\n entry: { index: config.entry },\n format: 'esm',\n inputOptions: {\n resolve: {\n mainFields: ['module', 'main'],\n },\n },\n logLevel: 'info',\n minify: config.build.minify,\n outDir: config.buildOutDir,\n outputOptions: {\n codeSplitting: false,\n },\n platform: 'node',\n plugins: [\n createAutoloadPlugin({\n commandsDir: config.commands,\n tagModulePath: resolveTagModulePath(),\n }),\n ],\n sourcemap: config.build.sourcemap,\n target: config.build.target,\n treeshake: true,\n }\n}\n\n/**\n * Map a resolved bundler config to a tsdown InlineConfig for watch mode.\n *\n * @param params - The resolved config and optional success callback.\n * @returns A tsdown InlineConfig with `watch: true`.\n */\nexport function mapToWatchConfig(params: {\n readonly config: ResolvedBundlerConfig\n readonly onSuccess?: () => void | Promise<void>\n}): InlineConfig {\n const buildConfig = mapToBuildConfig(params.config)\n\n return {\n ...buildConfig,\n onSuccess: params.onSuccess,\n watch: true,\n }\n}\n\n// ---------------------------------------------------------------------------\n\n/**\n * Combine Node.js builtins with user-specified externals.\n *\n * @private\n * @param userExternals - Additional packages to mark as external.\n * @returns Combined array of externals for tsdown's `deps.neverBundle`.\n */\nfunction buildExternals(userExternals: readonly string[]): (string | RegExp)[] {\n return [...NODE_BUILTINS, ...userExternals]\n}\n\n/**\n * Resolve the absolute file path to the `@kidd-cli/utils/tag` module.\n *\n * The static autoloader virtual module imports `withTag` via this path.\n * Using an absolute path ensures rolldown can resolve the import from\n * inside the virtual module without relying on tsdown's `alwaysBundle`\n * heuristic, which virtual modules may bypass.\n *\n * @private\n * @returns The absolute file path to the tag module.\n */\nfunction resolveTagModulePath(): string {\n const require = createRequire(import.meta.url)\n return require.resolve('@kidd-cli/utils/tag')\n}\n","import { existsSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\n\nimport type { CompileOptions, KiddConfig } from '@kidd-cli/config'\n\nimport {\n DEFAULT_BINARY_NAME,\n DEFAULT_COMMANDS,\n DEFAULT_ENTRY,\n DEFAULT_MINIFY,\n DEFAULT_OUT_DIR,\n DEFAULT_SOURCEMAP,\n DEFAULT_TARGET,\n} from './constants.js'\nimport type { ResolvedBundlerConfig } from './types.js'\n\n/**\n * Known entry file names produced by tsdown for ESM builds, in preference order.\n */\nconst ENTRY_CANDIDATES = ['index.mjs', 'index.js'] as const\n\n/**\n * Normalize the `compile` config field from `boolean | CompileOptions | undefined` to `CompileOptions`.\n *\n * - `true` → `{}` (compile with defaults)\n * - `false` / `undefined` → `{}` (no explicit options, caller decides whether to compile)\n * - object → pass through\n *\n * @param value - The raw compile config value.\n * @returns A normalized CompileOptions object.\n */\nexport function normalizeCompileOptions(\n value: boolean | CompileOptions | undefined\n): CompileOptions {\n if (typeof value === 'object') {\n return value\n }\n\n return {}\n}\n\n/**\n * Fill defaults and resolve relative paths against `cwd`.\n *\n * This is a pure function — the incoming config is already validated by `@kidd-cli/config`.\n * It only fills missing optional fields with defaults and resolves paths to absolute.\n *\n * @param params - The raw config and working directory.\n * @returns A fully resolved bundler configuration.\n */\nexport function resolveConfig(params: {\n readonly config: KiddConfig\n readonly cwd: string\n}): ResolvedBundlerConfig {\n const { config, cwd } = params\n\n const entry = resolve(cwd, config.entry ?? DEFAULT_ENTRY)\n const commands = resolve(cwd, config.commands ?? DEFAULT_COMMANDS)\n\n const buildOpts = config.build ?? {}\n const compileOpts = normalizeCompileOptions(config.compile)\n\n const buildOutDir = resolve(cwd, buildOpts.out ?? DEFAULT_OUT_DIR)\n const compileOutDir = resolve(cwd, compileOpts.out ?? DEFAULT_OUT_DIR)\n\n return {\n build: {\n external: buildOpts.external ?? [],\n minify: buildOpts.minify ?? DEFAULT_MINIFY,\n sourcemap: buildOpts.sourcemap ?? DEFAULT_SOURCEMAP,\n target: buildOpts.target ?? DEFAULT_TARGET,\n },\n buildOutDir,\n commands,\n compile: {\n name: compileOpts.name ?? DEFAULT_BINARY_NAME,\n targets: compileOpts.targets ?? [],\n },\n compileOutDir,\n cwd,\n entry,\n include: config.include ?? [],\n }\n}\n\n/**\n * Detect the bundled entry file in a build output directory.\n *\n * tsdown may produce `index.mjs` or `index.js` depending on the project's\n * `package.json` `type` field and tsdown configuration. This function checks\n * for both candidates and returns the first one that exists on disk.\n *\n * @param outDir - Absolute path to the build output directory.\n * @returns The absolute path to the entry file, or `undefined` when none is found.\n */\nexport function detectBuildEntry(outDir: string): string | undefined {\n return ENTRY_CANDIDATES.map((name) => join(outDir, name)).find(existsSync)\n}\n","import { err, ok } from '@kidd-cli/utils/fp'\nimport { build as tsdownBuild } from 'tsdown'\n\nimport { mapToBuildConfig } from './map-config.js'\nimport { detectBuildEntry, resolveConfig } from './resolve-config.js'\nimport type { AsyncBundlerResult, BuildOutput, BuildParams } from './types.js'\n\n/**\n * Build a kidd CLI tool using tsdown.\n *\n * Resolves defaults, maps the config to tsdown's InlineConfig, and invokes the build.\n *\n * @param params - The build parameters including config and working directory.\n * @returns A result tuple with build output on success or an Error on failure.\n */\nexport async function build(params: BuildParams): AsyncBundlerResult<BuildOutput> {\n const resolved = resolveConfig(params)\n const inlineConfig = mapToBuildConfig(resolved)\n\n try {\n await tsdownBuild(inlineConfig)\n } catch (error: unknown) {\n console.error('[kidd-bundler] build error:', error)\n return err(new Error('tsdown build failed', { cause: error }))\n }\n\n const entryFile = detectBuildEntry(resolved.buildOutDir)\n\n if (!entryFile) {\n return err(new Error(`build produced no entry file in ${resolved.buildOutDir}`))\n }\n\n return ok({\n entryFile,\n outDir: resolved.buildOutDir,\n })\n}\n","import { execFile as execFileCb } from 'node:child_process'\nimport { readdirSync, unlinkSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport type { CompileTarget } from '@kidd-cli/config'\nimport { err, ok } from '@kidd-cli/utils/fp'\nimport type { AsyncResult } from '@kidd-cli/utils/fp'\n\nimport { DEFAULT_COMPILE_TARGETS } from './constants.js'\nimport { detectBuildEntry, resolveConfig } from './resolve-config.js'\nimport type { CompileOutput, CompileParams, CompiledBinary } from './types.js'\n\n/**\n * Packages to externalize during `bun build --compile`.\n *\n * These are optional peer dependencies of `c12` (the config loader) that bun\n * eagerly tries to resolve even though they are behind dynamic `import()` calls\n * that never execute at runtime in a compiled CLI.\n */\nconst COMPILE_EXTERNALS: readonly string[] = ['chokidar', 'magicast', 'giget']\n\n/**\n * Human-readable labels for each compile target.\n */\nconst COMPILE_TARGET_LABELS: Readonly<Record<CompileTarget, string>> = {\n 'darwin-arm64': 'macOS Apple Silicon',\n 'darwin-x64': 'macOS Intel',\n 'linux-arm64': 'Linux ARM64',\n 'linux-x64': 'Linux x64',\n 'linux-x64-musl': 'Linux x64 (musl)',\n 'windows-arm64': 'Windows ARM64',\n 'windows-x64': 'Windows x64',\n}\n\n/**\n * Compile a kidd CLI tool into standalone binaries using `bun build --compile`.\n *\n * Expects the bundled entry to already exist in `outDir` (i.e., `build()` must\n * be run first). For each requested target (or the current platform if none\n * specified), spawns `bun build --compile` to produce a self-contained binary.\n *\n * @param params - The compile parameters including config and working directory.\n * @returns A result tuple with compile output on success or an Error on failure.\n */\nexport async function compile(params: CompileParams): AsyncResult<CompileOutput> {\n const resolved = resolveConfig(params)\n const bundledEntry = detectBuildEntry(resolved.buildOutDir)\n\n if (!bundledEntry) {\n return err(new Error(`bundled entry not found in ${resolved.buildOutDir} — run build() first`))\n }\n\n const targets: readonly CompileTarget[] = resolveTargets(resolved.compile.targets)\n const isMultiTarget = targets.length > 1\n\n const results = await Promise.all(\n targets.map(async (target) => {\n if (params.onTargetStart) {\n await params.onTargetStart(target)\n }\n\n const result = await compileSingleTarget({\n bundledEntry,\n isMultiTarget,\n name: resolved.compile.name,\n outDir: resolved.compileOutDir,\n target,\n })\n\n if (params.onTargetComplete) {\n await params.onTargetComplete(target)\n }\n\n return result\n })\n )\n\n cleanBunBuildArtifacts(resolved.cwd)\n\n const failedResult = results.find((r) => r[0] !== null)\n if (failedResult) {\n const [failedError] = failedResult\n if (failedError) {\n return err(failedError)\n }\n }\n\n const binaries: readonly CompiledBinary[] = results\n .filter((r): r is readonly [null, CompiledBinary] => r[1] !== null)\n .map(([, binary]) => binary)\n\n return ok({ binaries })\n}\n\n// ---------------------------------------------------------------------------\n\n/**\n * Compile a single target via `bun build --compile`.\n *\n * @private\n * @param params - Target compilation parameters.\n * @returns A result tuple with the compiled binary info or an error.\n */\nasync function compileSingleTarget(params: {\n readonly bundledEntry: string\n readonly outDir: string\n readonly name: string\n readonly target: CompileTarget\n readonly isMultiTarget: boolean\n}): AsyncResult<CompiledBinary> {\n const binaryName = resolveBinaryName(params.name, params.target, params.isMultiTarget)\n const outfile = join(params.outDir, binaryName)\n\n const args = [\n 'build',\n '--compile',\n params.bundledEntry,\n '--outfile',\n outfile,\n '--target',\n mapCompileTarget(params.target),\n ...COMPILE_EXTERNALS.flatMap((pkg) => ['--external', pkg]),\n ]\n\n const [execError] = await execBunBuild(args)\n if (execError) {\n return err(\n new Error(`bun build --compile failed for target ${params.target}`, { cause: execError })\n )\n }\n\n return ok({ label: resolveTargetLabel(params.target), path: outfile, target: params.target })\n}\n\n/**\n * Resolve the list of compile targets, falling back to the default set.\n *\n * When no targets are explicitly configured, defaults to linux-x64,\n * darwin-arm64, darwin-x64, and windows-x64 to cover ~95% of developers.\n *\n * @private\n * @param explicit - User-specified targets (may be empty).\n * @returns The targets to compile for.\n */\nfunction resolveTargets(explicit: readonly CompileTarget[]): readonly CompileTarget[] {\n if (explicit.length > 0) {\n return explicit\n }\n\n return DEFAULT_COMPILE_TARGETS\n}\n\n/**\n * Build the output binary name, appending the target suffix for multi-target builds.\n *\n * @private\n * @param name - Base binary name.\n * @param target - The compile target.\n * @param isMultiTarget - Whether multiple targets are being compiled.\n * @returns The resolved binary file name.\n */\nfunction resolveBinaryName(name: string, target: CompileTarget, isMultiTarget: boolean): string {\n if (isMultiTarget) {\n return `${name}-${target}`\n }\n\n return name\n}\n\n/**\n * Look up the human-readable label for a compile target.\n *\n * @param target - The compile target identifier.\n * @returns A descriptive label (e.g., \"macOS Apple Silicon\").\n */\nexport function resolveTargetLabel(target: CompileTarget): string {\n return COMPILE_TARGET_LABELS[target]\n}\n\n/**\n * Map a `CompileTarget` to Bun's `--target` string.\n *\n * Note: `linux-x64-musl` maps to `bun-linux-x64` because Bun's Linux\n * builds natively handle musl — there is no separate musl target.\n *\n * @private\n * @param target - The kidd compile target.\n * @returns The Bun target string (e.g., `'bun-darwin-arm64'`).\n */\nfunction mapCompileTarget(target: CompileTarget): string {\n if (target === 'linux-x64-musl') {\n return 'bun-linux-x64'\n }\n\n return `bun-${target}`\n}\n\n/**\n * Promisified wrapper around `execFile` to invoke `bun build`.\n *\n * @private\n * @param args - Arguments to pass to `bun`.\n * @returns A result tuple with stdout on success or an Error on failure.\n */\nfunction execBunBuild(args: readonly string[]): AsyncResult<string> {\n return new Promise((resolve) => {\n execFileCb('bun', [...args], (error, stdout) => {\n if (error) {\n resolve(err(error))\n return\n }\n\n resolve(ok(stdout))\n })\n })\n}\n\n/**\n * Remove temporary `.bun-build` files that `bun build --compile` leaves behind.\n *\n * @private\n * @param cwd - The working directory to clean.\n */\nfunction cleanBunBuildArtifacts(cwd: string): void {\n readdirSync(cwd)\n .filter((name) => name.endsWith('.bun-build'))\n .map((name) => join(cwd, name))\n .map(unlinkSync)\n}\n","import { err, ok } from '@kidd-cli/utils/fp'\nimport { build as tsdownBuild } from 'tsdown'\n\nimport { mapToWatchConfig } from './map-config.js'\nimport { resolveConfig } from './resolve-config.js'\nimport type { AsyncBundlerResult, WatchParams } from './types.js'\n\n/**\n * Start a watch-mode build for a kidd CLI tool using tsdown.\n *\n * The returned promise resolves only when tsdown's watch terminates (typically on process exit).\n * tsdown's `build()` with `watch: true` runs indefinitely.\n *\n * @param params - The watch parameters including config, working directory, and optional success callback.\n * @returns A result tuple with void on success or an Error on failure.\n */\nexport async function watch(params: WatchParams): AsyncBundlerResult<void> {\n const resolved = resolveConfig(params)\n const watchConfig = mapToWatchConfig({\n config: resolved,\n onSuccess: params.onSuccess,\n })\n\n try {\n await tsdownBuild(watchConfig)\n } catch (error: unknown) {\n return err(new Error('tsdown watch failed', { cause: error }))\n }\n\n return ok()\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["tsdownBuild","tsdownBuild"],"sources":["../src/generate-autoloader.ts","../src/scan-commands.ts","../src/autoload-plugin.ts","../src/constants.ts","../src/map-config.ts","../src/resolve-config.ts","../src/build.ts","../src/compile.ts","../src/watch.ts"],"sourcesContent":["import type { ScanResult, ScannedDir, ScannedFile } from './types.js'\n\n/**\n * Parameters for generating a static autoloader module.\n */\ninterface GenerateStaticAutoloaderParams {\n readonly scan: ScanResult\n readonly tagModulePath: string\n}\n\n/**\n * The two parts of a static autoloader transform: import statements to\n * prepend and the replacement code for the autoloader region.\n */\nexport interface StaticAutoloaderParts {\n readonly imports: string\n readonly region: string\n}\n\n/**\n * Generate JavaScript source code for a static autoloader virtual module.\n *\n * The generated module statically imports every discovered command file and\n * exports an `autoload()` function that returns the pre-built CommandMap.\n * Directory commands that merge a parent handler with subcommands are re-tagged\n * via `withTag` because the TAG symbol is non-enumerable and lost on spread.\n *\n * @param params - The scan result and path to the tag utility module.\n * @returns JavaScript source code for the static autoloader.\n */\nexport function generateStaticAutoloader(params: GenerateStaticAutoloaderParams): string {\n const imports = collectImports(params.scan)\n const importLines = buildImportStatements(imports, params.tagModulePath)\n const commandsObject = buildCommandsObject(params.scan)\n\n return [\n ...importLines,\n '',\n `const commands = ${commandsObject}`,\n '',\n 'export async function autoload() {',\n ' return commands',\n '}',\n '',\n ].join('\\n')\n}\n\n/**\n * Generate the two parts needed to transform kidd's bundled dist.\n *\n * Returns an empty imports string (no prepended imports needed) and a\n * replacement autoloader region that uses dynamic `import()` calls inside\n * the async `autoload()` function. This avoids circular dependency issues:\n * command files import `command` from `@kidd-cli/core`, so static imports would be\n * hoisted above kidd's own initialization code, causing `TAG` to be\n * accessed before initialization.\n *\n * By deferring to dynamic imports, kidd fully initializes first, then\n * command files are loaded when `autoload()` is called at CLI startup.\n *\n * @param params - The scan result and path to the tag utility module.\n * @returns Import statements (empty) and the replacement autoloader region.\n */\nexport function generateAutoloaderParts(\n params: GenerateStaticAutoloaderParams\n): StaticAutoloaderParts {\n const imports = collectImports(params.scan)\n\n if (imports.length === 0) {\n return {\n imports: '',\n region: buildEmptyAutoloaderRegion(),\n }\n }\n\n const commandsObject = buildCommandsObject(params.scan)\n const region = buildDynamicAutoloaderRegion(imports, commandsObject)\n\n return { imports: '', region }\n}\n\n// ---------------------------------------------------------------------------\n\n/**\n * A collected import entry with its identifier and absolute file path.\n *\n * @private\n */\ninterface ImportEntry {\n readonly identifier: string\n readonly filePath: string\n}\n\n/**\n * Collect all import entries from a scan result.\n *\n * @private\n * @param scan - The scan result to collect imports from.\n * @returns A flat array of all import entries.\n */\nfunction collectImports(scan: ScanResult): readonly ImportEntry[] {\n return [\n ...scan.files.map((file) => fileToImport(file, [])),\n ...scan.dirs.flatMap((dir) => collectDirImports(dir, [])),\n ]\n}\n\n/**\n * Recursively collect import entries from a scanned directory.\n *\n * @private\n * @param dir - The scanned directory.\n * @param parentPath - The path segments leading to this directory.\n * @returns A flat array of import entries for the directory and its children.\n */\nfunction collectDirImports(dir: ScannedDir, parentPath: readonly string[]): readonly ImportEntry[] {\n const currentPath = [...parentPath, dir.name]\n const indexImport: readonly ImportEntry[] = buildIndexImport(dir.index, currentPath)\n\n return [\n ...indexImport,\n ...dir.files.map((file) => fileToImport(file, currentPath)),\n ...dir.dirs.flatMap((sub) => collectDirImports(sub, currentPath)),\n ]\n}\n\n/**\n * Create an import entry for a leaf command file.\n *\n * @private\n * @param file - The scanned file.\n * @param parentPath - The path segments leading to the file's parent directory.\n * @returns An import entry with a generated identifier.\n */\nfunction fileToImport(file: ScannedFile, parentPath: readonly string[]): ImportEntry {\n return {\n filePath: file.filePath,\n identifier: toIdentifier([...parentPath, file.name]),\n }\n}\n\n/**\n * Convert a path segment array to a valid JavaScript identifier.\n *\n * Joins segments with underscores and prefixes with `_`.\n * Example: `['deploy', 'preview']` becomes `_deploy_preview`.\n *\n * @private\n * @param segments - The path segments to convert.\n * @returns A valid JavaScript identifier string.\n */\nfunction toIdentifier(segments: readonly string[]): string {\n return `_${segments.map((s) => s.replaceAll('-', '$')).join('_')}`\n}\n\n/**\n * Build the array of import statement lines.\n *\n * @private\n * @param imports - All collected import entries.\n * @param tagModulePath - Absolute path to the tag utility module.\n * @returns An array of import statement strings.\n */\nfunction buildImportStatements(\n imports: readonly ImportEntry[],\n tagModulePath: string\n): readonly string[] {\n const tagLine = buildTagImportLine(imports, tagModulePath)\n\n const importLines = imports.map((entry) => `import ${entry.identifier} from '${entry.filePath}'`)\n\n return [...tagLine, '', ...importLines]\n}\n\n/**\n * Build the JavaScript object literal string for the top-level commands map.\n *\n * @private\n * @param scan - The scan result.\n * @returns A string representation of the commands object literal.\n */\nfunction buildCommandsObject(scan: ScanResult): string {\n const entries = [\n ...scan.files.map((file) => buildFileEntry(file, [])),\n ...scan.dirs.map((dir) => buildDirEntry(dir, [])),\n ]\n\n return formatObject(entries)\n}\n\n/**\n * Build an object entry string for a leaf command file.\n *\n * @private\n * @param file - The scanned file.\n * @param parentPath - Path segments to the file's parent.\n * @returns A string like `'status': _status`.\n */\nfunction buildFileEntry(file: ScannedFile, parentPath: readonly string[]): string {\n const identifier = toIdentifier([...parentPath, file.name])\n return `'${file.name}': ${identifier}`\n}\n\n/**\n * Build an object entry string for a directory command (possibly with subcommands).\n *\n * @private\n * @param dir - The scanned directory.\n * @param parentPath - Path segments to the directory's parent.\n * @returns A string representing the directory command with withTag wrapping.\n */\nfunction buildDirEntry(dir: ScannedDir, parentPath: readonly string[]): string {\n const currentPath = [...parentPath, dir.name]\n const subEntries = [\n ...dir.files.map((file) => buildFileEntry(file, currentPath)),\n ...dir.dirs.map((sub) => buildDirEntry(sub, currentPath)),\n ]\n const commandsObj = formatObject(subEntries)\n\n if (dir.index) {\n const indexIdentifier = toIdentifier(currentPath)\n\n return `'${dir.name}': withTag({ ...${indexIdentifier}, commands: ${commandsObj} }, 'Command')`\n }\n\n return `'${dir.name}': withTag({ commands: ${commandsObj} }, 'Command')`\n}\n\n/**\n * Build the import entry for an index file, if present.\n *\n * @private\n * @param index - The absolute path to the index file, or undefined.\n * @param currentPath - The current path segments for identifier generation.\n * @returns An array with zero or one import entries.\n */\nfunction buildIndexImport(\n index: string | undefined,\n currentPath: readonly string[]\n): readonly ImportEntry[] {\n if (!index) {\n return []\n }\n return [{ filePath: index, identifier: toIdentifier(currentPath) }]\n}\n\n/**\n * Build the tag import line if any imports exist.\n *\n * @private\n * @param imports - The collected import entries.\n * @param tagModulePath - The absolute path to the tag module.\n * @returns An array with zero or one import statement strings.\n */\nfunction buildTagImportLine(\n imports: readonly ImportEntry[],\n tagModulePath: string\n): readonly string[] {\n if (imports.length === 0) {\n return []\n }\n return [`import { withTag } from '${tagModulePath}'`]\n}\n\n/**\n * Build the autoloader region for an empty scan result.\n *\n * @private\n * @returns A region string with an autoloader that returns an empty object.\n */\nfunction buildEmptyAutoloaderRegion(): string {\n return [\n '//#region src/autoloader.ts (static)',\n 'async function autoload() {',\n ' return {}',\n '}',\n '//#endregion',\n ].join('\\n')\n}\n\n/**\n * Build the autoloader region using dynamic `import()` calls.\n *\n * Uses `Promise.all` with array destructuring to load all command files\n * in parallel. The dynamic imports defer execution until `autoload()` is\n * called, avoiding circular dependency issues with kidd's own initialization.\n *\n * @private\n * @param imports - The collected import entries.\n * @param commandsObject - The commands object literal string.\n * @returns A region string with the full dynamic autoloader.\n */\nfunction buildDynamicAutoloaderRegion(\n imports: readonly ImportEntry[],\n commandsObject: string\n): string {\n const destructuring = imports.map((entry) => ` { default: ${entry.identifier} },`).join('\\n')\n\n const importCalls = imports.map((entry) => ` import('${entry.filePath}'),`).join('\\n')\n\n return [\n '//#region src/autoloader.ts (static)',\n 'async function autoload() {',\n ' const [',\n destructuring,\n ' ] = await Promise.all([',\n importCalls,\n ' ])',\n ` return ${commandsObject}`,\n '}',\n '//#endregion',\n ].join('\\n')\n}\n\n/**\n * Format an array of key-value strings as a JavaScript object literal.\n *\n * @private\n * @param entries - The key-value pair strings.\n * @returns A formatted object literal string.\n */\nfunction formatObject(entries: readonly string[]): string {\n if (entries.length === 0) {\n return '{}'\n }\n\n const body = entries.map((entry) => ` ${entry},`).join('\\n')\n return `{\\n${body}\\n}`\n}\n","import type { Dirent } from 'node:fs'\nimport { readdir } from 'node:fs/promises'\nimport { basename, extname, join } from 'node:path'\n\nimport type { ScanResult, ScannedDir, ScannedFile } from './types.js'\n\nconst VALID_EXTENSIONS = new Set(['.ts', '.js', '.mjs'])\nconst INDEX_NAME = 'index'\n\n/**\n * Scan a commands directory and produce a tree structure for static code generation.\n *\n * Mirrors the runtime autoloader's rules: valid extensions are `.ts`, `.js`, `.mjs`;\n * files and directories starting with `_` or `.` are skipped; `index` files in\n * subdirectories become parent command handlers.\n *\n * @param dir - Absolute path to the commands directory.\n * @returns A tree of scanned files and directories.\n */\nexport async function scanCommandsDir(dir: string): Promise<ScanResult> {\n const entries = await readdir(dir, { withFileTypes: true })\n\n const files = entries.filter(isCommandFile).map((entry) => toScannedFile(dir, entry))\n\n const dirs = await Promise.all(\n entries.filter(isCommandDir).map((entry) => scanSubDir(join(dir, entry.name)))\n )\n\n return { dirs, files }\n}\n\n// ---------------------------------------------------------------------------\n\n/**\n * Recursively scan a subdirectory into a ScannedDir.\n *\n * @private\n * @param dir - Absolute path to the subdirectory.\n * @returns A ScannedDir representing the directory and its contents.\n */\nasync function scanSubDir(dir: string): Promise<ScannedDir> {\n const name = basename(dir)\n const entries = await readdir(dir, { withFileTypes: true })\n const indexEntry = findIndexEntry(entries)\n\n const files = entries.filter(isCommandFile).map((entry) => toScannedFile(dir, entry))\n\n const dirs = await Promise.all(\n entries.filter(isCommandDir).map((entry) => scanSubDir(join(dir, entry.name)))\n )\n\n return {\n dirs,\n files,\n index: resolveIndexPath(dir, indexEntry),\n name,\n }\n}\n\n/**\n * Convert a directory entry into a ScannedFile.\n *\n * @private\n * @param dir - Parent directory absolute path.\n * @param entry - The directory entry for the file.\n * @returns A ScannedFile with name and absolute file path.\n */\nfunction toScannedFile(dir: string, entry: Dirent): ScannedFile {\n return {\n filePath: join(dir, entry.name),\n name: basename(entry.name, extname(entry.name)),\n }\n}\n\n/**\n * Find the index file entry among a list of directory entries.\n *\n * @private\n * @param entries - The directory entries to search.\n * @returns The Dirent for the index file, or undefined.\n */\nfunction findIndexEntry(entries: readonly Dirent[]): Dirent | undefined {\n return entries.find(\n (entry) =>\n entry.isFile() &&\n VALID_EXTENSIONS.has(extname(entry.name)) &&\n basename(entry.name, extname(entry.name)) === INDEX_NAME\n )\n}\n\n/**\n * Predicate: entry is a valid command file (not index, not hidden/private).\n *\n * @private\n * @param entry - The directory entry to check.\n * @returns True when the entry is a scannable command file.\n */\nfunction isCommandFile(entry: Dirent): boolean {\n if (!entry.isFile()) {\n return false\n }\n if (entry.name.startsWith('_') || entry.name.startsWith('.')) {\n return false\n }\n if (!VALID_EXTENSIONS.has(extname(entry.name))) {\n return false\n }\n return basename(entry.name, extname(entry.name)) !== INDEX_NAME\n}\n\n/**\n * Predicate: entry is a scannable command directory (not hidden/private).\n *\n * @private\n * @param entry - The directory entry to check.\n * @returns True when the entry is a scannable command directory.\n */\nfunction isCommandDir(entry: Dirent): boolean {\n if (!entry.isDirectory()) {\n return false\n }\n return !entry.name.startsWith('_') && !entry.name.startsWith('.')\n}\n\n/**\n * Resolve the absolute path to an index file entry, or undefined.\n *\n * @private\n * @param dir - The parent directory absolute path.\n * @param entry - The index file Dirent, or undefined.\n * @returns The absolute path to the index file, or undefined.\n */\nfunction resolveIndexPath(dir: string, entry: Dirent | undefined): string | undefined {\n if (!entry) {\n return undefined\n }\n return join(dir, entry.name)\n}\n","import type { Rolldown } from 'tsdown'\n\nimport { generateStaticAutoloader } from './generate-autoloader.js'\nimport { scanCommandsDir } from './scan-commands.js'\n\nconst VIRTUAL_MODULE_ID = 'virtual:kidd-static-commands'\nconst RESOLVED_VIRTUAL_ID = `\\0${VIRTUAL_MODULE_ID}`\n\nconst AUTOLOADER_REGION_START = '//#region src/autoloader.ts'\nconst AUTOLOADER_REGION_END = '//#endregion'\n\n/**\n * Parameters for creating the autoload plugin.\n */\ninterface CreateAutoloadPluginParams {\n readonly commandsDir: string\n readonly tagModulePath: string\n}\n\n/**\n * Create a rolldown plugin that replaces the runtime autoloader with a static version.\n *\n * Uses a three-hook approach to break the circular dependency between kidd's\n * dist and user command files (which `import { command } from '@kidd-cli/core'`):\n *\n * 1. `transform` — detects kidd's pre-bundled dist and replaces the autoloader\n * region with a dynamic `import()` to a virtual module\n * 2. `resolveId` — resolves the virtual module identifier\n * 3. `load` — scans the commands directory and generates a static autoloader\n * module with all command imports pre-resolved\n *\n * The dynamic import ensures command files execute after kidd's code is fully\n * initialized, avoiding `ReferenceError` from accessing `TAG` before its\n * declaration.\n *\n * @param params - The commands directory and tag module path.\n * @returns A rolldown plugin for static autoloading.\n */\nexport function createAutoloadPlugin(params: CreateAutoloadPluginParams): Rolldown.Plugin {\n return {\n async load(id) {\n if (id !== RESOLVED_VIRTUAL_ID) {\n return null\n }\n\n const scan = await scanCommandsDir(params.commandsDir)\n\n return generateStaticAutoloader({\n scan,\n tagModulePath: params.tagModulePath,\n })\n },\n name: 'kidd-static-autoloader',\n resolveId(source) {\n if (source === VIRTUAL_MODULE_ID) {\n return RESOLVED_VIRTUAL_ID\n }\n\n return null\n },\n transform(code, _id) {\n const regionStart = code.indexOf(AUTOLOADER_REGION_START)\n if (regionStart === -1) {\n return null\n }\n\n const regionEnd = code.indexOf(AUTOLOADER_REGION_END, regionStart)\n if (regionEnd === -1) {\n return null\n }\n\n const before = code.slice(0, regionStart)\n const after = code.slice(regionEnd + AUTOLOADER_REGION_END.length)\n const staticRegion = buildStaticRegion()\n\n return `${before}${staticRegion}${after}`\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n\n/**\n * Build the replacement autoloader region that delegates to the virtual module.\n *\n * @private\n * @returns The replacement region string with dynamic import.\n */\nfunction buildStaticRegion(): string {\n return [\n '//#region src/autoloader.ts (static)',\n 'async function autoload() {',\n ` const mod = await import('${VIRTUAL_MODULE_ID}')`,\n ' return mod.autoload()',\n '}',\n '//#endregion',\n ].join('\\n')\n}\n","import { builtinModules } from 'node:module'\n\nimport type { CompileTarget } from '@kidd-cli/config'\n\n/**\n * Shebang line prepended to CLI entry files.\n */\nexport const SHEBANG = '#!/usr/bin/env node\\n'\n\n/**\n * Default entry point for the CLI source.\n */\nexport const DEFAULT_ENTRY = './src/index.ts'\n\n/**\n * Default directory for CLI commands.\n */\nexport const DEFAULT_COMMANDS = './commands'\n\n/**\n * Default build output directory.\n */\nexport const DEFAULT_OUT_DIR = './dist'\n\n/**\n * Default Node.js target version for builds.\n */\nexport const DEFAULT_TARGET = 'node18'\n\n/**\n * Default minification setting.\n */\nexport const DEFAULT_MINIFY = false\n\n/**\n * Default source map generation setting.\n */\nexport const DEFAULT_SOURCEMAP = true\n\n/**\n * Default binary name for compiled SEA output.\n */\nexport const DEFAULT_BINARY_NAME = 'cli'\n\n/**\n * Default compile targets when none are explicitly configured.\n *\n * Covers Linux servers/CI, modern and Intel Macs, and Windows — roughly 95%\n * of developer environments.\n */\nexport const DEFAULT_COMPILE_TARGETS: readonly CompileTarget[] = [\n 'darwin-arm64',\n 'darwin-x64',\n 'linux-x64',\n 'windows-x64',\n]\n\n/**\n * Packages that must always be bundled into the output.\n *\n * The `@kidd-cli/core` framework and its internal `@kidd-cli/*` packages must be inlined\n * so the autoload plugin can intercept and replace the runtime autoloader\n * with a static version for compiled binaries.\n */\nexport const ALWAYS_BUNDLE: RegExp[] = [/^@?kidd/]\n\n/**\n * Node.js builtin modules in both bare and `node:` prefixed forms.\n */\nexport const NODE_BUILTINS: readonly string[] = [\n ...builtinModules,\n ...builtinModules.map((m) => `node:${m}`),\n]\n","import { createRequire } from 'node:module'\n\nimport type { InlineConfig } from 'tsdown'\n\nimport { createAutoloadPlugin } from './autoload-plugin.js'\nimport { ALWAYS_BUNDLE, NODE_BUILTINS, SHEBANG } from './constants.js'\nimport type { ResolvedBundlerConfig } from './types.js'\n\n/**\n * Map a resolved bundler config to a tsdown InlineConfig for production builds.\n *\n * @param config - The fully resolved bundler config.\n * @returns A tsdown InlineConfig ready for `build()`.\n */\nexport function mapToBuildConfig(config: ResolvedBundlerConfig): InlineConfig {\n return {\n banner: SHEBANG,\n clean: true,\n config: false,\n cwd: config.cwd,\n deps: {\n alwaysBundle: ALWAYS_BUNDLE,\n neverBundle: buildExternals(config.build.external),\n },\n dts: false,\n entry: { index: config.entry },\n format: 'esm',\n inputOptions: {\n resolve: {\n mainFields: ['module', 'main'],\n },\n },\n logLevel: 'info',\n minify: config.build.minify,\n outDir: config.buildOutDir,\n outputOptions: {\n codeSplitting: false,\n },\n platform: 'node',\n plugins: [\n createAutoloadPlugin({\n commandsDir: config.commands,\n tagModulePath: resolveTagModulePath(),\n }),\n ],\n sourcemap: config.build.sourcemap,\n target: config.build.target,\n treeshake: true,\n }\n}\n\n/**\n * Map a resolved bundler config to a tsdown InlineConfig for watch mode.\n *\n * @param params - The resolved config and optional success callback.\n * @returns A tsdown InlineConfig with `watch: true`.\n */\nexport function mapToWatchConfig(params: {\n readonly config: ResolvedBundlerConfig\n readonly onSuccess?: () => void | Promise<void>\n}): InlineConfig {\n const buildConfig = mapToBuildConfig(params.config)\n\n return {\n ...buildConfig,\n onSuccess: params.onSuccess,\n watch: true,\n }\n}\n\n// ---------------------------------------------------------------------------\n\n/**\n * Combine Node.js builtins with user-specified externals.\n *\n * @private\n * @param userExternals - Additional packages to mark as external.\n * @returns Combined array of externals for tsdown's `deps.neverBundle`.\n */\nfunction buildExternals(userExternals: readonly string[]): (string | RegExp)[] {\n return [...NODE_BUILTINS, ...userExternals]\n}\n\n/**\n * Resolve the absolute file path to the `@kidd-cli/utils/tag` module.\n *\n * The static autoloader virtual module imports `withTag` via this path.\n * Using an absolute path ensures rolldown can resolve the import from\n * inside the virtual module without relying on tsdown's `alwaysBundle`\n * heuristic, which virtual modules may bypass.\n *\n * @private\n * @returns The absolute file path to the tag module.\n */\nfunction resolveTagModulePath(): string {\n const require = createRequire(import.meta.url)\n return require.resolve('@kidd-cli/utils/tag')\n}\n","import { existsSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\n\nimport type { CompileOptions, KiddConfig } from '@kidd-cli/config'\n\nimport {\n DEFAULT_BINARY_NAME,\n DEFAULT_COMMANDS,\n DEFAULT_ENTRY,\n DEFAULT_MINIFY,\n DEFAULT_OUT_DIR,\n DEFAULT_SOURCEMAP,\n DEFAULT_TARGET,\n} from './constants.js'\nimport type { ResolvedBundlerConfig } from './types.js'\n\n/**\n * Known entry file names produced by tsdown for ESM builds, in preference order.\n */\nconst ENTRY_CANDIDATES = ['index.mjs', 'index.js'] as const\n\n/**\n * Normalize the `compile` config field from `boolean | CompileOptions | undefined` to `CompileOptions`.\n *\n * - `true` → `{}` (compile with defaults)\n * - `false` / `undefined` → `{}` (no explicit options, caller decides whether to compile)\n * - object → pass through\n *\n * @param value - The raw compile config value.\n * @returns A normalized CompileOptions object.\n */\nexport function normalizeCompileOptions(\n value: boolean | CompileOptions | undefined\n): CompileOptions {\n if (typeof value === 'object') {\n return value\n }\n\n return {}\n}\n\n/**\n * Fill defaults and resolve relative paths against `cwd`.\n *\n * This is a pure function — the incoming config is already validated by `@kidd-cli/config`.\n * It only fills missing optional fields with defaults and resolves paths to absolute.\n *\n * @param params - The raw config and working directory.\n * @returns A fully resolved bundler configuration.\n */\nexport function resolveConfig(params: {\n readonly config: KiddConfig\n readonly cwd: string\n}): ResolvedBundlerConfig {\n const { config, cwd } = params\n\n const entry = resolve(cwd, config.entry ?? DEFAULT_ENTRY)\n const commands = resolve(cwd, config.commands ?? DEFAULT_COMMANDS)\n\n const buildOpts = config.build ?? {}\n const compileOpts = normalizeCompileOptions(config.compile)\n\n const buildOutDir = resolve(cwd, buildOpts.out ?? DEFAULT_OUT_DIR)\n const compileOutDir = resolve(cwd, compileOpts.out ?? DEFAULT_OUT_DIR)\n\n return {\n build: {\n external: buildOpts.external ?? [],\n minify: buildOpts.minify ?? DEFAULT_MINIFY,\n sourcemap: buildOpts.sourcemap ?? DEFAULT_SOURCEMAP,\n target: buildOpts.target ?? DEFAULT_TARGET,\n },\n buildOutDir,\n commands,\n compile: {\n name: compileOpts.name ?? DEFAULT_BINARY_NAME,\n targets: compileOpts.targets ?? [],\n },\n compileOutDir,\n cwd,\n entry,\n include: config.include ?? [],\n }\n}\n\n/**\n * Detect the bundled entry file in a build output directory.\n *\n * tsdown may produce `index.mjs` or `index.js` depending on the project's\n * `package.json` `type` field and tsdown configuration. This function checks\n * for both candidates and returns the first one that exists on disk.\n *\n * @param outDir - Absolute path to the build output directory.\n * @returns The absolute path to the entry file, or `undefined` when none is found.\n */\nexport function detectBuildEntry(outDir: string): string | undefined {\n return ENTRY_CANDIDATES.map((name) => join(outDir, name)).find(existsSync)\n}\n","import { err, ok } from '@kidd-cli/utils/fp'\nimport { build as tsdownBuild } from 'tsdown'\n\nimport { mapToBuildConfig } from './map-config.js'\nimport { detectBuildEntry, resolveConfig } from './resolve-config.js'\nimport type { AsyncBundlerResult, BuildOutput, BuildParams } from './types.js'\n\n/**\n * Build a kidd CLI tool using tsdown.\n *\n * Resolves defaults, maps the config to tsdown's InlineConfig, and invokes the build.\n *\n * @param params - The build parameters including config and working directory.\n * @returns A result tuple with build output on success or an Error on failure.\n */\nexport async function build(params: BuildParams): AsyncBundlerResult<BuildOutput> {\n const resolved = resolveConfig(params)\n const inlineConfig = mapToBuildConfig(resolved)\n\n try {\n await tsdownBuild(inlineConfig)\n } catch (error: unknown) {\n console.error('[kidd-bundler] build error:', error)\n return err(new Error('tsdown build failed', { cause: error }))\n }\n\n const entryFile = detectBuildEntry(resolved.buildOutDir)\n\n if (!entryFile) {\n return err(new Error(`build produced no entry file in ${resolved.buildOutDir}`))\n }\n\n return ok({\n entryFile,\n outDir: resolved.buildOutDir,\n })\n}\n","import { execFile as execFileCb } from 'node:child_process'\nimport { readdirSync, unlinkSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport type { CompileTarget } from '@kidd-cli/config'\nimport { err, ok } from '@kidd-cli/utils/fp'\nimport type { AsyncResult } from '@kidd-cli/utils/fp'\n\nimport { DEFAULT_COMPILE_TARGETS } from './constants.js'\nimport { detectBuildEntry, resolveConfig } from './resolve-config.js'\nimport type { CompileOutput, CompileParams, CompiledBinary } from './types.js'\n\n/**\n * Packages to externalize during `bun build --compile`.\n *\n * These are optional peer dependencies of `c12` (the config loader) that bun\n * eagerly tries to resolve even though they are behind dynamic `import()` calls\n * that never execute at runtime in a compiled CLI.\n */\nconst COMPILE_EXTERNALS: readonly string[] = ['chokidar', 'magicast', 'giget']\n\n/**\n * Human-readable labels for each compile target.\n */\nconst COMPILE_TARGET_LABELS: Readonly<Record<CompileTarget, string>> = {\n 'darwin-arm64': 'macOS Apple Silicon',\n 'darwin-x64': 'macOS Intel',\n 'linux-arm64': 'Linux ARM64',\n 'linux-x64': 'Linux x64',\n 'linux-x64-musl': 'Linux x64 (musl)',\n 'windows-arm64': 'Windows ARM64',\n 'windows-x64': 'Windows x64',\n}\n\n/**\n * Compile a kidd CLI tool into standalone binaries using `bun build --compile`.\n *\n * Expects the bundled entry to already exist in `outDir` (i.e., `build()` must\n * be run first). For each requested target (or the current platform if none\n * specified), spawns `bun build --compile` to produce a self-contained binary.\n *\n * @param params - The compile parameters including config and working directory.\n * @returns A result tuple with compile output on success or an Error on failure.\n */\nexport async function compile(params: CompileParams): AsyncResult<CompileOutput> {\n const resolved = resolveConfig(params)\n const bundledEntry = detectBuildEntry(resolved.buildOutDir)\n\n if (!bundledEntry) {\n return err(new Error(`bundled entry not found in ${resolved.buildOutDir} — run build() first`))\n }\n\n const targets: readonly CompileTarget[] = resolveTargets(resolved.compile.targets)\n const isMultiTarget = targets.length > 1\n\n const results = await Promise.all(\n targets.map(async (target) => {\n if (params.onTargetStart) {\n await params.onTargetStart(target)\n }\n\n const result = await compileSingleTarget({\n bundledEntry,\n isMultiTarget,\n name: resolved.compile.name,\n outDir: resolved.compileOutDir,\n target,\n })\n\n if (params.onTargetComplete) {\n await params.onTargetComplete(target)\n }\n\n return result\n })\n )\n\n cleanBunBuildArtifacts(resolved.cwd)\n\n const failedResult = results.find((r) => r[0] !== null)\n if (failedResult) {\n const [failedError] = failedResult\n if (failedError) {\n return err(failedError)\n }\n }\n\n const binaries: readonly CompiledBinary[] = results\n .filter((r): r is readonly [null, CompiledBinary] => r[1] !== null)\n .map(([, binary]) => binary)\n\n return ok({ binaries })\n}\n\n// ---------------------------------------------------------------------------\n\n/**\n * Compile a single target via `bun build --compile`.\n *\n * @private\n * @param params - Target compilation parameters.\n * @returns A result tuple with the compiled binary info or an error.\n */\nasync function compileSingleTarget(params: {\n readonly bundledEntry: string\n readonly outDir: string\n readonly name: string\n readonly target: CompileTarget\n readonly isMultiTarget: boolean\n}): AsyncResult<CompiledBinary> {\n const binaryName = resolveBinaryName(params.name, params.target, params.isMultiTarget)\n const outfile = join(params.outDir, binaryName)\n\n const args = [\n 'build',\n '--compile',\n params.bundledEntry,\n '--outfile',\n outfile,\n '--target',\n mapCompileTarget(params.target),\n ...COMPILE_EXTERNALS.flatMap((pkg) => ['--external', pkg]),\n ]\n\n const [execError] = await execBunBuild(args)\n if (execError) {\n return err(\n new Error(`bun build --compile failed for target ${params.target}`, { cause: execError })\n )\n }\n\n return ok({ label: resolveTargetLabel(params.target), path: outfile, target: params.target })\n}\n\n/**\n * Resolve the list of compile targets, falling back to the default set.\n *\n * When no targets are explicitly configured, defaults to linux-x64,\n * darwin-arm64, darwin-x64, and windows-x64 to cover ~95% of developers.\n *\n * @private\n * @param explicit - User-specified targets (may be empty).\n * @returns The targets to compile for.\n */\nfunction resolveTargets(explicit: readonly CompileTarget[]): readonly CompileTarget[] {\n if (explicit.length > 0) {\n return explicit\n }\n\n return DEFAULT_COMPILE_TARGETS\n}\n\n/**\n * Build the output binary name, appending the target suffix for multi-target builds.\n *\n * @private\n * @param name - Base binary name.\n * @param target - The compile target.\n * @param isMultiTarget - Whether multiple targets are being compiled.\n * @returns The resolved binary file name.\n */\nfunction resolveBinaryName(name: string, target: CompileTarget, isMultiTarget: boolean): string {\n if (isMultiTarget) {\n return `${name}-${target}`\n }\n\n return name\n}\n\n/**\n * Look up the human-readable label for a compile target.\n *\n * @param target - The compile target identifier.\n * @returns A descriptive label (e.g., \"macOS Apple Silicon\").\n */\nexport function resolveTargetLabel(target: CompileTarget): string {\n return COMPILE_TARGET_LABELS[target]\n}\n\n/**\n * Map a `CompileTarget` to Bun's `--target` string.\n *\n * Note: `linux-x64-musl` maps to `bun-linux-x64` because Bun's Linux\n * builds natively handle musl — there is no separate musl target.\n *\n * @private\n * @param target - The kidd compile target.\n * @returns The Bun target string (e.g., `'bun-darwin-arm64'`).\n */\nfunction mapCompileTarget(target: CompileTarget): string {\n if (target === 'linux-x64-musl') {\n return 'bun-linux-x64'\n }\n\n return `bun-${target}`\n}\n\n/**\n * Promisified wrapper around `execFile` to invoke `bun build`.\n *\n * @private\n * @param args - Arguments to pass to `bun`.\n * @returns A result tuple with stdout on success or an Error on failure.\n */\nfunction execBunBuild(args: readonly string[]): AsyncResult<string> {\n return new Promise((resolve) => {\n execFileCb('bun', [...args], (error, stdout) => {\n if (error) {\n resolve(err(error))\n return\n }\n\n resolve(ok(stdout))\n })\n })\n}\n\n/**\n * Remove temporary `.bun-build` files that `bun build --compile` leaves behind.\n *\n * @private\n * @param cwd - The working directory to clean.\n */\nfunction cleanBunBuildArtifacts(cwd: string): void {\n readdirSync(cwd)\n .filter((name) => name.endsWith('.bun-build'))\n .map((name) => join(cwd, name))\n .map(unlinkSync)\n}\n","import { err, ok } from '@kidd-cli/utils/fp'\nimport { build as tsdownBuild } from 'tsdown'\n\nimport { mapToWatchConfig } from './map-config.js'\nimport { resolveConfig } from './resolve-config.js'\nimport type { AsyncBundlerResult, WatchParams } from './types.js'\n\n/**\n * Start a watch-mode build for a kidd CLI tool using tsdown.\n *\n * The returned promise resolves only when tsdown's watch terminates (typically on process exit).\n * tsdown's `build()` with `watch: true` runs indefinitely.\n *\n * @param params - The watch parameters including config, working directory, and optional success callback.\n * @returns A result tuple with void on success or an Error on failure.\n */\nexport async function watch(params: WatchParams): AsyncBundlerResult<void> {\n const resolved = resolveConfig(params)\n const watchConfig = mapToWatchConfig({\n config: resolved,\n onSuccess: params.onSuccess,\n })\n\n try {\n await tsdownBuild(watchConfig)\n } catch (error: unknown) {\n return err(new Error('tsdown watch failed', { cause: error }))\n }\n\n return ok()\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kidd-cli/bundler",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Programmatic bundler for kidd CLI tools powered by tsdown",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -19,15 +19,15 @@
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"es-toolkit": "^1.45.
|
|
22
|
+
"es-toolkit": "^1.45.1",
|
|
23
23
|
"ts-pattern": "^5.9.0",
|
|
24
|
-
"tsdown": "0.21.
|
|
24
|
+
"tsdown": "0.21.1",
|
|
25
25
|
"zod": "^4.3.6",
|
|
26
|
-
"@kidd-cli/config": "0.1.
|
|
27
|
-
"@kidd-cli/utils": "0.1.
|
|
26
|
+
"@kidd-cli/config": "0.1.3",
|
|
27
|
+
"@kidd-cli/utils": "0.1.3"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@types/node": "^25.
|
|
30
|
+
"@types/node": "^25.4.0",
|
|
31
31
|
"typescript": "^5.9.3",
|
|
32
32
|
"vitest": "^4.0.18"
|
|
33
33
|
},
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"lint": "oxlint --ignore-pattern node_modules",
|
|
38
38
|
"lint:fix": "oxlint --fix --ignore-pattern node_modules",
|
|
39
39
|
"test": "vitest run",
|
|
40
|
+
"test:coverage": "vitest run --coverage",
|
|
40
41
|
"test:watch": "vitest"
|
|
41
42
|
}
|
|
42
43
|
}
|