@codluv/versionguard 0.1.0 → 0.1.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/README.md +46 -0
- package/dist/chunks/{index-DPBYoIRi.js → index-C6jrxye7.js} +4 -2
- package/dist/chunks/index-C6jrxye7.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +25 -3
- package/dist/cli.js.map +1 -1
- package/dist/hooks.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +6 -1
- package/dist/chunks/index-DPBYoIRi.js.map +0 -1
package/README.md
CHANGED
|
@@ -274,6 +274,52 @@ npx versionguard bump --apply
|
|
|
274
274
|
npx versionguard tag 1.2.3 -m "Release 1.2.3"
|
|
275
275
|
```
|
|
276
276
|
|
|
277
|
+
## Using with Changesets
|
|
278
|
+
|
|
279
|
+
VersionGuard and [Changesets](https://github.com/changesets/changesets) are complementary tools that handle different parts of the release lifecycle.
|
|
280
|
+
|
|
281
|
+
| Concern | Changesets | VersionGuard |
|
|
282
|
+
| --- | --- | --- |
|
|
283
|
+
| Decide the next version | Yes | No (validates, doesn't choose) |
|
|
284
|
+
| Update `package.json` version | Yes | No (reads it as source of truth) |
|
|
285
|
+
| Validate version format | No | Yes (SemVer/CalVer strictness) |
|
|
286
|
+
| Sync version across files | No | Yes (regex-based sync) |
|
|
287
|
+
| Validate changelog structure | No | Yes (Keep a Changelog) |
|
|
288
|
+
| Git hooks enforcement | No | Yes |
|
|
289
|
+
| Publish to npm | Yes | No |
|
|
290
|
+
|
|
291
|
+
**Changesets decides what version comes next. VersionGuard validates that the result is correct.**
|
|
292
|
+
|
|
293
|
+
### Recommended workflow
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
# 1. Add a changeset when making changes
|
|
297
|
+
npx changeset
|
|
298
|
+
|
|
299
|
+
# 2. When ready to release, version the packages
|
|
300
|
+
npx changeset version
|
|
301
|
+
|
|
302
|
+
# 3. VersionGuard validates the new state
|
|
303
|
+
npx versionguard validate
|
|
304
|
+
|
|
305
|
+
# 4. Publish
|
|
306
|
+
npx changeset publish
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### CI integration
|
|
310
|
+
|
|
311
|
+
In GitHub Actions, both tools run in sequence. Changesets creates a "Version Packages" PR when changesets are pending. VersionGuard validates the result before publishing:
|
|
312
|
+
|
|
313
|
+
```yaml
|
|
314
|
+
- run: npm run build
|
|
315
|
+
- run: npx versionguard validate
|
|
316
|
+
- uses: changesets/action@v1
|
|
317
|
+
with:
|
|
318
|
+
publish: npx changeset publish --access public
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
VersionGuard does not replace Changesets and does not conflict with it. Use Changesets for release automation. Use VersionGuard for release correctness.
|
|
322
|
+
|
|
277
323
|
## Development
|
|
278
324
|
|
|
279
325
|
This repository uses a modern ESM toolchain:
|
|
@@ -343,7 +343,9 @@ function areHooksInstalled(cwd = process.cwd()) {
|
|
|
343
343
|
function generateHookScript(hookName) {
|
|
344
344
|
return `#!/bin/sh
|
|
345
345
|
# VersionGuard ${hookName} hook
|
|
346
|
-
|
|
346
|
+
# --no-install prevents accidentally downloading an unscoped package
|
|
347
|
+
# if @codluv/versionguard is not installed locally
|
|
348
|
+
npx --no-install versionguard validate --hook=${hookName}
|
|
347
349
|
status=$?
|
|
348
350
|
if [ $status -ne 0 ]; then
|
|
349
351
|
echo "VersionGuard validation failed."
|
|
@@ -1565,4 +1567,4 @@ export {
|
|
|
1565
1567
|
getTagFeedback as y,
|
|
1566
1568
|
semver as z
|
|
1567
1569
|
};
|
|
1568
|
-
//# sourceMappingURL=index-
|
|
1570
|
+
//# sourceMappingURL=index-C6jrxye7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-C6jrxye7.js","sources":["../../src/calver.ts","../../src/changelog.ts","../../src/hooks.ts","../../src/project.ts","../../src/semver.ts","../../src/sync.ts","../../src/config.ts","../../src/feedback/index.ts","../../src/fix/index.ts","../../src/tag/index.ts","../../src/index.ts"],"sourcesContent":["/**\n * Calendar version parsing, formatting, and comparison helpers.\n *\n * @packageDocumentation\n */\n\nimport type { CalVer, CalVerFormat, ValidationError, ValidationResult } from './types';\n\n/**\n * Parsed token layout for a supported CalVer format string.\n *\n * @public\n * @since 0.1.0\n * @forgeIgnore E020\n */\nexport interface ParsedCalVerFormat {\n /**\n * Year token captured from the format string.\n */\n year: 'YYYY' | 'YY';\n\n /**\n * Month token captured from the format string.\n */\n month: 'MM' | 'M' | '0M';\n\n /**\n * Day token captured from the format string when present.\n *\n * @defaultValue undefined\n */\n day?: 'DD' | 'D' | '0D';\n\n /**\n * Patch token captured from the format string when present.\n *\n * @defaultValue undefined\n */\n patch?: 'PATCH';\n}\n\n/**\n * Breaks a CalVer format string into its component tokens.\n *\n * @remarks\n * This helper is used internally by parsing, formatting, and version generation helpers\n * to decide which date parts or patch counters are present in a given CalVer layout.\n *\n * @param calverFormat - Format string to inspect.\n * @returns The parsed token definition for the requested format.\n *\n * @example\n * ```ts\n * import { parseFormat } from 'versionguard';\n *\n * parseFormat('YYYY.MM.PATCH');\n * // => { year: 'YYYY', month: 'MM', patch: 'PATCH' }\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function parseFormat(calverFormat: CalVerFormat): ParsedCalVerFormat {\n const parts = calverFormat.split('.');\n const result: ParsedCalVerFormat = {\n year: parts[0] as ParsedCalVerFormat['year'],\n month: parts[1] as ParsedCalVerFormat['month'],\n };\n\n if (parts[2] === 'PATCH') {\n result.patch = 'PATCH';\n } else if (parts[2]) {\n result.day = parts[2] as ParsedCalVerFormat['day'];\n }\n\n if (parts[3] === 'PATCH') {\n result.patch = 'PATCH';\n }\n\n return result;\n}\n\nfunction tokenPattern(token: string): string {\n switch (token) {\n case 'YYYY':\n return '(\\\\d{4})';\n case 'YY':\n return '(\\\\d{2})';\n case '0M':\n case '0D':\n return '(\\\\d{2})';\n case 'MM':\n case 'DD':\n case 'M':\n case 'D':\n return '(\\\\d{1,2})';\n case 'PATCH':\n return '(\\\\d+)';\n default:\n throw new Error(`Unsupported CalVer token: ${token}`);\n }\n}\n\n/**\n * Builds a regular expression that matches a supported CalVer format.\n *\n * @remarks\n * The returned regular expression is anchored to the start and end of the string so it can\n * be used directly for strict validation of a complete version value.\n *\n * @param calverFormat - Format string to convert into a regular expression.\n * @returns A strict regular expression for the supplied CalVer format.\n *\n * @example\n * ```ts\n * import { getRegexForFormat } from 'versionguard';\n *\n * getRegexForFormat('YYYY.0M.0D').test('2026.03.21');\n * // => true\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function getRegexForFormat(calverFormat: CalVerFormat): RegExp {\n const tokens = calverFormat.split('.');\n const pattern = tokens.map(tokenPattern).join('\\\\.');\n return new RegExp(`^${pattern}$`);\n}\n\n/**\n * Parses a CalVer string using the supplied format.\n *\n * @remarks\n * The parser returns `null` when the string does not structurally match the requested format.\n * It does not enforce range rules such as future-date rejection; use {@link validate} for that.\n *\n * @param version - Version string to parse.\n * @param calverFormat - Format expected for the version string.\n * @returns Parsed CalVer components, or `null` when the string does not match the format.\n *\n * @example\n * ```ts\n * import { parse } from 'versionguard';\n *\n * parse('2026.03.21', 'YYYY.0M.0D')?.month;\n * // => 3\n * ```\n *\n * @see {@link validate} to apply date-range and future-date validation.\n * @public\n * @since 0.1.0\n */\nexport function parse(version: string, calverFormat: CalVerFormat): CalVer | null {\n const match = version.match(getRegexForFormat(calverFormat));\n\n if (!match) {\n return null;\n }\n\n const definition = parseFormat(calverFormat);\n const year =\n definition.year === 'YYYY'\n ? Number.parseInt(match[1], 10)\n : 2000 + Number.parseInt(match[1], 10);\n const month = Number.parseInt(match[2], 10);\n\n let cursor = 3;\n let day: number | undefined;\n let patch: number | undefined;\n\n if (definition.day) {\n day = Number.parseInt(match[cursor], 10);\n cursor += 1;\n }\n\n if (definition.patch) {\n patch = Number.parseInt(match[cursor], 10);\n }\n\n return {\n year,\n month,\n day,\n patch,\n format: calverFormat,\n raw: version,\n };\n}\n\n/**\n * Validates a CalVer string against formatting and date rules.\n *\n * @remarks\n * Validation checks the requested CalVer format, month and day ranges, and optionally rejects\n * future dates relative to the current system date.\n *\n * @param version - Version string to validate.\n * @param calverFormat - Format expected for the version string.\n * @param preventFutureDates - Whether future dates should be reported as errors.\n * @returns A validation result containing any discovered errors and the parsed version on success.\n *\n * @example\n * ```ts\n * import { validate } from 'versionguard';\n *\n * validate('2026.03.21', 'YYYY.0M.0D', false).valid;\n * // => true\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function validate(\n version: string,\n calverFormat: CalVerFormat,\n preventFutureDates: boolean = true,\n): ValidationResult {\n const errors: ValidationError[] = [];\n const parsed = parse(version, calverFormat);\n\n if (!parsed) {\n return {\n valid: false,\n errors: [\n {\n message: `Invalid CalVer format: \"${version}\". Expected format: ${calverFormat}`,\n severity: 'error',\n },\n ],\n };\n }\n\n if (parsed.month < 1 || parsed.month > 12) {\n errors.push({\n message: `Invalid month: ${parsed.month}. Must be between 1 and 12.`,\n severity: 'error',\n });\n }\n\n if (parsed.day !== undefined) {\n if (parsed.day < 1 || parsed.day > 31) {\n errors.push({\n message: `Invalid day: ${parsed.day}. Must be between 1 and 31.`,\n severity: 'error',\n });\n } else {\n const daysInMonth = new Date(parsed.year, parsed.month, 0).getDate();\n if (parsed.day > daysInMonth) {\n errors.push({\n message: `Invalid day: ${parsed.day}. ${parsed.year}-${String(parsed.month).padStart(2, '0')} has only ${daysInMonth} days.`,\n severity: 'error',\n });\n }\n }\n }\n\n if (preventFutureDates) {\n const now = new Date();\n const currentYear = now.getFullYear();\n const currentMonth = now.getMonth() + 1;\n const currentDay = now.getDate();\n\n if (parsed.year > currentYear) {\n errors.push({\n message: `Future year not allowed: ${parsed.year}. Current year is ${currentYear}.`,\n severity: 'error',\n });\n } else if (parsed.year === currentYear && parsed.month > currentMonth) {\n errors.push({\n message: `Future month not allowed: ${parsed.year}.${parsed.month}. Current month is ${currentMonth}.`,\n severity: 'error',\n });\n } else if (\n parsed.year === currentYear &&\n parsed.month === currentMonth &&\n parsed.day !== undefined &&\n parsed.day > currentDay\n ) {\n errors.push({\n message: `Future day not allowed: ${parsed.year}.${parsed.month}.${parsed.day}. Current day is ${currentDay}.`,\n severity: 'error',\n });\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n version: { type: 'calver', version: parsed },\n };\n}\n\nfunction formatToken(token: string, value: number): string {\n if (token === '0M' || token === '0D') {\n return String(value).padStart(2, '0');\n }\n\n if (token === 'YY') {\n return String(value % 100).padStart(2, '0');\n }\n\n return String(value);\n}\n\n/**\n * Formats a parsed CalVer object back into a version string.\n *\n * @remarks\n * Missing `day` and `patch` values fall back to `1` and `0` respectively when the selected\n * format requires those tokens.\n *\n * @param version - Parsed CalVer value to serialize.\n * @returns The formatted CalVer string.\n *\n * @example\n * ```ts\n * import { format } from 'versionguard';\n *\n * const version = { year: 2026, month: 3, day: 21, format: 'YYYY.0M.0D', raw: '2026.03.21' };\n *\n * format(version);\n * // => '2026.03.21'\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function format(version: CalVer): string {\n const tokens = version.format.split('.');\n const values: number[] = [version.year, version.month];\n\n if (tokens.includes('DD') || tokens.includes('D') || tokens.includes('0D')) {\n values.push(version.day ?? 1);\n }\n\n if (tokens.includes('PATCH')) {\n values.push(version.patch ?? 0);\n }\n\n return tokens.map((token, index) => formatToken(token, values[index])).join('.');\n}\n\n/**\n * Creates the current CalVer string for a format.\n *\n * @remarks\n * This helper derives its values from the provided date and initializes any patch token to `0`.\n * It is useful for generating a same-day baseline before incrementing patch-based formats.\n *\n * @param calverFormat - Format to generate.\n * @param now - Date used as the source for year, month, and day values.\n * @returns The current version string for the requested format.\n *\n * @example\n * ```ts\n * import { getCurrentVersion } from 'versionguard';\n *\n * getCurrentVersion('YYYY.MM.PATCH', new Date('2026-03-21T00:00:00Z'));\n * // => '2026.3.0'\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function getCurrentVersion(calverFormat: CalVerFormat, now: Date = new Date()): string {\n const definition = parseFormat(calverFormat);\n const currentDay = now.getDate();\n const base: CalVer = {\n year: now.getFullYear(),\n month: now.getMonth() + 1,\n day: definition.day ? currentDay : undefined,\n patch: definition.patch ? 0 : undefined,\n format: calverFormat,\n raw: '',\n };\n const day = base.day ?? currentDay;\n const patch = base.patch ?? 0;\n\n return formatToken(definition.year, base.year)\n .concat(`.${formatToken(definition.month, base.month)}`)\n .concat(definition.day ? `.${formatToken(definition.day, day)}` : '')\n .concat(definition.patch ? `.${patch}` : '');\n}\n\n/**\n * Compares two CalVer strings using a shared format.\n *\n * @remarks\n * Comparison is performed component-by-component in year, month, day, then patch order.\n * Missing day and patch values are treated as `0` during comparison.\n *\n * @param a - Left-hand version string.\n * @param b - Right-hand version string.\n * @param calverFormat - Format used to parse both versions.\n * @returns `1` when `a` is greater, `-1` when `b` is greater, or `0` when they are equal.\n *\n * @example\n * ```ts\n * import { compare } from 'versionguard';\n *\n * compare('2026.03.2', '2026.03.1', 'YYYY.MM.PATCH');\n * // => 1\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function compare(a: string, b: string, calverFormat: CalVerFormat): number {\n const left = parse(a, calverFormat);\n const right = parse(b, calverFormat);\n\n if (!left || !right) {\n throw new Error(`Invalid CalVer comparison between \"${a}\" and \"${b}\"`);\n }\n\n for (const key of ['year', 'month', 'day', 'patch'] as const) {\n const leftValue = left[key] ?? 0;\n const rightValue = right[key] ?? 0;\n if (leftValue !== rightValue) {\n return leftValue > rightValue ? 1 : -1;\n }\n }\n\n return 0;\n}\n\n/**\n * Increments a CalVer string.\n *\n * @remarks\n * Patch-based formats increment the existing patch number. Formats without a patch token are\n * promoted to a patch-based output by appending `.PATCH` semantics with an initial value of `0`.\n *\n * @param version - Current version string.\n * @param calverFormat - Format used to parse the current version.\n * @returns The next version string.\n *\n * @example\n * ```ts\n * import { increment } from 'versionguard';\n *\n * increment('2026.03.1', 'YYYY.MM.PATCH');\n * // => '2026.3.2'\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function increment(version: string, calverFormat: CalVerFormat): string {\n const parsed = parse(version, calverFormat);\n\n if (!parsed) {\n throw new Error(`Invalid CalVer version: ${version}`);\n }\n\n const definition = parseFormat(calverFormat);\n const next: CalVer = {\n ...parsed,\n raw: version,\n };\n\n if (definition.patch) {\n const patch = parsed.patch ?? 0;\n next.patch = patch + 1;\n } else {\n next.patch = 0;\n next.format = `${calverFormat}.PATCH` as CalVerFormat;\n }\n\n return format(next);\n}\n\n/**\n * Returns the most likely next CalVer candidates.\n *\n * @remarks\n * The first candidate is the version derived from the current date. The second candidate is the\n * incremented form of the supplied current version.\n *\n * @param currentVersion - Existing project version.\n * @param calverFormat - Format used to generate both candidates.\n * @returns Two candidate version strings ordered as current-date then incremented version.\n *\n * @example\n * ```ts\n * import { getNextVersions } from 'versionguard';\n *\n * getNextVersions('2026.03.1', 'YYYY.MM.PATCH').length;\n * // => 2\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function getNextVersions(currentVersion: string, calverFormat: CalVerFormat): string[] {\n return [getCurrentVersion(calverFormat), increment(currentVersion, calverFormat)];\n}\n","import * as fs from 'node:fs';\n\n/**\n * Describes the outcome of validating a changelog file.\n *\n * @public\n * @since 0.1.0\n * @forgeIgnore E020\n */\nexport interface ChangelogValidationResult {\n /**\n * Indicates whether the changelog satisfies all requested checks.\n */\n valid: boolean;\n /**\n * Human-readable validation errors.\n */\n errors: string[];\n /**\n * Indicates whether the changelog contains an entry for the requested version.\n */\n hasEntryForVersion: boolean;\n}\n\nconst CHANGELOG_DATE_REGEX = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/**\n * Validates a changelog file for release readiness.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * The validator checks for a top-level changelog heading, an `[Unreleased]`\n * section, and optionally a dated entry for the requested version.\n *\n * @param changelogPath - Path to the changelog file.\n * @param version - Version that must be present in the changelog.\n * @param strict - Whether to require compare links and dated release headings.\n * @param requireEntry - Whether the requested version must already have an entry.\n * @returns The result of validating the changelog file.\n * @example\n * ```ts\n * import { validateChangelog } from 'versionguard';\n *\n * const result = validateChangelog('CHANGELOG.md', '1.2.0', true, true);\n * ```\n */\nexport function validateChangelog(\n changelogPath: string,\n version: string,\n strict: boolean = true,\n requireEntry: boolean = true,\n): ChangelogValidationResult {\n if (!fs.existsSync(changelogPath)) {\n return {\n valid: !requireEntry,\n errors: requireEntry ? [`Changelog not found: ${changelogPath}`] : [],\n hasEntryForVersion: false,\n };\n }\n\n const errors: string[] = [];\n const content = fs.readFileSync(changelogPath, 'utf-8');\n\n if (!content.startsWith('# Changelog')) {\n errors.push('Changelog must start with \"# Changelog\"');\n }\n\n if (!content.includes('## [Unreleased]')) {\n errors.push('Changelog must have an [Unreleased] section');\n }\n\n const versionHeader = `## [${version}]`;\n const hasEntryForVersion = content.includes(versionHeader);\n if (requireEntry && !hasEntryForVersion) {\n errors.push(`Changelog must have an entry for version ${version}`);\n }\n\n if (strict) {\n if (!content.includes('[Unreleased]:')) {\n errors.push('Changelog should include compare links at the bottom');\n }\n\n const versionHeaderMatch = content.match(\n new RegExp(`## \\\\[${escapeRegExp(version)}\\\\] - ([^\\r\\n]+)`),\n );\n if (requireEntry && hasEntryForVersion) {\n if (!versionHeaderMatch) {\n errors.push(`Version ${version} entry must use \"## [${version}] - YYYY-MM-DD\" format`);\n } else if (!CHANGELOG_DATE_REGEX.test(versionHeaderMatch[1])) {\n errors.push(`Version ${version} entry date must use YYYY-MM-DD format`);\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n hasEntryForVersion,\n };\n}\n\n/**\n * Gets the most recent released version from a changelog.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * The `[Unreleased]` section is skipped so the first concrete version heading is\n * treated as the latest release.\n *\n * @param changelogPath - Path to the changelog file.\n * @returns The latest released version, or `null` when no release entry exists.\n * @example\n * ```ts\n * import { getLatestVersion } from 'versionguard';\n *\n * const latest = getLatestVersion('CHANGELOG.md');\n * ```\n */\nexport function getLatestVersion(changelogPath: string): string | null {\n if (!fs.existsSync(changelogPath)) {\n return null;\n }\n\n const content = fs.readFileSync(changelogPath, 'utf-8');\n const match = content.match(/^## \\[(?!Unreleased\\])(.*?)\\]/m);\n return match?.[1] ?? null;\n}\n\n/**\n * Inserts a new version entry beneath the `[Unreleased]` section.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * If the changelog already contains the requested version, no changes are made.\n * The inserted entry includes a starter `Added` subsection for follow-up edits.\n *\n * @param changelogPath - Path to the changelog file.\n * @param version - Version to add.\n * @param date - Release date to write in `YYYY-MM-DD` format.\n * @example\n * ```ts\n * import { addVersionEntry } from 'versionguard';\n *\n * addVersionEntry('CHANGELOG.md', '1.2.0', '2026-03-21');\n * ```\n */\nexport function addVersionEntry(\n changelogPath: string,\n version: string,\n date: string = new Date().toISOString().slice(0, 10),\n): void {\n if (!fs.existsSync(changelogPath)) {\n throw new Error(`Changelog not found: ${changelogPath}`);\n }\n\n const content = fs.readFileSync(changelogPath, 'utf-8');\n if (content.includes(`## [${version}]`)) {\n return;\n }\n\n const block = `## [${version}] - ${date}\\n\\n### Added\\n\\n- Describe changes here.\\n\\n`;\n const unreleasedMatch = content.match(/## \\[Unreleased\\]\\r?\\n(?:\\r?\\n)?/);\n if (!unreleasedMatch || unreleasedMatch.index === undefined) {\n throw new Error('Changelog must have an [Unreleased] section');\n }\n\n const insertIndex = unreleasedMatch.index + unreleasedMatch[0].length;\n const updated = `${content.slice(0, insertIndex)}${block}${content.slice(insertIndex)}`;\n fs.writeFileSync(changelogPath, updated, 'utf-8');\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport type { GitConfig } from './types';\n\nconst HOOK_NAMES = ['pre-commit', 'pre-push', 'post-tag'] as const;\n\n/**\n * Installs VersionGuard-managed Git hooks in a repository.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * Only hooks enabled in `config.hooks` are written. Each installed hook runs\n * `versionguard validate` for its corresponding hook name.\n *\n * @param config - Git configuration that selects which hooks to install.\n * @param cwd - Repository directory where hooks should be installed.\n * @example\n * ```ts\n * import { getDefaultConfig, installHooks } from 'versionguard';\n *\n * installHooks(getDefaultConfig().git, process.cwd());\n * ```\n */\nexport function installHooks(config: GitConfig, cwd: string = process.cwd()): void {\n const gitDir = findGitDir(cwd);\n if (!gitDir) {\n throw new Error('Not a git repository. Run `git init` first.');\n }\n\n const hooksDir = path.join(gitDir, 'hooks');\n fs.mkdirSync(hooksDir, { recursive: true });\n\n for (const hookName of HOOK_NAMES) {\n if (config.hooks[hookName]) {\n const hookPath = path.join(hooksDir, hookName);\n fs.writeFileSync(hookPath, generateHookScript(hookName), { encoding: 'utf-8', mode: 0o755 });\n }\n }\n}\n\n/**\n * Removes VersionGuard-managed Git hooks from a repository.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * Only hook files containing `versionguard` are removed so unrelated custom\n * hooks are left untouched.\n *\n * @param cwd - Repository directory whose hooks should be cleaned up.\n * @example\n * ```ts\n * import { uninstallHooks } from 'versionguard';\n *\n * uninstallHooks(process.cwd());\n * ```\n */\nexport function uninstallHooks(cwd: string = process.cwd()): void {\n const gitDir = findGitDir(cwd);\n if (!gitDir) {\n return;\n }\n\n const hooksDir = path.join(gitDir, 'hooks');\n for (const hookName of HOOK_NAMES) {\n const hookPath = path.join(hooksDir, hookName);\n if (fs.existsSync(hookPath) && fs.readFileSync(hookPath, 'utf-8').includes('versionguard')) {\n fs.unlinkSync(hookPath);\n }\n }\n}\n\n/**\n * Finds the nearest `.git` directory by walking up from a starting directory.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This only resolves `.git` directories and returns `null` when the search\n * reaches the filesystem root without finding a repository.\n *\n * @param cwd - Directory to start searching from.\n * @returns The resolved `.git` directory path, or `null` when none is found.\n * @example\n * ```ts\n * import { findGitDir } from 'versionguard';\n *\n * const gitDir = findGitDir(process.cwd());\n * ```\n */\nexport function findGitDir(cwd: string): string | null {\n let current = cwd;\n\n while (true) {\n const gitPath = path.join(current, '.git');\n if (fs.existsSync(gitPath) && fs.statSync(gitPath).isDirectory()) {\n return gitPath;\n }\n\n const parent = path.dirname(current);\n if (parent === current) {\n return null;\n }\n current = parent;\n }\n}\n\n/**\n * Checks whether all VersionGuard-managed hooks are installed.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * A hook counts as installed only when the file exists and contains the\n * `versionguard` invocation written by this package.\n *\n * @param cwd - Repository directory to inspect.\n * @returns `true` when every managed hook is installed.\n * @example\n * ```ts\n * import { areHooksInstalled } from 'versionguard';\n *\n * const installed = areHooksInstalled(process.cwd());\n * ```\n */\nexport function areHooksInstalled(cwd: string = process.cwd()): boolean {\n const gitDir = findGitDir(cwd);\n if (!gitDir) {\n return false;\n }\n\n return HOOK_NAMES.every((hookName) => {\n const hookPath = path.join(gitDir, 'hooks', hookName);\n return fs.existsSync(hookPath) && fs.readFileSync(hookPath, 'utf-8').includes('versionguard');\n });\n}\n\n/**\n * Generates the shell script content for a Git hook.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * The generated script delegates to `npx versionguard validate` and exits with\n * the validation status code.\n *\n * @param hookName - Name of the Git hook to generate.\n * @returns Executable shell script contents for the hook.\n * @example\n * ```ts\n * import { generateHookScript } from 'versionguard';\n *\n * const script = generateHookScript('pre-commit');\n * ```\n */\nexport function generateHookScript(hookName: (typeof HOOK_NAMES)[number]): string {\n return `#!/bin/sh\n# VersionGuard ${hookName} hook\n# --no-install prevents accidentally downloading an unscoped package\n# if @codluv/versionguard is not installed locally\nnpx --no-install versionguard validate --hook=${hookName}\nstatus=$?\nif [ $status -ne 0 ]; then\n echo \"VersionGuard validation failed.\"\n exit $status\nfi\n`;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\n/**\n * JSON-compatible scalar, array, or object value used by package metadata.\n *\n * @public\n * @since 0.1.0\n * @forgeIgnore E020\n */\nexport type PackageJsonValue =\n | boolean\n | null\n | number\n | string\n | PackageJsonArray\n | PackageJsonObject;\n\n/**\n * Recursive array type used for arbitrary JSON-compatible package values.\n *\n * @public\n * @since 0.1.0\n * @forgeIgnore E020\n */\nexport type PackageJsonArray = PackageJsonValue[];\n\n/**\n * Recursive object type used for arbitrary JSON-compatible package values.\n *\n * @public\n * @since 0.1.0\n * @forgeIgnore E020\n */\nexport interface PackageJsonObject {\n [key: string]: PackageJsonValue;\n}\n\n/**\n * Minimal shape of a `package.json` document used by VersionGuard.\n *\n * @public\n * @since 0.1.0\n * @forgeIgnore E020\n */\nexport interface PackageJson {\n /**\n * Package name.\n *\n * @defaultValue `undefined`\n */\n name?: string;\n /**\n * Package version string.\n *\n * @defaultValue `undefined`\n */\n version?: string;\n [key: string]: PackageJsonValue | undefined;\n}\n\n/**\n * Gets the `package.json` path for a project directory.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This is a convenience helper used by the package read and write helpers.\n *\n * @param cwd - Project directory containing `package.json`.\n * @returns The resolved `package.json` path.\n * @example\n * ```ts\n * import { getPackageJsonPath } from 'versionguard';\n *\n * const packagePath = getPackageJsonPath(process.cwd());\n * ```\n */\nexport function getPackageJsonPath(cwd: string = process.cwd()): string {\n return path.join(cwd, 'package.json');\n}\n\n/**\n * Reads and parses a project's `package.json` file.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * An error is thrown when `package.json` does not exist in the requested\n * directory.\n *\n * @param cwd - Project directory containing `package.json`.\n * @returns The parsed `package.json` document.\n * @example\n * ```ts\n * import { readPackageJson } from 'versionguard';\n *\n * const pkg = readPackageJson(process.cwd());\n * ```\n */\nexport function readPackageJson(cwd: string = process.cwd()): PackageJson {\n const packagePath = getPackageJsonPath(cwd);\n\n if (!fs.existsSync(packagePath)) {\n throw new Error(`package.json not found in ${cwd}`);\n }\n\n return JSON.parse(fs.readFileSync(packagePath, 'utf-8')) as PackageJson;\n}\n\n/**\n * Writes a `package.json` document back to disk.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * Output is formatted with two-space indentation and always ends with a\n * trailing newline.\n *\n * @param pkg - Parsed `package.json` data to write.\n * @param cwd - Project directory containing `package.json`.\n * @example\n * ```ts\n * import { readPackageJson, writePackageJson } from 'versionguard';\n *\n * const pkg = readPackageJson(process.cwd());\n * writePackageJson(pkg, process.cwd());\n * ```\n */\nexport function writePackageJson(pkg: PackageJson, cwd: string = process.cwd()): void {\n fs.writeFileSync(getPackageJsonPath(cwd), `${JSON.stringify(pkg, null, 2)}\\n`, 'utf-8');\n}\n\n/**\n * Gets the version string from `package.json`.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This throws when the file exists but does not contain a non-empty `version`\n * field.\n *\n * @param cwd - Project directory containing `package.json`.\n * @returns The package version string.\n * @example\n * ```ts\n * import { getPackageVersion } from 'versionguard';\n *\n * const version = getPackageVersion(process.cwd());\n * ```\n */\nexport function getPackageVersion(cwd: string = process.cwd()): string {\n const pkg = readPackageJson(cwd);\n\n if (typeof pkg.version !== 'string' || pkg.version.length === 0) {\n throw new Error('No version field in package.json');\n }\n\n return pkg.version;\n}\n\n/**\n * Sets the version field in `package.json`.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * The existing document is read, the `version` field is replaced, and the full\n * file is written back to disk.\n *\n * @param version - Version string to persist.\n * @param cwd - Project directory containing `package.json`.\n * @example\n * ```ts\n * import { setPackageVersion } from 'versionguard';\n *\n * setPackageVersion('1.2.3', process.cwd());\n * ```\n */\nexport function setPackageVersion(version: string, cwd: string = process.cwd()): void {\n const pkg = readPackageJson(cwd);\n pkg.version = version;\n writePackageJson(pkg, cwd);\n}\n","/**\n * Semantic version parsing, validation, comparison, and increment helpers.\n *\n * @packageDocumentation\n */\n\nimport type { SemVer, ValidationError, ValidationResult } from './types';\n\nconst SEMVER_REGEX =\n /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$/;\n\n/**\n * Parses a semantic version string.\n *\n * @remarks\n * This helper enforces the standard SemVer structure and returns `null` when the input does not\n * match. It preserves prerelease and build identifiers as ordered string segments.\n *\n * @param version - Version string to parse.\n * @returns Parsed semantic version components, or `null` when the input is invalid.\n *\n * @example\n * ```ts\n * import { parse } from 'versionguard';\n *\n * parse('1.2.3-alpha.1+build.5')?.prerelease;\n * // => ['alpha', '1']\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function parse(version: string): SemVer | null {\n const match = version.match(SEMVER_REGEX);\n\n if (!match) {\n return null;\n }\n\n return {\n major: Number.parseInt(match[1], 10),\n minor: Number.parseInt(match[2], 10),\n patch: Number.parseInt(match[3], 10),\n prerelease: match[4] ? match[4].split('.') : [],\n build: match[5] ? match[5].split('.') : [],\n raw: version,\n };\n}\n\nfunction getStructuralErrors(version: string): ValidationError[] {\n const errors: ValidationError[] = [];\n\n if (version.startsWith('v')) {\n errors.push({\n message: `Version should not start with 'v': ${version}`,\n severity: 'error',\n });\n return errors;\n }\n\n const mainPart = version.split(/[+-]/, 1)[0];\n const segments = mainPart.split('.');\n if (segments.length === 3) {\n const leadingZeroSegment = segments.find((segment) => /^0\\d+$/.test(segment));\n if (leadingZeroSegment) {\n errors.push({\n message: `Invalid SemVer: numeric segment \"${leadingZeroSegment}\" has a leading zero`,\n severity: 'error',\n });\n return errors;\n }\n }\n\n const prerelease = version.match(/-([^+]+)/)?.[1];\n if (prerelease) {\n const invalidPrerelease = prerelease.split('.').find((segment) => /^0\\d+$/.test(segment));\n if (invalidPrerelease) {\n errors.push({\n message: `Invalid SemVer: prerelease identifier \"${invalidPrerelease}\" has a leading zero`,\n severity: 'error',\n });\n return errors;\n }\n }\n\n errors.push({\n message: `Invalid SemVer format: \"${version}\". Expected MAJOR.MINOR.PATCH[-prerelease][+build].`,\n severity: 'error',\n });\n return errors;\n}\n\n/**\n * Validates that a string is a supported semantic version.\n *\n * @remarks\n * When validation fails, the result includes targeted structural errors for common cases such as\n * leading `v` prefixes and numeric segments with leading zeroes.\n *\n * @param version - Version string to validate.\n * @returns A validation result containing any detected errors and the parsed version on success.\n *\n * @example\n * ```ts\n * import { validate } from 'versionguard';\n *\n * validate('1.2.3').valid;\n * // => true\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function validate(version: string): ValidationResult {\n const parsed = parse(version);\n\n if (!parsed) {\n return {\n valid: false,\n errors: getStructuralErrors(version),\n };\n }\n\n return {\n valid: true,\n errors: [],\n version: { type: 'semver', version: parsed },\n };\n}\n\n/**\n * Compares two semantic version strings.\n *\n * @remarks\n * Comparison follows SemVer precedence rules, including special handling for prerelease\n * identifiers and ignoring build metadata.\n *\n * @param a - Left-hand version string.\n * @param b - Right-hand version string.\n * @returns `1` when `a` is greater, `-1` when `b` is greater, or `0` when they are equal.\n *\n * @example\n * ```ts\n * import { compare } from 'versionguard';\n *\n * compare('1.2.3', '1.2.3-alpha.1');\n * // => 1\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function compare(a: string, b: string): number {\n const left = parse(a);\n const right = parse(b);\n\n if (!left || !right) {\n throw new Error(`Invalid SemVer comparison between \"${a}\" and \"${b}\"`);\n }\n\n for (const key of ['major', 'minor', 'patch'] as const) {\n if (left[key] !== right[key]) {\n return left[key] > right[key] ? 1 : -1;\n }\n }\n\n const leftHasPrerelease = left.prerelease.length > 0;\n const rightHasPrerelease = right.prerelease.length > 0;\n\n if (leftHasPrerelease && !rightHasPrerelease) {\n return -1;\n }\n\n if (!leftHasPrerelease && rightHasPrerelease) {\n return 1;\n }\n\n const length = Math.max(left.prerelease.length, right.prerelease.length);\n for (let index = 0; index < length; index += 1) {\n const leftValue = left.prerelease[index];\n const rightValue = right.prerelease[index];\n\n if (leftValue === undefined) {\n return -1;\n }\n\n if (rightValue === undefined) {\n return 1;\n }\n\n const leftNumeric = /^\\d+$/.test(leftValue) ? Number.parseInt(leftValue, 10) : null;\n const rightNumeric = /^\\d+$/.test(rightValue) ? Number.parseInt(rightValue, 10) : null;\n\n if (leftNumeric !== null && rightNumeric !== null) {\n if (leftNumeric !== rightNumeric) {\n return leftNumeric > rightNumeric ? 1 : -1;\n }\n continue;\n }\n\n if (leftNumeric !== null) {\n return -1;\n }\n\n if (rightNumeric !== null) {\n return 1;\n }\n\n if (leftValue !== rightValue) {\n return leftValue > rightValue ? 1 : -1;\n }\n }\n\n return 0;\n}\n\n/**\n * Checks whether one semantic version is greater than another.\n *\n * @remarks\n * This is a convenience wrapper around {@link compare} for callers that only need a boolean.\n *\n * @param a - Left-hand version string.\n * @param b - Right-hand version string.\n * @returns `true` when `a` has higher precedence than `b`.\n *\n * @example\n * ```ts\n * import { gt } from 'versionguard';\n *\n * gt('1.2.4', '1.2.3');\n * // => true\n * ```\n *\n * @see {@link compare} for full precedence ordering.\n * @public\n * @since 0.1.0\n */\nexport function gt(a: string, b: string): boolean {\n return compare(a, b) > 0;\n}\n\n/**\n * Checks whether one semantic version is less than another.\n *\n * @remarks\n * This is a convenience wrapper around {@link compare} for callers that only need a boolean.\n *\n * @param a - Left-hand version string.\n * @param b - Right-hand version string.\n * @returns `true` when `a` has lower precedence than `b`.\n *\n * @example\n * ```ts\n * import { lt } from 'versionguard';\n *\n * lt('1.2.3-alpha.1', '1.2.3');\n * // => true\n * ```\n *\n * @see {@link compare} for full precedence ordering.\n * @public\n * @since 0.1.0\n */\nexport function lt(a: string, b: string): boolean {\n return compare(a, b) < 0;\n}\n\n/**\n * Checks whether two semantic versions are equal in precedence.\n *\n * @remarks\n * This is a convenience wrapper around {@link compare}. Build metadata is ignored because\n * precedence comparisons in SemVer do not consider it.\n *\n * @param a - Left-hand version string.\n * @param b - Right-hand version string.\n * @returns `true` when both versions compare as equal.\n *\n * @example\n * ```ts\n * import { eq } from 'versionguard';\n *\n * eq('1.2.3', '1.2.3');\n * // => true\n * ```\n *\n * @see {@link compare} for full precedence ordering.\n * @public\n * @since 0.1.0\n */\nexport function eq(a: string, b: string): boolean {\n return compare(a, b) === 0;\n}\n\n/**\n * Increments a semantic version string by release type.\n *\n * @remarks\n * Incrementing `major` or `minor` resets lower-order numeric segments. When a prerelease label is\n * provided, it is appended to the newly generated version.\n *\n * @param version - Current semantic version string.\n * @param release - Segment to increment.\n * @param prerelease - Optional prerelease suffix to append to the next version.\n * @returns The incremented semantic version string.\n *\n * @example\n * ```ts\n * import { increment } from 'versionguard';\n *\n * increment('1.2.3', 'minor', 'beta.1');\n * // => '1.3.0-beta.1'\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function increment(\n version: string,\n release: 'major' | 'minor' | 'patch',\n prerelease?: string,\n): string {\n const parsed = parse(version);\n\n if (!parsed) {\n throw new Error(`Invalid SemVer version: ${version}`);\n }\n\n if (release === 'major') {\n return `${parsed.major + 1}.0.0${prerelease ? `-${prerelease}` : ''}`;\n }\n\n if (release === 'minor') {\n return `${parsed.major}.${parsed.minor + 1}.0${prerelease ? `-${prerelease}` : ''}`;\n }\n\n return `${parsed.major}.${parsed.minor}.${parsed.patch + 1}${prerelease ? `-${prerelease}` : ''}`;\n}\n\n/**\n * Formats a parsed semantic version object.\n *\n * @remarks\n * Prerelease and build metadata segments are only included when their arrays contain values.\n *\n * @param version - Parsed semantic version to serialize.\n * @returns The normalized semantic version string.\n *\n * @example\n * ```ts\n * import { format } from 'versionguard';\n *\n * const version = { major: 1, minor: 2, patch: 3, prerelease: ['rc', '1'], build: ['build', '5'], raw: '1.2.3-rc.1+build.5' };\n *\n * format(version);\n * // => '1.2.3-rc.1+build.5'\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function format(version: SemVer): string {\n let output = `${version.major}.${version.minor}.${version.patch}`;\n\n if (version.prerelease.length > 0) {\n output += `-${version.prerelease.join('.')}`;\n }\n\n if (version.build.length > 0) {\n output += `+${version.build.join('.')}`;\n }\n\n return output;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport { globSync } from 'glob';\n\nimport type { SyncConfig, SyncPattern, SyncResult, VersionMismatch } from './types';\n\nfunction resolveFiles(patterns: string[], cwd: string, ignore: string[] = []): string[] {\n return [\n ...new Set(patterns.flatMap((pattern) => globSync(pattern, { cwd, absolute: true, ignore }))),\n ].sort();\n}\n\nfunction getLineNumber(content: string, offset: number): number {\n return content.slice(0, offset).split('\\n').length;\n}\n\nfunction extractVersion(groups: string[]): string {\n return groups[1] ?? groups[0] ?? '';\n}\n\nfunction applyTemplate(template: string, groups: string[], version: string): string {\n return template.replace(/\\$(\\d+)|\\{\\{version\\}\\}/g, (match, groupIndex: string | undefined) => {\n if (match === '{{version}}') {\n return version;\n }\n\n return groups[Number.parseInt(groupIndex ?? '0', 10) - 1] ?? '';\n });\n}\n\nfunction stringifyCapture(value: unknown): string {\n return typeof value === 'string' ? value : '';\n}\n\n/**\n * Synchronizes configured files to a single version string.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * File globs are resolved relative to `cwd`, then each matched file is updated\n * with the configured replacement patterns.\n *\n * @param version - Version string to write into matching files.\n * @param config - Sync configuration describing files and replacement patterns.\n * @param cwd - Project directory used to resolve file globs.\n * @returns A sync result for each resolved file.\n * @example\n * ```ts\n * import { getDefaultConfig, syncVersion } from 'versionguard';\n *\n * const results = syncVersion('1.2.3', getDefaultConfig().sync, process.cwd());\n * ```\n */\nexport function syncVersion(\n version: string,\n config: SyncConfig,\n cwd: string = process.cwd(),\n): SyncResult[] {\n return resolveFiles(config.files, cwd).map((filePath) =>\n syncFile(filePath, version, config.patterns),\n );\n}\n\n/**\n * Synchronizes a single file to a target version.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * Each configured regex is applied globally, and `{{version}}` placeholders in\n * templates are replaced with the supplied version.\n *\n * @param filePath - Absolute or relative path to the file to update.\n * @param version - Version string to write.\n * @param patterns - Replacement patterns to apply.\n * @returns A result describing whether the file changed and what changed.\n * @example\n * ```ts\n * import { getDefaultConfig, syncFile } from 'versionguard';\n *\n * const result = syncFile('README.md', '1.2.3', getDefaultConfig().sync.patterns);\n * ```\n */\nexport function syncFile(filePath: string, version: string, patterns: SyncPattern[]): SyncResult {\n const original = fs.readFileSync(filePath, 'utf-8');\n let updatedContent = original;\n const changes: SyncResult['changes'] = [];\n\n for (const pattern of patterns) {\n const regex = new RegExp(pattern.regex, 'gm');\n updatedContent = updatedContent.replace(regex, (match, ...args: unknown[]) => {\n const hasNamedGroups = typeof args.at(-1) === 'object' && args.at(-1) !== null;\n const offsetIndex = hasNamedGroups ? -3 : -2;\n const offset = args.at(offsetIndex) as number;\n const groups = args.slice(0, offsetIndex).map((value) => stringifyCapture(value));\n const found = extractVersion(groups);\n\n if (found === 'Unreleased') {\n return match;\n }\n\n if (found !== version) {\n changes.push({\n line: getLineNumber(updatedContent, offset),\n oldValue: found,\n newValue: version,\n });\n }\n\n return applyTemplate(pattern.template, groups, version) || match;\n });\n }\n\n const result: SyncResult = {\n file: filePath,\n updated: updatedContent !== original,\n changes,\n };\n\n if (result.updated) {\n fs.writeFileSync(filePath, updatedContent, 'utf-8');\n }\n\n return result;\n}\n\n/**\n * Checks configured files for hardcoded version mismatches.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * Files matching the sync config are scanned without modification, and every\n * captured version that differs from `expectedVersion` is returned.\n *\n * @param expectedVersion - Version all matching entries should use.\n * @param config - Sync configuration describing files and replacement patterns.\n * @param ignorePatterns - Glob patterns to exclude while scanning.\n * @param cwd - Project directory used to resolve file globs.\n * @returns A list of detected version mismatches.\n * @example\n * ```ts\n * import { checkHardcodedVersions, getDefaultConfig } from 'versionguard';\n *\n * const mismatches = checkHardcodedVersions(\n * '1.2.3',\n * getDefaultConfig().sync,\n * getDefaultConfig().ignore,\n * process.cwd(),\n * );\n * ```\n */\nexport function checkHardcodedVersions(\n expectedVersion: string,\n config: SyncConfig,\n ignorePatterns: string[],\n cwd: string = process.cwd(),\n): VersionMismatch[] {\n const mismatches: VersionMismatch[] = [];\n const files = resolveFiles(config.files, cwd, ignorePatterns);\n\n for (const filePath of files) {\n const content = fs.readFileSync(filePath, 'utf-8');\n\n for (const pattern of config.patterns) {\n const regex = new RegExp(pattern.regex, 'gm');\n let match: RegExpExecArray | null = regex.exec(content);\n\n while (match) {\n const found = extractVersion(match.slice(1));\n if (found !== 'Unreleased' && found !== expectedVersion) {\n mismatches.push({\n file: path.relative(cwd, filePath),\n line: getLineNumber(content, match.index),\n found,\n });\n }\n match = regex.exec(content);\n }\n }\n }\n\n return mismatches;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport * as yaml from 'js-yaml';\n\nimport type { VersionGuardConfig } from './types';\n\nconst CONFIG_FILE_NAMES = [\n '.versionguard.yml',\n '.versionguard.yaml',\n 'versionguard.yml',\n 'versionguard.yaml',\n];\n\nconst DEFAULT_CONFIG: VersionGuardConfig = {\n versioning: {\n type: 'semver',\n calver: {\n format: 'YYYY.MM.PATCH',\n preventFutureDates: true,\n },\n },\n sync: {\n files: ['README.md', 'CHANGELOG.md'],\n patterns: [\n {\n regex: '(version\\\\s*[=:]\\\\s*[\"\\'])(.+?)([\"\\'])',\n template: '$1{{version}}$3',\n },\n {\n regex: '(##\\\\s*\\\\[)(.+?)(\\\\])',\n template: '$1{{version}}$3',\n },\n ],\n },\n changelog: {\n enabled: true,\n file: 'CHANGELOG.md',\n strict: true,\n requireEntry: true,\n },\n git: {\n hooks: {\n 'pre-commit': true,\n 'pre-push': true,\n 'post-tag': true,\n },\n enforceHooks: true,\n },\n ignore: ['node_modules/**', 'dist/**', '.git/**', '*.lock', 'package-lock.json'],\n};\n\nconst MODULE_DIR = path.dirname(fileURLToPath(import.meta.url));\n\n/**\n * Returns a deep-cloned copy of the built-in VersionGuard configuration.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * A fresh clone is returned so callers can safely modify the result without\n * mutating shared defaults.\n *\n * @returns The default VersionGuard configuration.\n * @example\n * ```ts\n * import { getDefaultConfig } from 'versionguard';\n *\n * const config = getDefaultConfig();\n * ```\n */\nexport function getDefaultConfig(): VersionGuardConfig {\n return structuredClone(DEFAULT_CONFIG);\n}\n\n/**\n * Finds the first supported VersionGuard config file in a directory.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * Search order follows `CONFIG_FILE_NAMES`, so `.versionguard.yml` takes\n * precedence over the other supported filenames.\n *\n * @param cwd - Directory to search.\n * @returns The resolved config path, or `null` when no config file exists.\n * @example\n * ```ts\n * import { findConfig } from 'versionguard';\n *\n * const configPath = findConfig(process.cwd());\n * ```\n */\nexport function findConfig(cwd: string = process.cwd()): string | null {\n for (const fileName of CONFIG_FILE_NAMES) {\n const fullPath = path.join(cwd, fileName);\n if (fs.existsSync(fullPath)) {\n return fullPath;\n }\n }\n\n return null;\n}\n\n/**\n * Loads a VersionGuard config file from disk.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * The parsed YAML object is merged with the built-in defaults so omitted keys\n * inherit their default values.\n *\n * @param configPath - Path to the YAML config file.\n * @returns The merged VersionGuard configuration.\n * @example\n * ```ts\n * import { loadConfig } from 'versionguard';\n *\n * const config = loadConfig('.versionguard.yml');\n * ```\n */\nexport function loadConfig(configPath: string): VersionGuardConfig {\n const content = fs.readFileSync(configPath, 'utf-8');\n const parsed = yaml.load(content);\n\n if (parsed === undefined) {\n return getDefaultConfig();\n }\n\n if (!isPlainObject(parsed)) {\n throw new Error(`Config file must contain a YAML object: ${configPath}`);\n }\n\n return mergeDeep(getDefaultConfig(), parsed);\n}\n\n/**\n * Resolves the active VersionGuard configuration for a project.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * If no config file is present, this falls back to the built-in defaults.\n *\n * @param cwd - Project directory to inspect.\n * @returns The resolved VersionGuard configuration.\n * @example\n * ```ts\n * import { getConfig } from 'versionguard';\n *\n * const config = getConfig(process.cwd());\n * ```\n */\nexport function getConfig(cwd: string = process.cwd()): VersionGuardConfig {\n const configPath = findConfig(cwd);\n return configPath ? loadConfig(configPath) : getDefaultConfig();\n}\n\n/**\n * Initializes a new VersionGuard config file in a project.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This writes `.versionguard.yml` using the bundled example when available,\n * otherwise it writes a generated default configuration.\n *\n * @param cwd - Project directory where the config should be created.\n * @returns The path to the created config file.\n * @example\n * ```ts\n * import { initConfig } from 'versionguard';\n *\n * const configPath = initConfig(process.cwd());\n * ```\n */\nexport function initConfig(cwd: string = process.cwd()): string {\n const configPath = path.join(cwd, '.versionguard.yml');\n const existingConfigPath = findConfig(cwd);\n\n if (existingConfigPath) {\n throw new Error(`Config file already exists: ${existingConfigPath}`);\n }\n\n const examplePath = path.join(MODULE_DIR, '..', '.versionguard.yml.example');\n const content = fs.existsSync(examplePath)\n ? fs.readFileSync(examplePath, 'utf-8')\n : generateDefaultConfig();\n\n fs.writeFileSync(configPath, content, 'utf-8');\n return configPath;\n}\n\nfunction generateDefaultConfig(): string {\n return `# VersionGuard Configuration\nversioning:\n type: semver\n\nsync:\n files:\n - \"README.md\"\n - \"CHANGELOG.md\"\n patterns:\n - regex: '(version\\\\s*[=:]\\\\s*[\"''])(.+?)([\"''])'\n template: '$1{{version}}$3'\n - regex: '(##\\\\s*\\\\[)(.+?)(\\\\])'\n template: '$1{{version}}$3'\n\nchangelog:\n enabled: true\n file: \"CHANGELOG.md\"\n strict: true\n requireEntry: true\n\ngit:\n hooks:\n pre-commit: true\n pre-push: true\n post-tag: true\n enforceHooks: true\n\nignore:\n - \"node_modules/**\"\n - \"dist/**\"\n - \".git/**\"\n`;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction mergeDeep<T>(target: T, source: Partial<T>): T {\n /* v8 ignore next 3 -- defensive fallback for non-object nested overrides */\n if (!isPlainObject(target) || !isPlainObject(source)) {\n return (source ?? target) as T;\n }\n\n const output: Record<string, unknown> = { ...target };\n\n for (const [key, value] of Object.entries(source)) {\n const current = output[key];\n output[key] =\n isPlainObject(current) && isPlainObject(value) ? mergeDeep(current, value) : value;\n }\n\n return output as T;\n}\n","import * as calver from '../calver';\nimport * as semver from '../semver';\n\nimport type { CalVer, CalVerConfig, ValidationError, VersionGuardConfig } from '../types';\n\n/**\n * Feedback helpers that turn validation failures into actionable suggestions.\n *\n * @packageDocumentation\n * @public\n */\n\n/**\n * Feedback entry point exports for suggestion and guidance helpers.\n *\n * @packageDocumentation\n * @public\n * @since 0.1.0\n * @forgeIgnore E020\n */\nexport interface Suggestion {\n /**\n * Human-readable guidance for the user.\n */\n message: string;\n\n /**\n * Command or action text that can be used to address the issue.\n *\n * @defaultValue `undefined`\n */\n fix?: string;\n\n /**\n * Indicates whether VersionGuard can apply the suggestion automatically.\n */\n autoFixable: boolean;\n}\n\n/**\n * Aggregates validation errors with suggested next steps.\n *\n * @public\n * @since 0.1.0\n */\nexport interface FeedbackResult {\n /**\n * Indicates whether the inspected version state is valid.\n */\n valid: boolean;\n\n /**\n * Validation errors collected during the check.\n */\n errors: ValidationError[];\n\n /**\n * Suggested next steps for resolving the reported issues.\n */\n suggestions: Suggestion[];\n\n /**\n * Indicates whether at least one suggestion can be auto-applied.\n */\n canAutoFix: boolean;\n}\n\n/**\n * Generates actionable feedback for a version string.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper dispatches to the SemVer or CalVer feedback flow based on the\n * configured versioning strategy and returns both hard validation errors and\n * softer suggestions for likely fixes.\n *\n * @param version - Version string to evaluate.\n * @param config - Loaded VersionGuard configuration.\n * @param previousVersion - Optional previous version used for progression checks.\n * @returns A feedback object with validation errors and suggested fixes.\n *\n * @example\n * ```typescript\n * const feedbackResult = getVersionFeedback('1.2.3', config, '1.2.2');\n * console.log(feedbackResult.valid);\n * ```\n */\nexport function getVersionFeedback(\n version: string,\n config: VersionGuardConfig,\n previousVersion?: string,\n): FeedbackResult {\n if (config.versioning.type === 'semver') {\n return getSemVerFeedback(version, previousVersion);\n }\n\n return getCalVerFeedback(version, getCalVerConfig(config), previousVersion);\n}\n\nfunction getCalVerConfig(config: VersionGuardConfig): CalVerConfig {\n if (!config.versioning.calver) {\n throw new Error('CalVer configuration is required when versioning.type is \"calver\"');\n }\n\n return config.versioning.calver;\n}\n\nfunction getSemVerFeedback(version: string, previousVersion?: string): FeedbackResult {\n const errors: ValidationError[] = [];\n const suggestions: Suggestion[] = [];\n\n // Try to parse\n const parsed = semver.parse(version);\n\n if (!parsed) {\n const validation = semver.validate(version);\n\n // Common mistakes\n if (version.startsWith('v')) {\n const cleanVersion = version.slice(1);\n errors.push({\n message: `Version should not start with 'v': ${version}`,\n severity: 'error',\n });\n suggestions.push({\n message: `Remove the 'v' prefix`,\n fix: `npm version ${cleanVersion}`,\n autoFixable: true,\n });\n } else if (version.split('.').length === 2) {\n errors.push({\n message: `Version missing patch number: ${version}`,\n severity: 'error',\n });\n suggestions.push({\n message: `Add patch number (e.g., ${version}.0)`,\n fix: `npm version ${version}.0`,\n autoFixable: true,\n });\n } else if (/^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(version)) {\n errors.push({\n message: `Version has too many segments: ${version}`,\n severity: 'error',\n });\n suggestions.push({\n message: `Use only 3 segments (MAJOR.MINOR.PATCH)`,\n autoFixable: false,\n });\n } else if (validation.errors.some((error) => error.message.includes('leading zero'))) {\n errors.push(...validation.errors);\n suggestions.push({\n message: `Remove leading zeros (e.g., 1.2.3 instead of 01.02.03)`,\n autoFixable: false,\n });\n } else {\n errors.push(\n ...(validation.errors.length > 0\n ? validation.errors\n : [\n {\n message: `Invalid SemVer format: ${version}`,\n severity: 'error' as const,\n },\n ]),\n );\n suggestions.push({\n message: `Use format: MAJOR.MINOR.PATCH (e.g., 1.0.0)`,\n autoFixable: false,\n });\n }\n\n return {\n valid: false,\n errors,\n suggestions,\n canAutoFix: suggestions.some((s) => s.autoFixable),\n };\n }\n\n // Check progression from previous version\n if (previousVersion) {\n const prevParsed = semver.parse(previousVersion);\n if (prevParsed) {\n const comparison = semver.compare(version, previousVersion);\n\n if (comparison < 0) {\n errors.push({\n message: `Version ${version} is older than previous ${previousVersion}`,\n severity: 'error',\n });\n suggestions.push({\n message: `Version must be greater than ${previousVersion}`,\n fix: `npm version ${semver.increment(previousVersion, 'patch')}`,\n autoFixable: true,\n });\n } else if (comparison === 0) {\n errors.push({\n message: `Version ${version} is the same as previous`,\n severity: 'error',\n });\n suggestions.push({\n message: `Bump the version`,\n fix: `npm version ${semver.increment(previousVersion, 'patch')}`,\n autoFixable: true,\n });\n } else {\n // Check if it's a reasonable jump\n const majorJump = parsed.major - prevParsed.major;\n const minorJump = parsed.minor - prevParsed.minor;\n const patchJump = parsed.patch - prevParsed.patch;\n\n if (majorJump > 1) {\n suggestions.push({\n message: `⚠️ Major version jumped by ${majorJump} (from ${previousVersion} to ${version})`,\n autoFixable: false,\n });\n }\n\n if (minorJump > 10) {\n suggestions.push({\n message: `⚠️ Minor version jumped by ${minorJump} - did you mean to do a major bump?`,\n autoFixable: false,\n });\n }\n\n if (patchJump > 20) {\n suggestions.push({\n message: `⚠️ Patch version jumped by ${patchJump} - consider a minor bump instead`,\n autoFixable: false,\n });\n }\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n suggestions,\n canAutoFix: suggestions.some((s) => s.autoFixable),\n };\n}\n\nfunction getCalVerFeedback(\n version: string,\n calverConfig: CalVerConfig,\n previousVersion?: string,\n): FeedbackResult {\n const errors: ValidationError[] = [];\n const suggestions: Suggestion[] = [];\n const { format, preventFutureDates } = calverConfig;\n\n const parsed = calver.parse(version, format);\n\n if (!parsed) {\n errors.push({\n message: `Invalid CalVer format: ${version}`,\n severity: 'error',\n });\n suggestions.push({\n message: `Expected format: ${format}`,\n fix: `Update package.json to use current date: \"${calver.getCurrentVersion(format)}\"`,\n autoFixable: true,\n });\n return { valid: false, errors, suggestions, canAutoFix: true };\n }\n\n const validation = calver.validate(version, format, preventFutureDates);\n errors.push(...validation.errors);\n\n const now = new Date();\n if (validation.errors.some((error) => error.message.startsWith('Invalid month:'))) {\n suggestions.push({\n message: `Month must be between 1-12`,\n autoFixable: false,\n });\n }\n\n if (validation.errors.some((error) => error.message.startsWith('Invalid day:'))) {\n suggestions.push({\n message: `Day must be valid for the selected month`,\n autoFixable: false,\n });\n }\n\n if (preventFutureDates && parsed.year > now.getFullYear()) {\n suggestions.push({\n message: `Use current year (${now.getFullYear()}) or a past year`,\n fix: `npm version ${formatCalVerVersion({ ...parsed, year: now.getFullYear() })}`,\n autoFixable: true,\n });\n }\n\n if (\n preventFutureDates &&\n parsed.year === now.getFullYear() &&\n parsed.month > now.getMonth() + 1\n ) {\n suggestions.push({\n message: `Current month is ${now.getMonth() + 1}`,\n fix: `npm version ${formatCalVerVersion({ ...parsed, month: now.getMonth() + 1 })}`,\n autoFixable: true,\n });\n }\n\n if (\n preventFutureDates &&\n parsed.year === now.getFullYear() &&\n parsed.month === now.getMonth() + 1 &&\n parsed.day !== undefined &&\n parsed.day > now.getDate()\n ) {\n suggestions.push({\n message: `Current day is ${now.getDate()}`,\n fix: `npm version ${formatCalVerVersion({ ...parsed, day: now.getDate() })}`,\n autoFixable: true,\n });\n }\n\n // Check progression\n if (previousVersion) {\n const prevParsed = calver.parse(previousVersion, format);\n if (prevParsed) {\n if (calver.compare(version, previousVersion, format) <= 0) {\n errors.push({\n message: `Version ${version} is not newer than previous ${previousVersion}`,\n severity: 'error',\n });\n suggestions.push({\n message: `CalVer must increase over time`,\n fix: `npm version ${calver.increment(previousVersion, format)}`,\n autoFixable: true,\n });\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n suggestions,\n canAutoFix: suggestions.some((s) => s.autoFixable),\n };\n}\n\nfunction formatCalVerVersion(version: CalVer): string {\n return calver.format({\n ...version,\n raw: version.raw || '',\n });\n}\n\n/**\n * Generates suggestions for version sync mismatches in a file.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * The returned suggestions include a general sync command and may include\n * file-type-specific hints for markdown or source files.\n *\n * @param file - File containing the mismatched version string.\n * @param foundVersion - Version currently found in the file.\n * @param expectedVersion - Version that should appear in the file.\n * @returns Suggestions for resolving the mismatch.\n *\n * @example\n * ```typescript\n * const suggestions = getSyncFeedback('README.md', '1.0.0', '1.0.1');\n * console.log(suggestions[0]?.message);\n * ```\n */\nexport function getSyncFeedback(\n file: string,\n foundVersion: string,\n expectedVersion: string,\n): Suggestion[] {\n const suggestions: Suggestion[] = [\n {\n message: `${file} has version \"${foundVersion}\" but should be \"${expectedVersion}\"`,\n fix: `npx versionguard sync`,\n autoFixable: true,\n },\n ];\n\n // Common patterns\n if (file.endsWith('.md')) {\n suggestions.push({\n message: `For markdown files, check headers like \"## [${expectedVersion}]\"`,\n autoFixable: false,\n });\n }\n\n if (file.endsWith('.ts') || file.endsWith('.js')) {\n suggestions.push({\n message: `For code files, check constants like \"export const VERSION = '${expectedVersion}'\"`,\n autoFixable: false,\n });\n }\n\n return suggestions;\n}\n\n/**\n * Generates suggestions for changelog-related validation issues.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper suggests either creating a missing entry or reconciling the latest\n * changelog version with the package version.\n *\n * @param hasEntry - Whether the changelog already contains an entry for the version.\n * @param version - Package version that should appear in the changelog.\n * @param latestChangelogVersion - Most recent version currently found in the changelog.\n * @returns Suggestions for bringing changelog state back into sync.\n *\n * @example\n * ```typescript\n * const suggestions = getChangelogFeedback(false, '1.2.3', '1.2.2');\n * console.log(suggestions.length > 0);\n * ```\n */\nexport function getChangelogFeedback(\n hasEntry: boolean,\n version: string,\n latestChangelogVersion?: string,\n): Suggestion[] {\n const suggestions: Suggestion[] = [];\n\n if (!hasEntry) {\n suggestions.push({\n message: `CHANGELOG.md is missing entry for version ${version}`,\n fix: `npx versionguard fix`,\n autoFixable: true,\n });\n\n suggestions.push({\n message: `Or manually add: \"## [${version}] - YYYY-MM-DD\" under [Unreleased]`,\n autoFixable: false,\n });\n }\n\n if (latestChangelogVersion && latestChangelogVersion !== version) {\n suggestions.push({\n message: `CHANGELOG.md latest entry is ${latestChangelogVersion}, but package.json is ${version}`,\n fix: `Make sure versions are in sync`,\n autoFixable: false,\n });\n }\n\n return suggestions;\n}\n\n/**\n * Generates suggestions for git tag mismatches.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper focuses on discrepancies between git tag versions, package.json,\n * and repository files that still need to be synchronized.\n *\n * @param tagVersion - Version represented by the git tag.\n * @param packageVersion - Version currently stored in `package.json`.\n * @param hasUnsyncedFiles - Whether repository files are still out of sync.\n * @returns Suggestions for correcting tag-related issues.\n *\n * @example\n * ```typescript\n * const suggestions = getTagFeedback('v1.2.2', '1.2.3', true);\n * console.log(suggestions.map((item) => item.message));\n * ```\n */\nexport function getTagFeedback(\n tagVersion: string,\n packageVersion: string,\n hasUnsyncedFiles: boolean,\n): Suggestion[] {\n const suggestions: Suggestion[] = [];\n\n if (tagVersion !== packageVersion) {\n suggestions.push({\n message: `Git tag \"${tagVersion}\" doesn't match package.json \"${packageVersion}\"`,\n fix: `Delete tag and recreate: git tag -d ${tagVersion} && git tag ${packageVersion}`,\n autoFixable: false,\n });\n }\n\n if (hasUnsyncedFiles) {\n suggestions.push({\n message: `Files are out of sync with version ${packageVersion}`,\n fix: `npx versionguard sync`,\n autoFixable: true,\n });\n }\n\n return suggestions;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport * as calver from '../calver';\nimport { addVersionEntry } from '../changelog';\nimport { getPackageVersion, setPackageVersion } from '../project';\nimport * as semver from '../semver';\nimport { syncVersion } from '../sync';\nimport type { CalVerConfig, VersionGuardConfig } from '../types';\n\n/**\n * Auto-fix helpers for package versions, synced files, and changelog entries.\n *\n * @packageDocumentation\n * @public\n */\n\n/**\n * Fix entry point exports for auto-remediation helpers.\n *\n * @packageDocumentation\n * @public\n * @since 0.1.0\n * @forgeIgnore E020\n */\nexport interface FixResult {\n /**\n * Indicates whether the operation changed repository state.\n */\n fixed: boolean;\n\n /**\n * Human-readable description of the fix attempt.\n */\n message: string;\n\n /**\n * Absolute path to the file that was updated, when applicable.\n *\n * @defaultValue `undefined`\n */\n file?: string;\n}\n\n/**\n * Updates the `package.json` version field when needed.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper writes the target version only when `package.json` exists and the\n * current version differs from the requested value.\n *\n * @param targetVersion - Version that should be written to `package.json`.\n * @param cwd - Repository directory containing `package.json`.\n * @returns The result of the package version fix attempt.\n *\n * @example\n * ```typescript\n * const result = fixPackageVersion('1.2.3', process.cwd());\n * console.log(result.fixed);\n * ```\n */\nexport function fixPackageVersion(targetVersion: string, cwd: string = process.cwd()): FixResult {\n const packagePath = path.join(cwd, 'package.json');\n\n if (!fs.existsSync(packagePath)) {\n return { fixed: false, message: 'package.json not found' };\n }\n\n const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf-8')) as { version?: string };\n const oldVersion = typeof pkg.version === 'string' ? pkg.version : undefined;\n\n if (oldVersion === targetVersion) {\n return { fixed: false, message: `Already at version ${targetVersion}` };\n }\n\n setPackageVersion(targetVersion, cwd);\n\n return {\n fixed: true,\n message: `Updated package.json from ${oldVersion} to ${targetVersion}`,\n file: packagePath,\n };\n}\n\n/**\n * Synchronizes configured files to the package version.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper uses the configured sync targets to update version strings across\n * the repository and reports only the files that changed.\n *\n * @param config - Loaded VersionGuard configuration.\n * @param cwd - Repository directory to synchronize.\n * @returns A list of per-file sync results.\n *\n * @example\n * ```typescript\n * const results = fixSyncIssues(config, process.cwd());\n * console.log(results.length);\n * ```\n */\nexport function fixSyncIssues(\n config: VersionGuardConfig,\n cwd: string = process.cwd(),\n): FixResult[] {\n const version = getPackageVersion(cwd);\n const results: FixResult[] = syncVersion(version, config.sync, cwd)\n .filter((result) => result.updated)\n .map((result) => ({\n fixed: true,\n message: `Updated ${path.relative(cwd, result.file)} (${result.changes.length} changes)`,\n file: result.file,\n }));\n\n if (results.length === 0) {\n results.push({ fixed: false, message: 'All files already in sync' });\n }\n\n return results;\n}\n\n/**\n * Ensures the changelog contains an entry for a version.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * When the changelog file does not exist, this helper creates a starter changelog.\n * Otherwise it appends a new version entry only when one is missing.\n *\n * @param version - Version that should appear in the changelog.\n * @param config - Loaded VersionGuard configuration.\n * @param cwd - Repository directory containing the changelog file.\n * @returns The result of the changelog fix attempt.\n *\n * @example\n * ```typescript\n * const result = fixChangelog('1.2.3', config, process.cwd());\n * console.log(result.message);\n * ```\n */\nexport function fixChangelog(\n version: string,\n config: VersionGuardConfig,\n cwd: string = process.cwd(),\n): FixResult {\n const changelogPath = path.join(cwd, config.changelog.file);\n\n if (!fs.existsSync(changelogPath)) {\n // Create initial changelog\n createInitialChangelog(changelogPath, version);\n return {\n fixed: true,\n message: `Created ${config.changelog.file} with entry for ${version}`,\n file: changelogPath,\n };\n }\n\n const content = fs.readFileSync(changelogPath, 'utf-8');\n\n if (content.includes(`## [${version}]`)) {\n return { fixed: false, message: `Changelog already has entry for ${version}` };\n }\n\n addVersionEntry(changelogPath, version);\n\n return {\n fixed: true,\n message: `Added entry for ${version} to ${config.changelog.file}`,\n file: changelogPath,\n };\n}\n\n/**\n * Create initial changelog\n */\nfunction createInitialChangelog(changelogPath: string, version: string): void {\n const today = new Date().toISOString().slice(0, 10);\n const content = `# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n## [${version}] - ${today}\n\n### Added\n\n- Initial release\n\n[Unreleased]: https://github.com/yourorg/project/compare/v${version}...HEAD\n[${version}]: https://github.com/yourorg/project/releases/tag/v${version}\n`;\n\n fs.writeFileSync(changelogPath, content, 'utf-8');\n}\n\n/**\n * Runs all configured auto-fix operations.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper optionally updates the package version first, then synchronizes\n * configured files, and finally updates the changelog when changelog support is\n * enabled.\n *\n * @param config - Loaded VersionGuard configuration.\n * @param targetVersion - Optional version to apply before running other fixes.\n * @param cwd - Repository directory where fixes should run.\n * @returns Ordered results describing every fix step that ran.\n *\n * @example\n * ```typescript\n * const results = fixAll(config, '1.2.3', process.cwd());\n * console.log(results.some((result) => result.fixed));\n * ```\n */\nexport function fixAll(\n config: VersionGuardConfig,\n targetVersion?: string,\n cwd: string = process.cwd(),\n): FixResult[] {\n const results: FixResult[] = [];\n const version = targetVersion || getPackageVersion(cwd);\n\n if (targetVersion && targetVersion !== getPackageVersion(cwd)) {\n results.push(fixPackageVersion(targetVersion, cwd));\n }\n\n const syncResults = fixSyncIssues(config, cwd);\n results.push(...syncResults);\n\n if (config.changelog.enabled) {\n const changelogResult = fixChangelog(version, config, cwd);\n if (changelogResult.fixed) {\n results.push(changelogResult);\n }\n }\n\n return results;\n}\n\n/**\n * Suggests candidate next versions for a release.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * The suggestions depend on the configured versioning mode. SemVer returns one or\n * more bump options, while CalVer suggests the current date-based version and an\n * incremented same-day release.\n *\n * @param currentVersion - Current package version.\n * @param config - Loaded VersionGuard configuration.\n * @param changeType - Preferred bump type, or `auto` to include common options.\n * @returns Candidate versions paired with the reason for each suggestion.\n *\n * @example\n * ```typescript\n * const suggestions = suggestNextVersion('1.2.3', config, 'minor');\n * console.log(suggestions[0]?.version);\n * ```\n */\nexport function suggestNextVersion(\n currentVersion: string,\n config: VersionGuardConfig,\n changeType?: 'major' | 'minor' | 'patch' | 'auto',\n): { version: string; reason: string }[] {\n const suggestions: { version: string; reason: string }[] = [];\n\n if (config.versioning.type === 'semver') {\n if (!changeType || changeType === 'auto' || changeType === 'patch') {\n suggestions.push({\n version: semver.increment(currentVersion, 'patch'),\n reason: 'Patch - bug fixes, small changes',\n });\n }\n\n if (!changeType || changeType === 'auto' || changeType === 'minor') {\n suggestions.push({\n version: semver.increment(currentVersion, 'minor'),\n reason: 'Minor - new features, backwards compatible',\n });\n }\n\n if (!changeType || changeType === 'auto' || changeType === 'major') {\n suggestions.push({\n version: semver.increment(currentVersion, 'major'),\n reason: 'Major - breaking changes',\n });\n }\n } else {\n // CalVer\n const format = getCalVerConfig(config).format;\n const currentCal = calver.getCurrentVersion(format);\n\n // Option 1: Current date\n suggestions.push({\n version: currentCal,\n reason: 'Current date - new release today',\n });\n\n // Option 2: Increment patch on current version\n suggestions.push({\n version: calver.increment(currentVersion, format),\n reason: 'Increment patch - additional release today',\n });\n }\n\n return suggestions;\n}\n\nfunction getCalVerConfig(config: VersionGuardConfig): CalVerConfig {\n if (!config.versioning.calver) {\n throw new Error('CalVer configuration is required when versioning.type is \"calver\"');\n }\n\n return config.versioning.calver;\n}\n","import * as childProcess from 'node:child_process';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport { validate as validateCalVer } from '../calver';\nimport { validateChangelog } from '../changelog';\nimport { fixAll } from '../fix';\nimport { areHooksInstalled } from '../hooks';\nimport { getPackageVersion } from '../project';\nimport { validate as validateSemVer } from '../semver';\nimport { checkHardcodedVersions } from '../sync';\nimport type { VersionGuardConfig } from '../types';\n\n/**\n * Tag management helpers for reading, validating, and creating release tags.\n *\n * @packageDocumentation\n * @public\n */\n\n/**\n * Tag entry point exports for release-tag management helpers.\n *\n * @packageDocumentation\n * @public\n * @since 0.1.0\n * @forgeIgnore E020\n */\nexport interface TagInfo {\n /**\n * Full git tag name, including any prefix such as `v`.\n */\n name: string;\n\n /**\n * Normalized version string derived from the tag name.\n */\n version: string;\n\n /**\n * Annotated tag message when one is available.\n *\n * @defaultValue `undefined`\n */\n message?: string;\n\n /**\n * Timestamp associated with the tag lookup result.\n */\n date: Date;\n}\n\nfunction runGit(cwd: string, args: string[], encoding?: BufferEncoding): string | Buffer {\n return childProcess.execFileSync('git', args, {\n cwd,\n encoding,\n stdio: ['pipe', 'pipe', 'ignore'],\n });\n}\n\nfunction runGitText(cwd: string, args: string[]): string {\n return runGit(cwd, args, 'utf-8') as string;\n}\n\n/**\n * Returns the most recent reachable git tag for a repository.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper reads the most recent annotated or lightweight tag that `git describe`\n * can resolve from the current HEAD. It returns `null` when no tags are available\n * or when git metadata cannot be read.\n *\n * @param cwd - Repository directory to inspect.\n * @returns The latest tag details, or `null` when no tag can be resolved.\n *\n * @example\n * ```typescript\n * const latestTag = getLatestTag(process.cwd());\n *\n * if (latestTag) {\n * console.log(latestTag.version);\n * }\n * ```\n */\nexport function getLatestTag(cwd: string = process.cwd()): TagInfo | null {\n try {\n const result = runGitText(cwd, ['describe', '--tags', '--abbrev=0']);\n\n const tagName = result.trim();\n const version = tagName.replace(/^v/, '');\n\n const dateResult = runGitText(cwd, ['log', '-1', '--format=%ai', tagName]);\n const messageResult = runGitText(cwd, ['tag', '-l', tagName, '--format=%(contents)']);\n const message = messageResult.trim();\n\n return {\n name: tagName,\n version,\n message: message.length > 0 ? message : undefined,\n date: new Date(dateResult.trim()),\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Lists all tags in a repository.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper returns tag names in the order provided by `git tag --list`. The\n * `date` field is populated with the current time because the implementation does\n * not perform per-tag date lookups.\n *\n * @param cwd - Repository directory to inspect.\n * @returns A list of discovered tags, or an empty array when tags cannot be read.\n *\n * @example\n * ```typescript\n * const tags = getAllTags(process.cwd());\n * console.log(tags.map((tag) => tag.name));\n * ```\n */\nexport function getAllTags(cwd: string = process.cwd()): TagInfo[] {\n try {\n const result = runGitText(cwd, ['tag', '--list']);\n\n return result\n .trim()\n .split('\\n')\n .filter(Boolean)\n .map((name) => ({\n name,\n version: name.replace(/^v/, ''),\n date: new Date(), // Would need individual lookup for accurate dates\n }));\n } catch {\n return [];\n }\n}\n\n/**\n * Creates a release tag and optionally fixes version state first.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * When `autoFix` is enabled, this helper updates versioned files, stages the\n * changes, and creates a release commit before creating the annotated tag. It\n * returns a structured result instead of throwing for most expected failures.\n *\n * @param version - Version to embed in the new tag name.\n * @param message - Custom annotated tag message.\n * @param autoFix - Whether to auto-fix version mismatches before tagging.\n * @param config - Loaded VersionGuard configuration used for validation and fixes.\n * @param cwd - Repository directory where git commands should run.\n * @returns The tagging outcome and any actions performed along the way.\n *\n * @example\n * ```typescript\n * const result = createTag('1.2.3', 'Release 1.2.3', true, config, process.cwd());\n *\n * if (!result.success) {\n * console.error(result.message);\n * }\n * ```\n */\nexport function createTag(\n version: string,\n message?: string,\n autoFix: boolean = true,\n config?: VersionGuardConfig,\n cwd: string = process.cwd(),\n): { success: boolean; message: string; actions: string[] } {\n const actions: string[] = [];\n\n try {\n if (!config) {\n return {\n success: false,\n message: 'VersionGuard config is required to create tags safely',\n actions,\n };\n }\n\n const packageVersion = getPackageVersion(cwd);\n const shouldAutoFix = autoFix;\n const preflightError = getTagPreflightError(config, cwd, version, shouldAutoFix);\n if (preflightError) {\n return {\n success: false,\n message: preflightError,\n actions,\n };\n }\n\n if (version !== packageVersion && !autoFix) {\n return {\n success: false,\n message: `Version mismatch: package.json is ${packageVersion}, tag is ${version}`,\n actions: [],\n };\n }\n\n if (autoFix) {\n const fixResults =\n version !== packageVersion ? fixAll(config, version, cwd) : fixAll(config, undefined, cwd);\n\n for (const result of fixResults) {\n if (result.fixed) {\n actions.push(result.message);\n }\n }\n\n if (fixResults.some((result) => result.fixed)) {\n runGit(cwd, ['add', '-A']);\n runGit(cwd, ['commit', '--no-verify', '-m', `chore(release): ${version}`]);\n actions.push('Committed version changes');\n }\n }\n\n const tagName = `v${version}`;\n const tagMessage = message || `Release ${version}`;\n\n if (getAllTags(cwd).some((tag) => tag.name === tagName)) {\n return {\n success: false,\n message: `Tag ${tagName} already exists`,\n actions,\n };\n }\n\n runGit(cwd, ['tag', '-a', tagName, '-m', tagMessage]);\n actions.push(`Created tag ${tagName}`);\n\n return {\n success: true,\n message: `Successfully created tag ${tagName}`,\n actions,\n };\n } catch (err) {\n return {\n success: false,\n message: `Failed to create tag: ${(err as Error).message}`,\n actions,\n };\n }\n}\n\n/**\n * Runs post-tag validation and sync checks.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper is intended for the `post-tag` git hook flow. It validates the\n * latest tag against the configured versioning rules and reports any required\n * follow-up actions without mutating git history.\n *\n * @param config - Loaded VersionGuard configuration used during validation.\n * @param cwd - Repository directory where validation should run.\n * @returns The post-tag workflow result and any follow-up actions.\n *\n * @example\n * ```typescript\n * const result = handlePostTag(config, process.cwd());\n * console.log(result.success);\n * ```\n */\nexport function handlePostTag(\n config: VersionGuardConfig,\n cwd: string = process.cwd(),\n): { success: boolean; message: string; actions: string[] } {\n const actions: string[] = [];\n\n try {\n const preflightError = getTagPreflightError(config, cwd);\n if (preflightError) {\n return {\n success: false,\n message: preflightError,\n actions,\n };\n }\n\n const tag = getLatestTag(cwd);\n if (!tag) {\n return {\n success: false,\n message: 'No tag found',\n actions,\n };\n }\n const packageVersion = getPackageVersion(cwd);\n\n if (tag.version !== packageVersion) {\n return {\n success: false,\n message: `Tag version ${tag.version} doesn't match package.json ${packageVersion}`,\n actions: [\n 'To fix: delete tag and recreate with correct version',\n ` git tag -d ${tag.name}`,\n ` npm version ${tag.version}`,\n ` git tag ${tag.name}`,\n ],\n };\n }\n const syncResults = fixAll(config, packageVersion, cwd);\n\n for (const result of syncResults) {\n /* v8 ignore next 3 -- preflight blocks remaining post-tag fixes */\n if (result.fixed) {\n actions.push(result.message);\n }\n }\n\n return {\n success: true,\n message: `Post-tag workflow completed for ${tag.name}`,\n actions,\n };\n } catch (err) {\n return {\n success: false,\n message: `Post-tag workflow failed: ${(err as Error).message}`,\n actions,\n };\n }\n}\n\nfunction getTagPreflightError(\n config: VersionGuardConfig,\n cwd: string,\n expectedVersion?: string,\n allowAutoFix: boolean = false,\n): string | null {\n if (config.git.enforceHooks && !areHooksInstalled(cwd)) {\n return 'Git hooks must be installed before creating or validating release tags';\n }\n\n if (hasDirtyWorktree(cwd)) {\n return 'Working tree must be clean before creating or validating release tags';\n }\n\n const version = expectedVersion ?? getPackageVersion(cwd);\n const versionResult =\n config.versioning.type === 'semver'\n ? validateSemVer(version)\n : validateCalVer(\n version,\n config.versioning.calver?.format ?? 'YYYY.MM.PATCH',\n config.versioning.calver?.preventFutureDates ?? true,\n );\n\n if (!versionResult.valid) {\n return versionResult.errors[0]?.message ?? `Invalid version: ${version}`;\n }\n\n if (allowAutoFix) {\n return null;\n }\n\n const mismatches = checkHardcodedVersions(version, config.sync, config.ignore, cwd);\n if (mismatches.length > 0) {\n const mismatch = mismatches[0];\n return `Version mismatch in ${mismatch.file}:${mismatch.line} - found \"${mismatch.found}\" but expected \"${version}\"`;\n }\n\n const changelogResult = validateChangelog(\n path.join(cwd, config.changelog.file),\n version,\n config.changelog.strict,\n config.changelog.requireEntry,\n );\n if (!changelogResult.valid) {\n return changelogResult.errors[0] ?? 'Changelog validation failed';\n }\n\n return null;\n}\n\nfunction hasDirtyWorktree(cwd: string): boolean {\n try {\n return runGitText(cwd, ['status', '--porcelain']).trim().length > 0;\n } catch {\n return true;\n }\n}\n\n/**\n * Validates that a local tag is safe to push to the default remote.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper checks that the tag exists locally and, when the tag also exists on\n * `origin`, verifies that both references point to the same commit.\n *\n * @param tagName - Name of the tag to validate.\n * @param cwd - Repository directory where git commands should run.\n * @returns A validation result with an optional suggested fix command.\n *\n * @example\n * ```typescript\n * const result = validateTagForPush('v1.2.3', process.cwd());\n * console.log(result.valid);\n * ```\n */\nexport function validateTagForPush(\n tagName: string,\n cwd: string = process.cwd(),\n): { valid: boolean; message: string; fix?: string } {\n try {\n runGit(cwd, ['rev-parse', tagName]);\n\n try {\n runGit(cwd, ['ls-remote', '--tags', 'origin', tagName]);\n\n const localHash = runGitText(cwd, ['rev-parse', tagName]).trim();\n const remoteOutput = runGitText(cwd, ['ls-remote', '--tags', 'origin', tagName]).trim();\n\n if (remoteOutput && !remoteOutput.includes(localHash)) {\n return {\n valid: false,\n message: `Tag ${tagName} exists on remote with different commit`,\n fix: `Delete remote tag first: git push origin :refs/tags/${tagName}`,\n };\n }\n } catch {\n return { valid: true, message: `Tag ${tagName} is valid for push` };\n }\n\n return { valid: true, message: `Tag ${tagName} is valid for push` };\n } catch {\n return {\n valid: false,\n message: `Tag ${tagName} not found locally`,\n fix: `Create tag: git tag ${tagName}`,\n };\n }\n}\n\n/**\n * Suggests an annotated tag message from changelog content.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * When a matching changelog entry exists, this helper uses the first bullet point\n * as a concise release summary. It falls back to a generic `Release {version}`\n * message when no changelog context is available.\n *\n * @param version - Version that the tag will represent.\n * @param cwd - Repository directory containing the changelog file.\n * @returns A suggested annotated tag message.\n *\n * @example\n * ```typescript\n * const message = suggestTagMessage('1.2.3', process.cwd());\n * console.log(message);\n * ```\n */\nexport function suggestTagMessage(version: string, cwd: string = process.cwd()): string {\n try {\n const changelogPath = path.join(cwd, 'CHANGELOG.md');\n if (fs.existsSync(changelogPath)) {\n const content = fs.readFileSync(changelogPath, 'utf-8');\n\n const versionRegex = new RegExp(\n `## \\\\[${version}\\\\].*?\\\\n(.*?)(?=\\\\n## \\\\[|\\\\n\\\\n## |$)`,\n 's',\n );\n const match = content.match(versionRegex);\n\n if (match) {\n const bulletMatch = match[1].match(/- (.+)/);\n if (bulletMatch) {\n return `Release ${version}: ${bulletMatch[1].trim()}`;\n }\n }\n }\n } catch {\n return `Release ${version}`;\n }\n\n return `Release ${version}`;\n}\n","/**\n * Public API for VersionGuard.\n *\n * @packageDocumentation\n * @public\n */\n\nimport { execSync } from 'node:child_process';\nimport * as path from 'node:path';\n\nimport * as calver from './calver';\nimport { validateChangelog } from './changelog';\nimport { areHooksInstalled, findGitDir } from './hooks';\nimport { getPackageVersion } from './project';\nimport * as semver from './semver';\nimport { checkHardcodedVersions, syncVersion } from './sync';\nimport type {\n CalVerConfig,\n DoctorReport,\n FullValidationResult,\n ValidationResult,\n VersionGuardConfig,\n} from './types';\n\nexport * as calver from './calver';\nexport { validateChangelog } from './changelog';\nexport { getConfig, initConfig } from './config';\nexport * from './feedback';\nexport * from './fix';\nexport { areHooksInstalled, installHooks, uninstallHooks } from './hooks';\nexport { getPackageVersion } from './project';\nexport * as semver from './semver';\nexport { checkHardcodedVersions, syncVersion } from './sync';\nexport * from './tag';\nexport * from './types';\n\n/**\n * Validates a version string against the active versioning strategy.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper dispatches to SemVer or CalVer validation based on\n * `config.versioning.type`.\n *\n * @param version - Version string to validate.\n * @param config - VersionGuard configuration that selects the validation rules.\n * @returns The validation result for the provided version.\n * @example\n * ```ts\n * import { getDefaultConfig, validateVersion } from 'versionguard';\n *\n * const result = validateVersion('1.2.3', getDefaultConfig());\n * ```\n */\nexport function validateVersion(version: string, config: VersionGuardConfig): ValidationResult {\n if (config.versioning.type === 'semver') {\n return semver.validate(version);\n }\n\n const calverConfig = getCalVerConfig(config);\n return calver.validate(version, calverConfig.format, calverConfig.preventFutureDates);\n}\n\n/**\n * Validates the current project state against the supplied configuration.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This reads the package version from `package.json`, validates the version\n * format, checks synchronized files, and optionally validates the changelog.\n *\n * @param config - VersionGuard configuration to apply.\n * @param cwd - Project directory to inspect.\n * @returns A full validation report for the project rooted at `cwd`.\n * @example\n * ```ts\n * import { getDefaultConfig, validate } from 'versionguard';\n *\n * const result = validate(getDefaultConfig(), process.cwd());\n * ```\n */\nexport function validate(\n config: VersionGuardConfig,\n cwd: string = process.cwd(),\n): FullValidationResult {\n const errors: string[] = [];\n\n let version: string;\n try {\n version = getPackageVersion(cwd);\n } catch (err) {\n return {\n valid: false,\n version: '',\n versionValid: false,\n syncValid: false,\n changelogValid: false,\n errors: [(err as Error).message],\n };\n }\n\n const versionResult = validateVersion(version, config);\n if (!versionResult.valid) {\n errors.push(...versionResult.errors.map((error) => error.message));\n }\n\n const hardcoded = checkHardcodedVersions(version, config.sync, config.ignore, cwd);\n\n if (hardcoded.length > 0) {\n for (const mismatch of hardcoded) {\n errors.push(\n `Version mismatch in ${mismatch.file}:${mismatch.line} - found \"${mismatch.found}\" but expected \"${version}\"`,\n );\n }\n }\n\n let changelogValid = true;\n if (config.changelog.enabled) {\n const changelogPath = path.join(cwd, config.changelog.file);\n const changelogResult = validateChangelog(\n changelogPath,\n version,\n config.changelog.strict,\n config.changelog.requireEntry,\n );\n\n if (!changelogResult.valid) {\n changelogValid = false;\n errors.push(...changelogResult.errors);\n }\n }\n\n return {\n valid: errors.length === 0,\n version,\n versionValid: versionResult.valid,\n syncValid: hardcoded.length === 0,\n changelogValid,\n errors,\n };\n}\n\n/**\n * Runs an extended readiness check for a project.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * In addition to `validate`, this inspects Git state so callers can determine\n * whether hooks are installed and the worktree is clean.\n *\n * @param config - VersionGuard configuration to apply.\n * @param cwd - Project directory to inspect.\n * @returns A readiness report that includes validation and Git diagnostics.\n * @example\n * ```ts\n * import { doctor, getDefaultConfig } from 'versionguard';\n *\n * const report = doctor(getDefaultConfig(), process.cwd());\n * ```\n */\nexport function doctor(config: VersionGuardConfig, cwd: string = process.cwd()): DoctorReport {\n const validation = validate(config, cwd);\n const gitRepository = findGitDir(cwd) !== null;\n const hooksInstalled = gitRepository ? areHooksInstalled(cwd) : false;\n const worktreeClean = gitRepository ? isWorktreeClean(cwd) : true;\n const errors = [...validation.errors];\n\n if (gitRepository && config.git.enforceHooks && !hooksInstalled) {\n errors.push('Git hooks are not installed');\n }\n\n if (gitRepository && !worktreeClean) {\n errors.push('Working tree is not clean');\n }\n\n return {\n ready: errors.length === 0,\n version: validation.version,\n versionValid: validation.versionValid,\n syncValid: validation.syncValid,\n changelogValid: validation.changelogValid,\n gitRepository,\n hooksInstalled,\n worktreeClean,\n errors,\n };\n}\n\n/**\n * Synchronizes configured files to the current package version.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This reads the version from `package.json` and rewrites configured files\n * using the sync patterns defined in the VersionGuard config.\n *\n * @param config - VersionGuard configuration containing sync rules.\n * @param cwd - Project directory whose files should be synchronized.\n * @example\n * ```ts\n * import { getDefaultConfig, sync } from 'versionguard';\n *\n * sync(getDefaultConfig(), process.cwd());\n * ```\n */\nexport function sync(config: VersionGuardConfig, cwd: string = process.cwd()): void {\n const version = getPackageVersion(cwd);\n syncVersion(version, config.sync, cwd);\n}\n\n/**\n * Determines whether a project can move from one version to another.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * Both the current and proposed versions must validate against the configured\n * versioning scheme, and the new version must compare greater than the current\n * version.\n *\n * @param currentVersion - Version currently in use.\n * @param newVersion - Proposed next version.\n * @param config - VersionGuard configuration that defines version rules.\n * @returns An object indicating whether the bump is allowed and why it failed.\n * @example\n * ```ts\n * import { canBump, getDefaultConfig } from 'versionguard';\n *\n * const result = canBump('1.2.3', '1.3.0', getDefaultConfig());\n * ```\n */\nexport function canBump(\n currentVersion: string,\n newVersion: string,\n config: VersionGuardConfig,\n): { canBump: boolean; error?: string } {\n const currentValid = validateVersion(currentVersion, config);\n const newValid = validateVersion(newVersion, config);\n\n if (!currentValid.valid) {\n return { canBump: false, error: `Current version is invalid: ${currentVersion}` };\n }\n\n if (!newValid.valid) {\n return { canBump: false, error: `New version is invalid: ${newVersion}` };\n }\n\n if (config.versioning.type === 'semver') {\n if (!semver.gt(newVersion, currentVersion)) {\n return {\n canBump: false,\n error: `New version ${newVersion} must be greater than current ${currentVersion}`,\n };\n }\n } else {\n const calverConfig = getCalVerConfig(config);\n const currentParsed = calver.parse(currentVersion, calverConfig.format);\n const newParsed = calver.parse(newVersion, calverConfig.format);\n\n if (!currentParsed || !newParsed) {\n return { canBump: false, error: 'Failed to parse CalVer versions' };\n }\n\n if (calver.compare(newVersion, currentVersion, calverConfig.format) <= 0) {\n return {\n canBump: false,\n error: `New CalVer ${newVersion} must be newer than current ${currentVersion}`,\n };\n }\n }\n\n return { canBump: true };\n}\n\nfunction getCalVerConfig(config: VersionGuardConfig): CalVerConfig {\n if (!config.versioning.calver) {\n throw new Error('CalVer configuration is required when versioning.type is \"calver\"');\n }\n\n return config.versioning.calver;\n}\n\nfunction isWorktreeClean(cwd: string): boolean {\n try {\n return execSync('git status --porcelain', { cwd, encoding: 'utf-8' }).trim().length === 0;\n } catch {\n return false;\n }\n}\n"],"names":["parse","validate","format","compare","increment","getCalVerConfig","semver.parse","semver.validate","semver.compare","semver.increment","calver.parse","calver.getCurrentVersion","calver.validate","calver.compare","calver.increment","calver.format","validateSemVer","validateCalVer","semver.gt"],"mappings":"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"}
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwBpC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,IAAI,OAAO,CA8YvC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,MAAM,CAAC,IAAI,GAAE,MAAM,EAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAC1B,IAAI,GAAE,MAAM,EAAiB,EAC7B,OAAO,GAAE,MAAwB,GAChC,OAAO,CAGT"}
|
package/dist/cli.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import * as fs from "node:fs";
|
|
2
3
|
import * as path from "node:path";
|
|
3
4
|
import { fileURLToPath } from "node:url";
|
|
4
5
|
import chalk from "chalk";
|
|
5
6
|
import { Command } from "commander";
|
|
6
|
-
import { i as initConfig, g as getConfig, a as getPackageVersion, b as getVersionFeedback, v as validate, h as handlePostTag, c as getSyncFeedback, d as getChangelogFeedback, e as doctor, f as fixAll, j as fixSyncIssues, s as suggestNextVersion, k as setPackageVersion, l as createTag, m as installHooks, u as uninstallHooks, n as areHooksInstalled } from "./chunks/index-
|
|
7
|
+
import { i as initConfig, g as getConfig, a as getPackageVersion, b as getVersionFeedback, v as validate, h as handlePostTag, c as getSyncFeedback, d as getChangelogFeedback, e as doctor, f as fixAll, j as fixSyncIssues, s as suggestNextVersion, k as setPackageVersion, l as createTag, m as installHooks, u as uninstallHooks, n as areHooksInstalled } from "./chunks/index-C6jrxye7.js";
|
|
8
|
+
const CLI_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const CLI_VERSION = JSON.parse(fs.readFileSync(path.join(CLI_DIR, "..", "package.json"), "utf-8")).version;
|
|
7
10
|
const styles = {
|
|
8
11
|
error: chalk.red,
|
|
9
12
|
warning: chalk.yellow,
|
|
@@ -14,7 +17,7 @@ const styles = {
|
|
|
14
17
|
};
|
|
15
18
|
function createProgram() {
|
|
16
19
|
const program = new Command();
|
|
17
|
-
program.name("versionguard").description("Strict versioning enforcement for SemVer and CalVer").version(
|
|
20
|
+
program.name("versionguard").description("Strict versioning enforcement for SemVer and CalVer").version(CLI_VERSION);
|
|
18
21
|
program.command("init").description("Initialize VersionGuard configuration").option("-c, --cwd <path>", "Working directory", process.cwd()).action((options) => {
|
|
19
22
|
try {
|
|
20
23
|
const configPath = initConfig(options.cwd);
|
|
@@ -29,11 +32,30 @@ function createProgram() {
|
|
|
29
32
|
process.exit(1);
|
|
30
33
|
}
|
|
31
34
|
});
|
|
32
|
-
program.command("check").description("Check the current version with actionable feedback").option("-c, --cwd <path>", "Working directory", process.cwd()).option("--prev <version>", "Previous version for comparison").action((options) => {
|
|
35
|
+
program.command("check").description("Check the current version with actionable feedback").option("-c, --cwd <path>", "Working directory", process.cwd()).option("--prev <version>", "Previous version for comparison").option("--json", "Print machine-readable JSON output").action((options) => {
|
|
33
36
|
try {
|
|
34
37
|
const config = getConfig(options.cwd);
|
|
35
38
|
const version = getPackageVersion(options.cwd);
|
|
36
39
|
const result = getVersionFeedback(version, config, options.prev);
|
|
40
|
+
if (options.json) {
|
|
41
|
+
console.log(
|
|
42
|
+
JSON.stringify(
|
|
43
|
+
{
|
|
44
|
+
version,
|
|
45
|
+
versioningType: config.versioning.type,
|
|
46
|
+
valid: result.valid,
|
|
47
|
+
errors: result.errors,
|
|
48
|
+
suggestions: result.suggestions
|
|
49
|
+
},
|
|
50
|
+
null,
|
|
51
|
+
2
|
|
52
|
+
)
|
|
53
|
+
);
|
|
54
|
+
if (!result.valid) {
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
37
59
|
console.log(styles.bold(`Current version: ${version}`));
|
|
38
60
|
console.log(styles.dim(`Versioning type: ${config.versioning.type}`));
|
|
39
61
|
console.log("");
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport * as path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport chalk from 'chalk';\nimport { Command } from 'commander';\n\nimport * as feedback from './feedback';\nimport * as fix from './fix';\nimport * as versionguard from './index';\nimport * as project from './project';\nimport * as tag from './tag';\n\nconst styles = {\n error: chalk.red,\n warning: chalk.yellow,\n success: chalk.green,\n info: chalk.blue,\n dim: chalk.gray,\n bold: chalk.bold,\n};\n\n/**\n * Creates the VersionGuard CLI program definition.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This function wires all commands, options, and handlers onto a fresh Commander\n * program instance without parsing arguments yet.\n *\n * @returns A configured Commander program for the VersionGuard CLI.\n *\n * @example\n * ```typescript\n * const program = createProgram();\n * console.log(program.name());\n * ```\n */\nexport function createProgram(): Command {\n const program = new Command();\n\n program\n .name('versionguard')\n .description('Strict versioning enforcement for SemVer and CalVer')\n .version('0.1.0');\n\n program\n .command('init')\n .description('Initialize VersionGuard configuration')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action((options: { cwd: string }) => {\n try {\n const configPath = versionguard.initConfig(options.cwd);\n console.log(styles.success(`✓ Created ${path.relative(options.cwd, configPath)}`));\n console.log('');\n console.log(styles.info('Next steps:'));\n console.log(' 1. Edit .versionguard.yml to set your versioning type');\n console.log(' 2. Run: npx versionguard hooks install');\n console.log(' 3. Run: npx versionguard check');\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n program\n .command('check')\n .description('Check the current version with actionable feedback')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .option('--prev <version>', 'Previous version for comparison')\n .action((options: { cwd: string; prev?: string }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const version = versionguard.getPackageVersion(options.cwd);\n const result = feedback.getVersionFeedback(version, config, options.prev);\n\n console.log(styles.bold(`Current version: ${version}`));\n console.log(styles.dim(`Versioning type: ${config.versioning.type}`));\n console.log('');\n\n if (result.valid) {\n console.log(styles.success('✓ Version is valid'));\n return;\n }\n\n console.log(styles.error('✗ Version has issues:'));\n console.log('');\n for (const error of result.errors) {\n console.log(styles.error(` ✗ ${error.message}`));\n }\n if (result.suggestions.length > 0) {\n console.log('');\n console.log(styles.info('How to fix:'));\n for (const suggestion of result.suggestions) {\n console.log(` → ${suggestion.message}`);\n if (suggestion.fix) {\n console.log(styles.dim(` Run: ${suggestion.fix}`));\n }\n }\n }\n process.exit(1);\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n program\n .command('validate')\n .description('Run full validation with smart feedback')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .option('--hook <name>', 'Running as git hook')\n .option('--json', 'Print machine-readable JSON output')\n .action((options: { cwd: string; hook?: string; json?: boolean }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const version = versionguard.getPackageVersion(options.cwd);\n const result = versionguard.validate(config, options.cwd);\n\n let postTagResult: { success: boolean; message: string; actions: string[] } | undefined;\n\n if (options.hook === 'post-tag') {\n postTagResult = tag.handlePostTag(config, options.cwd);\n }\n\n if (options.json) {\n console.log(\n JSON.stringify(\n {\n ...result,\n hook: options.hook ?? null,\n postTag: postTagResult ?? null,\n },\n null,\n 2,\n ),\n );\n\n if (!result.valid || (postTagResult && !postTagResult.success)) {\n process.exit(1);\n }\n\n return;\n }\n\n console.log(styles.bold(`Validating version ${version}...`));\n console.log('');\n\n if (!result.syncValid) {\n console.log(styles.error('Sync Issues:'));\n for (const error of result.errors.filter((item) => item.includes('mismatch'))) {\n const parts = error.match(\n /Version mismatch in (.+):(\\d+) - found \"(.+?)\" but expected \"(.+?)\"/,\n );\n if (!parts) {\n continue;\n }\n const suggestions = feedback.getSyncFeedback(parts[1], parts[3], parts[4]);\n console.log(styles.error(` ✗ ${parts[1]} has wrong version`));\n console.log(styles.dim(` Found: \"${parts[3]}\" Expected: \"${parts[4]}\"`));\n if (suggestions[0]?.fix) {\n console.log(styles.info(` Fix: ${suggestions[0].fix}`));\n }\n }\n console.log('');\n }\n\n if (config.changelog.enabled && !result.changelogValid) {\n console.log(styles.error('Changelog Issues:'));\n for (const error of result.errors.filter((item) =>\n item.toLowerCase().includes('changelog'),\n )) {\n console.log(styles.error(` ✗ ${error}`));\n }\n const suggestions = feedback.getChangelogFeedback(false, version);\n if (suggestions[0]?.fix) {\n console.log(styles.info(`Fix: ${suggestions[0].fix}`));\n }\n console.log('');\n }\n\n if (postTagResult) {\n if (!postTagResult.success) {\n console.log(styles.error(`✗ ${postTagResult.message}`));\n process.exit(1);\n }\n }\n\n if (!result.valid) {\n console.log(styles.error('✗ Validation failed'));\n process.exit(1);\n }\n\n console.log(styles.success('✓ All validations passed'));\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n program\n .command('doctor')\n .description('Report repository readiness in one pass')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .option('--json', 'Print machine-readable JSON output')\n .action((options: { cwd: string; json?: boolean }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const report = versionguard.doctor(config, options.cwd);\n\n if (options.json) {\n console.log(JSON.stringify(report, null, 2));\n if (!report.ready) {\n process.exit(1);\n }\n return;\n }\n\n console.log(styles.bold('VersionGuard Doctor'));\n console.log(` Version: ${report.version || '(missing)'}`);\n console.log(` Version valid: ${report.versionValid ? 'yes' : 'no'}`);\n console.log(` Files in sync: ${report.syncValid ? 'yes' : 'no'}`);\n console.log(` Changelog ready: ${report.changelogValid ? 'yes' : 'no'}`);\n console.log(` Git repository: ${report.gitRepository ? 'yes' : 'no'}`);\n console.log(\n ` Hooks installed: ${report.gitRepository ? (report.hooksInstalled ? 'yes' : 'no') : 'n/a'}`,\n );\n console.log(\n ` Worktree clean: ${report.gitRepository ? (report.worktreeClean ? 'yes' : 'no') : 'n/a'}`,\n );\n\n if (!report.ready) {\n console.log('');\n console.log(styles.error('Issues:'));\n for (const error of report.errors) {\n console.log(styles.error(` ✗ ${error}`));\n }\n process.exit(1);\n }\n\n console.log('');\n console.log(styles.success('✓ Repository is ready'));\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n program\n .command('fix')\n .description('Auto-fix detected issues')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action((options: { cwd: string }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const version = versionguard.getPackageVersion(options.cwd);\n const results = fix.fixAll(config, version, options.cwd);\n\n console.log(styles.bold(`Fixing issues for version ${version}...`));\n console.log('');\n\n for (const result of results) {\n const printer = result.fixed ? styles.success : styles.dim;\n console.log(printer(`${result.fixed ? '✓' : '•'} ${result.message}`));\n }\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n program\n .command('sync')\n .description('Sync version to all configured files')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action((options: { cwd: string }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const version = versionguard.getPackageVersion(options.cwd);\n const results = fix.fixSyncIssues(config, options.cwd);\n\n console.log(styles.bold(`Syncing version ${version}...`));\n for (const result of results) {\n const printer = result.fixed ? styles.success : styles.dim;\n console.log(printer(`${result.fixed ? '✓' : '•'} ${result.message}`));\n }\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n program\n .command('bump')\n .description('Suggest and optionally apply the next version')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .option('-t, --type <type>', 'Bump type (major, minor, patch, auto)')\n .option('--apply', 'Apply the first suggested version')\n .action(\n (options: { cwd: string; type?: 'major' | 'minor' | 'patch' | 'auto'; apply?: boolean }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const currentVersion = versionguard.getPackageVersion(options.cwd);\n const suggestions = fix.suggestNextVersion(currentVersion, config, options.type);\n\n console.log(styles.bold(`Current version: ${currentVersion}`));\n console.log('');\n for (const [index, suggestion] of suggestions.entries()) {\n console.log(` ${index + 1}. ${styles.bold(suggestion.version)}`);\n console.log(` ${styles.dim(suggestion.reason)}`);\n }\n\n if (options.apply) {\n const nextVersion = suggestions[0]?.version;\n if (!nextVersion) {\n throw new Error('No version suggestion available');\n }\n project.setPackageVersion(nextVersion, options.cwd);\n fix.fixAll(config, nextVersion, options.cwd);\n console.log(styles.success(`✓ Updated to ${nextVersion}`));\n }\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n },\n );\n\n program\n .command('tag')\n .description('Create a git tag with automation')\n .argument('[version]', 'Version to tag (defaults to package.json version)')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .option('-m, --message <msg>', 'Tag message')\n .option('--no-fix', 'Skip auto-fixing files before tagging')\n .action(\n (version: string | undefined, options: { cwd: string; message?: string; fix?: boolean }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const tagVersion = version || versionguard.getPackageVersion(options.cwd);\n const result = tag.createTag(\n tagVersion,\n options.message,\n options.fix !== false,\n config,\n options.cwd,\n );\n\n if (!result.success) {\n console.log(styles.error(`✗ ${result.message}`));\n process.exit(1);\n }\n\n console.log(styles.success(`✓ ${result.message}`));\n for (const action of result.actions) {\n console.log(` • ${action}`);\n }\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n },\n );\n\n const hooksCommand = program.command('hooks').description('Manage git hooks');\n\n hooksCommand\n .command('install')\n .description('Install git hooks')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action((options: { cwd: string }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n versionguard.installHooks(config.git, options.cwd);\n console.log(styles.success('✓ Git hooks installed'));\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n hooksCommand\n .command('uninstall')\n .description('Uninstall git hooks')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action((options: { cwd: string }) => {\n try {\n versionguard.uninstallHooks(options.cwd);\n console.log(styles.success('✓ Git hooks uninstalled'));\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n hooksCommand\n .command('status')\n .description('Check if hooks are installed')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action((options: { cwd: string }) => {\n try {\n if (versionguard.areHooksInstalled(options.cwd)) {\n console.log(styles.success('✓ VersionGuard hooks are installed'));\n return;\n }\n\n console.log(styles.warning('✗ VersionGuard hooks are not installed'));\n process.exit(1);\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n return program;\n}\n\n/**\n * Parses CLI arguments and executes the matching command.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper delegates argument parsing to the Commander program created by\n * {@link createProgram}. It resolves when the selected command finishes.\n *\n * @param argv - Full argument vector to parse.\n * @see {@link createProgram}\n *\n * @example\n * ```typescript\n * const argv = ['node', 'versionguard', 'check'];\n * await runCli(argv);\n * ```\n */\nexport async function runCli(argv: string[] = process.argv): Promise<void> {\n await createProgram().parseAsync(argv);\n}\n\n/**\n * Determines whether the current module is the invoked CLI entry point.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper compares the resolved script path from `argv` with the current\n * module URL so the CLI runs only during direct execution.\n *\n * @param argv - Full process argument vector.\n * @param metaUrl - Module URL to compare against the invoked entry path.\n * @returns `true` when the current module should launch the CLI.\n *\n * @example\n * ```typescript\n * const shouldRun = shouldRunCli(process.argv, import.meta.url);\n * console.log(shouldRun);\n * ```\n */\nexport function shouldRunCli(\n argv: string[] = process.argv,\n metaUrl: string = import.meta.url,\n): boolean {\n const entryPath = argv[1] ? path.resolve(argv[1]) : null;\n return entryPath === fileURLToPath(metaUrl);\n}\n\n/* v8 ignore start -- exercised only by direct CLI execution */\nif (shouldRunCli()) {\n void runCli();\n}\n/* v8 ignore stop */\n"],"names":["versionguard.initConfig","versionguard.getConfig","versionguard.getPackageVersion","feedback.getVersionFeedback","versionguard.validate","tag.handlePostTag","feedback.getSyncFeedback","feedback.getChangelogFeedback","versionguard.doctor","fix.fixAll","fix.fixSyncIssues","fix.suggestNextVersion","project.setPackageVersion","tag.createTag","versionguard.installHooks","versionguard.uninstallHooks","versionguard.areHooksInstalled"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport chalk from 'chalk';\nimport { Command } from 'commander';\n\nconst CLI_DIR = path.dirname(fileURLToPath(import.meta.url));\nconst CLI_VERSION: string = (\n JSON.parse(fs.readFileSync(path.join(CLI_DIR, '..', 'package.json'), 'utf-8')) as {\n version: string;\n }\n).version;\n\nimport * as feedback from './feedback';\nimport * as fix from './fix';\nimport * as versionguard from './index';\nimport * as project from './project';\nimport * as tag from './tag';\n\nconst styles = {\n error: chalk.red,\n warning: chalk.yellow,\n success: chalk.green,\n info: chalk.blue,\n dim: chalk.gray,\n bold: chalk.bold,\n};\n\n/**\n * Creates the VersionGuard CLI program definition.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This function wires all commands, options, and handlers onto a fresh Commander\n * program instance without parsing arguments yet.\n *\n * @returns A configured Commander program for the VersionGuard CLI.\n *\n * @example\n * ```typescript\n * const program = createProgram();\n * console.log(program.name());\n * ```\n */\nexport function createProgram(): Command {\n const program = new Command();\n\n program\n .name('versionguard')\n .description('Strict versioning enforcement for SemVer and CalVer')\n .version(CLI_VERSION);\n\n program\n .command('init')\n .description('Initialize VersionGuard configuration')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action((options: { cwd: string }) => {\n try {\n const configPath = versionguard.initConfig(options.cwd);\n console.log(styles.success(`✓ Created ${path.relative(options.cwd, configPath)}`));\n console.log('');\n console.log(styles.info('Next steps:'));\n console.log(' 1. Edit .versionguard.yml to set your versioning type');\n console.log(' 2. Run: npx versionguard hooks install');\n console.log(' 3. Run: npx versionguard check');\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n program\n .command('check')\n .description('Check the current version with actionable feedback')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .option('--prev <version>', 'Previous version for comparison')\n .option('--json', 'Print machine-readable JSON output')\n .action((options: { cwd: string; prev?: string; json?: boolean }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const version = versionguard.getPackageVersion(options.cwd);\n const result = feedback.getVersionFeedback(version, config, options.prev);\n\n if (options.json) {\n console.log(\n JSON.stringify(\n {\n version,\n versioningType: config.versioning.type,\n valid: result.valid,\n errors: result.errors,\n suggestions: result.suggestions,\n },\n null,\n 2,\n ),\n );\n if (!result.valid) {\n process.exit(1);\n }\n return;\n }\n\n console.log(styles.bold(`Current version: ${version}`));\n console.log(styles.dim(`Versioning type: ${config.versioning.type}`));\n console.log('');\n\n if (result.valid) {\n console.log(styles.success('✓ Version is valid'));\n return;\n }\n\n console.log(styles.error('✗ Version has issues:'));\n console.log('');\n for (const error of result.errors) {\n console.log(styles.error(` ✗ ${error.message}`));\n }\n if (result.suggestions.length > 0) {\n console.log('');\n console.log(styles.info('How to fix:'));\n for (const suggestion of result.suggestions) {\n console.log(` → ${suggestion.message}`);\n if (suggestion.fix) {\n console.log(styles.dim(` Run: ${suggestion.fix}`));\n }\n }\n }\n process.exit(1);\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n program\n .command('validate')\n .description('Run full validation with smart feedback')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .option('--hook <name>', 'Running as git hook')\n .option('--json', 'Print machine-readable JSON output')\n .action((options: { cwd: string; hook?: string; json?: boolean }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const version = versionguard.getPackageVersion(options.cwd);\n const result = versionguard.validate(config, options.cwd);\n\n let postTagResult: { success: boolean; message: string; actions: string[] } | undefined;\n\n if (options.hook === 'post-tag') {\n postTagResult = tag.handlePostTag(config, options.cwd);\n }\n\n if (options.json) {\n console.log(\n JSON.stringify(\n {\n ...result,\n hook: options.hook ?? null,\n postTag: postTagResult ?? null,\n },\n null,\n 2,\n ),\n );\n\n if (!result.valid || (postTagResult && !postTagResult.success)) {\n process.exit(1);\n }\n\n return;\n }\n\n console.log(styles.bold(`Validating version ${version}...`));\n console.log('');\n\n if (!result.syncValid) {\n console.log(styles.error('Sync Issues:'));\n for (const error of result.errors.filter((item) => item.includes('mismatch'))) {\n const parts = error.match(\n /Version mismatch in (.+):(\\d+) - found \"(.+?)\" but expected \"(.+?)\"/,\n );\n if (!parts) {\n continue;\n }\n const suggestions = feedback.getSyncFeedback(parts[1], parts[3], parts[4]);\n console.log(styles.error(` ✗ ${parts[1]} has wrong version`));\n console.log(styles.dim(` Found: \"${parts[3]}\" Expected: \"${parts[4]}\"`));\n if (suggestions[0]?.fix) {\n console.log(styles.info(` Fix: ${suggestions[0].fix}`));\n }\n }\n console.log('');\n }\n\n if (config.changelog.enabled && !result.changelogValid) {\n console.log(styles.error('Changelog Issues:'));\n for (const error of result.errors.filter((item) =>\n item.toLowerCase().includes('changelog'),\n )) {\n console.log(styles.error(` ✗ ${error}`));\n }\n const suggestions = feedback.getChangelogFeedback(false, version);\n if (suggestions[0]?.fix) {\n console.log(styles.info(`Fix: ${suggestions[0].fix}`));\n }\n console.log('');\n }\n\n if (postTagResult) {\n if (!postTagResult.success) {\n console.log(styles.error(`✗ ${postTagResult.message}`));\n process.exit(1);\n }\n }\n\n if (!result.valid) {\n console.log(styles.error('✗ Validation failed'));\n process.exit(1);\n }\n\n console.log(styles.success('✓ All validations passed'));\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n program\n .command('doctor')\n .description('Report repository readiness in one pass')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .option('--json', 'Print machine-readable JSON output')\n .action((options: { cwd: string; json?: boolean }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const report = versionguard.doctor(config, options.cwd);\n\n if (options.json) {\n console.log(JSON.stringify(report, null, 2));\n if (!report.ready) {\n process.exit(1);\n }\n return;\n }\n\n console.log(styles.bold('VersionGuard Doctor'));\n console.log(` Version: ${report.version || '(missing)'}`);\n console.log(` Version valid: ${report.versionValid ? 'yes' : 'no'}`);\n console.log(` Files in sync: ${report.syncValid ? 'yes' : 'no'}`);\n console.log(` Changelog ready: ${report.changelogValid ? 'yes' : 'no'}`);\n console.log(` Git repository: ${report.gitRepository ? 'yes' : 'no'}`);\n console.log(\n ` Hooks installed: ${report.gitRepository ? (report.hooksInstalled ? 'yes' : 'no') : 'n/a'}`,\n );\n console.log(\n ` Worktree clean: ${report.gitRepository ? (report.worktreeClean ? 'yes' : 'no') : 'n/a'}`,\n );\n\n if (!report.ready) {\n console.log('');\n console.log(styles.error('Issues:'));\n for (const error of report.errors) {\n console.log(styles.error(` ✗ ${error}`));\n }\n process.exit(1);\n }\n\n console.log('');\n console.log(styles.success('✓ Repository is ready'));\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n program\n .command('fix')\n .description('Auto-fix detected issues')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action((options: { cwd: string }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const version = versionguard.getPackageVersion(options.cwd);\n const results = fix.fixAll(config, version, options.cwd);\n\n console.log(styles.bold(`Fixing issues for version ${version}...`));\n console.log('');\n\n for (const result of results) {\n const printer = result.fixed ? styles.success : styles.dim;\n console.log(printer(`${result.fixed ? '✓' : '•'} ${result.message}`));\n }\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n program\n .command('sync')\n .description('Sync version to all configured files')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action((options: { cwd: string }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const version = versionguard.getPackageVersion(options.cwd);\n const results = fix.fixSyncIssues(config, options.cwd);\n\n console.log(styles.bold(`Syncing version ${version}...`));\n for (const result of results) {\n const printer = result.fixed ? styles.success : styles.dim;\n console.log(printer(`${result.fixed ? '✓' : '•'} ${result.message}`));\n }\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n program\n .command('bump')\n .description('Suggest and optionally apply the next version')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .option('-t, --type <type>', 'Bump type (major, minor, patch, auto)')\n .option('--apply', 'Apply the first suggested version')\n .action(\n (options: { cwd: string; type?: 'major' | 'minor' | 'patch' | 'auto'; apply?: boolean }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const currentVersion = versionguard.getPackageVersion(options.cwd);\n const suggestions = fix.suggestNextVersion(currentVersion, config, options.type);\n\n console.log(styles.bold(`Current version: ${currentVersion}`));\n console.log('');\n for (const [index, suggestion] of suggestions.entries()) {\n console.log(` ${index + 1}. ${styles.bold(suggestion.version)}`);\n console.log(` ${styles.dim(suggestion.reason)}`);\n }\n\n if (options.apply) {\n const nextVersion = suggestions[0]?.version;\n if (!nextVersion) {\n throw new Error('No version suggestion available');\n }\n project.setPackageVersion(nextVersion, options.cwd);\n fix.fixAll(config, nextVersion, options.cwd);\n console.log(styles.success(`✓ Updated to ${nextVersion}`));\n }\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n },\n );\n\n program\n .command('tag')\n .description('Create a git tag with automation')\n .argument('[version]', 'Version to tag (defaults to package.json version)')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .option('-m, --message <msg>', 'Tag message')\n .option('--no-fix', 'Skip auto-fixing files before tagging')\n .action(\n (version: string | undefined, options: { cwd: string; message?: string; fix?: boolean }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const tagVersion = version || versionguard.getPackageVersion(options.cwd);\n const result = tag.createTag(\n tagVersion,\n options.message,\n options.fix !== false,\n config,\n options.cwd,\n );\n\n if (!result.success) {\n console.log(styles.error(`✗ ${result.message}`));\n process.exit(1);\n }\n\n console.log(styles.success(`✓ ${result.message}`));\n for (const action of result.actions) {\n console.log(` • ${action}`);\n }\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n },\n );\n\n const hooksCommand = program.command('hooks').description('Manage git hooks');\n\n hooksCommand\n .command('install')\n .description('Install git hooks')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action((options: { cwd: string }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n versionguard.installHooks(config.git, options.cwd);\n console.log(styles.success('✓ Git hooks installed'));\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n hooksCommand\n .command('uninstall')\n .description('Uninstall git hooks')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action((options: { cwd: string }) => {\n try {\n versionguard.uninstallHooks(options.cwd);\n console.log(styles.success('✓ Git hooks uninstalled'));\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n hooksCommand\n .command('status')\n .description('Check if hooks are installed')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action((options: { cwd: string }) => {\n try {\n if (versionguard.areHooksInstalled(options.cwd)) {\n console.log(styles.success('✓ VersionGuard hooks are installed'));\n return;\n }\n\n console.log(styles.warning('✗ VersionGuard hooks are not installed'));\n process.exit(1);\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n return program;\n}\n\n/**\n * Parses CLI arguments and executes the matching command.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper delegates argument parsing to the Commander program created by\n * {@link createProgram}. It resolves when the selected command finishes.\n *\n * @param argv - Full argument vector to parse.\n * @see {@link createProgram}\n *\n * @example\n * ```typescript\n * const argv = ['node', 'versionguard', 'check'];\n * await runCli(argv);\n * ```\n */\nexport async function runCli(argv: string[] = process.argv): Promise<void> {\n await createProgram().parseAsync(argv);\n}\n\n/**\n * Determines whether the current module is the invoked CLI entry point.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper compares the resolved script path from `argv` with the current\n * module URL so the CLI runs only during direct execution.\n *\n * @param argv - Full process argument vector.\n * @param metaUrl - Module URL to compare against the invoked entry path.\n * @returns `true` when the current module should launch the CLI.\n *\n * @example\n * ```typescript\n * const shouldRun = shouldRunCli(process.argv, import.meta.url);\n * console.log(shouldRun);\n * ```\n */\nexport function shouldRunCli(\n argv: string[] = process.argv,\n metaUrl: string = import.meta.url,\n): boolean {\n const entryPath = argv[1] ? path.resolve(argv[1]) : null;\n return entryPath === fileURLToPath(metaUrl);\n}\n\n/* v8 ignore start -- exercised only by direct CLI execution */\nif (shouldRunCli()) {\n void runCli();\n}\n/* v8 ignore stop */\n"],"names":["versionguard.initConfig","versionguard.getConfig","versionguard.getPackageVersion","feedback.getVersionFeedback","versionguard.validate","tag.handlePostTag","feedback.getSyncFeedback","feedback.getChangelogFeedback","versionguard.doctor","fix.fixAll","fix.fixSyncIssues","fix.suggestNextVersion","project.setPackageVersion","tag.createTag","versionguard.installHooks","versionguard.uninstallHooks","versionguard.areHooksInstalled"],"mappings":"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"}
|
package/dist/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,QAAA,MAAM,UAAU,iDAAkD,CAAC;AAEnE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,GAAE,MAAsB,GAAG,IAAI,CAejF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAsB,GAAG,IAAI,CAahE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAerD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAUtE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,QAAA,MAAM,UAAU,iDAAkD,CAAC;AAEnE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,GAAE,MAAsB,GAAG,IAAI,CAejF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAsB,GAAG,IAAI,CAahE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAerD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAUtE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,GAAG,MAAM,CAYhF"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "node:child_process";
|
|
2
2
|
import "node:path";
|
|
3
|
-
import { n, o, p, q, l, e, f, r, t, j, w, d, g, x, a, c, y, b, h, i, m, z, s, A, B, C, u, v, D, E, F } from "./chunks/index-
|
|
3
|
+
import { n, o, p, q, l, e, f, r, t, j, w, d, g, x, a, c, y, b, h, i, m, z, s, A, B, C, u, v, D, E, F } from "./chunks/index-C6jrxye7.js";
|
|
4
4
|
export {
|
|
5
5
|
n as areHooksInstalled,
|
|
6
6
|
o as calver,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codluv/versionguard",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Strict versioning enforcement for SemVer and CalVer with git hooks, changelog validation, and file sync from package.json",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -31,6 +31,10 @@
|
|
|
31
31
|
"forge:build": "forge-ts build",
|
|
32
32
|
"forge:docs:init": "forge-ts init docs",
|
|
33
33
|
"forge:doctor": "forge-ts doctor",
|
|
34
|
+
"vg:check": "versionguard check",
|
|
35
|
+
"vg:validate": "versionguard validate",
|
|
36
|
+
"vg:doctor": "versionguard doctor",
|
|
37
|
+
"vg:sync": "versionguard sync",
|
|
34
38
|
"lint": "npm run lint:biome && npm run lint:eslint",
|
|
35
39
|
"lint:biome": "biome check .",
|
|
36
40
|
"lint:eslint": "eslint .",
|
|
@@ -69,6 +73,7 @@
|
|
|
69
73
|
"@biomejs/biome": "^2.2.4",
|
|
70
74
|
"@changesets/changelog-github": "^0.6.0",
|
|
71
75
|
"@changesets/cli": "^2.30.0",
|
|
76
|
+
"@codluv/versionguard": "^0.1.1",
|
|
72
77
|
"@eslint/js": "^9.37.0",
|
|
73
78
|
"@forge-ts/cli": "0.19.4",
|
|
74
79
|
"@types/js-yaml": "^4.0.9",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-DPBYoIRi.js","sources":["../../src/calver.ts","../../src/changelog.ts","../../src/hooks.ts","../../src/project.ts","../../src/semver.ts","../../src/sync.ts","../../src/config.ts","../../src/feedback/index.ts","../../src/fix/index.ts","../../src/tag/index.ts","../../src/index.ts"],"sourcesContent":["/**\n * Calendar version parsing, formatting, and comparison helpers.\n *\n * @packageDocumentation\n */\n\nimport type { CalVer, CalVerFormat, ValidationError, ValidationResult } from './types';\n\n/**\n * Parsed token layout for a supported CalVer format string.\n *\n * @public\n * @since 0.1.0\n * @forgeIgnore E020\n */\nexport interface ParsedCalVerFormat {\n /**\n * Year token captured from the format string.\n */\n year: 'YYYY' | 'YY';\n\n /**\n * Month token captured from the format string.\n */\n month: 'MM' | 'M' | '0M';\n\n /**\n * Day token captured from the format string when present.\n *\n * @defaultValue undefined\n */\n day?: 'DD' | 'D' | '0D';\n\n /**\n * Patch token captured from the format string when present.\n *\n * @defaultValue undefined\n */\n patch?: 'PATCH';\n}\n\n/**\n * Breaks a CalVer format string into its component tokens.\n *\n * @remarks\n * This helper is used internally by parsing, formatting, and version generation helpers\n * to decide which date parts or patch counters are present in a given CalVer layout.\n *\n * @param calverFormat - Format string to inspect.\n * @returns The parsed token definition for the requested format.\n *\n * @example\n * ```ts\n * import { parseFormat } from 'versionguard';\n *\n * parseFormat('YYYY.MM.PATCH');\n * // => { year: 'YYYY', month: 'MM', patch: 'PATCH' }\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function parseFormat(calverFormat: CalVerFormat): ParsedCalVerFormat {\n const parts = calverFormat.split('.');\n const result: ParsedCalVerFormat = {\n year: parts[0] as ParsedCalVerFormat['year'],\n month: parts[1] as ParsedCalVerFormat['month'],\n };\n\n if (parts[2] === 'PATCH') {\n result.patch = 'PATCH';\n } else if (parts[2]) {\n result.day = parts[2] as ParsedCalVerFormat['day'];\n }\n\n if (parts[3] === 'PATCH') {\n result.patch = 'PATCH';\n }\n\n return result;\n}\n\nfunction tokenPattern(token: string): string {\n switch (token) {\n case 'YYYY':\n return '(\\\\d{4})';\n case 'YY':\n return '(\\\\d{2})';\n case '0M':\n case '0D':\n return '(\\\\d{2})';\n case 'MM':\n case 'DD':\n case 'M':\n case 'D':\n return '(\\\\d{1,2})';\n case 'PATCH':\n return '(\\\\d+)';\n default:\n throw new Error(`Unsupported CalVer token: ${token}`);\n }\n}\n\n/**\n * Builds a regular expression that matches a supported CalVer format.\n *\n * @remarks\n * The returned regular expression is anchored to the start and end of the string so it can\n * be used directly for strict validation of a complete version value.\n *\n * @param calverFormat - Format string to convert into a regular expression.\n * @returns A strict regular expression for the supplied CalVer format.\n *\n * @example\n * ```ts\n * import { getRegexForFormat } from 'versionguard';\n *\n * getRegexForFormat('YYYY.0M.0D').test('2026.03.21');\n * // => true\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function getRegexForFormat(calverFormat: CalVerFormat): RegExp {\n const tokens = calverFormat.split('.');\n const pattern = tokens.map(tokenPattern).join('\\\\.');\n return new RegExp(`^${pattern}$`);\n}\n\n/**\n * Parses a CalVer string using the supplied format.\n *\n * @remarks\n * The parser returns `null` when the string does not structurally match the requested format.\n * It does not enforce range rules such as future-date rejection; use {@link validate} for that.\n *\n * @param version - Version string to parse.\n * @param calverFormat - Format expected for the version string.\n * @returns Parsed CalVer components, or `null` when the string does not match the format.\n *\n * @example\n * ```ts\n * import { parse } from 'versionguard';\n *\n * parse('2026.03.21', 'YYYY.0M.0D')?.month;\n * // => 3\n * ```\n *\n * @see {@link validate} to apply date-range and future-date validation.\n * @public\n * @since 0.1.0\n */\nexport function parse(version: string, calverFormat: CalVerFormat): CalVer | null {\n const match = version.match(getRegexForFormat(calverFormat));\n\n if (!match) {\n return null;\n }\n\n const definition = parseFormat(calverFormat);\n const year =\n definition.year === 'YYYY'\n ? Number.parseInt(match[1], 10)\n : 2000 + Number.parseInt(match[1], 10);\n const month = Number.parseInt(match[2], 10);\n\n let cursor = 3;\n let day: number | undefined;\n let patch: number | undefined;\n\n if (definition.day) {\n day = Number.parseInt(match[cursor], 10);\n cursor += 1;\n }\n\n if (definition.patch) {\n patch = Number.parseInt(match[cursor], 10);\n }\n\n return {\n year,\n month,\n day,\n patch,\n format: calverFormat,\n raw: version,\n };\n}\n\n/**\n * Validates a CalVer string against formatting and date rules.\n *\n * @remarks\n * Validation checks the requested CalVer format, month and day ranges, and optionally rejects\n * future dates relative to the current system date.\n *\n * @param version - Version string to validate.\n * @param calverFormat - Format expected for the version string.\n * @param preventFutureDates - Whether future dates should be reported as errors.\n * @returns A validation result containing any discovered errors and the parsed version on success.\n *\n * @example\n * ```ts\n * import { validate } from 'versionguard';\n *\n * validate('2026.03.21', 'YYYY.0M.0D', false).valid;\n * // => true\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function validate(\n version: string,\n calverFormat: CalVerFormat,\n preventFutureDates: boolean = true,\n): ValidationResult {\n const errors: ValidationError[] = [];\n const parsed = parse(version, calverFormat);\n\n if (!parsed) {\n return {\n valid: false,\n errors: [\n {\n message: `Invalid CalVer format: \"${version}\". Expected format: ${calverFormat}`,\n severity: 'error',\n },\n ],\n };\n }\n\n if (parsed.month < 1 || parsed.month > 12) {\n errors.push({\n message: `Invalid month: ${parsed.month}. Must be between 1 and 12.`,\n severity: 'error',\n });\n }\n\n if (parsed.day !== undefined) {\n if (parsed.day < 1 || parsed.day > 31) {\n errors.push({\n message: `Invalid day: ${parsed.day}. Must be between 1 and 31.`,\n severity: 'error',\n });\n } else {\n const daysInMonth = new Date(parsed.year, parsed.month, 0).getDate();\n if (parsed.day > daysInMonth) {\n errors.push({\n message: `Invalid day: ${parsed.day}. ${parsed.year}-${String(parsed.month).padStart(2, '0')} has only ${daysInMonth} days.`,\n severity: 'error',\n });\n }\n }\n }\n\n if (preventFutureDates) {\n const now = new Date();\n const currentYear = now.getFullYear();\n const currentMonth = now.getMonth() + 1;\n const currentDay = now.getDate();\n\n if (parsed.year > currentYear) {\n errors.push({\n message: `Future year not allowed: ${parsed.year}. Current year is ${currentYear}.`,\n severity: 'error',\n });\n } else if (parsed.year === currentYear && parsed.month > currentMonth) {\n errors.push({\n message: `Future month not allowed: ${parsed.year}.${parsed.month}. Current month is ${currentMonth}.`,\n severity: 'error',\n });\n } else if (\n parsed.year === currentYear &&\n parsed.month === currentMonth &&\n parsed.day !== undefined &&\n parsed.day > currentDay\n ) {\n errors.push({\n message: `Future day not allowed: ${parsed.year}.${parsed.month}.${parsed.day}. Current day is ${currentDay}.`,\n severity: 'error',\n });\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n version: { type: 'calver', version: parsed },\n };\n}\n\nfunction formatToken(token: string, value: number): string {\n if (token === '0M' || token === '0D') {\n return String(value).padStart(2, '0');\n }\n\n if (token === 'YY') {\n return String(value % 100).padStart(2, '0');\n }\n\n return String(value);\n}\n\n/**\n * Formats a parsed CalVer object back into a version string.\n *\n * @remarks\n * Missing `day` and `patch` values fall back to `1` and `0` respectively when the selected\n * format requires those tokens.\n *\n * @param version - Parsed CalVer value to serialize.\n * @returns The formatted CalVer string.\n *\n * @example\n * ```ts\n * import { format } from 'versionguard';\n *\n * const version = { year: 2026, month: 3, day: 21, format: 'YYYY.0M.0D', raw: '2026.03.21' };\n *\n * format(version);\n * // => '2026.03.21'\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function format(version: CalVer): string {\n const tokens = version.format.split('.');\n const values: number[] = [version.year, version.month];\n\n if (tokens.includes('DD') || tokens.includes('D') || tokens.includes('0D')) {\n values.push(version.day ?? 1);\n }\n\n if (tokens.includes('PATCH')) {\n values.push(version.patch ?? 0);\n }\n\n return tokens.map((token, index) => formatToken(token, values[index])).join('.');\n}\n\n/**\n * Creates the current CalVer string for a format.\n *\n * @remarks\n * This helper derives its values from the provided date and initializes any patch token to `0`.\n * It is useful for generating a same-day baseline before incrementing patch-based formats.\n *\n * @param calverFormat - Format to generate.\n * @param now - Date used as the source for year, month, and day values.\n * @returns The current version string for the requested format.\n *\n * @example\n * ```ts\n * import { getCurrentVersion } from 'versionguard';\n *\n * getCurrentVersion('YYYY.MM.PATCH', new Date('2026-03-21T00:00:00Z'));\n * // => '2026.3.0'\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function getCurrentVersion(calverFormat: CalVerFormat, now: Date = new Date()): string {\n const definition = parseFormat(calverFormat);\n const currentDay = now.getDate();\n const base: CalVer = {\n year: now.getFullYear(),\n month: now.getMonth() + 1,\n day: definition.day ? currentDay : undefined,\n patch: definition.patch ? 0 : undefined,\n format: calverFormat,\n raw: '',\n };\n const day = base.day ?? currentDay;\n const patch = base.patch ?? 0;\n\n return formatToken(definition.year, base.year)\n .concat(`.${formatToken(definition.month, base.month)}`)\n .concat(definition.day ? `.${formatToken(definition.day, day)}` : '')\n .concat(definition.patch ? `.${patch}` : '');\n}\n\n/**\n * Compares two CalVer strings using a shared format.\n *\n * @remarks\n * Comparison is performed component-by-component in year, month, day, then patch order.\n * Missing day and patch values are treated as `0` during comparison.\n *\n * @param a - Left-hand version string.\n * @param b - Right-hand version string.\n * @param calverFormat - Format used to parse both versions.\n * @returns `1` when `a` is greater, `-1` when `b` is greater, or `0` when they are equal.\n *\n * @example\n * ```ts\n * import { compare } from 'versionguard';\n *\n * compare('2026.03.2', '2026.03.1', 'YYYY.MM.PATCH');\n * // => 1\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function compare(a: string, b: string, calverFormat: CalVerFormat): number {\n const left = parse(a, calverFormat);\n const right = parse(b, calverFormat);\n\n if (!left || !right) {\n throw new Error(`Invalid CalVer comparison between \"${a}\" and \"${b}\"`);\n }\n\n for (const key of ['year', 'month', 'day', 'patch'] as const) {\n const leftValue = left[key] ?? 0;\n const rightValue = right[key] ?? 0;\n if (leftValue !== rightValue) {\n return leftValue > rightValue ? 1 : -1;\n }\n }\n\n return 0;\n}\n\n/**\n * Increments a CalVer string.\n *\n * @remarks\n * Patch-based formats increment the existing patch number. Formats without a patch token are\n * promoted to a patch-based output by appending `.PATCH` semantics with an initial value of `0`.\n *\n * @param version - Current version string.\n * @param calverFormat - Format used to parse the current version.\n * @returns The next version string.\n *\n * @example\n * ```ts\n * import { increment } from 'versionguard';\n *\n * increment('2026.03.1', 'YYYY.MM.PATCH');\n * // => '2026.3.2'\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function increment(version: string, calverFormat: CalVerFormat): string {\n const parsed = parse(version, calverFormat);\n\n if (!parsed) {\n throw new Error(`Invalid CalVer version: ${version}`);\n }\n\n const definition = parseFormat(calverFormat);\n const next: CalVer = {\n ...parsed,\n raw: version,\n };\n\n if (definition.patch) {\n const patch = parsed.patch ?? 0;\n next.patch = patch + 1;\n } else {\n next.patch = 0;\n next.format = `${calverFormat}.PATCH` as CalVerFormat;\n }\n\n return format(next);\n}\n\n/**\n * Returns the most likely next CalVer candidates.\n *\n * @remarks\n * The first candidate is the version derived from the current date. The second candidate is the\n * incremented form of the supplied current version.\n *\n * @param currentVersion - Existing project version.\n * @param calverFormat - Format used to generate both candidates.\n * @returns Two candidate version strings ordered as current-date then incremented version.\n *\n * @example\n * ```ts\n * import { getNextVersions } from 'versionguard';\n *\n * getNextVersions('2026.03.1', 'YYYY.MM.PATCH').length;\n * // => 2\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function getNextVersions(currentVersion: string, calverFormat: CalVerFormat): string[] {\n return [getCurrentVersion(calverFormat), increment(currentVersion, calverFormat)];\n}\n","import * as fs from 'node:fs';\n\n/**\n * Describes the outcome of validating a changelog file.\n *\n * @public\n * @since 0.1.0\n * @forgeIgnore E020\n */\nexport interface ChangelogValidationResult {\n /**\n * Indicates whether the changelog satisfies all requested checks.\n */\n valid: boolean;\n /**\n * Human-readable validation errors.\n */\n errors: string[];\n /**\n * Indicates whether the changelog contains an entry for the requested version.\n */\n hasEntryForVersion: boolean;\n}\n\nconst CHANGELOG_DATE_REGEX = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/**\n * Validates a changelog file for release readiness.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * The validator checks for a top-level changelog heading, an `[Unreleased]`\n * section, and optionally a dated entry for the requested version.\n *\n * @param changelogPath - Path to the changelog file.\n * @param version - Version that must be present in the changelog.\n * @param strict - Whether to require compare links and dated release headings.\n * @param requireEntry - Whether the requested version must already have an entry.\n * @returns The result of validating the changelog file.\n * @example\n * ```ts\n * import { validateChangelog } from 'versionguard';\n *\n * const result = validateChangelog('CHANGELOG.md', '1.2.0', true, true);\n * ```\n */\nexport function validateChangelog(\n changelogPath: string,\n version: string,\n strict: boolean = true,\n requireEntry: boolean = true,\n): ChangelogValidationResult {\n if (!fs.existsSync(changelogPath)) {\n return {\n valid: !requireEntry,\n errors: requireEntry ? [`Changelog not found: ${changelogPath}`] : [],\n hasEntryForVersion: false,\n };\n }\n\n const errors: string[] = [];\n const content = fs.readFileSync(changelogPath, 'utf-8');\n\n if (!content.startsWith('# Changelog')) {\n errors.push('Changelog must start with \"# Changelog\"');\n }\n\n if (!content.includes('## [Unreleased]')) {\n errors.push('Changelog must have an [Unreleased] section');\n }\n\n const versionHeader = `## [${version}]`;\n const hasEntryForVersion = content.includes(versionHeader);\n if (requireEntry && !hasEntryForVersion) {\n errors.push(`Changelog must have an entry for version ${version}`);\n }\n\n if (strict) {\n if (!content.includes('[Unreleased]:')) {\n errors.push('Changelog should include compare links at the bottom');\n }\n\n const versionHeaderMatch = content.match(\n new RegExp(`## \\\\[${escapeRegExp(version)}\\\\] - ([^\\r\\n]+)`),\n );\n if (requireEntry && hasEntryForVersion) {\n if (!versionHeaderMatch) {\n errors.push(`Version ${version} entry must use \"## [${version}] - YYYY-MM-DD\" format`);\n } else if (!CHANGELOG_DATE_REGEX.test(versionHeaderMatch[1])) {\n errors.push(`Version ${version} entry date must use YYYY-MM-DD format`);\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n hasEntryForVersion,\n };\n}\n\n/**\n * Gets the most recent released version from a changelog.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * The `[Unreleased]` section is skipped so the first concrete version heading is\n * treated as the latest release.\n *\n * @param changelogPath - Path to the changelog file.\n * @returns The latest released version, or `null` when no release entry exists.\n * @example\n * ```ts\n * import { getLatestVersion } from 'versionguard';\n *\n * const latest = getLatestVersion('CHANGELOG.md');\n * ```\n */\nexport function getLatestVersion(changelogPath: string): string | null {\n if (!fs.existsSync(changelogPath)) {\n return null;\n }\n\n const content = fs.readFileSync(changelogPath, 'utf-8');\n const match = content.match(/^## \\[(?!Unreleased\\])(.*?)\\]/m);\n return match?.[1] ?? null;\n}\n\n/**\n * Inserts a new version entry beneath the `[Unreleased]` section.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * If the changelog already contains the requested version, no changes are made.\n * The inserted entry includes a starter `Added` subsection for follow-up edits.\n *\n * @param changelogPath - Path to the changelog file.\n * @param version - Version to add.\n * @param date - Release date to write in `YYYY-MM-DD` format.\n * @example\n * ```ts\n * import { addVersionEntry } from 'versionguard';\n *\n * addVersionEntry('CHANGELOG.md', '1.2.0', '2026-03-21');\n * ```\n */\nexport function addVersionEntry(\n changelogPath: string,\n version: string,\n date: string = new Date().toISOString().slice(0, 10),\n): void {\n if (!fs.existsSync(changelogPath)) {\n throw new Error(`Changelog not found: ${changelogPath}`);\n }\n\n const content = fs.readFileSync(changelogPath, 'utf-8');\n if (content.includes(`## [${version}]`)) {\n return;\n }\n\n const block = `## [${version}] - ${date}\\n\\n### Added\\n\\n- Describe changes here.\\n\\n`;\n const unreleasedMatch = content.match(/## \\[Unreleased\\]\\r?\\n(?:\\r?\\n)?/);\n if (!unreleasedMatch || unreleasedMatch.index === undefined) {\n throw new Error('Changelog must have an [Unreleased] section');\n }\n\n const insertIndex = unreleasedMatch.index + unreleasedMatch[0].length;\n const updated = `${content.slice(0, insertIndex)}${block}${content.slice(insertIndex)}`;\n fs.writeFileSync(changelogPath, updated, 'utf-8');\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport type { GitConfig } from './types';\n\nconst HOOK_NAMES = ['pre-commit', 'pre-push', 'post-tag'] as const;\n\n/**\n * Installs VersionGuard-managed Git hooks in a repository.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * Only hooks enabled in `config.hooks` are written. Each installed hook runs\n * `versionguard validate` for its corresponding hook name.\n *\n * @param config - Git configuration that selects which hooks to install.\n * @param cwd - Repository directory where hooks should be installed.\n * @example\n * ```ts\n * import { getDefaultConfig, installHooks } from 'versionguard';\n *\n * installHooks(getDefaultConfig().git, process.cwd());\n * ```\n */\nexport function installHooks(config: GitConfig, cwd: string = process.cwd()): void {\n const gitDir = findGitDir(cwd);\n if (!gitDir) {\n throw new Error('Not a git repository. Run `git init` first.');\n }\n\n const hooksDir = path.join(gitDir, 'hooks');\n fs.mkdirSync(hooksDir, { recursive: true });\n\n for (const hookName of HOOK_NAMES) {\n if (config.hooks[hookName]) {\n const hookPath = path.join(hooksDir, hookName);\n fs.writeFileSync(hookPath, generateHookScript(hookName), { encoding: 'utf-8', mode: 0o755 });\n }\n }\n}\n\n/**\n * Removes VersionGuard-managed Git hooks from a repository.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * Only hook files containing `versionguard` are removed so unrelated custom\n * hooks are left untouched.\n *\n * @param cwd - Repository directory whose hooks should be cleaned up.\n * @example\n * ```ts\n * import { uninstallHooks } from 'versionguard';\n *\n * uninstallHooks(process.cwd());\n * ```\n */\nexport function uninstallHooks(cwd: string = process.cwd()): void {\n const gitDir = findGitDir(cwd);\n if (!gitDir) {\n return;\n }\n\n const hooksDir = path.join(gitDir, 'hooks');\n for (const hookName of HOOK_NAMES) {\n const hookPath = path.join(hooksDir, hookName);\n if (fs.existsSync(hookPath) && fs.readFileSync(hookPath, 'utf-8').includes('versionguard')) {\n fs.unlinkSync(hookPath);\n }\n }\n}\n\n/**\n * Finds the nearest `.git` directory by walking up from a starting directory.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This only resolves `.git` directories and returns `null` when the search\n * reaches the filesystem root without finding a repository.\n *\n * @param cwd - Directory to start searching from.\n * @returns The resolved `.git` directory path, or `null` when none is found.\n * @example\n * ```ts\n * import { findGitDir } from 'versionguard';\n *\n * const gitDir = findGitDir(process.cwd());\n * ```\n */\nexport function findGitDir(cwd: string): string | null {\n let current = cwd;\n\n while (true) {\n const gitPath = path.join(current, '.git');\n if (fs.existsSync(gitPath) && fs.statSync(gitPath).isDirectory()) {\n return gitPath;\n }\n\n const parent = path.dirname(current);\n if (parent === current) {\n return null;\n }\n current = parent;\n }\n}\n\n/**\n * Checks whether all VersionGuard-managed hooks are installed.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * A hook counts as installed only when the file exists and contains the\n * `versionguard` invocation written by this package.\n *\n * @param cwd - Repository directory to inspect.\n * @returns `true` when every managed hook is installed.\n * @example\n * ```ts\n * import { areHooksInstalled } from 'versionguard';\n *\n * const installed = areHooksInstalled(process.cwd());\n * ```\n */\nexport function areHooksInstalled(cwd: string = process.cwd()): boolean {\n const gitDir = findGitDir(cwd);\n if (!gitDir) {\n return false;\n }\n\n return HOOK_NAMES.every((hookName) => {\n const hookPath = path.join(gitDir, 'hooks', hookName);\n return fs.existsSync(hookPath) && fs.readFileSync(hookPath, 'utf-8').includes('versionguard');\n });\n}\n\n/**\n * Generates the shell script content for a Git hook.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * The generated script delegates to `npx versionguard validate` and exits with\n * the validation status code.\n *\n * @param hookName - Name of the Git hook to generate.\n * @returns Executable shell script contents for the hook.\n * @example\n * ```ts\n * import { generateHookScript } from 'versionguard';\n *\n * const script = generateHookScript('pre-commit');\n * ```\n */\nexport function generateHookScript(hookName: (typeof HOOK_NAMES)[number]): string {\n return `#!/bin/sh\n# VersionGuard ${hookName} hook\nnpx versionguard validate --hook=${hookName}\nstatus=$?\nif [ $status -ne 0 ]; then\n echo \"VersionGuard validation failed.\"\n exit $status\nfi\n`;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\n/**\n * JSON-compatible scalar, array, or object value used by package metadata.\n *\n * @public\n * @since 0.1.0\n * @forgeIgnore E020\n */\nexport type PackageJsonValue =\n | boolean\n | null\n | number\n | string\n | PackageJsonArray\n | PackageJsonObject;\n\n/**\n * Recursive array type used for arbitrary JSON-compatible package values.\n *\n * @public\n * @since 0.1.0\n * @forgeIgnore E020\n */\nexport type PackageJsonArray = PackageJsonValue[];\n\n/**\n * Recursive object type used for arbitrary JSON-compatible package values.\n *\n * @public\n * @since 0.1.0\n * @forgeIgnore E020\n */\nexport interface PackageJsonObject {\n [key: string]: PackageJsonValue;\n}\n\n/**\n * Minimal shape of a `package.json` document used by VersionGuard.\n *\n * @public\n * @since 0.1.0\n * @forgeIgnore E020\n */\nexport interface PackageJson {\n /**\n * Package name.\n *\n * @defaultValue `undefined`\n */\n name?: string;\n /**\n * Package version string.\n *\n * @defaultValue `undefined`\n */\n version?: string;\n [key: string]: PackageJsonValue | undefined;\n}\n\n/**\n * Gets the `package.json` path for a project directory.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This is a convenience helper used by the package read and write helpers.\n *\n * @param cwd - Project directory containing `package.json`.\n * @returns The resolved `package.json` path.\n * @example\n * ```ts\n * import { getPackageJsonPath } from 'versionguard';\n *\n * const packagePath = getPackageJsonPath(process.cwd());\n * ```\n */\nexport function getPackageJsonPath(cwd: string = process.cwd()): string {\n return path.join(cwd, 'package.json');\n}\n\n/**\n * Reads and parses a project's `package.json` file.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * An error is thrown when `package.json` does not exist in the requested\n * directory.\n *\n * @param cwd - Project directory containing `package.json`.\n * @returns The parsed `package.json` document.\n * @example\n * ```ts\n * import { readPackageJson } from 'versionguard';\n *\n * const pkg = readPackageJson(process.cwd());\n * ```\n */\nexport function readPackageJson(cwd: string = process.cwd()): PackageJson {\n const packagePath = getPackageJsonPath(cwd);\n\n if (!fs.existsSync(packagePath)) {\n throw new Error(`package.json not found in ${cwd}`);\n }\n\n return JSON.parse(fs.readFileSync(packagePath, 'utf-8')) as PackageJson;\n}\n\n/**\n * Writes a `package.json` document back to disk.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * Output is formatted with two-space indentation and always ends with a\n * trailing newline.\n *\n * @param pkg - Parsed `package.json` data to write.\n * @param cwd - Project directory containing `package.json`.\n * @example\n * ```ts\n * import { readPackageJson, writePackageJson } from 'versionguard';\n *\n * const pkg = readPackageJson(process.cwd());\n * writePackageJson(pkg, process.cwd());\n * ```\n */\nexport function writePackageJson(pkg: PackageJson, cwd: string = process.cwd()): void {\n fs.writeFileSync(getPackageJsonPath(cwd), `${JSON.stringify(pkg, null, 2)}\\n`, 'utf-8');\n}\n\n/**\n * Gets the version string from `package.json`.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This throws when the file exists but does not contain a non-empty `version`\n * field.\n *\n * @param cwd - Project directory containing `package.json`.\n * @returns The package version string.\n * @example\n * ```ts\n * import { getPackageVersion } from 'versionguard';\n *\n * const version = getPackageVersion(process.cwd());\n * ```\n */\nexport function getPackageVersion(cwd: string = process.cwd()): string {\n const pkg = readPackageJson(cwd);\n\n if (typeof pkg.version !== 'string' || pkg.version.length === 0) {\n throw new Error('No version field in package.json');\n }\n\n return pkg.version;\n}\n\n/**\n * Sets the version field in `package.json`.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * The existing document is read, the `version` field is replaced, and the full\n * file is written back to disk.\n *\n * @param version - Version string to persist.\n * @param cwd - Project directory containing `package.json`.\n * @example\n * ```ts\n * import { setPackageVersion } from 'versionguard';\n *\n * setPackageVersion('1.2.3', process.cwd());\n * ```\n */\nexport function setPackageVersion(version: string, cwd: string = process.cwd()): void {\n const pkg = readPackageJson(cwd);\n pkg.version = version;\n writePackageJson(pkg, cwd);\n}\n","/**\n * Semantic version parsing, validation, comparison, and increment helpers.\n *\n * @packageDocumentation\n */\n\nimport type { SemVer, ValidationError, ValidationResult } from './types';\n\nconst SEMVER_REGEX =\n /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$/;\n\n/**\n * Parses a semantic version string.\n *\n * @remarks\n * This helper enforces the standard SemVer structure and returns `null` when the input does not\n * match. It preserves prerelease and build identifiers as ordered string segments.\n *\n * @param version - Version string to parse.\n * @returns Parsed semantic version components, or `null` when the input is invalid.\n *\n * @example\n * ```ts\n * import { parse } from 'versionguard';\n *\n * parse('1.2.3-alpha.1+build.5')?.prerelease;\n * // => ['alpha', '1']\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function parse(version: string): SemVer | null {\n const match = version.match(SEMVER_REGEX);\n\n if (!match) {\n return null;\n }\n\n return {\n major: Number.parseInt(match[1], 10),\n minor: Number.parseInt(match[2], 10),\n patch: Number.parseInt(match[3], 10),\n prerelease: match[4] ? match[4].split('.') : [],\n build: match[5] ? match[5].split('.') : [],\n raw: version,\n };\n}\n\nfunction getStructuralErrors(version: string): ValidationError[] {\n const errors: ValidationError[] = [];\n\n if (version.startsWith('v')) {\n errors.push({\n message: `Version should not start with 'v': ${version}`,\n severity: 'error',\n });\n return errors;\n }\n\n const mainPart = version.split(/[+-]/, 1)[0];\n const segments = mainPart.split('.');\n if (segments.length === 3) {\n const leadingZeroSegment = segments.find((segment) => /^0\\d+$/.test(segment));\n if (leadingZeroSegment) {\n errors.push({\n message: `Invalid SemVer: numeric segment \"${leadingZeroSegment}\" has a leading zero`,\n severity: 'error',\n });\n return errors;\n }\n }\n\n const prerelease = version.match(/-([^+]+)/)?.[1];\n if (prerelease) {\n const invalidPrerelease = prerelease.split('.').find((segment) => /^0\\d+$/.test(segment));\n if (invalidPrerelease) {\n errors.push({\n message: `Invalid SemVer: prerelease identifier \"${invalidPrerelease}\" has a leading zero`,\n severity: 'error',\n });\n return errors;\n }\n }\n\n errors.push({\n message: `Invalid SemVer format: \"${version}\". Expected MAJOR.MINOR.PATCH[-prerelease][+build].`,\n severity: 'error',\n });\n return errors;\n}\n\n/**\n * Validates that a string is a supported semantic version.\n *\n * @remarks\n * When validation fails, the result includes targeted structural errors for common cases such as\n * leading `v` prefixes and numeric segments with leading zeroes.\n *\n * @param version - Version string to validate.\n * @returns A validation result containing any detected errors and the parsed version on success.\n *\n * @example\n * ```ts\n * import { validate } from 'versionguard';\n *\n * validate('1.2.3').valid;\n * // => true\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function validate(version: string): ValidationResult {\n const parsed = parse(version);\n\n if (!parsed) {\n return {\n valid: false,\n errors: getStructuralErrors(version),\n };\n }\n\n return {\n valid: true,\n errors: [],\n version: { type: 'semver', version: parsed },\n };\n}\n\n/**\n * Compares two semantic version strings.\n *\n * @remarks\n * Comparison follows SemVer precedence rules, including special handling for prerelease\n * identifiers and ignoring build metadata.\n *\n * @param a - Left-hand version string.\n * @param b - Right-hand version string.\n * @returns `1` when `a` is greater, `-1` when `b` is greater, or `0` when they are equal.\n *\n * @example\n * ```ts\n * import { compare } from 'versionguard';\n *\n * compare('1.2.3', '1.2.3-alpha.1');\n * // => 1\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function compare(a: string, b: string): number {\n const left = parse(a);\n const right = parse(b);\n\n if (!left || !right) {\n throw new Error(`Invalid SemVer comparison between \"${a}\" and \"${b}\"`);\n }\n\n for (const key of ['major', 'minor', 'patch'] as const) {\n if (left[key] !== right[key]) {\n return left[key] > right[key] ? 1 : -1;\n }\n }\n\n const leftHasPrerelease = left.prerelease.length > 0;\n const rightHasPrerelease = right.prerelease.length > 0;\n\n if (leftHasPrerelease && !rightHasPrerelease) {\n return -1;\n }\n\n if (!leftHasPrerelease && rightHasPrerelease) {\n return 1;\n }\n\n const length = Math.max(left.prerelease.length, right.prerelease.length);\n for (let index = 0; index < length; index += 1) {\n const leftValue = left.prerelease[index];\n const rightValue = right.prerelease[index];\n\n if (leftValue === undefined) {\n return -1;\n }\n\n if (rightValue === undefined) {\n return 1;\n }\n\n const leftNumeric = /^\\d+$/.test(leftValue) ? Number.parseInt(leftValue, 10) : null;\n const rightNumeric = /^\\d+$/.test(rightValue) ? Number.parseInt(rightValue, 10) : null;\n\n if (leftNumeric !== null && rightNumeric !== null) {\n if (leftNumeric !== rightNumeric) {\n return leftNumeric > rightNumeric ? 1 : -1;\n }\n continue;\n }\n\n if (leftNumeric !== null) {\n return -1;\n }\n\n if (rightNumeric !== null) {\n return 1;\n }\n\n if (leftValue !== rightValue) {\n return leftValue > rightValue ? 1 : -1;\n }\n }\n\n return 0;\n}\n\n/**\n * Checks whether one semantic version is greater than another.\n *\n * @remarks\n * This is a convenience wrapper around {@link compare} for callers that only need a boolean.\n *\n * @param a - Left-hand version string.\n * @param b - Right-hand version string.\n * @returns `true` when `a` has higher precedence than `b`.\n *\n * @example\n * ```ts\n * import { gt } from 'versionguard';\n *\n * gt('1.2.4', '1.2.3');\n * // => true\n * ```\n *\n * @see {@link compare} for full precedence ordering.\n * @public\n * @since 0.1.0\n */\nexport function gt(a: string, b: string): boolean {\n return compare(a, b) > 0;\n}\n\n/**\n * Checks whether one semantic version is less than another.\n *\n * @remarks\n * This is a convenience wrapper around {@link compare} for callers that only need a boolean.\n *\n * @param a - Left-hand version string.\n * @param b - Right-hand version string.\n * @returns `true` when `a` has lower precedence than `b`.\n *\n * @example\n * ```ts\n * import { lt } from 'versionguard';\n *\n * lt('1.2.3-alpha.1', '1.2.3');\n * // => true\n * ```\n *\n * @see {@link compare} for full precedence ordering.\n * @public\n * @since 0.1.0\n */\nexport function lt(a: string, b: string): boolean {\n return compare(a, b) < 0;\n}\n\n/**\n * Checks whether two semantic versions are equal in precedence.\n *\n * @remarks\n * This is a convenience wrapper around {@link compare}. Build metadata is ignored because\n * precedence comparisons in SemVer do not consider it.\n *\n * @param a - Left-hand version string.\n * @param b - Right-hand version string.\n * @returns `true` when both versions compare as equal.\n *\n * @example\n * ```ts\n * import { eq } from 'versionguard';\n *\n * eq('1.2.3', '1.2.3');\n * // => true\n * ```\n *\n * @see {@link compare} for full precedence ordering.\n * @public\n * @since 0.1.0\n */\nexport function eq(a: string, b: string): boolean {\n return compare(a, b) === 0;\n}\n\n/**\n * Increments a semantic version string by release type.\n *\n * @remarks\n * Incrementing `major` or `minor` resets lower-order numeric segments. When a prerelease label is\n * provided, it is appended to the newly generated version.\n *\n * @param version - Current semantic version string.\n * @param release - Segment to increment.\n * @param prerelease - Optional prerelease suffix to append to the next version.\n * @returns The incremented semantic version string.\n *\n * @example\n * ```ts\n * import { increment } from 'versionguard';\n *\n * increment('1.2.3', 'minor', 'beta.1');\n * // => '1.3.0-beta.1'\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function increment(\n version: string,\n release: 'major' | 'minor' | 'patch',\n prerelease?: string,\n): string {\n const parsed = parse(version);\n\n if (!parsed) {\n throw new Error(`Invalid SemVer version: ${version}`);\n }\n\n if (release === 'major') {\n return `${parsed.major + 1}.0.0${prerelease ? `-${prerelease}` : ''}`;\n }\n\n if (release === 'minor') {\n return `${parsed.major}.${parsed.minor + 1}.0${prerelease ? `-${prerelease}` : ''}`;\n }\n\n return `${parsed.major}.${parsed.minor}.${parsed.patch + 1}${prerelease ? `-${prerelease}` : ''}`;\n}\n\n/**\n * Formats a parsed semantic version object.\n *\n * @remarks\n * Prerelease and build metadata segments are only included when their arrays contain values.\n *\n * @param version - Parsed semantic version to serialize.\n * @returns The normalized semantic version string.\n *\n * @example\n * ```ts\n * import { format } from 'versionguard';\n *\n * const version = { major: 1, minor: 2, patch: 3, prerelease: ['rc', '1'], build: ['build', '5'], raw: '1.2.3-rc.1+build.5' };\n *\n * format(version);\n * // => '1.2.3-rc.1+build.5'\n * ```\n *\n * @public\n * @since 0.1.0\n */\nexport function format(version: SemVer): string {\n let output = `${version.major}.${version.minor}.${version.patch}`;\n\n if (version.prerelease.length > 0) {\n output += `-${version.prerelease.join('.')}`;\n }\n\n if (version.build.length > 0) {\n output += `+${version.build.join('.')}`;\n }\n\n return output;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport { globSync } from 'glob';\n\nimport type { SyncConfig, SyncPattern, SyncResult, VersionMismatch } from './types';\n\nfunction resolveFiles(patterns: string[], cwd: string, ignore: string[] = []): string[] {\n return [\n ...new Set(patterns.flatMap((pattern) => globSync(pattern, { cwd, absolute: true, ignore }))),\n ].sort();\n}\n\nfunction getLineNumber(content: string, offset: number): number {\n return content.slice(0, offset).split('\\n').length;\n}\n\nfunction extractVersion(groups: string[]): string {\n return groups[1] ?? groups[0] ?? '';\n}\n\nfunction applyTemplate(template: string, groups: string[], version: string): string {\n return template.replace(/\\$(\\d+)|\\{\\{version\\}\\}/g, (match, groupIndex: string | undefined) => {\n if (match === '{{version}}') {\n return version;\n }\n\n return groups[Number.parseInt(groupIndex ?? '0', 10) - 1] ?? '';\n });\n}\n\nfunction stringifyCapture(value: unknown): string {\n return typeof value === 'string' ? value : '';\n}\n\n/**\n * Synchronizes configured files to a single version string.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * File globs are resolved relative to `cwd`, then each matched file is updated\n * with the configured replacement patterns.\n *\n * @param version - Version string to write into matching files.\n * @param config - Sync configuration describing files and replacement patterns.\n * @param cwd - Project directory used to resolve file globs.\n * @returns A sync result for each resolved file.\n * @example\n * ```ts\n * import { getDefaultConfig, syncVersion } from 'versionguard';\n *\n * const results = syncVersion('1.2.3', getDefaultConfig().sync, process.cwd());\n * ```\n */\nexport function syncVersion(\n version: string,\n config: SyncConfig,\n cwd: string = process.cwd(),\n): SyncResult[] {\n return resolveFiles(config.files, cwd).map((filePath) =>\n syncFile(filePath, version, config.patterns),\n );\n}\n\n/**\n * Synchronizes a single file to a target version.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * Each configured regex is applied globally, and `{{version}}` placeholders in\n * templates are replaced with the supplied version.\n *\n * @param filePath - Absolute or relative path to the file to update.\n * @param version - Version string to write.\n * @param patterns - Replacement patterns to apply.\n * @returns A result describing whether the file changed and what changed.\n * @example\n * ```ts\n * import { getDefaultConfig, syncFile } from 'versionguard';\n *\n * const result = syncFile('README.md', '1.2.3', getDefaultConfig().sync.patterns);\n * ```\n */\nexport function syncFile(filePath: string, version: string, patterns: SyncPattern[]): SyncResult {\n const original = fs.readFileSync(filePath, 'utf-8');\n let updatedContent = original;\n const changes: SyncResult['changes'] = [];\n\n for (const pattern of patterns) {\n const regex = new RegExp(pattern.regex, 'gm');\n updatedContent = updatedContent.replace(regex, (match, ...args: unknown[]) => {\n const hasNamedGroups = typeof args.at(-1) === 'object' && args.at(-1) !== null;\n const offsetIndex = hasNamedGroups ? -3 : -2;\n const offset = args.at(offsetIndex) as number;\n const groups = args.slice(0, offsetIndex).map((value) => stringifyCapture(value));\n const found = extractVersion(groups);\n\n if (found === 'Unreleased') {\n return match;\n }\n\n if (found !== version) {\n changes.push({\n line: getLineNumber(updatedContent, offset),\n oldValue: found,\n newValue: version,\n });\n }\n\n return applyTemplate(pattern.template, groups, version) || match;\n });\n }\n\n const result: SyncResult = {\n file: filePath,\n updated: updatedContent !== original,\n changes,\n };\n\n if (result.updated) {\n fs.writeFileSync(filePath, updatedContent, 'utf-8');\n }\n\n return result;\n}\n\n/**\n * Checks configured files for hardcoded version mismatches.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * Files matching the sync config are scanned without modification, and every\n * captured version that differs from `expectedVersion` is returned.\n *\n * @param expectedVersion - Version all matching entries should use.\n * @param config - Sync configuration describing files and replacement patterns.\n * @param ignorePatterns - Glob patterns to exclude while scanning.\n * @param cwd - Project directory used to resolve file globs.\n * @returns A list of detected version mismatches.\n * @example\n * ```ts\n * import { checkHardcodedVersions, getDefaultConfig } from 'versionguard';\n *\n * const mismatches = checkHardcodedVersions(\n * '1.2.3',\n * getDefaultConfig().sync,\n * getDefaultConfig().ignore,\n * process.cwd(),\n * );\n * ```\n */\nexport function checkHardcodedVersions(\n expectedVersion: string,\n config: SyncConfig,\n ignorePatterns: string[],\n cwd: string = process.cwd(),\n): VersionMismatch[] {\n const mismatches: VersionMismatch[] = [];\n const files = resolveFiles(config.files, cwd, ignorePatterns);\n\n for (const filePath of files) {\n const content = fs.readFileSync(filePath, 'utf-8');\n\n for (const pattern of config.patterns) {\n const regex = new RegExp(pattern.regex, 'gm');\n let match: RegExpExecArray | null = regex.exec(content);\n\n while (match) {\n const found = extractVersion(match.slice(1));\n if (found !== 'Unreleased' && found !== expectedVersion) {\n mismatches.push({\n file: path.relative(cwd, filePath),\n line: getLineNumber(content, match.index),\n found,\n });\n }\n match = regex.exec(content);\n }\n }\n }\n\n return mismatches;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport * as yaml from 'js-yaml';\n\nimport type { VersionGuardConfig } from './types';\n\nconst CONFIG_FILE_NAMES = [\n '.versionguard.yml',\n '.versionguard.yaml',\n 'versionguard.yml',\n 'versionguard.yaml',\n];\n\nconst DEFAULT_CONFIG: VersionGuardConfig = {\n versioning: {\n type: 'semver',\n calver: {\n format: 'YYYY.MM.PATCH',\n preventFutureDates: true,\n },\n },\n sync: {\n files: ['README.md', 'CHANGELOG.md'],\n patterns: [\n {\n regex: '(version\\\\s*[=:]\\\\s*[\"\\'])(.+?)([\"\\'])',\n template: '$1{{version}}$3',\n },\n {\n regex: '(##\\\\s*\\\\[)(.+?)(\\\\])',\n template: '$1{{version}}$3',\n },\n ],\n },\n changelog: {\n enabled: true,\n file: 'CHANGELOG.md',\n strict: true,\n requireEntry: true,\n },\n git: {\n hooks: {\n 'pre-commit': true,\n 'pre-push': true,\n 'post-tag': true,\n },\n enforceHooks: true,\n },\n ignore: ['node_modules/**', 'dist/**', '.git/**', '*.lock', 'package-lock.json'],\n};\n\nconst MODULE_DIR = path.dirname(fileURLToPath(import.meta.url));\n\n/**\n * Returns a deep-cloned copy of the built-in VersionGuard configuration.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * A fresh clone is returned so callers can safely modify the result without\n * mutating shared defaults.\n *\n * @returns The default VersionGuard configuration.\n * @example\n * ```ts\n * import { getDefaultConfig } from 'versionguard';\n *\n * const config = getDefaultConfig();\n * ```\n */\nexport function getDefaultConfig(): VersionGuardConfig {\n return structuredClone(DEFAULT_CONFIG);\n}\n\n/**\n * Finds the first supported VersionGuard config file in a directory.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * Search order follows `CONFIG_FILE_NAMES`, so `.versionguard.yml` takes\n * precedence over the other supported filenames.\n *\n * @param cwd - Directory to search.\n * @returns The resolved config path, or `null` when no config file exists.\n * @example\n * ```ts\n * import { findConfig } from 'versionguard';\n *\n * const configPath = findConfig(process.cwd());\n * ```\n */\nexport function findConfig(cwd: string = process.cwd()): string | null {\n for (const fileName of CONFIG_FILE_NAMES) {\n const fullPath = path.join(cwd, fileName);\n if (fs.existsSync(fullPath)) {\n return fullPath;\n }\n }\n\n return null;\n}\n\n/**\n * Loads a VersionGuard config file from disk.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * The parsed YAML object is merged with the built-in defaults so omitted keys\n * inherit their default values.\n *\n * @param configPath - Path to the YAML config file.\n * @returns The merged VersionGuard configuration.\n * @example\n * ```ts\n * import { loadConfig } from 'versionguard';\n *\n * const config = loadConfig('.versionguard.yml');\n * ```\n */\nexport function loadConfig(configPath: string): VersionGuardConfig {\n const content = fs.readFileSync(configPath, 'utf-8');\n const parsed = yaml.load(content);\n\n if (parsed === undefined) {\n return getDefaultConfig();\n }\n\n if (!isPlainObject(parsed)) {\n throw new Error(`Config file must contain a YAML object: ${configPath}`);\n }\n\n return mergeDeep(getDefaultConfig(), parsed);\n}\n\n/**\n * Resolves the active VersionGuard configuration for a project.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * If no config file is present, this falls back to the built-in defaults.\n *\n * @param cwd - Project directory to inspect.\n * @returns The resolved VersionGuard configuration.\n * @example\n * ```ts\n * import { getConfig } from 'versionguard';\n *\n * const config = getConfig(process.cwd());\n * ```\n */\nexport function getConfig(cwd: string = process.cwd()): VersionGuardConfig {\n const configPath = findConfig(cwd);\n return configPath ? loadConfig(configPath) : getDefaultConfig();\n}\n\n/**\n * Initializes a new VersionGuard config file in a project.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This writes `.versionguard.yml` using the bundled example when available,\n * otherwise it writes a generated default configuration.\n *\n * @param cwd - Project directory where the config should be created.\n * @returns The path to the created config file.\n * @example\n * ```ts\n * import { initConfig } from 'versionguard';\n *\n * const configPath = initConfig(process.cwd());\n * ```\n */\nexport function initConfig(cwd: string = process.cwd()): string {\n const configPath = path.join(cwd, '.versionguard.yml');\n const existingConfigPath = findConfig(cwd);\n\n if (existingConfigPath) {\n throw new Error(`Config file already exists: ${existingConfigPath}`);\n }\n\n const examplePath = path.join(MODULE_DIR, '..', '.versionguard.yml.example');\n const content = fs.existsSync(examplePath)\n ? fs.readFileSync(examplePath, 'utf-8')\n : generateDefaultConfig();\n\n fs.writeFileSync(configPath, content, 'utf-8');\n return configPath;\n}\n\nfunction generateDefaultConfig(): string {\n return `# VersionGuard Configuration\nversioning:\n type: semver\n\nsync:\n files:\n - \"README.md\"\n - \"CHANGELOG.md\"\n patterns:\n - regex: '(version\\\\s*[=:]\\\\s*[\"''])(.+?)([\"''])'\n template: '$1{{version}}$3'\n - regex: '(##\\\\s*\\\\[)(.+?)(\\\\])'\n template: '$1{{version}}$3'\n\nchangelog:\n enabled: true\n file: \"CHANGELOG.md\"\n strict: true\n requireEntry: true\n\ngit:\n hooks:\n pre-commit: true\n pre-push: true\n post-tag: true\n enforceHooks: true\n\nignore:\n - \"node_modules/**\"\n - \"dist/**\"\n - \".git/**\"\n`;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction mergeDeep<T>(target: T, source: Partial<T>): T {\n /* v8 ignore next 3 -- defensive fallback for non-object nested overrides */\n if (!isPlainObject(target) || !isPlainObject(source)) {\n return (source ?? target) as T;\n }\n\n const output: Record<string, unknown> = { ...target };\n\n for (const [key, value] of Object.entries(source)) {\n const current = output[key];\n output[key] =\n isPlainObject(current) && isPlainObject(value) ? mergeDeep(current, value) : value;\n }\n\n return output as T;\n}\n","import * as calver from '../calver';\nimport * as semver from '../semver';\n\nimport type { CalVer, CalVerConfig, ValidationError, VersionGuardConfig } from '../types';\n\n/**\n * Feedback helpers that turn validation failures into actionable suggestions.\n *\n * @packageDocumentation\n * @public\n */\n\n/**\n * Feedback entry point exports for suggestion and guidance helpers.\n *\n * @packageDocumentation\n * @public\n * @since 0.1.0\n * @forgeIgnore E020\n */\nexport interface Suggestion {\n /**\n * Human-readable guidance for the user.\n */\n message: string;\n\n /**\n * Command or action text that can be used to address the issue.\n *\n * @defaultValue `undefined`\n */\n fix?: string;\n\n /**\n * Indicates whether VersionGuard can apply the suggestion automatically.\n */\n autoFixable: boolean;\n}\n\n/**\n * Aggregates validation errors with suggested next steps.\n *\n * @public\n * @since 0.1.0\n */\nexport interface FeedbackResult {\n /**\n * Indicates whether the inspected version state is valid.\n */\n valid: boolean;\n\n /**\n * Validation errors collected during the check.\n */\n errors: ValidationError[];\n\n /**\n * Suggested next steps for resolving the reported issues.\n */\n suggestions: Suggestion[];\n\n /**\n * Indicates whether at least one suggestion can be auto-applied.\n */\n canAutoFix: boolean;\n}\n\n/**\n * Generates actionable feedback for a version string.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper dispatches to the SemVer or CalVer feedback flow based on the\n * configured versioning strategy and returns both hard validation errors and\n * softer suggestions for likely fixes.\n *\n * @param version - Version string to evaluate.\n * @param config - Loaded VersionGuard configuration.\n * @param previousVersion - Optional previous version used for progression checks.\n * @returns A feedback object with validation errors and suggested fixes.\n *\n * @example\n * ```typescript\n * const feedbackResult = getVersionFeedback('1.2.3', config, '1.2.2');\n * console.log(feedbackResult.valid);\n * ```\n */\nexport function getVersionFeedback(\n version: string,\n config: VersionGuardConfig,\n previousVersion?: string,\n): FeedbackResult {\n if (config.versioning.type === 'semver') {\n return getSemVerFeedback(version, previousVersion);\n }\n\n return getCalVerFeedback(version, getCalVerConfig(config), previousVersion);\n}\n\nfunction getCalVerConfig(config: VersionGuardConfig): CalVerConfig {\n if (!config.versioning.calver) {\n throw new Error('CalVer configuration is required when versioning.type is \"calver\"');\n }\n\n return config.versioning.calver;\n}\n\nfunction getSemVerFeedback(version: string, previousVersion?: string): FeedbackResult {\n const errors: ValidationError[] = [];\n const suggestions: Suggestion[] = [];\n\n // Try to parse\n const parsed = semver.parse(version);\n\n if (!parsed) {\n const validation = semver.validate(version);\n\n // Common mistakes\n if (version.startsWith('v')) {\n const cleanVersion = version.slice(1);\n errors.push({\n message: `Version should not start with 'v': ${version}`,\n severity: 'error',\n });\n suggestions.push({\n message: `Remove the 'v' prefix`,\n fix: `npm version ${cleanVersion}`,\n autoFixable: true,\n });\n } else if (version.split('.').length === 2) {\n errors.push({\n message: `Version missing patch number: ${version}`,\n severity: 'error',\n });\n suggestions.push({\n message: `Add patch number (e.g., ${version}.0)`,\n fix: `npm version ${version}.0`,\n autoFixable: true,\n });\n } else if (/^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(version)) {\n errors.push({\n message: `Version has too many segments: ${version}`,\n severity: 'error',\n });\n suggestions.push({\n message: `Use only 3 segments (MAJOR.MINOR.PATCH)`,\n autoFixable: false,\n });\n } else if (validation.errors.some((error) => error.message.includes('leading zero'))) {\n errors.push(...validation.errors);\n suggestions.push({\n message: `Remove leading zeros (e.g., 1.2.3 instead of 01.02.03)`,\n autoFixable: false,\n });\n } else {\n errors.push(\n ...(validation.errors.length > 0\n ? validation.errors\n : [\n {\n message: `Invalid SemVer format: ${version}`,\n severity: 'error' as const,\n },\n ]),\n );\n suggestions.push({\n message: `Use format: MAJOR.MINOR.PATCH (e.g., 1.0.0)`,\n autoFixable: false,\n });\n }\n\n return {\n valid: false,\n errors,\n suggestions,\n canAutoFix: suggestions.some((s) => s.autoFixable),\n };\n }\n\n // Check progression from previous version\n if (previousVersion) {\n const prevParsed = semver.parse(previousVersion);\n if (prevParsed) {\n const comparison = semver.compare(version, previousVersion);\n\n if (comparison < 0) {\n errors.push({\n message: `Version ${version} is older than previous ${previousVersion}`,\n severity: 'error',\n });\n suggestions.push({\n message: `Version must be greater than ${previousVersion}`,\n fix: `npm version ${semver.increment(previousVersion, 'patch')}`,\n autoFixable: true,\n });\n } else if (comparison === 0) {\n errors.push({\n message: `Version ${version} is the same as previous`,\n severity: 'error',\n });\n suggestions.push({\n message: `Bump the version`,\n fix: `npm version ${semver.increment(previousVersion, 'patch')}`,\n autoFixable: true,\n });\n } else {\n // Check if it's a reasonable jump\n const majorJump = parsed.major - prevParsed.major;\n const minorJump = parsed.minor - prevParsed.minor;\n const patchJump = parsed.patch - prevParsed.patch;\n\n if (majorJump > 1) {\n suggestions.push({\n message: `⚠️ Major version jumped by ${majorJump} (from ${previousVersion} to ${version})`,\n autoFixable: false,\n });\n }\n\n if (minorJump > 10) {\n suggestions.push({\n message: `⚠️ Minor version jumped by ${minorJump} - did you mean to do a major bump?`,\n autoFixable: false,\n });\n }\n\n if (patchJump > 20) {\n suggestions.push({\n message: `⚠️ Patch version jumped by ${patchJump} - consider a minor bump instead`,\n autoFixable: false,\n });\n }\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n suggestions,\n canAutoFix: suggestions.some((s) => s.autoFixable),\n };\n}\n\nfunction getCalVerFeedback(\n version: string,\n calverConfig: CalVerConfig,\n previousVersion?: string,\n): FeedbackResult {\n const errors: ValidationError[] = [];\n const suggestions: Suggestion[] = [];\n const { format, preventFutureDates } = calverConfig;\n\n const parsed = calver.parse(version, format);\n\n if (!parsed) {\n errors.push({\n message: `Invalid CalVer format: ${version}`,\n severity: 'error',\n });\n suggestions.push({\n message: `Expected format: ${format}`,\n fix: `Update package.json to use current date: \"${calver.getCurrentVersion(format)}\"`,\n autoFixable: true,\n });\n return { valid: false, errors, suggestions, canAutoFix: true };\n }\n\n const validation = calver.validate(version, format, preventFutureDates);\n errors.push(...validation.errors);\n\n const now = new Date();\n if (validation.errors.some((error) => error.message.startsWith('Invalid month:'))) {\n suggestions.push({\n message: `Month must be between 1-12`,\n autoFixable: false,\n });\n }\n\n if (validation.errors.some((error) => error.message.startsWith('Invalid day:'))) {\n suggestions.push({\n message: `Day must be valid for the selected month`,\n autoFixable: false,\n });\n }\n\n if (preventFutureDates && parsed.year > now.getFullYear()) {\n suggestions.push({\n message: `Use current year (${now.getFullYear()}) or a past year`,\n fix: `npm version ${formatCalVerVersion({ ...parsed, year: now.getFullYear() })}`,\n autoFixable: true,\n });\n }\n\n if (\n preventFutureDates &&\n parsed.year === now.getFullYear() &&\n parsed.month > now.getMonth() + 1\n ) {\n suggestions.push({\n message: `Current month is ${now.getMonth() + 1}`,\n fix: `npm version ${formatCalVerVersion({ ...parsed, month: now.getMonth() + 1 })}`,\n autoFixable: true,\n });\n }\n\n if (\n preventFutureDates &&\n parsed.year === now.getFullYear() &&\n parsed.month === now.getMonth() + 1 &&\n parsed.day !== undefined &&\n parsed.day > now.getDate()\n ) {\n suggestions.push({\n message: `Current day is ${now.getDate()}`,\n fix: `npm version ${formatCalVerVersion({ ...parsed, day: now.getDate() })}`,\n autoFixable: true,\n });\n }\n\n // Check progression\n if (previousVersion) {\n const prevParsed = calver.parse(previousVersion, format);\n if (prevParsed) {\n if (calver.compare(version, previousVersion, format) <= 0) {\n errors.push({\n message: `Version ${version} is not newer than previous ${previousVersion}`,\n severity: 'error',\n });\n suggestions.push({\n message: `CalVer must increase over time`,\n fix: `npm version ${calver.increment(previousVersion, format)}`,\n autoFixable: true,\n });\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n suggestions,\n canAutoFix: suggestions.some((s) => s.autoFixable),\n };\n}\n\nfunction formatCalVerVersion(version: CalVer): string {\n return calver.format({\n ...version,\n raw: version.raw || '',\n });\n}\n\n/**\n * Generates suggestions for version sync mismatches in a file.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * The returned suggestions include a general sync command and may include\n * file-type-specific hints for markdown or source files.\n *\n * @param file - File containing the mismatched version string.\n * @param foundVersion - Version currently found in the file.\n * @param expectedVersion - Version that should appear in the file.\n * @returns Suggestions for resolving the mismatch.\n *\n * @example\n * ```typescript\n * const suggestions = getSyncFeedback('README.md', '1.0.0', '1.0.1');\n * console.log(suggestions[0]?.message);\n * ```\n */\nexport function getSyncFeedback(\n file: string,\n foundVersion: string,\n expectedVersion: string,\n): Suggestion[] {\n const suggestions: Suggestion[] = [\n {\n message: `${file} has version \"${foundVersion}\" but should be \"${expectedVersion}\"`,\n fix: `npx versionguard sync`,\n autoFixable: true,\n },\n ];\n\n // Common patterns\n if (file.endsWith('.md')) {\n suggestions.push({\n message: `For markdown files, check headers like \"## [${expectedVersion}]\"`,\n autoFixable: false,\n });\n }\n\n if (file.endsWith('.ts') || file.endsWith('.js')) {\n suggestions.push({\n message: `For code files, check constants like \"export const VERSION = '${expectedVersion}'\"`,\n autoFixable: false,\n });\n }\n\n return suggestions;\n}\n\n/**\n * Generates suggestions for changelog-related validation issues.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper suggests either creating a missing entry or reconciling the latest\n * changelog version with the package version.\n *\n * @param hasEntry - Whether the changelog already contains an entry for the version.\n * @param version - Package version that should appear in the changelog.\n * @param latestChangelogVersion - Most recent version currently found in the changelog.\n * @returns Suggestions for bringing changelog state back into sync.\n *\n * @example\n * ```typescript\n * const suggestions = getChangelogFeedback(false, '1.2.3', '1.2.2');\n * console.log(suggestions.length > 0);\n * ```\n */\nexport function getChangelogFeedback(\n hasEntry: boolean,\n version: string,\n latestChangelogVersion?: string,\n): Suggestion[] {\n const suggestions: Suggestion[] = [];\n\n if (!hasEntry) {\n suggestions.push({\n message: `CHANGELOG.md is missing entry for version ${version}`,\n fix: `npx versionguard fix`,\n autoFixable: true,\n });\n\n suggestions.push({\n message: `Or manually add: \"## [${version}] - YYYY-MM-DD\" under [Unreleased]`,\n autoFixable: false,\n });\n }\n\n if (latestChangelogVersion && latestChangelogVersion !== version) {\n suggestions.push({\n message: `CHANGELOG.md latest entry is ${latestChangelogVersion}, but package.json is ${version}`,\n fix: `Make sure versions are in sync`,\n autoFixable: false,\n });\n }\n\n return suggestions;\n}\n\n/**\n * Generates suggestions for git tag mismatches.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper focuses on discrepancies between git tag versions, package.json,\n * and repository files that still need to be synchronized.\n *\n * @param tagVersion - Version represented by the git tag.\n * @param packageVersion - Version currently stored in `package.json`.\n * @param hasUnsyncedFiles - Whether repository files are still out of sync.\n * @returns Suggestions for correcting tag-related issues.\n *\n * @example\n * ```typescript\n * const suggestions = getTagFeedback('v1.2.2', '1.2.3', true);\n * console.log(suggestions.map((item) => item.message));\n * ```\n */\nexport function getTagFeedback(\n tagVersion: string,\n packageVersion: string,\n hasUnsyncedFiles: boolean,\n): Suggestion[] {\n const suggestions: Suggestion[] = [];\n\n if (tagVersion !== packageVersion) {\n suggestions.push({\n message: `Git tag \"${tagVersion}\" doesn't match package.json \"${packageVersion}\"`,\n fix: `Delete tag and recreate: git tag -d ${tagVersion} && git tag ${packageVersion}`,\n autoFixable: false,\n });\n }\n\n if (hasUnsyncedFiles) {\n suggestions.push({\n message: `Files are out of sync with version ${packageVersion}`,\n fix: `npx versionguard sync`,\n autoFixable: true,\n });\n }\n\n return suggestions;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport * as calver from '../calver';\nimport { addVersionEntry } from '../changelog';\nimport { getPackageVersion, setPackageVersion } from '../project';\nimport * as semver from '../semver';\nimport { syncVersion } from '../sync';\nimport type { CalVerConfig, VersionGuardConfig } from '../types';\n\n/**\n * Auto-fix helpers for package versions, synced files, and changelog entries.\n *\n * @packageDocumentation\n * @public\n */\n\n/**\n * Fix entry point exports for auto-remediation helpers.\n *\n * @packageDocumentation\n * @public\n * @since 0.1.0\n * @forgeIgnore E020\n */\nexport interface FixResult {\n /**\n * Indicates whether the operation changed repository state.\n */\n fixed: boolean;\n\n /**\n * Human-readable description of the fix attempt.\n */\n message: string;\n\n /**\n * Absolute path to the file that was updated, when applicable.\n *\n * @defaultValue `undefined`\n */\n file?: string;\n}\n\n/**\n * Updates the `package.json` version field when needed.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper writes the target version only when `package.json` exists and the\n * current version differs from the requested value.\n *\n * @param targetVersion - Version that should be written to `package.json`.\n * @param cwd - Repository directory containing `package.json`.\n * @returns The result of the package version fix attempt.\n *\n * @example\n * ```typescript\n * const result = fixPackageVersion('1.2.3', process.cwd());\n * console.log(result.fixed);\n * ```\n */\nexport function fixPackageVersion(targetVersion: string, cwd: string = process.cwd()): FixResult {\n const packagePath = path.join(cwd, 'package.json');\n\n if (!fs.existsSync(packagePath)) {\n return { fixed: false, message: 'package.json not found' };\n }\n\n const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf-8')) as { version?: string };\n const oldVersion = typeof pkg.version === 'string' ? pkg.version : undefined;\n\n if (oldVersion === targetVersion) {\n return { fixed: false, message: `Already at version ${targetVersion}` };\n }\n\n setPackageVersion(targetVersion, cwd);\n\n return {\n fixed: true,\n message: `Updated package.json from ${oldVersion} to ${targetVersion}`,\n file: packagePath,\n };\n}\n\n/**\n * Synchronizes configured files to the package version.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper uses the configured sync targets to update version strings across\n * the repository and reports only the files that changed.\n *\n * @param config - Loaded VersionGuard configuration.\n * @param cwd - Repository directory to synchronize.\n * @returns A list of per-file sync results.\n *\n * @example\n * ```typescript\n * const results = fixSyncIssues(config, process.cwd());\n * console.log(results.length);\n * ```\n */\nexport function fixSyncIssues(\n config: VersionGuardConfig,\n cwd: string = process.cwd(),\n): FixResult[] {\n const version = getPackageVersion(cwd);\n const results: FixResult[] = syncVersion(version, config.sync, cwd)\n .filter((result) => result.updated)\n .map((result) => ({\n fixed: true,\n message: `Updated ${path.relative(cwd, result.file)} (${result.changes.length} changes)`,\n file: result.file,\n }));\n\n if (results.length === 0) {\n results.push({ fixed: false, message: 'All files already in sync' });\n }\n\n return results;\n}\n\n/**\n * Ensures the changelog contains an entry for a version.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * When the changelog file does not exist, this helper creates a starter changelog.\n * Otherwise it appends a new version entry only when one is missing.\n *\n * @param version - Version that should appear in the changelog.\n * @param config - Loaded VersionGuard configuration.\n * @param cwd - Repository directory containing the changelog file.\n * @returns The result of the changelog fix attempt.\n *\n * @example\n * ```typescript\n * const result = fixChangelog('1.2.3', config, process.cwd());\n * console.log(result.message);\n * ```\n */\nexport function fixChangelog(\n version: string,\n config: VersionGuardConfig,\n cwd: string = process.cwd(),\n): FixResult {\n const changelogPath = path.join(cwd, config.changelog.file);\n\n if (!fs.existsSync(changelogPath)) {\n // Create initial changelog\n createInitialChangelog(changelogPath, version);\n return {\n fixed: true,\n message: `Created ${config.changelog.file} with entry for ${version}`,\n file: changelogPath,\n };\n }\n\n const content = fs.readFileSync(changelogPath, 'utf-8');\n\n if (content.includes(`## [${version}]`)) {\n return { fixed: false, message: `Changelog already has entry for ${version}` };\n }\n\n addVersionEntry(changelogPath, version);\n\n return {\n fixed: true,\n message: `Added entry for ${version} to ${config.changelog.file}`,\n file: changelogPath,\n };\n}\n\n/**\n * Create initial changelog\n */\nfunction createInitialChangelog(changelogPath: string, version: string): void {\n const today = new Date().toISOString().slice(0, 10);\n const content = `# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n## [${version}] - ${today}\n\n### Added\n\n- Initial release\n\n[Unreleased]: https://github.com/yourorg/project/compare/v${version}...HEAD\n[${version}]: https://github.com/yourorg/project/releases/tag/v${version}\n`;\n\n fs.writeFileSync(changelogPath, content, 'utf-8');\n}\n\n/**\n * Runs all configured auto-fix operations.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper optionally updates the package version first, then synchronizes\n * configured files, and finally updates the changelog when changelog support is\n * enabled.\n *\n * @param config - Loaded VersionGuard configuration.\n * @param targetVersion - Optional version to apply before running other fixes.\n * @param cwd - Repository directory where fixes should run.\n * @returns Ordered results describing every fix step that ran.\n *\n * @example\n * ```typescript\n * const results = fixAll(config, '1.2.3', process.cwd());\n * console.log(results.some((result) => result.fixed));\n * ```\n */\nexport function fixAll(\n config: VersionGuardConfig,\n targetVersion?: string,\n cwd: string = process.cwd(),\n): FixResult[] {\n const results: FixResult[] = [];\n const version = targetVersion || getPackageVersion(cwd);\n\n if (targetVersion && targetVersion !== getPackageVersion(cwd)) {\n results.push(fixPackageVersion(targetVersion, cwd));\n }\n\n const syncResults = fixSyncIssues(config, cwd);\n results.push(...syncResults);\n\n if (config.changelog.enabled) {\n const changelogResult = fixChangelog(version, config, cwd);\n if (changelogResult.fixed) {\n results.push(changelogResult);\n }\n }\n\n return results;\n}\n\n/**\n * Suggests candidate next versions for a release.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * The suggestions depend on the configured versioning mode. SemVer returns one or\n * more bump options, while CalVer suggests the current date-based version and an\n * incremented same-day release.\n *\n * @param currentVersion - Current package version.\n * @param config - Loaded VersionGuard configuration.\n * @param changeType - Preferred bump type, or `auto` to include common options.\n * @returns Candidate versions paired with the reason for each suggestion.\n *\n * @example\n * ```typescript\n * const suggestions = suggestNextVersion('1.2.3', config, 'minor');\n * console.log(suggestions[0]?.version);\n * ```\n */\nexport function suggestNextVersion(\n currentVersion: string,\n config: VersionGuardConfig,\n changeType?: 'major' | 'minor' | 'patch' | 'auto',\n): { version: string; reason: string }[] {\n const suggestions: { version: string; reason: string }[] = [];\n\n if (config.versioning.type === 'semver') {\n if (!changeType || changeType === 'auto' || changeType === 'patch') {\n suggestions.push({\n version: semver.increment(currentVersion, 'patch'),\n reason: 'Patch - bug fixes, small changes',\n });\n }\n\n if (!changeType || changeType === 'auto' || changeType === 'minor') {\n suggestions.push({\n version: semver.increment(currentVersion, 'minor'),\n reason: 'Minor - new features, backwards compatible',\n });\n }\n\n if (!changeType || changeType === 'auto' || changeType === 'major') {\n suggestions.push({\n version: semver.increment(currentVersion, 'major'),\n reason: 'Major - breaking changes',\n });\n }\n } else {\n // CalVer\n const format = getCalVerConfig(config).format;\n const currentCal = calver.getCurrentVersion(format);\n\n // Option 1: Current date\n suggestions.push({\n version: currentCal,\n reason: 'Current date - new release today',\n });\n\n // Option 2: Increment patch on current version\n suggestions.push({\n version: calver.increment(currentVersion, format),\n reason: 'Increment patch - additional release today',\n });\n }\n\n return suggestions;\n}\n\nfunction getCalVerConfig(config: VersionGuardConfig): CalVerConfig {\n if (!config.versioning.calver) {\n throw new Error('CalVer configuration is required when versioning.type is \"calver\"');\n }\n\n return config.versioning.calver;\n}\n","import * as childProcess from 'node:child_process';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport { validate as validateCalVer } from '../calver';\nimport { validateChangelog } from '../changelog';\nimport { fixAll } from '../fix';\nimport { areHooksInstalled } from '../hooks';\nimport { getPackageVersion } from '../project';\nimport { validate as validateSemVer } from '../semver';\nimport { checkHardcodedVersions } from '../sync';\nimport type { VersionGuardConfig } from '../types';\n\n/**\n * Tag management helpers for reading, validating, and creating release tags.\n *\n * @packageDocumentation\n * @public\n */\n\n/**\n * Tag entry point exports for release-tag management helpers.\n *\n * @packageDocumentation\n * @public\n * @since 0.1.0\n * @forgeIgnore E020\n */\nexport interface TagInfo {\n /**\n * Full git tag name, including any prefix such as `v`.\n */\n name: string;\n\n /**\n * Normalized version string derived from the tag name.\n */\n version: string;\n\n /**\n * Annotated tag message when one is available.\n *\n * @defaultValue `undefined`\n */\n message?: string;\n\n /**\n * Timestamp associated with the tag lookup result.\n */\n date: Date;\n}\n\nfunction runGit(cwd: string, args: string[], encoding?: BufferEncoding): string | Buffer {\n return childProcess.execFileSync('git', args, {\n cwd,\n encoding,\n stdio: ['pipe', 'pipe', 'ignore'],\n });\n}\n\nfunction runGitText(cwd: string, args: string[]): string {\n return runGit(cwd, args, 'utf-8') as string;\n}\n\n/**\n * Returns the most recent reachable git tag for a repository.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper reads the most recent annotated or lightweight tag that `git describe`\n * can resolve from the current HEAD. It returns `null` when no tags are available\n * or when git metadata cannot be read.\n *\n * @param cwd - Repository directory to inspect.\n * @returns The latest tag details, or `null` when no tag can be resolved.\n *\n * @example\n * ```typescript\n * const latestTag = getLatestTag(process.cwd());\n *\n * if (latestTag) {\n * console.log(latestTag.version);\n * }\n * ```\n */\nexport function getLatestTag(cwd: string = process.cwd()): TagInfo | null {\n try {\n const result = runGitText(cwd, ['describe', '--tags', '--abbrev=0']);\n\n const tagName = result.trim();\n const version = tagName.replace(/^v/, '');\n\n const dateResult = runGitText(cwd, ['log', '-1', '--format=%ai', tagName]);\n const messageResult = runGitText(cwd, ['tag', '-l', tagName, '--format=%(contents)']);\n const message = messageResult.trim();\n\n return {\n name: tagName,\n version,\n message: message.length > 0 ? message : undefined,\n date: new Date(dateResult.trim()),\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Lists all tags in a repository.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper returns tag names in the order provided by `git tag --list`. The\n * `date` field is populated with the current time because the implementation does\n * not perform per-tag date lookups.\n *\n * @param cwd - Repository directory to inspect.\n * @returns A list of discovered tags, or an empty array when tags cannot be read.\n *\n * @example\n * ```typescript\n * const tags = getAllTags(process.cwd());\n * console.log(tags.map((tag) => tag.name));\n * ```\n */\nexport function getAllTags(cwd: string = process.cwd()): TagInfo[] {\n try {\n const result = runGitText(cwd, ['tag', '--list']);\n\n return result\n .trim()\n .split('\\n')\n .filter(Boolean)\n .map((name) => ({\n name,\n version: name.replace(/^v/, ''),\n date: new Date(), // Would need individual lookup for accurate dates\n }));\n } catch {\n return [];\n }\n}\n\n/**\n * Creates a release tag and optionally fixes version state first.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * When `autoFix` is enabled, this helper updates versioned files, stages the\n * changes, and creates a release commit before creating the annotated tag. It\n * returns a structured result instead of throwing for most expected failures.\n *\n * @param version - Version to embed in the new tag name.\n * @param message - Custom annotated tag message.\n * @param autoFix - Whether to auto-fix version mismatches before tagging.\n * @param config - Loaded VersionGuard configuration used for validation and fixes.\n * @param cwd - Repository directory where git commands should run.\n * @returns The tagging outcome and any actions performed along the way.\n *\n * @example\n * ```typescript\n * const result = createTag('1.2.3', 'Release 1.2.3', true, config, process.cwd());\n *\n * if (!result.success) {\n * console.error(result.message);\n * }\n * ```\n */\nexport function createTag(\n version: string,\n message?: string,\n autoFix: boolean = true,\n config?: VersionGuardConfig,\n cwd: string = process.cwd(),\n): { success: boolean; message: string; actions: string[] } {\n const actions: string[] = [];\n\n try {\n if (!config) {\n return {\n success: false,\n message: 'VersionGuard config is required to create tags safely',\n actions,\n };\n }\n\n const packageVersion = getPackageVersion(cwd);\n const shouldAutoFix = autoFix;\n const preflightError = getTagPreflightError(config, cwd, version, shouldAutoFix);\n if (preflightError) {\n return {\n success: false,\n message: preflightError,\n actions,\n };\n }\n\n if (version !== packageVersion && !autoFix) {\n return {\n success: false,\n message: `Version mismatch: package.json is ${packageVersion}, tag is ${version}`,\n actions: [],\n };\n }\n\n if (autoFix) {\n const fixResults =\n version !== packageVersion ? fixAll(config, version, cwd) : fixAll(config, undefined, cwd);\n\n for (const result of fixResults) {\n if (result.fixed) {\n actions.push(result.message);\n }\n }\n\n if (fixResults.some((result) => result.fixed)) {\n runGit(cwd, ['add', '-A']);\n runGit(cwd, ['commit', '--no-verify', '-m', `chore(release): ${version}`]);\n actions.push('Committed version changes');\n }\n }\n\n const tagName = `v${version}`;\n const tagMessage = message || `Release ${version}`;\n\n if (getAllTags(cwd).some((tag) => tag.name === tagName)) {\n return {\n success: false,\n message: `Tag ${tagName} already exists`,\n actions,\n };\n }\n\n runGit(cwd, ['tag', '-a', tagName, '-m', tagMessage]);\n actions.push(`Created tag ${tagName}`);\n\n return {\n success: true,\n message: `Successfully created tag ${tagName}`,\n actions,\n };\n } catch (err) {\n return {\n success: false,\n message: `Failed to create tag: ${(err as Error).message}`,\n actions,\n };\n }\n}\n\n/**\n * Runs post-tag validation and sync checks.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper is intended for the `post-tag` git hook flow. It validates the\n * latest tag against the configured versioning rules and reports any required\n * follow-up actions without mutating git history.\n *\n * @param config - Loaded VersionGuard configuration used during validation.\n * @param cwd - Repository directory where validation should run.\n * @returns The post-tag workflow result and any follow-up actions.\n *\n * @example\n * ```typescript\n * const result = handlePostTag(config, process.cwd());\n * console.log(result.success);\n * ```\n */\nexport function handlePostTag(\n config: VersionGuardConfig,\n cwd: string = process.cwd(),\n): { success: boolean; message: string; actions: string[] } {\n const actions: string[] = [];\n\n try {\n const preflightError = getTagPreflightError(config, cwd);\n if (preflightError) {\n return {\n success: false,\n message: preflightError,\n actions,\n };\n }\n\n const tag = getLatestTag(cwd);\n if (!tag) {\n return {\n success: false,\n message: 'No tag found',\n actions,\n };\n }\n const packageVersion = getPackageVersion(cwd);\n\n if (tag.version !== packageVersion) {\n return {\n success: false,\n message: `Tag version ${tag.version} doesn't match package.json ${packageVersion}`,\n actions: [\n 'To fix: delete tag and recreate with correct version',\n ` git tag -d ${tag.name}`,\n ` npm version ${tag.version}`,\n ` git tag ${tag.name}`,\n ],\n };\n }\n const syncResults = fixAll(config, packageVersion, cwd);\n\n for (const result of syncResults) {\n /* v8 ignore next 3 -- preflight blocks remaining post-tag fixes */\n if (result.fixed) {\n actions.push(result.message);\n }\n }\n\n return {\n success: true,\n message: `Post-tag workflow completed for ${tag.name}`,\n actions,\n };\n } catch (err) {\n return {\n success: false,\n message: `Post-tag workflow failed: ${(err as Error).message}`,\n actions,\n };\n }\n}\n\nfunction getTagPreflightError(\n config: VersionGuardConfig,\n cwd: string,\n expectedVersion?: string,\n allowAutoFix: boolean = false,\n): string | null {\n if (config.git.enforceHooks && !areHooksInstalled(cwd)) {\n return 'Git hooks must be installed before creating or validating release tags';\n }\n\n if (hasDirtyWorktree(cwd)) {\n return 'Working tree must be clean before creating or validating release tags';\n }\n\n const version = expectedVersion ?? getPackageVersion(cwd);\n const versionResult =\n config.versioning.type === 'semver'\n ? validateSemVer(version)\n : validateCalVer(\n version,\n config.versioning.calver?.format ?? 'YYYY.MM.PATCH',\n config.versioning.calver?.preventFutureDates ?? true,\n );\n\n if (!versionResult.valid) {\n return versionResult.errors[0]?.message ?? `Invalid version: ${version}`;\n }\n\n if (allowAutoFix) {\n return null;\n }\n\n const mismatches = checkHardcodedVersions(version, config.sync, config.ignore, cwd);\n if (mismatches.length > 0) {\n const mismatch = mismatches[0];\n return `Version mismatch in ${mismatch.file}:${mismatch.line} - found \"${mismatch.found}\" but expected \"${version}\"`;\n }\n\n const changelogResult = validateChangelog(\n path.join(cwd, config.changelog.file),\n version,\n config.changelog.strict,\n config.changelog.requireEntry,\n );\n if (!changelogResult.valid) {\n return changelogResult.errors[0] ?? 'Changelog validation failed';\n }\n\n return null;\n}\n\nfunction hasDirtyWorktree(cwd: string): boolean {\n try {\n return runGitText(cwd, ['status', '--porcelain']).trim().length > 0;\n } catch {\n return true;\n }\n}\n\n/**\n * Validates that a local tag is safe to push to the default remote.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper checks that the tag exists locally and, when the tag also exists on\n * `origin`, verifies that both references point to the same commit.\n *\n * @param tagName - Name of the tag to validate.\n * @param cwd - Repository directory where git commands should run.\n * @returns A validation result with an optional suggested fix command.\n *\n * @example\n * ```typescript\n * const result = validateTagForPush('v1.2.3', process.cwd());\n * console.log(result.valid);\n * ```\n */\nexport function validateTagForPush(\n tagName: string,\n cwd: string = process.cwd(),\n): { valid: boolean; message: string; fix?: string } {\n try {\n runGit(cwd, ['rev-parse', tagName]);\n\n try {\n runGit(cwd, ['ls-remote', '--tags', 'origin', tagName]);\n\n const localHash = runGitText(cwd, ['rev-parse', tagName]).trim();\n const remoteOutput = runGitText(cwd, ['ls-remote', '--tags', 'origin', tagName]).trim();\n\n if (remoteOutput && !remoteOutput.includes(localHash)) {\n return {\n valid: false,\n message: `Tag ${tagName} exists on remote with different commit`,\n fix: `Delete remote tag first: git push origin :refs/tags/${tagName}`,\n };\n }\n } catch {\n return { valid: true, message: `Tag ${tagName} is valid for push` };\n }\n\n return { valid: true, message: `Tag ${tagName} is valid for push` };\n } catch {\n return {\n valid: false,\n message: `Tag ${tagName} not found locally`,\n fix: `Create tag: git tag ${tagName}`,\n };\n }\n}\n\n/**\n * Suggests an annotated tag message from changelog content.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * When a matching changelog entry exists, this helper uses the first bullet point\n * as a concise release summary. It falls back to a generic `Release {version}`\n * message when no changelog context is available.\n *\n * @param version - Version that the tag will represent.\n * @param cwd - Repository directory containing the changelog file.\n * @returns A suggested annotated tag message.\n *\n * @example\n * ```typescript\n * const message = suggestTagMessage('1.2.3', process.cwd());\n * console.log(message);\n * ```\n */\nexport function suggestTagMessage(version: string, cwd: string = process.cwd()): string {\n try {\n const changelogPath = path.join(cwd, 'CHANGELOG.md');\n if (fs.existsSync(changelogPath)) {\n const content = fs.readFileSync(changelogPath, 'utf-8');\n\n const versionRegex = new RegExp(\n `## \\\\[${version}\\\\].*?\\\\n(.*?)(?=\\\\n## \\\\[|\\\\n\\\\n## |$)`,\n 's',\n );\n const match = content.match(versionRegex);\n\n if (match) {\n const bulletMatch = match[1].match(/- (.+)/);\n if (bulletMatch) {\n return `Release ${version}: ${bulletMatch[1].trim()}`;\n }\n }\n }\n } catch {\n return `Release ${version}`;\n }\n\n return `Release ${version}`;\n}\n","/**\n * Public API for VersionGuard.\n *\n * @packageDocumentation\n * @public\n */\n\nimport { execSync } from 'node:child_process';\nimport * as path from 'node:path';\n\nimport * as calver from './calver';\nimport { validateChangelog } from './changelog';\nimport { areHooksInstalled, findGitDir } from './hooks';\nimport { getPackageVersion } from './project';\nimport * as semver from './semver';\nimport { checkHardcodedVersions, syncVersion } from './sync';\nimport type {\n CalVerConfig,\n DoctorReport,\n FullValidationResult,\n ValidationResult,\n VersionGuardConfig,\n} from './types';\n\nexport * as calver from './calver';\nexport { validateChangelog } from './changelog';\nexport { getConfig, initConfig } from './config';\nexport * from './feedback';\nexport * from './fix';\nexport { areHooksInstalled, installHooks, uninstallHooks } from './hooks';\nexport { getPackageVersion } from './project';\nexport * as semver from './semver';\nexport { checkHardcodedVersions, syncVersion } from './sync';\nexport * from './tag';\nexport * from './types';\n\n/**\n * Validates a version string against the active versioning strategy.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper dispatches to SemVer or CalVer validation based on\n * `config.versioning.type`.\n *\n * @param version - Version string to validate.\n * @param config - VersionGuard configuration that selects the validation rules.\n * @returns The validation result for the provided version.\n * @example\n * ```ts\n * import { getDefaultConfig, validateVersion } from 'versionguard';\n *\n * const result = validateVersion('1.2.3', getDefaultConfig());\n * ```\n */\nexport function validateVersion(version: string, config: VersionGuardConfig): ValidationResult {\n if (config.versioning.type === 'semver') {\n return semver.validate(version);\n }\n\n const calverConfig = getCalVerConfig(config);\n return calver.validate(version, calverConfig.format, calverConfig.preventFutureDates);\n}\n\n/**\n * Validates the current project state against the supplied configuration.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This reads the package version from `package.json`, validates the version\n * format, checks synchronized files, and optionally validates the changelog.\n *\n * @param config - VersionGuard configuration to apply.\n * @param cwd - Project directory to inspect.\n * @returns A full validation report for the project rooted at `cwd`.\n * @example\n * ```ts\n * import { getDefaultConfig, validate } from 'versionguard';\n *\n * const result = validate(getDefaultConfig(), process.cwd());\n * ```\n */\nexport function validate(\n config: VersionGuardConfig,\n cwd: string = process.cwd(),\n): FullValidationResult {\n const errors: string[] = [];\n\n let version: string;\n try {\n version = getPackageVersion(cwd);\n } catch (err) {\n return {\n valid: false,\n version: '',\n versionValid: false,\n syncValid: false,\n changelogValid: false,\n errors: [(err as Error).message],\n };\n }\n\n const versionResult = validateVersion(version, config);\n if (!versionResult.valid) {\n errors.push(...versionResult.errors.map((error) => error.message));\n }\n\n const hardcoded = checkHardcodedVersions(version, config.sync, config.ignore, cwd);\n\n if (hardcoded.length > 0) {\n for (const mismatch of hardcoded) {\n errors.push(\n `Version mismatch in ${mismatch.file}:${mismatch.line} - found \"${mismatch.found}\" but expected \"${version}\"`,\n );\n }\n }\n\n let changelogValid = true;\n if (config.changelog.enabled) {\n const changelogPath = path.join(cwd, config.changelog.file);\n const changelogResult = validateChangelog(\n changelogPath,\n version,\n config.changelog.strict,\n config.changelog.requireEntry,\n );\n\n if (!changelogResult.valid) {\n changelogValid = false;\n errors.push(...changelogResult.errors);\n }\n }\n\n return {\n valid: errors.length === 0,\n version,\n versionValid: versionResult.valid,\n syncValid: hardcoded.length === 0,\n changelogValid,\n errors,\n };\n}\n\n/**\n * Runs an extended readiness check for a project.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * In addition to `validate`, this inspects Git state so callers can determine\n * whether hooks are installed and the worktree is clean.\n *\n * @param config - VersionGuard configuration to apply.\n * @param cwd - Project directory to inspect.\n * @returns A readiness report that includes validation and Git diagnostics.\n * @example\n * ```ts\n * import { doctor, getDefaultConfig } from 'versionguard';\n *\n * const report = doctor(getDefaultConfig(), process.cwd());\n * ```\n */\nexport function doctor(config: VersionGuardConfig, cwd: string = process.cwd()): DoctorReport {\n const validation = validate(config, cwd);\n const gitRepository = findGitDir(cwd) !== null;\n const hooksInstalled = gitRepository ? areHooksInstalled(cwd) : false;\n const worktreeClean = gitRepository ? isWorktreeClean(cwd) : true;\n const errors = [...validation.errors];\n\n if (gitRepository && config.git.enforceHooks && !hooksInstalled) {\n errors.push('Git hooks are not installed');\n }\n\n if (gitRepository && !worktreeClean) {\n errors.push('Working tree is not clean');\n }\n\n return {\n ready: errors.length === 0,\n version: validation.version,\n versionValid: validation.versionValid,\n syncValid: validation.syncValid,\n changelogValid: validation.changelogValid,\n gitRepository,\n hooksInstalled,\n worktreeClean,\n errors,\n };\n}\n\n/**\n * Synchronizes configured files to the current package version.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This reads the version from `package.json` and rewrites configured files\n * using the sync patterns defined in the VersionGuard config.\n *\n * @param config - VersionGuard configuration containing sync rules.\n * @param cwd - Project directory whose files should be synchronized.\n * @example\n * ```ts\n * import { getDefaultConfig, sync } from 'versionguard';\n *\n * sync(getDefaultConfig(), process.cwd());\n * ```\n */\nexport function sync(config: VersionGuardConfig, cwd: string = process.cwd()): void {\n const version = getPackageVersion(cwd);\n syncVersion(version, config.sync, cwd);\n}\n\n/**\n * Determines whether a project can move from one version to another.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * Both the current and proposed versions must validate against the configured\n * versioning scheme, and the new version must compare greater than the current\n * version.\n *\n * @param currentVersion - Version currently in use.\n * @param newVersion - Proposed next version.\n * @param config - VersionGuard configuration that defines version rules.\n * @returns An object indicating whether the bump is allowed and why it failed.\n * @example\n * ```ts\n * import { canBump, getDefaultConfig } from 'versionguard';\n *\n * const result = canBump('1.2.3', '1.3.0', getDefaultConfig());\n * ```\n */\nexport function canBump(\n currentVersion: string,\n newVersion: string,\n config: VersionGuardConfig,\n): { canBump: boolean; error?: string } {\n const currentValid = validateVersion(currentVersion, config);\n const newValid = validateVersion(newVersion, config);\n\n if (!currentValid.valid) {\n return { canBump: false, error: `Current version is invalid: ${currentVersion}` };\n }\n\n if (!newValid.valid) {\n return { canBump: false, error: `New version is invalid: ${newVersion}` };\n }\n\n if (config.versioning.type === 'semver') {\n if (!semver.gt(newVersion, currentVersion)) {\n return {\n canBump: false,\n error: `New version ${newVersion} must be greater than current ${currentVersion}`,\n };\n }\n } else {\n const calverConfig = getCalVerConfig(config);\n const currentParsed = calver.parse(currentVersion, calverConfig.format);\n const newParsed = calver.parse(newVersion, calverConfig.format);\n\n if (!currentParsed || !newParsed) {\n return { canBump: false, error: 'Failed to parse CalVer versions' };\n }\n\n if (calver.compare(newVersion, currentVersion, calverConfig.format) <= 0) {\n return {\n canBump: false,\n error: `New CalVer ${newVersion} must be newer than current ${currentVersion}`,\n };\n }\n }\n\n return { canBump: true };\n}\n\nfunction getCalVerConfig(config: VersionGuardConfig): CalVerConfig {\n if (!config.versioning.calver) {\n throw new Error('CalVer configuration is required when versioning.type is \"calver\"');\n }\n\n return config.versioning.calver;\n}\n\nfunction isWorktreeClean(cwd: string): boolean {\n try {\n return execSync('git status --porcelain', { cwd, encoding: 'utf-8' }).trim().length === 0;\n } catch {\n return false;\n }\n}\n"],"names":["parse","validate","format","compare","increment","getCalVerConfig","semver.parse","semver.validate","semver.compare","semver.increment","calver.parse","calver.getCurrentVersion","calver.validate","calver.compare","calver.increment","calver.format","validateSemVer","validateCalVer","semver.gt"],"mappings":";;;;;;;AA8DO,SAAS,YAAY,cAAgD;AAC1E,QAAM,QAAQ,aAAa,MAAM,GAAG;AACpC,QAAM,SAA6B;AAAA,IACjC,MAAM,MAAM,CAAC;AAAA,IACb,OAAO,MAAM,CAAC;AAAA,EAAA;AAGhB,MAAI,MAAM,CAAC,MAAM,SAAS;AACxB,WAAO,QAAQ;AAAA,EACjB,WAAW,MAAM,CAAC,GAAG;AACnB,WAAO,MAAM,MAAM,CAAC;AAAA,EACtB;AAEA,MAAI,MAAM,CAAC,MAAM,SAAS;AACxB,WAAO,QAAQ;AAAA,EACjB;AAEA,SAAO;AACT;AAEA,SAAS,aAAa,OAAuB;AAC3C,UAAQ,OAAA;AAAA,IACN,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,YAAM,IAAI,MAAM,6BAA6B,KAAK,EAAE;AAAA,EAAA;AAE1D;AAuBO,SAAS,kBAAkB,cAAoC;AACpE,QAAM,SAAS,aAAa,MAAM,GAAG;AACrC,QAAM,UAAU,OAAO,IAAI,YAAY,EAAE,KAAK,KAAK;AACnD,SAAO,IAAI,OAAO,IAAI,OAAO,GAAG;AAClC;AAyBO,SAASA,QAAM,SAAiB,cAA2C;AAChF,QAAM,QAAQ,QAAQ,MAAM,kBAAkB,YAAY,CAAC;AAE3D,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,YAAY,YAAY;AAC3C,QAAM,OACJ,WAAW,SAAS,SAChB,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,IAC5B,MAAO,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE;AACzC,QAAM,QAAQ,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE;AAE1C,MAAI,SAAS;AACb,MAAI;AACJ,MAAI;AAEJ,MAAI,WAAW,KAAK;AAClB,UAAM,OAAO,SAAS,MAAM,MAAM,GAAG,EAAE;AACvC,cAAU;AAAA,EACZ;AAEA,MAAI,WAAW,OAAO;AACpB,YAAQ,OAAO,SAAS,MAAM,MAAM,GAAG,EAAE;AAAA,EAC3C;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,KAAK;AAAA,EAAA;AAET;AAyBO,SAASC,WACd,SACA,cACA,qBAA8B,MACZ;AAClB,QAAM,SAA4B,CAAA;AAClC,QAAM,SAASD,QAAM,SAAS,YAAY;AAE1C,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,QACN;AAAA,UACE,SAAS,2BAA2B,OAAO,uBAAuB,YAAY;AAAA,UAC9E,UAAU;AAAA,QAAA;AAAA,MACZ;AAAA,IACF;AAAA,EAEJ;AAEA,MAAI,OAAO,QAAQ,KAAK,OAAO,QAAQ,IAAI;AACzC,WAAO,KAAK;AAAA,MACV,SAAS,kBAAkB,OAAO,KAAK;AAAA,MACvC,UAAU;AAAA,IAAA,CACX;AAAA,EACH;AAEA,MAAI,OAAO,QAAQ,QAAW;AAC5B,QAAI,OAAO,MAAM,KAAK,OAAO,MAAM,IAAI;AACrC,aAAO,KAAK;AAAA,QACV,SAAS,gBAAgB,OAAO,GAAG;AAAA,QACnC,UAAU;AAAA,MAAA,CACX;AAAA,IACH,OAAO;AACL,YAAM,cAAc,IAAI,KAAK,OAAO,MAAM,OAAO,OAAO,CAAC,EAAE,QAAA;AAC3D,UAAI,OAAO,MAAM,aAAa;AAC5B,eAAO,KAAK;AAAA,UACV,SAAS,gBAAgB,OAAO,GAAG,KAAK,OAAO,IAAI,IAAI,OAAO,OAAO,KAAK,EAAE,SAAS,GAAG,GAAG,CAAC,aAAa,WAAW;AAAA,UACpH,UAAU;AAAA,QAAA,CACX;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,MAAI,oBAAoB;AACtB,UAAM,0BAAU,KAAA;AAChB,UAAM,cAAc,IAAI,YAAA;AACxB,UAAM,eAAe,IAAI,SAAA,IAAa;AACtC,UAAM,aAAa,IAAI,QAAA;AAEvB,QAAI,OAAO,OAAO,aAAa;AAC7B,aAAO,KAAK;AAAA,QACV,SAAS,4BAA4B,OAAO,IAAI,qBAAqB,WAAW;AAAA,QAChF,UAAU;AAAA,MAAA,CACX;AAAA,IACH,WAAW,OAAO,SAAS,eAAe,OAAO,QAAQ,cAAc;AACrE,aAAO,KAAK;AAAA,QACV,SAAS,6BAA6B,OAAO,IAAI,IAAI,OAAO,KAAK,sBAAsB,YAAY;AAAA,QACnG,UAAU;AAAA,MAAA,CACX;AAAA,IACH,WACE,OAAO,SAAS,eAChB,OAAO,UAAU,gBACjB,OAAO,QAAQ,UACf,OAAO,MAAM,YACb;AACA,aAAO,KAAK;AAAA,QACV,SAAS,2BAA2B,OAAO,IAAI,IAAI,OAAO,KAAK,IAAI,OAAO,GAAG,oBAAoB,UAAU;AAAA,QAC3G,UAAU;AAAA,MAAA,CACX;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,OAAO,WAAW;AAAA,IACzB;AAAA,IACA,SAAS,EAAE,MAAM,UAAU,SAAS,OAAA;AAAA,EAAO;AAE/C;AAEA,SAAS,YAAY,OAAe,OAAuB;AACzD,MAAI,UAAU,QAAQ,UAAU,MAAM;AACpC,WAAO,OAAO,KAAK,EAAE,SAAS,GAAG,GAAG;AAAA,EACtC;AAEA,MAAI,UAAU,MAAM;AAClB,WAAO,OAAO,QAAQ,GAAG,EAAE,SAAS,GAAG,GAAG;AAAA,EAC5C;AAEA,SAAO,OAAO,KAAK;AACrB;AAyBO,SAASE,SAAO,SAAyB;AAC9C,QAAM,SAAS,QAAQ,OAAO,MAAM,GAAG;AACvC,QAAM,SAAmB,CAAC,QAAQ,MAAM,QAAQ,KAAK;AAErD,MAAI,OAAO,SAAS,IAAI,KAAK,OAAO,SAAS,GAAG,KAAK,OAAO,SAAS,IAAI,GAAG;AAC1E,WAAO,KAAK,QAAQ,OAAO,CAAC;AAAA,EAC9B;AAEA,MAAI,OAAO,SAAS,OAAO,GAAG;AAC5B,WAAO,KAAK,QAAQ,SAAS,CAAC;AAAA,EAChC;AAEA,SAAO,OAAO,IAAI,CAAC,OAAO,UAAU,YAAY,OAAO,OAAO,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG;AACjF;AAwBO,SAAS,kBAAkB,cAA4B,MAAY,oBAAI,QAAgB;AAC5F,QAAM,aAAa,YAAY,YAAY;AAC3C,QAAM,aAAa,IAAI,QAAA;AACvB,QAAM,OAAe;AAAA,IACnB,MAAM,IAAI,YAAA;AAAA,IACV,OAAO,IAAI,SAAA,IAAa;AAAA,IACxB,KAAK,WAAW,MAAM,aAAa;AAAA,IACnC,OAAO,WAAW,QAAQ,IAAI;AAAA,EAGhC;AACA,QAAM,MAAM,KAAK,OAAO;AACxB,QAAM,QAAQ,KAAK,SAAS;AAE5B,SAAO,YAAY,WAAW,MAAM,KAAK,IAAI,EAC1C,OAAO,IAAI,YAAY,WAAW,OAAO,KAAK,KAAK,CAAC,EAAE,EACtD,OAAO,WAAW,MAAM,IAAI,YAAY,WAAW,KAAK,GAAG,CAAC,KAAK,EAAE,EACnE,OAAO,WAAW,QAAQ,IAAI,KAAK,KAAK,EAAE;AAC/C;AAyBO,SAASC,UAAQ,GAAW,GAAW,cAAoC;AAChF,QAAM,OAAOH,QAAM,GAAG,YAAY;AAClC,QAAM,QAAQA,QAAM,GAAG,YAAY;AAEnC,MAAI,CAAC,QAAQ,CAAC,OAAO;AACnB,UAAM,IAAI,MAAM,sCAAsC,CAAC,UAAU,CAAC,GAAG;AAAA,EACvE;AAEA,aAAW,OAAO,CAAC,QAAQ,SAAS,OAAO,OAAO,GAAY;AAC5D,UAAM,YAAY,KAAK,GAAG,KAAK;AAC/B,UAAM,aAAa,MAAM,GAAG,KAAK;AACjC,QAAI,cAAc,YAAY;AAC5B,aAAO,YAAY,aAAa,IAAI;AAAA,IACtC;AAAA,EACF;AAEA,SAAO;AACT;AAwBO,SAASI,YAAU,SAAiB,cAAoC;AAC7E,QAAM,SAASJ,QAAM,SAAS,YAAY;AAE1C,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,2BAA2B,OAAO,EAAE;AAAA,EACtD;AAEA,QAAM,aAAa,YAAY,YAAY;AAC3C,QAAM,OAAe;AAAA,IACnB,GAAG;AAAA,EAEL;AAEA,MAAI,WAAW,OAAO;AACpB,UAAM,QAAQ,OAAO,SAAS;AAC9B,SAAK,QAAQ,QAAQ;AAAA,EACvB,OAAO;AACL,SAAK,QAAQ;AACb,SAAK,SAAS,GAAG,YAAY;AAAA,EAC/B;AAEA,SAAOE,SAAO,IAAI;AACpB;AAwBO,SAAS,gBAAgB,gBAAwB,cAAsC;AAC5F,SAAO,CAAC,kBAAkB,YAAY,GAAGE,YAAU,gBAAgB,YAAY,CAAC;AAClF;;;;;;;;;;;;;ACzdA,MAAM,uBAAuB;AAuBtB,SAAS,kBACd,eACA,SACA,SAAkB,MAClB,eAAwB,MACG;AAC3B,MAAI,CAAC,GAAG,WAAW,aAAa,GAAG;AACjC,WAAO;AAAA,MACL,OAAO,CAAC;AAAA,MACR,QAAQ,eAAe,CAAC,wBAAwB,aAAa,EAAE,IAAI,CAAA;AAAA,MACnE,oBAAoB;AAAA,IAAA;AAAA,EAExB;AAEA,QAAM,SAAmB,CAAA;AACzB,QAAM,UAAU,GAAG,aAAa,eAAe,OAAO;AAEtD,MAAI,CAAC,QAAQ,WAAW,aAAa,GAAG;AACtC,WAAO,KAAK,yCAAyC;AAAA,EACvD;AAEA,MAAI,CAAC,QAAQ,SAAS,iBAAiB,GAAG;AACxC,WAAO,KAAK,6CAA6C;AAAA,EAC3D;AAEA,QAAM,gBAAgB,OAAO,OAAO;AACpC,QAAM,qBAAqB,QAAQ,SAAS,aAAa;AACzD,MAAI,gBAAgB,CAAC,oBAAoB;AACvC,WAAO,KAAK,4CAA4C,OAAO,EAAE;AAAA,EACnE;AAEA,MAAI,QAAQ;AACV,QAAI,CAAC,QAAQ,SAAS,eAAe,GAAG;AACtC,aAAO,KAAK,sDAAsD;AAAA,IACpE;AAEA,UAAM,qBAAqB,QAAQ;AAAA,MACjC,IAAI,OAAO,SAAS,aAAa,OAAO,CAAC;AAAA,IAAkB;AAAA,IAAA;AAE7D,QAAI,gBAAgB,oBAAoB;AACtC,UAAI,CAAC,oBAAoB;AACvB,eAAO,KAAK,WAAW,OAAO,wBAAwB,OAAO,wBAAwB;AAAA,MACvF,WAAW,CAAC,qBAAqB,KAAK,mBAAmB,CAAC,CAAC,GAAG;AAC5D,eAAO,KAAK,WAAW,OAAO,wCAAwC;AAAA,MACxE;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,OAAO,WAAW;AAAA,IACzB;AAAA,IACA;AAAA,EAAA;AAEJ;AAiDO,SAAS,gBACd,eACA,SACA,QAAe,oBAAI,QAAO,cAAc,MAAM,GAAG,EAAE,GAC7C;AACN,MAAI,CAAC,GAAG,WAAW,aAAa,GAAG;AACjC,UAAM,IAAI,MAAM,wBAAwB,aAAa,EAAE;AAAA,EACzD;AAEA,QAAM,UAAU,GAAG,aAAa,eAAe,OAAO;AACtD,MAAI,QAAQ,SAAS,OAAO,OAAO,GAAG,GAAG;AACvC;AAAA,EACF;AAEA,QAAM,QAAQ,OAAO,OAAO,OAAO,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACvC,QAAM,kBAAkB,QAAQ,MAAM,kCAAkC;AACxE,MAAI,CAAC,mBAAmB,gBAAgB,UAAU,QAAW;AAC3D,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AAEA,QAAM,cAAc,gBAAgB,QAAQ,gBAAgB,CAAC,EAAE;AAC/D,QAAM,UAAU,GAAG,QAAQ,MAAM,GAAG,WAAW,CAAC,GAAG,KAAK,GAAG,QAAQ,MAAM,WAAW,CAAC;AACrF,KAAG,cAAc,eAAe,SAAS,OAAO;AAClD;AAEA,SAAS,aAAa,OAAuB;AAC3C,SAAO,MAAM,QAAQ,uBAAuB,MAAM;AACpD;AC3KA,MAAM,aAAa,CAAC,cAAc,YAAY,UAAU;AAoBjD,SAAS,aAAa,QAAmB,MAAc,QAAQ,OAAa;AACjF,QAAM,SAAS,WAAW,GAAG;AAC7B,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AAEA,QAAM,WAAW,KAAK,KAAK,QAAQ,OAAO;AAC1C,KAAG,UAAU,UAAU,EAAE,WAAW,MAAM;AAE1C,aAAW,YAAY,YAAY;AACjC,QAAI,OAAO,MAAM,QAAQ,GAAG;AAC1B,YAAM,WAAW,KAAK,KAAK,UAAU,QAAQ;AAC7C,SAAG,cAAc,UAAU,mBAAmB,QAAQ,GAAG,EAAE,UAAU,SAAS,MAAM,KAAO;AAAA,IAC7F;AAAA,EACF;AACF;AAmBO,SAAS,eAAe,MAAc,QAAQ,OAAa;AAChE,QAAM,SAAS,WAAW,GAAG;AAC7B,MAAI,CAAC,QAAQ;AACX;AAAA,EACF;AAEA,QAAM,WAAW,KAAK,KAAK,QAAQ,OAAO;AAC1C,aAAW,YAAY,YAAY;AACjC,UAAM,WAAW,KAAK,KAAK,UAAU,QAAQ;AAC7C,QAAI,GAAG,WAAW,QAAQ,KAAK,GAAG,aAAa,UAAU,OAAO,EAAE,SAAS,cAAc,GAAG;AAC1F,SAAG,WAAW,QAAQ;AAAA,IACxB;AAAA,EACF;AACF;AAoBO,SAAS,WAAW,KAA4B;AACrD,MAAI,UAAU;AAEd,SAAO,MAAM;AACX,UAAM,UAAU,KAAK,KAAK,SAAS,MAAM;AACzC,QAAI,GAAG,WAAW,OAAO,KAAK,GAAG,SAAS,OAAO,EAAE,eAAe;AAChE,aAAO;AAAA,IACT;AAEA,UAAM,SAAS,KAAK,QAAQ,OAAO;AACnC,QAAI,WAAW,SAAS;AACtB,aAAO;AAAA,IACT;AACA,cAAU;AAAA,EACZ;AACF;AAoBO,SAAS,kBAAkB,MAAc,QAAQ,OAAgB;AACtE,QAAM,SAAS,WAAW,GAAG;AAC7B,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AAEA,SAAO,WAAW,MAAM,CAAC,aAAa;AACpC,UAAM,WAAW,KAAK,KAAK,QAAQ,SAAS,QAAQ;AACpD,WAAO,GAAG,WAAW,QAAQ,KAAK,GAAG,aAAa,UAAU,OAAO,EAAE,SAAS,cAAc;AAAA,EAC9F,CAAC;AACH;AAoBO,SAAS,mBAAmB,UAA+C;AAChF,SAAO;AAAA,iBACQ,QAAQ;AAAA,mCACU,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAO3C;ACzFO,SAAS,mBAAmB,MAAc,QAAQ,OAAe;AACtE,SAAO,KAAK,KAAK,KAAK,cAAc;AACtC;AAoBO,SAAS,gBAAgB,MAAc,QAAQ,OAAoB;AACxE,QAAM,cAAc,mBAAmB,GAAG;AAE1C,MAAI,CAAC,GAAG,WAAW,WAAW,GAAG;AAC/B,UAAM,IAAI,MAAM,6BAA6B,GAAG,EAAE;AAAA,EACpD;AAEA,SAAO,KAAK,MAAM,GAAG,aAAa,aAAa,OAAO,CAAC;AACzD;AAqBO,SAAS,iBAAiB,KAAkB,MAAc,QAAQ,OAAa;AACpF,KAAG,cAAc,mBAAmB,GAAG,GAAG,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,CAAC;AAAA,GAAM,OAAO;AACxF;AAoBO,SAAS,kBAAkB,MAAc,QAAQ,OAAe;AACrE,QAAM,MAAM,gBAAgB,GAAG;AAE/B,MAAI,OAAO,IAAI,YAAY,YAAY,IAAI,QAAQ,WAAW,GAAG;AAC/D,UAAM,IAAI,MAAM,kCAAkC;AAAA,EACpD;AAEA,SAAO,IAAI;AACb;AAoBO,SAAS,kBAAkB,SAAiB,MAAc,QAAQ,OAAa;AACpF,QAAM,MAAM,gBAAgB,GAAG;AAC/B,MAAI,UAAU;AACd,mBAAiB,KAAK,GAAG;AAC3B;AC/KA,MAAM,eACJ;AAuBK,SAAS,MAAM,SAAgC;AACpD,QAAM,QAAQ,QAAQ,MAAM,YAAY;AAExC,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,OAAO,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE;AAAA,IACnC,OAAO,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE;AAAA,IACnC,OAAO,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE;AAAA,IACnC,YAAY,MAAM,CAAC,IAAI,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;AAAA,IAC7C,OAAO,MAAM,CAAC,IAAI,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;AAAA,IACxC,KAAK;AAAA,EAAA;AAET;AAEA,SAAS,oBAAoB,SAAoC;AAC/D,QAAM,SAA4B,CAAA;AAElC,MAAI,QAAQ,WAAW,GAAG,GAAG;AAC3B,WAAO,KAAK;AAAA,MACV,SAAS,sCAAsC,OAAO;AAAA,MACtD,UAAU;AAAA,IAAA,CACX;AACD,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,QAAQ,MAAM,QAAQ,CAAC,EAAE,CAAC;AAC3C,QAAM,WAAW,SAAS,MAAM,GAAG;AACnC,MAAI,SAAS,WAAW,GAAG;AACzB,UAAM,qBAAqB,SAAS,KAAK,CAAC,YAAY,SAAS,KAAK,OAAO,CAAC;AAC5E,QAAI,oBAAoB;AACtB,aAAO,KAAK;AAAA,QACV,SAAS,oCAAoC,kBAAkB;AAAA,QAC/D,UAAU;AAAA,MAAA,CACX;AACD,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,aAAa,QAAQ,MAAM,UAAU,IAAI,CAAC;AAChD,MAAI,YAAY;AACd,UAAM,oBAAoB,WAAW,MAAM,GAAG,EAAE,KAAK,CAAC,YAAY,SAAS,KAAK,OAAO,CAAC;AACxF,QAAI,mBAAmB;AACrB,aAAO,KAAK;AAAA,QACV,SAAS,0CAA0C,iBAAiB;AAAA,QACpE,UAAU;AAAA,MAAA,CACX;AACD,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO,KAAK;AAAA,IACV,SAAS,2BAA2B,OAAO;AAAA,IAC3C,UAAU;AAAA,EAAA,CACX;AACD,SAAO;AACT;AAuBO,SAASH,WAAS,SAAmC;AAC1D,QAAM,SAAS,MAAM,OAAO;AAE5B,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,oBAAoB,OAAO;AAAA,IAAA;AAAA,EAEvC;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,QAAQ,CAAA;AAAA,IACR,SAAS,EAAE,MAAM,UAAU,SAAS,OAAA;AAAA,EAAO;AAE/C;AAwBO,SAAS,QAAQ,GAAW,GAAmB;AACpD,QAAM,OAAO,MAAM,CAAC;AACpB,QAAM,QAAQ,MAAM,CAAC;AAErB,MAAI,CAAC,QAAQ,CAAC,OAAO;AACnB,UAAM,IAAI,MAAM,sCAAsC,CAAC,UAAU,CAAC,GAAG;AAAA,EACvE;AAEA,aAAW,OAAO,CAAC,SAAS,SAAS,OAAO,GAAY;AACtD,QAAI,KAAK,GAAG,MAAM,MAAM,GAAG,GAAG;AAC5B,aAAO,KAAK,GAAG,IAAI,MAAM,GAAG,IAAI,IAAI;AAAA,IACtC;AAAA,EACF;AAEA,QAAM,oBAAoB,KAAK,WAAW,SAAS;AACnD,QAAM,qBAAqB,MAAM,WAAW,SAAS;AAErD,MAAI,qBAAqB,CAAC,oBAAoB;AAC5C,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,qBAAqB,oBAAoB;AAC5C,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,KAAK,IAAI,KAAK,WAAW,QAAQ,MAAM,WAAW,MAAM;AACvE,WAAS,QAAQ,GAAG,QAAQ,QAAQ,SAAS,GAAG;AAC9C,UAAM,YAAY,KAAK,WAAW,KAAK;AACvC,UAAM,aAAa,MAAM,WAAW,KAAK;AAEzC,QAAI,cAAc,QAAW;AAC3B,aAAO;AAAA,IACT;AAEA,QAAI,eAAe,QAAW;AAC5B,aAAO;AAAA,IACT;AAEA,UAAM,cAAc,QAAQ,KAAK,SAAS,IAAI,OAAO,SAAS,WAAW,EAAE,IAAI;AAC/E,UAAM,eAAe,QAAQ,KAAK,UAAU,IAAI,OAAO,SAAS,YAAY,EAAE,IAAI;AAElF,QAAI,gBAAgB,QAAQ,iBAAiB,MAAM;AACjD,UAAI,gBAAgB,cAAc;AAChC,eAAO,cAAc,eAAe,IAAI;AAAA,MAC1C;AACA;AAAA,IACF;AAEA,QAAI,gBAAgB,MAAM;AACxB,aAAO;AAAA,IACT;AAEA,QAAI,iBAAiB,MAAM;AACzB,aAAO;AAAA,IACT;AAEA,QAAI,cAAc,YAAY;AAC5B,aAAO,YAAY,aAAa,IAAI;AAAA,IACtC;AAAA,EACF;AAEA,SAAO;AACT;AAwBO,SAAS,GAAG,GAAW,GAAoB;AAChD,SAAO,QAAQ,GAAG,CAAC,IAAI;AACzB;AAwBO,SAAS,GAAG,GAAW,GAAoB;AAChD,SAAO,QAAQ,GAAG,CAAC,IAAI;AACzB;AAyBO,SAAS,GAAG,GAAW,GAAoB;AAChD,SAAO,QAAQ,GAAG,CAAC,MAAM;AAC3B;AAyBO,SAAS,UACd,SACA,SACA,YACQ;AACR,QAAM,SAAS,MAAM,OAAO;AAE5B,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,2BAA2B,OAAO,EAAE;AAAA,EACtD;AAEA,MAAI,YAAY,SAAS;AACvB,WAAO,GAAG,OAAO,QAAQ,CAAC,OAAO,aAAa,IAAI,UAAU,KAAK,EAAE;AAAA,EACrE;AAEA,MAAI,YAAY,SAAS;AACvB,WAAO,GAAG,OAAO,KAAK,IAAI,OAAO,QAAQ,CAAC,KAAK,aAAa,IAAI,UAAU,KAAK,EAAE;AAAA,EACnF;AAEA,SAAO,GAAG,OAAO,KAAK,IAAI,OAAO,KAAK,IAAI,OAAO,QAAQ,CAAC,GAAG,aAAa,IAAI,UAAU,KAAK,EAAE;AACjG;AAwBO,SAAS,OAAO,SAAyB;AAC9C,MAAI,SAAS,GAAG,QAAQ,KAAK,IAAI,QAAQ,KAAK,IAAI,QAAQ,KAAK;AAE/D,MAAI,QAAQ,WAAW,SAAS,GAAG;AACjC,cAAU,IAAI,QAAQ,WAAW,KAAK,GAAG,CAAC;AAAA,EAC5C;AAEA,MAAI,QAAQ,MAAM,SAAS,GAAG;AAC5B,cAAU,IAAI,QAAQ,MAAM,KAAK,GAAG,CAAC;AAAA,EACvC;AAEA,SAAO;AACT;;;;;;;;;;;;AC/WA,SAAS,aAAa,UAAoB,KAAa,SAAmB,CAAA,GAAc;AACtF,SAAO;AAAA,IACL,GAAG,IAAI,IAAI,SAAS,QAAQ,CAAC,YAAY,SAAS,SAAS,EAAE,KAAK,UAAU,MAAM,OAAA,CAAQ,CAAC,CAAC;AAAA,EAAA,EAC5F,KAAA;AACJ;AAEA,SAAS,cAAc,SAAiB,QAAwB;AAC9D,SAAO,QAAQ,MAAM,GAAG,MAAM,EAAE,MAAM,IAAI,EAAE;AAC9C;AAEA,SAAS,eAAe,QAA0B;AAChD,SAAO,OAAO,CAAC,KAAK,OAAO,CAAC,KAAK;AACnC;AAEA,SAAS,cAAc,UAAkB,QAAkB,SAAyB;AAClF,SAAO,SAAS,QAAQ,4BAA4B,CAAC,OAAO,eAAmC;AAC7F,QAAI,UAAU,eAAe;AAC3B,aAAO;AAAA,IACT;AAEA,WAAO,OAAO,OAAO,SAAS,cAAc,KAAK,EAAE,IAAI,CAAC,KAAK;AAAA,EAC/D,CAAC;AACH;AAEA,SAAS,iBAAiB,OAAwB;AAChD,SAAO,OAAO,UAAU,WAAW,QAAQ;AAC7C;AAsBO,SAAS,YACd,SACA,QACA,MAAc,QAAQ,OACR;AACd,SAAO,aAAa,OAAO,OAAO,GAAG,EAAE;AAAA,IAAI,CAAC,aAC1C,SAAS,UAAU,SAAS,OAAO,QAAQ;AAAA,EAAA;AAE/C;AAsBO,SAAS,SAAS,UAAkB,SAAiB,UAAqC;AAC/F,QAAM,WAAW,GAAG,aAAa,UAAU,OAAO;AAClD,MAAI,iBAAiB;AACrB,QAAM,UAAiC,CAAA;AAEvC,aAAW,WAAW,UAAU;AAC9B,UAAM,QAAQ,IAAI,OAAO,QAAQ,OAAO,IAAI;AAC5C,qBAAiB,eAAe,QAAQ,OAAO,CAAC,UAAU,SAAoB;AAC5E,YAAM,iBAAiB,OAAO,KAAK,GAAG,EAAE,MAAM,YAAY,KAAK,GAAG,EAAE,MAAM;AAC1E,YAAM,cAAc,iBAAiB,KAAK;AAC1C,YAAM,SAAS,KAAK,GAAG,WAAW;AAClC,YAAM,SAAS,KAAK,MAAM,GAAG,WAAW,EAAE,IAAI,CAAC,UAAU,iBAAiB,KAAK,CAAC;AAChF,YAAM,QAAQ,eAAe,MAAM;AAEnC,UAAI,UAAU,cAAc;AAC1B,eAAO;AAAA,MACT;AAEA,UAAI,UAAU,SAAS;AACrB,gBAAQ,KAAK;AAAA,UACX,MAAM,cAAc,gBAAgB,MAAM;AAAA,UAC1C,UAAU;AAAA,UACV,UAAU;AAAA,QAAA,CACX;AAAA,MACH;AAEA,aAAO,cAAc,QAAQ,UAAU,QAAQ,OAAO,KAAK;AAAA,IAC7D,CAAC;AAAA,EACH;AAEA,QAAM,SAAqB;AAAA,IACzB,MAAM;AAAA,IACN,SAAS,mBAAmB;AAAA,IAC5B;AAAA,EAAA;AAGF,MAAI,OAAO,SAAS;AAClB,OAAG,cAAc,UAAU,gBAAgB,OAAO;AAAA,EACpD;AAEA,SAAO;AACT;AA4BO,SAAS,uBACd,iBACA,QACA,gBACA,MAAc,QAAQ,OACH;AACnB,QAAM,aAAgC,CAAA;AACtC,QAAM,QAAQ,aAAa,OAAO,OAAO,KAAK,cAAc;AAE5D,aAAW,YAAY,OAAO;AAC5B,UAAM,UAAU,GAAG,aAAa,UAAU,OAAO;AAEjD,eAAW,WAAW,OAAO,UAAU;AACrC,YAAM,QAAQ,IAAI,OAAO,QAAQ,OAAO,IAAI;AAC5C,UAAI,QAAgC,MAAM,KAAK,OAAO;AAEtD,aAAO,OAAO;AACZ,cAAM,QAAQ,eAAe,MAAM,MAAM,CAAC,CAAC;AAC3C,YAAI,UAAU,gBAAgB,UAAU,iBAAiB;AACvD,qBAAW,KAAK;AAAA,YACd,MAAM,KAAK,SAAS,KAAK,QAAQ;AAAA,YACjC,MAAM,cAAc,SAAS,MAAM,KAAK;AAAA,YACxC;AAAA,UAAA,CACD;AAAA,QACH;AACA,gBAAQ,MAAM,KAAK,OAAO;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;ACjLA,MAAM,oBAAoB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,iBAAqC;AAAA,EACzC,YAAY;AAAA,IACV,MAAM;AAAA,IACN,QAAQ;AAAA,MACN,QAAQ;AAAA,MACR,oBAAoB;AAAA,IAAA;AAAA,EACtB;AAAA,EAEF,MAAM;AAAA,IACJ,OAAO,CAAC,aAAa,cAAc;AAAA,IACnC,UAAU;AAAA,MACR;AAAA,QACE,OAAO;AAAA,QACP,UAAU;AAAA,MAAA;AAAA,MAEZ;AAAA,QACE,OAAO;AAAA,QACP,UAAU;AAAA,MAAA;AAAA,IACZ;AAAA,EACF;AAAA,EAEF,WAAW;AAAA,IACT,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAAA;AAAA,EAEhB,KAAK;AAAA,IACH,OAAO;AAAA,MACL,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,YAAY;AAAA,IAAA;AAAA,IAEd,cAAc;AAAA,EAAA;AAAA,EAEhB,QAAQ,CAAC,mBAAmB,WAAW,WAAW,UAAU,mBAAmB;AACjF;AAEA,MAAM,aAAa,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAmBvD,SAAS,mBAAuC;AACrD,SAAO,gBAAgB,cAAc;AACvC;AAoBO,SAAS,WAAW,MAAc,QAAQ,OAAsB;AACrE,aAAW,YAAY,mBAAmB;AACxC,UAAM,WAAW,KAAK,KAAK,KAAK,QAAQ;AACxC,QAAI,GAAG,WAAW,QAAQ,GAAG;AAC3B,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAoBO,SAAS,WAAW,YAAwC;AACjE,QAAM,UAAU,GAAG,aAAa,YAAY,OAAO;AACnD,QAAM,SAAS,KAAK,KAAK,OAAO;AAEhC,MAAI,WAAW,QAAW;AACxB,WAAO,iBAAA;AAAA,EACT;AAEA,MAAI,CAAC,cAAc,MAAM,GAAG;AAC1B,UAAM,IAAI,MAAM,2CAA2C,UAAU,EAAE;AAAA,EACzE;AAEA,SAAO,UAAU,iBAAA,GAAoB,MAAM;AAC7C;AAmBO,SAAS,UAAU,MAAc,QAAQ,OAA2B;AACzE,QAAM,aAAa,WAAW,GAAG;AACjC,SAAO,aAAa,WAAW,UAAU,IAAI,iBAAA;AAC/C;AAoBO,SAAS,WAAW,MAAc,QAAQ,OAAe;AAC9D,QAAM,aAAa,KAAK,KAAK,KAAK,mBAAmB;AACrD,QAAM,qBAAqB,WAAW,GAAG;AAEzC,MAAI,oBAAoB;AACtB,UAAM,IAAI,MAAM,+BAA+B,kBAAkB,EAAE;AAAA,EACrE;AAEA,QAAM,cAAc,KAAK,KAAK,YAAY,MAAM,2BAA2B;AAC3E,QAAM,UAAU,GAAG,WAAW,WAAW,IACrC,GAAG,aAAa,aAAa,OAAO,IACpC,sBAAA;AAEJ,KAAG,cAAc,YAAY,SAAS,OAAO;AAC7C,SAAO;AACT;AAEA,SAAS,wBAAgC;AACvC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgCT;AAEA,SAAS,cAAc,OAAkD;AACvE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,UAAa,QAAW,QAAuB;AAEtD,MAAI,CAAC,cAAc,MAAM,KAAK,CAAC,cAAc,MAAM,GAAG;AACpD,WAAQ,UAAU;AAAA,EACpB;AAEA,QAAM,SAAkC,EAAE,GAAG,OAAA;AAE7C,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,UAAM,UAAU,OAAO,GAAG;AAC1B,WAAO,GAAG,IACR,cAAc,OAAO,KAAK,cAAc,KAAK,IAAI,UAAU,SAAS,KAAK,IAAI;AAAA,EACjF;AAEA,SAAO;AACT;ACjKO,SAAS,mBACd,SACA,QACA,iBACgB;AAChB,MAAI,OAAO,WAAW,SAAS,UAAU;AACvC,WAAO,kBAAkB,SAAS,eAAe;AAAA,EACnD;AAEA,SAAO,kBAAkB,SAASI,kBAAgB,MAAM,GAAG,eAAe;AAC5E;AAEA,SAASA,kBAAgB,QAA0C;AACjE,MAAI,CAAC,OAAO,WAAW,QAAQ;AAC7B,UAAM,IAAI,MAAM,mEAAmE;AAAA,EACrF;AAEA,SAAO,OAAO,WAAW;AAC3B;AAEA,SAAS,kBAAkB,SAAiB,iBAA0C;AACpF,QAAM,SAA4B,CAAA;AAClC,QAAM,cAA4B,CAAA;AAGlC,QAAM,SAASC,MAAa,OAAO;AAEnC,MAAI,CAAC,QAAQ;AACX,UAAM,aAAaC,WAAgB,OAAO;AAG1C,QAAI,QAAQ,WAAW,GAAG,GAAG;AAC3B,YAAM,eAAe,QAAQ,MAAM,CAAC;AACpC,aAAO,KAAK;AAAA,QACV,SAAS,sCAAsC,OAAO;AAAA,QACtD,UAAU;AAAA,MAAA,CACX;AACD,kBAAY,KAAK;AAAA,QACf,SAAS;AAAA,QACT,KAAK,eAAe,YAAY;AAAA,QAChC,aAAa;AAAA,MAAA,CACd;AAAA,IACH,WAAW,QAAQ,MAAM,GAAG,EAAE,WAAW,GAAG;AAC1C,aAAO,KAAK;AAAA,QACV,SAAS,iCAAiC,OAAO;AAAA,QACjD,UAAU;AAAA,MAAA,CACX;AACD,kBAAY,KAAK;AAAA,QACf,SAAS,2BAA2B,OAAO;AAAA,QAC3C,KAAK,eAAe,OAAO;AAAA,QAC3B,aAAa;AAAA,MAAA,CACd;AAAA,IACH,WAAW,uBAAuB,KAAK,OAAO,GAAG;AAC/C,aAAO,KAAK;AAAA,QACV,SAAS,kCAAkC,OAAO;AAAA,QAClD,UAAU;AAAA,MAAA,CACX;AACD,kBAAY,KAAK;AAAA,QACf,SAAS;AAAA,QACT,aAAa;AAAA,MAAA,CACd;AAAA,IACH,WAAW,WAAW,OAAO,KAAK,CAAC,UAAU,MAAM,QAAQ,SAAS,cAAc,CAAC,GAAG;AACpF,aAAO,KAAK,GAAG,WAAW,MAAM;AAChC,kBAAY,KAAK;AAAA,QACf,SAAS;AAAA,QACT,aAAa;AAAA,MAAA,CACd;AAAA,IACH,OAAO;AACL,aAAO;AAAA,QACL,GAAI,WAAW,OAAO,SAAS,IAC3B,WAAW,SACX;AAAA,UACE;AAAA,YACE,SAAS,0BAA0B,OAAO;AAAA,YAC1C,UAAU;AAAA,UAAA;AAAA,QACZ;AAAA,MACF;AAEN,kBAAY,KAAK;AAAA,QACf,SAAS;AAAA,QACT,aAAa;AAAA,MAAA,CACd;AAAA,IACH;AAEA,WAAO;AAAA,MACL,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,YAAY,YAAY,KAAK,CAAC,MAAM,EAAE,WAAW;AAAA,IAAA;AAAA,EAErD;AAGA,MAAI,iBAAiB;AACnB,UAAM,aAAaD,MAAa,eAAe;AAC/C,QAAI,YAAY;AACd,YAAM,aAAaE,QAAe,SAAS,eAAe;AAE1D,UAAI,aAAa,GAAG;AAClB,eAAO,KAAK;AAAA,UACV,SAAS,WAAW,OAAO,2BAA2B,eAAe;AAAA,UACrE,UAAU;AAAA,QAAA,CACX;AACD,oBAAY,KAAK;AAAA,UACf,SAAS,gCAAgC,eAAe;AAAA,UACxD,KAAK,eAAeC,UAAiB,iBAAiB,OAAO,CAAC;AAAA,UAC9D,aAAa;AAAA,QAAA,CACd;AAAA,MACH,WAAW,eAAe,GAAG;AAC3B,eAAO,KAAK;AAAA,UACV,SAAS,WAAW,OAAO;AAAA,UAC3B,UAAU;AAAA,QAAA,CACX;AACD,oBAAY,KAAK;AAAA,UACf,SAAS;AAAA,UACT,KAAK,eAAeA,UAAiB,iBAAiB,OAAO,CAAC;AAAA,UAC9D,aAAa;AAAA,QAAA,CACd;AAAA,MACH,OAAO;AAEL,cAAM,YAAY,OAAO,QAAQ,WAAW;AAC5C,cAAM,YAAY,OAAO,QAAQ,WAAW;AAC5C,cAAM,YAAY,OAAO,QAAQ,WAAW;AAE5C,YAAI,YAAY,GAAG;AACjB,sBAAY,KAAK;AAAA,YACf,SAAS,+BAA+B,SAAS,UAAU,eAAe,OAAO,OAAO;AAAA,YACxF,aAAa;AAAA,UAAA,CACd;AAAA,QACH;AAEA,YAAI,YAAY,IAAI;AAClB,sBAAY,KAAK;AAAA,YACf,SAAS,+BAA+B,SAAS;AAAA,YACjD,aAAa;AAAA,UAAA,CACd;AAAA,QACH;AAEA,YAAI,YAAY,IAAI;AAClB,sBAAY,KAAK;AAAA,YACf,SAAS,+BAA+B,SAAS;AAAA,YACjD,aAAa;AAAA,UAAA,CACd;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,OAAO,WAAW;AAAA,IACzB;AAAA,IACA;AAAA,IACA,YAAY,YAAY,KAAK,CAAC,MAAM,EAAE,WAAW;AAAA,EAAA;AAErD;AAEA,SAAS,kBACP,SACA,cACA,iBACgB;AAChB,QAAM,SAA4B,CAAA;AAClC,QAAM,cAA4B,CAAA;AAClC,QAAM,EAAE,QAAAP,SAAQ,mBAAA,IAAuB;AAEvC,QAAM,SAASQ,QAAa,SAASR,OAAM;AAE3C,MAAI,CAAC,QAAQ;AACX,WAAO,KAAK;AAAA,MACV,SAAS,0BAA0B,OAAO;AAAA,MAC1C,UAAU;AAAA,IAAA,CACX;AACD,gBAAY,KAAK;AAAA,MACf,SAAS,oBAAoBA,OAAM;AAAA,MACnC,KAAK,6CAA6CS,kBAAyBT,OAAM,CAAC;AAAA,MAClF,aAAa;AAAA,IAAA,CACd;AACD,WAAO,EAAE,OAAO,OAAO,QAAQ,aAAa,YAAY,KAAA;AAAA,EAC1D;AAEA,QAAM,aAAaU,WAAgB,SAASV,SAAQ,kBAAkB;AACtE,SAAO,KAAK,GAAG,WAAW,MAAM;AAEhC,QAAM,0BAAU,KAAA;AAChB,MAAI,WAAW,OAAO,KAAK,CAAC,UAAU,MAAM,QAAQ,WAAW,gBAAgB,CAAC,GAAG;AACjF,gBAAY,KAAK;AAAA,MACf,SAAS;AAAA,MACT,aAAa;AAAA,IAAA,CACd;AAAA,EACH;AAEA,MAAI,WAAW,OAAO,KAAK,CAAC,UAAU,MAAM,QAAQ,WAAW,cAAc,CAAC,GAAG;AAC/E,gBAAY,KAAK;AAAA,MACf,SAAS;AAAA,MACT,aAAa;AAAA,IAAA,CACd;AAAA,EACH;AAEA,MAAI,sBAAsB,OAAO,OAAO,IAAI,eAAe;AACzD,gBAAY,KAAK;AAAA,MACf,SAAS,qBAAqB,IAAI,YAAA,CAAa;AAAA,MAC/C,KAAK,eAAe,oBAAoB,EAAE,GAAG,QAAQ,MAAM,IAAI,cAAY,CAAG,CAAC;AAAA,MAC/E,aAAa;AAAA,IAAA,CACd;AAAA,EACH;AAEA,MACE,sBACA,OAAO,SAAS,IAAI,YAAA,KACpB,OAAO,QAAQ,IAAI,SAAA,IAAa,GAChC;AACA,gBAAY,KAAK;AAAA,MACf,SAAS,oBAAoB,IAAI,SAAA,IAAa,CAAC;AAAA,MAC/C,KAAK,eAAe,oBAAoB,EAAE,GAAG,QAAQ,OAAO,IAAI,SAAA,IAAa,EAAA,CAAG,CAAC;AAAA,MACjF,aAAa;AAAA,IAAA,CACd;AAAA,EACH;AAEA,MACE,sBACA,OAAO,SAAS,IAAI,iBACpB,OAAO,UAAU,IAAI,aAAa,KAClC,OAAO,QAAQ,UACf,OAAO,MAAM,IAAI,WACjB;AACA,gBAAY,KAAK;AAAA,MACf,SAAS,kBAAkB,IAAI,QAAA,CAAS;AAAA,MACxC,KAAK,eAAe,oBAAoB,EAAE,GAAG,QAAQ,KAAK,IAAI,UAAQ,CAAG,CAAC;AAAA,MAC1E,aAAa;AAAA,IAAA,CACd;AAAA,EACH;AAGA,MAAI,iBAAiB;AACnB,UAAM,aAAaQ,QAAa,iBAAiBR,OAAM;AACvD,QAAI,YAAY;AACd,UAAIW,UAAe,SAAS,iBAAiBX,OAAM,KAAK,GAAG;AACzD,eAAO,KAAK;AAAA,UACV,SAAS,WAAW,OAAO,+BAA+B,eAAe;AAAA,UACzE,UAAU;AAAA,QAAA,CACX;AACD,oBAAY,KAAK;AAAA,UACf,SAAS;AAAA,UACT,KAAK,eAAeY,YAAiB,iBAAiBZ,OAAM,CAAC;AAAA,UAC7D,aAAa;AAAA,QAAA,CACd;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,OAAO,WAAW;AAAA,IACzB;AAAA,IACA;AAAA,IACA,YAAY,YAAY,KAAK,CAAC,MAAM,EAAE,WAAW;AAAA,EAAA;AAErD;AAEA,SAAS,oBAAoB,SAAyB;AACpD,SAAOa,SAAc;AAAA,IACnB,GAAG;AAAA,IACH,KAAK,QAAQ,OAAO;AAAA,EAAA,CACrB;AACH;AAsBO,SAAS,gBACd,MACA,cACA,iBACc;AACd,QAAM,cAA4B;AAAA,IAChC;AAAA,MACE,SAAS,GAAG,IAAI,iBAAiB,YAAY,oBAAoB,eAAe;AAAA,MAChF,KAAK;AAAA,MACL,aAAa;AAAA,IAAA;AAAA,EACf;AAIF,MAAI,KAAK,SAAS,KAAK,GAAG;AACxB,gBAAY,KAAK;AAAA,MACf,SAAS,+CAA+C,eAAe;AAAA,MACvE,aAAa;AAAA,IAAA,CACd;AAAA,EACH;AAEA,MAAI,KAAK,SAAS,KAAK,KAAK,KAAK,SAAS,KAAK,GAAG;AAChD,gBAAY,KAAK;AAAA,MACf,SAAS,iEAAiE,eAAe;AAAA,MACzF,aAAa;AAAA,IAAA,CACd;AAAA,EACH;AAEA,SAAO;AACT;AAsBO,SAAS,qBACd,UACA,SACA,wBACc;AACd,QAAM,cAA4B,CAAA;AAElC,MAAI,CAAC,UAAU;AACb,gBAAY,KAAK;AAAA,MACf,SAAS,6CAA6C,OAAO;AAAA,MAC7D,KAAK;AAAA,MACL,aAAa;AAAA,IAAA,CACd;AAED,gBAAY,KAAK;AAAA,MACf,SAAS,yBAAyB,OAAO;AAAA,MACzC,aAAa;AAAA,IAAA,CACd;AAAA,EACH;AAEA,MAAI,0BAA0B,2BAA2B,SAAS;AAChE,gBAAY,KAAK;AAAA,MACf,SAAS,gCAAgC,sBAAsB,yBAAyB,OAAO;AAAA,MAC/F,KAAK;AAAA,MACL,aAAa;AAAA,IAAA,CACd;AAAA,EACH;AAEA,SAAO;AACT;AAsBO,SAAS,eACd,YACA,gBACA,kBACc;AACd,QAAM,cAA4B,CAAA;AAElC,MAAI,eAAe,gBAAgB;AACjC,gBAAY,KAAK;AAAA,MACf,SAAS,YAAY,UAAU,iCAAiC,cAAc;AAAA,MAC9E,KAAK,uCAAuC,UAAU,eAAe,cAAc;AAAA,MACnF,aAAa;AAAA,IAAA,CACd;AAAA,EACH;AAEA,MAAI,kBAAkB;AACpB,gBAAY,KAAK;AAAA,MACf,SAAS,sCAAsC,cAAc;AAAA,MAC7D,KAAK;AAAA,MACL,aAAa;AAAA,IAAA,CACd;AAAA,EACH;AAEA,SAAO;AACT;ACpbO,SAAS,kBAAkB,eAAuB,MAAc,QAAQ,OAAkB;AAC/F,QAAM,cAAc,KAAK,KAAK,KAAK,cAAc;AAEjD,MAAI,CAAC,GAAG,WAAW,WAAW,GAAG;AAC/B,WAAO,EAAE,OAAO,OAAO,SAAS,yBAAA;AAAA,EAClC;AAEA,QAAM,MAAM,KAAK,MAAM,GAAG,aAAa,aAAa,OAAO,CAAC;AAC5D,QAAM,aAAa,OAAO,IAAI,YAAY,WAAW,IAAI,UAAU;AAEnE,MAAI,eAAe,eAAe;AAChC,WAAO,EAAE,OAAO,OAAO,SAAS,sBAAsB,aAAa,GAAA;AAAA,EACrE;AAEA,oBAAkB,eAAe,GAAG;AAEpC,SAAO;AAAA,IACL,OAAO;AAAA,IACP,SAAS,6BAA6B,UAAU,OAAO,aAAa;AAAA,IACpE,MAAM;AAAA,EAAA;AAEV;AAqBO,SAAS,cACd,QACA,MAAc,QAAQ,OACT;AACb,QAAM,UAAU,kBAAkB,GAAG;AACrC,QAAM,UAAuB,YAAY,SAAS,OAAO,MAAM,GAAG,EAC/D,OAAO,CAAC,WAAW,OAAO,OAAO,EACjC,IAAI,CAAC,YAAY;AAAA,IAChB,OAAO;AAAA,IACP,SAAS,WAAW,KAAK,SAAS,KAAK,OAAO,IAAI,CAAC,KAAK,OAAO,QAAQ,MAAM;AAAA,IAC7E,MAAM,OAAO;AAAA,EAAA,EACb;AAEJ,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,KAAK,EAAE,OAAO,OAAO,SAAS,6BAA6B;AAAA,EACrE;AAEA,SAAO;AACT;AAsBO,SAAS,aACd,SACA,QACA,MAAc,QAAQ,OACX;AACX,QAAM,gBAAgB,KAAK,KAAK,KAAK,OAAO,UAAU,IAAI;AAE1D,MAAI,CAAC,GAAG,WAAW,aAAa,GAAG;AAEjC,2BAAuB,eAAe,OAAO;AAC7C,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS,WAAW,OAAO,UAAU,IAAI,mBAAmB,OAAO;AAAA,MACnE,MAAM;AAAA,IAAA;AAAA,EAEV;AAEA,QAAM,UAAU,GAAG,aAAa,eAAe,OAAO;AAEtD,MAAI,QAAQ,SAAS,OAAO,OAAO,GAAG,GAAG;AACvC,WAAO,EAAE,OAAO,OAAO,SAAS,mCAAmC,OAAO,GAAA;AAAA,EAC5E;AAEA,kBAAgB,eAAe,OAAO;AAEtC,SAAO;AAAA,IACL,OAAO;AAAA,IACP,SAAS,mBAAmB,OAAO,OAAO,OAAO,UAAU,IAAI;AAAA,IAC/D,MAAM;AAAA,EAAA;AAEV;AAKA,SAAS,uBAAuB,eAAuB,SAAuB;AAC5E,QAAM,6BAAY,KAAA,GAAO,cAAc,MAAM,GAAG,EAAE;AAClD,QAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASZ,OAAO,OAAO,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4DAMmC,OAAO;AAAA,GAChE,OAAO,uDAAuD,OAAO;AAAA;AAGtE,KAAG,cAAc,eAAe,SAAS,OAAO;AAClD;AAuBO,SAAS,OACd,QACA,eACA,MAAc,QAAQ,OACT;AACb,QAAM,UAAuB,CAAA;AAC7B,QAAM,UAAU,iBAAiB,kBAAkB,GAAG;AAEtD,MAAI,iBAAiB,kBAAkB,kBAAkB,GAAG,GAAG;AAC7D,YAAQ,KAAK,kBAAkB,eAAe,GAAG,CAAC;AAAA,EACpD;AAEA,QAAM,cAAc,cAAc,QAAQ,GAAG;AAC7C,UAAQ,KAAK,GAAG,WAAW;AAE3B,MAAI,OAAO,UAAU,SAAS;AAC5B,UAAM,kBAAkB,aAAa,SAAS,QAAQ,GAAG;AACzD,QAAI,gBAAgB,OAAO;AACzB,cAAQ,KAAK,eAAe;AAAA,IAC9B;AAAA,EACF;AAEA,SAAO;AACT;AAuBO,SAAS,mBACd,gBACA,QACA,YACuC;AACvC,QAAM,cAAqD,CAAA;AAE3D,MAAI,OAAO,WAAW,SAAS,UAAU;AACvC,QAAI,CAAC,cAAc,eAAe,UAAU,eAAe,SAAS;AAClE,kBAAY,KAAK;AAAA,QACf,SAASN,UAAiB,gBAAgB,OAAO;AAAA,QACjD,QAAQ;AAAA,MAAA,CACT;AAAA,IACH;AAEA,QAAI,CAAC,cAAc,eAAe,UAAU,eAAe,SAAS;AAClE,kBAAY,KAAK;AAAA,QACf,SAASA,UAAiB,gBAAgB,OAAO;AAAA,QACjD,QAAQ;AAAA,MAAA,CACT;AAAA,IACH;AAEA,QAAI,CAAC,cAAc,eAAe,UAAU,eAAe,SAAS;AAClE,kBAAY,KAAK;AAAA,QACf,SAASA,UAAiB,gBAAgB,OAAO;AAAA,QACjD,QAAQ;AAAA,MAAA,CACT;AAAA,IACH;AAAA,EACF,OAAO;AAEL,UAAMP,UAASG,kBAAgB,MAAM,EAAE;AACvC,UAAM,aAAaM,kBAAyBT,OAAM;AAGlD,gBAAY,KAAK;AAAA,MACf,SAAS;AAAA,MACT,QAAQ;AAAA,IAAA,CACT;AAGD,gBAAY,KAAK;AAAA,MACf,SAASY,YAAiB,gBAAgBZ,OAAM;AAAA,MAChD,QAAQ;AAAA,IAAA,CACT;AAAA,EACH;AAEA,SAAO;AACT;AAEA,SAASG,kBAAgB,QAA0C;AACjE,MAAI,CAAC,OAAO,WAAW,QAAQ;AAC7B,UAAM,IAAI,MAAM,mEAAmE;AAAA,EACrF;AAEA,SAAO,OAAO,WAAW;AAC3B;AClRA,SAAS,OAAO,KAAa,MAAgB,UAA4C;AACvF,SAAO,aAAa,aAAa,OAAO,MAAM;AAAA,IAC5C;AAAA,IACA;AAAA,IACA,OAAO,CAAC,QAAQ,QAAQ,QAAQ;AAAA,EAAA,CACjC;AACH;AAEA,SAAS,WAAW,KAAa,MAAwB;AACvD,SAAO,OAAO,KAAK,MAAM,OAAO;AAClC;AAwBO,SAAS,aAAa,MAAc,QAAQ,OAAuB;AACxE,MAAI;AACF,UAAM,SAAS,WAAW,KAAK,CAAC,YAAY,UAAU,YAAY,CAAC;AAEnE,UAAM,UAAU,OAAO,KAAA;AACvB,UAAM,UAAU,QAAQ,QAAQ,MAAM,EAAE;AAExC,UAAM,aAAa,WAAW,KAAK,CAAC,OAAO,MAAM,gBAAgB,OAAO,CAAC;AACzE,UAAM,gBAAgB,WAAW,KAAK,CAAC,OAAO,MAAM,SAAS,sBAAsB,CAAC;AACpF,UAAM,UAAU,cAAc,KAAA;AAE9B,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA,SAAS,QAAQ,SAAS,IAAI,UAAU;AAAA,MACxC,MAAM,IAAI,KAAK,WAAW,MAAM;AAAA,IAAA;AAAA,EAEpC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAqBO,SAAS,WAAW,MAAc,QAAQ,OAAkB;AACjE,MAAI;AACF,UAAM,SAAS,WAAW,KAAK,CAAC,OAAO,QAAQ,CAAC;AAEhD,WAAO,OACJ,OACA,MAAM,IAAI,EACV,OAAO,OAAO,EACd,IAAI,CAAC,UAAU;AAAA,MACd;AAAA,MACA,SAAS,KAAK,QAAQ,MAAM,EAAE;AAAA,MAC9B,0BAAU,KAAA;AAAA;AAAA,IAAK,EACf;AAAA,EACN,QAAQ;AACN,WAAO,CAAA;AAAA,EACT;AACF;AA4BO,SAAS,UACd,SACA,SACA,UAAmB,MACnB,QACA,MAAc,QAAQ,OACoC;AAC1D,QAAM,UAAoB,CAAA;AAE1B,MAAI;AACF,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS;AAAA,QACT;AAAA,MAAA;AAAA,IAEJ;AAEA,UAAM,iBAAiB,kBAAkB,GAAG;AAC5C,UAAM,gBAAgB;AACtB,UAAM,iBAAiB,qBAAqB,QAAQ,KAAK,SAAS,aAAa;AAC/E,QAAI,gBAAgB;AAClB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS;AAAA,QACT;AAAA,MAAA;AAAA,IAEJ;AAEA,QAAI,YAAY,kBAAkB,CAAC,SAAS;AAC1C,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,qCAAqC,cAAc,YAAY,OAAO;AAAA,QAC/E,SAAS,CAAA;AAAA,MAAC;AAAA,IAEd;AAEA,QAAI,SAAS;AACX,YAAM,aACJ,YAAY,iBAAiB,OAAO,QAAQ,SAAS,GAAG,IAAI,OAAO,QAAQ,QAAW,GAAG;AAE3F,iBAAW,UAAU,YAAY;AAC/B,YAAI,OAAO,OAAO;AAChB,kBAAQ,KAAK,OAAO,OAAO;AAAA,QAC7B;AAAA,MACF;AAEA,UAAI,WAAW,KAAK,CAAC,WAAW,OAAO,KAAK,GAAG;AAC7C,eAAO,KAAK,CAAC,OAAO,IAAI,CAAC;AACzB,eAAO,KAAK,CAAC,UAAU,eAAe,MAAM,mBAAmB,OAAO,EAAE,CAAC;AACzE,gBAAQ,KAAK,2BAA2B;AAAA,MAC1C;AAAA,IACF;AAEA,UAAM,UAAU,IAAI,OAAO;AAC3B,UAAM,aAAa,WAAW,WAAW,OAAO;AAEhD,QAAI,WAAW,GAAG,EAAE,KAAK,CAAC,QAAQ,IAAI,SAAS,OAAO,GAAG;AACvD,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,OAAO,OAAO;AAAA,QACvB;AAAA,MAAA;AAAA,IAEJ;AAEA,WAAO,KAAK,CAAC,OAAO,MAAM,SAAS,MAAM,UAAU,CAAC;AACpD,YAAQ,KAAK,eAAe,OAAO,EAAE;AAErC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS,4BAA4B,OAAO;AAAA,MAC5C;AAAA,IAAA;AAAA,EAEJ,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS,yBAA0B,IAAc,OAAO;AAAA,MACxD;AAAA,IAAA;AAAA,EAEJ;AACF;AAsBO,SAAS,cACd,QACA,MAAc,QAAQ,OACoC;AAC1D,QAAM,UAAoB,CAAA;AAE1B,MAAI;AACF,UAAM,iBAAiB,qBAAqB,QAAQ,GAAG;AACvD,QAAI,gBAAgB;AAClB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS;AAAA,QACT;AAAA,MAAA;AAAA,IAEJ;AAEA,UAAM,MAAM,aAAa,GAAG;AAC5B,QAAI,CAAC,KAAK;AACR,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS;AAAA,QACT;AAAA,MAAA;AAAA,IAEJ;AACA,UAAM,iBAAiB,kBAAkB,GAAG;AAE5C,QAAI,IAAI,YAAY,gBAAgB;AAClC,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,eAAe,IAAI,OAAO,+BAA+B,cAAc;AAAA,QAChF,SAAS;AAAA,UACP;AAAA,UACA,gBAAgB,IAAI,IAAI;AAAA,UACxB,iBAAiB,IAAI,OAAO;AAAA,UAC5B,aAAa,IAAI,IAAI;AAAA,QAAA;AAAA,MACvB;AAAA,IAEJ;AACA,UAAM,cAAc,OAAO,QAAQ,gBAAgB,GAAG;AAEtD,eAAW,UAAU,aAAa;AAEhC,UAAI,OAAO,OAAO;AAChB,gBAAQ,KAAK,OAAO,OAAO;AAAA,MAC7B;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS,mCAAmC,IAAI,IAAI;AAAA,MACpD;AAAA,IAAA;AAAA,EAEJ,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS,6BAA8B,IAAc,OAAO;AAAA,MAC5D;AAAA,IAAA;AAAA,EAEJ;AACF;AAEA,SAAS,qBACP,QACA,KACA,iBACA,eAAwB,OACT;AACf,MAAI,OAAO,IAAI,gBAAgB,CAAC,kBAAkB,GAAG,GAAG;AACtD,WAAO;AAAA,EACT;AAEA,MAAI,iBAAiB,GAAG,GAAG;AACzB,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,mBAAmB,kBAAkB,GAAG;AACxD,QAAM,gBACJ,OAAO,WAAW,SAAS,WACvBW,WAAe,OAAO,IACtBC;AAAAA,IACE;AAAA,IACA,OAAO,WAAW,QAAQ,UAAU;AAAA,IACpC,OAAO,WAAW,QAAQ,sBAAsB;AAAA,EAAA;AAGxD,MAAI,CAAC,cAAc,OAAO;AACxB,WAAO,cAAc,OAAO,CAAC,GAAG,WAAW,oBAAoB,OAAO;AAAA,EACxE;AAEA,MAAI,cAAc;AAChB,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,uBAAuB,SAAS,OAAO,MAAM,OAAO,QAAQ,GAAG;AAClF,MAAI,WAAW,SAAS,GAAG;AACzB,UAAM,WAAW,WAAW,CAAC;AAC7B,WAAO,uBAAuB,SAAS,IAAI,IAAI,SAAS,IAAI,aAAa,SAAS,KAAK,mBAAmB,OAAO;AAAA,EACnH;AAEA,QAAM,kBAAkB;AAAA,IACtB,KAAK,KAAK,KAAK,OAAO,UAAU,IAAI;AAAA,IACpC;AAAA,IACA,OAAO,UAAU;AAAA,IACjB,OAAO,UAAU;AAAA,EAAA;AAEnB,MAAI,CAAC,gBAAgB,OAAO;AAC1B,WAAO,gBAAgB,OAAO,CAAC,KAAK;AAAA,EACtC;AAEA,SAAO;AACT;AAEA,SAAS,iBAAiB,KAAsB;AAC9C,MAAI;AACF,WAAO,WAAW,KAAK,CAAC,UAAU,aAAa,CAAC,EAAE,OAAO,SAAS;AAAA,EACpE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAqBO,SAAS,mBACd,SACA,MAAc,QAAQ,OAC6B;AACnD,MAAI;AACF,WAAO,KAAK,CAAC,aAAa,OAAO,CAAC;AAElC,QAAI;AACF,aAAO,KAAK,CAAC,aAAa,UAAU,UAAU,OAAO,CAAC;AAEtD,YAAM,YAAY,WAAW,KAAK,CAAC,aAAa,OAAO,CAAC,EAAE,KAAA;AAC1D,YAAM,eAAe,WAAW,KAAK,CAAC,aAAa,UAAU,UAAU,OAAO,CAAC,EAAE,KAAA;AAEjF,UAAI,gBAAgB,CAAC,aAAa,SAAS,SAAS,GAAG;AACrD,eAAO;AAAA,UACL,OAAO;AAAA,UACP,SAAS,OAAO,OAAO;AAAA,UACvB,KAAK,uDAAuD,OAAO;AAAA,QAAA;AAAA,MAEvE;AAAA,IACF,QAAQ;AACN,aAAO,EAAE,OAAO,MAAM,SAAS,OAAO,OAAO,qBAAA;AAAA,IAC/C;AAEA,WAAO,EAAE,OAAO,MAAM,SAAS,OAAO,OAAO,qBAAA;AAAA,EAC/C,QAAQ;AACN,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS,OAAO,OAAO;AAAA,MACvB,KAAK,uBAAuB,OAAO;AAAA,IAAA;AAAA,EAEvC;AACF;AAsBO,SAAS,kBAAkB,SAAiB,MAAc,QAAQ,OAAe;AACtF,MAAI;AACF,UAAM,gBAAgB,KAAK,KAAK,KAAK,cAAc;AACnD,QAAI,GAAG,WAAW,aAAa,GAAG;AAChC,YAAM,UAAU,GAAG,aAAa,eAAe,OAAO;AAEtD,YAAM,eAAe,IAAI;AAAA,QACvB,SAAS,OAAO;AAAA,QAChB;AAAA,MAAA;AAEF,YAAM,QAAQ,QAAQ,MAAM,YAAY;AAExC,UAAI,OAAO;AACT,cAAM,cAAc,MAAM,CAAC,EAAE,MAAM,QAAQ;AAC3C,YAAI,aAAa;AACf,iBAAO,WAAW,OAAO,KAAK,YAAY,CAAC,EAAE,MAAM;AAAA,QACrD;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AACN,WAAO,WAAW,OAAO;AAAA,EAC3B;AAEA,SAAO,WAAW,OAAO;AAC3B;ACnbO,SAAS,gBAAgB,SAAiB,QAA8C;AAC7F,MAAI,OAAO,WAAW,SAAS,UAAU;AACvC,WAAOV,WAAgB,OAAO;AAAA,EAChC;AAEA,QAAM,eAAe,gBAAgB,MAAM;AAC3C,SAAOK,WAAgB,SAAS,aAAa,QAAQ,aAAa,kBAAkB;AACtF;AAqBO,SAAS,SACd,QACA,MAAc,QAAQ,OACA;AACtB,QAAM,SAAmB,CAAA;AAEzB,MAAI;AACJ,MAAI;AACF,cAAU,kBAAkB,GAAG;AAAA,EACjC,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,MACT,cAAc;AAAA,MACd,WAAW;AAAA,MACX,gBAAgB;AAAA,MAChB,QAAQ,CAAE,IAAc,OAAO;AAAA,IAAA;AAAA,EAEnC;AAEA,QAAM,gBAAgB,gBAAgB,SAAS,MAAM;AACrD,MAAI,CAAC,cAAc,OAAO;AACxB,WAAO,KAAK,GAAG,cAAc,OAAO,IAAI,CAAC,UAAU,MAAM,OAAO,CAAC;AAAA,EACnE;AAEA,QAAM,YAAY,uBAAuB,SAAS,OAAO,MAAM,OAAO,QAAQ,GAAG;AAEjF,MAAI,UAAU,SAAS,GAAG;AACxB,eAAW,YAAY,WAAW;AAChC,aAAO;AAAA,QACL,uBAAuB,SAAS,IAAI,IAAI,SAAS,IAAI,aAAa,SAAS,KAAK,mBAAmB,OAAO;AAAA,MAAA;AAAA,IAE9G;AAAA,EACF;AAEA,MAAI,iBAAiB;AACrB,MAAI,OAAO,UAAU,SAAS;AAC5B,UAAM,gBAAgB,KAAK,KAAK,KAAK,OAAO,UAAU,IAAI;AAC1D,UAAM,kBAAkB;AAAA,MACtB;AAAA,MACA;AAAA,MACA,OAAO,UAAU;AAAA,MACjB,OAAO,UAAU;AAAA,IAAA;AAGnB,QAAI,CAAC,gBAAgB,OAAO;AAC1B,uBAAiB;AACjB,aAAO,KAAK,GAAG,gBAAgB,MAAM;AAAA,IACvC;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,OAAO,WAAW;AAAA,IACzB;AAAA,IACA,cAAc,cAAc;AAAA,IAC5B,WAAW,UAAU,WAAW;AAAA,IAChC;AAAA,IACA;AAAA,EAAA;AAEJ;AAqBO,SAAS,OAAO,QAA4B,MAAc,QAAQ,OAAqB;AAC5F,QAAM,aAAa,SAAS,QAAQ,GAAG;AACvC,QAAM,gBAAgB,WAAW,GAAG,MAAM;AAC1C,QAAM,iBAAiB,gBAAgB,kBAAkB,GAAG,IAAI;AAChE,QAAM,gBAAgB,gBAAgB,gBAAgB,GAAG,IAAI;AAC7D,QAAM,SAAS,CAAC,GAAG,WAAW,MAAM;AAEpC,MAAI,iBAAiB,OAAO,IAAI,gBAAgB,CAAC,gBAAgB;AAC/D,WAAO,KAAK,6BAA6B;AAAA,EAC3C;AAEA,MAAI,iBAAiB,CAAC,eAAe;AACnC,WAAO,KAAK,2BAA2B;AAAA,EACzC;AAEA,SAAO;AAAA,IACL,OAAO,OAAO,WAAW;AAAA,IACzB,SAAS,WAAW;AAAA,IACpB,cAAc,WAAW;AAAA,IACzB,WAAW,WAAW;AAAA,IACtB,gBAAgB,WAAW;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;AAoBO,SAAS,KAAK,QAA4B,MAAc,QAAQ,OAAa;AAClF,QAAM,UAAU,kBAAkB,GAAG;AACrC,cAAY,SAAS,OAAO,MAAM,GAAG;AACvC;AAuBO,SAAS,QACd,gBACA,YACA,QACsC;AACtC,QAAM,eAAe,gBAAgB,gBAAgB,MAAM;AAC3D,QAAM,WAAW,gBAAgB,YAAY,MAAM;AAEnD,MAAI,CAAC,aAAa,OAAO;AACvB,WAAO,EAAE,SAAS,OAAO,OAAO,+BAA+B,cAAc,GAAA;AAAA,EAC/E;AAEA,MAAI,CAAC,SAAS,OAAO;AACnB,WAAO,EAAE,SAAS,OAAO,OAAO,2BAA2B,UAAU,GAAA;AAAA,EACvE;AAEA,MAAI,OAAO,WAAW,SAAS,UAAU;AACvC,QAAI,CAACM,GAAU,YAAY,cAAc,GAAG;AAC1C,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,eAAe,UAAU,iCAAiC,cAAc;AAAA,MAAA;AAAA,IAEnF;AAAA,EACF,OAAO;AACL,UAAM,eAAe,gBAAgB,MAAM;AAC3C,UAAM,gBAAgBR,QAAa,gBAAgB,aAAa,MAAM;AACtE,UAAM,YAAYA,QAAa,YAAY,aAAa,MAAM;AAE9D,QAAI,CAAC,iBAAiB,CAAC,WAAW;AAChC,aAAO,EAAE,SAAS,OAAO,OAAO,kCAAA;AAAA,IAClC;AAEA,QAAIG,UAAe,YAAY,gBAAgB,aAAa,MAAM,KAAK,GAAG;AACxE,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,cAAc,UAAU,+BAA+B,cAAc;AAAA,MAAA;AAAA,IAEhF;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,KAAA;AACpB;AAEA,SAAS,gBAAgB,QAA0C;AACjE,MAAI,CAAC,OAAO,WAAW,QAAQ;AAC7B,UAAM,IAAI,MAAM,mEAAmE;AAAA,EACrF;AAEA,SAAO,OAAO,WAAW;AAC3B;AAEA,SAAS,gBAAgB,KAAsB;AAC7C,MAAI;AACF,WAAO,SAAS,0BAA0B,EAAE,KAAK,UAAU,SAAS,EAAE,OAAO,WAAW;AAAA,EAC1F,QAAQ;AACN,WAAO;AAAA,EACT;AACF;"}
|