@viberails/config 0.5.5 → 0.6.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/index.cjs CHANGED
@@ -185,6 +185,9 @@ function mapStructure(scanResult) {
185
185
  }
186
186
  if (structure.testPattern) {
187
187
  config.testPattern = structure.testPattern.value;
188
+ } else {
189
+ const isTypeScript = scanResult.stack.language.name === "typescript";
190
+ config.testPattern = isTypeScript ? "*.test.ts" : "*.test.js";
188
191
  }
189
192
  return config;
190
193
  }
@@ -807,7 +810,8 @@ var packageItemSchema = {
807
810
  maxTestFileLines: { type: "number" },
808
811
  testCoverage: { type: "number" },
809
812
  enforceNaming: { type: "boolean" },
810
- enforceBoundaries: { type: "boolean" }
813
+ enforceBoundaries: { type: "boolean" },
814
+ enforceMissingTests: { type: "boolean" }
811
815
  },
812
816
  additionalProperties: false
813
817
  },
@@ -954,7 +958,7 @@ var configSchema = {
954
958
  };
955
959
 
956
960
  // src/index.ts
957
- var VERSION = "0.5.5";
961
+ var VERSION = "0.6.0";
958
962
  // Annotate the CommonJS export names for ESM import in node:
959
963
  0 && (module.exports = {
960
964
  BUILTIN_IGNORE,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/generate-config.ts","../src/defaults.ts","../src/generate-packages.ts","../src/infer-coverage-command.ts","../src/compact-config.ts","../src/load-config.ts","../src/merge-config.ts","../src/schema-parts.ts","../src/schema.ts"],"sourcesContent":["declare const __PACKAGE_VERSION__: string;\nexport const VERSION: string = __PACKAGE_VERSION__;\n\nexport { compactConfig, expandDefaults } from './compact-config.js';\nexport { BUILTIN_IGNORE, DEFAULT_IGNORE, DEFAULT_RULES } from './defaults.js';\nexport { generateConfig } from './generate-config.js';\nexport { inferCoverageCommand } from './infer-coverage-command.js';\nexport { loadConfig, loadConfigSafe } from './load-config.js';\nexport { mergeConfig } from './merge-config.js';\nexport { configSchema } from './schema.js';\n","import * as path from 'node:path';\nimport type {\n ConfigConventions,\n ConfigMeta,\n ConfigStack,\n ConfigStructure,\n ConventionMeta,\n DetectedConvention,\n DirectoryRole,\n PackageConfig,\n ScanResult,\n StackItem,\n ViberailsConfig,\n} from '@viberails/types';\nimport { DEFAULT_IGNORE, DEFAULT_RULES } from './defaults.js';\nimport { generatePackages } from './generate-packages.js';\nimport { inferCoverageCommand } from './infer-coverage-command.js';\n\n/**\n * Format a StackItem as a config string: `\"name@version\"` or `\"name\"`.\n */\nexport function formatStackItem(item: StackItem): string {\n return item.version ? `${item.name}@${item.version}` : item.name;\n}\n\n/**\n * Map DetectedStack → ConfigStack by formatting each StackItem.\n */\nexport function mapStack(scanResult: ScanResult): ConfigStack {\n const { stack } = scanResult;\n const config: ConfigStack = {\n language: formatStackItem(stack.language),\n packageManager: formatStackItem(stack.packageManager),\n };\n\n if (stack.framework) config.framework = formatStackItem(stack.framework);\n if (stack.styling) config.styling = formatStackItem(stack.styling);\n if (stack.backend) config.backend = formatStackItem(stack.backend);\n if (stack.orm) config.orm = formatStackItem(stack.orm);\n if (stack.linter) config.linter = formatStackItem(stack.linter);\n if (stack.formatter) config.formatter = formatStackItem(stack.formatter);\n if (stack.testRunner) config.testRunner = formatStackItem(stack.testRunner);\n\n return config;\n}\n\n/** Directory roles that map to ConfigStructure fields. */\nconst ROLE_TO_FIELD: Partial<Record<DirectoryRole, keyof ConfigStructure>> = {\n pages: 'pages',\n components: 'components',\n hooks: 'hooks',\n utils: 'utils',\n types: 'types',\n tests: 'tests',\n};\n\n/**\n * Map DetectedStructure → ConfigStructure by finding the first directory\n * for each known role.\n */\nexport function mapStructure(scanResult: ScanResult): ConfigStructure {\n const { structure } = scanResult;\n const config: ConfigStructure = {};\n\n if (structure.srcDir) {\n config.srcDir = structure.srcDir;\n }\n\n for (const dir of structure.directories) {\n const field = ROLE_TO_FIELD[dir.role];\n if (field && config[field] === undefined) {\n (config as Record<string, string>)[field] = dir.path;\n }\n }\n\n if (structure.testPattern) {\n config.testPattern = structure.testPattern.value;\n }\n\n return config;\n}\n\n/** Convention keys from ScanResult that map to ConfigConventions fields. */\nexport const CONVENTION_KEYS: (keyof ConfigConventions)[] = [\n 'fileNaming',\n 'componentNaming',\n 'hookNaming',\n 'importAlias',\n];\n\n/**\n * Map scanner conventions → ConfigConventions as plain strings.\n * Low-confidence conventions are omitted.\n * Returns both the plain-string conventions and the metadata for _meta.\n */\nfunction mapConventions(scanResult: ScanResult): {\n conventions: ConfigConventions;\n meta: Record<string, ConventionMeta>;\n} {\n const conventions: ConfigConventions = {};\n const meta: Record<string, ConventionMeta> = {};\n\n for (const key of CONVENTION_KEYS) {\n const detected = scanResult.conventions[key];\n if (detected && detected.confidence !== 'low') {\n conventions[key] = detected.value;\n meta[key] = {\n value: detected.value,\n confidence: detected.confidence,\n consistency: detected.consistency,\n };\n }\n }\n\n return { conventions, meta };\n}\n\n/**\n * Build _meta for a single package's conventions.\n */\nexport function buildConventionMeta(\n conventions: Record<string, DetectedConvention>,\n): Record<string, ConventionMeta> {\n const meta: Record<string, ConventionMeta> = {};\n for (const key of CONVENTION_KEYS) {\n const detected = conventions[key];\n if (detected && detected.confidence !== 'low') {\n meta[key] = {\n value: detected.value,\n confidence: detected.confidence,\n consistency: detected.consistency,\n };\n }\n }\n return meta;\n}\n\n/**\n * Generate a ViberailsConfig from scan results.\n *\n * Produces the packages-first config format: all config lives in `packages[]`.\n * Single projects get one package with `path: \".\"`.\n * Monorepos get one package per workspace package.\n *\n * @param scanResult - The output of scanning a project\n * @returns A complete ViberailsConfig ready to be written as JSON\n */\nexport function generateConfig(scanResult: ScanResult): ViberailsConfig {\n const projectName = path.basename(scanResult.root);\n const { conventions, meta } = mapConventions(scanResult);\n\n // Build the root package\n const rootPackage: PackageConfig = {\n name: projectName,\n path: '.',\n stack: mapStack(scanResult),\n structure: mapStructure(scanResult),\n conventions,\n };\n\n const _meta: ConfigMeta = {\n lastSync: new Date().toISOString(),\n packages: {\n '.': { conventions: Object.keys(meta).length > 0 ? meta : undefined },\n },\n };\n\n const config: ViberailsConfig = {\n $schema: 'https://viberails.sh/schema/v1.json',\n version: 1,\n name: projectName,\n rules: { ...DEFAULT_RULES },\n ignore: [...DEFAULT_IGNORE],\n packages: [rootPackage],\n _meta,\n };\n\n // Infer coverage command from detected test runner\n const testRunner = scanResult.stack.testRunner;\n const coverageCommand = inferCoverageCommand(\n testRunner ? formatStackItem(testRunner) : undefined,\n );\n if (coverageCommand) {\n config.defaults = { coverage: { command: coverageCommand } };\n }\n\n // Monorepo: generate per-package configs\n if (scanResult.workspace) {\n const packages = generatePackages(scanResult);\n if (packages) {\n config.packages = packages;\n\n // If packages have different test runners, set per-package coverage\n // commands instead of a global default (which would be wrong for some).\n const runners = new Set(\n packages.map((p) => p.stack?.testRunner?.split('@')[0]).filter(Boolean),\n );\n if (runners.size > 1) {\n delete config.defaults?.coverage?.command;\n for (const pkg of packages) {\n const pkgCommand = inferCoverageCommand(pkg.stack?.testRunner);\n if (pkgCommand) {\n pkg.coverage = { ...pkg.coverage, command: pkgCommand };\n }\n }\n }\n // Rebuild _meta for all packages\n const pkgMeta: Record<string, { conventions?: Record<string, ConventionMeta> }> = {};\n for (const pkg of scanResult.packages) {\n const convMeta = buildConventionMeta(pkg.conventions);\n if (Object.keys(convMeta).length > 0) {\n pkgMeta[pkg.relativePath] = { conventions: convMeta };\n }\n }\n if (Object.keys(pkgMeta).length > 0) {\n _meta.packages = pkgMeta;\n }\n }\n config.boundaries = { deny: {} };\n }\n\n return config;\n}\n","import type { ConfigRules } from '@viberails/types';\n\n/**\n * Default rule thresholds and toggles for a new viberails config.\n * These values are intentionally conservative to build trust on first run.\n */\nexport const DEFAULT_RULES: ConfigRules = {\n maxFileLines: 300,\n maxTestFileLines: 0,\n testCoverage: 80,\n enforceNaming: true,\n enforceBoundaries: false,\n enforceMissingTests: true,\n};\n\n/**\n * Default project-specific ignore patterns for a new config.\n * Empty — universal patterns live in BUILTIN_IGNORE and are applied at check-time.\n */\nexport const DEFAULT_IGNORE: string[] = [];\n\n/**\n * Universal ignore patterns applied at check-time.\n * These are never written to config — they are always applied implicitly.\n */\nexport const BUILTIN_IGNORE: string[] = [\n '**/*.d.ts',\n '**/*.min.js',\n '**/*.min.cjs',\n '**/*.umd.js',\n '**/*.bundle.js',\n 'dist/**',\n 'node_modules/**',\n 'build/**',\n '.next/**',\n '.expo/**',\n '.output/**',\n '.svelte-kit/**',\n '.turbo/**',\n 'coverage/**',\n '**/public/**',\n '**/vendor/**',\n '.viberails/**',\n '**/generated/**',\n '**/__generated__/**',\n];\n","import type { ConfigConventions, ConfigStack, PackageConfig, ScanResult } from '@viberails/types';\nimport { CONVENTION_KEYS, formatStackItem, mapStructure } from './generate-config.js';\n\n/**\n * Build a full ConfigStack for a single package scan result.\n */\nfunction buildPackageStack(pkg: ScanResult['packages'][number]): ConfigStack {\n const config: ConfigStack = {\n language: formatStackItem(pkg.stack.language),\n packageManager: formatStackItem(pkg.stack.packageManager),\n };\n\n if (pkg.stack.framework) config.framework = formatStackItem(pkg.stack.framework);\n if (pkg.stack.styling) config.styling = formatStackItem(pkg.stack.styling);\n if (pkg.stack.backend) config.backend = formatStackItem(pkg.stack.backend);\n if (pkg.stack.orm) config.orm = formatStackItem(pkg.stack.orm);\n if (pkg.stack.linter) config.linter = formatStackItem(pkg.stack.linter);\n if (pkg.stack.formatter) config.formatter = formatStackItem(pkg.stack.formatter);\n if (pkg.stack.testRunner) config.testRunner = formatStackItem(pkg.stack.testRunner);\n\n return config;\n}\n\n/**\n * Build ConfigConventions as plain strings, omitting low-confidence entries.\n */\nfunction buildPackageConventions(\n pkgConventions: Record<string, import('@viberails/types').DetectedConvention>,\n): ConfigConventions {\n const config: ConfigConventions = {};\n\n for (const key of CONVENTION_KEYS) {\n const detected = pkgConventions[key];\n if (detected && detected.confidence !== 'low') {\n config[key] = detected.value;\n }\n }\n\n return config;\n}\n\n/**\n * Generate self-contained per-package configs for packages in a monorepo.\n * Each PackageConfig has its own full stack, structure, and conventions.\n *\n * Returns undefined for single-package projects.\n */\nexport function generatePackages(scanResult: ScanResult): PackageConfig[] | undefined {\n if (!scanResult.packages || scanResult.packages.length <= 1) return undefined;\n\n const packages: PackageConfig[] = [];\n\n for (const pkg of scanResult.packages) {\n // Build a temporary ScanResult-like object for mapStructure\n const pkgScanResult = {\n root: pkg.root,\n stack: pkg.stack,\n structure: pkg.structure,\n conventions: pkg.conventions,\n statistics: pkg.statistics,\n } as ScanResult;\n\n const packageConfig: PackageConfig = {\n name: pkg.name,\n path: pkg.relativePath,\n stack: buildPackageStack(pkg),\n structure: mapStructure(pkgScanResult),\n conventions: buildPackageConventions(pkg.conventions),\n };\n\n if (pkg.typesOnly) {\n packageConfig.rules = { testCoverage: 0 };\n }\n\n packages.push(packageConfig);\n }\n\n return packages.length > 0 ? packages : undefined;\n}\n","/**\n * Infer a coverage command from the detected test runner string.\n *\n * Used during `init` to store the inferred command in config so that\n * `check` can use it explicitly. Does not verify binary availability —\n * the command is stored as a suggestion for the user to review.\n *\n * @param testRunner - Test runner string from config (e.g. \"vitest@4\", \"jest@29\")\n * @returns Shell command string, or undefined if the runner is unsupported\n */\nexport function inferCoverageCommand(testRunner: string | undefined): string | undefined {\n if (!testRunner) return undefined;\n const runner = testRunner.split('@')[0];\n if (runner === 'vitest') {\n return 'npx vitest run --coverage --coverage.reporter=json-summary';\n }\n if (runner === 'jest') {\n return 'npx jest --coverage --coverageReporters=json-summary';\n }\n return undefined;\n}\n","import type {\n ConfigConventions,\n ConfigCoverage,\n ConfigDefaults,\n ConfigStack,\n ConfigStructure,\n ViberailsConfig,\n} from '@viberails/types';\nimport { CONVENTION_KEYS } from './generate-config.js';\n\n/** Stack field keys for comparison and extraction. */\nexport const STACK_KEYS: (keyof ConfigStack)[] = [\n 'language',\n 'packageManager',\n 'framework',\n 'styling',\n 'backend',\n 'orm',\n 'linter',\n 'formatter',\n 'testRunner',\n];\n\n/** Structure field keys for comparison and extraction. */\nexport const STRUCTURE_KEYS: (keyof ConfigStructure)[] = [\n 'srcDir',\n 'pages',\n 'components',\n 'hooks',\n 'utils',\n 'types',\n 'tests',\n 'testPattern',\n];\n\n/**\n * Extract shared values from packages into defaults and strip them from packages.\n * Only extracts values that are identical across ALL packages.\n * Strips empty objects from packages for clean JSON output.\n */\nexport function compactConfig(config: ViberailsConfig): ViberailsConfig {\n const pkgs = config.packages ?? [];\n\n const defaults: ConfigDefaults = {};\n\n // Start with copies; merge any existing defaults into each package first\n // so the extraction logic below works uniformly for 1 or N packages.\n const packages = pkgs.map((p) => {\n const copy = { ...p };\n if (config.defaults?.coverage) {\n copy.coverage = { ...config.defaults.coverage, ...(copy.coverage ?? {}) };\n }\n if (config.defaults?.stack) {\n copy.stack = { ...config.defaults.stack, ...(copy.stack ?? {}) } as ConfigStack;\n }\n if (config.defaults?.structure) {\n copy.structure = { ...config.defaults.structure, ...(copy.structure ?? {}) };\n }\n if (config.defaults?.conventions) {\n copy.conventions = { ...config.defaults.conventions, ...(copy.conventions ?? {}) };\n }\n return copy;\n });\n\n // For multi-package configs, extract shared values into defaults.\n // Single-package configs keep everything on the package (no defaults needed).\n if (packages.length <= 1) {\n // Strip empty objects from the single package\n for (const pkg of packages) {\n if (pkg.stack && Object.keys(pkg.stack).length === 0) delete pkg.stack;\n if (pkg.structure && Object.keys(pkg.structure).length === 0) delete pkg.structure;\n if (pkg.conventions && Object.keys(pkg.conventions).length === 0) delete pkg.conventions;\n if (pkg.coverage && Object.keys(pkg.coverage).length === 0) delete pkg.coverage;\n }\n const { defaults: _d, ...rest } = config;\n return { ...rest, packages };\n }\n\n // Extract shared stack fields\n const sharedStack: Partial<ConfigStack> = {};\n for (const key of STACK_KEYS) {\n const values = packages.map((p) => (p.stack ?? ({} as Partial<ConfigStack>))[key]);\n if (values[0] !== undefined && values.every((v) => v === values[0])) {\n sharedStack[key] = values[0] as string;\n }\n }\n if (Object.keys(sharedStack).length > 0) {\n defaults.stack = sharedStack;\n for (const pkg of packages) {\n const pkgStack = (pkg.stack ?? {}) as Partial<ConfigStack>;\n const sparse: Partial<ConfigStack> = {};\n for (const key of STACK_KEYS) {\n if (pkgStack[key] !== undefined && pkgStack[key] !== sharedStack[key]) {\n sparse[key] = pkgStack[key] as string;\n }\n }\n pkg.stack = sparse as ConfigStack;\n }\n }\n\n // Extract shared structure fields\n const sharedStructure: Partial<ConfigStructure> = {};\n for (const key of STRUCTURE_KEYS) {\n const values = packages.map((p) => p.structure?.[key]);\n const first = values[0];\n if (first !== undefined && values.every((v) => JSON.stringify(v) === JSON.stringify(first))) {\n (sharedStructure as Record<string, unknown>)[key] = first;\n }\n }\n if (Object.keys(sharedStructure).length > 0) {\n defaults.structure = sharedStructure;\n for (const pkg of packages) {\n const pkgStructure = pkg.structure ?? {};\n const sparse: Partial<ConfigStructure> = {};\n for (const key of STRUCTURE_KEYS) {\n const val = pkgStructure[key];\n if (val !== undefined && JSON.stringify(val) !== JSON.stringify(sharedStructure[key])) {\n (sparse as Record<string, unknown>)[key] = val;\n }\n }\n pkg.structure = sparse as ConfigStructure;\n }\n }\n\n // Extract shared conventions\n const sharedConventions: ConfigConventions = {};\n for (const key of CONVENTION_KEYS) {\n const values = packages.map((p) => p.conventions?.[key]);\n if (values[0] !== undefined && values.every((v) => v === values[0])) {\n sharedConventions[key] = values[0];\n }\n }\n\n // Extract shared coverage settings\n const sharedCoverage: ConfigCoverage = {};\n const coverageKeys: (keyof ConfigCoverage)[] = ['command', 'summaryPath'];\n for (const key of coverageKeys) {\n const values = packages.map((p) => p.coverage?.[key]);\n if (values[0] !== undefined && values.every((v) => v === values[0])) {\n sharedCoverage[key] = values[0];\n }\n }\n if (Object.keys(sharedCoverage).length > 0) {\n defaults.coverage = sharedCoverage;\n for (const pkg of packages) {\n const pkgCoverage = pkg.coverage ?? {};\n const sparse: ConfigCoverage = {};\n for (const key of coverageKeys) {\n if (pkgCoverage[key] !== undefined && pkgCoverage[key] !== sharedCoverage[key]) {\n sparse[key] = pkgCoverage[key];\n }\n }\n pkg.coverage = sparse;\n }\n }\n if (Object.keys(sharedConventions).length > 0) {\n defaults.conventions = sharedConventions;\n for (const pkg of packages) {\n const pkgConventions = pkg.conventions ?? {};\n const sparse: ConfigConventions = {};\n for (const key of CONVENTION_KEYS) {\n if (pkgConventions[key] !== undefined && pkgConventions[key] !== sharedConventions[key]) {\n sparse[key] = pkgConventions[key];\n }\n }\n pkg.conventions = sparse;\n }\n }\n\n // Strip empty objects from packages\n for (const pkg of packages) {\n if (pkg.stack && Object.keys(pkg.stack).length === 0) {\n delete pkg.stack;\n }\n if (pkg.structure && Object.keys(pkg.structure).length === 0) {\n delete pkg.structure;\n }\n if (pkg.conventions && Object.keys(pkg.conventions).length === 0) {\n delete pkg.conventions;\n }\n if (pkg.coverage && Object.keys(pkg.coverage).length === 0) {\n delete pkg.coverage;\n }\n }\n\n // Reconstruct with explicit key ordering so JSON output is readable:\n // $schema, version, name, rules, ignore, boundaries, defaults, packages, _meta\n const result: ViberailsConfig = {\n ...(config.$schema ? { $schema: config.$schema } : {}),\n version: config.version,\n name: config.name,\n rules: config.rules,\n ...(config.ignore && config.ignore.length > 0 ? { ignore: config.ignore } : {}),\n ...(config.boundaries ? { boundaries: config.boundaries } : {}),\n ...(Object.keys(defaults).length > 0 ? { defaults } : {}),\n packages,\n ...(config._meta ? { _meta: config._meta } : {}),\n };\n return result;\n}\n\n/**\n * Expand defaults into each package, producing fully self-contained packages.\n * Inverse of compactConfig. Ensures every package has stack, structure,\n * and conventions (even as empty objects) and config.ignore defaults to [].\n */\nexport function expandDefaults(config: ViberailsConfig): ViberailsConfig {\n const defaults = config.defaults;\n\n const packages = config.packages.map((pkg) => {\n const expanded = { ...pkg };\n\n // Merge defaults into package fields, or initialize to empty objects\n expanded.stack = { ...(defaults?.stack ?? {}), ...(pkg.stack ?? {}) } as ConfigStack;\n expanded.structure = { ...(defaults?.structure ?? {}), ...(pkg.structure ?? {}) };\n expanded.conventions = { ...(defaults?.conventions ?? {}), ...(pkg.conventions ?? {}) };\n const mergedCoverage = { ...(defaults?.coverage ?? {}), ...(pkg.coverage ?? {}) };\n if (Object.keys(mergedCoverage).length > 0) {\n expanded.coverage = mergedCoverage;\n } else {\n delete expanded.coverage;\n }\n\n return expanded;\n });\n\n // Ensure ignore defaults to []\n const ignore = config.ignore ?? [];\n\n // Return without defaults — packages are now self-contained\n const { defaults: _d, ...rest } = config;\n return { ...rest, ignore, packages };\n}\n","import * as fs from 'node:fs/promises';\nimport type { ViberailsConfig } from '@viberails/types';\nimport { expandDefaults } from './compact-config.js';\n\n/**\n * Validate that a parsed object has the required ViberailsConfig fields\n * and that their types are correct.\n * Throws a descriptive error if validation fails.\n */\nfunction validateConfig(parsed: Record<string, unknown>, configPath: string): void {\n const errors: string[] = [];\n\n // Required top-level fields\n const required = ['version', 'name', 'packages', 'rules'] as const;\n const missing = required.filter((field) => parsed[field] === undefined);\n if (missing.length > 0) {\n throw new Error(\n `Invalid viberails config at ${configPath}: missing required field(s): ${missing.join(', ')}`,\n );\n }\n\n // Type checks\n if (typeof parsed.version !== 'number') {\n errors.push('\"version\" must be a number');\n } else if (parsed.version !== 1) {\n errors.push('\"version\" must be 1');\n }\n if (typeof parsed.name !== 'string') errors.push('\"name\" must be a string');\n // Packages validation\n if (!Array.isArray(parsed.packages)) {\n errors.push('\"packages\" must be an array');\n } else if (parsed.packages.length === 0) {\n errors.push('\"packages\" must contain at least one package');\n } else {\n for (let i = 0; i < parsed.packages.length; i++) {\n const pkg = parsed.packages[i] as Record<string, unknown>;\n if (typeof pkg.name !== 'string') errors.push(`\"packages[${i}].name\" must be a string`);\n if (typeof pkg.path !== 'string') errors.push(`\"packages[${i}].path\" must be a string`);\n if (pkg.coverage !== undefined) {\n if (typeof pkg.coverage !== 'object' || pkg.coverage === null) {\n errors.push(`\"packages[${i}].coverage\" must be an object`);\n } else {\n const coverage = pkg.coverage as Record<string, unknown>;\n if (coverage.command !== undefined && typeof coverage.command !== 'string') {\n errors.push(`\"packages[${i}].coverage.command\" must be a string`);\n }\n if (coverage.summaryPath !== undefined && typeof coverage.summaryPath !== 'string') {\n errors.push(`\"packages[${i}].coverage.summaryPath\" must be a string`);\n }\n }\n }\n }\n }\n\n // Rules validation\n if (typeof parsed.rules !== 'object' || parsed.rules === null) {\n errors.push('\"rules\" must be an object');\n } else {\n const rules = parsed.rules as Record<string, unknown>;\n if (typeof rules.maxFileLines !== 'number')\n errors.push('\"rules.maxFileLines\" must be a number');\n else if (rules.maxFileLines < 0) errors.push('\"rules.maxFileLines\" must be >= 0');\n if (rules.maxTestFileLines !== undefined) {\n if (typeof rules.maxTestFileLines !== 'number') {\n errors.push('\"rules.maxTestFileLines\" must be a number');\n } else if (rules.maxTestFileLines < 0) {\n errors.push('\"rules.maxTestFileLines\" must be >= 0');\n }\n }\n if (typeof rules.testCoverage !== 'number')\n errors.push('\"rules.testCoverage\" must be a number');\n else if (rules.testCoverage < 0 || rules.testCoverage > 100)\n errors.push('\"rules.testCoverage\" must be between 0 and 100');\n if (typeof rules.enforceNaming !== 'boolean')\n errors.push('\"rules.enforceNaming\" must be a boolean');\n if (typeof rules.enforceBoundaries !== 'boolean')\n errors.push('\"rules.enforceBoundaries\" must be a boolean');\n }\n\n // Ignore validation\n if (parsed.ignore !== undefined && !Array.isArray(parsed.ignore)) {\n errors.push('\"ignore\" must be an array');\n }\n\n // Defaults validation\n if (parsed.defaults !== undefined) {\n if (typeof parsed.defaults !== 'object' || parsed.defaults === null) {\n errors.push('\"defaults\" must be an object');\n } else {\n const defaults = parsed.defaults as Record<string, unknown>;\n if (defaults.coverage !== undefined) {\n if (typeof defaults.coverage !== 'object' || defaults.coverage === null) {\n errors.push('\"defaults.coverage\" must be an object');\n } else {\n const coverage = defaults.coverage as Record<string, unknown>;\n if (coverage.command !== undefined && typeof coverage.command !== 'string') {\n errors.push('\"defaults.coverage.command\" must be a string');\n }\n if (coverage.summaryPath !== undefined && typeof coverage.summaryPath !== 'string') {\n errors.push('\"defaults.coverage.summaryPath\" must be a string');\n }\n }\n }\n }\n }\n\n if (errors.length > 0) {\n throw new Error(`Invalid viberails config at ${configPath}: ${errors.join('; ')}`);\n }\n}\n\n/**\n * Load and parse a viberails config file.\n *\n * Reads the JSON file at the given path, validates that it contains\n * the required fields (version, name, packages, rules), expands\n * defaults into packages, and returns the parsed config.\n *\n * @param configPath - Absolute or relative path to viberails.config.json\n * @returns The parsed ViberailsConfig with defaults expanded\n * @throws If the file doesn't exist, contains invalid JSON, or is missing required fields\n */\nexport async function loadConfig(configPath: string): Promise<ViberailsConfig> {\n let raw: string;\n try {\n raw = await fs.readFile(configPath, 'utf-8');\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') {\n throw new Error(`Config file not found: ${configPath}. Run \"npx viberails\" to generate one.`);\n }\n throw new Error(`Failed to read config file at ${configPath}: ${(err as Error).message}`);\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n throw new Error(`Invalid JSON in config file at ${configPath}. Check for syntax errors.`);\n }\n\n validateConfig(parsed, configPath);\n\n // Apply defaults for optional fields added after initial release\n const rules = parsed.rules as Record<string, unknown>;\n if (rules.maxTestFileLines === undefined) {\n rules.maxTestFileLines = 0;\n }\n if (rules.enforceMissingTests === undefined) {\n rules.enforceMissingTests = true;\n }\n\n // Default ignore to [] if missing\n if (parsed.ignore === undefined) {\n parsed.ignore = [];\n }\n\n // Safe to cast: validateConfig has verified all required fields and types\n let config = parsed as unknown as ViberailsConfig;\n\n // Expand defaults into packages so they are self-contained\n config = expandDefaults(config);\n\n return config;\n}\n\n/**\n * Safely load a viberails config file, returning null on any error.\n *\n * Used by the CLI for \"does config already exist?\" checks where\n * failure is an expected case, not an error.\n *\n * @param configPath - Absolute or relative path to viberails.config.json\n * @returns The parsed ViberailsConfig, or null if loading fails\n */\nexport async function loadConfigSafe(configPath: string): Promise<ViberailsConfig | null> {\n try {\n return await loadConfig(configPath);\n } catch {\n return null;\n }\n}\n","import type {\n ConfigConventions,\n ConfigStack,\n ConfigStructure,\n ConventionMeta,\n PackageConfig,\n ScanResult,\n ViberailsConfig,\n} from '@viberails/types';\nimport { CONVENTION_KEYS, generateConfig } from './generate-config.js';\n\n/**\n * Merge stack: keep existing values, fill in undefined fields from fresh scan.\n */\nfunction mergeStack(existing: ConfigStack, fresh: ConfigStack): ConfigStack {\n return {\n language: existing.language,\n packageManager: existing.packageManager,\n framework: existing.framework ?? fresh.framework,\n styling: existing.styling ?? fresh.styling,\n backend: existing.backend ?? fresh.backend,\n orm: existing.orm ?? fresh.orm,\n linter: existing.linter ?? fresh.linter,\n formatter: existing.formatter ?? fresh.formatter,\n testRunner: existing.testRunner ?? fresh.testRunner,\n };\n}\n\n/**\n * Merge structure: keep existing values, fill in undefined fields from fresh scan.\n */\nfunction mergeStructure(existing: ConfigStructure, fresh: ConfigStructure): ConfigStructure {\n return {\n srcDir: existing.srcDir ?? fresh.srcDir,\n pages: existing.pages ?? fresh.pages,\n components: existing.components ?? fresh.components,\n hooks: existing.hooks ?? fresh.hooks,\n utils: existing.utils ?? fresh.utils,\n types: existing.types ?? fresh.types,\n tests: existing.tests ?? fresh.tests,\n testPattern: existing.testPattern ?? fresh.testPattern,\n };\n}\n\n/**\n * Merge conventions: keep all existing values, add new ones from fresh scan.\n * New conventions are marked with `detected: true` in _meta.\n */\nfunction mergeConventions(\n existing: ConfigConventions,\n fresh: ConfigConventions,\n existingMeta: Record<string, ConventionMeta> | undefined,\n freshMeta: Record<string, ConventionMeta> | undefined,\n): { conventions: ConfigConventions; meta: Record<string, ConventionMeta> } {\n const conventions: ConfigConventions = { ...existing };\n const meta: Record<string, ConventionMeta> = { ...(existingMeta ?? {}) };\n\n for (const key of CONVENTION_KEYS) {\n if (existing[key] === undefined && fresh[key] !== undefined) {\n conventions[key] = fresh[key];\n // Mark as newly detected in meta\n if (freshMeta?.[key]) {\n meta[key] = { ...freshMeta[key], detected: true };\n }\n } else if (existing[key] !== undefined && freshMeta?.[key]) {\n // Update meta with latest scan data but preserve existing convention value\n meta[key] = { ...freshMeta[key], value: freshMeta[key].value };\n }\n }\n\n return { conventions, meta };\n}\n\n/**\n * Merge a single package config, preserving existing values and adding fresh detections.\n */\nfunction mergePackage(\n existing: PackageConfig,\n fresh: PackageConfig,\n existingMeta: Record<string, ConventionMeta> | undefined,\n freshMeta: Record<string, ConventionMeta> | undefined,\n): { pkg: PackageConfig; meta: Record<string, ConventionMeta> } {\n const { conventions, meta } = mergeConventions(\n existing.conventions ?? {},\n fresh.conventions ?? {},\n existingMeta,\n freshMeta,\n );\n\n return {\n pkg: {\n ...existing,\n stack: mergeStack(existing.stack ?? ({} as ConfigStack), fresh.stack ?? ({} as ConfigStack)),\n structure: mergeStructure(existing.structure ?? {}, fresh.structure ?? {}),\n conventions,\n },\n meta,\n };\n}\n\n/**\n * Merge a new scan result into an existing config for `viberails sync`.\n *\n * Preserves all developer-confirmed values from the existing config.\n * Adds newly detected values. New conventions are marked with\n * `detected: true` in _meta so the developer can review them.\n *\n * @param existing - The current ViberailsConfig (from viberails.config.json)\n * @param scanResult - Fresh scan results from re-scanning the project\n * @returns A merged config that preserves existing values and adds new detections\n */\nexport function mergeConfig(existing: ViberailsConfig, scanResult: ScanResult): ViberailsConfig {\n const fresh = generateConfig(scanResult);\n\n const existingByPath = new Map(existing.packages.map((p) => [p.path, p]));\n const freshByPath = new Map(fresh.packages.map((p) => [p.path, p]));\n\n const mergedPackages: PackageConfig[] = [];\n const mergedPkgMeta: Record<string, { conventions?: Record<string, ConventionMeta> }> = {};\n\n // Merge existing packages with fresh data\n for (const existingPkg of existing.packages) {\n const freshPkg = freshByPath.get(existingPkg.path);\n if (freshPkg) {\n const existingConvMeta = existing._meta?.packages?.[existingPkg.path]?.conventions;\n const freshConvMeta = fresh._meta?.packages?.[existingPkg.path]?.conventions;\n const { pkg, meta } = mergePackage(existingPkg, freshPkg, existingConvMeta, freshConvMeta);\n mergedPackages.push(pkg);\n if (Object.keys(meta).length > 0) {\n mergedPkgMeta[pkg.path] = { conventions: meta };\n }\n } else {\n mergedPackages.push(existingPkg);\n }\n }\n\n // Add new packages from fresh scan\n for (const freshPkg of fresh.packages) {\n if (!existingByPath.has(freshPkg.path)) {\n mergedPackages.push(freshPkg);\n const freshConvMeta = fresh._meta?.packages?.[freshPkg.path]?.conventions;\n if (freshConvMeta && Object.keys(freshConvMeta).length > 0) {\n mergedPkgMeta[freshPkg.path] = { conventions: freshConvMeta };\n }\n }\n }\n\n const merged: ViberailsConfig = {\n $schema: existing.$schema ?? fresh.$schema,\n version: existing.version,\n name: existing.name,\n rules: { ...existing.rules },\n ignore: [...(existing.ignore ?? [])],\n packages: mergedPackages,\n _meta: {\n lastSync: new Date().toISOString(),\n ...(Object.keys(mergedPkgMeta).length > 0 ? { packages: mergedPkgMeta } : {}),\n },\n };\n\n // Boundaries: preserve existing rules (user may have adjusted)\n if (existing.boundaries) {\n merged.boundaries = {\n deny: { ...existing.boundaries.deny },\n ...(existing.boundaries.ignore ? { ignore: [...existing.boundaries.ignore] } : {}),\n };\n } else if (fresh.boundaries) {\n merged.boundaries = {\n deny: { ...fresh.boundaries.deny },\n ...(fresh.boundaries.ignore ? { ignore: [...fresh.boundaries.ignore] } : {}),\n };\n }\n\n return merged;\n}\n","/**\n * Reusable sub-schema definitions extracted from the main config schema.\n * Keeps the primary schema file under 300 lines.\n */\n\nexport const boundarySchema = {\n type: 'object',\n required: ['deny'],\n properties: {\n deny: {\n type: 'object',\n additionalProperties: {\n type: 'array',\n items: { type: 'string' },\n },\n description:\n 'Map of source package/directory to the list of targets it must NOT import from.',\n },\n ignore: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'File paths that bypass boundary checks entirely (escape hatch for legitimate exceptions).',\n },\n },\n additionalProperties: false,\n} as const;\n\nexport const stackSchema = {\n type: 'object',\n properties: {\n framework: { type: 'string', description: 'Primary framework (e.g. \"nextjs@15\").' },\n language: { type: 'string', description: 'Primary language (e.g. \"typescript\").' },\n styling: { type: 'string', description: 'Styling solution (e.g. \"tailwindcss@4\").' },\n backend: { type: 'string', description: 'Backend framework (e.g. \"express@5\").' },\n orm: { type: 'string', description: 'ORM or database client (e.g. \"prisma\").' },\n packageManager: { type: 'string', description: 'Package manager (e.g. \"pnpm\").' },\n linter: { type: 'string', description: 'Linter (e.g. \"eslint@9\").' },\n formatter: { type: 'string', description: 'Formatter (e.g. \"prettier\").' },\n testRunner: { type: 'string', description: 'Test runner (e.g. \"vitest\").' },\n },\n additionalProperties: false,\n} as const;\n\nexport const structureSchema = {\n type: 'object',\n properties: {\n srcDir: { type: 'string', description: 'Source directory (e.g. \"src\").' },\n pages: { type: 'string', description: 'Pages or routes directory.' },\n components: { type: 'string', description: 'Components directory.' },\n hooks: { type: 'string', description: 'Hooks directory.' },\n utils: { type: 'string', description: 'Utilities directory.' },\n types: { type: 'string', description: 'Type definitions directory.' },\n tests: { type: 'string', description: 'Tests directory.' },\n testPattern: { type: 'string', description: 'Test file naming pattern (e.g. \"*.test.ts\").' },\n },\n additionalProperties: false,\n} as const;\n\nexport const conventionsSchema = {\n type: 'object',\n properties: {\n fileNaming: { type: 'string', description: 'File naming convention (e.g. \"kebab-case\").' },\n componentNaming: { type: 'string', description: 'Component naming convention.' },\n hookNaming: { type: 'string', description: 'Hook naming convention.' },\n importAlias: { type: 'string', description: 'Import alias pattern (e.g. \"@/*\").' },\n },\n additionalProperties: false,\n} as const;\n\nexport const coverageSchema = {\n type: 'object',\n properties: {\n command: {\n type: 'string',\n description: 'Command to generate coverage summary data for this package.',\n },\n summaryPath: {\n type: 'string',\n description: 'Path to coverage summary JSON relative to package root.',\n },\n },\n additionalProperties: false,\n} as const;\n\nexport const packageItemSchema = {\n type: 'object',\n required: ['name', 'path'],\n properties: {\n name: { type: 'string', description: 'Package name from package.json.' },\n path: { type: 'string', description: 'Relative path to the package (\".\" for root).' },\n stack: { ...stackSchema, description: 'Technology stack for this package.' },\n structure: { ...structureSchema, description: 'Directory structure for this package.' },\n conventions: { ...conventionsSchema, description: 'Coding conventions for this package.' },\n coverage: {\n ...coverageSchema,\n description: 'Coverage generation and summary settings for this package.',\n },\n rules: {\n type: 'object',\n properties: {\n maxFileLines: { type: 'number' },\n maxTestFileLines: { type: 'number' },\n testCoverage: { type: 'number' },\n enforceNaming: { type: 'boolean' },\n enforceBoundaries: { type: 'boolean' },\n },\n additionalProperties: false,\n },\n ignore: { type: 'array', items: { type: 'string' } },\n boundaries: {\n type: 'object',\n properties: {\n deny: { type: 'array', items: { type: 'string' } },\n ignore: { type: 'array', items: { type: 'string' } },\n },\n additionalProperties: false,\n },\n },\n additionalProperties: false,\n} as const;\n\nexport const defaultsSchema = {\n type: 'object',\n properties: {\n stack: { ...stackSchema, description: 'Default stack inherited by all packages.' },\n structure: { ...structureSchema, description: 'Default structure inherited by all packages.' },\n conventions: {\n ...conventionsSchema,\n description: 'Default conventions inherited by all packages.',\n },\n coverage: {\n ...coverageSchema,\n description: 'Default coverage settings inherited by all packages.',\n },\n },\n additionalProperties: false,\n description: 'Shared defaults for all packages. Packages inherit and can override.',\n} as const;\n","/**\n * JSON Schema (draft-07) definition for viberails.config.json.\n *\n * This schema will eventually be hosted at https://viberails.sh/schema/v1.json.\n * For now it is exported as a TypeScript object that can be serialized to JSON.\n */\nimport { boundarySchema, defaultsSchema, packageItemSchema } from './schema-parts.js';\n\nexport const configSchema = {\n $schema: 'http://json-schema.org/draft-07/schema#',\n $id: 'https://viberails.sh/schema/v1.json',\n title: 'viberails configuration',\n description: 'Configuration file for viberails — guardrails for vibe coding.',\n type: 'object',\n required: ['version', 'name', 'packages', 'rules'],\n properties: {\n $schema: {\n type: 'string',\n description: 'JSON Schema URL for editor validation.',\n },\n version: {\n type: 'number',\n const: 1,\n description: 'Config format version. Always 1.',\n },\n name: {\n type: 'string',\n description: 'Project name, typically from package.json.',\n },\n rules: {\n type: 'object',\n required: [\n 'maxFileLines',\n 'testCoverage',\n 'enforceNaming',\n 'enforceBoundaries',\n 'enforceMissingTests',\n ],\n properties: {\n maxFileLines: {\n type: 'number',\n default: 300,\n description: 'Maximum number of lines allowed per file.',\n },\n maxTestFileLines: {\n type: 'number',\n default: 0,\n description:\n 'Maximum number of lines allowed per test file. Set to 0 to exempt test files.',\n },\n testCoverage: {\n type: 'number',\n default: 80,\n description:\n 'Minimum line coverage target percentage. 0 disables coverage threshold checks.',\n },\n enforceNaming: {\n type: 'boolean',\n default: true,\n description: 'Whether to enforce detected file naming conventions.',\n },\n enforceBoundaries: {\n type: 'boolean',\n default: false,\n description: 'Whether to enforce module boundary rules.',\n },\n enforceMissingTests: {\n type: 'boolean',\n default: true,\n description: 'Whether to enforce that every source file has a corresponding test file.',\n },\n },\n additionalProperties: false,\n description: 'Rule thresholds and toggles for enforcement.',\n },\n ignore: {\n type: 'array',\n items: { type: 'string' },\n description: 'Project-specific glob patterns to ignore (universal patterns are built-in).',\n },\n boundaries: {\n ...boundarySchema,\n description: 'Module boundary rules for import enforcement.',\n },\n defaults: defaultsSchema,\n packages: {\n type: 'array',\n items: packageItemSchema,\n description: 'Per-package configs. Single projects use path \".\".',\n },\n _meta: {\n type: 'object',\n properties: {\n lastSync: { type: 'string', description: 'ISO timestamp of last sync.' },\n packages: {\n type: 'object',\n additionalProperties: {\n type: 'object',\n properties: {\n conventions: {\n type: 'object',\n additionalProperties: {\n type: 'object',\n properties: {\n value: { type: 'string' },\n confidence: { type: 'string', enum: ['high', 'medium', 'low'] },\n consistency: { type: 'number' },\n detected: { type: 'boolean' },\n },\n },\n },\n },\n },\n },\n },\n description: 'Scanner metadata. Regenerated on every sync — not user-editable.',\n },\n },\n additionalProperties: false,\n} as const;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/generate-config.ts","../src/defaults.ts","../src/generate-packages.ts","../src/infer-coverage-command.ts","../src/compact-config.ts","../src/load-config.ts","../src/merge-config.ts","../src/schema-parts.ts","../src/schema.ts"],"sourcesContent":["declare const __PACKAGE_VERSION__: string;\nexport const VERSION: string = __PACKAGE_VERSION__;\n\nexport { compactConfig, expandDefaults } from './compact-config.js';\nexport { BUILTIN_IGNORE, DEFAULT_IGNORE, DEFAULT_RULES } from './defaults.js';\nexport { generateConfig } from './generate-config.js';\nexport { inferCoverageCommand } from './infer-coverage-command.js';\nexport { loadConfig, loadConfigSafe } from './load-config.js';\nexport { mergeConfig } from './merge-config.js';\nexport { configSchema } from './schema.js';\n","import * as path from 'node:path';\nimport type {\n ConfigConventions,\n ConfigMeta,\n ConfigStack,\n ConfigStructure,\n ConventionMeta,\n DetectedConvention,\n DirectoryRole,\n PackageConfig,\n ScanResult,\n StackItem,\n ViberailsConfig,\n} from '@viberails/types';\nimport { DEFAULT_IGNORE, DEFAULT_RULES } from './defaults.js';\nimport { generatePackages } from './generate-packages.js';\nimport { inferCoverageCommand } from './infer-coverage-command.js';\n\n/**\n * Format a StackItem as a config string: `\"name@version\"` or `\"name\"`.\n */\nexport function formatStackItem(item: StackItem): string {\n return item.version ? `${item.name}@${item.version}` : item.name;\n}\n\n/**\n * Map DetectedStack → ConfigStack by formatting each StackItem.\n */\nexport function mapStack(scanResult: ScanResult): ConfigStack {\n const { stack } = scanResult;\n const config: ConfigStack = {\n language: formatStackItem(stack.language),\n packageManager: formatStackItem(stack.packageManager),\n };\n\n if (stack.framework) config.framework = formatStackItem(stack.framework);\n if (stack.styling) config.styling = formatStackItem(stack.styling);\n if (stack.backend) config.backend = formatStackItem(stack.backend);\n if (stack.orm) config.orm = formatStackItem(stack.orm);\n if (stack.linter) config.linter = formatStackItem(stack.linter);\n if (stack.formatter) config.formatter = formatStackItem(stack.formatter);\n if (stack.testRunner) config.testRunner = formatStackItem(stack.testRunner);\n\n return config;\n}\n\n/** Directory roles that map to ConfigStructure fields. */\nconst ROLE_TO_FIELD: Partial<Record<DirectoryRole, keyof ConfigStructure>> = {\n pages: 'pages',\n components: 'components',\n hooks: 'hooks',\n utils: 'utils',\n types: 'types',\n tests: 'tests',\n};\n\n/**\n * Map DetectedStructure → ConfigStructure by finding the first directory\n * for each known role.\n */\nexport function mapStructure(scanResult: ScanResult): ConfigStructure {\n const { structure } = scanResult;\n const config: ConfigStructure = {};\n\n if (structure.srcDir) {\n config.srcDir = structure.srcDir;\n }\n\n for (const dir of structure.directories) {\n const field = ROLE_TO_FIELD[dir.role];\n if (field && config[field] === undefined) {\n (config as Record<string, string>)[field] = dir.path;\n }\n }\n\n if (structure.testPattern) {\n config.testPattern = structure.testPattern.value;\n } else {\n // Default test pattern when no test files detected yet, based on project language\n const isTypeScript = scanResult.stack.language.name === 'typescript';\n config.testPattern = isTypeScript ? '*.test.ts' : '*.test.js';\n }\n\n return config;\n}\n\n/** Convention keys from ScanResult that map to ConfigConventions fields. */\nexport const CONVENTION_KEYS: (keyof ConfigConventions)[] = [\n 'fileNaming',\n 'componentNaming',\n 'hookNaming',\n 'importAlias',\n];\n\n/**\n * Map scanner conventions → ConfigConventions as plain strings.\n * Low-confidence conventions are omitted.\n * Returns both the plain-string conventions and the metadata for _meta.\n */\nfunction mapConventions(scanResult: ScanResult): {\n conventions: ConfigConventions;\n meta: Record<string, ConventionMeta>;\n} {\n const conventions: ConfigConventions = {};\n const meta: Record<string, ConventionMeta> = {};\n\n for (const key of CONVENTION_KEYS) {\n const detected = scanResult.conventions[key];\n if (detected && detected.confidence !== 'low') {\n conventions[key] = detected.value;\n meta[key] = {\n value: detected.value,\n confidence: detected.confidence,\n consistency: detected.consistency,\n };\n }\n }\n\n return { conventions, meta };\n}\n\n/**\n * Build _meta for a single package's conventions.\n */\nexport function buildConventionMeta(\n conventions: Record<string, DetectedConvention>,\n): Record<string, ConventionMeta> {\n const meta: Record<string, ConventionMeta> = {};\n for (const key of CONVENTION_KEYS) {\n const detected = conventions[key];\n if (detected && detected.confidence !== 'low') {\n meta[key] = {\n value: detected.value,\n confidence: detected.confidence,\n consistency: detected.consistency,\n };\n }\n }\n return meta;\n}\n\n/**\n * Generate a ViberailsConfig from scan results.\n *\n * Produces the packages-first config format: all config lives in `packages[]`.\n * Single projects get one package with `path: \".\"`.\n * Monorepos get one package per workspace package.\n *\n * @param scanResult - The output of scanning a project\n * @returns A complete ViberailsConfig ready to be written as JSON\n */\nexport function generateConfig(scanResult: ScanResult): ViberailsConfig {\n const projectName = path.basename(scanResult.root);\n const { conventions, meta } = mapConventions(scanResult);\n\n // Build the root package\n const rootPackage: PackageConfig = {\n name: projectName,\n path: '.',\n stack: mapStack(scanResult),\n structure: mapStructure(scanResult),\n conventions,\n };\n\n const _meta: ConfigMeta = {\n lastSync: new Date().toISOString(),\n packages: {\n '.': { conventions: Object.keys(meta).length > 0 ? meta : undefined },\n },\n };\n\n const config: ViberailsConfig = {\n $schema: 'https://viberails.sh/schema/v1.json',\n version: 1,\n name: projectName,\n rules: { ...DEFAULT_RULES },\n ignore: [...DEFAULT_IGNORE],\n packages: [rootPackage],\n _meta,\n };\n\n // Infer coverage command from detected test runner\n const testRunner = scanResult.stack.testRunner;\n const coverageCommand = inferCoverageCommand(\n testRunner ? formatStackItem(testRunner) : undefined,\n );\n if (coverageCommand) {\n config.defaults = { coverage: { command: coverageCommand } };\n }\n\n // Monorepo: generate per-package configs\n if (scanResult.workspace) {\n const packages = generatePackages(scanResult);\n if (packages) {\n config.packages = packages;\n\n // If packages have different test runners, set per-package coverage\n // commands instead of a global default (which would be wrong for some).\n const runners = new Set(\n packages.map((p) => p.stack?.testRunner?.split('@')[0]).filter(Boolean),\n );\n if (runners.size > 1) {\n delete config.defaults?.coverage?.command;\n for (const pkg of packages) {\n const pkgCommand = inferCoverageCommand(pkg.stack?.testRunner);\n if (pkgCommand) {\n pkg.coverage = { ...pkg.coverage, command: pkgCommand };\n }\n }\n }\n // Rebuild _meta for all packages\n const pkgMeta: Record<string, { conventions?: Record<string, ConventionMeta> }> = {};\n for (const pkg of scanResult.packages) {\n const convMeta = buildConventionMeta(pkg.conventions);\n if (Object.keys(convMeta).length > 0) {\n pkgMeta[pkg.relativePath] = { conventions: convMeta };\n }\n }\n if (Object.keys(pkgMeta).length > 0) {\n _meta.packages = pkgMeta;\n }\n }\n config.boundaries = { deny: {} };\n }\n\n return config;\n}\n","import type { ConfigRules } from '@viberails/types';\n\n/**\n * Default rule thresholds and toggles for a new viberails config.\n * These values are intentionally conservative to build trust on first run.\n */\nexport const DEFAULT_RULES: ConfigRules = {\n maxFileLines: 300,\n maxTestFileLines: 0,\n testCoverage: 80,\n enforceNaming: true,\n enforceBoundaries: false,\n enforceMissingTests: true,\n};\n\n/**\n * Default project-specific ignore patterns for a new config.\n * Empty — universal patterns live in BUILTIN_IGNORE and are applied at check-time.\n */\nexport const DEFAULT_IGNORE: string[] = [];\n\n/**\n * Universal ignore patterns applied at check-time.\n * These are never written to config — they are always applied implicitly.\n */\nexport const BUILTIN_IGNORE: string[] = [\n '**/*.d.ts',\n '**/*.min.js',\n '**/*.min.cjs',\n '**/*.umd.js',\n '**/*.bundle.js',\n 'dist/**',\n 'node_modules/**',\n 'build/**',\n '.next/**',\n '.expo/**',\n '.output/**',\n '.svelte-kit/**',\n '.turbo/**',\n 'coverage/**',\n '**/public/**',\n '**/vendor/**',\n '.viberails/**',\n '**/generated/**',\n '**/__generated__/**',\n];\n","import type { ConfigConventions, ConfigStack, PackageConfig, ScanResult } from '@viberails/types';\nimport { CONVENTION_KEYS, formatStackItem, mapStructure } from './generate-config.js';\n\n/**\n * Build a full ConfigStack for a single package scan result.\n */\nfunction buildPackageStack(pkg: ScanResult['packages'][number]): ConfigStack {\n const config: ConfigStack = {\n language: formatStackItem(pkg.stack.language),\n packageManager: formatStackItem(pkg.stack.packageManager),\n };\n\n if (pkg.stack.framework) config.framework = formatStackItem(pkg.stack.framework);\n if (pkg.stack.styling) config.styling = formatStackItem(pkg.stack.styling);\n if (pkg.stack.backend) config.backend = formatStackItem(pkg.stack.backend);\n if (pkg.stack.orm) config.orm = formatStackItem(pkg.stack.orm);\n if (pkg.stack.linter) config.linter = formatStackItem(pkg.stack.linter);\n if (pkg.stack.formatter) config.formatter = formatStackItem(pkg.stack.formatter);\n if (pkg.stack.testRunner) config.testRunner = formatStackItem(pkg.stack.testRunner);\n\n return config;\n}\n\n/**\n * Build ConfigConventions as plain strings, omitting low-confidence entries.\n */\nfunction buildPackageConventions(\n pkgConventions: Record<string, import('@viberails/types').DetectedConvention>,\n): ConfigConventions {\n const config: ConfigConventions = {};\n\n for (const key of CONVENTION_KEYS) {\n const detected = pkgConventions[key];\n if (detected && detected.confidence !== 'low') {\n config[key] = detected.value;\n }\n }\n\n return config;\n}\n\n/**\n * Generate self-contained per-package configs for packages in a monorepo.\n * Each PackageConfig has its own full stack, structure, and conventions.\n *\n * Returns undefined for single-package projects.\n */\nexport function generatePackages(scanResult: ScanResult): PackageConfig[] | undefined {\n if (!scanResult.packages || scanResult.packages.length <= 1) return undefined;\n\n const packages: PackageConfig[] = [];\n\n for (const pkg of scanResult.packages) {\n // Build a temporary ScanResult-like object for mapStructure\n const pkgScanResult = {\n root: pkg.root,\n stack: pkg.stack,\n structure: pkg.structure,\n conventions: pkg.conventions,\n statistics: pkg.statistics,\n } as ScanResult;\n\n const packageConfig: PackageConfig = {\n name: pkg.name,\n path: pkg.relativePath,\n stack: buildPackageStack(pkg),\n structure: mapStructure(pkgScanResult),\n conventions: buildPackageConventions(pkg.conventions),\n };\n\n if (pkg.typesOnly) {\n packageConfig.rules = { testCoverage: 0 };\n }\n\n packages.push(packageConfig);\n }\n\n return packages.length > 0 ? packages : undefined;\n}\n","/**\n * Infer a coverage command from the detected test runner string.\n *\n * Used during `init` to store the inferred command in config so that\n * `check` can use it explicitly. Does not verify binary availability —\n * the command is stored as a suggestion for the user to review.\n *\n * @param testRunner - Test runner string from config (e.g. \"vitest@4\", \"jest@29\")\n * @returns Shell command string, or undefined if the runner is unsupported\n */\nexport function inferCoverageCommand(testRunner: string | undefined): string | undefined {\n if (!testRunner) return undefined;\n const runner = testRunner.split('@')[0];\n if (runner === 'vitest') {\n return 'npx vitest run --coverage --coverage.reporter=json-summary';\n }\n if (runner === 'jest') {\n return 'npx jest --coverage --coverageReporters=json-summary';\n }\n return undefined;\n}\n","import type {\n ConfigConventions,\n ConfigCoverage,\n ConfigDefaults,\n ConfigStack,\n ConfigStructure,\n ViberailsConfig,\n} from '@viberails/types';\nimport { CONVENTION_KEYS } from './generate-config.js';\n\n/** Stack field keys for comparison and extraction. */\nexport const STACK_KEYS: (keyof ConfigStack)[] = [\n 'language',\n 'packageManager',\n 'framework',\n 'styling',\n 'backend',\n 'orm',\n 'linter',\n 'formatter',\n 'testRunner',\n];\n\n/** Structure field keys for comparison and extraction. */\nexport const STRUCTURE_KEYS: (keyof ConfigStructure)[] = [\n 'srcDir',\n 'pages',\n 'components',\n 'hooks',\n 'utils',\n 'types',\n 'tests',\n 'testPattern',\n];\n\n/**\n * Extract shared values from packages into defaults and strip them from packages.\n * Only extracts values that are identical across ALL packages.\n * Strips empty objects from packages for clean JSON output.\n */\nexport function compactConfig(config: ViberailsConfig): ViberailsConfig {\n const pkgs = config.packages ?? [];\n\n const defaults: ConfigDefaults = {};\n\n // Start with copies; merge any existing defaults into each package first\n // so the extraction logic below works uniformly for 1 or N packages.\n const packages = pkgs.map((p) => {\n const copy = { ...p };\n if (config.defaults?.coverage) {\n copy.coverage = { ...config.defaults.coverage, ...(copy.coverage ?? {}) };\n }\n if (config.defaults?.stack) {\n copy.stack = { ...config.defaults.stack, ...(copy.stack ?? {}) } as ConfigStack;\n }\n if (config.defaults?.structure) {\n copy.structure = { ...config.defaults.structure, ...(copy.structure ?? {}) };\n }\n if (config.defaults?.conventions) {\n copy.conventions = { ...config.defaults.conventions, ...(copy.conventions ?? {}) };\n }\n return copy;\n });\n\n // For multi-package configs, extract shared values into defaults.\n // Single-package configs keep everything on the package (no defaults needed).\n if (packages.length <= 1) {\n // Strip empty objects from the single package\n for (const pkg of packages) {\n if (pkg.stack && Object.keys(pkg.stack).length === 0) delete pkg.stack;\n if (pkg.structure && Object.keys(pkg.structure).length === 0) delete pkg.structure;\n if (pkg.conventions && Object.keys(pkg.conventions).length === 0) delete pkg.conventions;\n if (pkg.coverage && Object.keys(pkg.coverage).length === 0) delete pkg.coverage;\n }\n const { defaults: _d, ...rest } = config;\n return { ...rest, packages };\n }\n\n // Extract shared stack fields\n const sharedStack: Partial<ConfigStack> = {};\n for (const key of STACK_KEYS) {\n const values = packages.map((p) => (p.stack ?? ({} as Partial<ConfigStack>))[key]);\n if (values[0] !== undefined && values.every((v) => v === values[0])) {\n sharedStack[key] = values[0] as string;\n }\n }\n if (Object.keys(sharedStack).length > 0) {\n defaults.stack = sharedStack;\n for (const pkg of packages) {\n const pkgStack = (pkg.stack ?? {}) as Partial<ConfigStack>;\n const sparse: Partial<ConfigStack> = {};\n for (const key of STACK_KEYS) {\n if (pkgStack[key] !== undefined && pkgStack[key] !== sharedStack[key]) {\n sparse[key] = pkgStack[key] as string;\n }\n }\n pkg.stack = sparse as ConfigStack;\n }\n }\n\n // Extract shared structure fields\n const sharedStructure: Partial<ConfigStructure> = {};\n for (const key of STRUCTURE_KEYS) {\n const values = packages.map((p) => p.structure?.[key]);\n const first = values[0];\n if (first !== undefined && values.every((v) => JSON.stringify(v) === JSON.stringify(first))) {\n (sharedStructure as Record<string, unknown>)[key] = first;\n }\n }\n if (Object.keys(sharedStructure).length > 0) {\n defaults.structure = sharedStructure;\n for (const pkg of packages) {\n const pkgStructure = pkg.structure ?? {};\n const sparse: Partial<ConfigStructure> = {};\n for (const key of STRUCTURE_KEYS) {\n const val = pkgStructure[key];\n if (val !== undefined && JSON.stringify(val) !== JSON.stringify(sharedStructure[key])) {\n (sparse as Record<string, unknown>)[key] = val;\n }\n }\n pkg.structure = sparse as ConfigStructure;\n }\n }\n\n // Extract shared conventions\n const sharedConventions: ConfigConventions = {};\n for (const key of CONVENTION_KEYS) {\n const values = packages.map((p) => p.conventions?.[key]);\n if (values[0] !== undefined && values.every((v) => v === values[0])) {\n sharedConventions[key] = values[0];\n }\n }\n\n // Extract shared coverage settings\n const sharedCoverage: ConfigCoverage = {};\n const coverageKeys: (keyof ConfigCoverage)[] = ['command', 'summaryPath'];\n for (const key of coverageKeys) {\n const values = packages.map((p) => p.coverage?.[key]);\n if (values[0] !== undefined && values.every((v) => v === values[0])) {\n sharedCoverage[key] = values[0];\n }\n }\n if (Object.keys(sharedCoverage).length > 0) {\n defaults.coverage = sharedCoverage;\n for (const pkg of packages) {\n const pkgCoverage = pkg.coverage ?? {};\n const sparse: ConfigCoverage = {};\n for (const key of coverageKeys) {\n if (pkgCoverage[key] !== undefined && pkgCoverage[key] !== sharedCoverage[key]) {\n sparse[key] = pkgCoverage[key];\n }\n }\n pkg.coverage = sparse;\n }\n }\n if (Object.keys(sharedConventions).length > 0) {\n defaults.conventions = sharedConventions;\n for (const pkg of packages) {\n const pkgConventions = pkg.conventions ?? {};\n const sparse: ConfigConventions = {};\n for (const key of CONVENTION_KEYS) {\n if (pkgConventions[key] !== undefined && pkgConventions[key] !== sharedConventions[key]) {\n sparse[key] = pkgConventions[key];\n }\n }\n pkg.conventions = sparse;\n }\n }\n\n // Strip empty objects from packages\n for (const pkg of packages) {\n if (pkg.stack && Object.keys(pkg.stack).length === 0) {\n delete pkg.stack;\n }\n if (pkg.structure && Object.keys(pkg.structure).length === 0) {\n delete pkg.structure;\n }\n if (pkg.conventions && Object.keys(pkg.conventions).length === 0) {\n delete pkg.conventions;\n }\n if (pkg.coverage && Object.keys(pkg.coverage).length === 0) {\n delete pkg.coverage;\n }\n }\n\n // Reconstruct with explicit key ordering so JSON output is readable:\n // $schema, version, name, rules, ignore, boundaries, defaults, packages, _meta\n const result: ViberailsConfig = {\n ...(config.$schema ? { $schema: config.$schema } : {}),\n version: config.version,\n name: config.name,\n rules: config.rules,\n ...(config.ignore && config.ignore.length > 0 ? { ignore: config.ignore } : {}),\n ...(config.boundaries ? { boundaries: config.boundaries } : {}),\n ...(Object.keys(defaults).length > 0 ? { defaults } : {}),\n packages,\n ...(config._meta ? { _meta: config._meta } : {}),\n };\n return result;\n}\n\n/**\n * Expand defaults into each package, producing fully self-contained packages.\n * Inverse of compactConfig. Ensures every package has stack, structure,\n * and conventions (even as empty objects) and config.ignore defaults to [].\n */\nexport function expandDefaults(config: ViberailsConfig): ViberailsConfig {\n const defaults = config.defaults;\n\n const packages = config.packages.map((pkg) => {\n const expanded = { ...pkg };\n\n // Merge defaults into package fields, or initialize to empty objects\n expanded.stack = { ...(defaults?.stack ?? {}), ...(pkg.stack ?? {}) } as ConfigStack;\n expanded.structure = { ...(defaults?.structure ?? {}), ...(pkg.structure ?? {}) };\n expanded.conventions = { ...(defaults?.conventions ?? {}), ...(pkg.conventions ?? {}) };\n const mergedCoverage = { ...(defaults?.coverage ?? {}), ...(pkg.coverage ?? {}) };\n if (Object.keys(mergedCoverage).length > 0) {\n expanded.coverage = mergedCoverage;\n } else {\n delete expanded.coverage;\n }\n\n return expanded;\n });\n\n // Ensure ignore defaults to []\n const ignore = config.ignore ?? [];\n\n // Return without defaults — packages are now self-contained\n const { defaults: _d, ...rest } = config;\n return { ...rest, ignore, packages };\n}\n","import * as fs from 'node:fs/promises';\nimport type { ViberailsConfig } from '@viberails/types';\nimport { expandDefaults } from './compact-config.js';\n\n/**\n * Validate that a parsed object has the required ViberailsConfig fields\n * and that their types are correct.\n * Throws a descriptive error if validation fails.\n */\nfunction validateConfig(parsed: Record<string, unknown>, configPath: string): void {\n const errors: string[] = [];\n\n // Required top-level fields\n const required = ['version', 'name', 'packages', 'rules'] as const;\n const missing = required.filter((field) => parsed[field] === undefined);\n if (missing.length > 0) {\n throw new Error(\n `Invalid viberails config at ${configPath}: missing required field(s): ${missing.join(', ')}`,\n );\n }\n\n // Type checks\n if (typeof parsed.version !== 'number') {\n errors.push('\"version\" must be a number');\n } else if (parsed.version !== 1) {\n errors.push('\"version\" must be 1');\n }\n if (typeof parsed.name !== 'string') errors.push('\"name\" must be a string');\n // Packages validation\n if (!Array.isArray(parsed.packages)) {\n errors.push('\"packages\" must be an array');\n } else if (parsed.packages.length === 0) {\n errors.push('\"packages\" must contain at least one package');\n } else {\n for (let i = 0; i < parsed.packages.length; i++) {\n const pkg = parsed.packages[i] as Record<string, unknown>;\n if (typeof pkg.name !== 'string') errors.push(`\"packages[${i}].name\" must be a string`);\n if (typeof pkg.path !== 'string') errors.push(`\"packages[${i}].path\" must be a string`);\n if (pkg.coverage !== undefined) {\n if (typeof pkg.coverage !== 'object' || pkg.coverage === null) {\n errors.push(`\"packages[${i}].coverage\" must be an object`);\n } else {\n const coverage = pkg.coverage as Record<string, unknown>;\n if (coverage.command !== undefined && typeof coverage.command !== 'string') {\n errors.push(`\"packages[${i}].coverage.command\" must be a string`);\n }\n if (coverage.summaryPath !== undefined && typeof coverage.summaryPath !== 'string') {\n errors.push(`\"packages[${i}].coverage.summaryPath\" must be a string`);\n }\n }\n }\n }\n }\n\n // Rules validation\n if (typeof parsed.rules !== 'object' || parsed.rules === null) {\n errors.push('\"rules\" must be an object');\n } else {\n const rules = parsed.rules as Record<string, unknown>;\n if (typeof rules.maxFileLines !== 'number')\n errors.push('\"rules.maxFileLines\" must be a number');\n else if (rules.maxFileLines < 0) errors.push('\"rules.maxFileLines\" must be >= 0');\n if (rules.maxTestFileLines !== undefined) {\n if (typeof rules.maxTestFileLines !== 'number') {\n errors.push('\"rules.maxTestFileLines\" must be a number');\n } else if (rules.maxTestFileLines < 0) {\n errors.push('\"rules.maxTestFileLines\" must be >= 0');\n }\n }\n if (typeof rules.testCoverage !== 'number')\n errors.push('\"rules.testCoverage\" must be a number');\n else if (rules.testCoverage < 0 || rules.testCoverage > 100)\n errors.push('\"rules.testCoverage\" must be between 0 and 100');\n if (typeof rules.enforceNaming !== 'boolean')\n errors.push('\"rules.enforceNaming\" must be a boolean');\n if (typeof rules.enforceBoundaries !== 'boolean')\n errors.push('\"rules.enforceBoundaries\" must be a boolean');\n }\n\n // Ignore validation\n if (parsed.ignore !== undefined && !Array.isArray(parsed.ignore)) {\n errors.push('\"ignore\" must be an array');\n }\n\n // Defaults validation\n if (parsed.defaults !== undefined) {\n if (typeof parsed.defaults !== 'object' || parsed.defaults === null) {\n errors.push('\"defaults\" must be an object');\n } else {\n const defaults = parsed.defaults as Record<string, unknown>;\n if (defaults.coverage !== undefined) {\n if (typeof defaults.coverage !== 'object' || defaults.coverage === null) {\n errors.push('\"defaults.coverage\" must be an object');\n } else {\n const coverage = defaults.coverage as Record<string, unknown>;\n if (coverage.command !== undefined && typeof coverage.command !== 'string') {\n errors.push('\"defaults.coverage.command\" must be a string');\n }\n if (coverage.summaryPath !== undefined && typeof coverage.summaryPath !== 'string') {\n errors.push('\"defaults.coverage.summaryPath\" must be a string');\n }\n }\n }\n }\n }\n\n if (errors.length > 0) {\n throw new Error(`Invalid viberails config at ${configPath}: ${errors.join('; ')}`);\n }\n}\n\n/**\n * Load and parse a viberails config file.\n *\n * Reads the JSON file at the given path, validates that it contains\n * the required fields (version, name, packages, rules), expands\n * defaults into packages, and returns the parsed config.\n *\n * @param configPath - Absolute or relative path to viberails.config.json\n * @returns The parsed ViberailsConfig with defaults expanded\n * @throws If the file doesn't exist, contains invalid JSON, or is missing required fields\n */\nexport async function loadConfig(configPath: string): Promise<ViberailsConfig> {\n let raw: string;\n try {\n raw = await fs.readFile(configPath, 'utf-8');\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') {\n throw new Error(`Config file not found: ${configPath}. Run \"npx viberails\" to generate one.`);\n }\n throw new Error(`Failed to read config file at ${configPath}: ${(err as Error).message}`);\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n throw new Error(`Invalid JSON in config file at ${configPath}. Check for syntax errors.`);\n }\n\n validateConfig(parsed, configPath);\n\n // Apply defaults for optional fields added after initial release\n const rules = parsed.rules as Record<string, unknown>;\n if (rules.maxTestFileLines === undefined) {\n rules.maxTestFileLines = 0;\n }\n if (rules.enforceMissingTests === undefined) {\n rules.enforceMissingTests = true;\n }\n\n // Default ignore to [] if missing\n if (parsed.ignore === undefined) {\n parsed.ignore = [];\n }\n\n // Safe to cast: validateConfig has verified all required fields and types\n let config = parsed as unknown as ViberailsConfig;\n\n // Expand defaults into packages so they are self-contained\n config = expandDefaults(config);\n\n return config;\n}\n\n/**\n * Safely load a viberails config file, returning null on any error.\n *\n * Used by the CLI for \"does config already exist?\" checks where\n * failure is an expected case, not an error.\n *\n * @param configPath - Absolute or relative path to viberails.config.json\n * @returns The parsed ViberailsConfig, or null if loading fails\n */\nexport async function loadConfigSafe(configPath: string): Promise<ViberailsConfig | null> {\n try {\n return await loadConfig(configPath);\n } catch {\n return null;\n }\n}\n","import type {\n ConfigConventions,\n ConfigStack,\n ConfigStructure,\n ConventionMeta,\n PackageConfig,\n ScanResult,\n ViberailsConfig,\n} from '@viberails/types';\nimport { CONVENTION_KEYS, generateConfig } from './generate-config.js';\n\n/**\n * Merge stack: keep existing values, fill in undefined fields from fresh scan.\n */\nfunction mergeStack(existing: ConfigStack, fresh: ConfigStack): ConfigStack {\n return {\n language: existing.language,\n packageManager: existing.packageManager,\n framework: existing.framework ?? fresh.framework,\n styling: existing.styling ?? fresh.styling,\n backend: existing.backend ?? fresh.backend,\n orm: existing.orm ?? fresh.orm,\n linter: existing.linter ?? fresh.linter,\n formatter: existing.formatter ?? fresh.formatter,\n testRunner: existing.testRunner ?? fresh.testRunner,\n };\n}\n\n/**\n * Merge structure: keep existing values, fill in undefined fields from fresh scan.\n */\nfunction mergeStructure(existing: ConfigStructure, fresh: ConfigStructure): ConfigStructure {\n return {\n srcDir: existing.srcDir ?? fresh.srcDir,\n pages: existing.pages ?? fresh.pages,\n components: existing.components ?? fresh.components,\n hooks: existing.hooks ?? fresh.hooks,\n utils: existing.utils ?? fresh.utils,\n types: existing.types ?? fresh.types,\n tests: existing.tests ?? fresh.tests,\n testPattern: existing.testPattern ?? fresh.testPattern,\n };\n}\n\n/**\n * Merge conventions: keep all existing values, add new ones from fresh scan.\n * New conventions are marked with `detected: true` in _meta.\n */\nfunction mergeConventions(\n existing: ConfigConventions,\n fresh: ConfigConventions,\n existingMeta: Record<string, ConventionMeta> | undefined,\n freshMeta: Record<string, ConventionMeta> | undefined,\n): { conventions: ConfigConventions; meta: Record<string, ConventionMeta> } {\n const conventions: ConfigConventions = { ...existing };\n const meta: Record<string, ConventionMeta> = { ...(existingMeta ?? {}) };\n\n for (const key of CONVENTION_KEYS) {\n if (existing[key] === undefined && fresh[key] !== undefined) {\n conventions[key] = fresh[key];\n // Mark as newly detected in meta\n if (freshMeta?.[key]) {\n meta[key] = { ...freshMeta[key], detected: true };\n }\n } else if (existing[key] !== undefined && freshMeta?.[key]) {\n // Update meta with latest scan data but preserve existing convention value\n meta[key] = { ...freshMeta[key], value: freshMeta[key].value };\n }\n }\n\n return { conventions, meta };\n}\n\n/**\n * Merge a single package config, preserving existing values and adding fresh detections.\n */\nfunction mergePackage(\n existing: PackageConfig,\n fresh: PackageConfig,\n existingMeta: Record<string, ConventionMeta> | undefined,\n freshMeta: Record<string, ConventionMeta> | undefined,\n): { pkg: PackageConfig; meta: Record<string, ConventionMeta> } {\n const { conventions, meta } = mergeConventions(\n existing.conventions ?? {},\n fresh.conventions ?? {},\n existingMeta,\n freshMeta,\n );\n\n return {\n pkg: {\n ...existing,\n stack: mergeStack(existing.stack ?? ({} as ConfigStack), fresh.stack ?? ({} as ConfigStack)),\n structure: mergeStructure(existing.structure ?? {}, fresh.structure ?? {}),\n conventions,\n },\n meta,\n };\n}\n\n/**\n * Merge a new scan result into an existing config for `viberails sync`.\n *\n * Preserves all developer-confirmed values from the existing config.\n * Adds newly detected values. New conventions are marked with\n * `detected: true` in _meta so the developer can review them.\n *\n * @param existing - The current ViberailsConfig (from viberails.config.json)\n * @param scanResult - Fresh scan results from re-scanning the project\n * @returns A merged config that preserves existing values and adds new detections\n */\nexport function mergeConfig(existing: ViberailsConfig, scanResult: ScanResult): ViberailsConfig {\n const fresh = generateConfig(scanResult);\n\n const existingByPath = new Map(existing.packages.map((p) => [p.path, p]));\n const freshByPath = new Map(fresh.packages.map((p) => [p.path, p]));\n\n const mergedPackages: PackageConfig[] = [];\n const mergedPkgMeta: Record<string, { conventions?: Record<string, ConventionMeta> }> = {};\n\n // Merge existing packages with fresh data\n for (const existingPkg of existing.packages) {\n const freshPkg = freshByPath.get(existingPkg.path);\n if (freshPkg) {\n const existingConvMeta = existing._meta?.packages?.[existingPkg.path]?.conventions;\n const freshConvMeta = fresh._meta?.packages?.[existingPkg.path]?.conventions;\n const { pkg, meta } = mergePackage(existingPkg, freshPkg, existingConvMeta, freshConvMeta);\n mergedPackages.push(pkg);\n if (Object.keys(meta).length > 0) {\n mergedPkgMeta[pkg.path] = { conventions: meta };\n }\n } else {\n mergedPackages.push(existingPkg);\n }\n }\n\n // Add new packages from fresh scan\n for (const freshPkg of fresh.packages) {\n if (!existingByPath.has(freshPkg.path)) {\n mergedPackages.push(freshPkg);\n const freshConvMeta = fresh._meta?.packages?.[freshPkg.path]?.conventions;\n if (freshConvMeta && Object.keys(freshConvMeta).length > 0) {\n mergedPkgMeta[freshPkg.path] = { conventions: freshConvMeta };\n }\n }\n }\n\n const merged: ViberailsConfig = {\n $schema: existing.$schema ?? fresh.$schema,\n version: existing.version,\n name: existing.name,\n rules: { ...existing.rules },\n ignore: [...(existing.ignore ?? [])],\n packages: mergedPackages,\n _meta: {\n lastSync: new Date().toISOString(),\n ...(Object.keys(mergedPkgMeta).length > 0 ? { packages: mergedPkgMeta } : {}),\n },\n };\n\n // Boundaries: preserve existing rules (user may have adjusted)\n if (existing.boundaries) {\n merged.boundaries = {\n deny: { ...existing.boundaries.deny },\n ...(existing.boundaries.ignore ? { ignore: [...existing.boundaries.ignore] } : {}),\n };\n } else if (fresh.boundaries) {\n merged.boundaries = {\n deny: { ...fresh.boundaries.deny },\n ...(fresh.boundaries.ignore ? { ignore: [...fresh.boundaries.ignore] } : {}),\n };\n }\n\n return merged;\n}\n","/**\n * Reusable sub-schema definitions extracted from the main config schema.\n * Keeps the primary schema file under 300 lines.\n */\n\nexport const boundarySchema = {\n type: 'object',\n required: ['deny'],\n properties: {\n deny: {\n type: 'object',\n additionalProperties: {\n type: 'array',\n items: { type: 'string' },\n },\n description:\n 'Map of source package/directory to the list of targets it must NOT import from.',\n },\n ignore: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'File paths that bypass boundary checks entirely (escape hatch for legitimate exceptions).',\n },\n },\n additionalProperties: false,\n} as const;\n\nexport const stackSchema = {\n type: 'object',\n properties: {\n framework: { type: 'string', description: 'Primary framework (e.g. \"nextjs@15\").' },\n language: { type: 'string', description: 'Primary language (e.g. \"typescript\").' },\n styling: { type: 'string', description: 'Styling solution (e.g. \"tailwindcss@4\").' },\n backend: { type: 'string', description: 'Backend framework (e.g. \"express@5\").' },\n orm: { type: 'string', description: 'ORM or database client (e.g. \"prisma\").' },\n packageManager: { type: 'string', description: 'Package manager (e.g. \"pnpm\").' },\n linter: { type: 'string', description: 'Linter (e.g. \"eslint@9\").' },\n formatter: { type: 'string', description: 'Formatter (e.g. \"prettier\").' },\n testRunner: { type: 'string', description: 'Test runner (e.g. \"vitest\").' },\n },\n additionalProperties: false,\n} as const;\n\nexport const structureSchema = {\n type: 'object',\n properties: {\n srcDir: { type: 'string', description: 'Source directory (e.g. \"src\").' },\n pages: { type: 'string', description: 'Pages or routes directory.' },\n components: { type: 'string', description: 'Components directory.' },\n hooks: { type: 'string', description: 'Hooks directory.' },\n utils: { type: 'string', description: 'Utilities directory.' },\n types: { type: 'string', description: 'Type definitions directory.' },\n tests: { type: 'string', description: 'Tests directory.' },\n testPattern: { type: 'string', description: 'Test file naming pattern (e.g. \"*.test.ts\").' },\n },\n additionalProperties: false,\n} as const;\n\nexport const conventionsSchema = {\n type: 'object',\n properties: {\n fileNaming: { type: 'string', description: 'File naming convention (e.g. \"kebab-case\").' },\n componentNaming: { type: 'string', description: 'Component naming convention.' },\n hookNaming: { type: 'string', description: 'Hook naming convention.' },\n importAlias: { type: 'string', description: 'Import alias pattern (e.g. \"@/*\").' },\n },\n additionalProperties: false,\n} as const;\n\nexport const coverageSchema = {\n type: 'object',\n properties: {\n command: {\n type: 'string',\n description: 'Command to generate coverage summary data for this package.',\n },\n summaryPath: {\n type: 'string',\n description: 'Path to coverage summary JSON relative to package root.',\n },\n },\n additionalProperties: false,\n} as const;\n\nexport const packageItemSchema = {\n type: 'object',\n required: ['name', 'path'],\n properties: {\n name: { type: 'string', description: 'Package name from package.json.' },\n path: { type: 'string', description: 'Relative path to the package (\".\" for root).' },\n stack: { ...stackSchema, description: 'Technology stack for this package.' },\n structure: { ...structureSchema, description: 'Directory structure for this package.' },\n conventions: { ...conventionsSchema, description: 'Coding conventions for this package.' },\n coverage: {\n ...coverageSchema,\n description: 'Coverage generation and summary settings for this package.',\n },\n rules: {\n type: 'object',\n properties: {\n maxFileLines: { type: 'number' },\n maxTestFileLines: { type: 'number' },\n testCoverage: { type: 'number' },\n enforceNaming: { type: 'boolean' },\n enforceBoundaries: { type: 'boolean' },\n enforceMissingTests: { type: 'boolean' },\n },\n additionalProperties: false,\n },\n ignore: { type: 'array', items: { type: 'string' } },\n boundaries: {\n type: 'object',\n properties: {\n deny: { type: 'array', items: { type: 'string' } },\n ignore: { type: 'array', items: { type: 'string' } },\n },\n additionalProperties: false,\n },\n },\n additionalProperties: false,\n} as const;\n\nexport const defaultsSchema = {\n type: 'object',\n properties: {\n stack: { ...stackSchema, description: 'Default stack inherited by all packages.' },\n structure: { ...structureSchema, description: 'Default structure inherited by all packages.' },\n conventions: {\n ...conventionsSchema,\n description: 'Default conventions inherited by all packages.',\n },\n coverage: {\n ...coverageSchema,\n description: 'Default coverage settings inherited by all packages.',\n },\n },\n additionalProperties: false,\n description: 'Shared defaults for all packages. Packages inherit and can override.',\n} as const;\n","/**\n * JSON Schema (draft-07) definition for viberails.config.json.\n *\n * This schema will eventually be hosted at https://viberails.sh/schema/v1.json.\n * For now it is exported as a TypeScript object that can be serialized to JSON.\n */\nimport { boundarySchema, defaultsSchema, packageItemSchema } from './schema-parts.js';\n\nexport const configSchema = {\n $schema: 'http://json-schema.org/draft-07/schema#',\n $id: 'https://viberails.sh/schema/v1.json',\n title: 'viberails configuration',\n description: 'Configuration file for viberails — guardrails for vibe coding.',\n type: 'object',\n required: ['version', 'name', 'packages', 'rules'],\n properties: {\n $schema: {\n type: 'string',\n description: 'JSON Schema URL for editor validation.',\n },\n version: {\n type: 'number',\n const: 1,\n description: 'Config format version. Always 1.',\n },\n name: {\n type: 'string',\n description: 'Project name, typically from package.json.',\n },\n rules: {\n type: 'object',\n required: [\n 'maxFileLines',\n 'testCoverage',\n 'enforceNaming',\n 'enforceBoundaries',\n 'enforceMissingTests',\n ],\n properties: {\n maxFileLines: {\n type: 'number',\n default: 300,\n description: 'Maximum number of lines allowed per file.',\n },\n maxTestFileLines: {\n type: 'number',\n default: 0,\n description:\n 'Maximum number of lines allowed per test file. Set to 0 to exempt test files.',\n },\n testCoverage: {\n type: 'number',\n default: 80,\n description:\n 'Minimum line coverage target percentage. 0 disables coverage threshold checks.',\n },\n enforceNaming: {\n type: 'boolean',\n default: true,\n description: 'Whether to enforce detected file naming conventions.',\n },\n enforceBoundaries: {\n type: 'boolean',\n default: false,\n description: 'Whether to enforce module boundary rules.',\n },\n enforceMissingTests: {\n type: 'boolean',\n default: true,\n description: 'Whether to enforce that every source file has a corresponding test file.',\n },\n },\n additionalProperties: false,\n description: 'Rule thresholds and toggles for enforcement.',\n },\n ignore: {\n type: 'array',\n items: { type: 'string' },\n description: 'Project-specific glob patterns to ignore (universal patterns are built-in).',\n },\n boundaries: {\n ...boundarySchema,\n description: 'Module boundary rules for import enforcement.',\n },\n defaults: defaultsSchema,\n packages: {\n type: 'array',\n items: packageItemSchema,\n description: 'Per-package configs. Single projects use path \".\".',\n },\n _meta: {\n type: 'object',\n properties: {\n lastSync: { type: 'string', description: 'ISO timestamp of last sync.' },\n packages: {\n type: 'object',\n additionalProperties: {\n type: 'object',\n properties: {\n conventions: {\n type: 'object',\n additionalProperties: {\n type: 'object',\n properties: {\n value: { type: 'string' },\n confidence: { type: 'string', enum: ['high', 'medium', 'low'] },\n consistency: { type: 'number' },\n detected: { type: 'boolean' },\n },\n },\n },\n },\n },\n },\n },\n description: 'Scanner metadata. Regenerated on every sync — not user-editable.',\n },\n },\n additionalProperties: false,\n} as const;\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -459,6 +459,9 @@ declare const configSchema: {
459
459
  readonly enforceBoundaries: {
460
460
  readonly type: "boolean";
461
461
  };
462
+ readonly enforceMissingTests: {
463
+ readonly type: "boolean";
464
+ };
462
465
  };
463
466
  readonly additionalProperties: false;
464
467
  };
package/dist/index.d.ts CHANGED
@@ -459,6 +459,9 @@ declare const configSchema: {
459
459
  readonly enforceBoundaries: {
460
460
  readonly type: "boolean";
461
461
  };
462
+ readonly enforceMissingTests: {
463
+ readonly type: "boolean";
464
+ };
462
465
  };
463
466
  readonly additionalProperties: false;
464
467
  };
