@viberails/config 0.2.3 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +106 -93
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -6
- package/dist/index.d.ts +7 -6
- package/dist/index.js +106 -93
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -108,6 +108,7 @@ function generatePackageOverrides(scanResult, globalConfig) {
|
|
|
108
108
|
"framework",
|
|
109
109
|
"styling",
|
|
110
110
|
"backend",
|
|
111
|
+
"orm",
|
|
111
112
|
"linter",
|
|
112
113
|
"formatter",
|
|
113
114
|
"testRunner"
|
|
@@ -150,6 +151,7 @@ function mapStack(scanResult) {
|
|
|
150
151
|
if (stack.framework) config.framework = formatStackItem(stack.framework);
|
|
151
152
|
if (stack.styling) config.styling = formatStackItem(stack.styling);
|
|
152
153
|
if (stack.backend) config.backend = formatStackItem(stack.backend);
|
|
154
|
+
if (stack.orm) config.orm = formatStackItem(stack.orm);
|
|
153
155
|
if (stack.linter) config.linter = formatStackItem(stack.linter);
|
|
154
156
|
if (stack.formatter) config.formatter = formatStackItem(stack.formatter);
|
|
155
157
|
if (stack.testRunner) config.testRunner = formatStackItem(stack.testRunner);
|
|
@@ -321,6 +323,7 @@ function mergeStack(existing, fresh) {
|
|
|
321
323
|
framework: existing.framework ?? fresh.framework,
|
|
322
324
|
styling: existing.styling ?? fresh.styling,
|
|
323
325
|
backend: existing.backend ?? fresh.backend,
|
|
326
|
+
orm: existing.orm ?? fresh.orm,
|
|
324
327
|
linter: existing.linter ?? fresh.linter,
|
|
325
328
|
formatter: existing.formatter ?? fresh.formatter,
|
|
326
329
|
testRunner: existing.testRunner ?? fresh.testRunner
|
|
@@ -398,6 +401,101 @@ function mergePackageOverrides(existing, fresh) {
|
|
|
398
401
|
return merged.length > 0 ? merged : void 0;
|
|
399
402
|
}
|
|
400
403
|
|
|
404
|
+
// src/schema-parts.ts
|
|
405
|
+
var conventionValueDef = {
|
|
406
|
+
description: "A convention value \u2014 either a plain string (user-confirmed) or an object with scanner metadata.",
|
|
407
|
+
oneOf: [
|
|
408
|
+
{ type: "string" },
|
|
409
|
+
{
|
|
410
|
+
type: "object",
|
|
411
|
+
required: ["value", "_confidence", "_consistency"],
|
|
412
|
+
properties: {
|
|
413
|
+
value: {
|
|
414
|
+
type: "string",
|
|
415
|
+
description: "The convention value."
|
|
416
|
+
},
|
|
417
|
+
_confidence: {
|
|
418
|
+
type: "string",
|
|
419
|
+
enum: ["high", "medium", "low"],
|
|
420
|
+
description: "Scanner confidence level."
|
|
421
|
+
},
|
|
422
|
+
_consistency: {
|
|
423
|
+
type: "number",
|
|
424
|
+
minimum: 0,
|
|
425
|
+
maximum: 100,
|
|
426
|
+
description: "Scanner consistency percentage."
|
|
427
|
+
},
|
|
428
|
+
_detected: {
|
|
429
|
+
type: "boolean",
|
|
430
|
+
description: "Set by mergeConfig when a convention is newly detected during sync."
|
|
431
|
+
}
|
|
432
|
+
},
|
|
433
|
+
additionalProperties: false
|
|
434
|
+
}
|
|
435
|
+
]
|
|
436
|
+
};
|
|
437
|
+
var boundaryItemSchema = {
|
|
438
|
+
type: "object",
|
|
439
|
+
required: ["from", "to", "allow"],
|
|
440
|
+
properties: {
|
|
441
|
+
from: {
|
|
442
|
+
type: "string",
|
|
443
|
+
description: "Source package or directory pattern."
|
|
444
|
+
},
|
|
445
|
+
to: {
|
|
446
|
+
type: "string",
|
|
447
|
+
description: "Target package or directory pattern."
|
|
448
|
+
},
|
|
449
|
+
allow: {
|
|
450
|
+
type: "boolean",
|
|
451
|
+
description: "Whether this import direction is allowed or disallowed."
|
|
452
|
+
},
|
|
453
|
+
reason: {
|
|
454
|
+
type: "string",
|
|
455
|
+
description: "Human-readable explanation of why this boundary exists."
|
|
456
|
+
}
|
|
457
|
+
},
|
|
458
|
+
additionalProperties: false
|
|
459
|
+
};
|
|
460
|
+
var packageItemSchema = {
|
|
461
|
+
type: "object",
|
|
462
|
+
required: ["name", "path"],
|
|
463
|
+
properties: {
|
|
464
|
+
name: { type: "string", description: "Package name from package.json." },
|
|
465
|
+
path: { type: "string", description: "Relative path to the package." },
|
|
466
|
+
stack: {
|
|
467
|
+
type: "object",
|
|
468
|
+
properties: {
|
|
469
|
+
framework: { type: "string" },
|
|
470
|
+
language: { type: "string" },
|
|
471
|
+
styling: { type: "string" },
|
|
472
|
+
backend: { type: "string" },
|
|
473
|
+
orm: { type: "string" },
|
|
474
|
+
packageManager: { type: "string" },
|
|
475
|
+
linter: { type: "string" },
|
|
476
|
+
formatter: { type: "string" },
|
|
477
|
+
testRunner: { type: "string" }
|
|
478
|
+
},
|
|
479
|
+
additionalProperties: false
|
|
480
|
+
},
|
|
481
|
+
conventions: { $ref: "#/properties/conventions" },
|
|
482
|
+
rules: {
|
|
483
|
+
type: "object",
|
|
484
|
+
properties: {
|
|
485
|
+
maxFileLines: { type: "number" },
|
|
486
|
+
maxTestFileLines: { type: "number" },
|
|
487
|
+
maxFunctionLines: { type: "number" },
|
|
488
|
+
requireTests: { type: "boolean" },
|
|
489
|
+
enforceNaming: { type: "boolean" },
|
|
490
|
+
enforceBoundaries: { type: "boolean" }
|
|
491
|
+
},
|
|
492
|
+
additionalProperties: false
|
|
493
|
+
},
|
|
494
|
+
ignore: { type: "array", items: { type: "string" } }
|
|
495
|
+
},
|
|
496
|
+
additionalProperties: false
|
|
497
|
+
};
|
|
498
|
+
|
|
401
499
|
// src/schema.ts
|
|
402
500
|
var configSchema = {
|
|
403
501
|
$schema: "http://json-schema.org/draft-07/schema#",
|
|
@@ -446,6 +544,10 @@ var configSchema = {
|
|
|
446
544
|
type: "string",
|
|
447
545
|
description: 'Backend framework (e.g. "express@5", "fastify").'
|
|
448
546
|
},
|
|
547
|
+
orm: {
|
|
548
|
+
type: "string",
|
|
549
|
+
description: 'ORM or database client (e.g. "prisma", "drizzle", "typeorm").'
|
|
550
|
+
},
|
|
449
551
|
packageManager: {
|
|
450
552
|
type: "string",
|
|
451
553
|
description: 'Package manager (e.g. "pnpm", "npm", "yarn").'
|
|
@@ -567,29 +669,7 @@ var configSchema = {
|
|
|
567
669
|
},
|
|
568
670
|
boundaries: {
|
|
569
671
|
type: "array",
|
|
570
|
-
items:
|
|
571
|
-
type: "object",
|
|
572
|
-
required: ["from", "to", "allow"],
|
|
573
|
-
properties: {
|
|
574
|
-
from: {
|
|
575
|
-
type: "string",
|
|
576
|
-
description: "Source package or directory pattern."
|
|
577
|
-
},
|
|
578
|
-
to: {
|
|
579
|
-
type: "string",
|
|
580
|
-
description: "Target package or directory pattern."
|
|
581
|
-
},
|
|
582
|
-
allow: {
|
|
583
|
-
type: "boolean",
|
|
584
|
-
description: "Whether this import direction is allowed or disallowed."
|
|
585
|
-
},
|
|
586
|
-
reason: {
|
|
587
|
-
type: "string",
|
|
588
|
-
description: "Human-readable explanation of why this boundary exists."
|
|
589
|
-
}
|
|
590
|
-
},
|
|
591
|
-
additionalProperties: false
|
|
592
|
-
},
|
|
672
|
+
items: boundaryItemSchema,
|
|
593
673
|
description: "Module boundary rules for import enforcement."
|
|
594
674
|
},
|
|
595
675
|
workspace: {
|
|
@@ -611,85 +691,18 @@ var configSchema = {
|
|
|
611
691
|
},
|
|
612
692
|
packages: {
|
|
613
693
|
type: "array",
|
|
614
|
-
items:
|
|
615
|
-
type: "object",
|
|
616
|
-
required: ["name", "path"],
|
|
617
|
-
properties: {
|
|
618
|
-
name: { type: "string", description: "Package name from package.json." },
|
|
619
|
-
path: { type: "string", description: "Relative path to the package." },
|
|
620
|
-
stack: {
|
|
621
|
-
type: "object",
|
|
622
|
-
properties: {
|
|
623
|
-
framework: { type: "string" },
|
|
624
|
-
language: { type: "string" },
|
|
625
|
-
styling: { type: "string" },
|
|
626
|
-
backend: { type: "string" },
|
|
627
|
-
packageManager: { type: "string" },
|
|
628
|
-
linter: { type: "string" },
|
|
629
|
-
formatter: { type: "string" },
|
|
630
|
-
testRunner: { type: "string" }
|
|
631
|
-
},
|
|
632
|
-
additionalProperties: false
|
|
633
|
-
},
|
|
634
|
-
conventions: { $ref: "#/properties/conventions" },
|
|
635
|
-
rules: {
|
|
636
|
-
type: "object",
|
|
637
|
-
properties: {
|
|
638
|
-
maxFileLines: { type: "number" },
|
|
639
|
-
maxTestFileLines: { type: "number" },
|
|
640
|
-
maxFunctionLines: { type: "number" },
|
|
641
|
-
requireTests: { type: "boolean" },
|
|
642
|
-
enforceNaming: { type: "boolean" },
|
|
643
|
-
enforceBoundaries: { type: "boolean" }
|
|
644
|
-
},
|
|
645
|
-
additionalProperties: false
|
|
646
|
-
},
|
|
647
|
-
ignore: { type: "array", items: { type: "string" } }
|
|
648
|
-
},
|
|
649
|
-
additionalProperties: false
|
|
650
|
-
},
|
|
694
|
+
items: packageItemSchema,
|
|
651
695
|
description: "Per-package overrides for monorepo projects."
|
|
652
696
|
}
|
|
653
697
|
},
|
|
654
698
|
additionalProperties: false,
|
|
655
699
|
definitions: {
|
|
656
|
-
conventionValue:
|
|
657
|
-
description: "A convention value \u2014 either a plain string (user-confirmed) or an object with scanner metadata.",
|
|
658
|
-
oneOf: [
|
|
659
|
-
{ type: "string" },
|
|
660
|
-
{
|
|
661
|
-
type: "object",
|
|
662
|
-
required: ["value", "_confidence", "_consistency"],
|
|
663
|
-
properties: {
|
|
664
|
-
value: {
|
|
665
|
-
type: "string",
|
|
666
|
-
description: "The convention value."
|
|
667
|
-
},
|
|
668
|
-
_confidence: {
|
|
669
|
-
type: "string",
|
|
670
|
-
enum: ["high", "medium", "low"],
|
|
671
|
-
description: "Scanner confidence level."
|
|
672
|
-
},
|
|
673
|
-
_consistency: {
|
|
674
|
-
type: "number",
|
|
675
|
-
minimum: 0,
|
|
676
|
-
maximum: 100,
|
|
677
|
-
description: "Scanner consistency percentage."
|
|
678
|
-
},
|
|
679
|
-
_detected: {
|
|
680
|
-
type: "boolean",
|
|
681
|
-
description: "Set by mergeConfig when a convention is newly detected during sync."
|
|
682
|
-
}
|
|
683
|
-
},
|
|
684
|
-
additionalProperties: false
|
|
685
|
-
}
|
|
686
|
-
]
|
|
687
|
-
}
|
|
700
|
+
conventionValue: conventionValueDef
|
|
688
701
|
}
|
|
689
702
|
};
|
|
690
703
|
|
|
691
704
|
// src/index.ts
|
|
692
|
-
var VERSION = "0.
|
|
705
|
+
var VERSION = "0.3.1";
|
|
693
706
|
// Annotate the CommonJS export names for ESM import in node:
|
|
694
707
|
0 && (module.exports = {
|
|
695
708
|
DEFAULT_IGNORE,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/defaults.ts","../src/generate-config.ts","../src/generate-overrides.ts","../src/load-config.ts","../src/merge-config.ts","../src/schema.ts"],"sourcesContent":["declare const __PACKAGE_VERSION__: string;\nexport const VERSION: string = __PACKAGE_VERSION__;\n\nexport { DEFAULT_IGNORE, DEFAULT_RULES } from './defaults.js';\nexport { generateConfig } from './generate-config.js';\nexport { loadConfig, loadConfigSafe } from './load-config.js';\nexport { mergeConfig } from './merge-config.js';\nexport { configSchema } from './schema.js';\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 maxFunctionLines: 50,\n requireTests: true,\n enforceNaming: true,\n enforceBoundaries: false,\n};\n\n/**\n * Default glob patterns for files and directories to ignore.\n */\nexport const DEFAULT_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 * as path from 'node:path';\nimport type {\n ConfigConventions,\n ConfigStack,\n ConfigStructure,\n ConventionValue,\n DetectedConvention,\n DirectoryRole,\n ScanResult,\n StackItem,\n ViberailsConfig,\n} from '@viberails/types';\nimport { DEFAULT_IGNORE, DEFAULT_RULES } from './defaults.js';\nimport { generatePackageOverrides } from './generate-overrides.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 */\nfunction 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.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 */\nfunction 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/**\n * Convert a DetectedConvention to a ConventionValue with metadata.\n * Returns undefined for low-confidence conventions (they are omitted).\n */\nexport function mapConvention(convention: DetectedConvention): ConventionValue | undefined {\n if (convention.confidence === 'low') {\n return undefined;\n }\n\n return {\n value: convention.value,\n _confidence: convention.confidence,\n _consistency: convention.consistency,\n };\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, omitting low-confidence entries.\n */\nfunction mapConventions(scanResult: ScanResult): ConfigConventions {\n const config: ConfigConventions = {};\n\n for (const key of CONVENTION_KEYS) {\n const detected = scanResult.conventions[key];\n if (detected) {\n const value = mapConvention(detected);\n if (value !== undefined) {\n config[key] = value;\n }\n }\n }\n\n return config;\n}\n\n/**\n * Generate a ViberailsConfig from scan results.\n *\n * Maps the scanner's DetectedStack, DetectedStructure, and conventions\n * into the config format with smart defaults. Low-confidence conventions\n * are omitted. The project name is derived from the root directory basename.\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 config: ViberailsConfig = {\n $schema: 'https://viberails.sh/schema/v1.json',\n version: 1,\n name: path.basename(scanResult.root),\n enforcement: 'warn',\n stack: mapStack(scanResult),\n structure: mapStructure(scanResult),\n conventions: mapConventions(scanResult),\n rules: { ...DEFAULT_RULES },\n ignore: [...DEFAULT_IGNORE],\n };\n\n if (scanResult.workspace) {\n config.workspace = {\n packages: scanResult.workspace.packages.map((p) => p.relativePath),\n isMonorepo: true,\n };\n config.boundaries = [];\n }\n\n const packageOverrides = generatePackageOverrides(scanResult, config);\n if (packageOverrides) {\n config.packages = packageOverrides;\n }\n\n return config;\n}\n","import type {\n ConfigConventions,\n ConfigStack,\n DetectedConvention,\n PackageConfigOverrides,\n ScanResult,\n ViberailsConfig,\n} from '@viberails/types';\nimport { CONVENTION_KEYS, formatStackItem, mapConvention } from './generate-config.js';\n\n/**\n * Compare a package's conventions against the global config conventions.\n * Returns only the differing conventions, or undefined if all match.\n */\nexport function conventionsDiffer(\n pkgConventions: Record<string, DetectedConvention>,\n globalConventions: ConfigConventions,\n): Partial<ConfigConventions> | undefined {\n const overrides: Partial<ConfigConventions> = {};\n let hasDiff = false;\n\n for (const key of CONVENTION_KEYS) {\n const detected = pkgConventions[key];\n if (!detected) continue;\n\n const mapped = mapConvention(detected);\n if (mapped === undefined) continue;\n\n const globalValue = globalConventions[key];\n const globalStr = typeof globalValue === 'string' ? globalValue : globalValue?.value;\n if (detected.value !== globalStr) {\n overrides[key] = mapped;\n hasDiff = true;\n }\n }\n\n return hasDiff ? overrides : undefined;\n}\n\n/**\n * Generate per-package config overrides for packages whose stack or\n * conventions differ from the aggregate global config.\n */\nexport function generatePackageOverrides(\n scanResult: ScanResult,\n globalConfig: ViberailsConfig,\n): PackageConfigOverrides[] | undefined {\n if (!scanResult.packages || scanResult.packages.length <= 1) return undefined;\n\n const overrides: PackageConfigOverrides[] = [];\n\n for (const pkg of scanResult.packages) {\n const override: PackageConfigOverrides = {\n name: pkg.name,\n path: pkg.relativePath,\n };\n let hasDiff = false;\n\n // Compare stack fields — only include overrides when the package has a\n // value that differs from the global, not when the package simply lacks the field\n const stackOverride: Partial<ConfigStack> = {};\n let hasStackDiff = false;\n\n const optionalStackFields = [\n 'framework',\n 'styling',\n 'backend',\n 'linter',\n 'formatter',\n 'testRunner',\n ] as const;\n for (const field of optionalStackFields) {\n const pkgItem = pkg.stack[field];\n if (!pkgItem) continue;\n const pkgValue = formatStackItem(pkgItem);\n if (pkgValue !== globalConfig.stack[field]) {\n stackOverride[field] = pkgValue;\n hasStackDiff = true;\n }\n }\n\n if (hasStackDiff) {\n override.stack = stackOverride;\n hasDiff = true;\n }\n\n // Compare conventions\n const conventionOverrides = conventionsDiffer(pkg.conventions, globalConfig.conventions);\n if (conventionOverrides) {\n override.conventions = conventionOverrides;\n hasDiff = true;\n }\n\n if (hasDiff) {\n overrides.push(override);\n }\n }\n\n return overrides.length > 0 ? overrides : undefined;\n}\n","import * as fs from 'node:fs/promises';\nimport type { ViberailsConfig } from '@viberails/types';\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', 'stack', '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') errors.push('\"version\" must be a number');\n if (typeof parsed.name !== 'string') errors.push('\"name\" must be a string');\n if (\n parsed.enforcement !== undefined &&\n parsed.enforcement !== 'warn' &&\n parsed.enforcement !== 'enforce'\n ) {\n errors.push('\"enforcement\" must be \"warn\" or \"enforce\"');\n }\n\n // Stack validation\n if (typeof parsed.stack !== 'object' || parsed.stack === null) {\n errors.push('\"stack\" must be an object');\n } else {\n const stack = parsed.stack as Record<string, unknown>;\n if (typeof stack.language !== 'string') errors.push('\"stack.language\" must be a string');\n if (typeof stack.packageManager !== 'string')\n errors.push('\"stack.packageManager\" must be a string');\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 if (typeof rules.maxFunctionLines !== 'number')\n errors.push('\"rules.maxFunctionLines\" must be a number');\n if (typeof rules.requireTests !== 'boolean')\n errors.push('\"rules.requireTests\" must be a boolean');\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 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, stack, rules), and returns\n * the parsed config.\n *\n * @param configPath - Absolute or relative path to viberails.config.json\n * @returns The parsed ViberailsConfig\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 V1.0\n const rules = parsed.rules as Record<string, unknown>;\n if (rules.maxTestFileLines === undefined) {\n rules.maxTestFileLines = 0;\n }\n\n // Safe to cast: validateConfig has verified all required fields and types\n return parsed as unknown as ViberailsConfig;\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 ConventionValue,\n PackageConfigOverrides,\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 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 * Check if a convention key exists in the existing config\n * (either as a string or as an object with a value).\n */\nfunction hasConvention(conventions: ConfigConventions, key: keyof ConfigConventions): boolean {\n return conventions[key] !== undefined;\n}\n\n/**\n * Mark a ConventionValue as newly detected by adding `_detected: true`.\n * Only applies to object-form values (not plain strings).\n */\nfunction markAsDetected(value: ConventionValue): ConventionValue {\n if (typeof value === 'string') {\n return { value, _confidence: 'high', _consistency: 100, _detected: true };\n }\n return { ...value, _detected: true };\n}\n\n/**\n * Merge conventions: keep all existing values, add new detections with `_detected: true`.\n */\nfunction mergeConventions(\n existing: ConfigConventions,\n fresh: ConfigConventions,\n): ConfigConventions {\n const merged: ConfigConventions = { ...existing };\n\n for (const key of CONVENTION_KEYS) {\n if (!hasConvention(existing, key) && fresh[key] !== undefined) {\n const freshValue = fresh[key];\n if (freshValue !== undefined) {\n merged[key] = markAsDetected(freshValue);\n }\n }\n }\n\n return merged;\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 conventions with a `_detected: true` annotation\n * so the developer can review them. Never removes rules or values\n * the developer has set.\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 merged: ViberailsConfig = {\n $schema: existing.$schema ?? fresh.$schema,\n version: existing.version,\n name: existing.name,\n enforcement: existing.enforcement,\n stack: mergeStack(existing.stack, fresh.stack),\n structure: mergeStructure(existing.structure, fresh.structure),\n conventions: mergeConventions(existing.conventions, fresh.conventions),\n rules: { ...existing.rules },\n ignore: [...existing.ignore],\n };\n\n // Workspace: always take fresh scan (structure can change)\n if (fresh.workspace) {\n merged.workspace = fresh.workspace;\n }\n\n // Boundaries: preserve existing rules (user may have adjusted)\n if (existing.boundaries) {\n merged.boundaries = [...existing.boundaries];\n } else if (fresh.boundaries) {\n merged.boundaries = [...fresh.boundaries];\n }\n\n // Packages: preserve existing overrides, add new ones\n if (existing.packages || fresh.packages) {\n merged.packages = mergePackageOverrides(existing.packages, fresh.packages);\n }\n\n return merged;\n}\n\n/**\n * Merge per-package overrides: keep existing user-edited overrides,\n * add new packages from fresh scan.\n */\nfunction mergePackageOverrides(\n existing?: PackageConfigOverrides[],\n fresh?: PackageConfigOverrides[],\n): PackageConfigOverrides[] | undefined {\n if (!fresh || fresh.length === 0) return existing;\n if (!existing || existing.length === 0) return fresh;\n\n const existingByPath = new Map(existing.map((p) => [p.path, p]));\n const merged: PackageConfigOverrides[] = [...existing];\n\n for (const freshPkg of fresh) {\n if (!existingByPath.has(freshPkg.path)) {\n merged.push(freshPkg);\n }\n }\n\n return merged.length > 0 ? merged : undefined;\n}\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 */\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', 'stack', '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 for V1.0.',\n },\n name: {\n type: 'string',\n description: 'Project name, typically from package.json.',\n },\n enforcement: {\n type: 'string',\n enum: ['warn', 'enforce'],\n default: 'warn',\n description: 'Whether conventions are warned about or enforced as errors.',\n },\n stack: {\n type: 'object',\n required: ['language', 'packageManager'],\n properties: {\n framework: {\n type: 'string',\n description: 'Primary framework identifier (e.g. \"nextjs@15\", \"remix@2\").',\n },\n language: {\n type: 'string',\n description: 'Primary language (e.g. \"typescript\", \"javascript\").',\n },\n styling: {\n type: 'string',\n description: 'Styling solution (e.g. \"tailwindcss@4\", \"css-modules\").',\n },\n backend: {\n type: 'string',\n description: 'Backend framework (e.g. \"express@5\", \"fastify\").',\n },\n packageManager: {\n type: 'string',\n description: 'Package manager (e.g. \"pnpm\", \"npm\", \"yarn\").',\n },\n linter: {\n type: 'string',\n description: 'Linter (e.g. \"eslint@9\", \"biome\").',\n },\n formatter: {\n type: 'string',\n description: 'Formatter (e.g. \"prettier\", \"biome\").',\n },\n testRunner: {\n type: 'string',\n description: 'Test runner (e.g. \"vitest\", \"jest\").',\n },\n },\n additionalProperties: false,\n description: 'Detected or configured technology stack.',\n },\n structure: {\n type: 'object',\n properties: {\n srcDir: {\n type: 'string',\n description: 'Source directory (e.g. \"src\"), or omit for flat structure.',\n },\n pages: {\n type: 'string',\n description: 'Pages or routes directory (e.g. \"src/app\").',\n },\n components: {\n type: 'string',\n description: 'Components directory (e.g. \"src/components\").',\n },\n hooks: {\n type: 'string',\n description: 'Hooks directory (e.g. \"src/hooks\").',\n },\n utils: {\n type: 'string',\n description: 'Utilities directory (e.g. \"src/utils\", \"src/lib\").',\n },\n types: {\n type: 'string',\n description: 'Type definitions directory (e.g. \"src/types\").',\n },\n tests: {\n type: 'string',\n description: 'Tests directory (e.g. \"tests\", \"__tests__\").',\n },\n testPattern: {\n type: 'string',\n description: 'Test file naming pattern (e.g. \"*.test.ts\", \"*.spec.ts\").',\n },\n },\n additionalProperties: false,\n description: 'Detected or configured directory structure.',\n },\n conventions: {\n type: 'object',\n properties: {\n fileNaming: { $ref: '#/definitions/conventionValue' },\n componentNaming: { $ref: '#/definitions/conventionValue' },\n hookNaming: { $ref: '#/definitions/conventionValue' },\n importAlias: { $ref: '#/definitions/conventionValue' },\n },\n additionalProperties: false,\n description: 'Detected or configured coding conventions.',\n },\n rules: {\n type: 'object',\n required: [\n 'maxFileLines',\n 'maxFunctionLines',\n 'requireTests',\n 'enforceNaming',\n 'enforceBoundaries',\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 from size checks.',\n },\n maxFunctionLines: {\n type: 'number',\n default: 50,\n description: 'Maximum number of lines allowed per function.',\n },\n requireTests: {\n type: 'boolean',\n default: true,\n description: 'Whether to require test files for source modules.',\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 },\n additionalProperties: false,\n description: 'Rule thresholds and toggles for enforcement.',\n },\n ignore: {\n type: 'array',\n items: { type: 'string' },\n description: 'Glob patterns for files and directories to ignore.',\n },\n boundaries: {\n type: 'array',\n items: {\n type: 'object',\n required: ['from', 'to', 'allow'],\n properties: {\n from: {\n type: 'string',\n description: 'Source package or directory pattern.',\n },\n to: {\n type: 'string',\n description: 'Target package or directory pattern.',\n },\n allow: {\n type: 'boolean',\n description: 'Whether this import direction is allowed or disallowed.',\n },\n reason: {\n type: 'string',\n description: 'Human-readable explanation of why this boundary exists.',\n },\n },\n additionalProperties: false,\n },\n description: 'Module boundary rules for import enforcement.',\n },\n workspace: {\n type: 'object',\n required: ['packages', 'isMonorepo'],\n properties: {\n packages: {\n type: 'array',\n items: { type: 'string' },\n description: 'Relative paths to workspace packages.',\n },\n isMonorepo: {\n type: 'boolean',\n description: 'Whether this project is a monorepo with multiple packages.',\n },\n },\n additionalProperties: false,\n description: 'Workspace configuration for monorepo projects.',\n },\n packages: {\n type: 'array',\n items: {\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.' },\n stack: {\n type: 'object',\n properties: {\n framework: { type: 'string' },\n language: { type: 'string' },\n styling: { type: 'string' },\n backend: { type: 'string' },\n packageManager: { type: 'string' },\n linter: { type: 'string' },\n formatter: { type: 'string' },\n testRunner: { type: 'string' },\n },\n additionalProperties: false,\n },\n conventions: { $ref: '#/properties/conventions' },\n rules: {\n type: 'object',\n properties: {\n maxFileLines: { type: 'number' },\n maxTestFileLines: { type: 'number' },\n maxFunctionLines: { type: 'number' },\n requireTests: { type: 'boolean' },\n enforceNaming: { type: 'boolean' },\n enforceBoundaries: { type: 'boolean' },\n },\n additionalProperties: false,\n },\n ignore: { type: 'array', items: { type: 'string' } },\n },\n additionalProperties: false,\n },\n description: 'Per-package overrides for monorepo projects.',\n },\n },\n additionalProperties: false,\n definitions: {\n conventionValue: {\n description:\n 'A convention value — either a plain string (user-confirmed) or an object with scanner metadata.',\n oneOf: [\n { type: 'string' },\n {\n type: 'object',\n required: ['value', '_confidence', '_consistency'],\n properties: {\n value: {\n type: 'string',\n description: 'The convention value.',\n },\n _confidence: {\n type: 'string',\n enum: ['high', 'medium', 'low'],\n description: 'Scanner confidence level.',\n },\n _consistency: {\n type: 'number',\n minimum: 0,\n maximum: 100,\n description: 'Scanner consistency percentage.',\n },\n _detected: {\n type: 'boolean',\n description: 'Set by mergeConfig when a convention is newly detected during sync.',\n },\n },\n additionalProperties: false,\n },\n ],\n },\n },\n} as const;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/defaults.ts","../src/generate-config.ts","../src/generate-overrides.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 { DEFAULT_IGNORE, DEFAULT_RULES } from './defaults.js';\nexport { generateConfig } from './generate-config.js';\nexport { loadConfig, loadConfigSafe } from './load-config.js';\nexport { mergeConfig } from './merge-config.js';\nexport { configSchema } from './schema.js';\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 maxFunctionLines: 50,\n requireTests: true,\n enforceNaming: true,\n enforceBoundaries: false,\n};\n\n/**\n * Default glob patterns for files and directories to ignore.\n */\nexport const DEFAULT_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 * as path from 'node:path';\nimport type {\n ConfigConventions,\n ConfigStack,\n ConfigStructure,\n ConventionValue,\n DetectedConvention,\n DirectoryRole,\n ScanResult,\n StackItem,\n ViberailsConfig,\n} from '@viberails/types';\nimport { DEFAULT_IGNORE, DEFAULT_RULES } from './defaults.js';\nimport { generatePackageOverrides } from './generate-overrides.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 */\nfunction 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 */\nfunction 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/**\n * Convert a DetectedConvention to a ConventionValue with metadata.\n * Returns undefined for low-confidence conventions (they are omitted).\n */\nexport function mapConvention(convention: DetectedConvention): ConventionValue | undefined {\n if (convention.confidence === 'low') {\n return undefined;\n }\n\n return {\n value: convention.value,\n _confidence: convention.confidence,\n _consistency: convention.consistency,\n };\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, omitting low-confidence entries.\n */\nfunction mapConventions(scanResult: ScanResult): ConfigConventions {\n const config: ConfigConventions = {};\n\n for (const key of CONVENTION_KEYS) {\n const detected = scanResult.conventions[key];\n if (detected) {\n const value = mapConvention(detected);\n if (value !== undefined) {\n config[key] = value;\n }\n }\n }\n\n return config;\n}\n\n/**\n * Generate a ViberailsConfig from scan results.\n *\n * Maps the scanner's DetectedStack, DetectedStructure, and conventions\n * into the config format with smart defaults. Low-confidence conventions\n * are omitted. The project name is derived from the root directory basename.\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 config: ViberailsConfig = {\n $schema: 'https://viberails.sh/schema/v1.json',\n version: 1,\n name: path.basename(scanResult.root),\n enforcement: 'warn',\n stack: mapStack(scanResult),\n structure: mapStructure(scanResult),\n conventions: mapConventions(scanResult),\n rules: { ...DEFAULT_RULES },\n ignore: [...DEFAULT_IGNORE],\n };\n\n if (scanResult.workspace) {\n config.workspace = {\n packages: scanResult.workspace.packages.map((p) => p.relativePath),\n isMonorepo: true,\n };\n config.boundaries = [];\n }\n\n const packageOverrides = generatePackageOverrides(scanResult, config);\n if (packageOverrides) {\n config.packages = packageOverrides;\n }\n\n return config;\n}\n","import type {\n ConfigConventions,\n ConfigStack,\n DetectedConvention,\n PackageConfigOverrides,\n ScanResult,\n ViberailsConfig,\n} from '@viberails/types';\nimport { CONVENTION_KEYS, formatStackItem, mapConvention } from './generate-config.js';\n\n/**\n * Compare a package's conventions against the global config conventions.\n * Returns only the differing conventions, or undefined if all match.\n */\nexport function conventionsDiffer(\n pkgConventions: Record<string, DetectedConvention>,\n globalConventions: ConfigConventions,\n): Partial<ConfigConventions> | undefined {\n const overrides: Partial<ConfigConventions> = {};\n let hasDiff = false;\n\n for (const key of CONVENTION_KEYS) {\n const detected = pkgConventions[key];\n if (!detected) continue;\n\n const mapped = mapConvention(detected);\n if (mapped === undefined) continue;\n\n const globalValue = globalConventions[key];\n const globalStr = typeof globalValue === 'string' ? globalValue : globalValue?.value;\n if (detected.value !== globalStr) {\n overrides[key] = mapped;\n hasDiff = true;\n }\n }\n\n return hasDiff ? overrides : undefined;\n}\n\n/**\n * Generate per-package config overrides for packages whose stack or\n * conventions differ from the aggregate global config.\n */\nexport function generatePackageOverrides(\n scanResult: ScanResult,\n globalConfig: ViberailsConfig,\n): PackageConfigOverrides[] | undefined {\n if (!scanResult.packages || scanResult.packages.length <= 1) return undefined;\n\n const overrides: PackageConfigOverrides[] = [];\n\n for (const pkg of scanResult.packages) {\n const override: PackageConfigOverrides = {\n name: pkg.name,\n path: pkg.relativePath,\n };\n let hasDiff = false;\n\n // Compare stack fields — only include overrides when the package has a\n // value that differs from the global, not when the package simply lacks the field\n const stackOverride: Partial<ConfigStack> = {};\n let hasStackDiff = false;\n\n const optionalStackFields = [\n 'framework',\n 'styling',\n 'backend',\n 'orm',\n 'linter',\n 'formatter',\n 'testRunner',\n ] as const;\n for (const field of optionalStackFields) {\n const pkgItem = pkg.stack[field];\n if (!pkgItem) continue;\n const pkgValue = formatStackItem(pkgItem);\n if (pkgValue !== globalConfig.stack[field]) {\n stackOverride[field] = pkgValue;\n hasStackDiff = true;\n }\n }\n\n if (hasStackDiff) {\n override.stack = stackOverride;\n hasDiff = true;\n }\n\n // Compare conventions\n const conventionOverrides = conventionsDiffer(pkg.conventions, globalConfig.conventions);\n if (conventionOverrides) {\n override.conventions = conventionOverrides;\n hasDiff = true;\n }\n\n if (hasDiff) {\n overrides.push(override);\n }\n }\n\n return overrides.length > 0 ? overrides : undefined;\n}\n","import * as fs from 'node:fs/promises';\nimport type { ViberailsConfig } from '@viberails/types';\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', 'stack', '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') errors.push('\"version\" must be a number');\n if (typeof parsed.name !== 'string') errors.push('\"name\" must be a string');\n if (\n parsed.enforcement !== undefined &&\n parsed.enforcement !== 'warn' &&\n parsed.enforcement !== 'enforce'\n ) {\n errors.push('\"enforcement\" must be \"warn\" or \"enforce\"');\n }\n\n // Stack validation\n if (typeof parsed.stack !== 'object' || parsed.stack === null) {\n errors.push('\"stack\" must be an object');\n } else {\n const stack = parsed.stack as Record<string, unknown>;\n if (typeof stack.language !== 'string') errors.push('\"stack.language\" must be a string');\n if (typeof stack.packageManager !== 'string')\n errors.push('\"stack.packageManager\" must be a string');\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 if (typeof rules.maxFunctionLines !== 'number')\n errors.push('\"rules.maxFunctionLines\" must be a number');\n if (typeof rules.requireTests !== 'boolean')\n errors.push('\"rules.requireTests\" must be a boolean');\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 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, stack, rules), and returns\n * the parsed config.\n *\n * @param configPath - Absolute or relative path to viberails.config.json\n * @returns The parsed ViberailsConfig\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 V1.0\n const rules = parsed.rules as Record<string, unknown>;\n if (rules.maxTestFileLines === undefined) {\n rules.maxTestFileLines = 0;\n }\n\n // Safe to cast: validateConfig has verified all required fields and types\n return parsed as unknown as ViberailsConfig;\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 ConventionValue,\n PackageConfigOverrides,\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 * Check if a convention key exists in the existing config\n * (either as a string or as an object with a value).\n */\nfunction hasConvention(conventions: ConfigConventions, key: keyof ConfigConventions): boolean {\n return conventions[key] !== undefined;\n}\n\n/**\n * Mark a ConventionValue as newly detected by adding `_detected: true`.\n * Only applies to object-form values (not plain strings).\n */\nfunction markAsDetected(value: ConventionValue): ConventionValue {\n if (typeof value === 'string') {\n return { value, _confidence: 'high', _consistency: 100, _detected: true };\n }\n return { ...value, _detected: true };\n}\n\n/**\n * Merge conventions: keep all existing values, add new detections with `_detected: true`.\n */\nfunction mergeConventions(\n existing: ConfigConventions,\n fresh: ConfigConventions,\n): ConfigConventions {\n const merged: ConfigConventions = { ...existing };\n\n for (const key of CONVENTION_KEYS) {\n if (!hasConvention(existing, key) && fresh[key] !== undefined) {\n const freshValue = fresh[key];\n if (freshValue !== undefined) {\n merged[key] = markAsDetected(freshValue);\n }\n }\n }\n\n return merged;\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 conventions with a `_detected: true` annotation\n * so the developer can review them. Never removes rules or values\n * the developer has set.\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 merged: ViberailsConfig = {\n $schema: existing.$schema ?? fresh.$schema,\n version: existing.version,\n name: existing.name,\n enforcement: existing.enforcement,\n stack: mergeStack(existing.stack, fresh.stack),\n structure: mergeStructure(existing.structure, fresh.structure),\n conventions: mergeConventions(existing.conventions, fresh.conventions),\n rules: { ...existing.rules },\n ignore: [...existing.ignore],\n };\n\n // Workspace: always take fresh scan (structure can change)\n if (fresh.workspace) {\n merged.workspace = fresh.workspace;\n }\n\n // Boundaries: preserve existing rules (user may have adjusted)\n if (existing.boundaries) {\n merged.boundaries = [...existing.boundaries];\n } else if (fresh.boundaries) {\n merged.boundaries = [...fresh.boundaries];\n }\n\n // Packages: preserve existing overrides, add new ones\n if (existing.packages || fresh.packages) {\n merged.packages = mergePackageOverrides(existing.packages, fresh.packages);\n }\n\n return merged;\n}\n\n/**\n * Merge per-package overrides: keep existing user-edited overrides,\n * add new packages from fresh scan.\n */\nfunction mergePackageOverrides(\n existing?: PackageConfigOverrides[],\n fresh?: PackageConfigOverrides[],\n): PackageConfigOverrides[] | undefined {\n if (!fresh || fresh.length === 0) return existing;\n if (!existing || existing.length === 0) return fresh;\n\n const existingByPath = new Map(existing.map((p) => [p.path, p]));\n const merged: PackageConfigOverrides[] = [...existing];\n\n for (const freshPkg of fresh) {\n if (!existingByPath.has(freshPkg.path)) {\n merged.push(freshPkg);\n }\n }\n\n return merged.length > 0 ? merged : undefined;\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 conventionValueDef = {\n description:\n 'A convention value — either a plain string (user-confirmed) or an object with scanner metadata.',\n oneOf: [\n { type: 'string' },\n {\n type: 'object',\n required: ['value', '_confidence', '_consistency'],\n properties: {\n value: {\n type: 'string',\n description: 'The convention value.',\n },\n _confidence: {\n type: 'string',\n enum: ['high', 'medium', 'low'],\n description: 'Scanner confidence level.',\n },\n _consistency: {\n type: 'number',\n minimum: 0,\n maximum: 100,\n description: 'Scanner consistency percentage.',\n },\n _detected: {\n type: 'boolean',\n description: 'Set by mergeConfig when a convention is newly detected during sync.',\n },\n },\n additionalProperties: false,\n },\n ],\n} as const;\n\nexport const boundaryItemSchema = {\n type: 'object',\n required: ['from', 'to', 'allow'],\n properties: {\n from: {\n type: 'string',\n description: 'Source package or directory pattern.',\n },\n to: {\n type: 'string',\n description: 'Target package or directory pattern.',\n },\n allow: {\n type: 'boolean',\n description: 'Whether this import direction is allowed or disallowed.',\n },\n reason: {\n type: 'string',\n description: 'Human-readable explanation of why this boundary exists.',\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.' },\n stack: {\n type: 'object',\n properties: {\n framework: { type: 'string' },\n language: { type: 'string' },\n styling: { type: 'string' },\n backend: { type: 'string' },\n orm: { type: 'string' },\n packageManager: { type: 'string' },\n linter: { type: 'string' },\n formatter: { type: 'string' },\n testRunner: { type: 'string' },\n },\n additionalProperties: false,\n },\n conventions: { $ref: '#/properties/conventions' },\n rules: {\n type: 'object',\n properties: {\n maxFileLines: { type: 'number' },\n maxTestFileLines: { type: 'number' },\n maxFunctionLines: { type: 'number' },\n requireTests: { type: 'boolean' },\n enforceNaming: { type: 'boolean' },\n enforceBoundaries: { type: 'boolean' },\n },\n additionalProperties: false,\n },\n ignore: { type: 'array', items: { type: 'string' } },\n },\n additionalProperties: false,\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 { boundaryItemSchema, conventionValueDef, 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', 'stack', '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 for V1.0.',\n },\n name: {\n type: 'string',\n description: 'Project name, typically from package.json.',\n },\n enforcement: {\n type: 'string',\n enum: ['warn', 'enforce'],\n default: 'warn',\n description: 'Whether conventions are warned about or enforced as errors.',\n },\n stack: {\n type: 'object',\n required: ['language', 'packageManager'],\n properties: {\n framework: {\n type: 'string',\n description: 'Primary framework identifier (e.g. \"nextjs@15\", \"remix@2\").',\n },\n language: {\n type: 'string',\n description: 'Primary language (e.g. \"typescript\", \"javascript\").',\n },\n styling: {\n type: 'string',\n description: 'Styling solution (e.g. \"tailwindcss@4\", \"css-modules\").',\n },\n backend: {\n type: 'string',\n description: 'Backend framework (e.g. \"express@5\", \"fastify\").',\n },\n orm: {\n type: 'string',\n description: 'ORM or database client (e.g. \"prisma\", \"drizzle\", \"typeorm\").',\n },\n packageManager: {\n type: 'string',\n description: 'Package manager (e.g. \"pnpm\", \"npm\", \"yarn\").',\n },\n linter: {\n type: 'string',\n description: 'Linter (e.g. \"eslint@9\", \"biome\").',\n },\n formatter: {\n type: 'string',\n description: 'Formatter (e.g. \"prettier\", \"biome\").',\n },\n testRunner: {\n type: 'string',\n description: 'Test runner (e.g. \"vitest\", \"jest\").',\n },\n },\n additionalProperties: false,\n description: 'Detected or configured technology stack.',\n },\n structure: {\n type: 'object',\n properties: {\n srcDir: {\n type: 'string',\n description: 'Source directory (e.g. \"src\"), or omit for flat structure.',\n },\n pages: {\n type: 'string',\n description: 'Pages or routes directory (e.g. \"src/app\").',\n },\n components: {\n type: 'string',\n description: 'Components directory (e.g. \"src/components\").',\n },\n hooks: {\n type: 'string',\n description: 'Hooks directory (e.g. \"src/hooks\").',\n },\n utils: {\n type: 'string',\n description: 'Utilities directory (e.g. \"src/utils\", \"src/lib\").',\n },\n types: {\n type: 'string',\n description: 'Type definitions directory (e.g. \"src/types\").',\n },\n tests: {\n type: 'string',\n description: 'Tests directory (e.g. \"tests\", \"__tests__\").',\n },\n testPattern: {\n type: 'string',\n description: 'Test file naming pattern (e.g. \"*.test.ts\", \"*.spec.ts\").',\n },\n },\n additionalProperties: false,\n description: 'Detected or configured directory structure.',\n },\n conventions: {\n type: 'object',\n properties: {\n fileNaming: { $ref: '#/definitions/conventionValue' },\n componentNaming: { $ref: '#/definitions/conventionValue' },\n hookNaming: { $ref: '#/definitions/conventionValue' },\n importAlias: { $ref: '#/definitions/conventionValue' },\n },\n additionalProperties: false,\n description: 'Detected or configured coding conventions.',\n },\n rules: {\n type: 'object',\n required: [\n 'maxFileLines',\n 'maxFunctionLines',\n 'requireTests',\n 'enforceNaming',\n 'enforceBoundaries',\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 from size checks.',\n },\n maxFunctionLines: {\n type: 'number',\n default: 50,\n description: 'Maximum number of lines allowed per function.',\n },\n requireTests: {\n type: 'boolean',\n default: true,\n description: 'Whether to require test files for source modules.',\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 },\n additionalProperties: false,\n description: 'Rule thresholds and toggles for enforcement.',\n },\n ignore: {\n type: 'array',\n items: { type: 'string' },\n description: 'Glob patterns for files and directories to ignore.',\n },\n boundaries: {\n type: 'array',\n items: boundaryItemSchema,\n description: 'Module boundary rules for import enforcement.',\n },\n workspace: {\n type: 'object',\n required: ['packages', 'isMonorepo'],\n properties: {\n packages: {\n type: 'array',\n items: { type: 'string' },\n description: 'Relative paths to workspace packages.',\n },\n isMonorepo: {\n type: 'boolean',\n description: 'Whether this project is a monorepo with multiple packages.',\n },\n },\n additionalProperties: false,\n description: 'Workspace configuration for monorepo projects.',\n },\n packages: {\n type: 'array',\n items: packageItemSchema,\n description: 'Per-package overrides for monorepo projects.',\n },\n },\n additionalProperties: false,\n definitions: {\n conventionValue: conventionValueDef,\n },\n} as const;\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -59,12 +59,6 @@ declare function loadConfigSafe(configPath: string): Promise<ViberailsConfig | n
|
|
|
59
59
|
*/
|
|
60
60
|
declare function mergeConfig(existing: ViberailsConfig, scanResult: ScanResult): ViberailsConfig;
|
|
61
61
|
|
|
62
|
-
/**
|
|
63
|
-
* JSON Schema (draft-07) definition for viberails.config.json.
|
|
64
|
-
*
|
|
65
|
-
* This schema will eventually be hosted at https://viberails.sh/schema/v1.json.
|
|
66
|
-
* For now it is exported as a TypeScript object that can be serialized to JSON.
|
|
67
|
-
*/
|
|
68
62
|
declare const configSchema: {
|
|
69
63
|
readonly $schema: "http://json-schema.org/draft-07/schema#";
|
|
70
64
|
readonly $id: "https://viberails.sh/schema/v1.json";
|
|
@@ -112,6 +106,10 @@ declare const configSchema: {
|
|
|
112
106
|
readonly type: "string";
|
|
113
107
|
readonly description: "Backend framework (e.g. \"express@5\", \"fastify\").";
|
|
114
108
|
};
|
|
109
|
+
readonly orm: {
|
|
110
|
+
readonly type: "string";
|
|
111
|
+
readonly description: "ORM or database client (e.g. \"prisma\", \"drizzle\", \"typeorm\").";
|
|
112
|
+
};
|
|
115
113
|
readonly packageManager: {
|
|
116
114
|
readonly type: "string";
|
|
117
115
|
readonly description: "Package manager (e.g. \"pnpm\", \"npm\", \"yarn\").";
|
|
@@ -310,6 +308,9 @@ declare const configSchema: {
|
|
|
310
308
|
readonly backend: {
|
|
311
309
|
readonly type: "string";
|
|
312
310
|
};
|
|
311
|
+
readonly orm: {
|
|
312
|
+
readonly type: "string";
|
|
313
|
+
};
|
|
313
314
|
readonly packageManager: {
|
|
314
315
|
readonly type: "string";
|
|
315
316
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -59,12 +59,6 @@ declare function loadConfigSafe(configPath: string): Promise<ViberailsConfig | n
|
|
|
59
59
|
*/
|
|
60
60
|
declare function mergeConfig(existing: ViberailsConfig, scanResult: ScanResult): ViberailsConfig;
|
|
61
61
|
|
|
62
|
-
/**
|
|
63
|
-
* JSON Schema (draft-07) definition for viberails.config.json.
|
|
64
|
-
*
|
|
65
|
-
* This schema will eventually be hosted at https://viberails.sh/schema/v1.json.
|
|
66
|
-
* For now it is exported as a TypeScript object that can be serialized to JSON.
|
|
67
|
-
*/
|
|
68
62
|
declare const configSchema: {
|
|
69
63
|
readonly $schema: "http://json-schema.org/draft-07/schema#";
|
|
70
64
|
readonly $id: "https://viberails.sh/schema/v1.json";
|
|
@@ -112,6 +106,10 @@ declare const configSchema: {
|
|
|
112
106
|
readonly type: "string";
|
|
113
107
|
readonly description: "Backend framework (e.g. \"express@5\", \"fastify\").";
|
|
114
108
|
};
|
|
109
|
+
readonly orm: {
|
|
110
|
+
readonly type: "string";
|
|
111
|
+
readonly description: "ORM or database client (e.g. \"prisma\", \"drizzle\", \"typeorm\").";
|
|
112
|
+
};
|
|
115
113
|
readonly packageManager: {
|
|
116
114
|
readonly type: "string";
|
|
117
115
|
readonly description: "Package manager (e.g. \"pnpm\", \"npm\", \"yarn\").";
|
|
@@ -310,6 +308,9 @@ declare const configSchema: {
|
|
|
310
308
|
readonly backend: {
|
|
311
309
|
readonly type: "string";
|
|
312
310
|
};
|
|
311
|
+
readonly orm: {
|
|
312
|
+
readonly type: "string";
|
|
313
|
+
};
|
|
313
314
|
readonly packageManager: {
|
|
314
315
|
readonly type: "string";
|
|
315
316
|
};
|
package/dist/index.js
CHANGED
|
@@ -65,6 +65,7 @@ function generatePackageOverrides(scanResult, globalConfig) {
|
|
|
65
65
|
"framework",
|
|
66
66
|
"styling",
|
|
67
67
|
"backend",
|
|
68
|
+
"orm",
|
|
68
69
|
"linter",
|
|
69
70
|
"formatter",
|
|
70
71
|
"testRunner"
|
|
@@ -107,6 +108,7 @@ function mapStack(scanResult) {
|
|
|
107
108
|
if (stack.framework) config.framework = formatStackItem(stack.framework);
|
|
108
109
|
if (stack.styling) config.styling = formatStackItem(stack.styling);
|
|
109
110
|
if (stack.backend) config.backend = formatStackItem(stack.backend);
|
|
111
|
+
if (stack.orm) config.orm = formatStackItem(stack.orm);
|
|
110
112
|
if (stack.linter) config.linter = formatStackItem(stack.linter);
|
|
111
113
|
if (stack.formatter) config.formatter = formatStackItem(stack.formatter);
|
|
112
114
|
if (stack.testRunner) config.testRunner = formatStackItem(stack.testRunner);
|
|
@@ -278,6 +280,7 @@ function mergeStack(existing, fresh) {
|
|
|
278
280
|
framework: existing.framework ?? fresh.framework,
|
|
279
281
|
styling: existing.styling ?? fresh.styling,
|
|
280
282
|
backend: existing.backend ?? fresh.backend,
|
|
283
|
+
orm: existing.orm ?? fresh.orm,
|
|
281
284
|
linter: existing.linter ?? fresh.linter,
|
|
282
285
|
formatter: existing.formatter ?? fresh.formatter,
|
|
283
286
|
testRunner: existing.testRunner ?? fresh.testRunner
|
|
@@ -355,6 +358,101 @@ function mergePackageOverrides(existing, fresh) {
|
|
|
355
358
|
return merged.length > 0 ? merged : void 0;
|
|
356
359
|
}
|
|
357
360
|
|
|
361
|
+
// src/schema-parts.ts
|
|
362
|
+
var conventionValueDef = {
|
|
363
|
+
description: "A convention value \u2014 either a plain string (user-confirmed) or an object with scanner metadata.",
|
|
364
|
+
oneOf: [
|
|
365
|
+
{ type: "string" },
|
|
366
|
+
{
|
|
367
|
+
type: "object",
|
|
368
|
+
required: ["value", "_confidence", "_consistency"],
|
|
369
|
+
properties: {
|
|
370
|
+
value: {
|
|
371
|
+
type: "string",
|
|
372
|
+
description: "The convention value."
|
|
373
|
+
},
|
|
374
|
+
_confidence: {
|
|
375
|
+
type: "string",
|
|
376
|
+
enum: ["high", "medium", "low"],
|
|
377
|
+
description: "Scanner confidence level."
|
|
378
|
+
},
|
|
379
|
+
_consistency: {
|
|
380
|
+
type: "number",
|
|
381
|
+
minimum: 0,
|
|
382
|
+
maximum: 100,
|
|
383
|
+
description: "Scanner consistency percentage."
|
|
384
|
+
},
|
|
385
|
+
_detected: {
|
|
386
|
+
type: "boolean",
|
|
387
|
+
description: "Set by mergeConfig when a convention is newly detected during sync."
|
|
388
|
+
}
|
|
389
|
+
},
|
|
390
|
+
additionalProperties: false
|
|
391
|
+
}
|
|
392
|
+
]
|
|
393
|
+
};
|
|
394
|
+
var boundaryItemSchema = {
|
|
395
|
+
type: "object",
|
|
396
|
+
required: ["from", "to", "allow"],
|
|
397
|
+
properties: {
|
|
398
|
+
from: {
|
|
399
|
+
type: "string",
|
|
400
|
+
description: "Source package or directory pattern."
|
|
401
|
+
},
|
|
402
|
+
to: {
|
|
403
|
+
type: "string",
|
|
404
|
+
description: "Target package or directory pattern."
|
|
405
|
+
},
|
|
406
|
+
allow: {
|
|
407
|
+
type: "boolean",
|
|
408
|
+
description: "Whether this import direction is allowed or disallowed."
|
|
409
|
+
},
|
|
410
|
+
reason: {
|
|
411
|
+
type: "string",
|
|
412
|
+
description: "Human-readable explanation of why this boundary exists."
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
additionalProperties: false
|
|
416
|
+
};
|
|
417
|
+
var packageItemSchema = {
|
|
418
|
+
type: "object",
|
|
419
|
+
required: ["name", "path"],
|
|
420
|
+
properties: {
|
|
421
|
+
name: { type: "string", description: "Package name from package.json." },
|
|
422
|
+
path: { type: "string", description: "Relative path to the package." },
|
|
423
|
+
stack: {
|
|
424
|
+
type: "object",
|
|
425
|
+
properties: {
|
|
426
|
+
framework: { type: "string" },
|
|
427
|
+
language: { type: "string" },
|
|
428
|
+
styling: { type: "string" },
|
|
429
|
+
backend: { type: "string" },
|
|
430
|
+
orm: { type: "string" },
|
|
431
|
+
packageManager: { type: "string" },
|
|
432
|
+
linter: { type: "string" },
|
|
433
|
+
formatter: { type: "string" },
|
|
434
|
+
testRunner: { type: "string" }
|
|
435
|
+
},
|
|
436
|
+
additionalProperties: false
|
|
437
|
+
},
|
|
438
|
+
conventions: { $ref: "#/properties/conventions" },
|
|
439
|
+
rules: {
|
|
440
|
+
type: "object",
|
|
441
|
+
properties: {
|
|
442
|
+
maxFileLines: { type: "number" },
|
|
443
|
+
maxTestFileLines: { type: "number" },
|
|
444
|
+
maxFunctionLines: { type: "number" },
|
|
445
|
+
requireTests: { type: "boolean" },
|
|
446
|
+
enforceNaming: { type: "boolean" },
|
|
447
|
+
enforceBoundaries: { type: "boolean" }
|
|
448
|
+
},
|
|
449
|
+
additionalProperties: false
|
|
450
|
+
},
|
|
451
|
+
ignore: { type: "array", items: { type: "string" } }
|
|
452
|
+
},
|
|
453
|
+
additionalProperties: false
|
|
454
|
+
};
|
|
455
|
+
|
|
358
456
|
// src/schema.ts
|
|
359
457
|
var configSchema = {
|
|
360
458
|
$schema: "http://json-schema.org/draft-07/schema#",
|
|
@@ -403,6 +501,10 @@ var configSchema = {
|
|
|
403
501
|
type: "string",
|
|
404
502
|
description: 'Backend framework (e.g. "express@5", "fastify").'
|
|
405
503
|
},
|
|
504
|
+
orm: {
|
|
505
|
+
type: "string",
|
|
506
|
+
description: 'ORM or database client (e.g. "prisma", "drizzle", "typeorm").'
|
|
507
|
+
},
|
|
406
508
|
packageManager: {
|
|
407
509
|
type: "string",
|
|
408
510
|
description: 'Package manager (e.g. "pnpm", "npm", "yarn").'
|
|
@@ -524,29 +626,7 @@ var configSchema = {
|
|
|
524
626
|
},
|
|
525
627
|
boundaries: {
|
|
526
628
|
type: "array",
|
|
527
|
-
items:
|
|
528
|
-
type: "object",
|
|
529
|
-
required: ["from", "to", "allow"],
|
|
530
|
-
properties: {
|
|
531
|
-
from: {
|
|
532
|
-
type: "string",
|
|
533
|
-
description: "Source package or directory pattern."
|
|
534
|
-
},
|
|
535
|
-
to: {
|
|
536
|
-
type: "string",
|
|
537
|
-
description: "Target package or directory pattern."
|
|
538
|
-
},
|
|
539
|
-
allow: {
|
|
540
|
-
type: "boolean",
|
|
541
|
-
description: "Whether this import direction is allowed or disallowed."
|
|
542
|
-
},
|
|
543
|
-
reason: {
|
|
544
|
-
type: "string",
|
|
545
|
-
description: "Human-readable explanation of why this boundary exists."
|
|
546
|
-
}
|
|
547
|
-
},
|
|
548
|
-
additionalProperties: false
|
|
549
|
-
},
|
|
629
|
+
items: boundaryItemSchema,
|
|
550
630
|
description: "Module boundary rules for import enforcement."
|
|
551
631
|
},
|
|
552
632
|
workspace: {
|
|
@@ -568,85 +648,18 @@ var configSchema = {
|
|
|
568
648
|
},
|
|
569
649
|
packages: {
|
|
570
650
|
type: "array",
|
|
571
|
-
items:
|
|
572
|
-
type: "object",
|
|
573
|
-
required: ["name", "path"],
|
|
574
|
-
properties: {
|
|
575
|
-
name: { type: "string", description: "Package name from package.json." },
|
|
576
|
-
path: { type: "string", description: "Relative path to the package." },
|
|
577
|
-
stack: {
|
|
578
|
-
type: "object",
|
|
579
|
-
properties: {
|
|
580
|
-
framework: { type: "string" },
|
|
581
|
-
language: { type: "string" },
|
|
582
|
-
styling: { type: "string" },
|
|
583
|
-
backend: { type: "string" },
|
|
584
|
-
packageManager: { type: "string" },
|
|
585
|
-
linter: { type: "string" },
|
|
586
|
-
formatter: { type: "string" },
|
|
587
|
-
testRunner: { type: "string" }
|
|
588
|
-
},
|
|
589
|
-
additionalProperties: false
|
|
590
|
-
},
|
|
591
|
-
conventions: { $ref: "#/properties/conventions" },
|
|
592
|
-
rules: {
|
|
593
|
-
type: "object",
|
|
594
|
-
properties: {
|
|
595
|
-
maxFileLines: { type: "number" },
|
|
596
|
-
maxTestFileLines: { type: "number" },
|
|
597
|
-
maxFunctionLines: { type: "number" },
|
|
598
|
-
requireTests: { type: "boolean" },
|
|
599
|
-
enforceNaming: { type: "boolean" },
|
|
600
|
-
enforceBoundaries: { type: "boolean" }
|
|
601
|
-
},
|
|
602
|
-
additionalProperties: false
|
|
603
|
-
},
|
|
604
|
-
ignore: { type: "array", items: { type: "string" } }
|
|
605
|
-
},
|
|
606
|
-
additionalProperties: false
|
|
607
|
-
},
|
|
651
|
+
items: packageItemSchema,
|
|
608
652
|
description: "Per-package overrides for monorepo projects."
|
|
609
653
|
}
|
|
610
654
|
},
|
|
611
655
|
additionalProperties: false,
|
|
612
656
|
definitions: {
|
|
613
|
-
conventionValue:
|
|
614
|
-
description: "A convention value \u2014 either a plain string (user-confirmed) or an object with scanner metadata.",
|
|
615
|
-
oneOf: [
|
|
616
|
-
{ type: "string" },
|
|
617
|
-
{
|
|
618
|
-
type: "object",
|
|
619
|
-
required: ["value", "_confidence", "_consistency"],
|
|
620
|
-
properties: {
|
|
621
|
-
value: {
|
|
622
|
-
type: "string",
|
|
623
|
-
description: "The convention value."
|
|
624
|
-
},
|
|
625
|
-
_confidence: {
|
|
626
|
-
type: "string",
|
|
627
|
-
enum: ["high", "medium", "low"],
|
|
628
|
-
description: "Scanner confidence level."
|
|
629
|
-
},
|
|
630
|
-
_consistency: {
|
|
631
|
-
type: "number",
|
|
632
|
-
minimum: 0,
|
|
633
|
-
maximum: 100,
|
|
634
|
-
description: "Scanner consistency percentage."
|
|
635
|
-
},
|
|
636
|
-
_detected: {
|
|
637
|
-
type: "boolean",
|
|
638
|
-
description: "Set by mergeConfig when a convention is newly detected during sync."
|
|
639
|
-
}
|
|
640
|
-
},
|
|
641
|
-
additionalProperties: false
|
|
642
|
-
}
|
|
643
|
-
]
|
|
644
|
-
}
|
|
657
|
+
conventionValue: conventionValueDef
|
|
645
658
|
}
|
|
646
659
|
};
|
|
647
660
|
|
|
648
661
|
// src/index.ts
|
|
649
|
-
var VERSION = "0.
|
|
662
|
+
var VERSION = "0.3.1";
|
|
650
663
|
export {
|
|
651
664
|
DEFAULT_IGNORE,
|
|
652
665
|
DEFAULT_RULES,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/defaults.ts","../src/generate-config.ts","../src/generate-overrides.ts","../src/load-config.ts","../src/merge-config.ts","../src/schema.ts","../src/index.ts"],"sourcesContent":["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 maxFunctionLines: 50,\n requireTests: true,\n enforceNaming: true,\n enforceBoundaries: false,\n};\n\n/**\n * Default glob patterns for files and directories to ignore.\n */\nexport const DEFAULT_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 * as path from 'node:path';\nimport type {\n ConfigConventions,\n ConfigStack,\n ConfigStructure,\n ConventionValue,\n DetectedConvention,\n DirectoryRole,\n ScanResult,\n StackItem,\n ViberailsConfig,\n} from '@viberails/types';\nimport { DEFAULT_IGNORE, DEFAULT_RULES } from './defaults.js';\nimport { generatePackageOverrides } from './generate-overrides.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 */\nfunction 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.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 */\nfunction 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/**\n * Convert a DetectedConvention to a ConventionValue with metadata.\n * Returns undefined for low-confidence conventions (they are omitted).\n */\nexport function mapConvention(convention: DetectedConvention): ConventionValue | undefined {\n if (convention.confidence === 'low') {\n return undefined;\n }\n\n return {\n value: convention.value,\n _confidence: convention.confidence,\n _consistency: convention.consistency,\n };\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, omitting low-confidence entries.\n */\nfunction mapConventions(scanResult: ScanResult): ConfigConventions {\n const config: ConfigConventions = {};\n\n for (const key of CONVENTION_KEYS) {\n const detected = scanResult.conventions[key];\n if (detected) {\n const value = mapConvention(detected);\n if (value !== undefined) {\n config[key] = value;\n }\n }\n }\n\n return config;\n}\n\n/**\n * Generate a ViberailsConfig from scan results.\n *\n * Maps the scanner's DetectedStack, DetectedStructure, and conventions\n * into the config format with smart defaults. Low-confidence conventions\n * are omitted. The project name is derived from the root directory basename.\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 config: ViberailsConfig = {\n $schema: 'https://viberails.sh/schema/v1.json',\n version: 1,\n name: path.basename(scanResult.root),\n enforcement: 'warn',\n stack: mapStack(scanResult),\n structure: mapStructure(scanResult),\n conventions: mapConventions(scanResult),\n rules: { ...DEFAULT_RULES },\n ignore: [...DEFAULT_IGNORE],\n };\n\n if (scanResult.workspace) {\n config.workspace = {\n packages: scanResult.workspace.packages.map((p) => p.relativePath),\n isMonorepo: true,\n };\n config.boundaries = [];\n }\n\n const packageOverrides = generatePackageOverrides(scanResult, config);\n if (packageOverrides) {\n config.packages = packageOverrides;\n }\n\n return config;\n}\n","import type {\n ConfigConventions,\n ConfigStack,\n DetectedConvention,\n PackageConfigOverrides,\n ScanResult,\n ViberailsConfig,\n} from '@viberails/types';\nimport { CONVENTION_KEYS, formatStackItem, mapConvention } from './generate-config.js';\n\n/**\n * Compare a package's conventions against the global config conventions.\n * Returns only the differing conventions, or undefined if all match.\n */\nexport function conventionsDiffer(\n pkgConventions: Record<string, DetectedConvention>,\n globalConventions: ConfigConventions,\n): Partial<ConfigConventions> | undefined {\n const overrides: Partial<ConfigConventions> = {};\n let hasDiff = false;\n\n for (const key of CONVENTION_KEYS) {\n const detected = pkgConventions[key];\n if (!detected) continue;\n\n const mapped = mapConvention(detected);\n if (mapped === undefined) continue;\n\n const globalValue = globalConventions[key];\n const globalStr = typeof globalValue === 'string' ? globalValue : globalValue?.value;\n if (detected.value !== globalStr) {\n overrides[key] = mapped;\n hasDiff = true;\n }\n }\n\n return hasDiff ? overrides : undefined;\n}\n\n/**\n * Generate per-package config overrides for packages whose stack or\n * conventions differ from the aggregate global config.\n */\nexport function generatePackageOverrides(\n scanResult: ScanResult,\n globalConfig: ViberailsConfig,\n): PackageConfigOverrides[] | undefined {\n if (!scanResult.packages || scanResult.packages.length <= 1) return undefined;\n\n const overrides: PackageConfigOverrides[] = [];\n\n for (const pkg of scanResult.packages) {\n const override: PackageConfigOverrides = {\n name: pkg.name,\n path: pkg.relativePath,\n };\n let hasDiff = false;\n\n // Compare stack fields — only include overrides when the package has a\n // value that differs from the global, not when the package simply lacks the field\n const stackOverride: Partial<ConfigStack> = {};\n let hasStackDiff = false;\n\n const optionalStackFields = [\n 'framework',\n 'styling',\n 'backend',\n 'linter',\n 'formatter',\n 'testRunner',\n ] as const;\n for (const field of optionalStackFields) {\n const pkgItem = pkg.stack[field];\n if (!pkgItem) continue;\n const pkgValue = formatStackItem(pkgItem);\n if (pkgValue !== globalConfig.stack[field]) {\n stackOverride[field] = pkgValue;\n hasStackDiff = true;\n }\n }\n\n if (hasStackDiff) {\n override.stack = stackOverride;\n hasDiff = true;\n }\n\n // Compare conventions\n const conventionOverrides = conventionsDiffer(pkg.conventions, globalConfig.conventions);\n if (conventionOverrides) {\n override.conventions = conventionOverrides;\n hasDiff = true;\n }\n\n if (hasDiff) {\n overrides.push(override);\n }\n }\n\n return overrides.length > 0 ? overrides : undefined;\n}\n","import * as fs from 'node:fs/promises';\nimport type { ViberailsConfig } from '@viberails/types';\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', 'stack', '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') errors.push('\"version\" must be a number');\n if (typeof parsed.name !== 'string') errors.push('\"name\" must be a string');\n if (\n parsed.enforcement !== undefined &&\n parsed.enforcement !== 'warn' &&\n parsed.enforcement !== 'enforce'\n ) {\n errors.push('\"enforcement\" must be \"warn\" or \"enforce\"');\n }\n\n // Stack validation\n if (typeof parsed.stack !== 'object' || parsed.stack === null) {\n errors.push('\"stack\" must be an object');\n } else {\n const stack = parsed.stack as Record<string, unknown>;\n if (typeof stack.language !== 'string') errors.push('\"stack.language\" must be a string');\n if (typeof stack.packageManager !== 'string')\n errors.push('\"stack.packageManager\" must be a string');\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 if (typeof rules.maxFunctionLines !== 'number')\n errors.push('\"rules.maxFunctionLines\" must be a number');\n if (typeof rules.requireTests !== 'boolean')\n errors.push('\"rules.requireTests\" must be a boolean');\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 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, stack, rules), and returns\n * the parsed config.\n *\n * @param configPath - Absolute or relative path to viberails.config.json\n * @returns The parsed ViberailsConfig\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 V1.0\n const rules = parsed.rules as Record<string, unknown>;\n if (rules.maxTestFileLines === undefined) {\n rules.maxTestFileLines = 0;\n }\n\n // Safe to cast: validateConfig has verified all required fields and types\n return parsed as unknown as ViberailsConfig;\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 ConventionValue,\n PackageConfigOverrides,\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 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 * Check if a convention key exists in the existing config\n * (either as a string or as an object with a value).\n */\nfunction hasConvention(conventions: ConfigConventions, key: keyof ConfigConventions): boolean {\n return conventions[key] !== undefined;\n}\n\n/**\n * Mark a ConventionValue as newly detected by adding `_detected: true`.\n * Only applies to object-form values (not plain strings).\n */\nfunction markAsDetected(value: ConventionValue): ConventionValue {\n if (typeof value === 'string') {\n return { value, _confidence: 'high', _consistency: 100, _detected: true };\n }\n return { ...value, _detected: true };\n}\n\n/**\n * Merge conventions: keep all existing values, add new detections with `_detected: true`.\n */\nfunction mergeConventions(\n existing: ConfigConventions,\n fresh: ConfigConventions,\n): ConfigConventions {\n const merged: ConfigConventions = { ...existing };\n\n for (const key of CONVENTION_KEYS) {\n if (!hasConvention(existing, key) && fresh[key] !== undefined) {\n const freshValue = fresh[key];\n if (freshValue !== undefined) {\n merged[key] = markAsDetected(freshValue);\n }\n }\n }\n\n return merged;\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 conventions with a `_detected: true` annotation\n * so the developer can review them. Never removes rules or values\n * the developer has set.\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 merged: ViberailsConfig = {\n $schema: existing.$schema ?? fresh.$schema,\n version: existing.version,\n name: existing.name,\n enforcement: existing.enforcement,\n stack: mergeStack(existing.stack, fresh.stack),\n structure: mergeStructure(existing.structure, fresh.structure),\n conventions: mergeConventions(existing.conventions, fresh.conventions),\n rules: { ...existing.rules },\n ignore: [...existing.ignore],\n };\n\n // Workspace: always take fresh scan (structure can change)\n if (fresh.workspace) {\n merged.workspace = fresh.workspace;\n }\n\n // Boundaries: preserve existing rules (user may have adjusted)\n if (existing.boundaries) {\n merged.boundaries = [...existing.boundaries];\n } else if (fresh.boundaries) {\n merged.boundaries = [...fresh.boundaries];\n }\n\n // Packages: preserve existing overrides, add new ones\n if (existing.packages || fresh.packages) {\n merged.packages = mergePackageOverrides(existing.packages, fresh.packages);\n }\n\n return merged;\n}\n\n/**\n * Merge per-package overrides: keep existing user-edited overrides,\n * add new packages from fresh scan.\n */\nfunction mergePackageOverrides(\n existing?: PackageConfigOverrides[],\n fresh?: PackageConfigOverrides[],\n): PackageConfigOverrides[] | undefined {\n if (!fresh || fresh.length === 0) return existing;\n if (!existing || existing.length === 0) return fresh;\n\n const existingByPath = new Map(existing.map((p) => [p.path, p]));\n const merged: PackageConfigOverrides[] = [...existing];\n\n for (const freshPkg of fresh) {\n if (!existingByPath.has(freshPkg.path)) {\n merged.push(freshPkg);\n }\n }\n\n return merged.length > 0 ? merged : undefined;\n}\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 */\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', 'stack', '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 for V1.0.',\n },\n name: {\n type: 'string',\n description: 'Project name, typically from package.json.',\n },\n enforcement: {\n type: 'string',\n enum: ['warn', 'enforce'],\n default: 'warn',\n description: 'Whether conventions are warned about or enforced as errors.',\n },\n stack: {\n type: 'object',\n required: ['language', 'packageManager'],\n properties: {\n framework: {\n type: 'string',\n description: 'Primary framework identifier (e.g. \"nextjs@15\", \"remix@2\").',\n },\n language: {\n type: 'string',\n description: 'Primary language (e.g. \"typescript\", \"javascript\").',\n },\n styling: {\n type: 'string',\n description: 'Styling solution (e.g. \"tailwindcss@4\", \"css-modules\").',\n },\n backend: {\n type: 'string',\n description: 'Backend framework (e.g. \"express@5\", \"fastify\").',\n },\n packageManager: {\n type: 'string',\n description: 'Package manager (e.g. \"pnpm\", \"npm\", \"yarn\").',\n },\n linter: {\n type: 'string',\n description: 'Linter (e.g. \"eslint@9\", \"biome\").',\n },\n formatter: {\n type: 'string',\n description: 'Formatter (e.g. \"prettier\", \"biome\").',\n },\n testRunner: {\n type: 'string',\n description: 'Test runner (e.g. \"vitest\", \"jest\").',\n },\n },\n additionalProperties: false,\n description: 'Detected or configured technology stack.',\n },\n structure: {\n type: 'object',\n properties: {\n srcDir: {\n type: 'string',\n description: 'Source directory (e.g. \"src\"), or omit for flat structure.',\n },\n pages: {\n type: 'string',\n description: 'Pages or routes directory (e.g. \"src/app\").',\n },\n components: {\n type: 'string',\n description: 'Components directory (e.g. \"src/components\").',\n },\n hooks: {\n type: 'string',\n description: 'Hooks directory (e.g. \"src/hooks\").',\n },\n utils: {\n type: 'string',\n description: 'Utilities directory (e.g. \"src/utils\", \"src/lib\").',\n },\n types: {\n type: 'string',\n description: 'Type definitions directory (e.g. \"src/types\").',\n },\n tests: {\n type: 'string',\n description: 'Tests directory (e.g. \"tests\", \"__tests__\").',\n },\n testPattern: {\n type: 'string',\n description: 'Test file naming pattern (e.g. \"*.test.ts\", \"*.spec.ts\").',\n },\n },\n additionalProperties: false,\n description: 'Detected or configured directory structure.',\n },\n conventions: {\n type: 'object',\n properties: {\n fileNaming: { $ref: '#/definitions/conventionValue' },\n componentNaming: { $ref: '#/definitions/conventionValue' },\n hookNaming: { $ref: '#/definitions/conventionValue' },\n importAlias: { $ref: '#/definitions/conventionValue' },\n },\n additionalProperties: false,\n description: 'Detected or configured coding conventions.',\n },\n rules: {\n type: 'object',\n required: [\n 'maxFileLines',\n 'maxFunctionLines',\n 'requireTests',\n 'enforceNaming',\n 'enforceBoundaries',\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 from size checks.',\n },\n maxFunctionLines: {\n type: 'number',\n default: 50,\n description: 'Maximum number of lines allowed per function.',\n },\n requireTests: {\n type: 'boolean',\n default: true,\n description: 'Whether to require test files for source modules.',\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 },\n additionalProperties: false,\n description: 'Rule thresholds and toggles for enforcement.',\n },\n ignore: {\n type: 'array',\n items: { type: 'string' },\n description: 'Glob patterns for files and directories to ignore.',\n },\n boundaries: {\n type: 'array',\n items: {\n type: 'object',\n required: ['from', 'to', 'allow'],\n properties: {\n from: {\n type: 'string',\n description: 'Source package or directory pattern.',\n },\n to: {\n type: 'string',\n description: 'Target package or directory pattern.',\n },\n allow: {\n type: 'boolean',\n description: 'Whether this import direction is allowed or disallowed.',\n },\n reason: {\n type: 'string',\n description: 'Human-readable explanation of why this boundary exists.',\n },\n },\n additionalProperties: false,\n },\n description: 'Module boundary rules for import enforcement.',\n },\n workspace: {\n type: 'object',\n required: ['packages', 'isMonorepo'],\n properties: {\n packages: {\n type: 'array',\n items: { type: 'string' },\n description: 'Relative paths to workspace packages.',\n },\n isMonorepo: {\n type: 'boolean',\n description: 'Whether this project is a monorepo with multiple packages.',\n },\n },\n additionalProperties: false,\n description: 'Workspace configuration for monorepo projects.',\n },\n packages: {\n type: 'array',\n items: {\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.' },\n stack: {\n type: 'object',\n properties: {\n framework: { type: 'string' },\n language: { type: 'string' },\n styling: { type: 'string' },\n backend: { type: 'string' },\n packageManager: { type: 'string' },\n linter: { type: 'string' },\n formatter: { type: 'string' },\n testRunner: { type: 'string' },\n },\n additionalProperties: false,\n },\n conventions: { $ref: '#/properties/conventions' },\n rules: {\n type: 'object',\n properties: {\n maxFileLines: { type: 'number' },\n maxTestFileLines: { type: 'number' },\n maxFunctionLines: { type: 'number' },\n requireTests: { type: 'boolean' },\n enforceNaming: { type: 'boolean' },\n enforceBoundaries: { type: 'boolean' },\n },\n additionalProperties: false,\n },\n ignore: { type: 'array', items: { type: 'string' } },\n },\n additionalProperties: false,\n },\n description: 'Per-package overrides for monorepo projects.',\n },\n },\n additionalProperties: false,\n definitions: {\n conventionValue: {\n description:\n 'A convention value — either a plain string (user-confirmed) or an object with scanner metadata.',\n oneOf: [\n { type: 'string' },\n {\n type: 'object',\n required: ['value', '_confidence', '_consistency'],\n properties: {\n value: {\n type: 'string',\n description: 'The convention value.',\n },\n _confidence: {\n type: 'string',\n enum: ['high', 'medium', 'low'],\n description: 'Scanner confidence level.',\n },\n _consistency: {\n type: 'number',\n minimum: 0,\n maximum: 100,\n description: 'Scanner consistency percentage.',\n },\n _detected: {\n type: 'boolean',\n description: 'Set by mergeConfig when a convention is newly detected during sync.',\n },\n },\n additionalProperties: false,\n },\n ],\n },\n },\n} as const;\n","declare const __PACKAGE_VERSION__: string;\nexport const VERSION: string = __PACKAGE_VERSION__;\n\nexport { DEFAULT_IGNORE, DEFAULT_RULES } from './defaults.js';\nexport { generateConfig } from './generate-config.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/defaults.ts","../src/generate-config.ts","../src/generate-overrides.ts","../src/load-config.ts","../src/merge-config.ts","../src/schema-parts.ts","../src/schema.ts","../src/index.ts"],"sourcesContent":["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 maxFunctionLines: 50,\n requireTests: true,\n enforceNaming: true,\n enforceBoundaries: false,\n};\n\n/**\n * Default glob patterns for files and directories to ignore.\n */\nexport const DEFAULT_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 * as path from 'node:path';\nimport type {\n ConfigConventions,\n ConfigStack,\n ConfigStructure,\n ConventionValue,\n DetectedConvention,\n DirectoryRole,\n ScanResult,\n StackItem,\n ViberailsConfig,\n} from '@viberails/types';\nimport { DEFAULT_IGNORE, DEFAULT_RULES } from './defaults.js';\nimport { generatePackageOverrides } from './generate-overrides.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 */\nfunction 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 */\nfunction 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/**\n * Convert a DetectedConvention to a ConventionValue with metadata.\n * Returns undefined for low-confidence conventions (they are omitted).\n */\nexport function mapConvention(convention: DetectedConvention): ConventionValue | undefined {\n if (convention.confidence === 'low') {\n return undefined;\n }\n\n return {\n value: convention.value,\n _confidence: convention.confidence,\n _consistency: convention.consistency,\n };\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, omitting low-confidence entries.\n */\nfunction mapConventions(scanResult: ScanResult): ConfigConventions {\n const config: ConfigConventions = {};\n\n for (const key of CONVENTION_KEYS) {\n const detected = scanResult.conventions[key];\n if (detected) {\n const value = mapConvention(detected);\n if (value !== undefined) {\n config[key] = value;\n }\n }\n }\n\n return config;\n}\n\n/**\n * Generate a ViberailsConfig from scan results.\n *\n * Maps the scanner's DetectedStack, DetectedStructure, and conventions\n * into the config format with smart defaults. Low-confidence conventions\n * are omitted. The project name is derived from the root directory basename.\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 config: ViberailsConfig = {\n $schema: 'https://viberails.sh/schema/v1.json',\n version: 1,\n name: path.basename(scanResult.root),\n enforcement: 'warn',\n stack: mapStack(scanResult),\n structure: mapStructure(scanResult),\n conventions: mapConventions(scanResult),\n rules: { ...DEFAULT_RULES },\n ignore: [...DEFAULT_IGNORE],\n };\n\n if (scanResult.workspace) {\n config.workspace = {\n packages: scanResult.workspace.packages.map((p) => p.relativePath),\n isMonorepo: true,\n };\n config.boundaries = [];\n }\n\n const packageOverrides = generatePackageOverrides(scanResult, config);\n if (packageOverrides) {\n config.packages = packageOverrides;\n }\n\n return config;\n}\n","import type {\n ConfigConventions,\n ConfigStack,\n DetectedConvention,\n PackageConfigOverrides,\n ScanResult,\n ViberailsConfig,\n} from '@viberails/types';\nimport { CONVENTION_KEYS, formatStackItem, mapConvention } from './generate-config.js';\n\n/**\n * Compare a package's conventions against the global config conventions.\n * Returns only the differing conventions, or undefined if all match.\n */\nexport function conventionsDiffer(\n pkgConventions: Record<string, DetectedConvention>,\n globalConventions: ConfigConventions,\n): Partial<ConfigConventions> | undefined {\n const overrides: Partial<ConfigConventions> = {};\n let hasDiff = false;\n\n for (const key of CONVENTION_KEYS) {\n const detected = pkgConventions[key];\n if (!detected) continue;\n\n const mapped = mapConvention(detected);\n if (mapped === undefined) continue;\n\n const globalValue = globalConventions[key];\n const globalStr = typeof globalValue === 'string' ? globalValue : globalValue?.value;\n if (detected.value !== globalStr) {\n overrides[key] = mapped;\n hasDiff = true;\n }\n }\n\n return hasDiff ? overrides : undefined;\n}\n\n/**\n * Generate per-package config overrides for packages whose stack or\n * conventions differ from the aggregate global config.\n */\nexport function generatePackageOverrides(\n scanResult: ScanResult,\n globalConfig: ViberailsConfig,\n): PackageConfigOverrides[] | undefined {\n if (!scanResult.packages || scanResult.packages.length <= 1) return undefined;\n\n const overrides: PackageConfigOverrides[] = [];\n\n for (const pkg of scanResult.packages) {\n const override: PackageConfigOverrides = {\n name: pkg.name,\n path: pkg.relativePath,\n };\n let hasDiff = false;\n\n // Compare stack fields — only include overrides when the package has a\n // value that differs from the global, not when the package simply lacks the field\n const stackOverride: Partial<ConfigStack> = {};\n let hasStackDiff = false;\n\n const optionalStackFields = [\n 'framework',\n 'styling',\n 'backend',\n 'orm',\n 'linter',\n 'formatter',\n 'testRunner',\n ] as const;\n for (const field of optionalStackFields) {\n const pkgItem = pkg.stack[field];\n if (!pkgItem) continue;\n const pkgValue = formatStackItem(pkgItem);\n if (pkgValue !== globalConfig.stack[field]) {\n stackOverride[field] = pkgValue;\n hasStackDiff = true;\n }\n }\n\n if (hasStackDiff) {\n override.stack = stackOverride;\n hasDiff = true;\n }\n\n // Compare conventions\n const conventionOverrides = conventionsDiffer(pkg.conventions, globalConfig.conventions);\n if (conventionOverrides) {\n override.conventions = conventionOverrides;\n hasDiff = true;\n }\n\n if (hasDiff) {\n overrides.push(override);\n }\n }\n\n return overrides.length > 0 ? overrides : undefined;\n}\n","import * as fs from 'node:fs/promises';\nimport type { ViberailsConfig } from '@viberails/types';\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', 'stack', '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') errors.push('\"version\" must be a number');\n if (typeof parsed.name !== 'string') errors.push('\"name\" must be a string');\n if (\n parsed.enforcement !== undefined &&\n parsed.enforcement !== 'warn' &&\n parsed.enforcement !== 'enforce'\n ) {\n errors.push('\"enforcement\" must be \"warn\" or \"enforce\"');\n }\n\n // Stack validation\n if (typeof parsed.stack !== 'object' || parsed.stack === null) {\n errors.push('\"stack\" must be an object');\n } else {\n const stack = parsed.stack as Record<string, unknown>;\n if (typeof stack.language !== 'string') errors.push('\"stack.language\" must be a string');\n if (typeof stack.packageManager !== 'string')\n errors.push('\"stack.packageManager\" must be a string');\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 if (typeof rules.maxFunctionLines !== 'number')\n errors.push('\"rules.maxFunctionLines\" must be a number');\n if (typeof rules.requireTests !== 'boolean')\n errors.push('\"rules.requireTests\" must be a boolean');\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 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, stack, rules), and returns\n * the parsed config.\n *\n * @param configPath - Absolute or relative path to viberails.config.json\n * @returns The parsed ViberailsConfig\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 V1.0\n const rules = parsed.rules as Record<string, unknown>;\n if (rules.maxTestFileLines === undefined) {\n rules.maxTestFileLines = 0;\n }\n\n // Safe to cast: validateConfig has verified all required fields and types\n return parsed as unknown as ViberailsConfig;\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 ConventionValue,\n PackageConfigOverrides,\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 * Check if a convention key exists in the existing config\n * (either as a string or as an object with a value).\n */\nfunction hasConvention(conventions: ConfigConventions, key: keyof ConfigConventions): boolean {\n return conventions[key] !== undefined;\n}\n\n/**\n * Mark a ConventionValue as newly detected by adding `_detected: true`.\n * Only applies to object-form values (not plain strings).\n */\nfunction markAsDetected(value: ConventionValue): ConventionValue {\n if (typeof value === 'string') {\n return { value, _confidence: 'high', _consistency: 100, _detected: true };\n }\n return { ...value, _detected: true };\n}\n\n/**\n * Merge conventions: keep all existing values, add new detections with `_detected: true`.\n */\nfunction mergeConventions(\n existing: ConfigConventions,\n fresh: ConfigConventions,\n): ConfigConventions {\n const merged: ConfigConventions = { ...existing };\n\n for (const key of CONVENTION_KEYS) {\n if (!hasConvention(existing, key) && fresh[key] !== undefined) {\n const freshValue = fresh[key];\n if (freshValue !== undefined) {\n merged[key] = markAsDetected(freshValue);\n }\n }\n }\n\n return merged;\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 conventions with a `_detected: true` annotation\n * so the developer can review them. Never removes rules or values\n * the developer has set.\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 merged: ViberailsConfig = {\n $schema: existing.$schema ?? fresh.$schema,\n version: existing.version,\n name: existing.name,\n enforcement: existing.enforcement,\n stack: mergeStack(existing.stack, fresh.stack),\n structure: mergeStructure(existing.structure, fresh.structure),\n conventions: mergeConventions(existing.conventions, fresh.conventions),\n rules: { ...existing.rules },\n ignore: [...existing.ignore],\n };\n\n // Workspace: always take fresh scan (structure can change)\n if (fresh.workspace) {\n merged.workspace = fresh.workspace;\n }\n\n // Boundaries: preserve existing rules (user may have adjusted)\n if (existing.boundaries) {\n merged.boundaries = [...existing.boundaries];\n } else if (fresh.boundaries) {\n merged.boundaries = [...fresh.boundaries];\n }\n\n // Packages: preserve existing overrides, add new ones\n if (existing.packages || fresh.packages) {\n merged.packages = mergePackageOverrides(existing.packages, fresh.packages);\n }\n\n return merged;\n}\n\n/**\n * Merge per-package overrides: keep existing user-edited overrides,\n * add new packages from fresh scan.\n */\nfunction mergePackageOverrides(\n existing?: PackageConfigOverrides[],\n fresh?: PackageConfigOverrides[],\n): PackageConfigOverrides[] | undefined {\n if (!fresh || fresh.length === 0) return existing;\n if (!existing || existing.length === 0) return fresh;\n\n const existingByPath = new Map(existing.map((p) => [p.path, p]));\n const merged: PackageConfigOverrides[] = [...existing];\n\n for (const freshPkg of fresh) {\n if (!existingByPath.has(freshPkg.path)) {\n merged.push(freshPkg);\n }\n }\n\n return merged.length > 0 ? merged : undefined;\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 conventionValueDef = {\n description:\n 'A convention value — either a plain string (user-confirmed) or an object with scanner metadata.',\n oneOf: [\n { type: 'string' },\n {\n type: 'object',\n required: ['value', '_confidence', '_consistency'],\n properties: {\n value: {\n type: 'string',\n description: 'The convention value.',\n },\n _confidence: {\n type: 'string',\n enum: ['high', 'medium', 'low'],\n description: 'Scanner confidence level.',\n },\n _consistency: {\n type: 'number',\n minimum: 0,\n maximum: 100,\n description: 'Scanner consistency percentage.',\n },\n _detected: {\n type: 'boolean',\n description: 'Set by mergeConfig when a convention is newly detected during sync.',\n },\n },\n additionalProperties: false,\n },\n ],\n} as const;\n\nexport const boundaryItemSchema = {\n type: 'object',\n required: ['from', 'to', 'allow'],\n properties: {\n from: {\n type: 'string',\n description: 'Source package or directory pattern.',\n },\n to: {\n type: 'string',\n description: 'Target package or directory pattern.',\n },\n allow: {\n type: 'boolean',\n description: 'Whether this import direction is allowed or disallowed.',\n },\n reason: {\n type: 'string',\n description: 'Human-readable explanation of why this boundary exists.',\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.' },\n stack: {\n type: 'object',\n properties: {\n framework: { type: 'string' },\n language: { type: 'string' },\n styling: { type: 'string' },\n backend: { type: 'string' },\n orm: { type: 'string' },\n packageManager: { type: 'string' },\n linter: { type: 'string' },\n formatter: { type: 'string' },\n testRunner: { type: 'string' },\n },\n additionalProperties: false,\n },\n conventions: { $ref: '#/properties/conventions' },\n rules: {\n type: 'object',\n properties: {\n maxFileLines: { type: 'number' },\n maxTestFileLines: { type: 'number' },\n maxFunctionLines: { type: 'number' },\n requireTests: { type: 'boolean' },\n enforceNaming: { type: 'boolean' },\n enforceBoundaries: { type: 'boolean' },\n },\n additionalProperties: false,\n },\n ignore: { type: 'array', items: { type: 'string' } },\n },\n additionalProperties: false,\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 { boundaryItemSchema, conventionValueDef, 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', 'stack', '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 for V1.0.',\n },\n name: {\n type: 'string',\n description: 'Project name, typically from package.json.',\n },\n enforcement: {\n type: 'string',\n enum: ['warn', 'enforce'],\n default: 'warn',\n description: 'Whether conventions are warned about or enforced as errors.',\n },\n stack: {\n type: 'object',\n required: ['language', 'packageManager'],\n properties: {\n framework: {\n type: 'string',\n description: 'Primary framework identifier (e.g. \"nextjs@15\", \"remix@2\").',\n },\n language: {\n type: 'string',\n description: 'Primary language (e.g. \"typescript\", \"javascript\").',\n },\n styling: {\n type: 'string',\n description: 'Styling solution (e.g. \"tailwindcss@4\", \"css-modules\").',\n },\n backend: {\n type: 'string',\n description: 'Backend framework (e.g. \"express@5\", \"fastify\").',\n },\n orm: {\n type: 'string',\n description: 'ORM or database client (e.g. \"prisma\", \"drizzle\", \"typeorm\").',\n },\n packageManager: {\n type: 'string',\n description: 'Package manager (e.g. \"pnpm\", \"npm\", \"yarn\").',\n },\n linter: {\n type: 'string',\n description: 'Linter (e.g. \"eslint@9\", \"biome\").',\n },\n formatter: {\n type: 'string',\n description: 'Formatter (e.g. \"prettier\", \"biome\").',\n },\n testRunner: {\n type: 'string',\n description: 'Test runner (e.g. \"vitest\", \"jest\").',\n },\n },\n additionalProperties: false,\n description: 'Detected or configured technology stack.',\n },\n structure: {\n type: 'object',\n properties: {\n srcDir: {\n type: 'string',\n description: 'Source directory (e.g. \"src\"), or omit for flat structure.',\n },\n pages: {\n type: 'string',\n description: 'Pages or routes directory (e.g. \"src/app\").',\n },\n components: {\n type: 'string',\n description: 'Components directory (e.g. \"src/components\").',\n },\n hooks: {\n type: 'string',\n description: 'Hooks directory (e.g. \"src/hooks\").',\n },\n utils: {\n type: 'string',\n description: 'Utilities directory (e.g. \"src/utils\", \"src/lib\").',\n },\n types: {\n type: 'string',\n description: 'Type definitions directory (e.g. \"src/types\").',\n },\n tests: {\n type: 'string',\n description: 'Tests directory (e.g. \"tests\", \"__tests__\").',\n },\n testPattern: {\n type: 'string',\n description: 'Test file naming pattern (e.g. \"*.test.ts\", \"*.spec.ts\").',\n },\n },\n additionalProperties: false,\n description: 'Detected or configured directory structure.',\n },\n conventions: {\n type: 'object',\n properties: {\n fileNaming: { $ref: '#/definitions/conventionValue' },\n componentNaming: { $ref: '#/definitions/conventionValue' },\n hookNaming: { $ref: '#/definitions/conventionValue' },\n importAlias: { $ref: '#/definitions/conventionValue' },\n },\n additionalProperties: false,\n description: 'Detected or configured coding conventions.',\n },\n rules: {\n type: 'object',\n required: [\n 'maxFileLines',\n 'maxFunctionLines',\n 'requireTests',\n 'enforceNaming',\n 'enforceBoundaries',\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 from size checks.',\n },\n maxFunctionLines: {\n type: 'number',\n default: 50,\n description: 'Maximum number of lines allowed per function.',\n },\n requireTests: {\n type: 'boolean',\n default: true,\n description: 'Whether to require test files for source modules.',\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 },\n additionalProperties: false,\n description: 'Rule thresholds and toggles for enforcement.',\n },\n ignore: {\n type: 'array',\n items: { type: 'string' },\n description: 'Glob patterns for files and directories to ignore.',\n },\n boundaries: {\n type: 'array',\n items: boundaryItemSchema,\n description: 'Module boundary rules for import enforcement.',\n },\n workspace: {\n type: 'object',\n required: ['packages', 'isMonorepo'],\n properties: {\n packages: {\n type: 'array',\n items: { type: 'string' },\n description: 'Relative paths to workspace packages.',\n },\n isMonorepo: {\n type: 'boolean',\n description: 'Whether this project is a monorepo with multiple packages.',\n },\n },\n additionalProperties: false,\n description: 'Workspace configuration for monorepo projects.',\n },\n packages: {\n type: 'array',\n items: packageItemSchema,\n description: 'Per-package overrides for monorepo projects.',\n },\n },\n additionalProperties: false,\n definitions: {\n conventionValue: conventionValueDef,\n },\n} as const;\n","declare const __PACKAGE_VERSION__: string;\nexport const VERSION: string = __PACKAGE_VERSION__;\n\nexport { DEFAULT_IGNORE, DEFAULT_RULES } from './defaults.js';\nexport { generateConfig } from './generate-config.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.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Config generation and loading for viberails",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"ajv": "^8.18.0",
|
|
29
|
-
"@viberails/types": "0.
|
|
29
|
+
"@viberails/types": "0.3.1"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/node": "^25.3.5"
|