@long.dg/le-restaurant 0.1.0 → 0.1.1
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.
|
@@ -227,8 +227,65 @@ function writeOutputs(outputs, ctx) {
|
|
|
227
227
|
return results;
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
+
// package.json
|
|
231
|
+
var package_default = {
|
|
232
|
+
name: "@long.dg/le-restaurant",
|
|
233
|
+
version: "0.1.1",
|
|
234
|
+
description: "Install the brigade of agent skills into your project, translated for your coding agent.",
|
|
235
|
+
type: "module",
|
|
236
|
+
publishConfig: {
|
|
237
|
+
access: "public"
|
|
238
|
+
},
|
|
239
|
+
bin: {
|
|
240
|
+
"le-restaurant": "dist/cli.js"
|
|
241
|
+
},
|
|
242
|
+
main: "./dist/index.js",
|
|
243
|
+
module: "./dist/index.js",
|
|
244
|
+
types: "./dist/index.d.ts",
|
|
245
|
+
files: [
|
|
246
|
+
"dist",
|
|
247
|
+
"skills"
|
|
248
|
+
],
|
|
249
|
+
scripts: {
|
|
250
|
+
build: "tsup",
|
|
251
|
+
dev: "tsup --watch",
|
|
252
|
+
test: "vitest run",
|
|
253
|
+
"test:watch": "vitest",
|
|
254
|
+
typecheck: "tsc --noEmit",
|
|
255
|
+
"check:sync": "vitest run test/check-skills-sync.test.ts"
|
|
256
|
+
},
|
|
257
|
+
keywords: [
|
|
258
|
+
"claude",
|
|
259
|
+
"codex",
|
|
260
|
+
"gemini",
|
|
261
|
+
"skills",
|
|
262
|
+
"cli"
|
|
263
|
+
],
|
|
264
|
+
repository: {
|
|
265
|
+
type: "git",
|
|
266
|
+
url: "git+https://github.com/dglong/le-restaurant.git"
|
|
267
|
+
},
|
|
268
|
+
homepage: "https://github.com/dglong/le-restaurant#readme",
|
|
269
|
+
bugs: {
|
|
270
|
+
url: "https://github.com/dglong/le-restaurant/issues"
|
|
271
|
+
},
|
|
272
|
+
author: "",
|
|
273
|
+
license: "MIT",
|
|
274
|
+
dependencies: {
|
|
275
|
+
"@clack/prompts": "^1.6.0",
|
|
276
|
+
commander: "^14.0.1",
|
|
277
|
+
"gray-matter": "^4.0.3"
|
|
278
|
+
},
|
|
279
|
+
devDependencies: {
|
|
280
|
+
"@types/node": "^24.10.1",
|
|
281
|
+
tsup: "^8.5.0",
|
|
282
|
+
typescript: "^5.9.3",
|
|
283
|
+
vitest: "^3.2.4"
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
|
|
230
287
|
// src/cli.ts
|
|
231
|
-
var VERSION =
|
|
288
|
+
var VERSION = package_default.version;
|
|
232
289
|
var ADAPTERS = {
|
|
233
290
|
claude: claudeAdapter,
|
|
234
291
|
codex: codexAdapter,
|
|
@@ -382,4 +439,4 @@ export {
|
|
|
382
439
|
runCli,
|
|
383
440
|
run
|
|
384
441
|
};
|
|
385
|
-
//# sourceMappingURL=chunk-
|
|
442
|
+
//# sourceMappingURL=chunk-SWHUS5EX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/adapters/claude.ts","../src/registry.ts","../src/markers.ts","../src/adapters/codex.ts","../src/adapters/gemini.ts","../src/summary.ts","../src/writer.ts","../package.json"],"sourcesContent":["import { Command, CommanderError } from \"commander\";\nimport { claudeAdapter } from \"./adapters/claude.js\";\nimport { codexAdapter } from \"./adapters/codex.js\";\nimport { geminiAdapter } from \"./adapters/gemini.js\";\nimport type { Adapter } from \"./adapters/types.js\";\nimport { loadSkills } from \"./registry.js\";\nimport { renderSummary } from \"./summary.js\";\nimport type { ConflictPolicy, InstallContext, Skill } from \"./types.js\";\nimport { writeOutputs, type WriteResult } from \"./writer.js\";\nimport pkg from \"../package.json\" with { type: \"json\" };\n\n// Single source of truth: the published package version. `tsup` inlines this at\n// build time, so `npm version` bumping package.json is all that's needed.\nconst VERSION = pkg.version;\n\n/** The agents we can install for. */\nexport type AgentId = \"claude\" | \"codex\" | \"gemini\";\n\n/** Adapter registry, keyed by agent id. The single dispatch table. */\nconst ADAPTERS: Record<AgentId, Adapter> = {\n claude: claudeAdapter,\n codex: codexAdapter,\n gemini: geminiAdapter,\n};\n\n/** Valid agent ids, for validation + help text. */\nexport const AGENT_IDS = Object.keys(ADAPTERS) as AgentId[];\n\n/**\n * Map a chosen agent id to its adapter.\n *\n * Throws a clear error on an unknown id so both the CLI (non-zero exit) and\n * library callers fail loudly rather than silently installing the wrong thing.\n */\nexport function selectAdapter(agentId: string): Adapter {\n const adapter = ADAPTERS[agentId as AgentId];\n if (!adapter) {\n throw new Error(\n `Unknown agent \"${agentId}\". Choose one of: ${AGENT_IDS.join(\", \")}.`,\n );\n }\n return adapter;\n}\n\n/**\n * The conflict policy to use for an agent by default.\n *\n * Claude's passthrough files are fully tool-owned, so they overwrite. The\n * Codex/Gemini marker targets (`AGENTS.md`, `GEMINI.md`) merge so user content\n * outside the managed markers is preserved on re-runs.\n */\nexport function defaultConflictPolicy(agentId: string): ConflictPolicy {\n return agentId === \"claude\" ? \"overwrite\" : \"merge\";\n}\n\n/**\n * Resolve a `--skills` value into the concrete list of skills to install.\n *\n * Accepts the literal `all` (every available skill) or a comma-separated list\n * of skill names (order/whitespace tolerant). Throws clearly on an empty\n * selection or any unknown name.\n */\nexport function resolveSkillSelection(\n spec: string,\n available: Skill[],\n): Skill[] {\n const trimmed = (spec ?? \"\").trim();\n if (trimmed.toLowerCase() === \"all\") return available;\n\n const names = trimmed\n .split(\",\")\n .map((n) => n.trim())\n .filter((n) => n.length > 0);\n if (names.length === 0) {\n throw new Error(\n `No skills selected. Use --skills all or a comma list (e.g. ${available\n .map((s) => s.name)\n .slice(0, 2)\n .join(\",\")}).`,\n );\n }\n\n const byName = new Map(available.map((s) => [s.name, s]));\n const unknown = names.filter((n) => !byName.has(n));\n if (unknown.length > 0) {\n throw new Error(\n `Unknown skill(s): ${unknown.join(\", \")}. Available: ${available\n .map((s) => s.name)\n .join(\", \")}.`,\n );\n }\n return names.map((n) => byName.get(n)!);\n}\n\n/** A resolved, ready-to-run install request. */\nexport interface InstallRequest {\n agentId: AgentId;\n skills: Skill[];\n targetDir: string;\n conflictPolicy?: ConflictPolicy;\n}\n\n/**\n * Translate the selected skills with the chosen adapter and write them to the\n * target dir. The single install primitive shared by the flag and wizard paths.\n */\nexport function runInstall(req: InstallRequest): {\n adapter: Adapter;\n results: WriteResult[];\n} {\n const adapter = selectAdapter(req.agentId);\n const ctx: InstallContext = {\n targetDir: req.targetDir,\n selectedSkills: req.skills,\n conflictPolicy: req.conflictPolicy ?? defaultConflictPolicy(req.agentId),\n };\n const outputs = adapter.translate(req.skills, ctx);\n const results = writeOutputs(outputs, ctx);\n return { adapter, results };\n}\n\n/** Options collected from the non-interactive flags. */\ninterface InstallFlags {\n agent?: string;\n skills?: string;\n yes?: boolean;\n}\n\n/**\n * Resolve raw `--agent`/`--skills` flags into a validated install request.\n * Throws clearly (non-zero exit upstream) on any invalid value.\n */\nexport function resolveFlags(\n flags: InstallFlags,\n targetDir: string,\n available: Skill[],\n): InstallRequest {\n if (!flags.agent) {\n throw new Error(\"Missing --agent. Choose one of: \" + AGENT_IDS.join(\", \"));\n }\n selectAdapter(flags.agent); // validates the agent id\n const skills = resolveSkillSelection(flags.skills ?? \"all\", available);\n return { agentId: flags.agent as AgentId, skills, targetDir };\n}\n\n/** Run an install request and print its post-install summary. */\nfunction installAndReport(req: InstallRequest): void {\n const { adapter, results } = runInstall(req);\n console.log(\n renderSummary({\n agentId: adapter.id,\n agentLabel: adapter.label,\n results,\n }),\n );\n}\n\n/**\n * Build the commander program. Factored out so tests can introspect the\n * wired-up commands/options without spawning a process.\n */\nexport function buildProgram(): Command {\n const program = new Command();\n\n program\n .name(\"le-restaurant\")\n .description(\n \"Install the brigade of agent skills into your project, translated for your coding agent.\",\n )\n .version(VERSION);\n\n // Root command: non-interactive flags, or the wizard when no agent is given.\n program\n .argument(\"[targetDir]\", \"target project directory\", \".\")\n .option(\n \"--agent <agent>\",\n `target coding agent (${AGENT_IDS.join(\"|\")})`,\n )\n .option(\n \"--skills <skills>\",\n \"skills to install: 'all' or a comma-separated list\",\n )\n .option(\"--yes\", \"skip prompts; install with the given flags\", false)\n .action(async (targetDir: string, opts: InstallFlags) => {\n const available = loadSkills();\n\n // No agent flag → interactive wizard.\n if (!opts.agent) {\n const { runWizard } = await import(\"./wizard.js\");\n const choice = await runWizard(available);\n if (!choice) return; // cancelled\n installAndReport({\n agentId: choice.agentId,\n skills: choice.skills,\n targetDir,\n });\n return;\n }\n\n // Non-interactive: validate flags (throws → non-zero exit upstream).\n installAndReport(resolveFlags(opts, targetDir, available));\n });\n\n program\n .command(\"list\")\n .description(\"List the skills available to install.\")\n .action(() => {\n const skills = loadSkills();\n for (const skill of skills) {\n console.log(`- ${skill.name}: ${skill.description}`);\n }\n });\n\n return program;\n}\n\n/**\n * Parse argv, run the CLI, and resolve to the process exit code.\n *\n * commander is put in `exitOverride` mode so it throws instead of calling\n * `process.exit`, letting us (and tests) observe the exit code. Help/version\n * exit 0; parse/validation errors exit non-zero.\n */\nexport async function runCli(argv: string[] = process.argv): Promise<number> {\n const program = buildProgram();\n program.exitOverride();\n program.configureOutput({\n writeErr: (str) => process.stderr.write(str),\n });\n try {\n await program.parseAsync(argv);\n return Number(process.exitCode ?? 0);\n } catch (err) {\n if (err instanceof CommanderError) {\n // --help / --version resolve to exitCode 0; parse errors are non-zero.\n return err.exitCode;\n }\n console.error(err instanceof Error ? err.message : String(err));\n return 1;\n }\n}\n\n/** Convenience entry: run and let the process adopt the resolved exit code. */\nexport function run(argv: string[] = process.argv): Promise<number> {\n return runCli(argv).then((code) => {\n process.exitCode = code;\n return code;\n });\n}\n\n// Execute when invoked as the bin (not when imported by tests).\nconst invokedDirectly =\n typeof process !== \"undefined\" &&\n process.argv[1] !== undefined &&\n /cli\\.(js|ts)$/.test(process.argv[1]);\n\nif (invokedDirectly) {\n void run();\n}\n","import { readFileSync } from \"node:fs\";\nimport { skillSourcePath } from \"../registry.js\";\nimport type { FileOutput, InstallContext, Skill } from \"../types.js\";\nimport type { Adapter } from \"./types.js\";\n\n/**\n * Claude Code — passthrough strategy.\n *\n * Claude Code natively supports on-demand skills, so we copy each source\n * `SKILL.md` verbatim to `.claude/skills/<name>/SKILL.md`. To guarantee\n * byte-for-byte fidelity we read the original vendored file rather than\n * re-serialize the normalized `Skill` (which would lose exact formatting).\n */\nexport const claudeAdapter: Adapter = {\n id: \"claude\",\n label: \"Claude Code\",\n translate(skills: Skill[], _ctx: InstallContext): FileOutput[] {\n return skills.map((skill) => ({\n path: `.claude/skills/${skill.name}/SKILL.md`,\n contents: readFileSync(skillSourcePath(skill.name), \"utf8\"),\n mode: \"overwrite\",\n }));\n },\n};\n","import { readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport matter from \"gray-matter\";\nimport type { Skill } from \"./types.js\";\n\nconst moduleDir = dirname(fileURLToPath(import.meta.url));\n\n/**\n * Absolute path to the vendored source skills.\n *\n * This module lives at `src/registry.ts` in dev and `dist/registry.js` once\n * built; in both cases the vendored `skills/` directory sits one level up.\n */\nexport const skillsDir = resolve(moduleDir, \"..\", \"skills\");\n\n/** Absolute path to a vendored skill's source `SKILL.md`. */\nexport function skillSourcePath(name: string): string {\n return join(skillsDir, name, \"SKILL.md\");\n}\n\n/** Read one vendored `SKILL.md` and normalize it into a `Skill`. */\nexport function loadSkill(name: string): Skill {\n const raw = readFileSync(skillSourcePath(name), \"utf8\");\n const parsed = matter(raw);\n const frontmatter = parsed.data as Record<string, unknown>;\n return {\n name: typeof frontmatter.name === \"string\" ? frontmatter.name : name,\n description:\n typeof frontmatter.description === \"string\" ? frontmatter.description : \"\",\n frontmatter,\n body: parsed.content.replace(/^\\s+/, \"\"),\n };\n}\n\n/** Discover and load every vendored source skill. */\nexport function loadSkills(): Skill[] {\n return readdirSync(skillsDir)\n .filter((entry) => statSync(join(skillsDir, entry)).isDirectory())\n .map((dir) => loadSkill(dir))\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n","/**\n * Managed-marker helper, shared by the merge-style adapters (Codex, Gemini).\n *\n * Tool-owned content inside files a user may also edit (`AGENTS.md`,\n * `GEMINI.md`) is bounded by managed markers. Only the span between the\n * markers is ever rewritten on a re-run; everything outside is the user's and\n * is preserved verbatim.\n */\n\nexport const MARKER_START = \"<!-- le-restaurant:start -->\";\nexport const MARKER_END = \"<!-- le-restaurant:end -->\";\n\n/** Notice rendered as the first line inside every managed block. */\nexport const MANAGED_NOTICE =\n \"<!-- Managed by le-restaurant. Do not edit between these markers; re-run the installer to update. -->\";\n\n/** Wrap `inner` content in managed markers, returning a complete block. */\nexport function renderManagedBlock(inner: string): string {\n return `${MARKER_START}\\n${inner}\\n${MARKER_END}\\n`;\n}\n\n/** Does `content` already contain a managed block? */\nexport function hasManagedBlock(content: string): boolean {\n return content.includes(MARKER_START) && content.includes(MARKER_END);\n}\n\n/**\n * Merge a freshly rendered managed `block` into `existing` file content.\n *\n * If `existing` already contains a managed span, that span (markers included)\n * is replaced in place. Otherwise the block is appended, separated from any\n * prior content by a blank line. User content outside the markers is never\n * touched, so repeated merges are idempotent for a stable block.\n */\nexport function mergeManagedBlock(existing: string, block: string): string {\n const start = existing.indexOf(MARKER_START);\n const end = existing.indexOf(MARKER_END);\n if (start !== -1 && end !== -1 && end > start) {\n // Replace the managed span, including the end marker and its trailing\n // newline if present, so the rendered block (which ends in \"\\n\") slots in\n // without accumulating blank lines.\n let after = end + MARKER_END.length;\n if (existing[after] === \"\\n\") after += 1;\n return existing.slice(0, start) + block + existing.slice(after);\n }\n if (existing.length === 0) return block;\n const separator = existing.endsWith(\"\\n\") ? \"\\n\" : \"\\n\\n\";\n return existing + separator + block;\n}\n","import {\n MANAGED_NOTICE,\n renderManagedBlock,\n} from \"../markers.js\";\nimport type { FileOutput, InstallContext, Skill } from \"../types.js\";\nimport type { Adapter } from \"./types.js\";\n\n/**\n * Render one skill as a delimited `## Skill: <name>` section: heading, the\n * one-line description, then the skill body.\n */\nfunction renderSection(skill: Skill): string {\n return `## Skill: ${skill.name}\\n\\n${skill.description}\\n\\n${skill.body.trimEnd()}`;\n}\n\n/**\n * Codex — merge strategy.\n *\n * Codex reads a single monolithic `AGENTS.md` per directory with no named or\n * on-demand skills, so every selected skill is folded into one `AGENTS.md` as\n * a delimited `## Skill: <name>` section. The whole set lives inside managed\n * markers, so the writer's merge mode updates only that span on re-runs and\n * never disturbs surrounding user content. Triggering degrades to always-on\n * guidance (flagged to the user elsewhere).\n */\nexport const codexAdapter: Adapter = {\n id: \"codex\",\n label: \"Codex\",\n translate(skills: Skill[], _ctx: InstallContext): FileOutput[] {\n const inner = [MANAGED_NOTICE, ...skills.map(renderSection)].join(\"\\n\\n\");\n return [\n {\n path: \"AGENTS.md\",\n contents: renderManagedBlock(inner),\n mode: \"merge\",\n },\n ];\n },\n};\n","import { MANAGED_NOTICE, renderManagedBlock } from \"../markers.js\";\nimport type { FileOutput, InstallContext, Skill } from \"../types.js\";\nimport type { Adapter } from \"./types.js\";\n\n/** Notice rendered at the top of each generated `.gemini/skills/<name>.md`. */\nconst SKILL_FILE_NOTICE =\n \"<!-- Managed by le-restaurant; edit the source skill, not this file. -->\";\n\n/** Relative import path for a skill's modular file, as used in `GEMINI.md`. */\nfunction importPath(skill: Skill): string {\n return `./.gemini/skills/${skill.name}.md`;\n}\n\n/** Render one skill into its own modular `.gemini/skills/<name>.md` file. */\nfunction renderSkillFile(skill: Skill): string {\n return `${SKILL_FILE_NOTICE}\\n\\n${skill.description}\\n\\n${skill.body.trimEnd()}\\n`;\n}\n\n/**\n * Gemini — import strategy.\n *\n * Gemini concatenates `GEMINI.md` hierarchically and supports `@file.md`\n * imports, so each skill is written to its own modular\n * `.gemini/skills/<name>.md` and referenced by an `@./.gemini/skills/<name>.md`\n * import line. The import lines live inside managed markers in `GEMINI.md`, so\n * re-runs update only that span; the modular skill files are fully tool-owned\n * (overwrite). Skills are always-on — no on-demand triggering.\n */\nexport const geminiAdapter: Adapter = {\n id: \"gemini\",\n label: \"Gemini\",\n translate(skills: Skill[], _ctx: InstallContext): FileOutput[] {\n const skillFiles: FileOutput[] = skills.map((skill) => ({\n path: `.gemini/skills/${skill.name}.md`,\n contents: renderSkillFile(skill),\n mode: \"overwrite\",\n }));\n\n const imports = skills.map((skill) => `@${importPath(skill)}`).join(\"\\n\");\n const inner = `${MANAGED_NOTICE}\\n\\n${imports}`;\n const geminiMd: FileOutput = {\n path: \"GEMINI.md\",\n contents: renderManagedBlock(inner),\n mode: \"merge\",\n };\n\n return [...skillFiles, geminiMd];\n },\n};\n","import type { WriteResult } from \"./writer.js\";\n\n/** Everything the post-install summary needs to render. */\nexport interface SummaryInput {\n /** The agent the skills were installed for. */\n agentId: \"claude\" | \"codex\" | \"gemini\";\n /** Human-readable agent label (e.g. \"Claude Code\"). */\n agentLabel: string;\n /** What the writer did with each file. */\n results: WriteResult[];\n}\n\n/**\n * Per-agent \"how to use the skills\" guidance.\n *\n * Claude Code keeps native on-demand triggering, so its skills behave as\n * designed. Codex and Gemini have no skill system — the translation degrades to\n * always-on guidance, which we must state honestly (see Architecture: \"Accept\n * fidelity loss on Codex/Gemini rather than fake a skill system\").\n */\nfunction usageNotes(agentId: SummaryInput[\"agentId\"]): string[] {\n switch (agentId) {\n case \"claude\":\n return [\n \"Skills install to .claude/skills/<name>/SKILL.md.\",\n \"Claude Code triggers each skill on demand — it picks the right one\",\n \"from its description when a matching task comes up. Nothing else to do.\",\n ];\n case \"codex\":\n return [\n \"Skills are folded into AGENTS.md as delimited sections, inside\",\n \"le-restaurant managed markers (edit outside the markers freely).\",\n \"Caveat: Codex has no skill system, so this guidance is ALWAYS-ON —\",\n \"there is no on-demand triggering. Every section is in context all the\",\n \"time, unlike Claude Code's on-demand skills.\",\n ];\n case \"gemini\":\n return [\n \"Each skill is written to .gemini/skills/<name>.md and imported from\",\n \"GEMINI.md via @import lines inside le-restaurant managed markers.\",\n \"Caveat: Gemini has no skill system, so this guidance is ALWAYS-ON —\",\n \"there is no on-demand triggering. Every imported skill is in context\",\n \"all the time, unlike Claude Code's on-demand skills.\",\n ];\n }\n}\n\n/**\n * Render the post-install summary: the target agent, every file written (with\n * the action taken), and how to use the installed skills — including the\n * always-on caveat for Codex/Gemini.\n */\nexport function renderSummary(input: SummaryInput): string {\n const lines: string[] = [];\n lines.push(`Installed ${input.results.length} file(s) for ${input.agentLabel}:`);\n for (const r of input.results) {\n lines.push(` ${r.action.padEnd(11)} ${r.path}`);\n }\n lines.push(\"\");\n lines.push(\"How to use:\");\n for (const note of usageNotes(input.agentId)) {\n lines.push(` ${note}`);\n }\n return lines.join(\"\\n\");\n}\n","import {\n existsSync,\n mkdirSync,\n readFileSync,\n renameSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\";\nimport { randomBytes } from \"node:crypto\";\nimport { dirname, isAbsolute, resolve } from \"node:path\";\nimport { mergeManagedBlock } from \"./markers.js\";\nimport type { FileOutput, InstallContext } from \"./types.js\";\n\n/** What the writer did with a single output file. */\nexport type WriteAction = \"created\" | \"overwritten\" | \"merged\" | \"skipped\";\n\n/** A file the writer processed, for the post-install summary. */\nexport interface WriteResult {\n /** Path relative to the target dir (as the adapter emitted it). */\n path: string;\n /** The action the conflict policy resolved to. */\n action: WriteAction;\n}\n\n/**\n * Atomically write `contents` to `absolute`.\n *\n * The bytes are written to a sibling temp file first, then renamed over the\n * destination — `rename` is atomic on a single filesystem, so a reader never\n * sees a half-written file and a failure mid-write never clobbers the existing\n * target. On any error the temp file is removed and the error rethrown.\n */\nexport function atomicWriteFile(absolute: string, contents: string): void {\n mkdirSync(dirname(absolute), { recursive: true });\n const suffix = randomBytes(6).toString(\"hex\");\n const tmp = `${absolute}.${suffix}.tmp`;\n try {\n writeFileSync(tmp, contents);\n renameSync(tmp, absolute);\n } catch (err) {\n try {\n rmSync(tmp, { force: true });\n } catch {\n // best-effort cleanup; surface the original failure below\n }\n throw err;\n }\n}\n\n/**\n * Write a set of adapter outputs into the install target.\n *\n * Each `FileOutput.path` is resolved relative to `ctx.targetDir` and written\n * atomically. When a target file already exists, the `conflictPolicy` decides:\n * - `skip` — leave the existing file untouched;\n * - `overwrite` — replace it with the emitted contents;\n * - `merge` — for `mode: \"merge\"` outputs, fold the managed block into the\n * existing file (preserving user content outside the markers); for other\n * outputs, fall back to overwrite.\n *\n * A file that does not yet exist is always created regardless of policy.\n */\nexport function writeOutputs(\n outputs: FileOutput[],\n ctx: InstallContext,\n): WriteResult[] {\n const results: WriteResult[] = [];\n for (const output of outputs) {\n const absolute = isAbsolute(output.path)\n ? output.path\n : resolve(ctx.targetDir, output.path);\n\n if (!existsSync(absolute)) {\n atomicWriteFile(absolute, output.contents);\n results.push({ path: output.path, action: \"created\" });\n continue;\n }\n\n switch (ctx.conflictPolicy) {\n case \"skip\":\n results.push({ path: output.path, action: \"skipped\" });\n break;\n case \"merge\":\n if (output.mode === \"merge\") {\n const existing = readFileSync(absolute, \"utf8\");\n atomicWriteFile(absolute, mergeManagedBlock(existing, output.contents));\n results.push({ path: output.path, action: \"merged\" });\n } else {\n atomicWriteFile(absolute, output.contents);\n results.push({ path: output.path, action: \"overwritten\" });\n }\n break;\n default:\n atomicWriteFile(absolute, output.contents);\n results.push({ path: output.path, action: \"overwritten\" });\n break;\n }\n }\n return results;\n}\n","{\n \"name\": \"@long.dg/le-restaurant\",\n \"version\": \"0.1.1\",\n \"description\": \"Install the brigade of agent skills into your project, translated for your coding agent.\",\n \"type\": \"module\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"bin\": {\n \"le-restaurant\": \"dist/cli.js\"\n },\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"files\": [\n \"dist\",\n \"skills\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"typecheck\": \"tsc --noEmit\",\n \"check:sync\": \"vitest run test/check-skills-sync.test.ts\"\n },\n \"keywords\": [\n \"claude\",\n \"codex\",\n \"gemini\",\n \"skills\",\n \"cli\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/dglong/le-restaurant.git\"\n },\n \"homepage\": \"https://github.com/dglong/le-restaurant#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/dglong/le-restaurant/issues\"\n },\n \"author\": \"\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@clack/prompts\": \"^1.6.0\",\n \"commander\": \"^14.0.1\",\n \"gray-matter\": \"^4.0.3\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^24.10.1\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^3.2.4\"\n }\n}\n"],"mappings":"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","names":["readFileSync","readFileSync","readFileSync","dirname","resolve","dirname","resolve","readFileSync"]}
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
package/dist/wizard-4VNJ64P6.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/adapters/claude.ts","../src/registry.ts","../src/markers.ts","../src/adapters/codex.ts","../src/adapters/gemini.ts","../src/summary.ts","../src/writer.ts"],"sourcesContent":["import { Command, CommanderError } from \"commander\";\nimport { claudeAdapter } from \"./adapters/claude.js\";\nimport { codexAdapter } from \"./adapters/codex.js\";\nimport { geminiAdapter } from \"./adapters/gemini.js\";\nimport type { Adapter } from \"./adapters/types.js\";\nimport { loadSkills } from \"./registry.js\";\nimport { renderSummary } from \"./summary.js\";\nimport type { ConflictPolicy, InstallContext, Skill } from \"./types.js\";\nimport { writeOutputs, type WriteResult } from \"./writer.js\";\n\nconst VERSION = \"0.1.0\";\n\n/** The agents we can install for. */\nexport type AgentId = \"claude\" | \"codex\" | \"gemini\";\n\n/** Adapter registry, keyed by agent id. The single dispatch table. */\nconst ADAPTERS: Record<AgentId, Adapter> = {\n claude: claudeAdapter,\n codex: codexAdapter,\n gemini: geminiAdapter,\n};\n\n/** Valid agent ids, for validation + help text. */\nexport const AGENT_IDS = Object.keys(ADAPTERS) as AgentId[];\n\n/**\n * Map a chosen agent id to its adapter.\n *\n * Throws a clear error on an unknown id so both the CLI (non-zero exit) and\n * library callers fail loudly rather than silently installing the wrong thing.\n */\nexport function selectAdapter(agentId: string): Adapter {\n const adapter = ADAPTERS[agentId as AgentId];\n if (!adapter) {\n throw new Error(\n `Unknown agent \"${agentId}\". Choose one of: ${AGENT_IDS.join(\", \")}.`,\n );\n }\n return adapter;\n}\n\n/**\n * The conflict policy to use for an agent by default.\n *\n * Claude's passthrough files are fully tool-owned, so they overwrite. The\n * Codex/Gemini marker targets (`AGENTS.md`, `GEMINI.md`) merge so user content\n * outside the managed markers is preserved on re-runs.\n */\nexport function defaultConflictPolicy(agentId: string): ConflictPolicy {\n return agentId === \"claude\" ? \"overwrite\" : \"merge\";\n}\n\n/**\n * Resolve a `--skills` value into the concrete list of skills to install.\n *\n * Accepts the literal `all` (every available skill) or a comma-separated list\n * of skill names (order/whitespace tolerant). Throws clearly on an empty\n * selection or any unknown name.\n */\nexport function resolveSkillSelection(\n spec: string,\n available: Skill[],\n): Skill[] {\n const trimmed = (spec ?? \"\").trim();\n if (trimmed.toLowerCase() === \"all\") return available;\n\n const names = trimmed\n .split(\",\")\n .map((n) => n.trim())\n .filter((n) => n.length > 0);\n if (names.length === 0) {\n throw new Error(\n `No skills selected. Use --skills all or a comma list (e.g. ${available\n .map((s) => s.name)\n .slice(0, 2)\n .join(\",\")}).`,\n );\n }\n\n const byName = new Map(available.map((s) => [s.name, s]));\n const unknown = names.filter((n) => !byName.has(n));\n if (unknown.length > 0) {\n throw new Error(\n `Unknown skill(s): ${unknown.join(\", \")}. Available: ${available\n .map((s) => s.name)\n .join(\", \")}.`,\n );\n }\n return names.map((n) => byName.get(n)!);\n}\n\n/** A resolved, ready-to-run install request. */\nexport interface InstallRequest {\n agentId: AgentId;\n skills: Skill[];\n targetDir: string;\n conflictPolicy?: ConflictPolicy;\n}\n\n/**\n * Translate the selected skills with the chosen adapter and write them to the\n * target dir. The single install primitive shared by the flag and wizard paths.\n */\nexport function runInstall(req: InstallRequest): {\n adapter: Adapter;\n results: WriteResult[];\n} {\n const adapter = selectAdapter(req.agentId);\n const ctx: InstallContext = {\n targetDir: req.targetDir,\n selectedSkills: req.skills,\n conflictPolicy: req.conflictPolicy ?? defaultConflictPolicy(req.agentId),\n };\n const outputs = adapter.translate(req.skills, ctx);\n const results = writeOutputs(outputs, ctx);\n return { adapter, results };\n}\n\n/** Options collected from the non-interactive flags. */\ninterface InstallFlags {\n agent?: string;\n skills?: string;\n yes?: boolean;\n}\n\n/**\n * Resolve raw `--agent`/`--skills` flags into a validated install request.\n * Throws clearly (non-zero exit upstream) on any invalid value.\n */\nexport function resolveFlags(\n flags: InstallFlags,\n targetDir: string,\n available: Skill[],\n): InstallRequest {\n if (!flags.agent) {\n throw new Error(\"Missing --agent. Choose one of: \" + AGENT_IDS.join(\", \"));\n }\n selectAdapter(flags.agent); // validates the agent id\n const skills = resolveSkillSelection(flags.skills ?? \"all\", available);\n return { agentId: flags.agent as AgentId, skills, targetDir };\n}\n\n/** Run an install request and print its post-install summary. */\nfunction installAndReport(req: InstallRequest): void {\n const { adapter, results } = runInstall(req);\n console.log(\n renderSummary({\n agentId: adapter.id,\n agentLabel: adapter.label,\n results,\n }),\n );\n}\n\n/**\n * Build the commander program. Factored out so tests can introspect the\n * wired-up commands/options without spawning a process.\n */\nexport function buildProgram(): Command {\n const program = new Command();\n\n program\n .name(\"le-restaurant\")\n .description(\n \"Install the brigade of agent skills into your project, translated for your coding agent.\",\n )\n .version(VERSION);\n\n // Root command: non-interactive flags, or the wizard when no agent is given.\n program\n .argument(\"[targetDir]\", \"target project directory\", \".\")\n .option(\n \"--agent <agent>\",\n `target coding agent (${AGENT_IDS.join(\"|\")})`,\n )\n .option(\n \"--skills <skills>\",\n \"skills to install: 'all' or a comma-separated list\",\n )\n .option(\"--yes\", \"skip prompts; install with the given flags\", false)\n .action(async (targetDir: string, opts: InstallFlags) => {\n const available = loadSkills();\n\n // No agent flag → interactive wizard.\n if (!opts.agent) {\n const { runWizard } = await import(\"./wizard.js\");\n const choice = await runWizard(available);\n if (!choice) return; // cancelled\n installAndReport({\n agentId: choice.agentId,\n skills: choice.skills,\n targetDir,\n });\n return;\n }\n\n // Non-interactive: validate flags (throws → non-zero exit upstream).\n installAndReport(resolveFlags(opts, targetDir, available));\n });\n\n program\n .command(\"list\")\n .description(\"List the skills available to install.\")\n .action(() => {\n const skills = loadSkills();\n for (const skill of skills) {\n console.log(`- ${skill.name}: ${skill.description}`);\n }\n });\n\n return program;\n}\n\n/**\n * Parse argv, run the CLI, and resolve to the process exit code.\n *\n * commander is put in `exitOverride` mode so it throws instead of calling\n * `process.exit`, letting us (and tests) observe the exit code. Help/version\n * exit 0; parse/validation errors exit non-zero.\n */\nexport async function runCli(argv: string[] = process.argv): Promise<number> {\n const program = buildProgram();\n program.exitOverride();\n program.configureOutput({\n writeErr: (str) => process.stderr.write(str),\n });\n try {\n await program.parseAsync(argv);\n return Number(process.exitCode ?? 0);\n } catch (err) {\n if (err instanceof CommanderError) {\n // --help / --version resolve to exitCode 0; parse errors are non-zero.\n return err.exitCode;\n }\n console.error(err instanceof Error ? err.message : String(err));\n return 1;\n }\n}\n\n/** Convenience entry: run and let the process adopt the resolved exit code. */\nexport function run(argv: string[] = process.argv): Promise<number> {\n return runCli(argv).then((code) => {\n process.exitCode = code;\n return code;\n });\n}\n\n// Execute when invoked as the bin (not when imported by tests).\nconst invokedDirectly =\n typeof process !== \"undefined\" &&\n process.argv[1] !== undefined &&\n /cli\\.(js|ts)$/.test(process.argv[1]);\n\nif (invokedDirectly) {\n void run();\n}\n","import { readFileSync } from \"node:fs\";\nimport { skillSourcePath } from \"../registry.js\";\nimport type { FileOutput, InstallContext, Skill } from \"../types.js\";\nimport type { Adapter } from \"./types.js\";\n\n/**\n * Claude Code — passthrough strategy.\n *\n * Claude Code natively supports on-demand skills, so we copy each source\n * `SKILL.md` verbatim to `.claude/skills/<name>/SKILL.md`. To guarantee\n * byte-for-byte fidelity we read the original vendored file rather than\n * re-serialize the normalized `Skill` (which would lose exact formatting).\n */\nexport const claudeAdapter: Adapter = {\n id: \"claude\",\n label: \"Claude Code\",\n translate(skills: Skill[], _ctx: InstallContext): FileOutput[] {\n return skills.map((skill) => ({\n path: `.claude/skills/${skill.name}/SKILL.md`,\n contents: readFileSync(skillSourcePath(skill.name), \"utf8\"),\n mode: \"overwrite\",\n }));\n },\n};\n","import { readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport matter from \"gray-matter\";\nimport type { Skill } from \"./types.js\";\n\nconst moduleDir = dirname(fileURLToPath(import.meta.url));\n\n/**\n * Absolute path to the vendored source skills.\n *\n * This module lives at `src/registry.ts` in dev and `dist/registry.js` once\n * built; in both cases the vendored `skills/` directory sits one level up.\n */\nexport const skillsDir = resolve(moduleDir, \"..\", \"skills\");\n\n/** Absolute path to a vendored skill's source `SKILL.md`. */\nexport function skillSourcePath(name: string): string {\n return join(skillsDir, name, \"SKILL.md\");\n}\n\n/** Read one vendored `SKILL.md` and normalize it into a `Skill`. */\nexport function loadSkill(name: string): Skill {\n const raw = readFileSync(skillSourcePath(name), \"utf8\");\n const parsed = matter(raw);\n const frontmatter = parsed.data as Record<string, unknown>;\n return {\n name: typeof frontmatter.name === \"string\" ? frontmatter.name : name,\n description:\n typeof frontmatter.description === \"string\" ? frontmatter.description : \"\",\n frontmatter,\n body: parsed.content.replace(/^\\s+/, \"\"),\n };\n}\n\n/** Discover and load every vendored source skill. */\nexport function loadSkills(): Skill[] {\n return readdirSync(skillsDir)\n .filter((entry) => statSync(join(skillsDir, entry)).isDirectory())\n .map((dir) => loadSkill(dir))\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n","/**\n * Managed-marker helper, shared by the merge-style adapters (Codex, Gemini).\n *\n * Tool-owned content inside files a user may also edit (`AGENTS.md`,\n * `GEMINI.md`) is bounded by managed markers. Only the span between the\n * markers is ever rewritten on a re-run; everything outside is the user's and\n * is preserved verbatim.\n */\n\nexport const MARKER_START = \"<!-- le-restaurant:start -->\";\nexport const MARKER_END = \"<!-- le-restaurant:end -->\";\n\n/** Notice rendered as the first line inside every managed block. */\nexport const MANAGED_NOTICE =\n \"<!-- Managed by le-restaurant. Do not edit between these markers; re-run the installer to update. -->\";\n\n/** Wrap `inner` content in managed markers, returning a complete block. */\nexport function renderManagedBlock(inner: string): string {\n return `${MARKER_START}\\n${inner}\\n${MARKER_END}\\n`;\n}\n\n/** Does `content` already contain a managed block? */\nexport function hasManagedBlock(content: string): boolean {\n return content.includes(MARKER_START) && content.includes(MARKER_END);\n}\n\n/**\n * Merge a freshly rendered managed `block` into `existing` file content.\n *\n * If `existing` already contains a managed span, that span (markers included)\n * is replaced in place. Otherwise the block is appended, separated from any\n * prior content by a blank line. User content outside the markers is never\n * touched, so repeated merges are idempotent for a stable block.\n */\nexport function mergeManagedBlock(existing: string, block: string): string {\n const start = existing.indexOf(MARKER_START);\n const end = existing.indexOf(MARKER_END);\n if (start !== -1 && end !== -1 && end > start) {\n // Replace the managed span, including the end marker and its trailing\n // newline if present, so the rendered block (which ends in \"\\n\") slots in\n // without accumulating blank lines.\n let after = end + MARKER_END.length;\n if (existing[after] === \"\\n\") after += 1;\n return existing.slice(0, start) + block + existing.slice(after);\n }\n if (existing.length === 0) return block;\n const separator = existing.endsWith(\"\\n\") ? \"\\n\" : \"\\n\\n\";\n return existing + separator + block;\n}\n","import {\n MANAGED_NOTICE,\n renderManagedBlock,\n} from \"../markers.js\";\nimport type { FileOutput, InstallContext, Skill } from \"../types.js\";\nimport type { Adapter } from \"./types.js\";\n\n/**\n * Render one skill as a delimited `## Skill: <name>` section: heading, the\n * one-line description, then the skill body.\n */\nfunction renderSection(skill: Skill): string {\n return `## Skill: ${skill.name}\\n\\n${skill.description}\\n\\n${skill.body.trimEnd()}`;\n}\n\n/**\n * Codex — merge strategy.\n *\n * Codex reads a single monolithic `AGENTS.md` per directory with no named or\n * on-demand skills, so every selected skill is folded into one `AGENTS.md` as\n * a delimited `## Skill: <name>` section. The whole set lives inside managed\n * markers, so the writer's merge mode updates only that span on re-runs and\n * never disturbs surrounding user content. Triggering degrades to always-on\n * guidance (flagged to the user elsewhere).\n */\nexport const codexAdapter: Adapter = {\n id: \"codex\",\n label: \"Codex\",\n translate(skills: Skill[], _ctx: InstallContext): FileOutput[] {\n const inner = [MANAGED_NOTICE, ...skills.map(renderSection)].join(\"\\n\\n\");\n return [\n {\n path: \"AGENTS.md\",\n contents: renderManagedBlock(inner),\n mode: \"merge\",\n },\n ];\n },\n};\n","import { MANAGED_NOTICE, renderManagedBlock } from \"../markers.js\";\nimport type { FileOutput, InstallContext, Skill } from \"../types.js\";\nimport type { Adapter } from \"./types.js\";\n\n/** Notice rendered at the top of each generated `.gemini/skills/<name>.md`. */\nconst SKILL_FILE_NOTICE =\n \"<!-- Managed by le-restaurant; edit the source skill, not this file. -->\";\n\n/** Relative import path for a skill's modular file, as used in `GEMINI.md`. */\nfunction importPath(skill: Skill): string {\n return `./.gemini/skills/${skill.name}.md`;\n}\n\n/** Render one skill into its own modular `.gemini/skills/<name>.md` file. */\nfunction renderSkillFile(skill: Skill): string {\n return `${SKILL_FILE_NOTICE}\\n\\n${skill.description}\\n\\n${skill.body.trimEnd()}\\n`;\n}\n\n/**\n * Gemini — import strategy.\n *\n * Gemini concatenates `GEMINI.md` hierarchically and supports `@file.md`\n * imports, so each skill is written to its own modular\n * `.gemini/skills/<name>.md` and referenced by an `@./.gemini/skills/<name>.md`\n * import line. The import lines live inside managed markers in `GEMINI.md`, so\n * re-runs update only that span; the modular skill files are fully tool-owned\n * (overwrite). Skills are always-on — no on-demand triggering.\n */\nexport const geminiAdapter: Adapter = {\n id: \"gemini\",\n label: \"Gemini\",\n translate(skills: Skill[], _ctx: InstallContext): FileOutput[] {\n const skillFiles: FileOutput[] = skills.map((skill) => ({\n path: `.gemini/skills/${skill.name}.md`,\n contents: renderSkillFile(skill),\n mode: \"overwrite\",\n }));\n\n const imports = skills.map((skill) => `@${importPath(skill)}`).join(\"\\n\");\n const inner = `${MANAGED_NOTICE}\\n\\n${imports}`;\n const geminiMd: FileOutput = {\n path: \"GEMINI.md\",\n contents: renderManagedBlock(inner),\n mode: \"merge\",\n };\n\n return [...skillFiles, geminiMd];\n },\n};\n","import type { WriteResult } from \"./writer.js\";\n\n/** Everything the post-install summary needs to render. */\nexport interface SummaryInput {\n /** The agent the skills were installed for. */\n agentId: \"claude\" | \"codex\" | \"gemini\";\n /** Human-readable agent label (e.g. \"Claude Code\"). */\n agentLabel: string;\n /** What the writer did with each file. */\n results: WriteResult[];\n}\n\n/**\n * Per-agent \"how to use the skills\" guidance.\n *\n * Claude Code keeps native on-demand triggering, so its skills behave as\n * designed. Codex and Gemini have no skill system — the translation degrades to\n * always-on guidance, which we must state honestly (see Architecture: \"Accept\n * fidelity loss on Codex/Gemini rather than fake a skill system\").\n */\nfunction usageNotes(agentId: SummaryInput[\"agentId\"]): string[] {\n switch (agentId) {\n case \"claude\":\n return [\n \"Skills install to .claude/skills/<name>/SKILL.md.\",\n \"Claude Code triggers each skill on demand — it picks the right one\",\n \"from its description when a matching task comes up. Nothing else to do.\",\n ];\n case \"codex\":\n return [\n \"Skills are folded into AGENTS.md as delimited sections, inside\",\n \"le-restaurant managed markers (edit outside the markers freely).\",\n \"Caveat: Codex has no skill system, so this guidance is ALWAYS-ON —\",\n \"there is no on-demand triggering. Every section is in context all the\",\n \"time, unlike Claude Code's on-demand skills.\",\n ];\n case \"gemini\":\n return [\n \"Each skill is written to .gemini/skills/<name>.md and imported from\",\n \"GEMINI.md via @import lines inside le-restaurant managed markers.\",\n \"Caveat: Gemini has no skill system, so this guidance is ALWAYS-ON —\",\n \"there is no on-demand triggering. Every imported skill is in context\",\n \"all the time, unlike Claude Code's on-demand skills.\",\n ];\n }\n}\n\n/**\n * Render the post-install summary: the target agent, every file written (with\n * the action taken), and how to use the installed skills — including the\n * always-on caveat for Codex/Gemini.\n */\nexport function renderSummary(input: SummaryInput): string {\n const lines: string[] = [];\n lines.push(`Installed ${input.results.length} file(s) for ${input.agentLabel}:`);\n for (const r of input.results) {\n lines.push(` ${r.action.padEnd(11)} ${r.path}`);\n }\n lines.push(\"\");\n lines.push(\"How to use:\");\n for (const note of usageNotes(input.agentId)) {\n lines.push(` ${note}`);\n }\n return lines.join(\"\\n\");\n}\n","import {\n existsSync,\n mkdirSync,\n readFileSync,\n renameSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\";\nimport { randomBytes } from \"node:crypto\";\nimport { dirname, isAbsolute, resolve } from \"node:path\";\nimport { mergeManagedBlock } from \"./markers.js\";\nimport type { FileOutput, InstallContext } from \"./types.js\";\n\n/** What the writer did with a single output file. */\nexport type WriteAction = \"created\" | \"overwritten\" | \"merged\" | \"skipped\";\n\n/** A file the writer processed, for the post-install summary. */\nexport interface WriteResult {\n /** Path relative to the target dir (as the adapter emitted it). */\n path: string;\n /** The action the conflict policy resolved to. */\n action: WriteAction;\n}\n\n/**\n * Atomically write `contents` to `absolute`.\n *\n * The bytes are written to a sibling temp file first, then renamed over the\n * destination — `rename` is atomic on a single filesystem, so a reader never\n * sees a half-written file and a failure mid-write never clobbers the existing\n * target. On any error the temp file is removed and the error rethrown.\n */\nexport function atomicWriteFile(absolute: string, contents: string): void {\n mkdirSync(dirname(absolute), { recursive: true });\n const suffix = randomBytes(6).toString(\"hex\");\n const tmp = `${absolute}.${suffix}.tmp`;\n try {\n writeFileSync(tmp, contents);\n renameSync(tmp, absolute);\n } catch (err) {\n try {\n rmSync(tmp, { force: true });\n } catch {\n // best-effort cleanup; surface the original failure below\n }\n throw err;\n }\n}\n\n/**\n * Write a set of adapter outputs into the install target.\n *\n * Each `FileOutput.path` is resolved relative to `ctx.targetDir` and written\n * atomically. When a target file already exists, the `conflictPolicy` decides:\n * - `skip` — leave the existing file untouched;\n * - `overwrite` — replace it with the emitted contents;\n * - `merge` — for `mode: \"merge\"` outputs, fold the managed block into the\n * existing file (preserving user content outside the markers); for other\n * outputs, fall back to overwrite.\n *\n * A file that does not yet exist is always created regardless of policy.\n */\nexport function writeOutputs(\n outputs: FileOutput[],\n ctx: InstallContext,\n): WriteResult[] {\n const results: WriteResult[] = [];\n for (const output of outputs) {\n const absolute = isAbsolute(output.path)\n ? output.path\n : resolve(ctx.targetDir, output.path);\n\n if (!existsSync(absolute)) {\n atomicWriteFile(absolute, output.contents);\n results.push({ path: output.path, action: \"created\" });\n continue;\n }\n\n switch (ctx.conflictPolicy) {\n case \"skip\":\n results.push({ path: output.path, action: \"skipped\" });\n break;\n case \"merge\":\n if (output.mode === \"merge\") {\n const existing = readFileSync(absolute, \"utf8\");\n atomicWriteFile(absolute, mergeManagedBlock(existing, output.contents));\n results.push({ path: output.path, action: \"merged\" });\n } else {\n atomicWriteFile(absolute, output.contents);\n results.push({ path: output.path, action: \"overwritten\" });\n }\n break;\n default:\n atomicWriteFile(absolute, output.contents);\n results.push({ path: output.path, action: \"overwritten\" });\n break;\n }\n }\n return results;\n}\n"],"mappings":"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","names":["readFileSync","readFileSync","readFileSync","dirname","resolve","dirname","resolve","readFileSync"]}
|