package/dist/index.js CHANGED
@@ -138,6 +138,9 @@ function mapStructure(scanResult) {
138
138
  }
139
139
  if (structure.testPattern) {
140
140
  config.testPattern = structure.testPattern.value;
141
+ } else {
142
+ const isTypeScript = scanResult.stack.language.name === "typescript";
143
+ config.testPattern = isTypeScript ? "*.test.ts" : "*.test.js";
141
144
  }
142
145
  return config;
143
146
  }
@@ -760,7 +763,8 @@ var packageItemSchema = {
760
763
  maxTestFileLines: { type: "number" },
761
764
  testCoverage: { type: "number" },
762
765
  enforceNaming: { type: "boolean" },
763
- enforceBoundaries: { type: "boolean" }
766
+ enforceBoundaries: { type: "boolean" },
767
+ enforceMissingTests: { type: "boolean" }
764
768
  },
765
769
  additionalProperties: false
766
770
  },
@@ -907,7 +911,7 @@ var configSchema = {
907
911
  };
908
912
 
909
913
  // src/index.ts
910
- var VERSION = "0.5.5";
914
+ var VERSION = "0.6.0";
911
915
  export {
912
916
  BUILTIN_IGNORE,
913
917
  DEFAULT_IGNORE,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/generate-config.ts","../src/defaults.ts","../src/generate-packages.ts","../src/infer-coverage-command.ts","../src/compact-config.ts","../src/load-config.ts","../src/merge-config.ts","../src/schema-parts.ts","../src/schema.ts","../src/index.ts"],"sourcesContent":["import * as path from 'node:path';\nimport type {\n ConfigConventions,\n ConfigMeta,\n ConfigStack,\n ConfigStructure,\n ConventionMeta,\n DetectedConvention,\n DirectoryRole,\n PackageConfig,\n ScanResult,\n StackItem,\n ViberailsConfig,\n} from '@viberails/types';\nimport { DEFAULT_IGNORE, DEFAULT_RULES } from './defaults.js';\nimport { generatePackages } from './generate-packages.js';\nimport { inferCoverageCommand } from './infer-coverage-command.js';\n\n/**\n * Format a StackItem as a config string: `\"name@version\"` or `\"name\"`.\n */\nexport function formatStackItem(item: StackItem): string {\n return item.version ? `${item.name}@${item.version}` : item.name;\n}\n\n/**\n * Map DetectedStack → ConfigStack by formatting each StackItem.\n */\nexport function mapStack(scanResult: ScanResult): ConfigStack {\n const { stack } = scanResult;\n const config: ConfigStack = {\n language: formatStackItem(stack.language),\n packageManager: formatStackItem(stack.packageManager),\n };\n\n if (stack.framework) config.framework = formatStackItem(stack.framework);\n if (stack.styling) config.styling = formatStackItem(stack.styling);\n if (stack.backend) config.backend = formatStackItem(stack.backend);\n if (stack.orm) config.orm = formatStackItem(stack.orm);\n if (stack.linter) config.linter = formatStackItem(stack.linter);\n if (stack.formatter) config.formatter = formatStackItem(stack.formatter);\n if (stack.testRunner) config.testRunner = formatStackItem(stack.testRunner);\n\n return config;\n}\n\n/** Directory roles that map to ConfigStructure fields. */\nconst ROLE_TO_FIELD: Partial<Record<DirectoryRole, keyof ConfigStructure>> = {\n pages: 'pages',\n components: 'components',\n hooks: 'hooks',\n utils: 'utils',\n types: 'types',\n tests: 'tests',\n};\n\n/**\n * Map DetectedStructure → ConfigStructure by finding the first directory\n * for each known role.\n */\nexport function mapStructure(scanResult: ScanResult): ConfigStructure {\n const { structure } = scanResult;\n const config: ConfigStructure = {};\n\n if (structure.srcDir) {\n config.srcDir = structure.srcDir;\n }\n\n for (const dir of structure.directories) {\n const field = ROLE_TO_FIELD[dir.role];\n if (field && config[field] === undefined) {\n (config as Record<string, string>)[field] = dir.path;\n }\n }\n\n if (structure.testPattern) {\n config.testPattern = structure.testPattern.value;\n }\n\n return config;\n}\n\n/** Convention keys from ScanResult that map to ConfigConventions fields. */\nexport const CONVENTION_KEYS: (keyof ConfigConventions)[] = [\n 'fileNaming',\n 'componentNaming',\n 'hookNaming',\n 'importAlias',\n];\n\n/**\n * Map scanner conventions → ConfigConventions as plain strings.\n * Low-confidence conventions are omitted.\n * Returns both the plain-string conventions and the metadata for _meta.\n */\nfunction mapConventions(scanResult: ScanResult): {\n conventions: ConfigConventions;\n meta: Record<string, ConventionMeta>;\n} {\n const conventions: ConfigConventions = {};\n const meta: Record<string, ConventionMeta> = {};\n\n for (const key of CONVENTION_KEYS) {\n const detected = scanResult.conventions[key];\n if (detected && detected.confidence !== 'low') {\n conventions[key] = detected.value;\n meta[key] = {\n value: detected.value,\n confidence: detected.confidence,\n consistency: detected.consistency,\n };\n }\n }\n\n return { conventions, meta };\n}\n\n/**\n * Build _meta for a single package's conventions.\n */\nexport function buildConventionMeta(\n conventions: Record<string, DetectedConvention>,\n): Record<string, ConventionMeta> {\n const meta: Record<string, ConventionMeta> = {};\n for (const key of CONVENTION_KEYS) {\n const detected = conventions[key];\n if (detected && detected.confidence !== 'low') {\n meta[key] = {\n value: detected.value,\n confidence: detected.confidence,\n consistency: detected.consistency,\n };\n }\n }\n return meta;\n}\n\n/**\n * Generate a ViberailsConfig from scan results.\n *\n * Produces the packages-first config format: all config lives in `packages[]`.\n * Single projects get one package with `path: \".\"`.\n * Monorepos get one package per workspace package.\n *\n * @param scanResult - The output of scanning a project\n * @returns A complete ViberailsConfig ready to be written as JSON\n */\nexport function generateConfig(scanResult: ScanResult): ViberailsConfig {\n const projectName = path.basename(scanResult.root);\n const { conventions, meta } = mapConventions(scanResult);\n\n // Build the root package\n const rootPackage: PackageConfig = {\n name: projectName,\n path: '.',\n stack: mapStack(scanResult),\n structure: mapStructure(scanResult),\n conventions,\n };\n\n const _meta: ConfigMeta = {\n lastSync: new Date().toISOString(),\n packages: {\n '.': { conventions: Object.keys(meta).length > 0 ? meta : undefined },\n },\n };\n\n const config: ViberailsConfig = {\n $schema: 'https://viberails.sh/schema/v1.json',\n version: 1,\n name: projectName,\n rules: { ...DEFAULT_RULES },\n ignore: [...DEFAULT_IGNORE],\n packages: [rootPackage],\n _meta,\n };\n\n // Infer coverage command from detected test runner\n const testRunner = scanResult.stack.testRunner;\n const coverageCommand = inferCoverageCommand(\n testRunner ? formatStackItem(testRunner) : undefined,\n );\n if (coverageCommand) {\n config.defaults = { coverage: { command: coverageCommand } };\n }\n\n // Monorepo: generate per-package configs\n if (scanResult.workspace) {\n const packages = generatePackages(scanResult);\n if (packages) {\n config.packages = packages;\n\n // If packages have different test runners, set per-package coverage\n // commands instead of a global default (which would be wrong for some).\n const runners = new Set(\n packages.map((p) => p.stack?.testRunner?.split('@')[0]).filter(Boolean),\n );\n if (runners.size > 1) {\n delete config.defaults?.coverage?.command;\n for (const pkg of packages) {\n const pkgCommand = inferCoverageCommand(pkg.stack?.testRunner);\n if (pkgCommand) {\n pkg.coverage = { ...pkg.coverage, command: pkgCommand };\n }\n }\n }\n // Rebuild _meta for all packages\n const pkgMeta: Record<string, { conventions?: Record<string, ConventionMeta> }> = {};\n for (const pkg of scanResult.packages) {\n const convMeta = buildConventionMeta(pkg.conventions);\n if (Object.keys(convMeta).length > 0) {\n pkgMeta[pkg.relativePath] = { conventions: convMeta };\n }\n }\n if (Object.keys(pkgMeta).length > 0) {\n _meta.packages = pkgMeta;\n }\n }\n config.boundaries = { deny: {} };\n }\n\n return config;\n}\n","import type { ConfigRules } from '@viberails/types';\n\n/**\n * Default rule thresholds and toggles for a new viberails config.\n * These values are intentionally conservative to build trust on first run.\n */\nexport const DEFAULT_RULES: ConfigRules = {\n maxFileLines: 300,\n maxTestFileLines: 0,\n testCoverage: 80,\n enforceNaming: true,\n enforceBoundaries: false,\n enforceMissingTests: true,\n};\n\n/**\n * Default project-specific ignore patterns for a new config.\n * Empty — universal patterns live in BUILTIN_IGNORE and are applied at check-time.\n */\nexport const DEFAULT_IGNORE: string[] = [];\n\n/**\n * Universal ignore patterns applied at check-time.\n * These are never written to config — they are always applied implicitly.\n */\nexport const BUILTIN_IGNORE: string[] = [\n '**/*.d.ts',\n '**/*.min.js',\n '**/*.min.cjs',\n '**/*.umd.js',\n '**/*.bundle.js',\n 'dist/**',\n 'node_modules/**',\n 'build/**',\n '.next/**',\n '.expo/**',\n '.output/**',\n '.svelte-kit/**',\n '.turbo/**',\n 'coverage/**',\n '**/public/**',\n '**/vendor/**',\n '.viberails/**',\n '**/generated/**',\n '**/__generated__/**',\n];\n","import type { ConfigConventions, ConfigStack, PackageConfig, ScanResult } from '@viberails/types';\nimport { CONVENTION_KEYS, formatStackItem, mapStructure } from './generate-config.js';\n\n/**\n * Build a full ConfigStack for a single package scan result.\n */\nfunction buildPackageStack(pkg: ScanResult['packages'][number]): ConfigStack {\n const config: ConfigStack = {\n language: formatStackItem(pkg.stack.language),\n packageManager: formatStackItem(pkg.stack.packageManager),\n };\n\n if (pkg.stack.framework) config.framework = formatStackItem(pkg.stack.framework);\n if (pkg.stack.styling) config.styling = formatStackItem(pkg.stack.styling);\n if (pkg.stack.backend) config.backend = formatStackItem(pkg.stack.backend);\n if (pkg.stack.orm) config.orm = formatStackItem(pkg.stack.orm);\n if (pkg.stack.linter) config.linter = formatStackItem(pkg.stack.linter);\n if (pkg.stack.formatter) config.formatter = formatStackItem(pkg.stack.formatter);\n if (pkg.stack.testRunner) config.testRunner = formatStackItem(pkg.stack.testRunner);\n\n return config;\n}\n\n/**\n * Build ConfigConventions as plain strings, omitting low-confidence entries.\n */\nfunction buildPackageConventions(\n pkgConventions: Record<string, import('@viberails/types').DetectedConvention>,\n): ConfigConventions {\n const config: ConfigConventions = {};\n\n for (const key of CONVENTION_KEYS) {\n const detected = pkgConventions[key];\n if (detected && detected.confidence !== 'low') {\n config[key] = detected.value;\n }\n }\n\n return config;\n}\n\n/**\n * Generate self-contained per-package configs for packages in a monorepo.\n * Each PackageConfig has its own full stack, structure, and conventions.\n *\n * Returns undefined for single-package projects.\n */\nexport function generatePackages(scanResult: ScanResult): PackageConfig[] | undefined {\n if (!scanResult.packages || scanResult.packages.length <= 1) return undefined;\n\n const packages: PackageConfig[] = [];\n\n for (const pkg of scanResult.packages) {\n // Build a temporary ScanResult-like object for mapStructure\n const pkgScanResult = {\n root: pkg.root,\n stack: pkg.stack,\n structure: pkg.structure,\n conventions: pkg.conventions,\n statistics: pkg.statistics,\n } as ScanResult;\n\n const packageConfig: PackageConfig = {\n name: pkg.name,\n path: pkg.relativePath,\n stack: buildPackageStack(pkg),\n structure: mapStructure(pkgScanResult),\n conventions: buildPackageConventions(pkg.conventions),\n };\n\n if (pkg.typesOnly) {\n packageConfig.rules = { testCoverage: 0 };\n }\n\n packages.push(packageConfig);\n }\n\n return packages.length > 0 ? packages : undefined;\n}\n","/**\n * Infer a coverage command from the detected test runner string.\n *\n * Used during `init` to store the inferred command in config so that\n * `check` can use it explicitly. Does not verify binary availability —\n * the command is stored as a suggestion for the user to review.\n *\n * @param testRunner - Test runner string from config (e.g. \"vitest@4\", \"jest@29\")\n * @returns Shell command string, or undefined if the runner is unsupported\n */\nexport function inferCoverageCommand(testRunner: string | undefined): string | undefined {\n if (!testRunner) return undefined;\n const runner = testRunner.split('@')[0];\n if (runner === 'vitest') {\n return 'npx vitest run --coverage --coverage.reporter=json-summary';\n }\n if (runner === 'jest') {\n return 'npx jest --coverage --coverageReporters=json-summary';\n }\n return undefined;\n}\n","import type {\n ConfigConventions,\n ConfigCoverage,\n ConfigDefaults,\n ConfigStack,\n ConfigStructure,\n ViberailsConfig,\n} from '@viberails/types';\nimport { CONVENTION_KEYS } from './generate-config.js';\n\n/** Stack field keys for comparison and extraction. */\nexport const STACK_KEYS: (keyof ConfigStack)[] = [\n 'language',\n 'packageManager',\n 'framework',\n 'styling',\n 'backend',\n 'orm',\n 'linter',\n 'formatter',\n 'testRunner',\n];\n\n/** Structure field keys for comparison and extraction. */\nexport const STRUCTURE_KEYS: (keyof ConfigStructure)[] = [\n 'srcDir',\n 'pages',\n 'components',\n 'hooks',\n 'utils',\n 'types',\n 'tests',\n 'testPattern',\n];\n\n/**\n * Extract shared values from packages into defaults and strip them from packages.\n * Only extracts values that are identical across ALL packages.\n * Strips empty objects from packages for clean JSON output.\n */\nexport function compactConfig(config: ViberailsConfig): ViberailsConfig {\n const pkgs = config.packages ?? [];\n\n const defaults: ConfigDefaults = {};\n\n // Start with copies; merge any existing defaults into each package first\n // so the extraction logic below works uniformly for 1 or N packages.\n const packages = pkgs.map((p) => {\n const copy = { ...p };\n if (config.defaults?.coverage) {\n copy.coverage = { ...config.defaults.coverage, ...(copy.coverage ?? {}) };\n }\n if (config.defaults?.stack) {\n copy.stack = { ...config.defaults.stack, ...(copy.stack ?? {}) } as ConfigStack;\n }\n if (config.defaults?.structure) {\n copy.structure = { ...config.defaults.structure, ...(copy.structure ?? {}) };\n }\n if (config.defaults?.conventions) {\n copy.conventions = { ...config.defaults.conventions, ...(copy.conventions ?? {}) };\n }\n return copy;\n });\n\n // For multi-package configs, extract shared values into defaults.\n // Single-package configs keep everything on the package (no defaults needed).\n if (packages.length <= 1) {\n // Strip empty objects from the single package\n for (const pkg of packages) {\n if (pkg.stack && Object.keys(pkg.stack).length === 0) delete pkg.stack;\n if (pkg.structure && Object.keys(pkg.structure).length === 0) delete pkg.structure;\n if (pkg.conventions && Object.keys(pkg.conventions).length === 0) delete pkg.conventions;\n if (pkg.coverage && Object.keys(pkg.coverage).length === 0) delete pkg.coverage;\n }\n const { defaults: _d, ...rest } = config;\n return { ...rest, packages };\n }\n\n // Extract shared stack fields\n const sharedStack: Partial<ConfigStack> = {};\n for (const key of STACK_KEYS) {\n const values = packages.map((p) => (p.stack ?? ({} as Partial<ConfigStack>))[key]);\n if (values[0] !== undefined && values.every((v) => v === values[0])) {\n sharedStack[key] = values[0] as string;\n }\n }\n if (Object.keys(sharedStack).length > 0) {\n defaults.stack = sharedStack;\n for (const pkg of packages) {\n const pkgStack = (pkg.stack ?? {}) as Partial<ConfigStack>;\n const sparse: Partial<ConfigStack> = {};\n for (const key of STACK_KEYS) {\n if (pkgStack[key] !== undefined && pkgStack[key] !== sharedStack[key]) {\n sparse[key] = pkgStack[key] as string;\n }\n }\n pkg.stack = sparse as ConfigStack;\n }\n }\n\n // Extract shared structure fields\n const sharedStructure: Partial<ConfigStructure> = {};\n for (const key of STRUCTURE_KEYS) {\n const values = packages.map((p) => p.structure?.[key]);\n const first = values[0];\n if (first !== undefined && values.every((v) => JSON.stringify(v) === JSON.stringify(first))) {\n (sharedStructure as Record<string, unknown>)[key] = first;\n }\n }\n if (Object.keys(sharedStructure).length > 0) {\n defaults.structure = sharedStructure;\n for (const pkg of packages) {\n const pkgStructure = pkg.structure ?? {};\n const sparse: Partial<ConfigStructure> = {};\n for (const key of STRUCTURE_KEYS) {\n const val = pkgStructure[key];\n if (val !== undefined && JSON.stringify(val) !== JSON.stringify(sharedStructure[key])) {\n (sparse as Record<string, unknown>)[key] = val;\n }\n }\n pkg.structure = sparse as ConfigStructure;\n }\n }\n\n // Extract shared conventions\n const sharedConventions: ConfigConventions = {};\n for (const key of CONVENTION_KEYS) {\n const values = packages.map((p) => p.conventions?.[key]);\n if (values[0] !== undefined && values.every((v) => v === values[0])) {\n sharedConventions[key] = values[0];\n }\n }\n\n // Extract shared coverage settings\n const sharedCoverage: ConfigCoverage = {};\n const coverageKeys: (keyof ConfigCoverage)[] = ['command', 'summaryPath'];\n for (const key of coverageKeys) {\n const values = packages.map((p) => p.coverage?.[key]);\n if (values[0] !== undefined && values.every((v) => v === values[0])) {\n sharedCoverage[key] = values[0];\n }\n }\n if (Object.keys(sharedCoverage).length > 0) {\n defaults.coverage = sharedCoverage;\n for (const pkg of packages) {\n const pkgCoverage = pkg.coverage ?? {};\n const sparse: ConfigCoverage = {};\n for (const key of coverageKeys) {\n if (pkgCoverage[key] !== undefined && pkgCoverage[key] !== sharedCoverage[key]) {\n sparse[key] = pkgCoverage[key];\n }\n }\n pkg.coverage = sparse;\n }\n }\n if (Object.keys(sharedConventions).length > 0) {\n defaults.conventions = sharedConventions;\n for (const pkg of packages) {\n const pkgConventions = pkg.conventions ?? {};\n const sparse: ConfigConventions = {};\n for (const key of CONVENTION_KEYS) {\n if (pkgConventions[key] !== undefined && pkgConventions[key] !== sharedConventions[key]) {\n sparse[key] = pkgConventions[key];\n }\n }\n pkg.conventions = sparse;\n }\n }\n\n // Strip empty objects from packages\n for (const pkg of packages) {\n if (pkg.stack && Object.keys(pkg.stack).length === 0) {\n delete pkg.stack;\n }\n if (pkg.structure && Object.keys(pkg.structure).length === 0) {\n delete pkg.structure;\n }\n if (pkg.conventions && Object.keys(pkg.conventions).length === 0) {\n delete pkg.conventions;\n }\n if (pkg.coverage && Object.keys(pkg.coverage).length === 0) {\n delete pkg.coverage;\n }\n }\n\n // Reconstruct with explicit key ordering so JSON output is readable:\n // $schema, version, name, rules, ignore, boundaries, defaults, packages, _meta\n const result: ViberailsConfig = {\n ...(config.$schema ? { $schema: config.$schema } : {}),\n version: config.version,\n name: config.name,\n rules: config.rules,\n ...(config.ignore && config.ignore.length > 0 ? { ignore: config.ignore } : {}),\n ...(config.boundaries ? { boundaries: config.boundaries } : {}),\n ...(Object.keys(defaults).length > 0 ? { defaults } : {}),\n packages,\n ...(config._meta ? { _meta: config._meta } : {}),\n };\n return result;\n}\n\n/**\n * Expand defaults into each package, producing fully self-contained packages.\n * Inverse of compactConfig. Ensures every package has stack, structure,\n * and conventions (even as empty objects) and config.ignore defaults to [].\n */\nexport function expandDefaults(config: ViberailsConfig): ViberailsConfig {\n const defaults = config.defaults;\n\n const packages = config.packages.map((pkg) => {\n const expanded = { ...pkg };\n\n // Merge defaults into package fields, or initialize to empty objects\n expanded.stack = { ...(defaults?.stack ?? {}), ...(pkg.stack ?? {}) } as ConfigStack;\n expanded.structure = { ...(defaults?.structure ?? {}), ...(pkg.structure ?? {}) };\n expanded.conventions = { ...(defaults?.conventions ?? {}), ...(pkg.conventions ?? {}) };\n const mergedCoverage = { ...(defaults?.coverage ?? {}), ...(pkg.coverage ?? {}) };\n if (Object.keys(mergedCoverage).length > 0) {\n expanded.coverage = mergedCoverage;\n } else {\n delete expanded.coverage;\n }\n\n return expanded;\n });\n\n // Ensure ignore defaults to []\n const ignore = config.ignore ?? [];\n\n // Return without defaults — packages are now self-contained\n const { defaults: _d, ...rest } = config;\n return { ...rest, ignore, packages };\n}\n","import * as fs from 'node:fs/promises';\nimport type { ViberailsConfig } from '@viberails/types';\nimport { expandDefaults } from './compact-config.js';\n\n/**\n * Validate that a parsed object has the required ViberailsConfig fields\n * and that their types are correct.\n * Throws a descriptive error if validation fails.\n */\nfunction validateConfig(parsed: Record<string, unknown>, configPath: string): void {\n const errors: string[] = [];\n\n // Required top-level fields\n const required = ['version', 'name', 'packages', 'rules'] as const;\n const missing = required.filter((field) => parsed[field] === undefined);\n if (missing.length > 0) {\n throw new Error(\n `Invalid viberails config at ${configPath}: missing required field(s): ${missing.join(', ')}`,\n );\n }\n\n // Type checks\n if (typeof parsed.version !== 'number') {\n errors.push('\"version\" must be a number');\n } else if (parsed.version !== 1) {\n errors.push('\"version\" must be 1');\n }\n if (typeof parsed.name !== 'string') errors.push('\"name\" must be a string');\n // Packages validation\n if (!Array.isArray(parsed.packages)) {\n errors.push('\"packages\" must be an array');\n } else if (parsed.packages.length === 0) {\n errors.push('\"packages\" must contain at least one package');\n } else {\n for (let i = 0; i < parsed.packages.length; i++) {\n const pkg = parsed.packages[i] as Record<string, unknown>;\n if (typeof pkg.name !== 'string') errors.push(`\"packages[${i}].name\" must be a string`);\n if (typeof pkg.path !== 'string') errors.push(`\"packages[${i}].path\" must be a string`);\n if (pkg.coverage !== undefined) {\n if (typeof pkg.coverage !== 'object' || pkg.coverage === null) {\n errors.push(`\"packages[${i}].coverage\" must be an object`);\n } else {\n const coverage = pkg.coverage as Record<string, unknown>;\n if (coverage.command !== undefined && typeof coverage.command !== 'string') {\n errors.push(`\"packages[${i}].coverage.command\" must be a string`);\n }\n if (coverage.summaryPath !== undefined && typeof coverage.summaryPath !== 'string') {\n errors.push(`\"packages[${i}].coverage.summaryPath\" must be a string`);\n }\n }\n }\n }\n }\n\n // Rules validation\n if (typeof parsed.rules !== 'object' || parsed.rules === null) {\n errors.push('\"rules\" must be an object');\n } else {\n const rules = parsed.rules as Record<string, unknown>;\n if (typeof rules.maxFileLines !== 'number')\n errors.push('\"rules.maxFileLines\" must be a number');\n else if (rules.maxFileLines < 0) errors.push('\"rules.maxFileLines\" must be >= 0');\n if (rules.maxTestFileLines !== undefined) {\n if (typeof rules.maxTestFileLines !== 'number') {\n errors.push('\"rules.maxTestFileLines\" must be a number');\n } else if (rules.maxTestFileLines < 0) {\n errors.push('\"rules.maxTestFileLines\" must be >= 0');\n }\n }\n if (typeof rules.testCoverage !== 'number')\n errors.push('\"rules.testCoverage\" must be a number');\n else if (rules.testCoverage < 0 || rules.testCoverage > 100)\n errors.push('\"rules.testCoverage\" must be between 0 and 100');\n if (typeof rules.enforceNaming !== 'boolean')\n errors.push('\"rules.enforceNaming\" must be a boolean');\n if (typeof rules.enforceBoundaries !== 'boolean')\n errors.push('\"rules.enforceBoundaries\" must be a boolean');\n }\n\n // Ignore validation\n if (parsed.ignore !== undefined && !Array.isArray(parsed.ignore)) {\n errors.push('\"ignore\" must be an array');\n }\n\n // Defaults validation\n if (parsed.defaults !== undefined) {\n if (typeof parsed.defaults !== 'object' || parsed.defaults === null) {\n errors.push('\"defaults\" must be an object');\n } else {\n const defaults = parsed.defaults as Record<string, unknown>;\n if (defaults.coverage !== undefined) {\n if (typeof defaults.coverage !== 'object' || defaults.coverage === null) {\n errors.push('\"defaults.coverage\" must be an object');\n } else {\n const coverage = defaults.coverage as Record<string, unknown>;\n if (coverage.command !== undefined && typeof coverage.command !== 'string') {\n errors.push('\"defaults.coverage.command\" must be a string');\n }\n if (coverage.summaryPath !== undefined && typeof coverage.summaryPath !== 'string') {\n errors.push('\"defaults.coverage.summaryPath\" must be a string');\n }\n }\n }\n }\n }\n\n if (errors.length > 0) {\n throw new Error(`Invalid viberails config at ${configPath}: ${errors.join('; ')}`);\n }\n}\n\n/**\n * Load and parse a viberails config file.\n *\n * Reads the JSON file at the given path, validates that it contains\n * the required fields (version, name, packages, rules), expands\n * defaults into packages, and returns the parsed config.\n *\n * @param configPath - Absolute or relative path to viberails.config.json\n * @returns The parsed ViberailsConfig with defaults expanded\n * @throws If the file doesn't exist, contains invalid JSON, or is missing required fields\n */\nexport async function loadConfig(configPath: string): Promise<ViberailsConfig> {\n let raw: string;\n try {\n raw = await fs.readFile(configPath, 'utf-8');\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') {\n throw new Error(`Config file not found: ${configPath}. Run \"npx viberails\" to generate one.`);\n }\n throw new Error(`Failed to read config file at ${configPath}: ${(err as Error).message}`);\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n throw new Error(`Invalid JSON in config file at ${configPath}. Check for syntax errors.`);\n }\n\n validateConfig(parsed, configPath);\n\n // Apply defaults for optional fields added after initial release\n const rules = parsed.rules as Record<string, unknown>;\n if (rules.maxTestFileLines === undefined) {\n rules.maxTestFileLines = 0;\n }\n if (rules.enforceMissingTests === undefined) {\n rules.enforceMissingTests = true;\n }\n\n // Default ignore to [] if missing\n if (parsed.ignore === undefined) {\n parsed.ignore = [];\n }\n\n // Safe to cast: validateConfig has verified all required fields and types\n let config = parsed as unknown as ViberailsConfig;\n\n // Expand defaults into packages so they are self-contained\n config = expandDefaults(config);\n\n return config;\n}\n\n/**\n * Safely load a viberails config file, returning null on any error.\n *\n * Used by the CLI for \"does config already exist?\" checks where\n * failure is an expected case, not an error.\n *\n * @param configPath - Absolute or relative path to viberails.config.json\n * @returns The parsed ViberailsConfig, or null if loading fails\n */\nexport async function loadConfigSafe(configPath: string): Promise<ViberailsConfig | null> {\n try {\n return await loadConfig(configPath);\n } catch {\n return null;\n }\n}\n","import type {\n ConfigConventions,\n ConfigStack,\n ConfigStructure,\n ConventionMeta,\n PackageConfig,\n ScanResult,\n ViberailsConfig,\n} from '@viberails/types';\nimport { CONVENTION_KEYS, generateConfig } from './generate-config.js';\n\n/**\n * Merge stack: keep existing values, fill in undefined fields from fresh scan.\n */\nfunction mergeStack(existing: ConfigStack, fresh: ConfigStack): ConfigStack {\n return {\n language: existing.language,\n packageManager: existing.packageManager,\n framework: existing.framework ?? fresh.framework,\n styling: existing.styling ?? fresh.styling,\n backend: existing.backend ?? fresh.backend,\n orm: existing.orm ?? fresh.orm,\n linter: existing.linter ?? fresh.linter,\n formatter: existing.formatter ?? fresh.formatter,\n testRunner: existing.testRunner ?? fresh.testRunner,\n };\n}\n\n/**\n * Merge structure: keep existing values, fill in undefined fields from fresh scan.\n */\nfunction mergeStructure(existing: ConfigStructure, fresh: ConfigStructure): ConfigStructure {\n return {\n srcDir: existing.srcDir ?? fresh.srcDir,\n pages: existing.pages ?? fresh.pages,\n components: existing.components ?? fresh.components,\n hooks: existing.hooks ?? fresh.hooks,\n utils: existing.utils ?? fresh.utils,\n types: existing.types ?? fresh.types,\n tests: existing.tests ?? fresh.tests,\n testPattern: existing.testPattern ?? fresh.testPattern,\n };\n}\n\n/**\n * Merge conventions: keep all existing values, add new ones from fresh scan.\n * New conventions are marked with `detected: true` in _meta.\n */\nfunction mergeConventions(\n existing: ConfigConventions,\n fresh: ConfigConventions,\n existingMeta: Record<string, ConventionMeta> | undefined,\n freshMeta: Record<string, ConventionMeta> | undefined,\n): { conventions: ConfigConventions; meta: Record<string, ConventionMeta> } {\n const conventions: ConfigConventions = { ...existing };\n const meta: Record<string, ConventionMeta> = { ...(existingMeta ?? {}) };\n\n for (const key of CONVENTION_KEYS) {\n if (existing[key] === undefined && fresh[key] !== undefined) {\n conventions[key] = fresh[key];\n // Mark as newly detected in meta\n if (freshMeta?.[key]) {\n meta[key] = { ...freshMeta[key], detected: true };\n }\n } else if (existing[key] !== undefined && freshMeta?.[key]) {\n // Update meta with latest scan data but preserve existing convention value\n meta[key] = { ...freshMeta[key], value: freshMeta[key].value };\n }\n }\n\n return { conventions, meta };\n}\n\n/**\n * Merge a single package config, preserving existing values and adding fresh detections.\n */\nfunction mergePackage(\n existing: PackageConfig,\n fresh: PackageConfig,\n existingMeta: Record<string, ConventionMeta> | undefined,\n freshMeta: Record<string, ConventionMeta> | undefined,\n): { pkg: PackageConfig; meta: Record<string, ConventionMeta> } {\n const { conventions, meta } = mergeConventions(\n existing.conventions ?? {},\n fresh.conventions ?? {},\n existingMeta,\n freshMeta,\n );\n\n return {\n pkg: {\n ...existing,\n stack: mergeStack(existing.stack ?? ({} as ConfigStack), fresh.stack ?? ({} as ConfigStack)),\n structure: mergeStructure(existing.structure ?? {}, fresh.structure ?? {}),\n conventions,\n },\n meta,\n };\n}\n\n/**\n * Merge a new scan result into an existing config for `viberails sync`.\n *\n * Preserves all developer-confirmed values from the existing config.\n * Adds newly detected values. New conventions are marked with\n * `detected: true` in _meta so the developer can review them.\n *\n * @param existing - The current ViberailsConfig (from viberails.config.json)\n * @param scanResult - Fresh scan results from re-scanning the project\n * @returns A merged config that preserves existing values and adds new detections\n */\nexport function mergeConfig(existing: ViberailsConfig, scanResult: ScanResult): ViberailsConfig {\n const fresh = generateConfig(scanResult);\n\n const existingByPath = new Map(existing.packages.map((p) => [p.path, p]));\n const freshByPath = new Map(fresh.packages.map((p) => [p.path, p]));\n\n const mergedPackages: PackageConfig[] = [];\n const mergedPkgMeta: Record<string, { conventions?: Record<string, ConventionMeta> }> = {};\n\n // Merge existing packages with fresh data\n for (const existingPkg of existing.packages) {\n const freshPkg = freshByPath.get(existingPkg.path);\n if (freshPkg) {\n const existingConvMeta = existing._meta?.packages?.[existingPkg.path]?.conventions;\n const freshConvMeta = fresh._meta?.packages?.[existingPkg.path]?.conventions;\n const { pkg, meta } = mergePackage(existingPkg, freshPkg, existingConvMeta, freshConvMeta);\n mergedPackages.push(pkg);\n if (Object.keys(meta).length > 0) {\n mergedPkgMeta[pkg.path] = { conventions: meta };\n }\n } else {\n mergedPackages.push(existingPkg);\n }\n }\n\n // Add new packages from fresh scan\n for (const freshPkg of fresh.packages) {\n if (!existingByPath.has(freshPkg.path)) {\n mergedPackages.push(freshPkg);\n const freshConvMeta = fresh._meta?.packages?.[freshPkg.path]?.conventions;\n if (freshConvMeta && Object.keys(freshConvMeta).length > 0) {\n mergedPkgMeta[freshPkg.path] = { conventions: freshConvMeta };\n }\n }\n }\n\n const merged: ViberailsConfig = {\n $schema: existing.$schema ?? fresh.$schema,\n version: existing.version,\n name: existing.name,\n rules: { ...existing.rules },\n ignore: [...(existing.ignore ?? [])],\n packages: mergedPackages,\n _meta: {\n lastSync: new Date().toISOString(),\n ...(Object.keys(mergedPkgMeta).length > 0 ? { packages: mergedPkgMeta } : {}),\n },\n };\n\n // Boundaries: preserve existing rules (user may have adjusted)\n if (existing.boundaries) {\n merged.boundaries = {\n deny: { ...existing.boundaries.deny },\n ...(existing.boundaries.ignore ? { ignore: [...existing.boundaries.ignore] } : {}),\n };\n } else if (fresh.boundaries) {\n merged.boundaries = {\n deny: { ...fresh.boundaries.deny },\n ...(fresh.boundaries.ignore ? { ignore: [...fresh.boundaries.ignore] } : {}),\n };\n }\n\n return merged;\n}\n","/**\n * Reusable sub-schema definitions extracted from the main config schema.\n * Keeps the primary schema file under 300 lines.\n */\n\nexport const boundarySchema = {\n type: 'object',\n required: ['deny'],\n properties: {\n deny: {\n type: 'object',\n additionalProperties: {\n type: 'array',\n items: { type: 'string' },\n },\n description:\n 'Map of source package/directory to the list of targets it must NOT import from.',\n },\n ignore: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'File paths that bypass boundary checks entirely (escape hatch for legitimate exceptions).',\n },\n },\n additionalProperties: false,\n} as const;\n\nexport const stackSchema = {\n type: 'object',\n properties: {\n framework: { type: 'string', description: 'Primary framework (e.g. \"nextjs@15\").' },\n language: { type: 'string', description: 'Primary language (e.g. \"typescript\").' },\n styling: { type: 'string', description: 'Styling solution (e.g. \"tailwindcss@4\").' },\n backend: { type: 'string', description: 'Backend framework (e.g. \"express@5\").' },\n orm: { type: 'string', description: 'ORM or database client (e.g. \"prisma\").' },\n packageManager: { type: 'string', description: 'Package manager (e.g. \"pnpm\").' },\n linter: { type: 'string', description: 'Linter (e.g. \"eslint@9\").' },\n formatter: { type: 'string', description: 'Formatter (e.g. \"prettier\").' },\n testRunner: { type: 'string', description: 'Test runner (e.g. \"vitest\").' },\n },\n additionalProperties: false,\n} as const;\n\nexport const structureSchema = {\n type: 'object',\n properties: {\n srcDir: { type: 'string', description: 'Source directory (e.g. \"src\").' },\n pages: { type: 'string', description: 'Pages or routes directory.' },\n components: { type: 'string', description: 'Components directory.' },\n hooks: { type: 'string', description: 'Hooks directory.' },\n utils: { type: 'string', description: 'Utilities directory.' },\n types: { type: 'string', description: 'Type definitions directory.' },\n tests: { type: 'string', description: 'Tests directory.' },\n testPattern: { type: 'string', description: 'Test file naming pattern (e.g. \"*.test.ts\").' },\n },\n additionalProperties: false,\n} as const;\n\nexport const conventionsSchema = {\n type: 'object',\n properties: {\n fileNaming: { type: 'string', description: 'File naming convention (e.g. \"kebab-case\").' },\n componentNaming: { type: 'string', description: 'Component naming convention.' },\n hookNaming: { type: 'string', description: 'Hook naming convention.' },\n importAlias: { type: 'string', description: 'Import alias pattern (e.g. \"@/*\").' },\n },\n additionalProperties: false,\n} as const;\n\nexport const coverageSchema = {\n type: 'object',\n properties: {\n command: {\n type: 'string',\n description: 'Command to generate coverage summary data for this package.',\n },\n summaryPath: {\n type: 'string',\n description: 'Path to coverage summary JSON relative to package root.',\n },\n },\n additionalProperties: false,\n} as const;\n\nexport const packageItemSchema = {\n type: 'object',\n required: ['name', 'path'],\n properties: {\n name: { type: 'string', description: 'Package name from package.json.' },\n path: { type: 'string', description: 'Relative path to the package (\".\" for root).' },\n stack: { ...stackSchema, description: 'Technology stack for this package.' },\n structure: { ...structureSchema, description: 'Directory structure for this package.' },\n conventions: { ...conventionsSchema, description: 'Coding conventions for this package.' },\n coverage: {\n ...coverageSchema,\n description: 'Coverage generation and summary settings for this package.',\n },\n rules: {\n type: 'object',\n properties: {\n maxFileLines: { type: 'number' },\n maxTestFileLines: { type: 'number' },\n testCoverage: { type: 'number' },\n enforceNaming: { type: 'boolean' },\n enforceBoundaries: { type: 'boolean' },\n },\n additionalProperties: false,\n },\n ignore: { type: 'array', items: { type: 'string' } },\n boundaries: {\n type: 'object',\n properties: {\n deny: { type: 'array', items: { type: 'string' } },\n ignore: { type: 'array', items: { type: 'string' } },\n },\n additionalProperties: false,\n },\n },\n additionalProperties: false,\n} as const;\n\nexport const defaultsSchema = {\n type: 'object',\n properties: {\n stack: { ...stackSchema, description: 'Default stack inherited by all packages.' },\n structure: { ...structureSchema, description: 'Default structure inherited by all packages.' },\n conventions: {\n ...conventionsSchema,\n description: 'Default conventions inherited by all packages.',\n },\n coverage: {\n ...coverageSchema,\n description: 'Default coverage settings inherited by all packages.',\n },\n },\n additionalProperties: false,\n description: 'Shared defaults for all packages. Packages inherit and can override.',\n} as const;\n","/**\n * JSON Schema (draft-07) definition for viberails.config.json.\n *\n * This schema will eventually be hosted at https://viberails.sh/schema/v1.json.\n * For now it is exported as a TypeScript object that can be serialized to JSON.\n */\nimport { boundarySchema, defaultsSchema, packageItemSchema } from './schema-parts.js';\n\nexport const configSchema = {\n $schema: 'http://json-schema.org/draft-07/schema#',\n $id: 'https://viberails.sh/schema/v1.json',\n title: 'viberails configuration',\n description: 'Configuration file for viberails — guardrails for vibe coding.',\n type: 'object',\n required: ['version', 'name', 'packages', 'rules'],\n properties: {\n $schema: {\n type: 'string',\n description: 'JSON Schema URL for editor validation.',\n },\n version: {\n type: 'number',\n const: 1,\n description: 'Config format version. Always 1.',\n },\n name: {\n type: 'string',\n description: 'Project name, typically from package.json.',\n },\n rules: {\n type: 'object',\n required: [\n 'maxFileLines',\n 'testCoverage',\n 'enforceNaming',\n 'enforceBoundaries',\n 'enforceMissingTests',\n ],\n properties: {\n maxFileLines: {\n type: 'number',\n default: 300,\n description: 'Maximum number of lines allowed per file.',\n },\n maxTestFileLines: {\n type: 'number',\n default: 0,\n description:\n 'Maximum number of lines allowed per test file. Set to 0 to exempt test files.',\n },\n testCoverage: {\n type: 'number',\n default: 80,\n description:\n 'Minimum line coverage target percentage. 0 disables coverage threshold checks.',\n },\n enforceNaming: {\n type: 'boolean',\n default: true,\n description: 'Whether to enforce detected file naming conventions.',\n },\n enforceBoundaries: {\n type: 'boolean',\n default: false,\n description: 'Whether to enforce module boundary rules.',\n },\n enforceMissingTests: {\n type: 'boolean',\n default: true,\n description: 'Whether to enforce that every source file has a corresponding test file.',\n },\n },\n additionalProperties: false,\n description: 'Rule thresholds and toggles for enforcement.',\n },\n ignore: {\n type: 'array',\n items: { type: 'string' },\n description: 'Project-specific glob patterns to ignore (universal patterns are built-in).',\n },\n boundaries: {\n ...boundarySchema,\n description: 'Module boundary rules for import enforcement.',\n },\n defaults: defaultsSchema,\n packages: {\n type: 'array',\n items: packageItemSchema,\n description: 'Per-package configs. Single projects use path \".\".',\n },\n _meta: {\n type: 'object',\n properties: {\n lastSync: { type: 'string', description: 'ISO timestamp of last sync.' },\n packages: {\n type: 'object',\n additionalProperties: {\n type: 'object',\n properties: {\n conventions: {\n type: 'object',\n additionalProperties: {\n type: 'object',\n properties: {\n value: { type: 'string' },\n confidence: { type: 'string', enum: ['high', 'medium', 'low'] },\n consistency: { type: 'number' },\n detected: { type: 'boolean' },\n },\n },\n },\n },\n },\n },\n },\n description: 'Scanner metadata. Regenerated on every sync — not user-editable.',\n },\n },\n additionalProperties: false,\n} as const;\n","declare const __PACKAGE_VERSION__: string;\nexport const VERSION: string = __PACKAGE_VERSION__;\n\nexport { compactConfig, expandDefaults } from './compact-config.js';\nexport { BUILTIN_IGNORE, DEFAULT_IGNORE, DEFAULT_RULES } from './defaults.js';\nexport { generateConfig } from './generate-config.js';\nexport { inferCoverageCommand } from './infer-coverage-command.js';\nexport { loadConfig, loadConfigSafe } from './load-config.js';\nexport { mergeConfig } from './merge-config.js';\nexport { configSchema } from './schema.js';\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/generate-config.ts","../src/defaults.ts","../src/generate-packages.ts","../src/infer-coverage-command.ts","../src/compact-config.ts","../src/load-config.ts","../src/merge-config.ts","../src/schema-parts.ts","../src/schema.ts","../src/index.ts"],"sourcesContent":["import * as path from 'node:path';\nimport type {\n ConfigConventions,\n ConfigMeta,\n ConfigStack,\n ConfigStructure,\n ConventionMeta,\n DetectedConvention,\n DirectoryRole,\n PackageConfig,\n ScanResult,\n StackItem,\n ViberailsConfig,\n} from '@viberails/types';\nimport { DEFAULT_IGNORE, DEFAULT_RULES } from './defaults.js';\nimport { generatePackages } from './generate-packages.js';\nimport { inferCoverageCommand } from './infer-coverage-command.js';\n\n/**\n * Format a StackItem as a config string: `\"name@version\"` or `\"name\"`.\n */\nexport function formatStackItem(item: StackItem): string {\n return item.version ? `${item.name}@${item.version}` : item.name;\n}\n\n/**\n * Map DetectedStack → ConfigStack by formatting each StackItem.\n */\nexport function mapStack(scanResult: ScanResult): ConfigStack {\n const { stack } = scanResult;\n const config: ConfigStack = {\n language: formatStackItem(stack.language),\n packageManager: formatStackItem(stack.packageManager),\n };\n\n if (stack.framework) config.framework = formatStackItem(stack.framework);\n if (stack.styling) config.styling = formatStackItem(stack.styling);\n if (stack.backend) config.backend = formatStackItem(stack.backend);\n if (stack.orm) config.orm = formatStackItem(stack.orm);\n if (stack.linter) config.linter = formatStackItem(stack.linter);\n if (stack.formatter) config.formatter = formatStackItem(stack.formatter);\n if (stack.testRunner) config.testRunner = formatStackItem(stack.testRunner);\n\n return config;\n}\n\n/** Directory roles that map to ConfigStructure fields. */\nconst ROLE_TO_FIELD: Partial<Record<DirectoryRole, keyof ConfigStructure>> = {\n pages: 'pages',\n components: 'components',\n hooks: 'hooks',\n utils: 'utils',\n types: 'types',\n tests: 'tests',\n};\n\n/**\n * Map DetectedStructure → ConfigStructure by finding the first directory\n * for each known role.\n */\nexport function mapStructure(scanResult: ScanResult): ConfigStructure {\n const { structure } = scanResult;\n const config: ConfigStructure = {};\n\n if (structure.srcDir) {\n config.srcDir = structure.srcDir;\n }\n\n for (const dir of structure.directories) {\n const field = ROLE_TO_FIELD[dir.role];\n if (field && config[field] === undefined) {\n (config as Record<string, string>)[field] = dir.path;\n }\n }\n\n if (structure.testPattern) {\n config.testPattern = structure.testPattern.value;\n } else {\n // Default test pattern when no test files detected yet, based on project language\n const isTypeScript = scanResult.stack.language.name === 'typescript';\n config.testPattern = isTypeScript ? '*.test.ts' : '*.test.js';\n }\n\n return config;\n}\n\n/** Convention keys from ScanResult that map to ConfigConventions fields. */\nexport const CONVENTION_KEYS: (keyof ConfigConventions)[] = [\n 'fileNaming',\n 'componentNaming',\n 'hookNaming',\n 'importAlias',\n];\n\n/**\n * Map scanner conventions → ConfigConventions as plain strings.\n * Low-confidence conventions are omitted.\n * Returns both the plain-string conventions and the metadata for _meta.\n */\nfunction mapConventions(scanResult: ScanResult): {\n conventions: ConfigConventions;\n meta: Record<string, ConventionMeta>;\n} {\n const conventions: ConfigConventions = {};\n const meta: Record<string, ConventionMeta> = {};\n\n for (const key of CONVENTION_KEYS) {\n const detected = scanResult.conventions[key];\n if (detected && detected.confidence !== 'low') {\n conventions[key] = detected.value;\n meta[key] = {\n value: detected.value,\n confidence: detected.confidence,\n consistency: detected.consistency,\n };\n }\n }\n\n return { conventions, meta };\n}\n\n/**\n * Build _meta for a single package's conventions.\n */\nexport function buildConventionMeta(\n conventions: Record<string, DetectedConvention>,\n): Record<string, ConventionMeta> {\n const meta: Record<string, ConventionMeta> = {};\n for (const key of CONVENTION_KEYS) {\n const detected = conventions[key];\n if (detected && detected.confidence !== 'low') {\n meta[key] = {\n value: detected.value,\n confidence: detected.confidence,\n consistency: detected.consistency,\n };\n }\n }\n return meta;\n}\n\n/**\n * Generate a ViberailsConfig from scan results.\n *\n * Produces the packages-first config format: all config lives in `packages[]`.\n * Single projects get one package with `path: \".\"`.\n * Monorepos get one package per workspace package.\n *\n * @param scanResult - The output of scanning a project\n * @returns A complete ViberailsConfig ready to be written as JSON\n */\nexport function generateConfig(scanResult: ScanResult): ViberailsConfig {\n const projectName = path.basename(scanResult.root);\n const { conventions, meta } = mapConventions(scanResult);\n\n // Build the root package\n const rootPackage: PackageConfig = {\n name: projectName,\n path: '.',\n stack: mapStack(scanResult),\n structure: mapStructure(scanResult),\n conventions,\n };\n\n const _meta: ConfigMeta = {\n lastSync: new Date().toISOString(),\n packages: {\n '.': { conventions: Object.keys(meta).length > 0 ? meta : undefined },\n },\n };\n\n const config: ViberailsConfig = {\n $schema: 'https://viberails.sh/schema/v1.json',\n version: 1,\n name: projectName,\n rules: { ...DEFAULT_RULES },\n ignore: [...DEFAULT_IGNORE],\n packages: [rootPackage],\n _meta,\n };\n\n // Infer coverage command from detected test runner\n const testRunner = scanResult.stack.testRunner;\n const coverageCommand = inferCoverageCommand(\n testRunner ? formatStackItem(testRunner) : undefined,\n );\n if (coverageCommand) {\n config.defaults = { coverage: { command: coverageCommand } };\n }\n\n // Monorepo: generate per-package configs\n if (scanResult.workspace) {\n const packages = generatePackages(scanResult);\n if (packages) {\n config.packages = packages;\n\n // If packages have different test runners, set per-package coverage\n // commands instead of a global default (which would be wrong for some).\n const runners = new Set(\n packages.map((p) => p.stack?.testRunner?.split('@')[0]).filter(Boolean),\n );\n if (runners.size > 1) {\n delete config.defaults?.coverage?.command;\n for (const pkg of packages) {\n const pkgCommand = inferCoverageCommand(pkg.stack?.testRunner);\n if (pkgCommand) {\n pkg.coverage = { ...pkg.coverage, command: pkgCommand };\n }\n }\n }\n // Rebuild _meta for all packages\n const pkgMeta: Record<string, { conventions?: Record<string, ConventionMeta> }> = {};\n for (const pkg of scanResult.packages) {\n const convMeta = buildConventionMeta(pkg.conventions);\n if (Object.keys(convMeta).length > 0) {\n pkgMeta[pkg.relativePath] = { conventions: convMeta };\n }\n }\n if (Object.keys(pkgMeta).length > 0) {\n _meta.packages = pkgMeta;\n }\n }\n config.boundaries = { deny: {} };\n }\n\n return config;\n}\n","import type { ConfigRules } from '@viberails/types';\n\n/**\n * Default rule thresholds and toggles for a new viberails config.\n * These values are intentionally conservative to build trust on first run.\n */\nexport const DEFAULT_RULES: ConfigRules = {\n maxFileLines: 300,\n maxTestFileLines: 0,\n testCoverage: 80,\n enforceNaming: true,\n enforceBoundaries: false,\n enforceMissingTests: true,\n};\n\n/**\n * Default project-specific ignore patterns for a new config.\n * Empty — universal patterns live in BUILTIN_IGNORE and are applied at check-time.\n */\nexport const DEFAULT_IGNORE: string[] = [];\n\n/**\n * Universal ignore patterns applied at check-time.\n * These are never written to config — they are always applied implicitly.\n */\nexport const BUILTIN_IGNORE: string[] = [\n '**/*.d.ts',\n '**/*.min.js',\n '**/*.min.cjs',\n '**/*.umd.js',\n '**/*.bundle.js',\n 'dist/**',\n 'node_modules/**',\n 'build/**',\n '.next/**',\n '.expo/**',\n '.output/**',\n '.svelte-kit/**',\n '.turbo/**',\n 'coverage/**',\n '**/public/**',\n '**/vendor/**',\n '.viberails/**',\n '**/generated/**',\n '**/__generated__/**',\n];\n","import type { ConfigConventions, ConfigStack, PackageConfig, ScanResult } from '@viberails/types';\nimport { CONVENTION_KEYS, formatStackItem, mapStructure } from './generate-config.js';\n\n/**\n * Build a full ConfigStack for a single package scan result.\n */\nfunction buildPackageStack(pkg: ScanResult['packages'][number]): ConfigStack {\n const config: ConfigStack = {\n language: formatStackItem(pkg.stack.language),\n packageManager: formatStackItem(pkg.stack.packageManager),\n };\n\n if (pkg.stack.framework) config.framework = formatStackItem(pkg.stack.framework);\n if (pkg.stack.styling) config.styling = formatStackItem(pkg.stack.styling);\n if (pkg.stack.backend) config.backend = formatStackItem(pkg.stack.backend);\n if (pkg.stack.orm) config.orm = formatStackItem(pkg.stack.orm);\n if (pkg.stack.linter) config.linter = formatStackItem(pkg.stack.linter);\n if (pkg.stack.formatter) config.formatter = formatStackItem(pkg.stack.formatter);\n if (pkg.stack.testRunner) config.testRunner = formatStackItem(pkg.stack.testRunner);\n\n return config;\n}\n\n/**\n * Build ConfigConventions as plain strings, omitting low-confidence entries.\n */\nfunction buildPackageConventions(\n pkgConventions: Record<string, import('@viberails/types').DetectedConvention>,\n): ConfigConventions {\n const config: ConfigConventions = {};\n\n for (const key of CONVENTION_KEYS) {\n const detected = pkgConventions[key];\n if (detected && detected.confidence !== 'low') {\n config[key] = detected.value;\n }\n }\n\n return config;\n}\n\n/**\n * Generate self-contained per-package configs for packages in a monorepo.\n * Each PackageConfig has its own full stack, structure, and conventions.\n *\n * Returns undefined for single-package projects.\n */\nexport function generatePackages(scanResult: ScanResult): PackageConfig[] | undefined {\n if (!scanResult.packages || scanResult.packages.length <= 1) return undefined;\n\n const packages: PackageConfig[] = [];\n\n for (const pkg of scanResult.packages) {\n // Build a temporary ScanResult-like object for mapStructure\n const pkgScanResult = {\n root: pkg.root,\n stack: pkg.stack,\n structure: pkg.structure,\n conventions: pkg.conventions,\n statistics: pkg.statistics,\n } as ScanResult;\n\n const packageConfig: PackageConfig = {\n name: pkg.name,\n path: pkg.relativePath,\n stack: buildPackageStack(pkg),\n structure: mapStructure(pkgScanResult),\n conventions: buildPackageConventions(pkg.conventions),\n };\n\n if (pkg.typesOnly) {\n packageConfig.rules = { testCoverage: 0 };\n }\n\n packages.push(packageConfig);\n }\n\n return packages.length > 0 ? packages : undefined;\n}\n","/**\n * Infer a coverage command from the detected test runner string.\n *\n * Used during `init` to store the inferred command in config so that\n * `check` can use it explicitly. Does not verify binary availability —\n * the command is stored as a suggestion for the user to review.\n *\n * @param testRunner - Test runner string from config (e.g. \"vitest@4\", \"jest@29\")\n * @returns Shell command string, or undefined if the runner is unsupported\n */\nexport function inferCoverageCommand(testRunner: string | undefined): string | undefined {\n if (!testRunner) return undefined;\n const runner = testRunner.split('@')[0];\n if (runner === 'vitest') {\n return 'npx vitest run --coverage --coverage.reporter=json-summary';\n }\n if (runner === 'jest') {\n return 'npx jest --coverage --coverageReporters=json-summary';\n }\n return undefined;\n}\n","import type {\n ConfigConventions,\n ConfigCoverage,\n ConfigDefaults,\n ConfigStack,\n ConfigStructure,\n ViberailsConfig,\n} from '@viberails/types';\nimport { CONVENTION_KEYS } from './generate-config.js';\n\n/** Stack field keys for comparison and extraction. */\nexport const STACK_KEYS: (keyof ConfigStack)[] = [\n 'language',\n 'packageManager',\n 'framework',\n 'styling',\n 'backend',\n 'orm',\n 'linter',\n 'formatter',\n 'testRunner',\n];\n\n/** Structure field keys for comparison and extraction. */\nexport const STRUCTURE_KEYS: (keyof ConfigStructure)[] = [\n 'srcDir',\n 'pages',\n 'components',\n 'hooks',\n 'utils',\n 'types',\n 'tests',\n 'testPattern',\n];\n\n/**\n * Extract shared values from packages into defaults and strip them from packages.\n * Only extracts values that are identical across ALL packages.\n * Strips empty objects from packages for clean JSON output.\n */\nexport function compactConfig(config: ViberailsConfig): ViberailsConfig {\n const pkgs = config.packages ?? [];\n\n const defaults: ConfigDefaults = {};\n\n // Start with copies; merge any existing defaults into each package first\n // so the extraction logic below works uniformly for 1 or N packages.\n const packages = pkgs.map((p) => {\n const copy = { ...p };\n if (config.defaults?.coverage) {\n copy.coverage = { ...config.defaults.coverage, ...(copy.coverage ?? {}) };\n }\n if (config.defaults?.stack) {\n copy.stack = { ...config.defaults.stack, ...(copy.stack ?? {}) } as ConfigStack;\n }\n if (config.defaults?.structure) {\n copy.structure = { ...config.defaults.structure, ...(copy.structure ?? {}) };\n }\n if (config.defaults?.conventions) {\n copy.conventions = { ...config.defaults.conventions, ...(copy.conventions ?? {}) };\n }\n return copy;\n });\n\n // For multi-package configs, extract shared values into defaults.\n // Single-package configs keep everything on the package (no defaults needed).\n if (packages.length <= 1) {\n // Strip empty objects from the single package\n for (const pkg of packages) {\n if (pkg.stack && Object.keys(pkg.stack).length === 0) delete pkg.stack;\n if (pkg.structure && Object.keys(pkg.structure).length === 0) delete pkg.structure;\n if (pkg.conventions && Object.keys(pkg.conventions).length === 0) delete pkg.conventions;\n if (pkg.coverage && Object.keys(pkg.coverage).length === 0) delete pkg.coverage;\n }\n const { defaults: _d, ...rest } = config;\n return { ...rest, packages };\n }\n\n // Extract shared stack fields\n const sharedStack: Partial<ConfigStack> = {};\n for (const key of STACK_KEYS) {\n const values = packages.map((p) => (p.stack ?? ({} as Partial<ConfigStack>))[key]);\n if (values[0] !== undefined && values.every((v) => v === values[0])) {\n sharedStack[key] = values[0] as string;\n }\n }\n if (Object.keys(sharedStack).length > 0) {\n defaults.stack = sharedStack;\n for (const pkg of packages) {\n const pkgStack = (pkg.stack ?? {}) as Partial<ConfigStack>;\n const sparse: Partial<ConfigStack> = {};\n for (const key of STACK_KEYS) {\n if (pkgStack[key] !== undefined && pkgStack[key] !== sharedStack[key]) {\n sparse[key] = pkgStack[key] as string;\n }\n }\n pkg.stack = sparse as ConfigStack;\n }\n }\n\n // Extract shared structure fields\n const sharedStructure: Partial<ConfigStructure> = {};\n for (const key of STRUCTURE_KEYS) {\n const values = packages.map((p) => p.structure?.[key]);\n const first = values[0];\n if (first !== undefined && values.every((v) => JSON.stringify(v) === JSON.stringify(first))) {\n (sharedStructure as Record<string, unknown>)[key] = first;\n }\n }\n if (Object.keys(sharedStructure).length > 0) {\n defaults.structure = sharedStructure;\n for (const pkg of packages) {\n const pkgStructure = pkg.structure ?? {};\n const sparse: Partial<ConfigStructure> = {};\n for (const key of STRUCTURE_KEYS) {\n const val = pkgStructure[key];\n if (val !== undefined && JSON.stringify(val) !== JSON.stringify(sharedStructure[key])) {\n (sparse as Record<string, unknown>)[key] = val;\n }\n }\n pkg.structure = sparse as ConfigStructure;\n }\n }\n\n // Extract shared conventions\n const sharedConventions: ConfigConventions = {};\n for (const key of CONVENTION_KEYS) {\n const values = packages.map((p) => p.conventions?.[key]);\n if (values[0] !== undefined && values.every((v) => v === values[0])) {\n sharedConventions[key] = values[0];\n }\n }\n\n // Extract shared coverage settings\n const sharedCoverage: ConfigCoverage = {};\n const coverageKeys: (keyof ConfigCoverage)[] = ['command', 'summaryPath'];\n for (const key of coverageKeys) {\n const values = packages.map((p) => p.coverage?.[key]);\n if (values[0] !== undefined && values.every((v) => v === values[0])) {\n sharedCoverage[key] = values[0];\n }\n }\n if (Object.keys(sharedCoverage).length > 0) {\n defaults.coverage = sharedCoverage;\n for (const pkg of packages) {\n const pkgCoverage = pkg.coverage ?? {};\n const sparse: ConfigCoverage = {};\n for (const key of coverageKeys) {\n if (pkgCoverage[key] !== undefined && pkgCoverage[key] !== sharedCoverage[key]) {\n sparse[key] = pkgCoverage[key];\n }\n }\n pkg.coverage = sparse;\n }\n }\n if (Object.keys(sharedConventions).length > 0) {\n defaults.conventions = sharedConventions;\n for (const pkg of packages) {\n const pkgConventions = pkg.conventions ?? {};\n const sparse: ConfigConventions = {};\n for (const key of CONVENTION_KEYS) {\n if (pkgConventions[key] !== undefined && pkgConventions[key] !== sharedConventions[key]) {\n sparse[key] = pkgConventions[key];\n }\n }\n pkg.conventions = sparse;\n }\n }\n\n // Strip empty objects from packages\n for (const pkg of packages) {\n if (pkg.stack && Object.keys(pkg.stack).length === 0) {\n delete pkg.stack;\n }\n if (pkg.structure && Object.keys(pkg.structure).length === 0) {\n delete pkg.structure;\n }\n if (pkg.conventions && Object.keys(pkg.conventions).length === 0) {\n delete pkg.conventions;\n }\n if (pkg.coverage && Object.keys(pkg.coverage).length === 0) {\n delete pkg.coverage;\n }\n }\n\n // Reconstruct with explicit key ordering so JSON output is readable:\n // $schema, version, name, rules, ignore, boundaries, defaults, packages, _meta\n const result: ViberailsConfig = {\n ...(config.$schema ? { $schema: config.$schema } : {}),\n version: config.version,\n name: config.name,\n rules: config.rules,\n ...(config.ignore && config.ignore.length > 0 ? { ignore: config.ignore } : {}),\n ...(config.boundaries ? { boundaries: config.boundaries } : {}),\n ...(Object.keys(defaults).length > 0 ? { defaults } : {}),\n packages,\n ...(config._meta ? { _meta: config._meta } : {}),\n };\n return result;\n}\n\n/**\n * Expand defaults into each package, producing fully self-contained packages.\n * Inverse of compactConfig. Ensures every package has stack, structure,\n * and conventions (even as empty objects) and config.ignore defaults to [].\n */\nexport function expandDefaults(config: ViberailsConfig): ViberailsConfig {\n const defaults = config.defaults;\n\n const packages = config.packages.map((pkg) => {\n const expanded = { ...pkg };\n\n // Merge defaults into package fields, or initialize to empty objects\n expanded.stack = { ...(defaults?.stack ?? {}), ...(pkg.stack ?? {}) } as ConfigStack;\n expanded.structure = { ...(defaults?.structure ?? {}), ...(pkg.structure ?? {}) };\n expanded.conventions = { ...(defaults?.conventions ?? {}), ...(pkg.conventions ?? {}) };\n const mergedCoverage = { ...(defaults?.coverage ?? {}), ...(pkg.coverage ?? {}) };\n if (Object.keys(mergedCoverage).length > 0) {\n expanded.coverage = mergedCoverage;\n } else {\n delete expanded.coverage;\n }\n\n return expanded;\n });\n\n // Ensure ignore defaults to []\n const ignore = config.ignore ?? [];\n\n // Return without defaults — packages are now self-contained\n const { defaults: _d, ...rest } = config;\n return { ...rest, ignore, packages };\n}\n","import * as fs from 'node:fs/promises';\nimport type { ViberailsConfig } from '@viberails/types';\nimport { expandDefaults } from './compact-config.js';\n\n/**\n * Validate that a parsed object has the required ViberailsConfig fields\n * and that their types are correct.\n * Throws a descriptive error if validation fails.\n */\nfunction validateConfig(parsed: Record<string, unknown>, configPath: string): void {\n const errors: string[] = [];\n\n // Required top-level fields\n const required = ['version', 'name', 'packages', 'rules'] as const;\n const missing = required.filter((field) => parsed[field] === undefined);\n if (missing.length > 0) {\n throw new Error(\n `Invalid viberails config at ${configPath}: missing required field(s): ${missing.join(', ')}`,\n );\n }\n\n // Type checks\n if (typeof parsed.version !== 'number') {\n errors.push('\"version\" must be a number');\n } else if (parsed.version !== 1) {\n errors.push('\"version\" must be 1');\n }\n if (typeof parsed.name !== 'string') errors.push('\"name\" must be a string');\n // Packages validation\n if (!Array.isArray(parsed.packages)) {\n errors.push('\"packages\" must be an array');\n } else if (parsed.packages.length === 0) {\n errors.push('\"packages\" must contain at least one package');\n } else {\n for (let i = 0; i < parsed.packages.length; i++) {\n const pkg = parsed.packages[i] as Record<string, unknown>;\n if (typeof pkg.name !== 'string') errors.push(`\"packages[${i}].name\" must be a string`);\n if (typeof pkg.path !== 'string') errors.push(`\"packages[${i}].path\" must be a string`);\n if (pkg.coverage !== undefined) {\n if (typeof pkg.coverage !== 'object' || pkg.coverage === null) {\n errors.push(`\"packages[${i}].coverage\" must be an object`);\n } else {\n const coverage = pkg.coverage as Record<string, unknown>;\n if (coverage.command !== undefined && typeof coverage.command !== 'string') {\n errors.push(`\"packages[${i}].coverage.command\" must be a string`);\n }\n if (coverage.summaryPath !== undefined && typeof coverage.summaryPath !== 'string') {\n errors.push(`\"packages[${i}].coverage.summaryPath\" must be a string`);\n }\n }\n }\n }\n }\n\n // Rules validation\n if (typeof parsed.rules !== 'object' || parsed.rules === null) {\n errors.push('\"rules\" must be an object');\n } else {\n const rules = parsed.rules as Record<string, unknown>;\n if (typeof rules.maxFileLines !== 'number')\n errors.push('\"rules.maxFileLines\" must be a number');\n else if (rules.maxFileLines < 0) errors.push('\"rules.maxFileLines\" must be >= 0');\n if (rules.maxTestFileLines !== undefined) {\n if (typeof rules.maxTestFileLines !== 'number') {\n errors.push('\"rules.maxTestFileLines\" must be a number');\n } else if (rules.maxTestFileLines < 0) {\n errors.push('\"rules.maxTestFileLines\" must be >= 0');\n }\n }\n if (typeof rules.testCoverage !== 'number')\n errors.push('\"rules.testCoverage\" must be a number');\n else if (rules.testCoverage < 0 || rules.testCoverage > 100)\n errors.push('\"rules.testCoverage\" must be between 0 and 100');\n if (typeof rules.enforceNaming !== 'boolean')\n errors.push('\"rules.enforceNaming\" must be a boolean');\n if (typeof rules.enforceBoundaries !== 'boolean')\n errors.push('\"rules.enforceBoundaries\" must be a boolean');\n }\n\n // Ignore validation\n if (parsed.ignore !== undefined && !Array.isArray(parsed.ignore)) {\n errors.push('\"ignore\" must be an array');\n }\n\n // Defaults validation\n if (parsed.defaults !== undefined) {\n if (typeof parsed.defaults !== 'object' || parsed.defaults === null) {\n errors.push('\"defaults\" must be an object');\n } else {\n const defaults = parsed.defaults as Record<string, unknown>;\n if (defaults.coverage !== undefined) {\n if (typeof defaults.coverage !== 'object' || defaults.coverage === null) {\n errors.push('\"defaults.coverage\" must be an object');\n } else {\n const coverage = defaults.coverage as Record<string, unknown>;\n if (coverage.command !== undefined && typeof coverage.command !== 'string') {\n errors.push('\"defaults.coverage.command\" must be a string');\n }\n if (coverage.summaryPath !== undefined && typeof coverage.summaryPath !== 'string') {\n errors.push('\"defaults.coverage.summaryPath\" must be a string');\n }\n }\n }\n }\n }\n\n if (errors.length > 0) {\n throw new Error(`Invalid viberails config at ${configPath}: ${errors.join('; ')}`);\n }\n}\n\n/**\n * Load and parse a viberails config file.\n *\n * Reads the JSON file at the given path, validates that it contains\n * the required fields (version, name, packages, rules), expands\n * defaults into packages, and returns the parsed config.\n *\n * @param configPath - Absolute or relative path to viberails.config.json\n * @returns The parsed ViberailsConfig with defaults expanded\n * @throws If the file doesn't exist, contains invalid JSON, or is missing required fields\n */\nexport async function loadConfig(configPath: string): Promise<ViberailsConfig> {\n let raw: string;\n try {\n raw = await fs.readFile(configPath, 'utf-8');\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') {\n throw new Error(`Config file not found: ${configPath}. Run \"npx viberails\" to generate one.`);\n }\n throw new Error(`Failed to read config file at ${configPath}: ${(err as Error).message}`);\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n throw new Error(`Invalid JSON in config file at ${configPath}. Check for syntax errors.`);\n }\n\n validateConfig(parsed, configPath);\n\n // Apply defaults for optional fields added after initial release\n const rules = parsed.rules as Record<string, unknown>;\n if (rules.maxTestFileLines === undefined) {\n rules.maxTestFileLines = 0;\n }\n if (rules.enforceMissingTests === undefined) {\n rules.enforceMissingTests = true;\n }\n\n // Default ignore to [] if missing\n if (parsed.ignore === undefined) {\n parsed.ignore = [];\n }\n\n // Safe to cast: validateConfig has verified all required fields and types\n let config = parsed as unknown as ViberailsConfig;\n\n // Expand defaults into packages so they are self-contained\n config = expandDefaults(config);\n\n return config;\n}\n\n/**\n * Safely load a viberails config file, returning null on any error.\n *\n * Used by the CLI for \"does config already exist?\" checks where\n * failure is an expected case, not an error.\n *\n * @param configPath - Absolute or relative path to viberails.config.json\n * @returns The parsed ViberailsConfig, or null if loading fails\n */\nexport async function loadConfigSafe(configPath: string): Promise<ViberailsConfig | null> {\n try {\n return await loadConfig(configPath);\n } catch {\n return null;\n }\n}\n","import type {\n ConfigConventions,\n ConfigStack,\n ConfigStructure,\n ConventionMeta,\n PackageConfig,\n ScanResult,\n ViberailsConfig,\n} from '@viberails/types';\nimport { CONVENTION_KEYS, generateConfig } from './generate-config.js';\n\n/**\n * Merge stack: keep existing values, fill in undefined fields from fresh scan.\n */\nfunction mergeStack(existing: ConfigStack, fresh: ConfigStack): ConfigStack {\n return {\n language: existing.language,\n packageManager: existing.packageManager,\n framework: existing.framework ?? fresh.framework,\n styling: existing.styling ?? fresh.styling,\n backend: existing.backend ?? fresh.backend,\n orm: existing.orm ?? fresh.orm,\n linter: existing.linter ?? fresh.linter,\n formatter: existing.formatter ?? fresh.formatter,\n testRunner: existing.testRunner ?? fresh.testRunner,\n };\n}\n\n/**\n * Merge structure: keep existing values, fill in undefined fields from fresh scan.\n */\nfunction mergeStructure(existing: ConfigStructure, fresh: ConfigStructure): ConfigStructure {\n return {\n srcDir: existing.srcDir ?? fresh.srcDir,\n pages: existing.pages ?? fresh.pages,\n components: existing.components ?? fresh.components,\n hooks: existing.hooks ?? fresh.hooks,\n utils: existing.utils ?? fresh.utils,\n types: existing.types ?? fresh.types,\n tests: existing.tests ?? fresh.tests,\n testPattern: existing.testPattern ?? fresh.testPattern,\n };\n}\n\n/**\n * Merge conventions: keep all existing values, add new ones from fresh scan.\n * New conventions are marked with `detected: true` in _meta.\n */\nfunction mergeConventions(\n existing: ConfigConventions,\n fresh: ConfigConventions,\n existingMeta: Record<string, ConventionMeta> | undefined,\n freshMeta: Record<string, ConventionMeta> | undefined,\n): { conventions: ConfigConventions; meta: Record<string, ConventionMeta> } {\n const conventions: ConfigConventions = { ...existing };\n const meta: Record<string, ConventionMeta> = { ...(existingMeta ?? {}) };\n\n for (const key of CONVENTION_KEYS) {\n if (existing[key] === undefined && fresh[key] !== undefined) {\n conventions[key] = fresh[key];\n // Mark as newly detected in meta\n if (freshMeta?.[key]) {\n meta[key] = { ...freshMeta[key], detected: true };\n }\n } else if (existing[key] !== undefined && freshMeta?.[key]) {\n // Update meta with latest scan data but preserve existing convention value\n meta[key] = { ...freshMeta[key], value: freshMeta[key].value };\n }\n }\n\n return { conventions, meta };\n}\n\n/**\n * Merge a single package config, preserving existing values and adding fresh detections.\n */\nfunction mergePackage(\n existing: PackageConfig,\n fresh: PackageConfig,\n existingMeta: Record<string, ConventionMeta> | undefined,\n freshMeta: Record<string, ConventionMeta> | undefined,\n): { pkg: PackageConfig; meta: Record<string, ConventionMeta> } {\n const { conventions, meta } = mergeConventions(\n existing.conventions ?? {},\n fresh.conventions ?? {},\n existingMeta,\n freshMeta,\n );\n\n return {\n pkg: {\n ...existing,\n stack: mergeStack(existing.stack ?? ({} as ConfigStack), fresh.stack ?? ({} as ConfigStack)),\n structure: mergeStructure(existing.structure ?? {}, fresh.structure ?? {}),\n conventions,\n },\n meta,\n };\n}\n\n/**\n * Merge a new scan result into an existing config for `viberails sync`.\n *\n * Preserves all developer-confirmed values from the existing config.\n * Adds newly detected values. New conventions are marked with\n * `detected: true` in _meta so the developer can review them.\n *\n * @param existing - The current ViberailsConfig (from viberails.config.json)\n * @param scanResult - Fresh scan results from re-scanning the project\n * @returns A merged config that preserves existing values and adds new detections\n */\nexport function mergeConfig(existing: ViberailsConfig, scanResult: ScanResult): ViberailsConfig {\n const fresh = generateConfig(scanResult);\n\n const existingByPath = new Map(existing.packages.map((p) => [p.path, p]));\n const freshByPath = new Map(fresh.packages.map((p) => [p.path, p]));\n\n const mergedPackages: PackageConfig[] = [];\n const mergedPkgMeta: Record<string, { conventions?: Record<string, ConventionMeta> }> = {};\n\n // Merge existing packages with fresh data\n for (const existingPkg of existing.packages) {\n const freshPkg = freshByPath.get(existingPkg.path);\n if (freshPkg) {\n const existingConvMeta = existing._meta?.packages?.[existingPkg.path]?.conventions;\n const freshConvMeta = fresh._meta?.packages?.[existingPkg.path]?.conventions;\n const { pkg, meta } = mergePackage(existingPkg, freshPkg, existingConvMeta, freshConvMeta);\n mergedPackages.push(pkg);\n if (Object.keys(meta).length > 0) {\n mergedPkgMeta[pkg.path] = { conventions: meta };\n }\n } else {\n mergedPackages.push(existingPkg);\n }\n }\n\n // Add new packages from fresh scan\n for (const freshPkg of fresh.packages) {\n if (!existingByPath.has(freshPkg.path)) {\n mergedPackages.push(freshPkg);\n const freshConvMeta = fresh._meta?.packages?.[freshPkg.path]?.conventions;\n if (freshConvMeta && Object.keys(freshConvMeta).length > 0) {\n mergedPkgMeta[freshPkg.path] = { conventions: freshConvMeta };\n }\n }\n }\n\n const merged: ViberailsConfig = {\n $schema: existing.$schema ?? fresh.$schema,\n version: existing.version,\n name: existing.name,\n rules: { ...existing.rules },\n ignore: [...(existing.ignore ?? [])],\n packages: mergedPackages,\n _meta: {\n lastSync: new Date().toISOString(),\n ...(Object.keys(mergedPkgMeta).length > 0 ? { packages: mergedPkgMeta } : {}),\n },\n };\n\n // Boundaries: preserve existing rules (user may have adjusted)\n if (existing.boundaries) {\n merged.boundaries = {\n deny: { ...existing.boundaries.deny },\n ...(existing.boundaries.ignore ? { ignore: [...existing.boundaries.ignore] } : {}),\n };\n } else if (fresh.boundaries) {\n merged.boundaries = {\n deny: { ...fresh.boundaries.deny },\n ...(fresh.boundaries.ignore ? { ignore: [...fresh.boundaries.ignore] } : {}),\n };\n }\n\n return merged;\n}\n","/**\n * Reusable sub-schema definitions extracted from the main config schema.\n * Keeps the primary schema file under 300 lines.\n */\n\nexport const boundarySchema = {\n type: 'object',\n required: ['deny'],\n properties: {\n deny: {\n type: 'object',\n additionalProperties: {\n type: 'array',\n items: { type: 'string' },\n },\n description:\n 'Map of source package/directory to the list of targets it must NOT import from.',\n },\n ignore: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'File paths that bypass boundary checks entirely (escape hatch for legitimate exceptions).',\n },\n },\n additionalProperties: false,\n} as const;\n\nexport const stackSchema = {\n type: 'object',\n properties: {\n framework: { type: 'string', description: 'Primary framework (e.g. \"nextjs@15\").' },\n language: { type: 'string', description: 'Primary language (e.g. \"typescript\").' },\n styling: { type: 'string', description: 'Styling solution (e.g. \"tailwindcss@4\").' },\n backend: { type: 'string', description: 'Backend framework (e.g. \"express@5\").' },\n orm: { type: 'string', description: 'ORM or database client (e.g. \"prisma\").' },\n packageManager: { type: 'string', description: 'Package manager (e.g. \"pnpm\").' },\n linter: { type: 'string', description: 'Linter (e.g. \"eslint@9\").' },\n formatter: { type: 'string', description: 'Formatter (e.g. \"prettier\").' },\n testRunner: { type: 'string', description: 'Test runner (e.g. \"vitest\").' },\n },\n additionalProperties: false,\n} as const;\n\nexport const structureSchema = {\n type: 'object',\n properties: {\n srcDir: { type: 'string', description: 'Source directory (e.g. \"src\").' },\n pages: { type: 'string', description: 'Pages or routes directory.' },\n components: { type: 'string', description: 'Components directory.' },\n hooks: { type: 'string', description: 'Hooks directory.' },\n utils: { type: 'string', description: 'Utilities directory.' },\n types: { type: 'string', description: 'Type definitions directory.' },\n tests: { type: 'string', description: 'Tests directory.' },\n testPattern: { type: 'string', description: 'Test file naming pattern (e.g. \"*.test.ts\").' },\n },\n additionalProperties: false,\n} as const;\n\nexport const conventionsSchema = {\n type: 'object',\n properties: {\n fileNaming: { type: 'string', description: 'File naming convention (e.g. \"kebab-case\").' },\n componentNaming: { type: 'string', description: 'Component naming convention.' },\n hookNaming: { type: 'string', description: 'Hook naming convention.' },\n importAlias: { type: 'string', description: 'Import alias pattern (e.g. \"@/*\").' },\n },\n additionalProperties: false,\n} as const;\n\nexport const coverageSchema = {\n type: 'object',\n properties: {\n command: {\n type: 'string',\n description: 'Command to generate coverage summary data for this package.',\n },\n summaryPath: {\n type: 'string',\n description: 'Path to coverage summary JSON relative to package root.',\n },\n },\n additionalProperties: false,\n} as const;\n\nexport const packageItemSchema = {\n type: 'object',\n required: ['name', 'path'],\n properties: {\n name: { type: 'string', description: 'Package name from package.json.' },\n path: { type: 'string', description: 'Relative path to the package (\".\" for root).' },\n stack: { ...stackSchema, description: 'Technology stack for this package.' },\n structure: { ...structureSchema, description: 'Directory structure for this package.' },\n conventions: { ...conventionsSchema, description: 'Coding conventions for this package.' },\n coverage: {\n ...coverageSchema,\n description: 'Coverage generation and summary settings for this package.',\n },\n rules: {\n type: 'object',\n properties: {\n maxFileLines: { type: 'number' },\n maxTestFileLines: { type: 'number' },\n testCoverage: { type: 'number' },\n enforceNaming: { type: 'boolean' },\n enforceBoundaries: { type: 'boolean' },\n enforceMissingTests: { type: 'boolean' },\n },\n additionalProperties: false,\n },\n ignore: { type: 'array', items: { type: 'string' } },\n boundaries: {\n type: 'object',\n properties: {\n deny: { type: 'array', items: { type: 'string' } },\n ignore: { type: 'array', items: { type: 'string' } },\n },\n additionalProperties: false,\n },\n },\n additionalProperties: false,\n} as const;\n\nexport const defaultsSchema = {\n type: 'object',\n properties: {\n stack: { ...stackSchema, description: 'Default stack inherited by all packages.' },\n structure: { ...structureSchema, description: 'Default structure inherited by all packages.' },\n conventions: {\n ...conventionsSchema,\n description: 'Default conventions inherited by all packages.',\n },\n coverage: {\n ...coverageSchema,\n description: 'Default coverage settings inherited by all packages.',\n },\n },\n additionalProperties: false,\n description: 'Shared defaults for all packages. Packages inherit and can override.',\n} as const;\n","/**\n * JSON Schema (draft-07) definition for viberails.config.json.\n *\n * This schema will eventually be hosted at https://viberails.sh/schema/v1.json.\n * For now it is exported as a TypeScript object that can be serialized to JSON.\n */\nimport { boundarySchema, defaultsSchema, packageItemSchema } from './schema-parts.js';\n\nexport const configSchema = {\n $schema: 'http://json-schema.org/draft-07/schema#',\n $id: 'https://viberails.sh/schema/v1.json',\n title: 'viberails configuration',\n description: 'Configuration file for viberails — guardrails for vibe coding.',\n type: 'object',\n required: ['version', 'name', 'packages', 'rules'],\n properties: {\n $schema: {\n type: 'string',\n description: 'JSON Schema URL for editor validation.',\n },\n version: {\n type: 'number',\n const: 1,\n description: 'Config format version. Always 1.',\n },\n name: {\n type: 'string',\n description: 'Project name, typically from package.json.',\n },\n rules: {\n type: 'object',\n required: [\n 'maxFileLines',\n 'testCoverage',\n 'enforceNaming',\n 'enforceBoundaries',\n 'enforceMissingTests',\n ],\n properties: {\n maxFileLines: {\n type: 'number',\n default: 300,\n description: 'Maximum number of lines allowed per file.',\n },\n maxTestFileLines: {\n type: 'number',\n default: 0,\n description:\n 'Maximum number of lines allowed per test file. Set to 0 to exempt test files.',\n },\n testCoverage: {\n type: 'number',\n default: 80,\n description:\n 'Minimum line coverage target percentage. 0 disables coverage threshold checks.',\n },\n enforceNaming: {\n type: 'boolean',\n default: true,\n description: 'Whether to enforce detected file naming conventions.',\n },\n enforceBoundaries: {\n type: 'boolean',\n default: false,\n description: 'Whether to enforce module boundary rules.',\n },\n enforceMissingTests: {\n type: 'boolean',\n default: true,\n description: 'Whether to enforce that every source file has a corresponding test file.',\n },\n },\n additionalProperties: false,\n description: 'Rule thresholds and toggles for enforcement.',\n },\n ignore: {\n type: 'array',\n items: { type: 'string' },\n description: 'Project-specific glob patterns to ignore (universal patterns are built-in).',\n },\n boundaries: {\n ...boundarySchema,\n description: 'Module boundary rules for import enforcement.',\n },\n defaults: defaultsSchema,\n packages: {\n type: 'array',\n items: packageItemSchema,\n description: 'Per-package configs. Single projects use path \".\".',\n },\n _meta: {\n type: 'object',\n properties: {\n lastSync: { type: 'string', description: 'ISO timestamp of last sync.' },\n packages: {\n type: 'object',\n additionalProperties: {\n type: 'object',\n properties: {\n conventions: {\n type: 'object',\n additionalProperties: {\n type: 'object',\n properties: {\n value: { type: 'string' },\n confidence: { type: 'string', enum: ['high', 'medium', 'low'] },\n consistency: { type: 'number' },\n detected: { type: 'boolean' },\n },\n },\n },\n },\n },\n },\n },\n description: 'Scanner metadata. Regenerated on every sync — not user-editable.',\n },\n },\n additionalProperties: false,\n} as const;\n","declare const __PACKAGE_VERSION__: string;\nexport const VERSION: string = __PACKAGE_VERSION__;\n\nexport { compactConfig, expandDefaults } from './compact-config.js';\nexport { BUILTIN_IGNORE, DEFAULT_IGNORE, DEFAULT_RULES } from './defaults.js';\nexport { generateConfig } from './generate-config.js';\nexport { inferCoverageCommand } from './infer-coverage-command.js';\nexport { loadConfig, loadConfigSafe } from './load-config.js';\nexport { mergeConfig } from './merge-config.js';\nexport { configSchema } from './schema.js';\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viberails/config",
3
- "version": "0.5.5",
3
+ "version": "0.6.0",
4
4
  "description": "Config generation and loading for viberails",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -25,7 +25,7 @@
25
25
  "access": "public"
26
26
  },
27
27
  "dependencies": {
28
- "@viberails/types": "0.5.5"
28
+ "@viberails/types": "0.6.0"
29
29
  },
30
30
  "devDependencies": {
31
31
  "ajv": "^8.18.0",