@kidd-cli/bundler 0.1.2 → 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.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,7 +351,6 @@ 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";
@@ -420,7 +417,6 @@ function buildStaticRegion() {
420
417
  "//#endregion"
421
418
  ].join("\n");
422
419
  }
423
-
424
420
  //#endregion
425
421
  //#region src/constants.ts
426
422
  /**
@@ -428,34 +424,6 @@ function buildStaticRegion() {
428
424
  */
429
425
  const SHEBANG = "#!/usr/bin/env node\n";
430
426
  /**
431
- * Default entry point for the CLI source.
432
- */
433
- const DEFAULT_ENTRY = "./src/index.ts";
434
- /**
435
- * Default directory for CLI commands.
436
- */
437
- const DEFAULT_COMMANDS = "./commands";
438
- /**
439
- * Default build output directory.
440
- */
441
- const DEFAULT_OUT_DIR = "./dist";
442
- /**
443
- * Default Node.js target version for builds.
444
- */
445
- const DEFAULT_TARGET = "node18";
446
- /**
447
- * Default minification setting.
448
- */
449
- const DEFAULT_MINIFY = false;
450
- /**
451
- * Default source map generation setting.
452
- */
453
- const DEFAULT_SOURCEMAP = true;
454
- /**
455
- * Default binary name for compiled SEA output.
456
- */
457
- const DEFAULT_BINARY_NAME = "cli";
458
- /**
459
427
  * Default compile targets when none are explicitly configured.
460
428
  *
461
429
  * Covers Linux servers/CI, modern and Intel Macs, and Windows — roughly 95%
@@ -479,7 +447,6 @@ const ALWAYS_BUNDLE = [/^@?kidd/];
479
447
  * Node.js builtin modules in both bare and `node:` prefixed forms.
480
448
  */
481
449
  const NODE_BUILTINS = [...builtinModules, ...builtinModules.map((m) => `node:${m}`)];
482
-
483
450
  //#endregion
484
451
  //#region src/map-config.ts
485
452
  /**
@@ -553,7 +520,6 @@ function buildExternals(userExternals) {
553
520
  function resolveTagModulePath() {
554
521
  return createRequire(import.meta.url).resolve("@kidd-cli/utils/tag");
555
522
  }
556
-
557
523
  //#endregion
558
524
  //#region src/resolve-config.ts
559
525
  /**
@@ -585,23 +551,23 @@ function normalizeCompileOptions(value) {
585
551
  */
586
552
  function resolveConfig(params) {
587
553
  const { config, cwd } = params;
588
- const entry = resolve(cwd, config.entry ?? DEFAULT_ENTRY);
589
- const commands = resolve(cwd, config.commands ?? DEFAULT_COMMANDS);
554
+ const entry = resolve(cwd, config.entry ?? "./src/index.ts");
555
+ const commands = resolve(cwd, config.commands ?? "./commands");
590
556
  const buildOpts = config.build ?? {};
591
557
  const compileOpts = normalizeCompileOptions(config.compile);
592
- const buildOutDir = resolve(cwd, buildOpts.out ?? DEFAULT_OUT_DIR);
593
- const compileOutDir = resolve(cwd, compileOpts.out ?? DEFAULT_OUT_DIR);
558
+ const buildOutDir = resolve(cwd, buildOpts.out ?? "./dist");
559
+ const compileOutDir = resolve(cwd, compileOpts.out ?? "./dist");
594
560
  return {
595
561
  build: {
596
562
  external: buildOpts.external ?? [],
597
- minify: buildOpts.minify ?? DEFAULT_MINIFY,
598
- sourcemap: buildOpts.sourcemap ?? DEFAULT_SOURCEMAP,
599
- target: buildOpts.target ?? DEFAULT_TARGET
563
+ minify: buildOpts.minify ?? false,
564
+ sourcemap: buildOpts.sourcemap ?? true,
565
+ target: buildOpts.target ?? "node18"
600
566
  },
601
567
  buildOutDir,
602
568
  commands,
603
569
  compile: {
604
- name: compileOpts.name ?? DEFAULT_BINARY_NAME,
570
+ name: compileOpts.name ?? "cli",
605
571
  targets: compileOpts.targets ?? []
606
572
  },
607
573
  compileOutDir,
@@ -623,7 +589,6 @@ function resolveConfig(params) {
623
589
  function detectBuildEntry(outDir) {
624
590
  return ENTRY_CANDIDATES.map((name) => join(outDir, name)).find(existsSync);
625
591
  }
626
-
627
592
  //#endregion
628
593
  //#region src/build.ts
629
594
  /**
@@ -650,7 +615,6 @@ async function build(params) {
650
615
  outDir: resolved.buildOutDir
651
616
  });
652
617
  }
653
-
654
618
  //#endregion
655
619
  //#region src/compile.ts
656
620
  /**
@@ -817,7 +781,6 @@ function execBunBuild(args) {
817
781
  function cleanBunBuildArtifacts(cwd) {
818
782
  readdirSync(cwd).filter((name) => name.endsWith(".bun-build")).map((name) => join(cwd, name)).map(unlinkSync);
819
783
  }
820
-
821
784
  //#endregion
822
785
  //#region src/watch.ts
823
786
  /**
@@ -841,7 +804,7 @@ async function watch(params) {
841
804
  }
842
805
  return ok();
843
806
  }
844
-
845
807
  //#endregion
846
808
  export { build, compile, createAutoloadPlugin, detectBuildEntry, generateAutoloaderParts, generateStaticAutoloader, mapToBuildConfig, mapToWatchConfig, normalizeCompileOptions, resolveConfig, resolveTargetLabel, scanCommandsDir, watch };
809
+
847
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'\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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"}
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.2",
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.0",
22
+ "es-toolkit": "^1.45.1",
23
23
  "ts-pattern": "^5.9.0",
24
- "tsdown": "0.21.0-beta.2",
24
+ "tsdown": "0.21.1",
25
25
  "zod": "^4.3.6",
26
- "@kidd-cli/config": "0.1.2",
27
- "@kidd-cli/utils": "0.1.2"
26
+ "@kidd-cli/config": "0.1.3",
27
+ "@kidd-cli/utils": "0.1.3"
28
28
  },
29
29
  "devDependencies": {
30
- "@types/node": "^25.3.3",
30
+ "@types/node": "^25.4.0",
31
31
  "typescript": "^5.9.3",
32
32
  "vitest": "^4.0.18"
33
33
  },