@precisa-saude/cli 1.7.0 → 1.8.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.
package/dist/bin.js CHANGED
@@ -135,6 +135,7 @@ function tokenContext(manifest) {
135
135
  SECURITY_EMAIL: manifest.contactEmails.security,
136
136
  SITE_FILTER: manifest.siteFilter ?? "",
137
137
  SITE_PROJECT_NAME: manifest.siteProjectName ?? "",
138
+ SITE_SOURCE_PATH: manifest.siteSourcePath ?? "site/",
138
139
  VISIBILITY: manifest.visibility
139
140
  };
140
141
  }
@@ -192,6 +193,9 @@ function validateManifest(raw) {
192
193
  if (m.siteFilter !== void 0 && typeof m.siteFilter !== "string") {
193
194
  errors.push({ message: "must be a string", path: "siteFilter" });
194
195
  }
196
+ if (m.siteSourcePath !== void 0 && typeof m.siteSourcePath !== "string") {
197
+ errors.push({ message: "must be a string", path: "siteSourcePath" });
198
+ }
195
199
  if (!m.contactEmails || typeof m.contactEmails !== "object") {
196
200
  errors.push({ message: "must be an object", path: "contactEmails" });
197
201
  } else {
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bin.ts","../src/commands/doctor.ts","../src/lib/templates.ts","../src/lib/paths.ts","../src/manifest.ts","../src/commands/new.ts","../src/lib/merge.ts","../src/commands/sync.ts","../src/lib/diff.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\n\nimport { runDoctor } from './commands/doctor.js';\nimport { runNew } from './commands/new.js';\nimport { runSync } from './commands/sync.js';\n\nconst program = new Command();\n\nprogram\n .name('precisa')\n .description('Bootstrap and sync Precisa Saúde repositories.')\n .version('0.0.0');\n\nprogram\n .command('new <repo-name>')\n .description('Scaffold a new repository from the shared templates.')\n .option('--profile <profile>', 'preset: oss-library | oss-site | private-app', 'oss-library')\n .option('--dry-run', 'print what would be written without touching disk', false)\n .option('--non-interactive', 'skip prompts; use --owner/--scopes/etc. flags instead', false)\n .option('--owner <org>', 'GitHub owner (org or user)', 'Precisa-Saude')\n .option(\n '--scopes <csv>',\n 'Comma-separated commit scopes (e.g. \"core,docs,ci,deps\")',\n 'docs,ci,deps',\n )\n .option('--security-email <email>', 'Security contact email', 'security@precisa-saude.com.br')\n .option(\n '--conduct-email <email>',\n 'Code-of-conduct contact email',\n 'conduct@precisa-saude.com.br',\n )\n .action(\n async (\n repoName: string,\n opts: {\n profile: string;\n dryRun: boolean;\n nonInteractive: boolean;\n owner: string;\n scopes: string;\n securityEmail: string;\n conductEmail: string;\n },\n ) => {\n await runNew(repoName, opts);\n },\n );\n\nprogram\n .command('sync')\n .description(\"Re-render templates against this repo's .precisa.json manifest.\")\n .option('--dry-run', 'print a diff without writing', false)\n .action(async (opts: { dryRun: boolean }) => {\n await runSync(opts);\n });\n\nprogram\n .command('doctor')\n .description('Audit this repo against the templates and report drift.')\n .action(async () => {\n await runDoctor();\n });\n\nprogram.parseAsync(process.argv).catch((err: unknown) => {\n console.error(err);\n process.exit(1);\n});\n","import { existsSync, readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nimport chalk from 'chalk';\n\nimport {\n loadTemplateManifest,\n readTemplateSource,\n renderTokens,\n type TemplateEntry,\n} from '../lib/templates.js';\nimport { isRequired, loadManifest, tokenContext } from '../manifest.js';\n\ntype Severity = 'ok' | 'info' | 'warning' | 'error';\n\ninterface DriftReport {\n message: string;\n severity: Severity;\n target: string;\n}\n\nexport async function runDoctor(): Promise<void> {\n const cwd = process.cwd();\n console.log(chalk.bold.cyan('\\nprecisa doctor'));\n\n let manifest;\n try {\n manifest = loadManifest(cwd);\n } catch (err) {\n console.error(chalk.red(`\\n${(err as Error).message}`));\n process.exit(1);\n }\n\n const entries = loadTemplateManifest();\n const context = tokenContext(manifest);\n\n const reports: DriftReport[] = [];\n\n for (const entry of entries) {\n const required = isRequired(entry.required_when, manifest);\n const targetPath = resolve(cwd, entry.target);\n const exists = existsSync(targetPath);\n\n if (!required && !exists) continue;\n if (!required && exists) {\n reports.push({\n message: `Present but not required by the manifest profile (ok)`,\n severity: 'info',\n target: entry.target,\n });\n continue;\n }\n if (!exists) {\n reports.push({\n message: 'Missing',\n severity: 'error',\n target: entry.target,\n });\n continue;\n }\n\n // Exists + required — compare to rendered template\n const source = readTemplateSource(entry);\n const rendered = renderTokens(source, context);\n const current = readFileSync(targetPath, 'utf-8');\n reports.push(compareContent(entry, current, rendered));\n }\n\n console.log('');\n let errors = 0;\n let warnings = 0;\n let infos = 0;\n let oks = 0;\n\n for (const r of reports) {\n const icon = iconFor(r.severity);\n const line = `${icon} ${r.target}${r.message ? chalk.dim(` — ${r.message}`) : ''}`;\n console.log(line);\n if (r.severity === 'error') errors += 1;\n else if (r.severity === 'warning') warnings += 1;\n else if (r.severity === 'info') infos += 1;\n else oks += 1;\n }\n\n console.log('');\n console.log(chalk.dim(`${oks} ok, ${warnings} warning, ${errors} error, ${infos} info`));\n\n if (errors > 0) process.exit(1);\n}\n\nfunction compareContent(entry: TemplateEntry, current: string, rendered: string): DriftReport {\n if (current === rendered) {\n return { message: '', severity: 'ok', target: entry.target };\n }\n\n // Non-overwrite strategies don't re-render on sync — treat drift as\n // informational, not a warning. Makes the doctor output scannable:\n // warnings are the files sync WOULD change; infos are files where\n // drift is intentional (customized scaffold, preserved docs).\n if (entry.merge_strategy === 'preserve') {\n return {\n message: 'Differs from template (preserve strategy — suggestion only)',\n severity: 'info',\n target: entry.target,\n };\n }\n if (entry.merge_strategy === 'skip_if_exists') {\n return {\n message: 'Differs from template (scaffold-only; sync will not overwrite)',\n severity: 'info',\n target: entry.target,\n };\n }\n\n return {\n message: 'Differs from template (run `precisa sync` to update)',\n severity: 'warning',\n target: entry.target,\n };\n}\n\nfunction iconFor(severity: Severity): string {\n switch (severity) {\n case 'ok':\n return chalk.green('✓');\n case 'info':\n return chalk.blue('i');\n case 'warning':\n return chalk.yellow('!');\n case 'error':\n return chalk.red('✗');\n }\n}\n","import { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nimport { parse as parseYaml } from 'yaml';\n\nimport type { RequiredWhen } from '../manifest.js';\nimport { resolveTemplatesDir } from './paths.js';\n\nexport type MergeStrategy = 'overwrite' | 'merge_json' | 'preserve' | 'skip_if_exists';\n\nexport interface TemplateEntry {\n /** Whether to mark the rendered file executable (chmod +x). */\n executable?: boolean;\n /** How to merge when the target already exists. */\n merge_strategy: MergeStrategy;\n /** Gate for inclusion. */\n required_when: RequiredWhen;\n /** Path relative to templates/. */\n source: string;\n /** Path in the target repo (relative to the repo root). */\n target: string;\n}\n\ninterface TemplateManifestFile {\n templates: TemplateEntry[];\n}\n\n/**\n * Load the `templates.manifest.yml` from the bundled templates directory.\n * Throws if the file is missing or the shape is wrong.\n */\nexport function loadTemplateManifest(): TemplateEntry[] {\n const dir = resolveTemplatesDir();\n const manifestPath = resolve(dir, 'templates.manifest.yml');\n const raw = readFileSync(manifestPath, 'utf-8');\n const parsed = parseYaml(raw) as TemplateManifestFile | undefined;\n if (!parsed || !Array.isArray(parsed.templates)) {\n throw new Error(`${manifestPath}: expected { templates: [...] } at root`);\n }\n for (const [i, t] of parsed.templates.entries()) {\n if (!t.source || !t.target) {\n throw new Error(`${manifestPath}: entry ${i} is missing source or target`);\n }\n }\n return parsed.templates;\n}\n\nexport function readTemplateSource(entry: TemplateEntry): string {\n const dir = resolveTemplatesDir();\n const path = resolve(dir, entry.source);\n return readFileSync(path, 'utf-8');\n}\n\n/**\n * Substitute `{{TOKEN}}` placeholders with values from `context`. Unknown\n * tokens are left untouched (keeps the double braces visible so bad keys\n * are easy to spot in rendered output).\n *\n * Also processes conditional blocks:\n *\n * {{#if HAS_SITE}}\n * ...lines rendered only when HAS_SITE is truthy...\n * {{/if}}\n *\n * Markers can appear inside a host-language comment so the template stays\n * parseable by syntax-aware tools (prettier on YAML, for example):\n *\n * # {{#if HAS_SITE}}\n * ...\n * # {{/if}}\n *\n * A token is \"truthy\" when its string value is non-empty and not `\"false\"`.\n * Blocks may nest; they are expanded before token substitution so a block's\n * body can itself reference tokens.\n */\nexport function renderTokens(source: string, context: Record<string, string>): string {\n return renderTokenSubstitutions(renderConditionalBlocks(source, context), context);\n}\n\nfunction renderTokenSubstitutions(source: string, context: Record<string, string>): string {\n return source.replace(/\\{\\{([A-Z_]+)\\}\\}/g, (match, token: string) => {\n return Object.prototype.hasOwnProperty.call(context, token) ? context[token]! : match;\n });\n}\n\nfunction renderConditionalBlocks(source: string, context: Record<string, string>): string {\n // Match an entire line containing `{{#if TOKEN}}` (possibly wrapped in a\n // host-language comment like `# {{#if TOKEN}}` or `// {{#if TOKEN}}`),\n // up through the matching `{{/if}}` line. The whole marker line is\n // consumed so commented-out markers don't leak into rendered output.\n const pattern =\n /^[ \\t]*[^\\S\\n]*[^\\n]*\\{\\{#if ([A-Z_]+)\\}\\}[^\\n]*\\n([\\s\\S]*?)^[ \\t]*[^\\n]*\\{\\{\\/if\\}\\}[^\\n]*\\n?/gm;\n let prev: string;\n let out = source;\n // Re-run to handle nested blocks. Simple fixed-point loop keeps the\n // replacement rules uniform.\n do {\n prev = out;\n out = out.replace(pattern, (_match, token: string, body: string) => {\n const value = context[token];\n const truthy = value !== undefined && value !== '' && value !== 'false';\n return truthy ? body : '';\n });\n } while (out !== prev);\n return out;\n}\n","import { existsSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/**\n * Locate the bundled `templates/` directory.\n *\n * When published to npm, the templates live at `dist/templates/` inside\n * the CLI package (copied by `scripts/copy-templates.mjs` during build).\n *\n * When running from the monorepo (e.g. `pnpm --filter @precisa-saude/cli dev`),\n * the templates live at the repo root — fall back to walking up from the\n * package directory.\n */\nexport function resolveTemplatesDir(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n\n // Published case: cli package's dist/templates\n const bundled = resolve(here, 'templates');\n if (existsSync(bundled)) return bundled;\n\n // Dev case: walk up from packages/cli/{src|dist} to the monorepo root\n const repoRoot = resolve(here, '..', '..', '..', '..');\n const repoTemplates = resolve(repoRoot, 'templates');\n if (existsSync(repoTemplates)) return repoTemplates;\n\n // Sibling-in-package case (tsup output): packages/cli/dist -> ../../templates\n const packageParent = resolve(here, '..', '..', 'templates');\n if (existsSync(packageParent)) return packageParent;\n\n throw new Error(\n `Could not locate templates/ directory. Searched:\\n ${bundled}\\n ${repoTemplates}\\n ${packageParent}`,\n );\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\n/**\n * `.precisa.json` manifest — sits at the root of every consumer repo and\n * declares the repo's profile so `precisa sync` and `precisa doctor` know\n * which templates to render and which rules to enforce.\n */\nexport interface PrecisaManifest {\n /** Commitlint scope enum for this repo. */\n commitScopes: string[];\n\n /** Contact emails used in governance doc templates. */\n contactEmails: {\n security: string;\n conduct: string;\n };\n\n /** Does this repo have publishable packages/*? */\n hasPackages: boolean;\n\n /** Does this repo ship a website? Controls preview-deploy workflows. */\n hasSite: boolean;\n\n /** Repository name (typically matches the GitHub repo name). */\n name: string;\n\n /** Pinned runtime versions. Default: node=22, pnpm=9.15.9. */\n nodeVersion?: string;\n\n /** GitHub organization or user that owns the repo (e.g. `Precisa-Saude`). */\n owner: string;\n\n pnpmVersion?: string;\n\n /** Publishes any workspace package to npm? */\n publishesToNpm: boolean;\n\n /**\n * Workspace package directories (relative to repo root) that the\n * `publish` job in `ci.yml` should pass to `_publish.yml`. Only read\n * when `publishesToNpm: true`. Example: `[\"packages/core\", \"packages/cli\"]`.\n */\n publishPackages?: string[];\n\n /** Schema version of this manifest file. Bump when the schema changes. */\n schemaVersion: 1;\n\n /**\n * pnpm filter selector for the site package, passed to the deploy\n * workflow. Only read when `hasSite: true`. Example: `@my-repo/site`.\n */\n siteFilter?: string;\n\n /**\n * Cloudflare Pages project name for the deploy-site workflow. Only\n * read when `hasSite: true`.\n */\n siteProjectName?: string;\n\n /** Public-OSS or private-internal. Controls which templates are rendered. */\n visibility: 'oss' | 'private';\n}\n\nexport const MANIFEST_FILENAME = '.precisa.json';\n\nexport const DEFAULT_MANIFEST_FIELDS = {\n hasPackages: true,\n hasSite: false,\n nodeVersion: '22',\n pnpmVersion: '9.15.9',\n publishesToNpm: true,\n schemaVersion: 1 as const,\n visibility: 'oss' as const,\n};\n\n/** Template gate values — `required_when` in templates.manifest.yml. */\nexport type RequiredWhen =\n | 'always'\n | 'never'\n | 'oss'\n | 'private'\n | 'has_site'\n | 'has_packages'\n | 'publishes_to_npm';\n\n/** Returns true when a template's `required_when` gate applies to this manifest. */\nexport function isRequired(when: RequiredWhen, manifest: PrecisaManifest): boolean {\n switch (when) {\n case 'always':\n return true;\n case 'never':\n return false;\n case 'oss':\n return manifest.visibility === 'oss';\n case 'private':\n return manifest.visibility === 'private';\n case 'has_site':\n return manifest.hasSite;\n case 'has_packages':\n return manifest.hasPackages;\n case 'publishes_to_npm':\n return manifest.publishesToNpm;\n default:\n return true;\n }\n}\n\n/**\n * Build the token substitution map from a manifest. Keys are `{{TOKEN}}`\n * (without braces); values are always strings.\n */\nexport function tokenContext(manifest: PrecisaManifest): Record<string, string> {\n return {\n COMMIT_SCOPES: manifest.commitScopes.join(','),\n // For human-readable docs (AGENTS.md, README) — backticked list.\n COMMIT_SCOPES_HUMAN: manifest.commitScopes.map((s) => `\\`${s}\\``).join(', '),\n // For `.commitlintrc.cjs` — scope array spelled as JS string literals,\n // ready to drop inside `[ ... ]`.\n COMMIT_SCOPES_JSON: manifest.commitScopes.map((s) => `'${s}'`).join(', '),\n CONDUCT_EMAIL: manifest.contactEmails.conduct,\n HAS_PACKAGES: String(manifest.hasPackages),\n HAS_SITE: String(manifest.hasSite),\n NODE_VERSION: manifest.nodeVersion ?? '22',\n OWNER_ORG: manifest.owner,\n PNPM_VERSION: manifest.pnpmVersion ?? '9.15.9',\n // YAML block-scalar body for the `packages: |` input of `_publish.yml`.\n // The template provides the first entry's indent; subsequent entries\n // get 8 spaces explicitly to match. Empty when no packages declared.\n PUBLISH_PACKAGES_YAML: (manifest.publishPackages ?? []).join('\\n '),\n PUBLISHES_TO_NPM: String(manifest.publishesToNpm),\n REPO_NAME: manifest.name,\n REPO_SLUG: `${manifest.owner}/${manifest.name}`,\n SECURITY_EMAIL: manifest.contactEmails.security,\n SITE_FILTER: manifest.siteFilter ?? '',\n SITE_PROJECT_NAME: manifest.siteProjectName ?? '',\n VISIBILITY: manifest.visibility,\n };\n}\n\nexport interface ManifestValidationError {\n message: string;\n path: string;\n}\n\nexport function validateManifest(raw: unknown): ManifestValidationError[] {\n const errors: ManifestValidationError[] = [];\n const m = raw as Partial<PrecisaManifest> | undefined;\n if (!m || typeof m !== 'object') {\n return [{ message: 'manifest must be a JSON object', path: '$' }];\n }\n if (m.schemaVersion !== 1) {\n errors.push({ message: 'must be 1', path: 'schemaVersion' });\n }\n if (typeof m.name !== 'string' || !m.name) {\n errors.push({ message: 'must be a non-empty string', path: 'name' });\n }\n if (typeof m.owner !== 'string' || !m.owner) {\n errors.push({ message: 'must be a non-empty string', path: 'owner' });\n }\n if (m.visibility !== 'oss' && m.visibility !== 'private') {\n errors.push({ message: \"must be 'oss' or 'private'\", path: 'visibility' });\n }\n for (const key of ['hasSite', 'hasPackages', 'publishesToNpm'] as const) {\n if (typeof m[key] !== 'boolean') {\n errors.push({ message: 'must be a boolean', path: key });\n }\n }\n if (!Array.isArray(m.commitScopes)) {\n errors.push({ message: 'must be an array of strings', path: 'commitScopes' });\n }\n if (m.publishPackages !== undefined) {\n if (!Array.isArray(m.publishPackages)) {\n errors.push({ message: 'must be an array of strings', path: 'publishPackages' });\n } else if (m.publishPackages.some((p) => typeof p !== 'string' || !p)) {\n errors.push({ message: 'entries must be non-empty strings', path: 'publishPackages' });\n }\n }\n if (m.publishesToNpm) {\n if (!Array.isArray(m.publishPackages) || m.publishPackages.length === 0) {\n errors.push({\n message: 'must have at least one entry when publishesToNpm is true',\n path: 'publishPackages',\n });\n }\n }\n if (m.hasSite === true) {\n for (const key of ['siteProjectName', 'siteFilter'] as const) {\n if (typeof m[key] !== 'string' || !m[key]) {\n errors.push({ message: 'required and non-empty when hasSite is true', path: key });\n }\n }\n }\n if (m.siteProjectName !== undefined && typeof m.siteProjectName !== 'string') {\n errors.push({ message: 'must be a string', path: 'siteProjectName' });\n }\n if (m.siteFilter !== undefined && typeof m.siteFilter !== 'string') {\n errors.push({ message: 'must be a string', path: 'siteFilter' });\n }\n if (!m.contactEmails || typeof m.contactEmails !== 'object') {\n errors.push({ message: 'must be an object', path: 'contactEmails' });\n } else {\n for (const key of ['security', 'conduct'] as const) {\n if (typeof m.contactEmails[key] !== 'string' || !m.contactEmails[key]) {\n errors.push({\n message: 'must be a non-empty string',\n path: `contactEmails.${key}`,\n });\n }\n }\n }\n return errors;\n}\n\nexport function loadManifest(cwd: string): PrecisaManifest {\n const path = resolve(cwd, MANIFEST_FILENAME);\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(path, 'utf-8'));\n } catch (err) {\n throw new Error(`Failed to read ${MANIFEST_FILENAME} at ${path}: ${(err as Error).message}`);\n }\n const errors = validateManifest(raw);\n if (errors.length > 0) {\n const detail = errors.map((e) => ` - ${e.path}: ${e.message}`).join('\\n');\n throw new Error(`Invalid ${MANIFEST_FILENAME}:\\n${detail}`);\n }\n return raw as PrecisaManifest;\n}\n\nexport function writeManifest(cwd: string, manifest: PrecisaManifest): void {\n const path = resolve(cwd, MANIFEST_FILENAME);\n writeFileSync(path, `${JSON.stringify(manifest, null, 2)}\\n`);\n}\n","import { execSync } from 'node:child_process';\nimport { existsSync, mkdirSync, readdirSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport prompts from 'prompts';\n\nimport { applyTemplate } from '../lib/merge.js';\nimport { loadTemplateManifest, readTemplateSource, renderTokens } from '../lib/templates.js';\nimport {\n DEFAULT_MANIFEST_FIELDS,\n isRequired,\n type PrecisaManifest,\n tokenContext,\n writeManifest,\n} from '../manifest.js';\n\nexport interface NewOptions {\n conductEmail?: string;\n dryRun: boolean;\n /** Skip interactive prompts; require --owner/--scopes/--*-email flags. */\n nonInteractive?: boolean;\n owner?: string;\n profile: string;\n /** Comma-separated list, e.g. \"core,docs,ci,deps\". */\n scopes?: string;\n securityEmail?: string;\n}\n\nconst PROFILES = {\n 'oss-library': {\n hasPackages: true,\n hasSite: false,\n publishesToNpm: true,\n visibility: 'oss',\n },\n 'oss-site': {\n hasPackages: false,\n hasSite: true,\n publishesToNpm: false,\n visibility: 'oss',\n },\n 'private-app': {\n hasPackages: true,\n hasSite: true,\n publishesToNpm: false,\n visibility: 'private',\n },\n} as const satisfies Record<\n string,\n Pick<PrecisaManifest, 'visibility' | 'hasSite' | 'hasPackages' | 'publishesToNpm'>\n>;\n\nexport async function runNew(repoName: string, opts: NewOptions): Promise<void> {\n const targetDir = resolve(process.cwd(), repoName);\n\n if (existsSync(targetDir) && readdirSync(targetDir).length > 0) {\n console.error(chalk.red(`\\nError: ${targetDir} already exists and is not empty.`));\n process.exit(1);\n }\n\n const profile = PROFILES[opts.profile as keyof typeof PROFILES];\n if (!profile) {\n console.error(\n chalk.red(`\\nError: unknown profile '${opts.profile}'. Choose one of:`),\n Object.keys(PROFILES).join(', '),\n );\n process.exit(1);\n }\n\n console.log(chalk.bold.cyan(`\\nprecisa new ${repoName}`));\n console.log(chalk.dim(`profile: ${opts.profile}${opts.dryRun ? ' (dry-run)' : ''}`));\n console.log(chalk.dim(`target: ${targetDir}\\n`));\n\n const answers = opts.nonInteractive\n ? {\n commitScopes: (opts.scopes ?? 'docs,ci,deps')\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean),\n conductEmail: opts.conductEmail ?? 'conduct@precisa-saude.com.br',\n owner: opts.owner ?? 'Precisa-Saude',\n securityEmail: opts.securityEmail ?? 'security@precisa-saude.com.br',\n }\n : await prompts(\n [\n {\n initial: opts.owner ?? 'Precisa-Saude',\n message: 'GitHub owner (org or user):',\n name: 'owner',\n type: 'text',\n },\n {\n initial: opts.securityEmail ?? 'security@precisa-saude.com.br',\n message: 'Security contact email:',\n name: 'securityEmail',\n type: 'text',\n },\n {\n initial: opts.conductEmail ?? 'conduct@precisa-saude.com.br',\n message: 'Code-of-conduct contact email:',\n name: 'conductEmail',\n type: 'text',\n },\n {\n initial: opts.scopes ?? 'docs,ci,deps',\n message: 'Commit scopes (comma-separated):',\n name: 'commitScopes',\n separator: ',',\n type: 'list',\n },\n ],\n { onCancel: () => process.exit(1) },\n );\n\n const manifest: PrecisaManifest = {\n ...DEFAULT_MANIFEST_FIELDS,\n ...profile,\n commitScopes: answers.commitScopes,\n contactEmails: {\n conduct: answers.conductEmail,\n security: answers.securityEmail,\n },\n name: repoName,\n owner: answers.owner,\n };\n\n const spinner = ora('Rendering templates').start();\n try {\n if (!opts.dryRun) mkdirSync(targetDir, { recursive: true });\n\n const entries = loadTemplateManifest().filter((e) => isRequired(e.required_when, manifest));\n const context = tokenContext(manifest);\n\n let created = 0;\n let skipped = 0;\n\n for (const entry of entries) {\n const source = readTemplateSource(entry);\n const rendered = renderTokens(source, context);\n const outcome = applyTemplate({\n cwd: targetDir,\n dryRun: opts.dryRun,\n entry,\n rendered,\n });\n if (outcome.kind === 'create') created += 1;\n else if (outcome.kind === 'skip-exists') skipped += 1;\n else if (outcome.kind === 'error') {\n spinner.fail(`Failed on ${entry.target}`);\n console.error(chalk.red(outcome.message));\n process.exit(1);\n }\n }\n\n spinner.succeed(\n opts.dryRun\n ? `Would render ${created} file${created === 1 ? '' : 's'} (${skipped} skipped)`\n : `Rendered ${created} file${created === 1 ? '' : 's'} (${skipped} skipped)`,\n );\n\n if (opts.dryRun) return;\n\n writeManifest(targetDir, manifest);\n console.log(chalk.dim(` wrote .precisa.json`));\n\n const gitStep = ora('git init + pnpm install').start();\n try {\n execSync('git init --initial-branch=main', { cwd: targetDir, stdio: 'pipe' });\n execSync('pnpm install', { cwd: targetDir, stdio: 'pipe' });\n gitStep.succeed('git init + pnpm install complete');\n } catch (err) {\n gitStep.warn(\n `git/pnpm setup skipped: ${(err as Error).message}. Run manually in ${targetDir}.`,\n );\n }\n\n console.log(chalk.bold.green(`\\n✓ ${repoName} scaffolded at ${targetDir}`));\n console.log(chalk.dim('\\nNext:'));\n console.log(chalk.dim(` cd ${repoName}`));\n console.log(chalk.dim(` # start adding your code`));\n } catch (err) {\n spinner.fail((err as Error).message);\n process.exit(1);\n }\n}\n","import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\n\nimport type { MergeStrategy, TemplateEntry } from './templates.js';\n\nexport type ApplyOutcome =\n | { kind: 'create'; target: string; rendered: string }\n | { kind: 'update'; target: string; previous: string; rendered: string }\n | { kind: 'skip-identical'; target: string }\n | { kind: 'preserve'; target: string; current: string; rendered: string }\n | { kind: 'skip-exists'; target: string }\n | { kind: 'merge-json'; target: string; previous: string; rendered: string }\n | { kind: 'error'; target: string; message: string };\n\nexport interface ApplyOptions {\n /** Repo root to apply into. */\n cwd: string;\n /** When true, compute the outcome but do not write to disk. */\n dryRun: boolean;\n /** Template entry being applied. */\n entry: TemplateEntry;\n /** Rendered template content (post token substitution). */\n rendered: string;\n}\n\n/**\n * Apply a single template file to the target repo. Returns the outcome\n * so callers can print a per-file status row and, on dry-run, a diff.\n */\nexport function applyTemplate({ cwd, dryRun, entry, rendered }: ApplyOptions): ApplyOutcome {\n const targetPath = resolve(cwd, entry.target);\n const exists = existsSync(targetPath);\n\n if (!exists) {\n if (!dryRun) writeFile(targetPath, rendered, entry.executable === true);\n return { kind: 'create', rendered, target: entry.target };\n }\n\n const current = readFileSync(targetPath, 'utf-8');\n\n switch (entry.merge_strategy as MergeStrategy) {\n case 'overwrite': {\n if (current === rendered) {\n return { kind: 'skip-identical', target: entry.target };\n }\n if (!dryRun) writeFile(targetPath, rendered, entry.executable === true);\n return { kind: 'update', previous: current, rendered, target: entry.target };\n }\n case 'skip_if_exists': {\n return { kind: 'skip-exists', target: entry.target };\n }\n case 'preserve': {\n return { current, kind: 'preserve', rendered, target: entry.target };\n }\n case 'merge_json': {\n let merged: string;\n try {\n merged = mergeJson(current, rendered);\n } catch (err) {\n return {\n kind: 'error',\n message: `JSON merge failed: ${(err as Error).message}`,\n target: entry.target,\n };\n }\n if (current === merged) {\n return { kind: 'skip-identical', target: entry.target };\n }\n if (!dryRun) writeFile(targetPath, merged, entry.executable === true);\n return { kind: 'merge-json', previous: current, rendered: merged, target: entry.target };\n }\n default: {\n return {\n kind: 'error',\n message: `Unknown merge_strategy '${entry.merge_strategy}'`,\n target: entry.target,\n };\n }\n }\n}\n\nfunction writeFile(path: string, contents: string, executable: boolean): void {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, contents);\n if (executable) chmodSync(path, 0o755);\n}\n\n/**\n * Shallow 3-way-ish JSON merge — the current file wins on conflicts so\n * repo-local customizations aren't clobbered. Objects are merged\n * key-by-key; arrays and scalars are replaced entirely by the current\n * value when present (falls back to the template value).\n *\n * If parsing fails, throws so the caller can report the error.\n */\nexport function mergeJson(currentRaw: string, templateRaw: string): string {\n const current = JSON.parse(currentRaw) as unknown;\n const template = JSON.parse(templateRaw) as unknown;\n const merged = mergeValue(template, current);\n return `${JSON.stringify(merged, null, 2)}\\n`;\n}\n\nfunction mergeValue(template: unknown, current: unknown): unknown {\n if (current === undefined) return template;\n if (\n typeof template !== 'object' ||\n template === null ||\n Array.isArray(template) ||\n typeof current !== 'object' ||\n current === null ||\n Array.isArray(current)\n ) {\n // Scalars / arrays: current value wins (never clobber repo-local values).\n return current;\n }\n const out: Record<string, unknown> = {};\n const keys = new Set([\n ...Object.keys(template as Record<string, unknown>),\n ...Object.keys(current as Record<string, unknown>),\n ]);\n for (const k of keys) {\n out[k] = mergeValue(\n (template as Record<string, unknown>)[k],\n (current as Record<string, unknown>)[k],\n );\n }\n return out;\n}\n","import chalk from 'chalk';\n\nimport { colorDiff } from '../lib/diff.js';\nimport { type ApplyOutcome, applyTemplate } from '../lib/merge.js';\nimport { loadTemplateManifest, readTemplateSource, renderTokens } from '../lib/templates.js';\nimport { isRequired, loadManifest, tokenContext } from '../manifest.js';\n\nexport interface SyncOptions {\n dryRun: boolean;\n}\n\nexport async function runSync(opts: SyncOptions): Promise<void> {\n const cwd = process.cwd();\n console.log(chalk.bold.cyan(`\\nprecisa sync${opts.dryRun ? ' --dry-run' : ''}`));\n\n let manifest;\n try {\n manifest = loadManifest(cwd);\n } catch (err) {\n console.error(chalk.red(`\\n${(err as Error).message}`));\n console.error(\n chalk.dim('\\n Run `precisa new <repo>` in an empty directory to scaffold a new repo,'),\n );\n console.error(chalk.dim(' or create a `.precisa.json` manifest manually.'));\n process.exit(1);\n }\n\n const entries = loadTemplateManifest().filter((e) => isRequired(e.required_when, manifest));\n const context = tokenContext(manifest);\n\n const outcomes: ApplyOutcome[] = [];\n for (const entry of entries) {\n const source = readTemplateSource(entry);\n const rendered = renderTokens(source, context);\n outcomes.push(\n applyTemplate({\n cwd,\n dryRun: opts.dryRun,\n entry,\n rendered,\n }),\n );\n }\n\n console.log('');\n for (const o of outcomes) {\n printOutcome(o, opts.dryRun);\n }\n\n const summary = summarize(outcomes);\n console.log('');\n console.log(\n chalk.dim(\n `${summary.create} create, ${summary.update} update, ${summary.mergeJson} merge-json, ${summary.preserve} preserve, ${summary.skip} skip, ${summary.error} error`,\n ),\n );\n\n if (summary.error > 0) process.exit(1);\n}\n\ninterface Summary {\n create: number;\n error: number;\n mergeJson: number;\n preserve: number;\n skip: number;\n update: number;\n}\n\nfunction summarize(outcomes: ApplyOutcome[]): Summary {\n const s: Summary = { create: 0, error: 0, mergeJson: 0, preserve: 0, skip: 0, update: 0 };\n for (const o of outcomes) {\n switch (o.kind) {\n case 'create':\n s.create += 1;\n break;\n case 'update':\n s.update += 1;\n break;\n case 'merge-json':\n s.mergeJson += 1;\n break;\n case 'preserve':\n s.preserve += 1;\n break;\n case 'skip-identical':\n case 'skip-exists':\n s.skip += 1;\n break;\n case 'error':\n s.error += 1;\n break;\n }\n }\n return s;\n}\n\nfunction printOutcome(o: ApplyOutcome, dryRun: boolean): void {\n const prefix = dryRun ? '(dry-run) ' : '';\n switch (o.kind) {\n case 'create':\n console.log(`${chalk.green('+')} ${prefix}create ${o.target}`);\n return;\n case 'update':\n console.log(`${chalk.yellow('~')} ${prefix}update ${o.target}`);\n if (dryRun) console.log(indent(colorDiff(o.target, o.previous, o.rendered)));\n return;\n case 'merge-json':\n console.log(`${chalk.yellow('~')} ${prefix}merge ${o.target}`);\n if (dryRun) console.log(indent(colorDiff(o.target, o.previous, o.rendered)));\n return;\n case 'preserve':\n console.log(\n `${chalk.blue('i')} ${prefix}preserve ${o.target} (template differs; not written)`,\n );\n if (dryRun && o.current !== o.rendered) {\n console.log(indent(colorDiff(o.target, o.current, o.rendered)));\n }\n return;\n case 'skip-identical':\n console.log(`${chalk.dim('=')} ${prefix}unchanged ${o.target}`);\n return;\n case 'skip-exists':\n console.log(`${chalk.dim('s')} ${prefix}skip ${o.target} (already exists)`);\n return;\n case 'error':\n console.log(`${chalk.red('!')} ${prefix}error ${o.target}: ${o.message}`);\n return;\n }\n}\n\nfunction indent(text: string): string {\n return text\n .split('\\n')\n .map((l) => ` ${l}`)\n .join('\\n');\n}\n","import chalk from 'chalk';\nimport { createPatch } from 'diff';\n\n/**\n * Format a unified diff with ANSI colors for terminal display.\n * Skips the `@@ hunk @@` metadata lines for a cleaner look.\n */\nexport function colorDiff(filename: string, previous: string, next: string): string {\n const patch = createPatch(filename, previous, next, '', '');\n const lines = patch.split('\\n');\n const out: string[] = [];\n for (const line of lines) {\n if (line.startsWith('---') || line.startsWith('+++')) continue;\n if (line.startsWith('@@')) {\n out.push(chalk.cyan(line));\n continue;\n }\n if (line.startsWith('+')) {\n out.push(chalk.green(line));\n continue;\n }\n if (line.startsWith('-')) {\n out.push(chalk.red(line));\n continue;\n }\n out.push(line);\n }\n return out.join('\\n');\n}\n"],"mappings":"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","names":["existsSync","readFileSync","resolve","resolve","resolve","readFileSync","resolve","resolve","existsSync","readFileSync","existsSync","mkdirSync","resolve","chalk","existsSync","readFileSync","writeFileSync","dirname","resolve","resolve","existsSync","chalk","mkdirSync","chalk","chalk","chalk"]}
1
+ {"version":3,"sources":["../src/bin.ts","../src/commands/doctor.ts","../src/lib/templates.ts","../src/lib/paths.ts","../src/manifest.ts","../src/commands/new.ts","../src/lib/merge.ts","../src/commands/sync.ts","../src/lib/diff.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\n\nimport { runDoctor } from './commands/doctor.js';\nimport { runNew } from './commands/new.js';\nimport { runSync } from './commands/sync.js';\n\nconst program = new Command();\n\nprogram\n .name('precisa')\n .description('Bootstrap and sync Precisa Saúde repositories.')\n .version('0.0.0');\n\nprogram\n .command('new <repo-name>')\n .description('Scaffold a new repository from the shared templates.')\n .option('--profile <profile>', 'preset: oss-library | oss-site | private-app', 'oss-library')\n .option('--dry-run', 'print what would be written without touching disk', false)\n .option('--non-interactive', 'skip prompts; use --owner/--scopes/etc. flags instead', false)\n .option('--owner <org>', 'GitHub owner (org or user)', 'Precisa-Saude')\n .option(\n '--scopes <csv>',\n 'Comma-separated commit scopes (e.g. \"core,docs,ci,deps\")',\n 'docs,ci,deps',\n )\n .option('--security-email <email>', 'Security contact email', 'security@precisa-saude.com.br')\n .option(\n '--conduct-email <email>',\n 'Code-of-conduct contact email',\n 'conduct@precisa-saude.com.br',\n )\n .action(\n async (\n repoName: string,\n opts: {\n profile: string;\n dryRun: boolean;\n nonInteractive: boolean;\n owner: string;\n scopes: string;\n securityEmail: string;\n conductEmail: string;\n },\n ) => {\n await runNew(repoName, opts);\n },\n );\n\nprogram\n .command('sync')\n .description(\"Re-render templates against this repo's .precisa.json manifest.\")\n .option('--dry-run', 'print a diff without writing', false)\n .action(async (opts: { dryRun: boolean }) => {\n await runSync(opts);\n });\n\nprogram\n .command('doctor')\n .description('Audit this repo against the templates and report drift.')\n .action(async () => {\n await runDoctor();\n });\n\nprogram.parseAsync(process.argv).catch((err: unknown) => {\n console.error(err);\n process.exit(1);\n});\n","import { existsSync, readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nimport chalk from 'chalk';\n\nimport {\n loadTemplateManifest,\n readTemplateSource,\n renderTokens,\n type TemplateEntry,\n} from '../lib/templates.js';\nimport { isRequired, loadManifest, tokenContext } from '../manifest.js';\n\ntype Severity = 'ok' | 'info' | 'warning' | 'error';\n\ninterface DriftReport {\n message: string;\n severity: Severity;\n target: string;\n}\n\nexport async function runDoctor(): Promise<void> {\n const cwd = process.cwd();\n console.log(chalk.bold.cyan('\\nprecisa doctor'));\n\n let manifest;\n try {\n manifest = loadManifest(cwd);\n } catch (err) {\n console.error(chalk.red(`\\n${(err as Error).message}`));\n process.exit(1);\n }\n\n const entries = loadTemplateManifest();\n const context = tokenContext(manifest);\n\n const reports: DriftReport[] = [];\n\n for (const entry of entries) {\n const required = isRequired(entry.required_when, manifest);\n const targetPath = resolve(cwd, entry.target);\n const exists = existsSync(targetPath);\n\n if (!required && !exists) continue;\n if (!required && exists) {\n reports.push({\n message: `Present but not required by the manifest profile (ok)`,\n severity: 'info',\n target: entry.target,\n });\n continue;\n }\n if (!exists) {\n reports.push({\n message: 'Missing',\n severity: 'error',\n target: entry.target,\n });\n continue;\n }\n\n // Exists + required — compare to rendered template\n const source = readTemplateSource(entry);\n const rendered = renderTokens(source, context);\n const current = readFileSync(targetPath, 'utf-8');\n reports.push(compareContent(entry, current, rendered));\n }\n\n console.log('');\n let errors = 0;\n let warnings = 0;\n let infos = 0;\n let oks = 0;\n\n for (const r of reports) {\n const icon = iconFor(r.severity);\n const line = `${icon} ${r.target}${r.message ? chalk.dim(` — ${r.message}`) : ''}`;\n console.log(line);\n if (r.severity === 'error') errors += 1;\n else if (r.severity === 'warning') warnings += 1;\n else if (r.severity === 'info') infos += 1;\n else oks += 1;\n }\n\n console.log('');\n console.log(chalk.dim(`${oks} ok, ${warnings} warning, ${errors} error, ${infos} info`));\n\n if (errors > 0) process.exit(1);\n}\n\nfunction compareContent(entry: TemplateEntry, current: string, rendered: string): DriftReport {\n if (current === rendered) {\n return { message: '', severity: 'ok', target: entry.target };\n }\n\n // Non-overwrite strategies don't re-render on sync — treat drift as\n // informational, not a warning. Makes the doctor output scannable:\n // warnings are the files sync WOULD change; infos are files where\n // drift is intentional (customized scaffold, preserved docs).\n if (entry.merge_strategy === 'preserve') {\n return {\n message: 'Differs from template (preserve strategy — suggestion only)',\n severity: 'info',\n target: entry.target,\n };\n }\n if (entry.merge_strategy === 'skip_if_exists') {\n return {\n message: 'Differs from template (scaffold-only; sync will not overwrite)',\n severity: 'info',\n target: entry.target,\n };\n }\n\n return {\n message: 'Differs from template (run `precisa sync` to update)',\n severity: 'warning',\n target: entry.target,\n };\n}\n\nfunction iconFor(severity: Severity): string {\n switch (severity) {\n case 'ok':\n return chalk.green('✓');\n case 'info':\n return chalk.blue('i');\n case 'warning':\n return chalk.yellow('!');\n case 'error':\n return chalk.red('✗');\n }\n}\n","import { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nimport { parse as parseYaml } from 'yaml';\n\nimport type { RequiredWhen } from '../manifest.js';\nimport { resolveTemplatesDir } from './paths.js';\n\nexport type MergeStrategy = 'overwrite' | 'merge_json' | 'preserve' | 'skip_if_exists';\n\nexport interface TemplateEntry {\n /** Whether to mark the rendered file executable (chmod +x). */\n executable?: boolean;\n /** How to merge when the target already exists. */\n merge_strategy: MergeStrategy;\n /** Gate for inclusion. */\n required_when: RequiredWhen;\n /** Path relative to templates/. */\n source: string;\n /** Path in the target repo (relative to the repo root). */\n target: string;\n}\n\ninterface TemplateManifestFile {\n templates: TemplateEntry[];\n}\n\n/**\n * Load the `templates.manifest.yml` from the bundled templates directory.\n * Throws if the file is missing or the shape is wrong.\n */\nexport function loadTemplateManifest(): TemplateEntry[] {\n const dir = resolveTemplatesDir();\n const manifestPath = resolve(dir, 'templates.manifest.yml');\n const raw = readFileSync(manifestPath, 'utf-8');\n const parsed = parseYaml(raw) as TemplateManifestFile | undefined;\n if (!parsed || !Array.isArray(parsed.templates)) {\n throw new Error(`${manifestPath}: expected { templates: [...] } at root`);\n }\n for (const [i, t] of parsed.templates.entries()) {\n if (!t.source || !t.target) {\n throw new Error(`${manifestPath}: entry ${i} is missing source or target`);\n }\n }\n return parsed.templates;\n}\n\nexport function readTemplateSource(entry: TemplateEntry): string {\n const dir = resolveTemplatesDir();\n const path = resolve(dir, entry.source);\n return readFileSync(path, 'utf-8');\n}\n\n/**\n * Substitute `{{TOKEN}}` placeholders with values from `context`. Unknown\n * tokens are left untouched (keeps the double braces visible so bad keys\n * are easy to spot in rendered output).\n *\n * Also processes conditional blocks:\n *\n * {{#if HAS_SITE}}\n * ...lines rendered only when HAS_SITE is truthy...\n * {{/if}}\n *\n * Markers can appear inside a host-language comment so the template stays\n * parseable by syntax-aware tools (prettier on YAML, for example):\n *\n * # {{#if HAS_SITE}}\n * ...\n * # {{/if}}\n *\n * A token is \"truthy\" when its string value is non-empty and not `\"false\"`.\n * Blocks may nest; they are expanded before token substitution so a block's\n * body can itself reference tokens.\n */\nexport function renderTokens(source: string, context: Record<string, string>): string {\n return renderTokenSubstitutions(renderConditionalBlocks(source, context), context);\n}\n\nfunction renderTokenSubstitutions(source: string, context: Record<string, string>): string {\n return source.replace(/\\{\\{([A-Z_]+)\\}\\}/g, (match, token: string) => {\n return Object.prototype.hasOwnProperty.call(context, token) ? context[token]! : match;\n });\n}\n\nfunction renderConditionalBlocks(source: string, context: Record<string, string>): string {\n // Match an entire line containing `{{#if TOKEN}}` (possibly wrapped in a\n // host-language comment like `# {{#if TOKEN}}` or `// {{#if TOKEN}}`),\n // up through the matching `{{/if}}` line. The whole marker line is\n // consumed so commented-out markers don't leak into rendered output.\n const pattern =\n /^[ \\t]*[^\\S\\n]*[^\\n]*\\{\\{#if ([A-Z_]+)\\}\\}[^\\n]*\\n([\\s\\S]*?)^[ \\t]*[^\\n]*\\{\\{\\/if\\}\\}[^\\n]*\\n?/gm;\n let prev: string;\n let out = source;\n // Re-run to handle nested blocks. Simple fixed-point loop keeps the\n // replacement rules uniform.\n do {\n prev = out;\n out = out.replace(pattern, (_match, token: string, body: string) => {\n const value = context[token];\n const truthy = value !== undefined && value !== '' && value !== 'false';\n return truthy ? body : '';\n });\n } while (out !== prev);\n return out;\n}\n","import { existsSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/**\n * Locate the bundled `templates/` directory.\n *\n * When published to npm, the templates live at `dist/templates/` inside\n * the CLI package (copied by `scripts/copy-templates.mjs` during build).\n *\n * When running from the monorepo (e.g. `pnpm --filter @precisa-saude/cli dev`),\n * the templates live at the repo root — fall back to walking up from the\n * package directory.\n */\nexport function resolveTemplatesDir(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n\n // Published case: cli package's dist/templates\n const bundled = resolve(here, 'templates');\n if (existsSync(bundled)) return bundled;\n\n // Dev case: walk up from packages/cli/{src|dist} to the monorepo root\n const repoRoot = resolve(here, '..', '..', '..', '..');\n const repoTemplates = resolve(repoRoot, 'templates');\n if (existsSync(repoTemplates)) return repoTemplates;\n\n // Sibling-in-package case (tsup output): packages/cli/dist -> ../../templates\n const packageParent = resolve(here, '..', '..', 'templates');\n if (existsSync(packageParent)) return packageParent;\n\n throw new Error(\n `Could not locate templates/ directory. Searched:\\n ${bundled}\\n ${repoTemplates}\\n ${packageParent}`,\n );\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\n/**\n * `.precisa.json` manifest — sits at the root of every consumer repo and\n * declares the repo's profile so `precisa sync` and `precisa doctor` know\n * which templates to render and which rules to enforce.\n */\nexport interface PrecisaManifest {\n /** Commitlint scope enum for this repo. */\n commitScopes: string[];\n\n /** Contact emails used in governance doc templates. */\n contactEmails: {\n security: string;\n conduct: string;\n };\n\n /** Does this repo have publishable packages/*? */\n hasPackages: boolean;\n\n /** Does this repo ship a website? Controls preview-deploy workflows. */\n hasSite: boolean;\n\n /** Repository name (typically matches the GitHub repo name). */\n name: string;\n\n /** Pinned runtime versions. Default: node=22, pnpm=9.15.9. */\n nodeVersion?: string;\n\n /** GitHub organization or user that owns the repo (e.g. `Precisa-Saude`). */\n owner: string;\n\n pnpmVersion?: string;\n\n /** Publishes any workspace package to npm? */\n publishesToNpm: boolean;\n\n /**\n * Workspace package directories (relative to repo root) that the\n * `publish` job in `ci.yml` should pass to `_publish.yml`. Only read\n * when `publishesToNpm: true`. Example: `[\"packages/core\", \"packages/cli\"]`.\n */\n publishPackages?: string[];\n\n /** Schema version of this manifest file. Bump when the schema changes. */\n schemaVersion: 1;\n\n /**\n * pnpm filter selector for the site package, passed to the deploy\n * workflow. Only read when `hasSite: true`. Example: `@my-repo/site`.\n */\n siteFilter?: string;\n\n /**\n * Cloudflare Pages project name for the deploy-site workflow. Only\n * read when `hasSite: true`.\n */\n siteProjectName?: string;\n\n /**\n * Path prefix (relative to repo root, trailing slash) treated as site\n * source for change detection in `_deploy-site.yml`. Defaults to\n * `site/` — override to `packages/site/` for monorepos where the site\n * lives under `packages/`.\n */\n siteSourcePath?: string;\n\n /** Public-OSS or private-internal. Controls which templates are rendered. */\n visibility: 'oss' | 'private';\n}\n\nexport const MANIFEST_FILENAME = '.precisa.json';\n\nexport const DEFAULT_MANIFEST_FIELDS = {\n hasPackages: true,\n hasSite: false,\n nodeVersion: '22',\n pnpmVersion: '9.15.9',\n publishesToNpm: true,\n schemaVersion: 1 as const,\n visibility: 'oss' as const,\n};\n\n/** Template gate values — `required_when` in templates.manifest.yml. */\nexport type RequiredWhen =\n | 'always'\n | 'never'\n | 'oss'\n | 'private'\n | 'has_site'\n | 'has_packages'\n | 'publishes_to_npm';\n\n/** Returns true when a template's `required_when` gate applies to this manifest. */\nexport function isRequired(when: RequiredWhen, manifest: PrecisaManifest): boolean {\n switch (when) {\n case 'always':\n return true;\n case 'never':\n return false;\n case 'oss':\n return manifest.visibility === 'oss';\n case 'private':\n return manifest.visibility === 'private';\n case 'has_site':\n return manifest.hasSite;\n case 'has_packages':\n return manifest.hasPackages;\n case 'publishes_to_npm':\n return manifest.publishesToNpm;\n default:\n return true;\n }\n}\n\n/**\n * Build the token substitution map from a manifest. Keys are `{{TOKEN}}`\n * (without braces); values are always strings.\n */\nexport function tokenContext(manifest: PrecisaManifest): Record<string, string> {\n return {\n COMMIT_SCOPES: manifest.commitScopes.join(','),\n // For human-readable docs (AGENTS.md, README) — backticked list.\n COMMIT_SCOPES_HUMAN: manifest.commitScopes.map((s) => `\\`${s}\\``).join(', '),\n // For `.commitlintrc.cjs` — scope array spelled as JS string literals,\n // ready to drop inside `[ ... ]`.\n COMMIT_SCOPES_JSON: manifest.commitScopes.map((s) => `'${s}'`).join(', '),\n CONDUCT_EMAIL: manifest.contactEmails.conduct,\n HAS_PACKAGES: String(manifest.hasPackages),\n HAS_SITE: String(manifest.hasSite),\n NODE_VERSION: manifest.nodeVersion ?? '22',\n OWNER_ORG: manifest.owner,\n PNPM_VERSION: manifest.pnpmVersion ?? '9.15.9',\n // YAML block-scalar body for the `packages: |` input of `_publish.yml`.\n // The template provides the first entry's indent; subsequent entries\n // get 8 spaces explicitly to match. Empty when no packages declared.\n PUBLISH_PACKAGES_YAML: (manifest.publishPackages ?? []).join('\\n '),\n PUBLISHES_TO_NPM: String(manifest.publishesToNpm),\n REPO_NAME: manifest.name,\n REPO_SLUG: `${manifest.owner}/${manifest.name}`,\n SECURITY_EMAIL: manifest.contactEmails.security,\n SITE_FILTER: manifest.siteFilter ?? '',\n SITE_PROJECT_NAME: manifest.siteProjectName ?? '',\n SITE_SOURCE_PATH: manifest.siteSourcePath ?? 'site/',\n VISIBILITY: manifest.visibility,\n };\n}\n\nexport interface ManifestValidationError {\n message: string;\n path: string;\n}\n\nexport function validateManifest(raw: unknown): ManifestValidationError[] {\n const errors: ManifestValidationError[] = [];\n const m = raw as Partial<PrecisaManifest> | undefined;\n if (!m || typeof m !== 'object') {\n return [{ message: 'manifest must be a JSON object', path: '$' }];\n }\n if (m.schemaVersion !== 1) {\n errors.push({ message: 'must be 1', path: 'schemaVersion' });\n }\n if (typeof m.name !== 'string' || !m.name) {\n errors.push({ message: 'must be a non-empty string', path: 'name' });\n }\n if (typeof m.owner !== 'string' || !m.owner) {\n errors.push({ message: 'must be a non-empty string', path: 'owner' });\n }\n if (m.visibility !== 'oss' && m.visibility !== 'private') {\n errors.push({ message: \"must be 'oss' or 'private'\", path: 'visibility' });\n }\n for (const key of ['hasSite', 'hasPackages', 'publishesToNpm'] as const) {\n if (typeof m[key] !== 'boolean') {\n errors.push({ message: 'must be a boolean', path: key });\n }\n }\n if (!Array.isArray(m.commitScopes)) {\n errors.push({ message: 'must be an array of strings', path: 'commitScopes' });\n }\n if (m.publishPackages !== undefined) {\n if (!Array.isArray(m.publishPackages)) {\n errors.push({ message: 'must be an array of strings', path: 'publishPackages' });\n } else if (m.publishPackages.some((p) => typeof p !== 'string' || !p)) {\n errors.push({ message: 'entries must be non-empty strings', path: 'publishPackages' });\n }\n }\n if (m.publishesToNpm) {\n if (!Array.isArray(m.publishPackages) || m.publishPackages.length === 0) {\n errors.push({\n message: 'must have at least one entry when publishesToNpm is true',\n path: 'publishPackages',\n });\n }\n }\n if (m.hasSite === true) {\n for (const key of ['siteProjectName', 'siteFilter'] as const) {\n if (typeof m[key] !== 'string' || !m[key]) {\n errors.push({ message: 'required and non-empty when hasSite is true', path: key });\n }\n }\n }\n if (m.siteProjectName !== undefined && typeof m.siteProjectName !== 'string') {\n errors.push({ message: 'must be a string', path: 'siteProjectName' });\n }\n if (m.siteFilter !== undefined && typeof m.siteFilter !== 'string') {\n errors.push({ message: 'must be a string', path: 'siteFilter' });\n }\n if (m.siteSourcePath !== undefined && typeof m.siteSourcePath !== 'string') {\n errors.push({ message: 'must be a string', path: 'siteSourcePath' });\n }\n if (!m.contactEmails || typeof m.contactEmails !== 'object') {\n errors.push({ message: 'must be an object', path: 'contactEmails' });\n } else {\n for (const key of ['security', 'conduct'] as const) {\n if (typeof m.contactEmails[key] !== 'string' || !m.contactEmails[key]) {\n errors.push({\n message: 'must be a non-empty string',\n path: `contactEmails.${key}`,\n });\n }\n }\n }\n return errors;\n}\n\nexport function loadManifest(cwd: string): PrecisaManifest {\n const path = resolve(cwd, MANIFEST_FILENAME);\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(path, 'utf-8'));\n } catch (err) {\n throw new Error(`Failed to read ${MANIFEST_FILENAME} at ${path}: ${(err as Error).message}`);\n }\n const errors = validateManifest(raw);\n if (errors.length > 0) {\n const detail = errors.map((e) => ` - ${e.path}: ${e.message}`).join('\\n');\n throw new Error(`Invalid ${MANIFEST_FILENAME}:\\n${detail}`);\n }\n return raw as PrecisaManifest;\n}\n\nexport function writeManifest(cwd: string, manifest: PrecisaManifest): void {\n const path = resolve(cwd, MANIFEST_FILENAME);\n writeFileSync(path, `${JSON.stringify(manifest, null, 2)}\\n`);\n}\n","import { execSync } from 'node:child_process';\nimport { existsSync, mkdirSync, readdirSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport prompts from 'prompts';\n\nimport { applyTemplate } from '../lib/merge.js';\nimport { loadTemplateManifest, readTemplateSource, renderTokens } from '../lib/templates.js';\nimport {\n DEFAULT_MANIFEST_FIELDS,\n isRequired,\n type PrecisaManifest,\n tokenContext,\n writeManifest,\n} from '../manifest.js';\n\nexport interface NewOptions {\n conductEmail?: string;\n dryRun: boolean;\n /** Skip interactive prompts; require --owner/--scopes/--*-email flags. */\n nonInteractive?: boolean;\n owner?: string;\n profile: string;\n /** Comma-separated list, e.g. \"core,docs,ci,deps\". */\n scopes?: string;\n securityEmail?: string;\n}\n\nconst PROFILES = {\n 'oss-library': {\n hasPackages: true,\n hasSite: false,\n publishesToNpm: true,\n visibility: 'oss',\n },\n 'oss-site': {\n hasPackages: false,\n hasSite: true,\n publishesToNpm: false,\n visibility: 'oss',\n },\n 'private-app': {\n hasPackages: true,\n hasSite: true,\n publishesToNpm: false,\n visibility: 'private',\n },\n} as const satisfies Record<\n string,\n Pick<PrecisaManifest, 'visibility' | 'hasSite' | 'hasPackages' | 'publishesToNpm'>\n>;\n\nexport async function runNew(repoName: string, opts: NewOptions): Promise<void> {\n const targetDir = resolve(process.cwd(), repoName);\n\n if (existsSync(targetDir) && readdirSync(targetDir).length > 0) {\n console.error(chalk.red(`\\nError: ${targetDir} already exists and is not empty.`));\n process.exit(1);\n }\n\n const profile = PROFILES[opts.profile as keyof typeof PROFILES];\n if (!profile) {\n console.error(\n chalk.red(`\\nError: unknown profile '${opts.profile}'. Choose one of:`),\n Object.keys(PROFILES).join(', '),\n );\n process.exit(1);\n }\n\n console.log(chalk.bold.cyan(`\\nprecisa new ${repoName}`));\n console.log(chalk.dim(`profile: ${opts.profile}${opts.dryRun ? ' (dry-run)' : ''}`));\n console.log(chalk.dim(`target: ${targetDir}\\n`));\n\n const answers = opts.nonInteractive\n ? {\n commitScopes: (opts.scopes ?? 'docs,ci,deps')\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean),\n conductEmail: opts.conductEmail ?? 'conduct@precisa-saude.com.br',\n owner: opts.owner ?? 'Precisa-Saude',\n securityEmail: opts.securityEmail ?? 'security@precisa-saude.com.br',\n }\n : await prompts(\n [\n {\n initial: opts.owner ?? 'Precisa-Saude',\n message: 'GitHub owner (org or user):',\n name: 'owner',\n type: 'text',\n },\n {\n initial: opts.securityEmail ?? 'security@precisa-saude.com.br',\n message: 'Security contact email:',\n name: 'securityEmail',\n type: 'text',\n },\n {\n initial: opts.conductEmail ?? 'conduct@precisa-saude.com.br',\n message: 'Code-of-conduct contact email:',\n name: 'conductEmail',\n type: 'text',\n },\n {\n initial: opts.scopes ?? 'docs,ci,deps',\n message: 'Commit scopes (comma-separated):',\n name: 'commitScopes',\n separator: ',',\n type: 'list',\n },\n ],\n { onCancel: () => process.exit(1) },\n );\n\n const manifest: PrecisaManifest = {\n ...DEFAULT_MANIFEST_FIELDS,\n ...profile,\n commitScopes: answers.commitScopes,\n contactEmails: {\n conduct: answers.conductEmail,\n security: answers.securityEmail,\n },\n name: repoName,\n owner: answers.owner,\n };\n\n const spinner = ora('Rendering templates').start();\n try {\n if (!opts.dryRun) mkdirSync(targetDir, { recursive: true });\n\n const entries = loadTemplateManifest().filter((e) => isRequired(e.required_when, manifest));\n const context = tokenContext(manifest);\n\n let created = 0;\n let skipped = 0;\n\n for (const entry of entries) {\n const source = readTemplateSource(entry);\n const rendered = renderTokens(source, context);\n const outcome = applyTemplate({\n cwd: targetDir,\n dryRun: opts.dryRun,\n entry,\n rendered,\n });\n if (outcome.kind === 'create') created += 1;\n else if (outcome.kind === 'skip-exists') skipped += 1;\n else if (outcome.kind === 'error') {\n spinner.fail(`Failed on ${entry.target}`);\n console.error(chalk.red(outcome.message));\n process.exit(1);\n }\n }\n\n spinner.succeed(\n opts.dryRun\n ? `Would render ${created} file${created === 1 ? '' : 's'} (${skipped} skipped)`\n : `Rendered ${created} file${created === 1 ? '' : 's'} (${skipped} skipped)`,\n );\n\n if (opts.dryRun) return;\n\n writeManifest(targetDir, manifest);\n console.log(chalk.dim(` wrote .precisa.json`));\n\n const gitStep = ora('git init + pnpm install').start();\n try {\n execSync('git init --initial-branch=main', { cwd: targetDir, stdio: 'pipe' });\n execSync('pnpm install', { cwd: targetDir, stdio: 'pipe' });\n gitStep.succeed('git init + pnpm install complete');\n } catch (err) {\n gitStep.warn(\n `git/pnpm setup skipped: ${(err as Error).message}. Run manually in ${targetDir}.`,\n );\n }\n\n console.log(chalk.bold.green(`\\n✓ ${repoName} scaffolded at ${targetDir}`));\n console.log(chalk.dim('\\nNext:'));\n console.log(chalk.dim(` cd ${repoName}`));\n console.log(chalk.dim(` # start adding your code`));\n } catch (err) {\n spinner.fail((err as Error).message);\n process.exit(1);\n }\n}\n","import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\n\nimport type { MergeStrategy, TemplateEntry } from './templates.js';\n\nexport type ApplyOutcome =\n | { kind: 'create'; target: string; rendered: string }\n | { kind: 'update'; target: string; previous: string; rendered: string }\n | { kind: 'skip-identical'; target: string }\n | { kind: 'preserve'; target: string; current: string; rendered: string }\n | { kind: 'skip-exists'; target: string }\n | { kind: 'merge-json'; target: string; previous: string; rendered: string }\n | { kind: 'error'; target: string; message: string };\n\nexport interface ApplyOptions {\n /** Repo root to apply into. */\n cwd: string;\n /** When true, compute the outcome but do not write to disk. */\n dryRun: boolean;\n /** Template entry being applied. */\n entry: TemplateEntry;\n /** Rendered template content (post token substitution). */\n rendered: string;\n}\n\n/**\n * Apply a single template file to the target repo. Returns the outcome\n * so callers can print a per-file status row and, on dry-run, a diff.\n */\nexport function applyTemplate({ cwd, dryRun, entry, rendered }: ApplyOptions): ApplyOutcome {\n const targetPath = resolve(cwd, entry.target);\n const exists = existsSync(targetPath);\n\n if (!exists) {\n if (!dryRun) writeFile(targetPath, rendered, entry.executable === true);\n return { kind: 'create', rendered, target: entry.target };\n }\n\n const current = readFileSync(targetPath, 'utf-8');\n\n switch (entry.merge_strategy as MergeStrategy) {\n case 'overwrite': {\n if (current === rendered) {\n return { kind: 'skip-identical', target: entry.target };\n }\n if (!dryRun) writeFile(targetPath, rendered, entry.executable === true);\n return { kind: 'update', previous: current, rendered, target: entry.target };\n }\n case 'skip_if_exists': {\n return { kind: 'skip-exists', target: entry.target };\n }\n case 'preserve': {\n return { current, kind: 'preserve', rendered, target: entry.target };\n }\n case 'merge_json': {\n let merged: string;\n try {\n merged = mergeJson(current, rendered);\n } catch (err) {\n return {\n kind: 'error',\n message: `JSON merge failed: ${(err as Error).message}`,\n target: entry.target,\n };\n }\n if (current === merged) {\n return { kind: 'skip-identical', target: entry.target };\n }\n if (!dryRun) writeFile(targetPath, merged, entry.executable === true);\n return { kind: 'merge-json', previous: current, rendered: merged, target: entry.target };\n }\n default: {\n return {\n kind: 'error',\n message: `Unknown merge_strategy '${entry.merge_strategy}'`,\n target: entry.target,\n };\n }\n }\n}\n\nfunction writeFile(path: string, contents: string, executable: boolean): void {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, contents);\n if (executable) chmodSync(path, 0o755);\n}\n\n/**\n * Shallow 3-way-ish JSON merge — the current file wins on conflicts so\n * repo-local customizations aren't clobbered. Objects are merged\n * key-by-key; arrays and scalars are replaced entirely by the current\n * value when present (falls back to the template value).\n *\n * If parsing fails, throws so the caller can report the error.\n */\nexport function mergeJson(currentRaw: string, templateRaw: string): string {\n const current = JSON.parse(currentRaw) as unknown;\n const template = JSON.parse(templateRaw) as unknown;\n const merged = mergeValue(template, current);\n return `${JSON.stringify(merged, null, 2)}\\n`;\n}\n\nfunction mergeValue(template: unknown, current: unknown): unknown {\n if (current === undefined) return template;\n if (\n typeof template !== 'object' ||\n template === null ||\n Array.isArray(template) ||\n typeof current !== 'object' ||\n current === null ||\n Array.isArray(current)\n ) {\n // Scalars / arrays: current value wins (never clobber repo-local values).\n return current;\n }\n const out: Record<string, unknown> = {};\n const keys = new Set([\n ...Object.keys(template as Record<string, unknown>),\n ...Object.keys(current as Record<string, unknown>),\n ]);\n for (const k of keys) {\n out[k] = mergeValue(\n (template as Record<string, unknown>)[k],\n (current as Record<string, unknown>)[k],\n );\n }\n return out;\n}\n","import chalk from 'chalk';\n\nimport { colorDiff } from '../lib/diff.js';\nimport { type ApplyOutcome, applyTemplate } from '../lib/merge.js';\nimport { loadTemplateManifest, readTemplateSource, renderTokens } from '../lib/templates.js';\nimport { isRequired, loadManifest, tokenContext } from '../manifest.js';\n\nexport interface SyncOptions {\n dryRun: boolean;\n}\n\nexport async function runSync(opts: SyncOptions): Promise<void> {\n const cwd = process.cwd();\n console.log(chalk.bold.cyan(`\\nprecisa sync${opts.dryRun ? ' --dry-run' : ''}`));\n\n let manifest;\n try {\n manifest = loadManifest(cwd);\n } catch (err) {\n console.error(chalk.red(`\\n${(err as Error).message}`));\n console.error(\n chalk.dim('\\n Run `precisa new <repo>` in an empty directory to scaffold a new repo,'),\n );\n console.error(chalk.dim(' or create a `.precisa.json` manifest manually.'));\n process.exit(1);\n }\n\n const entries = loadTemplateManifest().filter((e) => isRequired(e.required_when, manifest));\n const context = tokenContext(manifest);\n\n const outcomes: ApplyOutcome[] = [];\n for (const entry of entries) {\n const source = readTemplateSource(entry);\n const rendered = renderTokens(source, context);\n outcomes.push(\n applyTemplate({\n cwd,\n dryRun: opts.dryRun,\n entry,\n rendered,\n }),\n );\n }\n\n console.log('');\n for (const o of outcomes) {\n printOutcome(o, opts.dryRun);\n }\n\n const summary = summarize(outcomes);\n console.log('');\n console.log(\n chalk.dim(\n `${summary.create} create, ${summary.update} update, ${summary.mergeJson} merge-json, ${summary.preserve} preserve, ${summary.skip} skip, ${summary.error} error`,\n ),\n );\n\n if (summary.error > 0) process.exit(1);\n}\n\ninterface Summary {\n create: number;\n error: number;\n mergeJson: number;\n preserve: number;\n skip: number;\n update: number;\n}\n\nfunction summarize(outcomes: ApplyOutcome[]): Summary {\n const s: Summary = { create: 0, error: 0, mergeJson: 0, preserve: 0, skip: 0, update: 0 };\n for (const o of outcomes) {\n switch (o.kind) {\n case 'create':\n s.create += 1;\n break;\n case 'update':\n s.update += 1;\n break;\n case 'merge-json':\n s.mergeJson += 1;\n break;\n case 'preserve':\n s.preserve += 1;\n break;\n case 'skip-identical':\n case 'skip-exists':\n s.skip += 1;\n break;\n case 'error':\n s.error += 1;\n break;\n }\n }\n return s;\n}\n\nfunction printOutcome(o: ApplyOutcome, dryRun: boolean): void {\n const prefix = dryRun ? '(dry-run) ' : '';\n switch (o.kind) {\n case 'create':\n console.log(`${chalk.green('+')} ${prefix}create ${o.target}`);\n return;\n case 'update':\n console.log(`${chalk.yellow('~')} ${prefix}update ${o.target}`);\n if (dryRun) console.log(indent(colorDiff(o.target, o.previous, o.rendered)));\n return;\n case 'merge-json':\n console.log(`${chalk.yellow('~')} ${prefix}merge ${o.target}`);\n if (dryRun) console.log(indent(colorDiff(o.target, o.previous, o.rendered)));\n return;\n case 'preserve':\n console.log(\n `${chalk.blue('i')} ${prefix}preserve ${o.target} (template differs; not written)`,\n );\n if (dryRun && o.current !== o.rendered) {\n console.log(indent(colorDiff(o.target, o.current, o.rendered)));\n }\n return;\n case 'skip-identical':\n console.log(`${chalk.dim('=')} ${prefix}unchanged ${o.target}`);\n return;\n case 'skip-exists':\n console.log(`${chalk.dim('s')} ${prefix}skip ${o.target} (already exists)`);\n return;\n case 'error':\n console.log(`${chalk.red('!')} ${prefix}error ${o.target}: ${o.message}`);\n return;\n }\n}\n\nfunction indent(text: string): string {\n return text\n .split('\\n')\n .map((l) => ` ${l}`)\n .join('\\n');\n}\n","import chalk from 'chalk';\nimport { createPatch } from 'diff';\n\n/**\n * Format a unified diff with ANSI colors for terminal display.\n * Skips the `@@ hunk @@` metadata lines for a cleaner look.\n */\nexport function colorDiff(filename: string, previous: string, next: string): string {\n const patch = createPatch(filename, previous, next, '', '');\n const lines = patch.split('\\n');\n const out: string[] = [];\n for (const line of lines) {\n if (line.startsWith('---') || line.startsWith('+++')) continue;\n if (line.startsWith('@@')) {\n out.push(chalk.cyan(line));\n continue;\n }\n if (line.startsWith('+')) {\n out.push(chalk.green(line));\n continue;\n }\n if (line.startsWith('-')) {\n out.push(chalk.red(line));\n continue;\n }\n out.push(line);\n }\n return out.join('\\n');\n}\n"],"mappings":"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","names":["existsSync","readFileSync","resolve","resolve","resolve","readFileSync","resolve","resolve","existsSync","readFileSync","existsSync","mkdirSync","resolve","chalk","existsSync","readFileSync","writeFileSync","dirname","resolve","resolve","existsSync","chalk","mkdirSync","chalk","chalk","chalk"]}
package/dist/index.d.ts CHANGED
@@ -62,6 +62,13 @@ interface PrecisaManifest {
62
62
  * read when `hasSite: true`.
63
63
  */
64
64
  siteProjectName?: string;
65
+ /**
66
+ * Path prefix (relative to repo root, trailing slash) treated as site
67
+ * source for change detection in `_deploy-site.yml`. Defaults to
68
+ * `site/` — override to `packages/site/` for monorepos where the site
69
+ * lives under `packages/`.
70
+ */
71
+ siteSourcePath?: string;
65
72
  /** Public-OSS or private-internal. Controls which templates are rendered. */
66
73
  visibility: 'oss' | 'private';
67
74
  }
package/dist/index.js CHANGED
@@ -130,6 +130,7 @@ function tokenContext(manifest) {
130
130
  SECURITY_EMAIL: manifest.contactEmails.security,
131
131
  SITE_FILTER: manifest.siteFilter ?? "",
132
132
  SITE_PROJECT_NAME: manifest.siteProjectName ?? "",
133
+ SITE_SOURCE_PATH: manifest.siteSourcePath ?? "site/",
133
134
  VISIBILITY: manifest.visibility
134
135
  };
135
136
  }
