#!/usr/bin/env -S npx --yes tsx // ============================================================================= // init.ts — Initialize a data store from a YAML definition // // Part of: .opencode/skills/templating-vault/scripts/ // // Creates or validates a data directory from a YAML definition file. // Handles three modes for existing stores: ignore, validate, fix. // // USAGE: // init.ts --source --target // [--on-exists ignore|validate|fix] // // DEFINITION FORMAT: // defaults: // literal: true // type: string // keys: // credentials.forgejo_pat: // literal: true // write_once: true // type: hex // description: "Primary bot Forgejo PAT" // value: "preset_value" # optional preset value // config.max_workers: // literal: false // type: positive_integer // on_absent: "4" // // OUTPUT (stdout): JSON result // ============================================================================= import * as fs from 'node:fs'; import * as path from 'node:path'; import { fileURLToPath } from 'node:url'; import yaml from 'js-yaml'; import { parseCommonFlags, getFlag, output, log, atomicWrite, } from './api.ts'; interface KeyDefinition { literal?: boolean; readonly?: boolean; write_once?: boolean; type?: string; validate?: { regex?: string; message?: string }; template?: boolean; on_absent?: string | number; description?: string; value?: string; // optional preset value owner?: string; } interface StoreDefinition { defaults?: Record; keys?: Record; } async function main(): Promise { const { rest } = parseCommonFlags(process.argv); const source = getFlag(rest, '--source'); const target = getFlag(rest, '--target'); const onExists = (getFlag(rest, '--on-exists') ?? 'ignore') as 'ignore' | 'validate' | 'fix'; if (!source) { output({ initialized: false, error: '--source is required' }); process.exit(1); } if (!target) { output({ initialized: false, error: '--target is required' }); process.exit(1); } if (!fs.existsSync(source)) { output({ initialized: false, error: `Source file "${source}" not found` }); process.exit(1); } const definition = yaml.load(fs.readFileSync(source, 'utf-8')) as StoreDefinition; if (!definition) { output({ initialized: false, error: 'Empty or invalid YAML definition' }); process.exit(1); } const targetExists = fs.existsSync(target); if (targetExists && onExists === 'ignore') { output({ initialized: true, action: 'ignored', message: 'Store already exists' }); return; } // Create target directory fs.mkdirSync(target, { recursive: true }); const actions: string[] = []; const errors: string[] = []; // Write .store.yaml with defaults if (definition.defaults) { const storeYamlPath = path.join(target, '.store.yaml'); if (!targetExists || onExists === 'fix' || !fs.existsSync(storeYamlPath)) { atomicWrite(storeYamlPath, yaml.dump({ defaults: definition.defaults }, { lineWidth: -1 })); actions.push('wrote .store.yaml'); } else if (onExists === 'validate') { // Check if existing .store.yaml matches const existing = fs.existsSync(storeYamlPath) ? yaml.load(fs.readFileSync(storeYamlPath, 'utf-8')) : null; if (JSON.stringify(existing) !== JSON.stringify({ defaults: definition.defaults })) { errors.push('.store.yaml diverges from definition'); } } } // Process keys if (definition.keys) { for (const [keyPath, keyDef] of Object.entries(definition.keys)) { const segments = keyPath.split('.'); const keyDir = path.join(target, ...segments); // Create directory fs.mkdirSync(keyDir, { recursive: true }); // Write meta.yaml const metaPath = path.join(keyDir, 'meta.yaml'); const metaContent: Record = {}; if (keyDef.literal !== undefined) metaContent.literal = keyDef.literal; if (keyDef.readonly !== undefined) metaContent.readonly = keyDef.readonly; if (keyDef.write_once !== undefined) metaContent.write_once = keyDef.write_once; if (keyDef.type !== undefined) metaContent.type = keyDef.type; if (keyDef.validate !== undefined) metaContent.validate = keyDef.validate; if (keyDef.template !== undefined) metaContent.template = keyDef.template; if (keyDef.on_absent !== undefined) metaContent.on_absent = keyDef.on_absent; if (keyDef.description !== undefined) metaContent.description = keyDef.description; if (keyDef.owner !== undefined) metaContent.owner = keyDef.owner; if (Object.keys(metaContent).length > 0) { if (!targetExists || onExists === 'fix' || !fs.existsSync(metaPath)) { atomicWrite(metaPath, yaml.dump(metaContent, { lineWidth: -1 })); actions.push(`wrote meta for ${keyPath}`); } else if (onExists === 'validate') { const existing = fs.existsSync(metaPath) ? yaml.load(fs.readFileSync(metaPath, 'utf-8')) : null; if (JSON.stringify(existing) !== JSON.stringify(metaContent)) { errors.push(`${keyPath}: meta.yaml diverges from definition`); } } } // Write preset value if defined if (keyDef.value !== undefined) { const valuePath = path.join(keyDir, 'value'); if (!targetExists || onExists === 'fix' || !fs.existsSync(valuePath)) { atomicWrite(valuePath, String(keyDef.value)); actions.push(`wrote value for ${keyPath}`); } else if (onExists === 'validate') { const existing = fs.existsSync(valuePath) ? fs.readFileSync(valuePath, 'utf-8') : null; if (existing !== String(keyDef.value)) { errors.push(`${keyPath}: value diverges from definition`); } } } } } if (onExists === 'validate' && errors.length > 0) { output({ initialized: false, action: 'validate', errors }); process.exit(1); } output({ initialized: true, action: targetExists ? onExists : 'created', target, actions, }); } if (process.argv[1] === fileURLToPath(import.meta.url)) { main().catch((err: unknown) => { output({ initialized: false, error: String(err instanceof Error ? err.message : err) }); process.exit(1); }); }