@dovocode/workstation 0.1.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/api/jsonc.ts","../src/api/tasks.ts","../src/config/tasks.ts","../src/resources/tasks.ts","../src/api/config.ts","../src/api/shell.ts","../src/config/load.ts","../src/config/identity.ts","../src/config/source-hash.ts","../src/config/validation.ts","../src/persistence/manifest.ts","../src/persistence/lock.ts","../src/resources/shared.ts","../src/resources/brew-info.ts","../src/resources/package-version.ts","../src/resources/runner.ts"],"sourcesContent":["import type { ConfigValue } from \"./types.js\";\n\n/** A JSONC value with comments, ready to pass to files.jsonc. */\nexport class JsoncDocument {\n /** Store the rendered document text; callers construct documents through the builder commands. */\n private constructor(readonly content: string) {}\n\n /** @internal Build from typed commands; arbitrary unvalidated JSONC is not accepted. */\n static from(lines: readonly JsoncLine[]): JsoncDocument {\n const flattened = flatten(lines);\n if (flattened.filter((line) => line.kind === \"value\").length !== 1 ||\n flattened.some((line) => line.kind === \"property\")) {\n throw new Error(\"A JSONC document must contain exactly one value and no top-level properties\");\n }\n return new JsoncDocument(renderLines(flattened, 0, false).join(\"\\n\") + \"\\n\");\n }\n}\n\n/** One JSONC builder instruction. Prefer the jsonc helpers to constructing instructions manually. */\nexport type JsoncCommand =\n | { readonly kind: \"comment\"; readonly text: string }\n | { readonly kind: \"blank\" }\n | { readonly kind: \"value\"; readonly content: string }\n | { readonly kind: \"property\"; readonly name: string; readonly content: string };\n\n/** A builder command or nested group. Absent/disabled groups are ignored. */\nexport type JsoncLine = JsoncCommand | JsoncDocument | readonly JsoncLine[] | false | null | undefined;\n\n/** Compose JSONC line by line with comments; punctuation and escaping are generated. */\nexport const jsonc = {\n /** Join a document's comments and single root value, separating commands by newlines.\n * @example jsonc.concat(jsonc.comment(\"Editor settings\"), jsonc.object([jsonc.property(\"theme\", \"dark\")]))\n */\n concat(...lines: readonly JsoncLine[]): JsoncDocument {\n return JsoncDocument.from(lines);\n },\n /** Add a // comment. Each line of multiline text receives its own comment prefix. */\n comment(text: string): JsoncCommand {\n return { kind: \"comment\", text };\n },\n /** Insert an intentional empty line. */\n blank(): JsoncCommand {\n return { kind: \"blank\" };\n },\n /** Add an object property. Values may be ordinary JSON data or a nested JSONC document. */\n property(name: string, value: ConfigValue | JsoncDocument): JsoncCommand {\n return { kind: \"property\", name, content: renderValue(value) };\n },\n /** Add a JSON value, for example an array element or a primitive document root. */\n value(value: ConfigValue | JsoncDocument): JsoncCommand {\n return { kind: \"value\", content: renderValue(value) };\n },\n /** Build an object from properties, comments, blank lines, and optional groups. */\n object(lines: readonly JsoncLine[]): JsoncDocument {\n return container(lines, \"property\", \"{\", \"}\");\n },\n /** Build an array from values, comments, blank lines, and optional groups. */\n array(lines: readonly JsoncLine[]): JsoncDocument {\n return container(lines, \"value\", \"[\", \"]\");\n },\n};\n\n/** Validate object or array commands and render their punctuation and indentation. */\nfunction container(lines: readonly JsoncLine[], kind: \"property\" | \"value\", open: string, close: string): JsoncDocument {\n const commands = flatten(lines);\n if (commands.some((line) => line.kind !== kind && line.kind !== \"comment\" && line.kind !== \"blank\")) {\n throw new Error(`JSONC ${open === \"{\" ? \"objects require properties\" : \"arrays require values\"}`);\n }\n const body = renderLines(commands, 1, true);\n const content = body.length ? [open, ...body, close].join(\"\\n\") : open + close;\n return JsoncDocument.from([{ kind: \"value\", content }]);\n}\n\n/** Flatten nested declarations while omitting disabled or absent entries. */\nfunction flatten(lines: readonly JsoncLine[]): JsoncCommand[] {\n return lines.flatMap((line): JsoncCommand[] => {\n if (!line) return [];\n if (line instanceof JsoncDocument) return [{ kind: \"value\", content: line.content.trimEnd() }];\n if (isGroup(line)) return flatten(line);\n return [line];\n });\n}\n\n/** Narrow a JSONC declaration to a nested command array. */\nfunction isGroup(line: JsoncLine): line is readonly JsoncLine[] {\n return Array.isArray(line);\n}\n\n/** Render comment and value lines, placing commas where comments cannot consume them. */\nfunction renderLines(lines: readonly JsoncCommand[], depth: number, commas: boolean): string[] {\n const indent = \" \".repeat(depth);\n const lastValue = lines.findLastIndex((line) => line.kind === \"value\" || line.kind === \"property\");\n return lines.flatMap((line, index) => {\n if (line.kind === \"blank\") return [\"\"];\n if (line.kind === \"comment\") return line.text.split(/\\r\\n|\\r|\\n/).map((text) => `${indent}// ${text}`);\n const content = line.kind === \"property\" ? `${JSON.stringify(line.name)}: ${line.content}` : line.content;\n const rendered = content.split(\"\\n\").map((text) => indent + text);\n if (commas && index !== lastValue) {\n if (/^\\s*\\/\\//.test(rendered.at(-1) ?? \"\")) rendered.push(indent + \",\");\n else rendered[rendered.length - 1] += \",\";\n }\n return rendered;\n });\n}\n\n/** Render a value using the target format's literal and expression rules. */\nfunction renderValue(value: ConfigValue | JsoncDocument): string {\n if (value instanceof JsoncDocument) return value.content.trimEnd();\n const content = JSON.stringify(value, (_key, item: unknown) => {\n if (typeof item === \"number\" && !Number.isFinite(item)) throw new Error(\"JSONC numbers must be finite\");\n if (item === undefined || typeof item === \"function\" || typeof item === \"symbol\") throw new Error(\"Invalid JSONC value\");\n return item;\n }, 2);\n if (content === undefined) throw new Error(\"Invalid JSONC value\");\n return content;\n}\n","import type { TaskDefinition } from \"./types.js\";\n\n/** Declare a task command; arguments are passed directly without a shell.\n * @example tasks: { test: task(\"pnpm\", [\"test\"], { description: \"Run tests\" }) }\n */\nexport function task(command: string, args: readonly string[] = [], options: Omit<TaskDefinition, \"command\" | \"args\"> = {}): TaskDefinition {\n return { command, args, ...options };\n}\n","import { isAbsolute, resolve } from \"node:path\";\nimport type { ConfigDefinition, Context, TaskDefinition } from \"../api/types.js\";\n\n/** Validate tasks and aliases, resolving relative working directories against the entry point. */\nexport function resolveTasks(definition: ConfigDefinition, context: Context): {\n tasks: Record<string, TaskDefinition>; aliases: Record<string, string>;\n} {\n const tasks: Record<string, TaskDefinition> = Object.create(null);\n const aliases: Record<string, string> = Object.create(null);\n for (const [name, value] of Object.entries(definition.tasks ?? {})) {\n validateName(name);\n if (!value || typeof value !== \"object\" || typeof value.command !== \"string\" || !value.command.trim() ||\n (value.args !== undefined && (!Array.isArray(value.args) || !value.args.every((arg) => typeof arg === \"string\"))) ||\n (value.cwd !== undefined && typeof value.cwd !== \"string\") ||\n (value.description !== undefined && typeof value.description !== \"string\") ||\n (value.environment !== undefined && (typeof value.environment !== \"object\" || value.environment === null ||\n Array.isArray(value.environment) || !Object.values(value.environment).every((item) => typeof item === \"string\")))) {\n throw new Error(`Invalid task: ${name}`);\n }\n const cwd = value.cwd?.replace(/^~(?=\\/|$)/, context.home) ?? context.configDir;\n tasks[name] = { ...value, cwd: isAbsolute(cwd) ? cwd : resolve(context.configDir, cwd) };\n }\n for (const [name, target] of Object.entries(definition.aliases ?? {})) {\n validateName(name);\n if (Object.hasOwn(tasks, name)) throw new Error(`Task and alias share a name: ${name}`);\n if (typeof target !== \"string\") throw new Error(`Invalid alias target: ${name}`);\n aliases[name] = target;\n }\n for (const name of Object.keys(aliases)) resolveTaskName(name, tasks, aliases);\n return { tasks, aliases };\n}\n\n/** Follow task aliases, rejecting cycles and unknown targets. */\nexport function resolveTaskName(name: string, tasks: Readonly<Record<string, TaskDefinition>>, aliases: Readonly<Record<string, string>>): string {\n const visited = new Set<string>();\n let current = name;\n while (Object.hasOwn(aliases, current)) {\n if (visited.has(current)) throw new Error(`Task alias cycle: ${[...visited, current].join(\" -> \")}`);\n visited.add(current);\n const target = aliases[current];\n if (target === undefined) throw new Error(`Invalid alias: ${current}`);\n current = target;\n }\n if (!Object.hasOwn(tasks, current)) throw new Error(`Unknown task: ${current}`);\n return current;\n}\n\n/** Keep task names distinct from flags and reserved CLI commands. */\nfunction validateName(name: string): void {\n if (!/^[a-zA-Z0-9][a-zA-Z0-9:_-]*$/.test(name) || name === \"help\" || name === \"init\") throw new Error(`Invalid or reserved task name: ${name}`);\n}\n","import { resolveTaskName } from \"../config/tasks.js\";\nimport type { ResolvedConfig, Runner, CommandResult } from \"../api/types.js\";\n\n/** Run one explicit task or alias, appending CLI arguments without shell interpolation. */\nexport async function runTask(config: ResolvedConfig, name: string, args: readonly string[], runner: Runner): Promise<CommandResult> {\n const tasks = config.tasks ?? {};\n const resolved = resolveTaskName(name, tasks, config.aliases ?? {});\n const task = tasks[resolved];\n if (!task) throw new Error(`Unknown task: ${resolved}`);\n return await runner.run(task.command, [...(task.args ?? []), ...args], {\n ...(task.cwd ? { cwd: task.cwd } : {}),\n ...(task.environment ? { environment: task.environment } : {}),\n });\n}\n","import { JsoncDocument } from \"./jsonc.js\";\nimport type {\n BrewCaskUpgradeOptions,\n ConfigDefinition,\n ConfigFactory,\n ConfigInput,\n Context,\n ConfigValue,\n CustomToolResource,\n GeneratedFileResource,\n IfExistsPolicy,\n LaunchAgentResource,\n PackageManager,\n PackageResource,\n ResourceInput,\n SymlinkResource,\n StructuredFormat,\n SystemdServiceResource,\n WorkstationConfig,\n} from \"./types.js\";\n\n/** Normalize package names or version selectors into resource declarations. */\nfunction packageList(\n manager: PackageManager,\n packages: readonly string[] | Readonly<Record<string, string>>,\n upgrade?: BrewCaskUpgradeOptions,\n): PackageResource[] {\n if (Array.isArray(packages)) {\n return packages.map((name) => ({\n kind: \"package\",\n manager,\n name,\n ...(upgrade ? { upgrade } : {}),\n }));\n }\n\n return Object.entries(packages).map(([name, version]) => ({\n kind: \"package\",\n manager,\n name,\n version,\n }));\n}\n\n/** Declare packages; installation happens when the Workstation CLI runs. */\nexport const tools = {\n /**\n * Install mise tools. A list requests `latest`; a map accepts version selectors.\n * @example tools.mise({ node: \"lts\", go: \"1.27\" })\n */\n mise: (packages: readonly string[] | Readonly<Record<string, string>>): PackageResource[] =>\n packageList(\"mise\", packages),\n /** Install Homebrew formulae (command-line packages). */\n brew: (packages: readonly string[]): PackageResource[] => packageList(\"brew\", packages),\n /**\n * Install macOS applications. Greedy casks refresh their lock pin each run.\n * @example tools.brewCask([\"ghostty\"], { greedy: true, force: true })\n */\n brewCask: (\n packages: readonly string[],\n upgrade?: BrewCaskUpgradeOptions,\n ): PackageResource[] => packageList(\"brew-cask\", packages, upgrade),\n /** Install Debian/Ubuntu packages through APT. Mutations request sudo. */\n apt: (packages: readonly string[]): PackageResource[] => packageList(\"apt\", packages),\n /** Use the configured platform manager; defaults to Homebrew on macOS and APT on Linux. */\n system: (packages: readonly string[]): PackageResource[] => packageList(\"system\", packages),\n};\n\n/**\n * Link a config-relative source to a home-relative target. Absolute paths are supported.\n * @example symlink(\"dotfiles/gitconfig\", \"~/.gitconfig\")\n */\nexport function symlink(source: string, target: string): SymlinkResource {\n return { kind: \"symlink\", source, target };\n}\n\n/**\n * Declare a macOS user LaunchAgent. Use inside `darwin(...)`.\n * @param label Unique launchd label, for example `dev.example.worker`.\n */\nexport function launchAgent(\n label: string,\n options: Omit<LaunchAgentResource, \"kind\" | \"label\">,\n): LaunchAgentResource {\n return { kind: \"launch-agent\", label, ...options };\n}\n\n/** Control how a generated file replaces existing content and its Unix permissions. */\nexport interface GeneratedFileOptions {\n /** Existing-file policy. Defaults to `overwrite`, with the original saved for restoration. */\n readonly ifExists?: IfExistsPolicy;\n /** Unix permissions as an octal number. Defaults to `0o644`; use `0o600` for private files. */\n readonly mode?: number;\n}\n\n/** Create a generated-file declaration with the default overwrite policy. */\nfunction generatedFile(\n format: StructuredFormat,\n target: string,\n value: ConfigValue,\n options: GeneratedFileOptions = {},\n): GeneratedFileResource {\n return {\n kind: \"generated-file\",\n format,\n target,\n value,\n ifExists: options.ifExists ?? \"overwrite\",\n ...(options.mode !== undefined ? { mode: options.mode } : {}),\n };\n}\n\n/** Generate structured files from ordinary TypeScript values. Targets resolve relative to home. */\nexport const files = {\n /**\n * Generate TOML. Values must be representable in TOML (for example, no null).\n * @example files.toml(\"~/.config/app/config.toml\", { server: { port: 3000 } })\n */\n toml: (target: string, value: ConfigValue, options?: GeneratedFileOptions) =>\n generatedFile(\"toml\", target, value, options),\n /** Generate YAML with the standard overwrite/restore policy. */\n yaml: (target: string, value: ConfigValue, options?: GeneratedFileOptions) =>\n generatedFile(\"yaml\", target, value, options),\n /**\n * Generate formatted JSON.\n * @example files.json(\"~/.config/app/config.json\", { enabled: true })\n */\n json: (target: string, value: ConfigValue, options?: GeneratedFileOptions) =>\n generatedFile(\"json\", target, value, options),\n /** Generate JSONC from plain data or jsonc.concat/object commands with comments. */\n jsonc: (target: string, value: ConfigValue | JsoncDocument, options?: GeneratedFileOptions): GeneratedFileResource =>\n value instanceof JsoncDocument\n ? { ...generatedFile(\"jsonc\", target, null, options), renderedContent: value.content }\n : generatedFile(\"jsonc\", target, value, options),\n};\n\n/**\n * Declare a Linux systemd service. Defaults to user scope; system scope uses sudo.\n * Use inside `linux(...)`. The `.service` suffix is added when omitted.\n */\nexport function systemdService(\n name: string,\n options: Omit<SystemdServiceResource, \"kind\" | \"name\" | \"scope\"> & {\n readonly scope?: SystemdServiceResource[\"scope\"];\n },\n): SystemdServiceResource {\n return { kind: \"systemd-service\", name, scope: options.scope ?? \"user\", ...options };\n}\n\n/**\n * Build a local source tree into an executable. Source changes trigger a rebuild.\n * The build must write `{output}`; `{source}` and `{target}` are also available in arguments.\n * @example customTool(\"hello\", { source: \"tools/hello\", target: \"~/.local/bin/hello\", build: { command: \"go\", args: [\"build\", \"-o\", \"{output}\", \"{source}\"] } })\n */\nexport function customTool(\n name: string,\n options: Omit<CustomToolResource, \"kind\" | \"name\" | \"sourceHash\">,\n): CustomToolResource {\n return { kind: \"custom-tool\", name, ...options };\n}\n\n/** Include resources when a TypeScript condition is true. For config fragments, use platform/machine helpers. */\nexport function when(condition: boolean, resources: ResourceInput): ResourceInput {\n return condition ? resources : [];\n}\n\n/**\n * Define an entry point or imported fragment. Arrays and factories compose; false, null and undefined are ignored.\n * Later declarations with the same resource ID win.\n * @example export default defineConfig({ resources: [tools.mise({ node: \"lts\" })] })\n */\nexport function defineConfig(config: WorkstationConfig): WorkstationConfig {\n return config;\n}\n\n/** Define a configuration factory with typed access to machine, platform, home, and configDir. */\nexport function configure(factory: ConfigFactory): ConfigFactory {\n return factory;\n}\n\n/**\n * Include a configuration fragment only on macOS.\n * @example defineConfig([common, darwin(macos)])\n */\nexport function darwin(config: ConfigInput): ConfigFactory {\n return conditional((context) => context.platform === \"darwin\", config);\n}\n\n/** Include a configuration fragment only on Linux. */\nexport function linux(config: ConfigInput): ConfigFactory {\n return conditional((context) => context.platform === \"linux\", config);\n}\n\n/**\n * Include a fragment for one or more exact machine names. Defaults to the short hostname; `--machine` overrides it.\n * @example machine([\"studio\", \"macbook\"], sharedMacConfig)\n */\nexport function machine(names: string | readonly string[], config: ConfigInput): ConfigFactory {\n const accepted = typeof names === \"string\" ? [names] : names;\n return conditional((context) => accepted.includes(context.machine), config);\n}\n\n/** Wrap a config fragment in a context predicate without evaluating excluded fragments. */\nfunction conditional(predicate: (context: Context) => boolean, config: ConfigInput): ConfigFactory {\n return (context) => (predicate(context) ? resolveInput(config, context) : undefined);\n}\n\n/** Evaluate a configuration factory or return a static fragment unchanged. */\nfunction resolveInput(config: ConfigInput, context: Context): ConfigInput {\n return typeof config === \"function\" ? config(context) : config;\n}\n\nexport type { ConfigDefinition };\n","import type { GeneratedFileResource, IfExistsPolicy } from \"./types.js\";\n\n/** Supported shell rendering targets. */\nexport type Shell = \"zsh\" | \"bash\";\n\n/** A value expanded when the generated shell file runs, rather than during configuration loading. */\nexport type ShellExpression =\n | { readonly kind: \"variable\"; readonly name: string }\n | { readonly kind: \"home\"; readonly path: string }\n | { readonly kind: \"concat\"; readonly values: readonly ShellValue[] }\n | { readonly kind: \"capture\"; readonly command: ShellCommand };\n\n/** Plain strings are quoted literals. Use `shell.variable`, `shell.home`, or `shell.capture` for expansion. */\nexport type ShellValue = string | ShellExpression;\n\n/** A command plus individually quoted arguments; it is not executed while declaring configuration. */\nexport interface ShellCommand {\n readonly command: string;\n readonly args?: readonly ShellValue[];\n readonly stderr?: \"inherit\" | \"ignore\";\n}\n\n/** A condition evaluated by the generated shell script. */\nexport type ShellCondition =\n | { readonly kind: \"command-exists\"; readonly command: string }\n | { readonly kind: \"executable\" | \"file\" | \"directory\"; readonly path: ShellValue }\n | { readonly kind: \"empty\" | \"non-empty\"; readonly value: ShellValue }\n | { readonly kind: \"and\"; readonly conditions: readonly ShellCondition[] }\n | { readonly kind: \"or\"; readonly conditions: readonly ShellCondition[] }\n | { readonly kind: \"not\"; readonly condition: ShellCondition };\n\n/** A statement in the portable Zsh/Bash declaration language. */\nexport type ShellStatement =\n | { readonly kind: \"export\"; readonly name: string; readonly value: ShellValue }\n | { readonly kind: \"assign\"; readonly name: string; readonly value: ShellValue }\n | { readonly kind: \"unset\"; readonly names: readonly string[] }\n | { readonly kind: \"prepend-path\"; readonly values: readonly ShellValue[] }\n | { readonly kind: \"alias\"; readonly name: string; readonly command: string }\n | { readonly kind: \"eval\"; readonly command: ShellCommand }\n | { readonly kind: \"source\"; readonly path: ShellValue; readonly ifExists: boolean }\n | { readonly kind: \"if\"; readonly condition: ShellCondition; readonly statements: readonly ShellStatement[] }\n | { readonly kind: \"zsh-setopt\"; readonly options: readonly string[] }\n | { readonly kind: \"raw\"; readonly code: string };\n\n/** Generated startup-file options. Defaults to overwrite and mode `0o644`. */\nexport interface ShellFileOptions {\n /** Defaults to overwrite; replaced originals are saved in local state for restoration. */\n readonly ifExists?: IfExistsPolicy;\n /** Unix permissions, for example `0o600`. */\n readonly mode?: number;\n}\n\n/** Build shell statements without hand-written quoting. Helpers describe code; they do not execute commands. */\nexport const shell = {\n /**\n * Reference a shell variable at runtime.\n * @example shell.export(\"VISUAL\", shell.variable(\"EDITOR\"))\n */\n variable(name: string): ShellExpression {\n return { kind: \"variable\", name: validateVariable(name) };\n },\n /**\n * Expand a path under the shell's HOME at runtime.\n * @example shell.home(\".local/bin\")\n */\n home(path = \"\"): ShellExpression {\n if (path.includes(\"\\0\") || path.includes(\"\\n\")) throw new Error(\"Invalid home-relative path\");\n return { kind: \"home\", path: path.replace(/^\\//, \"\") };\n },\n /** Join literals and expressions into one shell value. */\n concat(...values: readonly ShellValue[]): ShellExpression {\n return { kind: \"concat\", values };\n },\n /** Use a command's stdout as a value via command substitution. */\n capture(command: ShellCommand): ShellExpression {\n return { kind: \"capture\", command };\n },\n /** Describe a command and its arguments. Use `capture` for its output or `eval` for initialization code. */\n command(\n command: string,\n args: readonly ShellValue[] = [],\n options: Pick<ShellCommand, \"stderr\"> = {},\n ): ShellCommand {\n if (!command || command.includes(\"\\0\") || command.includes(\"\\n\")) {\n throw new Error(\"Invalid shell command\");\n }\n return { command, args, ...options };\n },\n /** Set and export an environment variable. */\n export(name: string, value: ShellValue): ShellStatement {\n return { kind: \"export\", name: validateVariable(name), value };\n },\n /** Set a shell variable without exporting it. */\n assign(name: string, value: ShellValue): ShellStatement {\n return { kind: \"assign\", name: validateVariable(name), value };\n },\n /** Remove one or more shell variables. */\n unset(...names: readonly string[]): ShellStatement {\n if (names.length === 0) throw new Error(\"unset requires at least one variable\");\n return { kind: \"unset\", names: names.map(validateVariable) };\n },\n /**\n * Prepend paths while retaining the current PATH.\n * @example shell.prependPath(shell.home(\".local/bin\"))\n */\n prependPath(...values: readonly ShellValue[]): ShellStatement {\n return { kind: \"prepend-path\", values };\n },\n /** Define an alias; its command text is interpreted when the alias runs. */\n alias(name: string, command: string): ShellStatement {\n if (!/^[A-Za-z0-9_.-]+$/.test(name)) throw new Error(`Invalid shell alias: ${name}`);\n return { kind: \"alias\", name, command };\n },\n /**\n * Evaluate shell code printed by a command.\n * @example shell.eval(shell.command(\"mise\", [\"activate\", \"zsh\"]))\n */\n eval(command: ShellCommand): ShellStatement {\n return { kind: \"eval\", command };\n },\n /** Source another shell file. With `ifExists: true`, source only when readable. */\n source(path: ShellValue, options: { readonly ifExists?: boolean } = {}): ShellStatement {\n return { kind: \"source\", path, ifExists: options.ifExists ?? false };\n },\n /** Generate a shell-time conditional containing one or more statements. */\n when(condition: ShellCondition, statements: readonly ShellStatement[]): ShellStatement {\n if (statements.length === 0) throw new Error(\"Shell condition requires at least one statement\");\n return { kind: \"if\", condition, statements };\n },\n /** Insert literal shell code without validation or quoting. Prefer typed helpers for ordinary statements. */\n raw(code: string): ShellStatement {\n return { kind: \"raw\", code };\n },\n /** Construct conditions evaluated when the shell starts. */\n condition: {\n /** Test whether a command is available on PATH. */\n commandExists(command: string): ShellCondition {\n if (!command || command.includes(\"\\0\") || command.includes(\"\\n\")) {\n throw new Error(\"Invalid shell command\");\n }\n return { kind: \"command-exists\", command };\n },\n /** Test whether a path is executable. */\n executable(path: ShellValue): ShellCondition {\n return { kind: \"executable\", path };\n },\n /** Test whether a path is a regular file. */\n file(path: ShellValue): ShellCondition {\n return { kind: \"file\", path };\n },\n /** Test whether a path is a directory. */\n directory(path: ShellValue): ShellCondition {\n return { kind: \"directory\", path };\n },\n /** Test whether a value is empty. */\n empty(value: ShellValue): ShellCondition {\n return { kind: \"empty\", value };\n },\n /** Test whether a value is non-empty. */\n nonEmpty(value: ShellValue): ShellCondition {\n return { kind: \"non-empty\", value };\n },\n /** Combine conditions with shell AND. */\n and(...conditions: readonly ShellCondition[]): ShellCondition {\n if (conditions.length === 0) throw new Error(\"and requires at least one condition\");\n return { kind: \"and\", conditions };\n },\n /** Combine conditions with shell OR. */\n or(...conditions: readonly ShellCondition[]): ShellCondition {\n if (conditions.length === 0) throw new Error(\"or requires at least one condition\");\n return { kind: \"or\", conditions };\n },\n /** Negate a condition. */\n not(condition: ShellCondition): ShellCondition {\n return { kind: \"not\", condition };\n },\n },\n};\n\n/** Declare independent Zsh startup files. Each defaults to overwrite with original-file restoration. */\nexport const zsh = {\n /** Generate ~/.zshenv, read by every Zsh invocation. Keep this minimal. */\n zshenv: (statements: readonly ShellStatement[], options?: ShellFileOptions) =>\n shellFile(\"zsh\", \"~/.zshenv\", statements, options),\n /** Generate ~/.zprofile for login-shell environment initialization. */\n zprofile: (statements: readonly ShellStatement[], options?: ShellFileOptions) =>\n shellFile(\"zsh\", \"~/.zprofile\", statements, options),\n /** Generate ~/.zshrc for interactive aliases, prompts, and completion. */\n zshrc: (statements: readonly ShellStatement[], options?: ShellFileOptions) =>\n shellFile(\"zsh\", \"~/.zshrc\", statements, options),\n /** Enable Zsh-only options using uppercase names. Cannot be rendered to Bash. */\n setopt(...options: readonly string[]): ShellStatement {\n if (options.length === 0) throw new Error(\"setopt requires at least one option\");\n for (const option of options) {\n if (!/^[A-Z_]+$/.test(option)) throw new Error(`Invalid Zsh option: ${option}`);\n }\n return { kind: \"zsh-setopt\", options };\n },\n};\n\n/** Declare Bash startup files. Bash login shells read the first available profile file. */\nexport const bash = {\n /** Generate ~/.bashrc for interactive non-login shells. */\n bashrc: (statements: readonly ShellStatement[], options?: ShellFileOptions) =>\n shellFile(\"bash\", \"~/.bashrc\", statements, options),\n /** Generate ~/.bash_profile for Bash login shells; source ~/.bashrc explicitly if desired. */\n bashProfile: (statements: readonly ShellStatement[], options?: ShellFileOptions) =>\n shellFile(\"bash\", \"~/.bash_profile\", statements, options),\n /** Generate ~/.profile using Bash syntax; use only where Bash will read it. */\n profile: (statements: readonly ShellStatement[], options?: ShellFileOptions) =>\n shellFile(\"bash\", \"~/.profile\", statements, options),\n};\n\n/** Render statements to shell text without writing a file or running a command. */\nexport function renderShell(statements: readonly ShellStatement[], target: Shell): string {\n return `${statements.map((statement) => renderStatement(statement, target, 0)).join(\"\\n\")}\\n`;\n}\n\n/** Render shell statements into a generated startup-file resource. */\nfunction shellFile(\n format: Shell,\n target: string,\n statements: readonly ShellStatement[],\n options: ShellFileOptions = {},\n): GeneratedFileResource {\n return {\n kind: \"generated-file\",\n target,\n format,\n value: renderShell(statements, format),\n ifExists: options.ifExists ?? \"overwrite\",\n mode: options.mode ?? 0o644,\n };\n}\n\n/** Render a shell statement at the requested indentation depth. */\nfunction renderStatement(statement: ShellStatement, target: Shell, depth: number): string {\n const indent = \" \".repeat(depth);\n switch (statement.kind) {\n case \"export\":\n return `${indent}export ${statement.name}=${renderValue(statement.value)}`;\n case \"assign\":\n return `${indent}${statement.name}=${renderValue(statement.value)}`;\n case \"unset\":\n return `${indent}unset ${statement.names.join(\" \")}`;\n case \"prepend-path\":\n return `${indent}export PATH=${[...statement.values.map(renderValue), '\"$PATH\"'].join(\":\")}`;\n case \"alias\":\n return `${indent}alias ${statement.name}=${quote(statement.command)}`;\n case \"eval\":\n return `${indent}eval \"${escapeDouble(`$(${renderCommand(statement.command)})`)}\"`;\n case \"source\": {\n const source = `source ${renderValue(statement.path)}`;\n return statement.ifExists\n ? `${indent}if [[ -r ${renderValue(statement.path)} ]]; then ${source}; fi`\n : `${indent}${source}`;\n }\n case \"if\":\n return [\n `${indent}if ${renderCondition(statement.condition)}; then`,\n ...statement.statements.map((child) => renderStatement(child, target, depth + 1)),\n `${indent}fi`,\n ].join(\"\\n\");\n case \"zsh-setopt\":\n if (target !== \"zsh\") throw new Error(\"setopt is only valid in Zsh configuration\");\n return `${indent}setopt ${statement.options.join(\" \")}`;\n case \"raw\":\n return statement.code.split(\"\\n\").map((line) => `${indent}${line}`).join(\"\\n\");\n }\n}\n\n/** Translate a typed condition into shell test syntax. */\nfunction renderCondition(condition: ShellCondition): string {\n switch (condition.kind) {\n case \"command-exists\":\n return `command -v ${quote(condition.command)} >/dev/null 2>&1`;\n case \"executable\":\n return `[[ -x ${renderValue(condition.path)} ]]`;\n case \"file\":\n return `[[ -f ${renderValue(condition.path)} ]]`;\n case \"directory\":\n return `[[ -d ${renderValue(condition.path)} ]]`;\n case \"empty\":\n return `[[ -z ${renderValue(condition.value)} ]]`;\n case \"non-empty\":\n return `[[ -n ${renderValue(condition.value)} ]]`;\n case \"and\":\n return condition.conditions.map(renderCondition).join(\" && \");\n case \"or\":\n return condition.conditions.map(renderCondition).join(\" || \");\n case \"not\":\n return `! ${renderCondition(condition.condition)}`;\n }\n}\n\n/** Quote command arguments and append the requested stderr redirection. */\nfunction renderCommand(command: ShellCommand): string {\n const stderr = command.stderr === \"ignore\" ? \" 2>/dev/null\" : \"\";\n return [quote(command.command), ...(command.args ?? []).map(renderValue)].join(\" \") + stderr;\n}\n\n/** Render a value using the target format's literal and expression rules. */\nfunction renderValue(value: ShellValue): string {\n if (typeof value === \"string\") return quote(value);\n switch (value.kind) {\n case \"variable\":\n return `\"\\${${value.name}}\"`;\n case \"home\":\n return `\"\\${HOME}${value.path ? `/${escapeDouble(value.path)}` : \"\"}\"`;\n case \"concat\":\n return `\"${value.values.map(renderInsideDoubleQuotes).join(\"\")}\"`;\n case \"capture\":\n return `\"$(${renderCommand(value.command)})\"`;\n }\n}\n\n/** Render a literal or expression inside an existing double-quoted shell value. */\nfunction renderInsideDoubleQuotes(value: ShellValue): string {\n if (typeof value === \"string\") return escapeDouble(value);\n const rendered = renderValue(value);\n return rendered.startsWith('\"') && rendered.endsWith('\"') ? rendered.slice(1, -1) : rendered;\n}\n\n/** Quote a literal according to the target renderer's escaping rules. */\nfunction quote(value: string): string {\n return `'${value.replaceAll(\"'\", `'\\\\''`)}'`;\n}\n\n/** Escape backslashes and double quotes inside a shell expression. */\nfunction escapeDouble(value: string): string {\n return value.replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll('\"', '\\\\\"');\n}\n\n/** Reject names that are not valid shell variable identifiers. */\nfunction validateVariable(name: string): string {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) throw new Error(`Invalid shell variable: ${name}`);\n return name;\n}\n","import { hostname as readHostname, homedir, platform as readPlatform } from \"node:os\";\nimport { dirname, isAbsolute, resolve } from \"node:path\";\nimport { access } from \"node:fs/promises\";\nimport { resourceId } from \"./identity.js\";\nexport { resourceId, fingerprint } from \"./identity.js\";\nimport { hashSource } from \"./source-hash.js\";\nimport { validateResource } from \"./validation.js\";\nimport { createJiti } from \"jiti/static\";\nimport { resolveTasks } from \"./tasks.js\";\nimport type {\n ConfigDefinition,\n ConfigInput,\n Context,\n PackageManager,\n ResolvedConfig,\n ResolvedResource,\n Resource,\n ResourceInput,\n} from \"../api/types.js\";\n\nconst DEFAULT_CONFIG_FILE = \"workstation.config.ts\";\n\n/** Resolve an explicit entry path, or find workstation.config.ts in the current directory. */\nexport async function findConfig(explicit?: string): Promise<string> {\n if (explicit) return resolve(explicit);\n const path = resolve(DEFAULT_CONFIG_FILE);\n try {\n await access(path);\n return path;\n } catch {\n throw new Error(`No configuration found (${DEFAULT_CONFIG_FILE})`);\n }\n}\n\n/** Load an absolute TypeScript entry path, evaluate fragments, and resolve paths without applying resources. */\nexport async function loadConfig(\n configPath: string,\n machineOverride?: string,\n): Promise<ResolvedConfig> {\n const nativePlatform = readPlatform();\n if (nativePlatform !== \"darwin\" && nativePlatform !== \"linux\") {\n throw new Error(`Unsupported platform: ${nativePlatform}`);\n }\n\n const context: Context = {\n machine: machineOverride ?? readHostname().split(\".\")[0] ?? readHostname(),\n hostname: readHostname(),\n platform: nativePlatform,\n home: homedir(),\n configDir: dirname(configPath),\n };\n const jiti = createJiti(configPath);\n const imported: unknown = await jiti.import(configPath, { default: true });\n const definitions = collectDefinitions(imported, context);\n if (definitions.length === 0) {\n throw new Error(`${configPath} did not produce any configuration`);\n }\n const definition = mergeDefinitions(definitions);\n const inputs = definitions.flatMap((fragment) => [\n fragment.resources,\n fragment.machines?.[context.machine],\n ]);\n const resolved = await Promise.all(\n flatten(inputs).map((resource) => resolveResource(resource, definition, context)),\n );\n const resources = [...new Map(resolved.map((resource) => [resourceId(resource), resource])).values()];\n\n return {\n context,\n ...resolveTasks(definition, context),\n resources,\n stateFile: expandPath(\n definition.stateFile ?? \"~/.local/state/workstation/state.json\",\n context,\n false,\n ),\n };\n}\n\n/** Resolve platform managers and paths, and fingerprint custom-tool source trees. */\nasync function resolveResource(\n resource: Resource,\n definition: ConfigDefinition,\n context: Context,\n): Promise<ResolvedResource> {\n if (resource.kind === \"package\") {\n const manager = resolveManager(resource.manager, definition, context);\n if (resource.upgrade !== undefined && manager !== \"brew-cask\") {\n throw new Error(`Upgrade options are only supported for Homebrew casks (${resource.name})`);\n }\n if (manager === \"mise\") {\n return { ...resource, manager, version: resource.version ?? \"latest\" };\n }\n if (resource.version !== undefined) {\n throw new Error(`${manager} package ${resource.name} cannot declare a version`);\n }\n return { ...resource, manager };\n }\n if (resource.kind === \"symlink\") {\n return {\n ...resource,\n source: expandPath(resource.source, context, true),\n target: expandPath(resource.target, context, false),\n };\n }\n if (resource.kind === \"generated-file\") {\n return { ...resource, target: expandPath(resource.target, context, false) };\n }\n if (resource.kind === \"systemd-service\") {\n if (context.platform !== \"linux\") {\n throw new Error(`systemd service ${resource.name} is only supported on Linux`);\n }\n return {\n ...resource,\n name: resource.name.endsWith(\".service\") ? resource.name : `${resource.name}.service`,\n program: expandPath(resource.program, context, true),\n };\n }\n if (resource.kind === \"custom-tool\") {\n const source = expandPath(resource.source, context, true);\n const target = expandPath(resource.target, context, false);\n return {\n ...resource,\n source,\n target,\n sourceHash: await hashSource(source),\n build: {\n ...resource.build,\n ...(resource.build.cwd && !resource.build.cwd.includes(\"{\")\n ? { cwd: expandPath(resource.build.cwd, context, true) }\n : {}),\n },\n };\n }\n if (context.platform !== \"darwin\") {\n throw new Error(`LaunchAgent ${resource.label} is only supported on macOS`);\n }\n return {\n ...resource,\n program: expandPath(resource.program, context, true),\n ...(resource.stdoutPath\n ? { stdoutPath: expandPath(resource.stdoutPath, context, false) }\n : {}),\n ...(resource.stderrPath\n ? { stderrPath: expandPath(resource.stderrPath, context, false) }\n : {}),\n };\n}\n\n/** Replace the system manager alias with the configured platform backend. */\nfunction resolveManager(\n manager: PackageManager,\n definition: ConfigDefinition,\n context: Context,\n): Exclude<PackageManager, \"system\"> {\n if (manager !== \"system\") return manager;\n return definition.managers?.[context.platform] ?? (context.platform === \"darwin\" ? \"brew\" : \"apt\");\n}\n\n/** Expand home shorthand and resolve relative paths against home or the entry directory. */\nfunction expandPath(path: string, context: Context, relativeToConfig: boolean): string {\n const expanded = path === \"~\" ? context.home : path.replace(/^~\\//, `${context.home}/`);\n if (isAbsolute(expanded)) return resolve(expanded);\n return resolve(relativeToConfig ? context.configDir : context.home, expanded);\n}\n\n/** Flatten nested declarations while omitting disabled or absent entries. */\nfunction flatten(input: ResourceInput): Resource[] {\n if (!input) return [];\n if (Array.isArray(input)) return input.flatMap((item) => flatten(item));\n validateResource(input);\n return [input];\n}\n\n/** Require a non-array configuration object at the loading boundary. */\nfunction validateDefinition(value: unknown): asserts value is ConfigDefinition {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new Error(\"Configuration must resolve to an object\");\n }\n}\n\n/** Evaluate and flatten configuration fragments in declaration order. */\nfunction collectDefinitions(value: unknown, context: Context): ConfigDefinition[] {\n if (value === null || value === undefined || value === false) return [];\n if (typeof value === \"function\") {\n return collectDefinitions((value as (context: Context) => ConfigInput)(context), context);\n }\n if (Array.isArray(value)) {\n return value.flatMap((fragment) => collectDefinitions(fragment, context));\n }\n validateDefinition(value);\n return [value];\n}\n\n/** Merge manager and state-path settings; later declarations override earlier settings. */\nfunction mergeDefinitions(definitions: readonly ConfigDefinition[]): ConfigDefinition {\n return definitions.reduce<ConfigDefinition>(\n (merged, fragment) => ({\n managers: { ...merged.managers, ...fragment.managers },\n tasks: { ...merged.tasks, ...fragment.tasks },\n aliases: { ...merged.aliases, ...fragment.aliases },\n ...(fragment.stateFile !== undefined\n ? { stateFile: fragment.stateFile }\n : merged.stateFile !== undefined\n ? { stateFile: merged.stateFile }\n : {}),\n }),\n {},\n );\n}\n","import { createHash } from \"node:crypto\";\nimport type { ResolvedResource } from \"../api/types.js\";\n\n/** Stable ownership key. File-like resources share their destination as an identity. */\nexport function resourceId(resource: ResolvedResource): string {\n switch (resource.kind) {\n case \"package\":\n return `package:${resource.manager}:${resource.name}`;\n case \"symlink\":\n return `file:${resource.target}`;\n case \"launch-agent\":\n return `launch-agent:${resource.label}`;\n case \"generated-file\":\n return `file:${resource.target}`;\n case \"systemd-service\":\n return `systemd-service:${resource.scope}:${resource.name}`;\n case \"custom-tool\":\n return `file:${resource.target}`;\n }\n}\n\n/** SHA-256 of a declaration with object keys ordered consistently. Array order remains meaningful. */\nexport function fingerprint(resource: ResolvedResource): string {\n return createHash(\"sha256\").update(stableJson(resource)).digest(\"hex\");\n}\n\n/** Serialize values deterministically by sorting object keys while preserving array order. */\nfunction stableJson(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(stableJson).join(\",\")}]`;\n if (typeof value === \"object\" && value !== null) {\n return `{${Object.entries(value)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, child]) => `${JSON.stringify(key)}:${stableJson(child)}`)\n .join(\",\")}}`;\n }\n return JSON.stringify(value);\n}\n","import { createHash } from \"node:crypto\";\nimport { lstat, readFile, readdir, readlink } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\n/** Hash a source tree deterministically, including file contents and symlink targets. */\nexport async function hashSource(path: string): Promise<string> {\n const hash = createHash(\"sha256\");\n await addPathToHash(hash, path, \".\");\n return hash.digest(\"hex\");\n}\n\n/** Visit one source entry and its sorted children, recording entry type and relative path. */\nexport async function addPathToHash(\n hash: ReturnType<typeof createHash>,\n path: string,\n relativePath: string,\n): Promise<void> {\n const stats = await lstat(path);\n if (stats.isSymbolicLink()) {\n hash.update(`link\\0${relativePath}\\0${await readlink(path)}\\0`);\n return;\n }\n if (stats.isFile()) {\n hash.update(`file\\0${relativePath}\\0`);\n hash.update(await readFile(path));\n return;\n }\n if (!stats.isDirectory()) throw new Error(`Unsupported custom tool source entry: ${path}`);\n hash.update(`directory\\0${relativePath}\\0`);\n const entries = (await readdir(path, { withFileTypes: true })).sort((left, right) =>\n left.name.localeCompare(right.name),\n );\n for (const entry of entries) {\n await addPathToHash(hash, resolve(path, entry.name), `${relativePath}/${entry.name}`);\n }\n}\n","import type { Resource } from \"../api/types.js\";\n\n/** Validate a resource declaration before resolving paths or running backends. */\nexport function validateResource(value: unknown): asserts value is Resource {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new Error(\"Every configured resource must be an object, array, or falsey value\");\n }\n const candidate = value as Record<string, unknown>;\n switch (candidate.kind) {\n case \"package\":\n if (\n ![\"mise\", \"brew\", \"brew-cask\", \"apt\", \"system\"].includes(String(candidate.manager)) ||\n typeof candidate.name !== \"string\" ||\n candidate.name.length === 0 ||\n (candidate.version !== undefined && typeof candidate.version !== \"string\") ||\n !isBrewCaskUpgradeOptions(candidate.upgrade)\n ) {\n throw new Error(\"Invalid package resource\");\n }\n return;\n case \"symlink\":\n if (typeof candidate.source !== \"string\" || typeof candidate.target !== \"string\") {\n throw new Error(\"Invalid symlink resource\");\n }\n return;\n case \"launch-agent\":\n if (\n typeof candidate.label !== \"string\" ||\n !/^[A-Za-z0-9.-]+$/.test(candidate.label) ||\n typeof candidate.program !== \"string\" ||\n (candidate.args !== undefined &&\n (!Array.isArray(candidate.args) ||\n !candidate.args.every((argument) => typeof argument === \"string\")))\n ) {\n throw new Error(\"Invalid LaunchAgent resource\");\n }\n return;\n case \"generated-file\":\n if (\n typeof candidate.target !== \"string\" ||\n ![\"toml\", \"yaml\", \"json\", \"jsonc\", \"zsh\", \"bash\"].includes(String(candidate.format)) ||\n ![\"update\", \"overwrite\", \"ignore\"].includes(String(candidate.ifExists)) ||\n !isConfigValue(candidate.value) ||\n (candidate.renderedContent !== undefined &&\n (candidate.format !== \"jsonc\" || typeof candidate.renderedContent !== \"string\")) ||\n ([\"zsh\", \"bash\"].includes(String(candidate.format)) &&\n typeof candidate.value !== \"string\") ||\n (candidate.mode !== undefined &&\n (typeof candidate.mode !== \"number\" ||\n !Number.isInteger(candidate.mode) ||\n candidate.mode < 0 ||\n candidate.mode > 0o777))\n ) {\n throw new Error(\"Invalid generated file resource\");\n }\n return;\n case \"custom-tool\":\n if (\n typeof candidate.name !== \"string\" ||\n !/^[A-Za-z0-9_.-]+$/.test(candidate.name) ||\n typeof candidate.source !== \"string\" ||\n typeof candidate.target !== \"string\" ||\n !isCommandSpec(candidate.build)\n ) {\n throw new Error(\"Invalid custom tool resource\");\n }\n return;\n case \"systemd-service\":\n if (\n typeof candidate.name !== \"string\" ||\n !/^[A-Za-z0-9_.@-]+(?:\\.service)?$/.test(candidate.name) ||\n typeof candidate.program !== \"string\" ||\n ![\"user\", \"system\"].includes(String(candidate.scope)) ||\n (candidate.restart !== undefined &&\n ![\"no\", \"on-failure\", \"always\"].includes(String(candidate.restart))) ||\n (candidate.args !== undefined &&\n (!Array.isArray(candidate.args) ||\n !candidate.args.every((argument) => typeof argument === \"string\"))) ||\n (candidate.environment !== undefined && !isStringRecord(candidate.environment))\n ) {\n throw new Error(\"Invalid systemd service resource\");\n }\n return;\n default:\n throw new Error(`Unknown resource kind: ${String(candidate.kind)}`);\n }\n}\n\n/** Check that a value consists only of supported finite JSON-like data. */\nfunction isConfigValue(value: unknown): boolean {\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"boolean\" ||\n (typeof value === \"number\" && Number.isFinite(value))\n ) {\n return true;\n }\n if (Array.isArray(value)) return value.every(isConfigValue);\n return typeof value === \"object\" && value !== null && Object.values(value).every(isConfigValue);\n}\n\n/** Check that an object contains only string values. */\nfunction isStringRecord(value: unknown): boolean {\n return (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n Object.values(value).every((item) => typeof item === \"string\")\n );\n}\n\n/** Validate a direct command declaration, arguments, working directory, and environment. */\nfunction isCommandSpec(value: unknown): boolean {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n const candidate = value as Record<string, unknown>;\n return (\n typeof candidate.command === \"string\" &&\n candidate.command.length > 0 &&\n (candidate.args === undefined ||\n (Array.isArray(candidate.args) && candidate.args.every((item) => typeof item === \"string\"))) &&\n (candidate.cwd === undefined || typeof candidate.cwd === \"string\") &&\n (candidate.environment === undefined || isStringRecord(candidate.environment))\n );\n}\n\n/** Validate the supported Homebrew upgrade option fields. */\nfunction isBrewCaskUpgradeOptions(value: unknown): boolean {\n if (value === undefined) return true;\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n const options = value as Record<string, unknown>;\n return (\n Object.keys(options).every((key) => key === \"greedy\" || key === \"force\") &&\n (options.greedy === undefined || typeof options.greedy === \"boolean\") &&\n (options.force === undefined || typeof options.force === \"boolean\")\n );\n}\n","import { mkdir, readFile, rename, writeFile } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\nimport { parse, stringify, type TomlTableWithoutBigInt } from \"smol-toml\";\nimport type {\n Context,\n ConfigValue,\n CustomToolResource,\n GeneratedFileResource,\n LaunchAgentResource,\n PackageResource,\n ResolvedPackageResource,\n ResolvedConfig,\n ResolvedResource,\n SymlinkResource,\n SystemdServiceResource,\n} from \"../api/types.js\";\n\nconst MANIFEST_VERSION = 1;\n\n/** Return the resolved config.toml path beside the private ownership state. */\nexport function manifestPath(config: ResolvedConfig): string {\n return resolve(dirname(config.stateFile), \"config.toml\");\n}\n\n/** Write resolved declarations atomically as a private TOML manifest. */\nexport async function writeManifest(path: string, config: ResolvedConfig): Promise<void> {\n const document = {\n version: MANIFEST_VERSION,\n state_file: config.stateFile,\n context: {\n machine: config.context.machine,\n hostname: config.context.hostname,\n platform: config.context.platform,\n home: config.context.home,\n config_dir: config.context.configDir,\n },\n resources: config.resources.map(toTomlResource),\n };\n await mkdir(dirname(path), { recursive: true, mode: 0o700 });\n const temporary = `${path}.${process.pid}.tmp`;\n await writeFile(temporary, stringify(document), { mode: 0o600 });\n await rename(temporary, path);\n}\n\n/** Read and validate a resolved manifest; reject unsupported schema versions. */\nexport async function readManifest(path: string): Promise<ResolvedConfig> {\n const document = parse(await readFile(path, \"utf8\"));\n if (document.version !== MANIFEST_VERSION) {\n throw new Error(`Unsupported workstation manifest version in ${path}`);\n }\n const stateFile = requireString(document.state_file, \"state_file\");\n const context = parseContext(requireTable(document.context, \"context\"));\n if (!Array.isArray(document.resources)) throw new Error(\"Manifest resources must be an array\");\n const resources = document.resources.map((resource, index) =>\n parseResource(requireTable(resource, `resources[${index}]`)),\n );\n return { context, resources, stateFile };\n}\n\n/** Encode a resolved resource using the manifest's field names and JSON value payload. */\nfunction toTomlResource(resource: ResolvedResource): TomlTableWithoutBigInt {\n switch (resource.kind) {\n case \"package\":\n return {\n kind: resource.kind,\n manager: resource.manager,\n name: resource.name,\n ...(resource.version ? { version: resource.version } : {}),\n ...(resource.lockedVersion ? { locked_version: resource.lockedVersion } : {}),\n ...(resource.upgrade\n ? {\n upgrade: {\n ...(resource.upgrade.greedy !== undefined\n ? { greedy: resource.upgrade.greedy }\n : {}),\n ...(resource.upgrade.force !== undefined ? { force: resource.upgrade.force } : {}),\n },\n }\n : {}),\n };\n case \"symlink\":\n return { kind: resource.kind, source: resource.source, target: resource.target };\n case \"launch-agent\":\n return {\n kind: resource.kind,\n label: resource.label,\n program: resource.program,\n ...(resource.args ? { args: [...resource.args] } : {}),\n ...(resource.environment ? { environment: { ...resource.environment } } : {}),\n ...(resource.runAtLoad !== undefined ? { run_at_load: resource.runAtLoad } : {}),\n ...(resource.keepAlive !== undefined ? { keep_alive: resource.keepAlive } : {}),\n ...(resource.stdoutPath ? { stdout_path: resource.stdoutPath } : {}),\n ...(resource.stderrPath ? { stderr_path: resource.stderrPath } : {}),\n };\n case \"generated-file\":\n return {\n kind: resource.kind,\n target: resource.target,\n format: resource.format,\n if_exists: resource.ifExists,\n value_json: JSON.stringify(resource.value),\n ...(resource.renderedContent !== undefined ? { rendered_content: resource.renderedContent } : {}),\n ...(resource.mode !== undefined ? { mode: resource.mode } : {}),\n };\n case \"systemd-service\":\n return {\n kind: resource.kind,\n name: resource.name,\n scope: resource.scope,\n program: resource.program,\n ...(resource.description ? { description: resource.description } : {}),\n ...(resource.args ? { args: [...resource.args] } : {}),\n ...(resource.environment ? { environment: { ...resource.environment } } : {}),\n ...(resource.restart ? { restart: resource.restart } : {}),\n ...(resource.wantedBy ? { wanted_by: resource.wantedBy } : {}),\n };\n case \"custom-tool\":\n return {\n kind: resource.kind,\n name: resource.name,\n source: resource.source,\n source_hash: resource.sourceHash ?? \"\",\n target: resource.target,\n build: {\n command: resource.build.command,\n ...(resource.build.args ? { args: [...resource.build.args] } : {}),\n ...(resource.build.cwd ? { cwd: resource.build.cwd } : {}),\n ...(resource.build.environment\n ? { environment: { ...resource.build.environment } }\n : {}),\n },\n };\n }\n}\n\n/** Validate and decode the machine and path context from a manifest. */\nfunction parseContext(value: TomlTableWithoutBigInt): Context {\n const platform = requireString(value.platform, \"context.platform\");\n if (platform !== \"darwin\" && platform !== \"linux\") {\n throw new Error(`Invalid manifest platform: ${platform}`);\n }\n return {\n machine: requireString(value.machine, \"context.machine\"),\n hostname: requireString(value.hostname, \"context.hostname\"),\n platform,\n home: requireString(value.home, \"context.home\"),\n configDir: requireString(value.config_dir, \"context.config_dir\"),\n };\n}\n\n/** Dispatch manifest decoding by resource kind and reject unknown kinds. */\nfunction parseResource(value: TomlTableWithoutBigInt): ResolvedResource {\n const kind = requireString(value.kind, \"resource.kind\");\n if (kind === \"package\") return parsePackage(value);\n if (kind === \"symlink\") return parseSymlink(value);\n if (kind === \"launch-agent\") return parseLaunchAgent(value);\n if (kind === \"generated-file\") return parseGeneratedFile(value);\n if (kind === \"systemd-service\") return parseSystemdService(value);\n if (kind === \"custom-tool\") return parseCustomTool(value);\n throw new Error(`Unknown manifest resource kind: ${kind}`);\n}\n\n/** Validate and decode a generated file, including permissions and rendered JSONC content. */\nfunction parseGeneratedFile(value: TomlTableWithoutBigInt): GeneratedFileResource {\n const format = requireString(value.format, \"generated-file.format\");\n if (value.rendered_content !== undefined && format !== \"jsonc\") {\n throw new Error(\"Pre-rendered content requires JSONC format\");\n }\n const ifExists = requireString(value.if_exists, \"generated-file.if_exists\");\n if (\n format !== \"toml\" &&\n format !== \"yaml\" &&\n format !== \"json\" &&\n format !== \"jsonc\" &&\n format !== \"zsh\" &&\n format !== \"bash\"\n ) {\n throw new Error(`Invalid generated file format: ${format}`);\n }\n if (ifExists !== \"update\" && ifExists !== \"overwrite\" && ifExists !== \"ignore\") {\n throw new Error(`Invalid generated file policy: ${ifExists}`);\n }\n const configValue: unknown = JSON.parse(requireString(value.value_json, \"generated-file.value_json\"));\n if (!isConfigValue(configValue)) throw new Error(\"Invalid generated file value\");\n const mode = value.mode;\n if (\n mode !== undefined &&\n (typeof mode !== \"number\" || !Number.isInteger(mode) || mode < 0 || mode > 0o777)\n ) {\n throw new Error(\"generated-file.mode must be between 0 and 0777\");\n }\n return {\n kind: \"generated-file\",\n target: requireString(value.target, \"generated-file.target\"),\n format,\n ifExists,\n value: configValue,\n ...(value.rendered_content !== undefined\n ? { renderedContent: requireString(value.rendered_content, \"generated-file.rendered_content\") }\n : {}),\n ...(mode !== undefined ? { mode } : {}),\n };\n}\n\n/** Decode a custom tool and its resolved build command from the manifest. */\nfunction parseCustomTool(value: TomlTableWithoutBigInt): CustomToolResource {\n const build = requireTable(value.build, \"custom-tool.build\");\n return {\n kind: \"custom-tool\",\n name: requireString(value.name, \"custom-tool.name\"),\n source: requireString(value.source, \"custom-tool.source\"),\n sourceHash: requireString(value.source_hash, \"custom-tool.source_hash\"),\n target: requireString(value.target, \"custom-tool.target\"),\n build: {\n command: requireString(build.command, \"custom-tool.build.command\"),\n ...(build.args !== undefined\n ? { args: requireStringArray(build.args, \"custom-tool.build.args\") }\n : {}),\n ...(build.cwd !== undefined\n ? { cwd: requireString(build.cwd, \"custom-tool.build.cwd\") }\n : {}),\n ...(build.environment !== undefined\n ? { environment: requireStringTable(build.environment, \"custom-tool.build.environment\") }\n : {}),\n },\n };\n}\n\n/** Validate scope and restart policy while decoding a systemd unit declaration. */\nfunction parseSystemdService(value: TomlTableWithoutBigInt): SystemdServiceResource {\n const scope = requireString(value.scope, \"systemd-service.scope\");\n if (scope !== \"user\" && scope !== \"system\") throw new Error(`Invalid systemd scope: ${scope}`);\n const restart =\n value.restart === undefined ? undefined : requireString(value.restart, \"systemd-service.restart\");\n if (restart !== undefined && restart !== \"no\" && restart !== \"on-failure\" && restart !== \"always\") {\n throw new Error(`Invalid systemd restart policy: ${restart}`);\n }\n return {\n kind: \"systemd-service\",\n name: requireString(value.name, \"systemd-service.name\"),\n scope,\n program: requireString(value.program, \"systemd-service.program\"),\n ...(value.description !== undefined\n ? { description: requireString(value.description, \"systemd-service.description\") }\n : {}),\n ...(value.args !== undefined\n ? { args: requireStringArray(value.args, \"systemd-service.args\") }\n : {}),\n ...(value.environment !== undefined\n ? { environment: requireStringTable(value.environment, \"systemd-service.environment\") }\n : {}),\n ...(restart ? { restart } : {}),\n ...(value.wanted_by !== undefined\n ? { wantedBy: requireString(value.wanted_by, \"systemd-service.wanted_by\") }\n : {}),\n };\n}\n\n/** Validate the resolved package backend, selectors, pins, and cask upgrade options. */\nfunction parsePackage(value: TomlTableWithoutBigInt): ResolvedPackageResource {\n const manager = requireString(value.manager, \"package.manager\");\n if (!isPackageManager(manager)) {\n throw new Error(`Invalid manifest package manager: ${manager}`);\n }\n const upgrade = value.upgrade === undefined ? undefined : requireTable(value.upgrade, \"package.upgrade\");\n if (value.version !== undefined && manager !== \"mise\") {\n throw new Error(`Manifest ${manager} package cannot declare a version`);\n }\n if (upgrade !== undefined && manager !== \"brew-cask\") {\n throw new Error(`Manifest upgrade options require a Homebrew cask`);\n }\n return {\n kind: \"package\",\n manager,\n name: requireString(value.name, \"package.name\"),\n ...(value.version !== undefined\n ? { version: requireString(value.version, \"package.version\") }\n : {}),\n ...(value.locked_version !== undefined\n ? { lockedVersion: requireString(value.locked_version, \"package.locked_version\") }\n : {}),\n ...(upgrade\n ? {\n upgrade: {\n ...(upgrade.greedy !== undefined\n ? { greedy: requireBoolean(upgrade.greedy, \"package.upgrade.greedy\") }\n : {}),\n ...(upgrade.force !== undefined\n ? { force: requireBoolean(upgrade.force, \"package.upgrade.force\") }\n : {}),\n },\n }\n : {}),\n };\n}\n\n/** Decode a symlink's resolved source and destination. */\nfunction parseSymlink(value: TomlTableWithoutBigInt): SymlinkResource {\n return {\n kind: \"symlink\",\n source: requireString(value.source, \"symlink.source\"),\n target: requireString(value.target, \"symlink.target\"),\n };\n}\n\n/** Decode a launchd label, executable, environment, and lifecycle options. */\nfunction parseLaunchAgent(value: TomlTableWithoutBigInt): LaunchAgentResource {\n const args = value.args === undefined ? undefined : requireStringArray(value.args, \"launch-agent.args\");\n const environment =\n value.environment === undefined\n ? undefined\n : requireStringTable(value.environment, \"launch-agent.environment\");\n return {\n kind: \"launch-agent\",\n label: requireString(value.label, \"launch-agent.label\"),\n program: requireString(value.program, \"launch-agent.program\"),\n ...(args ? { args } : {}),\n ...(environment ? { environment } : {}),\n ...(value.run_at_load !== undefined\n ? { runAtLoad: requireBoolean(value.run_at_load, \"launch-agent.run_at_load\") }\n : {}),\n ...(value.keep_alive !== undefined\n ? { keepAlive: requireBoolean(value.keep_alive, \"launch-agent.keep_alive\") }\n : {}),\n ...(value.stdout_path !== undefined\n ? { stdoutPath: requireString(value.stdout_path, \"launch-agent.stdout_path\") }\n : {}),\n ...(value.stderr_path !== undefined\n ? { stderrPath: requireString(value.stderr_path, \"launch-agent.stderr_path\") }\n : {}),\n };\n}\n\n/** Require an object-shaped TOML table and identify the invalid field on failure. */\nfunction requireTable(value: unknown, field: string): TomlTableWithoutBigInt {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new Error(`${field} must be a table`);\n }\n return value as TomlTableWithoutBigInt;\n}\n\n/** Require a non-empty string at a serialized-data boundary. */\nfunction requireString(value: unknown, field: string): string {\n if (typeof value !== \"string\" || value.length === 0) throw new Error(`${field} must be a string`);\n return value;\n}\n\n/** Require a boolean manifest field without coercion. */\nfunction requireBoolean(value: unknown, field: string): boolean {\n if (typeof value !== \"boolean\") throw new Error(`${field} must be a boolean`);\n return value;\n}\n\n/** Require an array containing only strings. */\nfunction requireStringArray(value: unknown, field: string): string[] {\n if (!Array.isArray(value) || !value.every((item) => typeof item === \"string\")) {\n throw new Error(`${field} must be an array of strings`);\n }\n return value;\n}\n\n/** Validate a TOML table of string-valued environment entries. */\nfunction requireStringTable(value: unknown, field: string): Record<string, string> {\n const table = requireTable(value, field);\n const result: Record<string, string> = {};\n for (const [key, item] of Object.entries(table)) {\n if (typeof item !== \"string\") throw new Error(`${field} must contain strings`);\n result[key] = item;\n }\n return result;\n}\n\n/** Recognize concrete package backends accepted by a resolved manifest. */\nfunction isPackageManager(value: string): value is PackageResource[\"manager\"] {\n return value === \"mise\" || value === \"brew\" || value === \"brew-cask\" || value === \"apt\";\n}\n\n/** Check that a value consists only of supported finite JSON-like data. */\nfunction isConfigValue(value: unknown): value is ConfigValue {\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"boolean\" ||\n (typeof value === \"number\" && Number.isFinite(value))\n ) {\n return true;\n }\n if (Array.isArray(value)) return value.every(isConfigValue);\n return typeof value === \"object\" && value !== null && Object.values(value).every(isConfigValue);\n}\n","import { readFile, rename, writeFile } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\nimport { parse, stringify, type TomlTableWithoutBigInt } from \"smol-toml\";\nimport { fingerprint, resourceId } from \"../config/identity.js\";\nimport { resolvePackageVersion } from \"../resources/package-version.js\";\nimport type {\n Platform,\n ResolvedConfig,\n ResolvedResource,\n Runner,\n} from \"../api/types.js\";\n\nconst LOCK_VERSION = 1;\n\ninterface LockEntry {\n readonly id: string;\n readonly fingerprint: string;\n readonly lockedVersion?: string;\n}\n\ninterface LockTarget {\n readonly machine: string;\n readonly platform: Platform;\n readonly resources: readonly LockEntry[];\n}\n\ninterface WorkstationLock {\n readonly version: 1;\n readonly targets: readonly LockTarget[];\n}\n\nexport interface LockedConfigResult {\n readonly config: ResolvedConfig;\n readonly path: string;\n readonly changed: boolean;\n}\n\n/** Return the workstation.lock path beside the TypeScript entry point. */\nexport function lockPath(configPath: string): string {\n return resolve(dirname(configPath), \"workstation.lock\");\n}\n\n/** Resolve package pins and update the current machine's lock target; does not install resources. */\nexport async function lockConfig(\n configPath: string,\n config: ResolvedConfig,\n runner: Runner,\n): Promise<LockedConfigResult> {\n const path = lockPath(configPath);\n const previousText = await readOptional(path);\n const previous = previousText === undefined ? emptyLock() : parseLock(previousText, path);\n const target = previous.targets.find(({ machine }) => machine === config.context.machine);\n const existing = new Map(target?.resources.map((entry) => [entry.id, entry]));\n const resources: ResolvedResource[] = [];\n const entries: LockEntry[] = [];\n\n for (const resource of config.resources) {\n const id = resourceId(resource);\n const declarationFingerprint = fingerprint(resource);\n const prior = existing.get(id);\n const refreshesOnRun =\n resource.kind === \"package\" &&\n resource.manager === \"brew-cask\" &&\n resource.upgrade?.greedy === true;\n const canReuse =\n !refreshesOnRun &&\n prior?.fingerprint === declarationFingerprint &&\n (resource.kind !== \"package\" || prior.lockedVersion !== undefined);\n const lockedVersion =\n canReuse\n ? prior.lockedVersion\n : await resolvePackageVersion(resource, runner);\n resources.push(withLockedVersion(resource, lockedVersion));\n entries.push({\n id,\n fingerprint: declarationFingerprint,\n ...(lockedVersion ? { lockedVersion } : {}),\n });\n }\n\n const nextTarget: LockTarget = {\n machine: config.context.machine,\n platform: config.context.platform,\n resources: entries.sort((left, right) => left.id.localeCompare(right.id)),\n };\n const next: WorkstationLock = {\n version: LOCK_VERSION,\n targets: [\n ...previous.targets.filter(({ machine }) => machine !== config.context.machine),\n nextTarget,\n ].sort((left, right) => left.machine.localeCompare(right.machine)),\n };\n const nextText = stringifyLock(next);\n const changed = previousText !== nextText;\n if (changed) await atomicWrite(path, nextText);\n\n return { config: { ...config, resources }, path, changed };\n}\n\n/** Attach a resolved package pin without changing non-package resources. */\nfunction withLockedVersion(\n resource: ResolvedResource,\n lockedVersion: string | undefined,\n): ResolvedResource {\n if (resource.kind !== \"package\" || lockedVersion === undefined) return resource;\n return { ...resource, lockedVersion };\n}\n\n/** Create an empty lock document using the current schema version. */\nfunction emptyLock(): WorkstationLock {\n return { version: LOCK_VERSION, targets: [] };\n}\n\n/** Serialize machine targets and package pins to the committed TOML format. */\nfunction stringifyLock(lock: WorkstationLock): string {\n return stringify({\n version: lock.version,\n targets: lock.targets.map((target) => ({\n machine: target.machine,\n platform: target.platform,\n resources: target.resources.map((entry) => ({\n id: entry.id,\n fingerprint: entry.fingerprint,\n ...(entry.lockedVersion ? { locked_version: entry.lockedVersion } : {}),\n })),\n })),\n });\n}\n\n/** Validate lock schema, platform names, and duplicate machine/resource identities. */\nfunction parseLock(text: string, path: string): WorkstationLock {\n const document = parse(text);\n if (document.version !== LOCK_VERSION) {\n throw new Error(`Unsupported workstation lock version in ${path}`);\n }\n if (!Array.isArray(document.targets)) throw new Error(`Lock targets must be an array in ${path}`);\n const machines = new Set<string>();\n const targets = document.targets.map((value, targetIndex): LockTarget => {\n const target = requireTable(value, `targets[${targetIndex}]`);\n const machine = requireString(target.machine, `targets[${targetIndex}].machine`);\n if (machines.has(machine)) throw new Error(`Duplicate machine ${machine} in ${path}`);\n machines.add(machine);\n const platform = requireString(target.platform, `targets[${targetIndex}].platform`);\n if (platform !== \"darwin\" && platform !== \"linux\") {\n throw new Error(`Invalid platform for ${machine} in ${path}`);\n }\n if (!Array.isArray(target.resources)) {\n throw new Error(`Lock resources for ${machine} must be an array in ${path}`);\n }\n const ids = new Set<string>();\n const resources = target.resources.map((value, resourceIndex): LockEntry => {\n const entry = requireTable(value, `targets[${targetIndex}].resources[${resourceIndex}]`);\n const id = requireString(entry.id, \"lock resource id\");\n if (ids.has(id)) throw new Error(`Duplicate resource ${id} for ${machine} in ${path}`);\n ids.add(id);\n return {\n id,\n fingerprint: requireString(entry.fingerprint, `lock fingerprint for ${id}`),\n ...(entry.locked_version === undefined\n ? {}\n : { lockedVersion: requireString(entry.locked_version, `locked version for ${id}`) }),\n };\n });\n return { machine, platform, resources };\n });\n return { version: LOCK_VERSION, targets };\n}\n\n/** Require an object-shaped TOML table and identify the invalid field on failure. */\nfunction requireTable(value: unknown, field: string): TomlTableWithoutBigInt {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new Error(`${field} must be a table`);\n }\n return value as TomlTableWithoutBigInt;\n}\n\n/** Require a non-empty string at a serialized-data boundary. */\nfunction requireString(value: unknown, field: string): string {\n if (typeof value !== \"string\" || value.length === 0) throw new Error(`${field} must be a string`);\n return value;\n}\n\n/** Read a lock file, treating only a missing path as an absent lock. */\nasync function readOptional(path: string): Promise<string | undefined> {\n try {\n return await readFile(path, \"utf8\");\n } catch (error) {\n if (typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n}\n\n/** Write a temporary sibling and rename it into place to avoid partial destination content. */\nasync function atomicWrite(path: string, contents: string): Promise<void> {\n const temporary = `${path}.${process.pid}.tmp`;\n await writeFile(temporary, contents, { mode: 0o644 });\n await rename(temporary, path);\n}\n","import { chmod, rename, writeFile } from \"node:fs/promises\";\nimport type { CommandResult, Runner } from \"../api/types.js\";\n\nexport interface Inspection {\n readonly present: boolean;\n readonly matches: boolean;\n readonly installedVersion?: string;\n readonly installedHash?: string;\n readonly conflict?: string;\n}\n\n/** Write a temporary sibling and rename it into place to avoid partial destination content. */\nexport async function atomicWrite(path: string, content: string, mode = 0o644): Promise<void> {\n const temporary = `${path}.${process.pid}.tmp`;\n await writeFile(temporary, content, { mode });\n await chmod(temporary, mode);\n await rename(temporary, path);\n}\n\n/** Run a command and return its output; throw with command context on a nonzero exit. */\nexport async function requireSuccess(\n runner: Runner,\n command: string,\n args: readonly string[],\n options?: Parameters<Runner[\"run\"]>[2],\n): Promise<CommandResult> {\n const result = await runner.run(command, args, options);\n if (result.exitCode !== 0) {\n throw new Error(\n `${command} ${args.join(\" \")} failed (${result.exitCode})${result.stderr ? `: ${result.stderr.trim()}` : \"\"}`,\n );\n }\n return result;\n}\n\n/** Recognize ENOENT without swallowing permission or other filesystem failures. */\nexport function isMissingFile(error: unknown): boolean {\n return error instanceof Error && \"code\" in error && error.code === \"ENOENT\";\n}\n","import type { ResolvedPackageResource, Runner } from \"../api/types.js\";\nimport { requireSuccess } from \"./shared.js\";\n\n/** Read the installed formula or cask version from Homebrew JSON metadata. */\nexport async function readInstalledBrewVersion(\n resource: ResolvedPackageResource,\n runner: Runner,\n): Promise<string | undefined> {\n const document = await readBrewInfo(resource, runner);\n const item = brewItem(document, resource);\n const installed = item.installed;\n if (typeof installed === \"string\") return installed;\n if (Array.isArray(installed)) {\n const value = installed[0];\n if (typeof value === \"string\") return value;\n if (typeof value === \"object\" && value !== null && \"version\" in value) {\n return typeof value.version === \"string\" ? value.version : undefined;\n }\n }\n return undefined;\n}\n\n/** Read the current Homebrew version, including a formula's packaging revision. */\nexport async function readAvailableBrewVersion(\n resource: ResolvedPackageResource,\n runner: Runner,\n): Promise<string> {\n const item = brewItem(await readBrewInfo(resource, runner), resource);\n const baseVersion =\n resource.manager === \"brew-cask\"\n ? item.version\n : typeof item.versions === \"object\" && item.versions !== null && \"stable\" in item.versions\n ? item.versions.stable\n : undefined;\n const version =\n resource.manager === \"brew\" &&\n typeof baseVersion === \"string\" &&\n typeof item.revision === \"number\" &&\n item.revision > 0\n ? `${baseVersion}_${item.revision}`\n : baseVersion;\n if (typeof version !== \"string\" || version.length === 0) {\n throw new Error(`Homebrew did not report an available version for ${resource.name}`);\n }\n return version;\n}\n\n/** Query Homebrew JSON metadata and reject command or malformed-response failures. */\nasync function readBrewInfo(\n resource: ResolvedPackageResource,\n runner: Runner,\n): Promise<Record<string, unknown>> {\n const flag = resource.manager === \"brew-cask\" ? \"--cask\" : \"--formula\";\n const result = await requireSuccess(runner, \"brew\", [\"info\", \"--json=v2\", flag, resource.name]);\n try {\n const value: unknown = JSON.parse(result.stdout);\n if (!isRecord(value)) throw new Error(\"Expected a JSON object\");\n return value;\n } catch (error) {\n throw new Error(`Homebrew returned invalid JSON for ${resource.name}`, { cause: error });\n }\n}\n\n/** Select the formula or cask record from a Homebrew response. */\nfunction brewItem(\n document: Record<string, unknown>,\n resource: ResolvedPackageResource,\n): Record<string, unknown> {\n const collection = document[resource.manager === \"brew-cask\" ? \"casks\" : \"formulae\"];\n const value = Array.isArray(collection) ? collection[0] : undefined;\n if (!isRecord(value)) {\n throw new Error(`Homebrew did not report information for ${resource.name}`);\n }\n return value;\n}\n\n/** Narrow an unknown value to a non-null, non-array object. */\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { readAvailableBrewVersion } from \"./brew-info.js\";\nimport { requireSuccess } from \"./shared.js\";\nimport type { ResolvedResource, Runner } from \"../api/types.js\";\n\n/** Resolve mise/APT/Homebrew selectors; return no pin for non-packages and rolling latest casks. */\nexport async function resolvePackageVersion(\n resource: ResolvedResource,\n runner: Runner,\n): Promise<string | undefined> {\n if (resource.kind !== \"package\") return undefined;\n switch (resource.manager) {\n case \"mise\": {\n const spec = `${resource.name}@${resource.version ?? \"latest\"}`;\n const result = await requireSuccess(runner, \"mise\", [\"latest\", spec]);\n const version = result.stdout.trim().split(/\\s+/).at(-1);\n if (!version) throw new Error(`mise latest ${spec} did not report a version`);\n return version;\n }\n case \"apt\": {\n const result = await requireSuccess(runner, \"apt-cache\", [\"policy\", resource.name]);\n const candidate = /^\\s*Candidate:\\s*(\\S+)\\s*$/m.exec(result.stdout)?.[1];\n if (!candidate || candidate === \"(none)\") {\n throw new Error(`apt has no installation candidate for ${resource.name}`);\n }\n return candidate;\n }\n case \"brew\":\n case \"brew-cask\": {\n const version = await readAvailableBrewVersion(resource, runner);\n return version === \"latest\" ? undefined : version;\n }\n case \"system\":\n throw new Error(\"System package manager must be resolved before locking\");\n }\n}\n","import { spawn } from \"node:child_process\";\nimport type { CommandResult, Runner, RunOptions } from \"../api/types.js\";\n\n/** Run child processes directly, inheriting stdin and capturing stdout/stderr. No implicit shell is used. */\nexport class ProcessRunner implements Runner {\n /** Execute a command directly and return captured output and its exit code; spawn failures reject. */\n async run(\n command: string,\n args: readonly string[],\n options?: RunOptions,\n ): Promise<CommandResult> {\n return await new Promise((resolve, reject) => {\n const child = spawn(command, [...args], {\n cwd: options?.cwd,\n env: { ...process.env, ...options?.environment },\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.setEncoding(\"utf8\");\n child.stderr.setEncoding(\"utf8\");\n child.stdout.on(\"data\", (chunk: string) => (stdout += chunk));\n child.stderr.on(\"data\", (chunk: string) => (stderr += chunk));\n child.once(\"error\", reject);\n child.once(\"close\", (exitCode) =>\n resolve({ exitCode: exitCode ?? 1, stdout, stderr }),\n );\n });\n }\n}\n"],"mappings":"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","names":["task","renderValue","isAbsolute","resolve","createHash","resolve","resolve","flatten","isAbsolute","readFile","dirname","resolve","isConfigValue","readFile","rename","writeFile","dirname","resolve","parse","stringify","rename","writeFile","resolve","dirname","machine","stringify","parse","requireTable","requireString","value","readFile","writeFile","rename","resolve"]}
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@dovocode/workstation",
3
+ "version": "0.1.0",
4
+ "description": "A stateful, programmable workstation configuration reconciler",
5
+ "type": "module",
6
+ "bin": {
7
+ "workstation": "dist/cli.js"
8
+ },
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist/*.js",
17
+ "dist/*.d.ts",
18
+ "dist/*.map"
19
+ ],
20
+ "scripts": {
21
+ "docs": "node scripts/check-docs.mjs && typedoc --options typedoc.json --treatWarningsAsErrors",
22
+ "docs:check": "node scripts/check-docs.mjs",
23
+ "build": "tsup",
24
+ "build:native": "tsup && node scripts/build-native.mjs",
25
+ "check": "tsc --noEmit && eslint .",
26
+ "test": "vitest run"
27
+ },
28
+ "dependencies": {
29
+ "jiti": "2.7.0",
30
+ "smol-toml": "1.8.0",
31
+ "yaml": "2.9.0"
32
+ },
33
+ "devDependencies": {
34
+ "@eslint/js": "10.0.1",
35
+ "@types/node": "24.3.1",
36
+ "eslint": "10.10.0",
37
+ "postject": "1.0.0-alpha.6",
38
+ "tsup": "8.5.0",
39
+ "typedoc": "0.28.20",
40
+ "typescript": "5.9.2",
41
+ "typescript-eslint": "8.69.0",
42
+ "vitest": "3.2.4"
43
+ },
44
+ "engines": {
45
+ "node": ">=22.13"
46
+ },
47
+ "packageManager": "pnpm@10.17.1",
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "git+https://github.com/dovocode/workstation.git"
51
+ },
52
+ "homepage": "https://github.com/dovocode/workstation",
53
+ "bugs": {
54
+ "url": "https://github.com/dovocode/workstation/issues"
55
+ },
56
+ "publishConfig": {
57
+ "access": "public"
58
+ }
59
+ }