@@ -187,6 +188,9 @@ function validateManifest(raw) {
187
188
  if (m.siteFilter !== void 0 && typeof m.siteFilter !== "string") {
188
189
  errors.push({ message: "must be a string", path: "siteFilter" });
189
190
  }
191
+ if (m.siteSourcePath !== void 0 && typeof m.siteSourcePath !== "string") {
192
+ errors.push({ message: "must be a string", path: "siteSourcePath" });
193
+ }
190
194
  if (!m.contactEmails || typeof m.contactEmails !== "object") {
191
195
  errors.push({ message: "must be an object", path: "contactEmails" });
192
196
  } else {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/doctor.ts","../src/lib/templates.ts","../src/lib/paths.ts","../src/manifest.ts","../src/commands/new.ts","../src/lib/merge.ts","../src/commands/sync.ts","../src/lib/diff.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nimport chalk from 'chalk';\n\nimport {\n loadTemplateManifest,\n readTemplateSource,\n renderTokens,\n type TemplateEntry,\n} from '../lib/templates.js';\nimport { isRequired, loadManifest, tokenContext } from '../manifest.js';\n\ntype Severity = 'ok' | 'info' | 'warning' | 'error';\n\ninterface DriftReport {\n message: string;\n severity: Severity;\n target: string;\n}\n\nexport async function runDoctor(): Promise<void> {\n const cwd = process.cwd();\n console.log(chalk.bold.cyan('\\nprecisa doctor'));\n\n let manifest;\n try {\n manifest = loadManifest(cwd);\n } catch (err) {\n console.error(chalk.red(`\\n${(err as Error).message}`));\n process.exit(1);\n }\n\n const entries = loadTemplateManifest();\n const context = tokenContext(manifest);\n\n const reports: DriftReport[] = [];\n\n for (const entry of entries) {\n const required = isRequired(entry.required_when, manifest);\n const targetPath = resolve(cwd, entry.target);\n const exists = existsSync(targetPath);\n\n if (!required && !exists) continue;\n if (!required && exists) {\n reports.push({\n message: `Present but not required by the manifest profile (ok)`,\n severity: 'info',\n target: entry.target,\n });\n continue;\n }\n if (!exists) {\n reports.push({\n message: 'Missing',\n severity: 'error',\n target: entry.target,\n });\n continue;\n }\n\n // Exists + required — compare to rendered template\n const source = readTemplateSource(entry);\n const rendered = renderTokens(source, context);\n const current = readFileSync(targetPath, 'utf-8');\n reports.push(compareContent(entry, current, rendered));\n }\n\n console.log('');\n let errors = 0;\n let warnings = 0;\n let infos = 0;\n let oks = 0;\n\n for (const r of reports) {\n const icon = iconFor(r.severity);\n const line = `${icon} ${r.target}${r.message ? chalk.dim(` — ${r.message}`) : ''}`;\n console.log(line);\n if (r.severity === 'error') errors += 1;\n else if (r.severity === 'warning') warnings += 1;\n else if (r.severity === 'info') infos += 1;\n else oks += 1;\n }\n\n console.log('');\n console.log(chalk.dim(`${oks} ok, ${warnings} warning, ${errors} error, ${infos} info`));\n\n if (errors > 0) process.exit(1);\n}\n\nfunction compareContent(entry: TemplateEntry, current: string, rendered: string): DriftReport {\n if (current === rendered) {\n return { message: '', severity: 'ok', target: entry.target };\n }\n\n // Non-overwrite strategies don't re-render on sync — treat drift as\n // informational, not a warning. Makes the doctor output scannable:\n // warnings are the files sync WOULD change; infos are files where\n // drift is intentional (customized scaffold, preserved docs).\n if (entry.merge_strategy === 'preserve') {\n return {\n message: 'Differs from template (preserve strategy — suggestion only)',\n severity: 'info',\n target: entry.target,\n };\n }\n if (entry.merge_strategy === 'skip_if_exists') {\n return {\n message: 'Differs from template (scaffold-only; sync will not overwrite)',\n severity: 'info',\n target: entry.target,\n };\n }\n\n return {\n message: 'Differs from template (run `precisa sync` to update)',\n severity: 'warning',\n target: entry.target,\n };\n}\n\nfunction iconFor(severity: Severity): string {\n switch (severity) {\n case 'ok':\n return chalk.green('✓');\n case 'info':\n return chalk.blue('i');\n case 'warning':\n return chalk.yellow('!');\n case 'error':\n return chalk.red('✗');\n }\n}\n","import { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nimport { parse as parseYaml } from 'yaml';\n\nimport type { RequiredWhen } from '../manifest.js';\nimport { resolveTemplatesDir } from './paths.js';\n\nexport type MergeStrategy = 'overwrite' | 'merge_json' | 'preserve' | 'skip_if_exists';\n\nexport interface TemplateEntry {\n /** Whether to mark the rendered file executable (chmod +x). */\n executable?: boolean;\n /** How to merge when the target already exists. */\n merge_strategy: MergeStrategy;\n /** Gate for inclusion. */\n required_when: RequiredWhen;\n /** Path relative to templates/. */\n source: string;\n /** Path in the target repo (relative to the repo root). */\n target: string;\n}\n\ninterface TemplateManifestFile {\n templates: TemplateEntry[];\n}\n\n/**\n * Load the `templates.manifest.yml` from the bundled templates directory.\n * Throws if the file is missing or the shape is wrong.\n */\nexport function loadTemplateManifest(): TemplateEntry[] {\n const dir = resolveTemplatesDir();\n const manifestPath = resolve(dir, 'templates.manifest.yml');\n const raw = readFileSync(manifestPath, 'utf-8');\n const parsed = parseYaml(raw) as TemplateManifestFile | undefined;\n if (!parsed || !Array.isArray(parsed.templates)) {\n throw new Error(`${manifestPath}: expected { templates: [...] } at root`);\n }\n for (const [i, t] of parsed.templates.entries()) {\n if (!t.source || !t.target) {\n throw new Error(`${manifestPath}: entry ${i} is missing source or target`);\n }\n }\n return parsed.templates;\n}\n\nexport function readTemplateSource(entry: TemplateEntry): string {\n const dir = resolveTemplatesDir();\n const path = resolve(dir, entry.source);\n return readFileSync(path, 'utf-8');\n}\n\n/**\n * Substitute `{{TOKEN}}` placeholders with values from `context`. Unknown\n * tokens are left untouched (keeps the double braces visible so bad keys\n * are easy to spot in rendered output).\n *\n * Also processes conditional blocks:\n *\n * {{#if HAS_SITE}}\n * ...lines rendered only when HAS_SITE is truthy...\n * {{/if}}\n *\n * Markers can appear inside a host-language comment so the template stays\n * parseable by syntax-aware tools (prettier on YAML, for example):\n *\n * # {{#if HAS_SITE}}\n * ...\n * # {{/if}}\n *\n * A token is \"truthy\" when its string value is non-empty and not `\"false\"`.\n * Blocks may nest; they are expanded before token substitution so a block's\n * body can itself reference tokens.\n */\nexport function renderTokens(source: string, context: Record<string, string>): string {\n return renderTokenSubstitutions(renderConditionalBlocks(source, context), context);\n}\n\nfunction renderTokenSubstitutions(source: string, context: Record<string, string>): string {\n return source.replace(/\\{\\{([A-Z_]+)\\}\\}/g, (match, token: string) => {\n return Object.prototype.hasOwnProperty.call(context, token) ? context[token]! : match;\n });\n}\n\nfunction renderConditionalBlocks(source: string, context: Record<string, string>): string {\n // Match an entire line containing `{{#if TOKEN}}` (possibly wrapped in a\n // host-language comment like `# {{#if TOKEN}}` or `// {{#if TOKEN}}`),\n // up through the matching `{{/if}}` line. The whole marker line is\n // consumed so commented-out markers don't leak into rendered output.\n const pattern =\n /^[ \\t]*[^\\S\\n]*[^\\n]*\\{\\{#if ([A-Z_]+)\\}\\}[^\\n]*\\n([\\s\\S]*?)^[ \\t]*[^\\n]*\\{\\{\\/if\\}\\}[^\\n]*\\n?/gm;\n let prev: string;\n let out = source;\n // Re-run to handle nested blocks. Simple fixed-point loop keeps the\n // replacement rules uniform.\n do {\n prev = out;\n out = out.replace(pattern, (_match, token: string, body: string) => {\n const value = context[token];\n const truthy = value !== undefined && value !== '' && value !== 'false';\n return truthy ? body : '';\n });\n } while (out !== prev);\n return out;\n}\n","import { existsSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/**\n * Locate the bundled `templates/` directory.\n *\n * When published to npm, the templates live at `dist/templates/` inside\n * the CLI package (copied by `scripts/copy-templates.mjs` during build).\n *\n * When running from the monorepo (e.g. `pnpm --filter @precisa-saude/cli dev`),\n * the templates live at the repo root — fall back to walking up from the\n * package directory.\n */\nexport function resolveTemplatesDir(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n\n // Published case: cli package's dist/templates\n const bundled = resolve(here, 'templates');\n if (existsSync(bundled)) return bundled;\n\n // Dev case: walk up from packages/cli/{src|dist} to the monorepo root\n const repoRoot = resolve(here, '..', '..', '..', '..');\n const repoTemplates = resolve(repoRoot, 'templates');\n if (existsSync(repoTemplates)) return repoTemplates;\n\n // Sibling-in-package case (tsup output): packages/cli/dist -> ../../templates\n const packageParent = resolve(here, '..', '..', 'templates');\n if (existsSync(packageParent)) return packageParent;\n\n throw new Error(\n `Could not locate templates/ directory. Searched:\\n ${bundled}\\n ${repoTemplates}\\n ${packageParent}`,\n );\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\n/**\n * `.precisa.json` manifest — sits at the root of every consumer repo and\n * declares the repo's profile so `precisa sync` and `precisa doctor` know\n * which templates to render and which rules to enforce.\n */\nexport interface PrecisaManifest {\n /** Commitlint scope enum for this repo. */\n commitScopes: string[];\n\n /** Contact emails used in governance doc templates. */\n contactEmails: {\n security: string;\n conduct: string;\n };\n\n /** Does this repo have publishable packages/*? */\n hasPackages: boolean;\n\n /** Does this repo ship a website? Controls preview-deploy workflows. */\n hasSite: boolean;\n\n /** Repository name (typically matches the GitHub repo name). */\n name: string;\n\n /** Pinned runtime versions. Default: node=22, pnpm=9.15.9. */\n nodeVersion?: string;\n\n /** GitHub organization or user that owns the repo (e.g. `Precisa-Saude`). */\n owner: string;\n\n pnpmVersion?: string;\n\n /** Publishes any workspace package to npm? */\n publishesToNpm: boolean;\n\n /**\n * Workspace package directories (relative to repo root) that the\n * `publish` job in `ci.yml` should pass to `_publish.yml`. Only read\n * when `publishesToNpm: true`. Example: `[\"packages/core\", \"packages/cli\"]`.\n */\n publishPackages?: string[];\n\n /** Schema version of this manifest file. Bump when the schema changes. */\n schemaVersion: 1;\n\n /**\n * pnpm filter selector for the site package, passed to the deploy\n * workflow. Only read when `hasSite: true`. Example: `@my-repo/site`.\n */\n siteFilter?: string;\n\n /**\n * Cloudflare Pages project name for the deploy-site workflow. Only\n * read when `hasSite: true`.\n */\n siteProjectName?: string;\n\n /** Public-OSS or private-internal. Controls which templates are rendered. */\n visibility: 'oss' | 'private';\n}\n\nexport const MANIFEST_FILENAME = '.precisa.json';\n\nexport const DEFAULT_MANIFEST_FIELDS = {\n hasPackages: true,\n hasSite: false,\n nodeVersion: '22',\n pnpmVersion: '9.15.9',\n publishesToNpm: true,\n schemaVersion: 1 as const,\n visibility: 'oss' as const,\n};\n\n/** Template gate values — `required_when` in templates.manifest.yml. */\nexport type RequiredWhen =\n | 'always'\n | 'never'\n | 'oss'\n | 'private'\n | 'has_site'\n | 'has_packages'\n | 'publishes_to_npm';\n\n/** Returns true when a template's `required_when` gate applies to this manifest. */\nexport function isRequired(when: RequiredWhen, manifest: PrecisaManifest): boolean {\n switch (when) {\n case 'always':\n return true;\n case 'never':\n return false;\n case 'oss':\n return manifest.visibility === 'oss';\n case 'private':\n return manifest.visibility === 'private';\n case 'has_site':\n return manifest.hasSite;\n case 'has_packages':\n return manifest.hasPackages;\n case 'publishes_to_npm':\n return manifest.publishesToNpm;\n default:\n return true;\n }\n}\n\n/**\n * Build the token substitution map from a manifest. Keys are `{{TOKEN}}`\n * (without braces); values are always strings.\n */\nexport function tokenContext(manifest: PrecisaManifest): Record<string, string> {\n return {\n COMMIT_SCOPES: manifest.commitScopes.join(','),\n // For human-readable docs (AGENTS.md, README) — backticked list.\n COMMIT_SCOPES_HUMAN: manifest.commitScopes.map((s) => `\\`${s}\\``).join(', '),\n // For `.commitlintrc.cjs` — scope array spelled as JS string literals,\n // ready to drop inside `[ ... ]`.\n COMMIT_SCOPES_JSON: manifest.commitScopes.map((s) => `'${s}'`).join(', '),\n CONDUCT_EMAIL: manifest.contactEmails.conduct,\n HAS_PACKAGES: String(manifest.hasPackages),\n HAS_SITE: String(manifest.hasSite),\n NODE_VERSION: manifest.nodeVersion ?? '22',\n OWNER_ORG: manifest.owner,\n PNPM_VERSION: manifest.pnpmVersion ?? '9.15.9',\n // YAML block-scalar body for the `packages: |` input of `_publish.yml`.\n // The template provides the first entry's indent; subsequent entries\n // get 8 spaces explicitly to match. Empty when no packages declared.\n PUBLISH_PACKAGES_YAML: (manifest.publishPackages ?? []).join('\\n '),\n PUBLISHES_TO_NPM: String(manifest.publishesToNpm),\n REPO_NAME: manifest.name,\n REPO_SLUG: `${manifest.owner}/${manifest.name}`,\n SECURITY_EMAIL: manifest.contactEmails.security,\n SITE_FILTER: manifest.siteFilter ?? '',\n SITE_PROJECT_NAME: manifest.siteProjectName ?? '',\n VISIBILITY: manifest.visibility,\n };\n}\n\nexport interface ManifestValidationError {\n message: string;\n path: string;\n}\n\nexport function validateManifest(raw: unknown): ManifestValidationError[] {\n const errors: ManifestValidationError[] = [];\n const m = raw as Partial<PrecisaManifest> | undefined;\n if (!m || typeof m !== 'object') {\n return [{ message: 'manifest must be a JSON object', path: '$' }];\n }\n if (m.schemaVersion !== 1) {\n errors.push({ message: 'must be 1', path: 'schemaVersion' });\n }\n if (typeof m.name !== 'string' || !m.name) {\n errors.push({ message: 'must be a non-empty string', path: 'name' });\n }\n if (typeof m.owner !== 'string' || !m.owner) {\n errors.push({ message: 'must be a non-empty string', path: 'owner' });\n }\n if (m.visibility !== 'oss' && m.visibility !== 'private') {\n errors.push({ message: \"must be 'oss' or 'private'\", path: 'visibility' });\n }\n for (const key of ['hasSite', 'hasPackages', 'publishesToNpm'] as const) {\n if (typeof m[key] !== 'boolean') {\n errors.push({ message: 'must be a boolean', path: key });\n }\n }\n if (!Array.isArray(m.commitScopes)) {\n errors.push({ message: 'must be an array of strings', path: 'commitScopes' });\n }\n if (m.publishPackages !== undefined) {\n if (!Array.isArray(m.publishPackages)) {\n errors.push({ message: 'must be an array of strings', path: 'publishPackages' });\n } else if (m.publishPackages.some((p) => typeof p !== 'string' || !p)) {\n errors.push({ message: 'entries must be non-empty strings', path: 'publishPackages' });\n }\n }\n if (m.publishesToNpm) {\n if (!Array.isArray(m.publishPackages) || m.publishPackages.length === 0) {\n errors.push({\n message: 'must have at least one entry when publishesToNpm is true',\n path: 'publishPackages',\n });\n }\n }\n if (m.hasSite === true) {\n for (const key of ['siteProjectName', 'siteFilter'] as const) {\n if (typeof m[key] !== 'string' || !m[key]) {\n errors.push({ message: 'required and non-empty when hasSite is true', path: key });\n }\n }\n }\n if (m.siteProjectName !== undefined && typeof m.siteProjectName !== 'string') {\n errors.push({ message: 'must be a string', path: 'siteProjectName' });\n }\n if (m.siteFilter !== undefined && typeof m.siteFilter !== 'string') {\n errors.push({ message: 'must be a string', path: 'siteFilter' });\n }\n if (!m.contactEmails || typeof m.contactEmails !== 'object') {\n errors.push({ message: 'must be an object', path: 'contactEmails' });\n } else {\n for (const key of ['security', 'conduct'] as const) {\n if (typeof m.contactEmails[key] !== 'string' || !m.contactEmails[key]) {\n errors.push({\n message: 'must be a non-empty string',\n path: `contactEmails.${key}`,\n });\n }\n }\n }\n return errors;\n}\n\nexport function loadManifest(cwd: string): PrecisaManifest {\n const path = resolve(cwd, MANIFEST_FILENAME);\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(path, 'utf-8'));\n } catch (err) {\n throw new Error(`Failed to read ${MANIFEST_FILENAME} at ${path}: ${(err as Error).message}`);\n }\n const errors = validateManifest(raw);\n if (errors.length > 0) {\n const detail = errors.map((e) => ` - ${e.path}: ${e.message}`).join('\\n');\n throw new Error(`Invalid ${MANIFEST_FILENAME}:\\n${detail}`);\n }\n return raw as PrecisaManifest;\n}\n\nexport function writeManifest(cwd: string, manifest: PrecisaManifest): void {\n const path = resolve(cwd, MANIFEST_FILENAME);\n writeFileSync(path, `${JSON.stringify(manifest, null, 2)}\\n`);\n}\n","import { execSync } from 'node:child_process';\nimport { existsSync, mkdirSync, readdirSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport prompts from 'prompts';\n\nimport { applyTemplate } from '../lib/merge.js';\nimport { loadTemplateManifest, readTemplateSource, renderTokens } from '../lib/templates.js';\nimport {\n DEFAULT_MANIFEST_FIELDS,\n isRequired,\n type PrecisaManifest,\n tokenContext,\n writeManifest,\n} from '../manifest.js';\n\nexport interface NewOptions {\n conductEmail?: string;\n dryRun: boolean;\n /** Skip interactive prompts; require --owner/--scopes/--*-email flags. */\n nonInteractive?: boolean;\n owner?: string;\n profile: string;\n /** Comma-separated list, e.g. \"core,docs,ci,deps\". */\n scopes?: string;\n securityEmail?: string;\n}\n\nconst PROFILES = {\n 'oss-library': {\n hasPackages: true,\n hasSite: false,\n publishesToNpm: true,\n visibility: 'oss',\n },\n 'oss-site': {\n hasPackages: false,\n hasSite: true,\n publishesToNpm: false,\n visibility: 'oss',\n },\n 'private-app': {\n hasPackages: true,\n hasSite: true,\n publishesToNpm: false,\n visibility: 'private',\n },\n} as const satisfies Record<\n string,\n Pick<PrecisaManifest, 'visibility' | 'hasSite' | 'hasPackages' | 'publishesToNpm'>\n>;\n\nexport async function runNew(repoName: string, opts: NewOptions): Promise<void> {\n const targetDir = resolve(process.cwd(), repoName);\n\n if (existsSync(targetDir) && readdirSync(targetDir).length > 0) {\n console.error(chalk.red(`\\nError: ${targetDir} already exists and is not empty.`));\n process.exit(1);\n }\n\n const profile = PROFILES[opts.profile as keyof typeof PROFILES];\n if (!profile) {\n console.error(\n chalk.red(`\\nError: unknown profile '${opts.profile}'. Choose one of:`),\n Object.keys(PROFILES).join(', '),\n );\n process.exit(1);\n }\n\n console.log(chalk.bold.cyan(`\\nprecisa new ${repoName}`));\n console.log(chalk.dim(`profile: ${opts.profile}${opts.dryRun ? ' (dry-run)' : ''}`));\n console.log(chalk.dim(`target: ${targetDir}\\n`));\n\n const answers = opts.nonInteractive\n ? {\n commitScopes: (opts.scopes ?? 'docs,ci,deps')\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean),\n conductEmail: opts.conductEmail ?? 'conduct@precisa-saude.com.br',\n owner: opts.owner ?? 'Precisa-Saude',\n securityEmail: opts.securityEmail ?? 'security@precisa-saude.com.br',\n }\n : await prompts(\n [\n {\n initial: opts.owner ?? 'Precisa-Saude',\n message: 'GitHub owner (org or user):',\n name: 'owner',\n type: 'text',\n },\n {\n initial: opts.securityEmail ?? 'security@precisa-saude.com.br',\n message: 'Security contact email:',\n name: 'securityEmail',\n type: 'text',\n },\n {\n initial: opts.conductEmail ?? 'conduct@precisa-saude.com.br',\n message: 'Code-of-conduct contact email:',\n name: 'conductEmail',\n type: 'text',\n },\n {\n initial: opts.scopes ?? 'docs,ci,deps',\n message: 'Commit scopes (comma-separated):',\n name: 'commitScopes',\n separator: ',',\n type: 'list',\n },\n ],\n { onCancel: () => process.exit(1) },\n );\n\n const manifest: PrecisaManifest = {\n ...DEFAULT_MANIFEST_FIELDS,\n ...profile,\n commitScopes: answers.commitScopes,\n contactEmails: {\n conduct: answers.conductEmail,\n security: answers.securityEmail,\n },\n name: repoName,\n owner: answers.owner,\n };\n\n const spinner = ora('Rendering templates').start();\n try {\n if (!opts.dryRun) mkdirSync(targetDir, { recursive: true });\n\n const entries = loadTemplateManifest().filter((e) => isRequired(e.required_when, manifest));\n const context = tokenContext(manifest);\n\n let created = 0;\n let skipped = 0;\n\n for (const entry of entries) {\n const source = readTemplateSource(entry);\n const rendered = renderTokens(source, context);\n const outcome = applyTemplate({\n cwd: targetDir,\n dryRun: opts.dryRun,\n entry,\n rendered,\n });\n if (outcome.kind === 'create') created += 1;\n else if (outcome.kind === 'skip-exists') skipped += 1;\n else if (outcome.kind === 'error') {\n spinner.fail(`Failed on ${entry.target}`);\n console.error(chalk.red(outcome.message));\n process.exit(1);\n }\n }\n\n spinner.succeed(\n opts.dryRun\n ? `Would render ${created} file${created === 1 ? '' : 's'} (${skipped} skipped)`\n : `Rendered ${created} file${created === 1 ? '' : 's'} (${skipped} skipped)`,\n );\n\n if (opts.dryRun) return;\n\n writeManifest(targetDir, manifest);\n console.log(chalk.dim(` wrote .precisa.json`));\n\n const gitStep = ora('git init + pnpm install').start();\n try {\n execSync('git init --initial-branch=main', { cwd: targetDir, stdio: 'pipe' });\n execSync('pnpm install', { cwd: targetDir, stdio: 'pipe' });\n gitStep.succeed('git init + pnpm install complete');\n } catch (err) {\n gitStep.warn(\n `git/pnpm setup skipped: ${(err as Error).message}. Run manually in ${targetDir}.`,\n );\n }\n\n console.log(chalk.bold.green(`\\n✓ ${repoName} scaffolded at ${targetDir}`));\n console.log(chalk.dim('\\nNext:'));\n console.log(chalk.dim(` cd ${repoName}`));\n console.log(chalk.dim(` # start adding your code`));\n } catch (err) {\n spinner.fail((err as Error).message);\n process.exit(1);\n }\n}\n","import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\n\nimport type { MergeStrategy, TemplateEntry } from './templates.js';\n\nexport type ApplyOutcome =\n | { kind: 'create'; target: string; rendered: string }\n | { kind: 'update'; target: string; previous: string; rendered: string }\n | { kind: 'skip-identical'; target: string }\n | { kind: 'preserve'; target: string; current: string; rendered: string }\n | { kind: 'skip-exists'; target: string }\n | { kind: 'merge-json'; target: string; previous: string; rendered: string }\n | { kind: 'error'; target: string; message: string };\n\nexport interface ApplyOptions {\n /** Repo root to apply into. */\n cwd: string;\n /** When true, compute the outcome but do not write to disk. */\n dryRun: boolean;\n /** Template entry being applied. */\n entry: TemplateEntry;\n /** Rendered template content (post token substitution). */\n rendered: string;\n}\n\n/**\n * Apply a single template file to the target repo. Returns the outcome\n * so callers can print a per-file status row and, on dry-run, a diff.\n */\nexport function applyTemplate({ cwd, dryRun, entry, rendered }: ApplyOptions): ApplyOutcome {\n const targetPath = resolve(cwd, entry.target);\n const exists = existsSync(targetPath);\n\n if (!exists) {\n if (!dryRun) writeFile(targetPath, rendered, entry.executable === true);\n return { kind: 'create', rendered, target: entry.target };\n }\n\n const current = readFileSync(targetPath, 'utf-8');\n\n switch (entry.merge_strategy as MergeStrategy) {\n case 'overwrite': {\n if (current === rendered) {\n return { kind: 'skip-identical', target: entry.target };\n }\n if (!dryRun) writeFile(targetPath, rendered, entry.executable === true);\n return { kind: 'update', previous: current, rendered, target: entry.target };\n }\n case 'skip_if_exists': {\n return { kind: 'skip-exists', target: entry.target };\n }\n case 'preserve': {\n return { current, kind: 'preserve', rendered, target: entry.target };\n }\n case 'merge_json': {\n let merged: string;\n try {\n merged = mergeJson(current, rendered);\n } catch (err) {\n return {\n kind: 'error',\n message: `JSON merge failed: ${(err as Error).message}`,\n target: entry.target,\n };\n }\n if (current === merged) {\n return { kind: 'skip-identical', target: entry.target };\n }\n if (!dryRun) writeFile(targetPath, merged, entry.executable === true);\n return { kind: 'merge-json', previous: current, rendered: merged, target: entry.target };\n }\n default: {\n return {\n kind: 'error',\n message: `Unknown merge_strategy '${entry.merge_strategy}'`,\n target: entry.target,\n };\n }\n }\n}\n\nfunction writeFile(path: string, contents: string, executable: boolean): void {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, contents);\n if (executable) chmodSync(path, 0o755);\n}\n\n/**\n * Shallow 3-way-ish JSON merge — the current file wins on conflicts so\n * repo-local customizations aren't clobbered. Objects are merged\n * key-by-key; arrays and scalars are replaced entirely by the current\n * value when present (falls back to the template value).\n *\n * If parsing fails, throws so the caller can report the error.\n */\nexport function mergeJson(currentRaw: string, templateRaw: string): string {\n const current = JSON.parse(currentRaw) as unknown;\n const template = JSON.parse(templateRaw) as unknown;\n const merged = mergeValue(template, current);\n return `${JSON.stringify(merged, null, 2)}\\n`;\n}\n\nfunction mergeValue(template: unknown, current: unknown): unknown {\n if (current === undefined) return template;\n if (\n typeof template !== 'object' ||\n template === null ||\n Array.isArray(template) ||\n typeof current !== 'object' ||\n current === null ||\n Array.isArray(current)\n ) {\n // Scalars / arrays: current value wins (never clobber repo-local values).\n return current;\n }\n const out: Record<string, unknown> = {};\n const keys = new Set([\n ...Object.keys(template as Record<string, unknown>),\n ...Object.keys(current as Record<string, unknown>),\n ]);\n for (const k of keys) {\n out[k] = mergeValue(\n (template as Record<string, unknown>)[k],\n (current as Record<string, unknown>)[k],\n );\n }\n return out;\n}\n","import chalk from 'chalk';\n\nimport { colorDiff } from '../lib/diff.js';\nimport { type ApplyOutcome, applyTemplate } from '../lib/merge.js';\nimport { loadTemplateManifest, readTemplateSource, renderTokens } from '../lib/templates.js';\nimport { isRequired, loadManifest, tokenContext } from '../manifest.js';\n\nexport interface SyncOptions {\n dryRun: boolean;\n}\n\nexport async function runSync(opts: SyncOptions): Promise<void> {\n const cwd = process.cwd();\n console.log(chalk.bold.cyan(`\\nprecisa sync${opts.dryRun ? ' --dry-run' : ''}`));\n\n let manifest;\n try {\n manifest = loadManifest(cwd);\n } catch (err) {\n console.error(chalk.red(`\\n${(err as Error).message}`));\n console.error(\n chalk.dim('\\n Run `precisa new <repo>` in an empty directory to scaffold a new repo,'),\n );\n console.error(chalk.dim(' or create a `.precisa.json` manifest manually.'));\n process.exit(1);\n }\n\n const entries = loadTemplateManifest().filter((e) => isRequired(e.required_when, manifest));\n const context = tokenContext(manifest);\n\n const outcomes: ApplyOutcome[] = [];\n for (const entry of entries) {\n const source = readTemplateSource(entry);\n const rendered = renderTokens(source, context);\n outcomes.push(\n applyTemplate({\n cwd,\n dryRun: opts.dryRun,\n entry,\n rendered,\n }),\n );\n }\n\n console.log('');\n for (const o of outcomes) {\n printOutcome(o, opts.dryRun);\n }\n\n const summary = summarize(outcomes);\n console.log('');\n console.log(\n chalk.dim(\n `${summary.create} create, ${summary.update} update, ${summary.mergeJson} merge-json, ${summary.preserve} preserve, ${summary.skip} skip, ${summary.error} error`,\n ),\n );\n\n if (summary.error > 0) process.exit(1);\n}\n\ninterface Summary {\n create: number;\n error: number;\n mergeJson: number;\n preserve: number;\n skip: number;\n update: number;\n}\n\nfunction summarize(outcomes: ApplyOutcome[]): Summary {\n const s: Summary = { create: 0, error: 0, mergeJson: 0, preserve: 0, skip: 0, update: 0 };\n for (const o of outcomes) {\n switch (o.kind) {\n case 'create':\n s.create += 1;\n break;\n case 'update':\n s.update += 1;\n break;\n case 'merge-json':\n s.mergeJson += 1;\n break;\n case 'preserve':\n s.preserve += 1;\n break;\n case 'skip-identical':\n case 'skip-exists':\n s.skip += 1;\n break;\n case 'error':\n s.error += 1;\n break;\n }\n }\n return s;\n}\n\nfunction printOutcome(o: ApplyOutcome, dryRun: boolean): void {\n const prefix = dryRun ? '(dry-run) ' : '';\n switch (o.kind) {\n case 'create':\n console.log(`${chalk.green('+')} ${prefix}create ${o.target}`);\n return;\n case 'update':\n console.log(`${chalk.yellow('~')} ${prefix}update ${o.target}`);\n if (dryRun) console.log(indent(colorDiff(o.target, o.previous, o.rendered)));\n return;\n case 'merge-json':\n console.log(`${chalk.yellow('~')} ${prefix}merge ${o.target}`);\n if (dryRun) console.log(indent(colorDiff(o.target, o.previous, o.rendered)));\n return;\n case 'preserve':\n console.log(\n `${chalk.blue('i')} ${prefix}preserve ${o.target} (template differs; not written)`,\n );\n if (dryRun && o.current !== o.rendered) {\n console.log(indent(colorDiff(o.target, o.current, o.rendered)));\n }\n return;\n case 'skip-identical':\n console.log(`${chalk.dim('=')} ${prefix}unchanged ${o.target}`);\n return;\n case 'skip-exists':\n console.log(`${chalk.dim('s')} ${prefix}skip ${o.target} (already exists)`);\n return;\n case 'error':\n console.log(`${chalk.red('!')} ${prefix}error ${o.target}: ${o.message}`);\n return;\n }\n}\n\nfunction indent(text: string): string {\n return text\n .split('\\n')\n .map((l) => ` ${l}`)\n .join('\\n');\n}\n","import chalk from 'chalk';\nimport { createPatch } from 'diff';\n\n/**\n * Format a unified diff with ANSI colors for terminal display.\n * Skips the `@@ hunk @@` metadata lines for a cleaner look.\n */\nexport function colorDiff(filename: string, previous: string, next: string): string {\n const patch = createPatch(filename, previous, next, '', '');\n const lines = patch.split('\\n');\n const out: string[] = [];\n for (const line of lines) {\n if (line.startsWith('---') || line.startsWith('+++')) continue;\n if (line.startsWith('@@')) {\n out.push(chalk.cyan(line));\n continue;\n }\n if (line.startsWith('+')) {\n out.push(chalk.green(line));\n continue;\n }\n if (line.startsWith('-')) {\n out.push(chalk.red(line));\n continue;\n }\n out.push(line);\n }\n return out.join('\\n');\n}\n"],"mappings":"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","names":["existsSync","readFileSync","resolve","resolve","resolve","readFileSync","resolve","resolve","existsSync","readFileSync","existsSync","mkdirSync","resolve","chalk","existsSync","readFileSync","writeFileSync","dirname","resolve","resolve","existsSync","chalk","mkdirSync","chalk","chalk","chalk"]}
1
+ {"version":3,"sources":["../src/commands/doctor.ts","../src/lib/templates.ts","../src/lib/paths.ts","../src/manifest.ts","../src/commands/new.ts","../src/lib/merge.ts","../src/commands/sync.ts","../src/lib/diff.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nimport chalk from 'chalk';\n\nimport {\n loadTemplateManifest,\n readTemplateSource,\n renderTokens,\n type TemplateEntry,\n} from '../lib/templates.js';\nimport { isRequired, loadManifest, tokenContext } from '../manifest.js';\n\ntype Severity = 'ok' | 'info' | 'warning' | 'error';\n\ninterface DriftReport {\n message: string;\n severity: Severity;\n target: string;\n}\n\nexport async function runDoctor(): Promise<void> {\n const cwd = process.cwd();\n console.log(chalk.bold.cyan('\\nprecisa doctor'));\n\n let manifest;\n try {\n manifest = loadManifest(cwd);\n } catch (err) {\n console.error(chalk.red(`\\n${(err as Error).message}`));\n process.exit(1);\n }\n\n const entries = loadTemplateManifest();\n const context = tokenContext(manifest);\n\n const reports: DriftReport[] = [];\n\n for (const entry of entries) {\n const required = isRequired(entry.required_when, manifest);\n const targetPath = resolve(cwd, entry.target);\n const exists = existsSync(targetPath);\n\n if (!required && !exists) continue;\n if (!required && exists) {\n reports.push({\n message: `Present but not required by the manifest profile (ok)`,\n severity: 'info',\n target: entry.target,\n });\n continue;\n }\n if (!exists) {\n reports.push({\n message: 'Missing',\n severity: 'error',\n target: entry.target,\n });\n continue;\n }\n\n // Exists + required — compare to rendered template\n const source = readTemplateSource(entry);\n const rendered = renderTokens(source, context);\n const current = readFileSync(targetPath, 'utf-8');\n reports.push(compareContent(entry, current, rendered));\n }\n\n console.log('');\n let errors = 0;\n let warnings = 0;\n let infos = 0;\n let oks = 0;\n\n for (const r of reports) {\n const icon = iconFor(r.severity);\n const line = `${icon} ${r.target}${r.message ? chalk.dim(` — ${r.message}`) : ''}`;\n console.log(line);\n if (r.severity === 'error') errors += 1;\n else if (r.severity === 'warning') warnings += 1;\n else if (r.severity === 'info') infos += 1;\n else oks += 1;\n }\n\n console.log('');\n console.log(chalk.dim(`${oks} ok, ${warnings} warning, ${errors} error, ${infos} info`));\n\n if (errors > 0) process.exit(1);\n}\n\nfunction compareContent(entry: TemplateEntry, current: string, rendered: string): DriftReport {\n if (current === rendered) {\n return { message: '', severity: 'ok', target: entry.target };\n }\n\n // Non-overwrite strategies don't re-render on sync — treat drift as\n // informational, not a warning. Makes the doctor output scannable:\n // warnings are the files sync WOULD change; infos are files where\n // drift is intentional (customized scaffold, preserved docs).\n if (entry.merge_strategy === 'preserve') {\n return {\n message: 'Differs from template (preserve strategy — suggestion only)',\n severity: 'info',\n target: entry.target,\n };\n }\n if (entry.merge_strategy === 'skip_if_exists') {\n return {\n message: 'Differs from template (scaffold-only; sync will not overwrite)',\n severity: 'info',\n target: entry.target,\n };\n }\n\n return {\n message: 'Differs from template (run `precisa sync` to update)',\n severity: 'warning',\n target: entry.target,\n };\n}\n\nfunction iconFor(severity: Severity): string {\n switch (severity) {\n case 'ok':\n return chalk.green('✓');\n case 'info':\n return chalk.blue('i');\n case 'warning':\n return chalk.yellow('!');\n case 'error':\n return chalk.red('✗');\n }\n}\n","import { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nimport { parse as parseYaml } from 'yaml';\n\nimport type { RequiredWhen } from '../manifest.js';\nimport { resolveTemplatesDir } from './paths.js';\n\nexport type MergeStrategy = 'overwrite' | 'merge_json' | 'preserve' | 'skip_if_exists';\n\nexport interface TemplateEntry {\n /** Whether to mark the rendered file executable (chmod +x). */\n executable?: boolean;\n /** How to merge when the target already exists. */\n merge_strategy: MergeStrategy;\n /** Gate for inclusion. */\n required_when: RequiredWhen;\n /** Path relative to templates/. */\n source: string;\n /** Path in the target repo (relative to the repo root). */\n target: string;\n}\n\ninterface TemplateManifestFile {\n templates: TemplateEntry[];\n}\n\n/**\n * Load the `templates.manifest.yml` from the bundled templates directory.\n * Throws if the file is missing or the shape is wrong.\n */\nexport function loadTemplateManifest(): TemplateEntry[] {\n const dir = resolveTemplatesDir();\n const manifestPath = resolve(dir, 'templates.manifest.yml');\n const raw = readFileSync(manifestPath, 'utf-8');\n const parsed = parseYaml(raw) as TemplateManifestFile | undefined;\n if (!parsed || !Array.isArray(parsed.templates)) {\n throw new Error(`${manifestPath}: expected { templates: [...] } at root`);\n }\n for (const [i, t] of parsed.templates.entries()) {\n if (!t.source || !t.target) {\n throw new Error(`${manifestPath}: entry ${i} is missing source or target`);\n }\n }\n return parsed.templates;\n}\n\nexport function readTemplateSource(entry: TemplateEntry): string {\n const dir = resolveTemplatesDir();\n const path = resolve(dir, entry.source);\n return readFileSync(path, 'utf-8');\n}\n\n/**\n * Substitute `{{TOKEN}}` placeholders with values from `context`. Unknown\n * tokens are left untouched (keeps the double braces visible so bad keys\n * are easy to spot in rendered output).\n *\n * Also processes conditional blocks:\n *\n * {{#if HAS_SITE}}\n * ...lines rendered only when HAS_SITE is truthy...\n * {{/if}}\n *\n * Markers can appear inside a host-language comment so the template stays\n * parseable by syntax-aware tools (prettier on YAML, for example):\n *\n * # {{#if HAS_SITE}}\n * ...\n * # {{/if}}\n *\n * A token is \"truthy\" when its string value is non-empty and not `\"false\"`.\n * Blocks may nest; they are expanded before token substitution so a block's\n * body can itself reference tokens.\n */\nexport function renderTokens(source: string, context: Record<string, string>): string {\n return renderTokenSubstitutions(renderConditionalBlocks(source, context), context);\n}\n\nfunction renderTokenSubstitutions(source: string, context: Record<string, string>): string {\n return source.replace(/\\{\\{([A-Z_]+)\\}\\}/g, (match, token: string) => {\n return Object.prototype.hasOwnProperty.call(context, token) ? context[token]! : match;\n });\n}\n\nfunction renderConditionalBlocks(source: string, context: Record<string, string>): string {\n // Match an entire line containing `{{#if TOKEN}}` (possibly wrapped in a\n // host-language comment like `# {{#if TOKEN}}` or `// {{#if TOKEN}}`),\n // up through the matching `{{/if}}` line. The whole marker line is\n // consumed so commented-out markers don't leak into rendered output.\n const pattern =\n /^[ \\t]*[^\\S\\n]*[^\\n]*\\{\\{#if ([A-Z_]+)\\}\\}[^\\n]*\\n([\\s\\S]*?)^[ \\t]*[^\\n]*\\{\\{\\/if\\}\\}[^\\n]*\\n?/gm;\n let prev: string;\n let out = source;\n // Re-run to handle nested blocks. Simple fixed-point loop keeps the\n // replacement rules uniform.\n do {\n prev = out;\n out = out.replace(pattern, (_match, token: string, body: string) => {\n const value = context[token];\n const truthy = value !== undefined && value !== '' && value !== 'false';\n return truthy ? body : '';\n });\n } while (out !== prev);\n return out;\n}\n","import { existsSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/**\n * Locate the bundled `templates/` directory.\n *\n * When published to npm, the templates live at `dist/templates/` inside\n * the CLI package (copied by `scripts/copy-templates.mjs` during build).\n *\n * When running from the monorepo (e.g. `pnpm --filter @precisa-saude/cli dev`),\n * the templates live at the repo root — fall back to walking up from the\n * package directory.\n */\nexport function resolveTemplatesDir(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n\n // Published case: cli package's dist/templates\n const bundled = resolve(here, 'templates');\n if (existsSync(bundled)) return bundled;\n\n // Dev case: walk up from packages/cli/{src|dist} to the monorepo root\n const repoRoot = resolve(here, '..', '..', '..', '..');\n const repoTemplates = resolve(repoRoot, 'templates');\n if (existsSync(repoTemplates)) return repoTemplates;\n\n // Sibling-in-package case (tsup output): packages/cli/dist -> ../../templates\n const packageParent = resolve(here, '..', '..', 'templates');\n if (existsSync(packageParent)) return packageParent;\n\n throw new Error(\n `Could not locate templates/ directory. Searched:\\n ${bundled}\\n ${repoTemplates}\\n ${packageParent}`,\n );\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\n/**\n * `.precisa.json` manifest — sits at the root of every consumer repo and\n * declares the repo's profile so `precisa sync` and `precisa doctor` know\n * which templates to render and which rules to enforce.\n */\nexport interface PrecisaManifest {\n /** Commitlint scope enum for this repo. */\n commitScopes: string[];\n\n /** Contact emails used in governance doc templates. */\n contactEmails: {\n security: string;\n conduct: string;\n };\n\n /** Does this repo have publishable packages/*? */\n hasPackages: boolean;\n\n /** Does this repo ship a website? Controls preview-deploy workflows. */\n hasSite: boolean;\n\n /** Repository name (typically matches the GitHub repo name). */\n name: string;\n\n /** Pinned runtime versions. Default: node=22, pnpm=9.15.9. */\n nodeVersion?: string;\n\n /** GitHub organization or user that owns the repo (e.g. `Precisa-Saude`). */\n owner: string;\n\n pnpmVersion?: string;\n\n /** Publishes any workspace package to npm? */\n publishesToNpm: boolean;\n\n /**\n * Workspace package directories (relative to repo root) that the\n * `publish` job in `ci.yml` should pass to `_publish.yml`. Only read\n * when `publishesToNpm: true`. Example: `[\"packages/core\", \"packages/cli\"]`.\n */\n publishPackages?: string[];\n\n /** Schema version of this manifest file. Bump when the schema changes. */\n schemaVersion: 1;\n\n /**\n * pnpm filter selector for the site package, passed to the deploy\n * workflow. Only read when `hasSite: true`. Example: `@my-repo/site`.\n */\n siteFilter?: string;\n\n /**\n * Cloudflare Pages project name for the deploy-site workflow. Only\n * read when `hasSite: true`.\n */\n siteProjectName?: string;\n\n /**\n * Path prefix (relative to repo root, trailing slash) treated as site\n * source for change detection in `_deploy-site.yml`. Defaults to\n * `site/` — override to `packages/site/` for monorepos where the site\n * lives under `packages/`.\n */\n siteSourcePath?: string;\n\n /** Public-OSS or private-internal. Controls which templates are rendered. */\n visibility: 'oss' | 'private';\n}\n\nexport const MANIFEST_FILENAME = '.precisa.json';\n\nexport const DEFAULT_MANIFEST_FIELDS = {\n hasPackages: true,\n hasSite: false,\n nodeVersion: '22',\n pnpmVersion: '9.15.9',\n publishesToNpm: true,\n schemaVersion: 1 as const,\n visibility: 'oss' as const,\n};\n\n/** Template gate values — `required_when` in templates.manifest.yml. */\nexport type RequiredWhen =\n | 'always'\n | 'never'\n | 'oss'\n | 'private'\n | 'has_site'\n | 'has_packages'\n | 'publishes_to_npm';\n\n/** Returns true when a template's `required_when` gate applies to this manifest. */\nexport function isRequired(when: RequiredWhen, manifest: PrecisaManifest): boolean {\n switch (when) {\n case 'always':\n return true;\n case 'never':\n return false;\n case 'oss':\n return manifest.visibility === 'oss';\n case 'private':\n return manifest.visibility === 'private';\n case 'has_site':\n return manifest.hasSite;\n case 'has_packages':\n return manifest.hasPackages;\n case 'publishes_to_npm':\n return manifest.publishesToNpm;\n default:\n return true;\n }\n}\n\n/**\n * Build the token substitution map from a manifest. Keys are `{{TOKEN}}`\n * (without braces); values are always strings.\n */\nexport function tokenContext(manifest: PrecisaManifest): Record<string, string> {\n return {\n COMMIT_SCOPES: manifest.commitScopes.join(','),\n // For human-readable docs (AGENTS.md, README) — backticked list.\n COMMIT_SCOPES_HUMAN: manifest.commitScopes.map((s) => `\\`${s}\\``).join(', '),\n // For `.commitlintrc.cjs` — scope array spelled as JS string literals,\n // ready to drop inside `[ ... ]`.\n COMMIT_SCOPES_JSON: manifest.commitScopes.map((s) => `'${s}'`).join(', '),\n CONDUCT_EMAIL: manifest.contactEmails.conduct,\n HAS_PACKAGES: String(manifest.hasPackages),\n HAS_SITE: String(manifest.hasSite),\n NODE_VERSION: manifest.nodeVersion ?? '22',\n OWNER_ORG: manifest.owner,\n PNPM_VERSION: manifest.pnpmVersion ?? '9.15.9',\n // YAML block-scalar body for the `packages: |` input of `_publish.yml`.\n // The template provides the first entry's indent; subsequent entries\n // get 8 spaces explicitly to match. Empty when no packages declared.\n PUBLISH_PACKAGES_YAML: (manifest.publishPackages ?? []).join('\\n '),\n PUBLISHES_TO_NPM: String(manifest.publishesToNpm),\n REPO_NAME: manifest.name,\n REPO_SLUG: `${manifest.owner}/${manifest.name}`,\n SECURITY_EMAIL: manifest.contactEmails.security,\n SITE_FILTER: manifest.siteFilter ?? '',\n SITE_PROJECT_NAME: manifest.siteProjectName ?? '',\n SITE_SOURCE_PATH: manifest.siteSourcePath ?? 'site/',\n VISIBILITY: manifest.visibility,\n };\n}\n\nexport interface ManifestValidationError {\n message: string;\n path: string;\n}\n\nexport function validateManifest(raw: unknown): ManifestValidationError[] {\n const errors: ManifestValidationError[] = [];\n const m = raw as Partial<PrecisaManifest> | undefined;\n if (!m || typeof m !== 'object') {\n return [{ message: 'manifest must be a JSON object', path: '$' }];\n }\n if (m.schemaVersion !== 1) {\n errors.push({ message: 'must be 1', path: 'schemaVersion' });\n }\n if (typeof m.name !== 'string' || !m.name) {\n errors.push({ message: 'must be a non-empty string', path: 'name' });\n }\n if (typeof m.owner !== 'string' || !m.owner) {\n errors.push({ message: 'must be a non-empty string', path: 'owner' });\n }\n if (m.visibility !== 'oss' && m.visibility !== 'private') {\n errors.push({ message: \"must be 'oss' or 'private'\", path: 'visibility' });\n }\n for (const key of ['hasSite', 'hasPackages', 'publishesToNpm'] as const) {\n if (typeof m[key] !== 'boolean') {\n errors.push({ message: 'must be a boolean', path: key });\n }\n }\n if (!Array.isArray(m.commitScopes)) {\n errors.push({ message: 'must be an array of strings', path: 'commitScopes' });\n }\n if (m.publishPackages !== undefined) {\n if (!Array.isArray(m.publishPackages)) {\n errors.push({ message: 'must be an array of strings', path: 'publishPackages' });\n } else if (m.publishPackages.some((p) => typeof p !== 'string' || !p)) {\n errors.push({ message: 'entries must be non-empty strings', path: 'publishPackages' });\n }\n }\n if (m.publishesToNpm) {\n if (!Array.isArray(m.publishPackages) || m.publishPackages.length === 0) {\n errors.push({\n message: 'must have at least one entry when publishesToNpm is true',\n path: 'publishPackages',\n });\n }\n }\n if (m.hasSite === true) {\n for (const key of ['siteProjectName', 'siteFilter'] as const) {\n if (typeof m[key] !== 'string' || !m[key]) {\n errors.push({ message: 'required and non-empty when hasSite is true', path: key });\n }\n }\n }\n if (m.siteProjectName !== undefined && typeof m.siteProjectName !== 'string') {\n errors.push({ message: 'must be a string', path: 'siteProjectName' });\n }\n if (m.siteFilter !== undefined && typeof m.siteFilter !== 'string') {\n errors.push({ message: 'must be a string', path: 'siteFilter' });\n }\n if (m.siteSourcePath !== undefined && typeof m.siteSourcePath !== 'string') {\n errors.push({ message: 'must be a string', path: 'siteSourcePath' });\n }\n if (!m.contactEmails || typeof m.contactEmails !== 'object') {\n errors.push({ message: 'must be an object', path: 'contactEmails' });\n } else {\n for (const key of ['security', 'conduct'] as const) {\n if (typeof m.contactEmails[key] !== 'string' || !m.contactEmails[key]) {\n errors.push({\n message: 'must be a non-empty string',\n path: `contactEmails.${key}`,\n });\n }\n }\n }\n return errors;\n}\n\nexport function loadManifest(cwd: string): PrecisaManifest {\n const path = resolve(cwd, MANIFEST_FILENAME);\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(path, 'utf-8'));\n } catch (err) {\n throw new Error(`Failed to read ${MANIFEST_FILENAME} at ${path}: ${(err as Error).message}`);\n }\n const errors = validateManifest(raw);\n if (errors.length > 0) {\n const detail = errors.map((e) => ` - ${e.path}: ${e.message}`).join('\\n');\n throw new Error(`Invalid ${MANIFEST_FILENAME}:\\n${detail}`);\n }\n return raw as PrecisaManifest;\n}\n\nexport function writeManifest(cwd: string, manifest: PrecisaManifest): void {\n const path = resolve(cwd, MANIFEST_FILENAME);\n writeFileSync(path, `${JSON.stringify(manifest, null, 2)}\\n`);\n}\n","import { execSync } from 'node:child_process';\nimport { existsSync, mkdirSync, readdirSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport prompts from 'prompts';\n\nimport { applyTemplate } from '../lib/merge.js';\nimport { loadTemplateManifest, readTemplateSource, renderTokens } from '../lib/templates.js';\nimport {\n DEFAULT_MANIFEST_FIELDS,\n isRequired,\n type PrecisaManifest,\n tokenContext,\n writeManifest,\n} from '../manifest.js';\n\nexport interface NewOptions {\n conductEmail?: string;\n dryRun: boolean;\n /** Skip interactive prompts; require --owner/--scopes/--*-email flags. */\n nonInteractive?: boolean;\n owner?: string;\n profile: string;\n /** Comma-separated list, e.g. \"core,docs,ci,deps\". */\n scopes?: string;\n securityEmail?: string;\n}\n\nconst PROFILES = {\n 'oss-library': {\n hasPackages: true,\n hasSite: false,\n publishesToNpm: true,\n visibility: 'oss',\n },\n 'oss-site': {\n hasPackages: false,\n hasSite: true,\n publishesToNpm: false,\n visibility: 'oss',\n },\n 'private-app': {\n hasPackages: true,\n hasSite: true,\n publishesToNpm: false,\n visibility: 'private',\n },\n} as const satisfies Record<\n string,\n Pick<PrecisaManifest, 'visibility' | 'hasSite' | 'hasPackages' | 'publishesToNpm'>\n>;\n\nexport async function runNew(repoName: string, opts: NewOptions): Promise<void> {\n const targetDir = resolve(process.cwd(), repoName);\n\n if (existsSync(targetDir) && readdirSync(targetDir).length > 0) {\n console.error(chalk.red(`\\nError: ${targetDir} already exists and is not empty.`));\n process.exit(1);\n }\n\n const profile = PROFILES[opts.profile as keyof typeof PROFILES];\n if (!profile) {\n console.error(\n chalk.red(`\\nError: unknown profile '${opts.profile}'. Choose one of:`),\n Object.keys(PROFILES).join(', '),\n );\n process.exit(1);\n }\n\n console.log(chalk.bold.cyan(`\\nprecisa new ${repoName}`));\n console.log(chalk.dim(`profile: ${opts.profile}${opts.dryRun ? ' (dry-run)' : ''}`));\n console.log(chalk.dim(`target: ${targetDir}\\n`));\n\n const answers = opts.nonInteractive\n ? {\n commitScopes: (opts.scopes ?? 'docs,ci,deps')\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean),\n conductEmail: opts.conductEmail ?? 'conduct@precisa-saude.com.br',\n owner: opts.owner ?? 'Precisa-Saude',\n securityEmail: opts.securityEmail ?? 'security@precisa-saude.com.br',\n }\n : await prompts(\n [\n {\n initial: opts.owner ?? 'Precisa-Saude',\n message: 'GitHub owner (org or user):',\n name: 'owner',\n type: 'text',\n },\n {\n initial: opts.securityEmail ?? 'security@precisa-saude.com.br',\n message: 'Security contact email:',\n name: 'securityEmail',\n type: 'text',\n },\n {\n initial: opts.conductEmail ?? 'conduct@precisa-saude.com.br',\n message: 'Code-of-conduct contact email:',\n name: 'conductEmail',\n type: 'text',\n },\n {\n initial: opts.scopes ?? 'docs,ci,deps',\n message: 'Commit scopes (comma-separated):',\n name: 'commitScopes',\n separator: ',',\n type: 'list',\n },\n ],\n { onCancel: () => process.exit(1) },\n );\n\n const manifest: PrecisaManifest = {\n ...DEFAULT_MANIFEST_FIELDS,\n ...profile,\n commitScopes: answers.commitScopes,\n contactEmails: {\n conduct: answers.conductEmail,\n security: answers.securityEmail,\n },\n name: repoName,\n owner: answers.owner,\n };\n\n const spinner = ora('Rendering templates').start();\n try {\n if (!opts.dryRun) mkdirSync(targetDir, { recursive: true });\n\n const entries = loadTemplateManifest().filter((e) => isRequired(e.required_when, manifest));\n const context = tokenContext(manifest);\n\n let created = 0;\n let skipped = 0;\n\n for (const entry of entries) {\n const source = readTemplateSource(entry);\n const rendered = renderTokens(source, context);\n const outcome = applyTemplate({\n cwd: targetDir,\n dryRun: opts.dryRun,\n entry,\n rendered,\n });\n if (outcome.kind === 'create') created += 1;\n else if (outcome.kind === 'skip-exists') skipped += 1;\n else if (outcome.kind === 'error') {\n spinner.fail(`Failed on ${entry.target}`);\n console.error(chalk.red(outcome.message));\n process.exit(1);\n }\n }\n\n spinner.succeed(\n opts.dryRun\n ? `Would render ${created} file${created === 1 ? '' : 's'} (${skipped} skipped)`\n : `Rendered ${created} file${created === 1 ? '' : 's'} (${skipped} skipped)`,\n );\n\n if (opts.dryRun) return;\n\n writeManifest(targetDir, manifest);\n console.log(chalk.dim(` wrote .precisa.json`));\n\n const gitStep = ora('git init + pnpm install').start();\n try {\n execSync('git init --initial-branch=main', { cwd: targetDir, stdio: 'pipe' });\n execSync('pnpm install', { cwd: targetDir, stdio: 'pipe' });\n gitStep.succeed('git init + pnpm install complete');\n } catch (err) {\n gitStep.warn(\n `git/pnpm setup skipped: ${(err as Error).message}. Run manually in ${targetDir}.`,\n );\n }\n\n console.log(chalk.bold.green(`\\n✓ ${repoName} scaffolded at ${targetDir}`));\n console.log(chalk.dim('\\nNext:'));\n console.log(chalk.dim(` cd ${repoName}`));\n console.log(chalk.dim(` # start adding your code`));\n } catch (err) {\n spinner.fail((err as Error).message);\n process.exit(1);\n }\n}\n","import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\n\nimport type { MergeStrategy, TemplateEntry } from './templates.js';\n\nexport type ApplyOutcome =\n | { kind: 'create'; target: string; rendered: string }\n | { kind: 'update'; target: string; previous: string; rendered: string }\n | { kind: 'skip-identical'; target: string }\n | { kind: 'preserve'; target: string; current: string; rendered: string }\n | { kind: 'skip-exists'; target: string }\n | { kind: 'merge-json'; target: string; previous: string; rendered: string }\n | { kind: 'error'; target: string; message: string };\n\nexport interface ApplyOptions {\n /** Repo root to apply into. */\n cwd: string;\n /** When true, compute the outcome but do not write to disk. */\n dryRun: boolean;\n /** Template entry being applied. */\n entry: TemplateEntry;\n /** Rendered template content (post token substitution). */\n rendered: string;\n}\n\n/**\n * Apply a single template file to the target repo. Returns the outcome\n * so callers can print a per-file status row and, on dry-run, a diff.\n */\nexport function applyTemplate({ cwd, dryRun, entry, rendered }: ApplyOptions): ApplyOutcome {\n const targetPath = resolve(cwd, entry.target);\n const exists = existsSync(targetPath);\n\n if (!exists) {\n if (!dryRun) writeFile(targetPath, rendered, entry.executable === true);\n return { kind: 'create', rendered, target: entry.target };\n }\n\n const current = readFileSync(targetPath, 'utf-8');\n\n switch (entry.merge_strategy as MergeStrategy) {\n case 'overwrite': {\n if (current === rendered) {\n return { kind: 'skip-identical', target: entry.target };\n }\n if (!dryRun) writeFile(targetPath, rendered, entry.executable === true);\n return { kind: 'update', previous: current, rendered, target: entry.target };\n }\n case 'skip_if_exists': {\n return { kind: 'skip-exists', target: entry.target };\n }\n case 'preserve': {\n return { current, kind: 'preserve', rendered, target: entry.target };\n }\n case 'merge_json': {\n let merged: string;\n try {\n merged = mergeJson(current, rendered);\n } catch (err) {\n return {\n kind: 'error',\n message: `JSON merge failed: ${(err as Error).message}`,\n target: entry.target,\n };\n }\n if (current === merged) {\n return { kind: 'skip-identical', target: entry.target };\n }\n if (!dryRun) writeFile(targetPath, merged, entry.executable === true);\n return { kind: 'merge-json', previous: current, rendered: merged, target: entry.target };\n }\n default: {\n return {\n kind: 'error',\n message: `Unknown merge_strategy '${entry.merge_strategy}'`,\n target: entry.target,\n };\n }\n }\n}\n\nfunction writeFile(path: string, contents: string, executable: boolean): void {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, contents);\n if (executable) chmodSync(path, 0o755);\n}\n\n/**\n * Shallow 3-way-ish JSON merge — the current file wins on conflicts so\n * repo-local customizations aren't clobbered. Objects are merged\n * key-by-key; arrays and scalars are replaced entirely by the current\n * value when present (falls back to the template value).\n *\n * If parsing fails, throws so the caller can report the error.\n */\nexport function mergeJson(currentRaw: string, templateRaw: string): string {\n const current = JSON.parse(currentRaw) as unknown;\n const template = JSON.parse(templateRaw) as unknown;\n const merged = mergeValue(template, current);\n return `${JSON.stringify(merged, null, 2)}\\n`;\n}\n\nfunction mergeValue(template: unknown, current: unknown): unknown {\n if (current === undefined) return template;\n if (\n typeof template !== 'object' ||\n template === null ||\n Array.isArray(template) ||\n typeof current !== 'object' ||\n current === null ||\n Array.isArray(current)\n ) {\n // Scalars / arrays: current value wins (never clobber repo-local values).\n return current;\n }\n const out: Record<string, unknown> = {};\n const keys = new Set([\n ...Object.keys(template as Record<string, unknown>),\n ...Object.keys(current as Record<string, unknown>),\n ]);\n for (const k of keys) {\n out[k] = mergeValue(\n (template as Record<string, unknown>)[k],\n (current as Record<string, unknown>)[k],\n );\n }\n return out;\n}\n","import chalk from 'chalk';\n\nimport { colorDiff } from '../lib/diff.js';\nimport { type ApplyOutcome, applyTemplate } from '../lib/merge.js';\nimport { loadTemplateManifest, readTemplateSource, renderTokens } from '../lib/templates.js';\nimport { isRequired, loadManifest, tokenContext } from '../manifest.js';\n\nexport interface SyncOptions {\n dryRun: boolean;\n}\n\nexport async function runSync(opts: SyncOptions): Promise<void> {\n const cwd = process.cwd();\n console.log(chalk.bold.cyan(`\\nprecisa sync${opts.dryRun ? ' --dry-run' : ''}`));\n\n let manifest;\n try {\n manifest = loadManifest(cwd);\n } catch (err) {\n console.error(chalk.red(`\\n${(err as Error).message}`));\n console.error(\n chalk.dim('\\n Run `precisa new <repo>` in an empty directory to scaffold a new repo,'),\n );\n console.error(chalk.dim(' or create a `.precisa.json` manifest manually.'));\n process.exit(1);\n }\n\n const entries = loadTemplateManifest().filter((e) => isRequired(e.required_when, manifest));\n const context = tokenContext(manifest);\n\n const outcomes: ApplyOutcome[] = [];\n for (const entry of entries) {\n const source = readTemplateSource(entry);\n const rendered = renderTokens(source, context);\n outcomes.push(\n applyTemplate({\n cwd,\n dryRun: opts.dryRun,\n entry,\n rendered,\n }),\n );\n }\n\n console.log('');\n for (const o of outcomes) {\n printOutcome(o, opts.dryRun);\n }\n\n const summary = summarize(outcomes);\n console.log('');\n console.log(\n chalk.dim(\n `${summary.create} create, ${summary.update} update, ${summary.mergeJson} merge-json, ${summary.preserve} preserve, ${summary.skip} skip, ${summary.error} error`,\n ),\n );\n\n if (summary.error > 0) process.exit(1);\n}\n\ninterface Summary {\n create: number;\n error: number;\n mergeJson: number;\n preserve: number;\n skip: number;\n update: number;\n}\n\nfunction summarize(outcomes: ApplyOutcome[]): Summary {\n const s: Summary = { create: 0, error: 0, mergeJson: 0, preserve: 0, skip: 0, update: 0 };\n for (const o of outcomes) {\n switch (o.kind) {\n case 'create':\n s.create += 1;\n break;\n case 'update':\n s.update += 1;\n break;\n case 'merge-json':\n s.mergeJson += 1;\n break;\n case 'preserve':\n s.preserve += 1;\n break;\n case 'skip-identical':\n case 'skip-exists':\n s.skip += 1;\n break;\n case 'error':\n s.error += 1;\n break;\n }\n }\n return s;\n}\n\nfunction printOutcome(o: ApplyOutcome, dryRun: boolean): void {\n const prefix = dryRun ? '(dry-run) ' : '';\n switch (o.kind) {\n case 'create':\n console.log(`${chalk.green('+')} ${prefix}create ${o.target}`);\n return;\n case 'update':\n console.log(`${chalk.yellow('~')} ${prefix}update ${o.target}`);\n if (dryRun) console.log(indent(colorDiff(o.target, o.previous, o.rendered)));\n return;\n case 'merge-json':\n console.log(`${chalk.yellow('~')} ${prefix}merge ${o.target}`);\n if (dryRun) console.log(indent(colorDiff(o.target, o.previous, o.rendered)));\n return;\n case 'preserve':\n console.log(\n `${chalk.blue('i')} ${prefix}preserve ${o.target} (template differs; not written)`,\n );\n if (dryRun && o.current !== o.rendered) {\n console.log(indent(colorDiff(o.target, o.current, o.rendered)));\n }\n return;\n case 'skip-identical':\n console.log(`${chalk.dim('=')} ${prefix}unchanged ${o.target}`);\n return;\n case 'skip-exists':\n console.log(`${chalk.dim('s')} ${prefix}skip ${o.target} (already exists)`);\n return;\n case 'error':\n console.log(`${chalk.red('!')} ${prefix}error ${o.target}: ${o.message}`);\n return;\n }\n}\n\nfunction indent(text: string): string {\n return text\n .split('\\n')\n .map((l) => ` ${l}`)\n .join('\\n');\n}\n","import chalk from 'chalk';\nimport { createPatch } from 'diff';\n\n/**\n * Format a unified diff with ANSI colors for terminal display.\n * Skips the `@@ hunk @@` metadata lines for a cleaner look.\n */\nexport function colorDiff(filename: string, previous: string, next: string): string {\n const patch = createPatch(filename, previous, next, '', '');\n const lines = patch.split('\\n');\n const out: string[] = [];\n for (const line of lines) {\n if (line.startsWith('---') || line.startsWith('+++')) continue;\n if (line.startsWith('@@')) {\n out.push(chalk.cyan(line));\n continue;\n }\n if (line.startsWith('+')) {\n out.push(chalk.green(line));\n continue;\n }\n if (line.startsWith('-')) {\n out.push(chalk.red(line));\n continue;\n }\n out.push(line);\n }\n return out.join('\\n');\n}\n"],"mappings":"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","names":["existsSync","readFileSync","resolve","resolve","resolve","readFileSync","resolve","resolve","existsSync","readFileSync","existsSync","mkdirSync","resolve","chalk","existsSync","readFileSync","writeFileSync","dirname","resolve","resolve","existsSync","chalk","mkdirSync","chalk","chalk","chalk"]}
@@ -19,6 +19,10 @@ on:
19
19
  description: 'Output directory to deploy (default: site/dist)'
20
20
  type: string
21
21
  default: 'site/dist'
22
+ site_source_path:
23
+ description: 'Path prefix treated as site source files for change detection (default: site/)'
24
+ type: string
25
+ default: 'site/'
22
26
 
23
27
  jobs:
24
28
  build-site:
@@ -57,7 +61,8 @@ jobs:
57
61
  );
58
62
  filenames = pages.flatMap(p => (p.files ?? []).map(f => f.filename));
59
63
  }
60
- const siteChanged = filenames.some(f => f.startsWith('site/'));
64
+ const sourcePath = `${{ inputs.site_source_path }}`;
65
+ const siteChanged = filenames.some(f => f.startsWith(sourcePath));
61
66
  core.setOutput('site_changed', siteChanged ? 'true' : 'false');
62
67
 
63
68
  - uses: actions/checkout@v6
@@ -82,5 +82,6 @@ jobs:
82
82
  with:
83
83
  project_name: '{{SITE_PROJECT_NAME}}'
84
84
  site_filter: '{{SITE_FILTER}}'
85
+ site_source_path: '{{SITE_SOURCE_PATH}}'
85
86
  secrets: inherit
86
87
  # {{/if}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@precisa-saude/cli",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "Bootstrap and sync Precisa Saúde repositories — the `precisa` CLI.",
5
5
  "keywords": [
6
6
  "cli",
@@ -45,7 +45,7 @@
45
45
  "@types/prompts": "^2.4.9",
46
46
  "tsup": "^8.3.5",
47
47
  "typescript": "~5.7.3",
48
- "@precisa-saude/tsconfig": "1.7.0"
48
+ "@precisa-saude/tsconfig": "1.8.0"
49
49
  },
50
50
  "engines": {
51
51
  "node": ">=22.0.0"