@contentrain/types 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -220,7 +220,12 @@ interface ContentrainConfig {
220
220
  };
221
221
  domains: string[];
222
222
  assets_path?: string;
223
+ /** Days a merged `cr/*` branch is kept before lazy cleanup. Default: 30. */
223
224
  branchRetention?: number;
225
+ /** Unmerged `cr/*` branch count that triggers a warning. Default: 50. */
226
+ branchWarnLimit?: number;
227
+ /** Unmerged `cr/*` branch count that blocks new writes. Default: 80. */
228
+ branchBlockLimit?: number;
224
229
  }
225
230
  interface Vocabulary {
226
231
  version: number;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/provider.ts","../src/index.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/provider.ts","../src/index.ts"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/provider.ts","../src/index.ts"],"sourcesContent":["import type { SyncResult } from './index.js'\n\n// ─── Repository Provider Contracts ───\n//\n// Shared interfaces for the provider-agnostic content repository model used\n// by @contentrain/mcp. They live in @contentrain/types so third-party tools\n// can implement a custom RepoProvider (e.g. for a private git host, an\n// internal service, a mock in a test suite) without depending on MCP\n// internals.\n//\n// @contentrain/mcp re-exports every symbol here from\n// @contentrain/mcp/core/contracts so existing consumers do not have to\n// migrate imports.\n\n// ─── File change ───\n\n/**\n * A single file change within a plan.\n *\n * - `content: string` — write or overwrite the file with this UTF-8 content.\n * - `content: null` — delete the file.\n *\n * Paths are content-root relative, use forward slashes, and must not contain\n * `..` segments or absolute anchors. Providers are responsible for resolving\n * paths against their backing store (worktree, git tree, etc.).\n */\nexport interface FileChange {\n path: string\n content: string | null\n}\n\n// ─── Capabilities ───\n\n/**\n * Capabilities describe what a provider can and cannot do. Operations check\n * required capabilities before running. Normalize extract needs `sourceRead`;\n * normalize reuse needs `sourceWrite`; submit needs `pushRemote`; AST scans\n * need `astScan` (which implies a local working tree).\n *\n * The consistent position is: all git hosts are commodity MIT providers; the\n * distinction between providers is operational (how they read/write), not\n * commercial. Enterprise features live in Studio, not in capability gates.\n */\nexport interface ProviderCapabilities {\n /** Provider backs onto a local worktree and can selectively sync changes into the developer's working tree. */\n localWorktree: boolean\n /** Provider can read arbitrary source files outside `.contentrain/`. Required for normalize extract. */\n sourceRead: boolean\n /** Provider can write arbitrary source files outside `.contentrain/`. Required for normalize reuse. */\n sourceWrite: boolean\n /** Provider can push commits to a remote. Required for submit. */\n pushRemote: boolean\n /** Provider detects branch protection rules on the remote. */\n branchProtection: boolean\n /** Provider can open a pull request as a merge fallback when branch protection blocks direct merge. */\n pullRequestFallback: boolean\n /** Provider can execute AST scanners against source files. Implies local disk access. */\n astScan: boolean\n}\n\n/** Capability set for the LocalProvider (simple-git + worktree). */\nexport const LOCAL_CAPABILITIES: ProviderCapabilities = {\n localWorktree: true,\n sourceRead: true,\n sourceWrite: true,\n pushRemote: true,\n branchProtection: false,\n pullRequestFallback: false,\n astScan: true,\n}\n\n// ─── Reader ───\n\n/**\n * Read-only interface to a content repository.\n *\n * Paths are relative to the repository's content root (e.g.\n * `.contentrain/config.json`). The `ref` parameter is a branch name, tag,\n * or commit SHA. Providers that operate on a single working tree\n * (LocalReader) ignore `ref`; API-backed providers use it to resolve the\n * correct revision.\n *\n * `readFile` and `listDirectory` deliberately have different error semantics:\n * - `readFile` THROWS when the file is missing so callers must opt into\n * tolerance explicitly (typically with a try/catch returning a default).\n * - `listDirectory` returns `[]` for a missing directory because the empty\n * case is the common, uninteresting one.\n */\nexport interface RepoReader {\n /**\n * Read a file's contents as UTF-8.\n * @throws when the file does not exist or cannot be read.\n */\n readFile(path: string, ref?: string): Promise<string>\n\n /**\n * List file and directory names directly under `path`. Does not recurse.\n * Returns an empty array when the directory does not exist.\n */\n listDirectory(path: string, ref?: string): Promise<string[]>\n\n /** Check whether a file or directory exists at `path`. */\n fileExists(path: string, ref?: string): Promise<boolean>\n}\n\n// ─── Writer ───\n\nexport interface CommitAuthor {\n name: string\n email: string\n}\n\nexport interface Commit {\n sha: string\n message: string\n author: CommitAuthor\n timestamp: string\n}\n\n/**\n * Input to `applyPlan`. Represents a single atomic commit: all changes land\n * in one commit on `branch`, created from `base` if it does not yet exist.\n */\nexport interface ApplyPlanInput {\n /** Branch name to commit to. Created from `base` if missing. */\n branch: string\n /** File additions, modifications and deletions to apply in a single commit. */\n changes: FileChange[]\n /** Commit message. */\n message: string\n /** Commit author. */\n author: CommitAuthor\n /**\n * Optional base branch. Defaults to the Contentrain content-tracking\n * branch (`CONTENTRAIN_BRANCH` — the `contentrain` ref) — NOT the\n * repository's default branch. This is the single source of truth for\n * content state; every feature branch forks from it. Pass an explicit\n * `base` only when you know you want to bypass the invariant.\n */\n base?: string\n}\n\n/**\n * Write-side interface. Providers implement this to persist a set of file\n * changes as a single atomic commit. LocalProvider writes through a worktree\n * and `git commit`; API-backed providers post to the Git Data API or\n * equivalent.\n */\nexport interface RepoWriter {\n applyPlan(input: ApplyPlanInput): Promise<Commit>\n}\n\n// ─── Branch / diff / merge ───\n\nexport interface Branch {\n name: string\n sha: string\n protected?: boolean\n}\n\nexport interface FileDiff {\n path: string\n status: 'added' | 'modified' | 'removed'\n before: string | null\n after: string | null\n}\n\nexport interface MergeResult {\n merged: boolean\n sha: string | null\n pullRequestUrl: string | null\n /**\n * Selective-sync bookkeeping — only populated by providers that back onto\n * a local worktree (LocalProvider). Remote-API providers (GitHub, GitLab,\n * etc.) omit it because they do not touch a developer's working tree.\n */\n sync?: SyncResult\n}\n\n// ─── Provider (full surface) ───\n\n/**\n * A content repository provider — the unified surface that MCP tools drive.\n *\n * Implementations wrap a git backend:\n *\n * - `LocalProvider` — simple-git + temp worktree + selective sync\n * - `GitHubProvider` — Octokit Git Data API (no clone)\n * - `GitLabProvider` — gitbeaker REST client (no clone)\n * - `BitbucketProvider` — planned, coming soon\n *\n * Providers are commodity and all live in MIT.\n */\nexport interface RepoProvider extends RepoReader, RepoWriter {\n readonly capabilities: ProviderCapabilities\n\n listBranches(prefix?: string): Promise<Branch[]>\n createBranch(name: string, fromRef?: string): Promise<void>\n deleteBranch(name: string): Promise<void>\n getBranchDiff(branch: string, base?: string): Promise<FileDiff[]>\n mergeBranch(branch: string, into: string): Promise<MergeResult>\n isMerged(branch: string, into?: string): Promise<boolean>\n getDefaultBranch(): Promise<string>\n}\n","// ─── Type System ───\n\nexport type FieldType =\n | 'string' | 'text' | 'email' | 'url' | 'slug' | 'color' | 'phone' | 'code' | 'icon'\n | 'markdown' | 'richtext'\n | 'number' | 'integer' | 'decimal' | 'percent' | 'rating'\n | 'boolean'\n | 'date' | 'datetime'\n | 'image' | 'video' | 'file'\n | 'relation' | 'relations'\n | 'select' | 'array' | 'object'\n\nexport type ModelKind = 'singleton' | 'collection' | 'document' | 'dictionary'\nexport type ContentStatus = 'draft' | 'in_review' | 'published' | 'rejected' | 'archived'\nexport type ContentSource = 'agent' | 'human' | 'import'\nexport type WorkflowMode = 'auto-merge' | 'review'\n// Meta-frameworks\nexport type StackType =\n | 'nuxt' | 'next' | 'astro' | 'sveltekit' | 'remix' | 'analog'\n // Plain frameworks\n | 'vue' | 'react' | 'svelte' | 'solid' | 'angular'\n // Mobile\n | 'react-native' | 'expo' | 'flutter'\n // Backend\n | 'node' | 'express' | 'fastify' | 'nestjs' | 'django' | 'rails' | 'laravel' | 'go' | 'rust' | 'dotnet'\n // Static site generators\n | 'hugo' | 'jekyll' | 'eleventy'\n // Desktop\n | 'electron' | 'tauri'\n // Catch-all\n | 'other'\n\nexport type Platform = 'web' | 'mobile' | 'api' | 'desktop' | 'static' | 'other'\nexport type ContextSource = 'mcp-local' | 'mcp-studio' | 'studio-ui'\nexport type CollectionRuntimeFormat = 'map' | 'array'\n\n// ─── Field Definition ───\n\nexport interface FieldDef {\n type: FieldType\n required?: boolean\n unique?: boolean\n default?: unknown\n min?: number\n max?: number\n pattern?: string\n options?: string[]\n model?: string | string[]\n items?: string | FieldDef\n fields?: Record<string, FieldDef>\n accept?: string\n maxSize?: number\n description?: string\n}\n\n// ─── Model Definition ───\n\nexport type LocaleStrategy = 'file' | 'suffix' | 'directory' | 'none'\n\nexport interface ModelDefinition {\n id: string\n name: string\n kind: ModelKind\n domain: string\n i18n: boolean\n description?: string\n fields?: Record<string, FieldDef>\n /** Framework-relative path for content files (e.g. \"content/blog\", \"locales\"). When set, content is written here instead of .contentrain/content/ */\n content_path?: string\n /** How locale is encoded in file names. Default: \"file\" ({dir}/{locale}.json or {dir}/{slug}/{locale}.md) */\n locale_strategy?: LocaleStrategy\n}\n\n// ─── Config ───\n\nexport interface ContentrainConfig {\n version: number\n platform?: Platform\n stack: StackType\n workflow: WorkflowMode\n repository?: {\n /**\n * Git host backing this project's remote. Widens as new providers ship\n * in @contentrain/mcp — `github` and `gitlab` are currently supported.\n * The value is informational for tooling: the concrete provider the\n * MCP server talks to is chosen at server construction time, not from\n * this config.\n */\n provider: 'github' | 'gitlab'\n owner: string\n name: string\n default_branch: string\n }\n locales: {\n default: string\n supported: string[]\n }\n domains: string[]\n assets_path?: string\n branchRetention?: number\n}\n\n// ─── Vocabulary ───\n\nexport interface Vocabulary {\n version: number\n terms: Record<string, Record<string, string>>\n}\n\n// ─── Metadata ───\n\nexport interface EntryMeta {\n status: ContentStatus\n source: ContentSource\n updated_by: string\n approved_by?: string | null\n version?: string\n publish_at?: string\n expire_at?: string\n}\n\nexport type SingletonMeta = EntryMeta\nexport type CollectionMeta = Record<string, EntryMeta>\nexport type DocumentMeta = EntryMeta\nexport type DictionaryMeta = EntryMeta\n\n// ─── Asset ───\n\nexport interface AssetEntry {\n path: string\n type: string\n size: number\n alt?: string\n}\n\n// ─── Validation ───\n\nexport interface ValidationError {\n severity: 'error' | 'warning' | 'notice'\n model?: string\n locale?: string\n entry?: string\n slug?: string\n field?: string\n message: string\n}\n\nexport interface ValidationResult {\n valid: boolean\n errors: ValidationError[]\n}\n\n// ─── Content Types (Storage vs Output) ───\n\n// Storage formats — how content is written to disk (canonical JSON)\nexport type SingletonContentFile = Record<string, unknown>\nexport type CollectionContentFile = Record<string, Record<string, unknown>>\nexport type DictionaryContentFile = Record<string, string>\n// Document storage = markdown file (frontmatter + body), not JSON\n\n// Output formats — how MCP/SDK returns content to consumers\nexport type CollectionEntry = { id: string } & Record<string, unknown>\nexport type CollectionContentOutput = CollectionEntry[]\n\n/** Document entry as returned by MCP/SDK — parsed markdown with frontmatter */\nexport interface DocumentEntry {\n slug: string\n frontmatter: Record<string, unknown>\n body: string\n}\n\nexport type DocumentContentOutput = DocumentEntry[]\n\n/** Polymorphic relation storage — used when model field is string[] (multiple targets) */\nexport interface PolymorphicRelationRef {\n model: string\n ref: string\n}\n\n// ─── Model Summary ───\n\n/** Lightweight model info for listing and status operations */\nexport interface ModelSummary {\n id: string\n kind: ModelKind\n domain: string\n i18n: boolean\n fields: number\n}\n\n// ─── File Framework ───\n\n/** Source file framework — detected from extension for normalize/apply operations */\nexport type FileFramework = 'vue' | 'svelte' | 'jsx' | 'astro' | 'script'\n\n// ─── Path Conventions ───\n\n/** Root directory name for all Contentrain data */\nexport const CONTENTRAIN_DIR = '.contentrain' as const\n\n/**\n * Default path patterns for Contentrain projects.\n * Variables: {domain}, {modelId}, {locale}, {slug}\n *\n * When a model has `content_path` set, content files are written to\n * `{projectRoot}/{content_path}/` instead — but meta files always\n * remain under `.contentrain/meta/`.\n */\nexport const PATH_PATTERNS = {\n config: '.contentrain/config.json',\n context: '.contentrain/context.json',\n vocabulary: '.contentrain/vocabulary.json',\n model: '.contentrain/models/{modelId}.json',\n content: {\n singleton: '.contentrain/content/{domain}/{modelId}/{locale}.json',\n collection: '.contentrain/content/{domain}/{modelId}/{locale}.json',\n document: '.contentrain/content/{domain}/{slug}/{locale}.md',\n dictionary: '.contentrain/content/{domain}/{modelId}/{locale}.json',\n /** Non-i18n content (i18n: false) */\n noLocale: '.contentrain/content/{domain}/{modelId}/data.json',\n },\n meta: {\n singleton: '.contentrain/meta/{modelId}/{locale}.json',\n collection: '.contentrain/meta/{modelId}/{locale}.json',\n document: '.contentrain/meta/{modelId}/{slug}/{locale}.json',\n dictionary: '.contentrain/meta/{modelId}/{locale}.json',\n },\n} as const\n\n// ─── Validation Patterns ───\n\n/** Slug: lowercase alphanumeric with hyphens */\nexport const SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/\n/** Entry ID: alphanumeric, 1-40 chars, starts with alphanumeric */\nexport const ENTRY_ID_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,39}$/\n/** Locale: ISO 639-1 with optional region code */\nexport const LOCALE_PATTERN = /^[a-z]{2}(?:-[A-Z]{2})?$/\n\n// ─── Canonical Serialization ───\n\n/** Rules for deterministic JSON output — ensures stable git diffs */\nexport const CANONICAL_JSON = {\n indent: 2,\n encoding: 'utf-8',\n trailingNewline: true,\n omitNull: true,\n omitDefaults: true,\n sortKeys: true,\n} as const\n\n// ─── Scaffold ───\n\nexport interface ScaffoldTemplate {\n id: string\n models: ModelDefinition[]\n sample_content?: Record<string, Record<string, unknown>>\n vocabulary?: Record<string, Record<string, string>>\n}\n\n// ─── Scan Types ───\n\nexport type StringContext =\n | 'jsx_text' | 'jsx_attribute'\n | 'template_text' | 'template_attribute'\n | 'variable_assignment' | 'function_argument'\n | 'object_value' | 'other'\n\nexport type FileCategory = 'page' | 'component' | 'layout' | 'other'\n\nexport interface ScanCandidate {\n file: string\n line: number\n column: number\n value: string\n context: StringContext\n surrounding: string\n /** Content confidence score (0-1). Higher = more likely user-visible content. */\n contentScore: number\n /** All locations where this value appears (populated when dedup is enabled). */\n occurrences: Array<{ file: string; line: number }>\n}\n\nexport interface DuplicateGroup {\n value: string\n count: number\n occurrences: Array<{ file: string; line: number }>\n}\n\nexport interface GraphNode {\n file: string\n category: FileCategory\n components?: string[]\n imports: string[]\n used_by: string[]\n strings: number\n}\n\nexport interface ProjectGraph {\n pages: GraphNode[]\n components: GraphNode[]\n layouts: GraphNode[]\n orphan_files: string[]\n stats: {\n total_files: number\n total_components: number\n total_pages: number\n total_strings_estimate: number\n }\n}\n\nexport interface ScanCandidatesResult {\n candidates: ScanCandidate[]\n duplicates: DuplicateGroup[]\n stats: {\n files_scanned: number\n raw_strings_found: number\n skipped: number\n low_confidence: number\n unique_candidates: number\n candidates_returned: number\n has_more: boolean\n skip_reasons: Record<string, number>\n }\n}\n\nexport interface ScanSummaryResult {\n total_files: number\n total_candidates_estimate: number\n by_directory: Record<string, { files: number; candidates: number }>\n top_repeated: Array<{ value: string; count: number }>\n sampling_note?: string\n file_types: Record<string, number>\n}\n\n// ─── Normalize Plan ───\n\nexport interface NormalizePlan {\n version: number\n status: 'pending' | 'approved' | 'rejected'\n created_at: string\n approved_at?: string\n agent: string\n scan_stats: {\n files_scanned: number\n raw_strings: number\n candidates_sent: number\n extracted: number\n skipped: number\n }\n models: NormalizePlanModel[]\n extractions: NormalizePlanExtraction[]\n patches: NormalizePlanPatch[]\n approved_models?: string[]\n}\n\nexport interface NormalizePlanModel {\n id: string\n kind: ModelKind\n domain: string\n i18n?: boolean\n fields: Record<string, FieldDef>\n}\n\nexport interface NormalizePlanExtraction {\n value: string\n file: string\n line: number\n model: string\n field: string\n locale?: string\n}\n\nexport interface NormalizePlanPatch {\n file: string\n line: number\n old_value: string\n new_expression: string\n import_statement?: string\n}\n\n// ─── Context ───\n\nexport interface ContextJson {\n version: string\n lastOperation: {\n tool: string\n model: string\n locale: string\n entries?: string[]\n timestamp: string\n source: ContextSource\n }\n stats: {\n models: number\n entries: number\n locales: string[]\n lastSync: string\n }\n}\n\n// ─── Git Transaction Types ───\n\n/** Standard name for the dedicated content branch */\nexport const CONTENTRAIN_BRANCH = 'contentrain' as const\n\n/** Result of selective file sync to developer's working tree */\nexport interface SyncResult {\n /** Files successfully synced to working tree */\n synced: string[]\n /** Files skipped due to uncommitted local changes */\n skipped: string[]\n /** Human-readable warning if files were skipped */\n warning?: string\n}\n\n/** Structured error for git operations with actionable guidance */\nexport interface ContentrainError {\n /** Machine-readable error code */\n code: string\n /** Human-readable error message */\n message: string\n /** Guidance for AI agents on how to handle this error */\n agent_hint: string\n /** Command or action the developer should take */\n developer_action: string\n}\n\n// ─── Validate: Pure Functions ───\n\n/** Common patterns for detecting potential secrets in content values */\nexport const SECRET_PATTERNS: ReadonlyArray<RegExp> = [\n /sk_/, /pk_/, /api_key/i, /apikey/i,\n /ghp_/, /gho_/, /Bearer /,\n /postgres:\\/\\//, /mysql:\\/\\//, /mongodb:\\/\\//,\n /-----BEGIN/, /AKIA/, /aws_secret/i,\n]\n\n/** Validate a slug — returns error message or null if valid */\nexport function validateSlug(slug: string): string | null {\n if (!slug) return 'Slug is required'\n if (!SLUG_PATTERN.test(slug)) return `Invalid slug \"${slug}\": must be kebab-case alphanumeric (a-z, 0-9, hyphens)`\n if (slug.startsWith('.') || slug.includes('..')) return `Invalid slug \"${slug}\": path traversal not allowed`\n return null\n}\n\n/** Validate an entry ID — returns error message or null if valid */\nexport function validateEntryId(id: string): string | null {\n if (!ENTRY_ID_PATTERN.test(id)) return `Invalid entry ID \"${id}\": must be 1-40 alphanumeric characters (hyphens and underscores allowed)`\n return null\n}\n\n/** Validate a locale code against pattern and config — returns error message or null if valid */\nexport function validateLocale(locale: string, config: ContentrainConfig): string | null {\n if (!LOCALE_PATTERN.test(locale)) return `Invalid locale \"${locale}\": must be ISO 639-1 format (e.g. \"en\", \"tr\", \"pt-BR\")`\n if (!config.locales.supported.includes(locale)) {\n return `Locale \"${locale}\" is not in supported locales [${config.locales.supported.join(', ')}]. Update config first.`\n }\n return null\n}\n\n/** Detect potential secrets in a value — returns validation errors if found */\nexport function detectSecrets(value: unknown): ValidationError[] {\n if (typeof value !== 'string') return []\n if (SECRET_PATTERNS.some(p => p.test(value))) {\n return [{ severity: 'error', message: 'Potential secret detected in value' }]\n }\n return []\n}\n\nfunction fieldTypeMatches(value: unknown, fieldDef: FieldDef): boolean {\n if (value === null || value === undefined) return true\n\n switch (fieldDef.type) {\n case 'string':\n case 'text':\n case 'email':\n case 'url':\n case 'slug':\n case 'color':\n case 'phone':\n case 'code':\n case 'icon':\n case 'markdown':\n case 'richtext':\n case 'date':\n case 'datetime':\n case 'image':\n case 'video':\n case 'file':\n case 'select':\n return typeof value === 'string'\n\n case 'number':\n case 'integer':\n case 'decimal':\n case 'percent':\n case 'rating':\n return typeof value === 'number'\n\n case 'boolean':\n return typeof value === 'boolean'\n\n case 'relation':\n return typeof value === 'string'\n\n case 'relations':\n case 'array':\n return Array.isArray(value)\n\n case 'object':\n return typeof value === 'object' && !Array.isArray(value)\n\n default:\n return true\n }\n}\n\nfunction checkMinMax(value: unknown, fieldDef: FieldDef): string | null {\n if (fieldDef.min !== undefined) {\n if (typeof value === 'number' && value < fieldDef.min) {\n return `Value ${value} is below minimum ${fieldDef.min}`\n }\n if (typeof value === 'string' && value.length < fieldDef.min) {\n return `String length ${value.length} is below minimum ${fieldDef.min}`\n }\n if (Array.isArray(value) && value.length < fieldDef.min) {\n return `Array length ${value.length} is below minimum ${fieldDef.min}`\n }\n }\n if (fieldDef.max !== undefined) {\n if (typeof value === 'number' && value > fieldDef.max) {\n return `Value ${value} is above maximum ${fieldDef.max}`\n }\n if (typeof value === 'string' && value.length > fieldDef.max) {\n return `String length ${value.length} is above maximum ${fieldDef.max}`\n }\n if (Array.isArray(value) && value.length > fieldDef.max) {\n return `Array length ${value.length} is above maximum ${fieldDef.max}`\n }\n }\n return null\n}\n\n/**\n * Validate a field value against its FieldDef schema.\n * Checks: required, type match, min/max, pattern, select options.\n * Does NOT check: secrets (use detectSecrets), uniqueness (stateful), relations (I/O).\n */\nexport function validateFieldValue(value: unknown, fieldDef: FieldDef): ValidationError[] {\n const issues: ValidationError[] = []\n\n if (fieldDef.required && (value === undefined || value === null || value === '')) {\n issues.push({ severity: 'error', message: 'Required field is missing or empty' })\n return issues\n }\n\n if (value === undefined || value === null) return issues\n\n if (!fieldTypeMatches(value, fieldDef)) {\n issues.push({ severity: 'error', message: `Type mismatch: expected ${fieldDef.type}, got ${typeof value}` })\n return issues\n }\n\n const minMaxErr = checkMinMax(value, fieldDef)\n if (minMaxErr) {\n issues.push({ severity: 'error', message: minMaxErr })\n }\n\n if (fieldDef.pattern && typeof value === 'string') {\n try {\n const regex = new RegExp(fieldDef.pattern)\n if (!regex.test(value)) {\n issues.push({ severity: 'error', message: `Value \"${value}\" does not match pattern /${fieldDef.pattern}/` })\n }\n } catch {\n issues.push({ severity: 'warning', message: `Invalid pattern regex: ${fieldDef.pattern}` })\n }\n }\n\n if (fieldDef.type === 'select' && fieldDef.options && typeof value === 'string') {\n if (!fieldDef.options.includes(value)) {\n issues.push({ severity: 'error', message: `Value \"${value}\" is not in allowed options: [${fieldDef.options.join(', ')}]` })\n }\n }\n\n return issues\n}\n\n// ─── Serialize: Pure Functions ───\n\n/** Recursively sort object keys — respects optional fieldOrder for top-level keys */\nexport function sortKeys(obj: unknown, fieldOrder?: string[]): unknown {\n if (obj === null || obj === undefined) return undefined\n if (Array.isArray(obj)) return obj.map(item => sortKeys(item, fieldOrder))\n if (typeof obj !== 'object') return obj\n\n const record = obj as Record<string, unknown>\n const sorted: Record<string, unknown> = {}\n\n const keys = fieldOrder\n ? [...new Set([...fieldOrder, ...Object.keys(record).toSorted()])]\n : Object.keys(record).toSorted()\n\n for (const key of keys) {\n if (!(key in record)) continue\n const val = record[key]\n if (val === null || val === undefined) continue\n sorted[key] = sortKeys(val)\n }\n\n return sorted\n}\n\n/** Canonical JSON serialization — deterministic output for stable git diffs */\nexport function canonicalStringify(data: unknown, fieldOrder?: string[]): string {\n const sorted = sortKeys(data, fieldOrder)\n return `${JSON.stringify(sorted, null, 2)}\\n`\n}\n\n/** Generate a 12-character hex entry ID */\nexport function generateEntryId(): string {\n const hex = '0123456789abcdef'\n let id = ''\n for (let i = 0; i < 12; i++) {\n id += hex[Math.floor(Math.random() * 16)]\n }\n return id\n}\n\n// ─── Markdown Frontmatter ───\n\nfunction parseYamlValue(raw: string): unknown {\n if (raw === 'true') return true\n if (raw === 'false') return false\n if (raw === 'null') return null\n if (/^-?\\d+$/.test(raw)) return parseInt(raw, 10)\n if (/^-?\\d+\\.\\d+$/.test(raw)) return parseFloat(raw)\n if ((raw.startsWith('\"') && raw.endsWith('\"')) || (raw.startsWith(\"'\") && raw.endsWith(\"'\"))) {\n return raw.slice(1, -1)\n }\n return raw\n}\n\nfunction yamlScalar(value: unknown): string {\n const str = String(value)\n if (str.includes(':') || str.includes('#') || str.includes('{') || str.includes('}')\n || str.includes('[') || str.includes(']') || str.includes('*') || str.includes('&')\n || str.includes('!') || str.includes('|') || str.includes('>') || str.includes(\"'\")\n || str.includes('\"') || str.includes('%') || str.includes('@') || str.includes('`')\n || str.startsWith('-') || str.startsWith('?')\n || str === 'true' || str === 'false' || str === 'null' || str === 'yes' || str === 'no'\n || str === '') {\n return `\"${str.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`\n }\n return str\n}\n\nfunction serializeYamlValue(value: unknown, indent: number): string[] {\n const pad = ' '.repeat(indent)\n if (value === null || value === undefined) return []\n if (typeof value === 'object' && !Array.isArray(value)) {\n const lines: string[] = []\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n if (v === null || v === undefined) continue\n if (typeof v === 'object' && !Array.isArray(v)) {\n lines.push(`${pad}${k}:`)\n lines.push(...serializeYamlValue(v, indent + 1))\n } else if (Array.isArray(v)) {\n lines.push(`${pad}${k}:`)\n for (const item of v) {\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n const nested = serializeYamlValue(item, indent + 2)\n if (nested.length > 0) {\n lines.push(`${pad} - ${nested[0]!.trimStart()}`)\n lines.push(...nested.slice(1))\n }\n } else {\n lines.push(`${pad} - ${yamlScalar(item)}`)\n }\n }\n } else {\n lines.push(`${pad}${k}: ${yamlScalar(v)}`)\n }\n }\n return lines\n }\n if (Array.isArray(value)) {\n const lines: string[] = []\n for (const item of value) {\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n const nested = serializeYamlValue(item, indent + 1)\n if (nested.length > 0) {\n lines.push(`${pad}- ${nested[0]!.trimStart()}`)\n lines.push(...nested.slice(1))\n }\n } else {\n lines.push(`${pad}- ${yamlScalar(item)}`)\n }\n }\n return lines\n }\n return [`${pad}${yamlScalar(value)}`]\n}\n\nfunction serializeYamlFields(data: Record<string, unknown>): string[] {\n const lines: string[] = []\n for (const [key, value] of Object.entries(data)) {\n if (key === 'body') continue\n if (value === null || value === undefined) continue\n if (typeof value === 'object' && !Array.isArray(value)) {\n lines.push(`${key}:`)\n lines.push(...serializeYamlValue(value, 1))\n } else if (Array.isArray(value)) {\n lines.push(`${key}:`)\n for (const item of value) {\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n const nested = serializeYamlValue(item, 2)\n if (nested.length > 0) {\n lines.push(` - ${nested[0]!.trimStart()}`)\n lines.push(...nested.slice(1))\n }\n } else {\n lines.push(` - ${yamlScalar(item)}`)\n }\n }\n } else {\n lines.push(`${key}: ${yamlScalar(value)}`)\n }\n }\n return lines\n}\n\n/** Parse markdown frontmatter — extracts YAML frontmatter and body from a markdown string */\nexport function parseMarkdownFrontmatter(content: string): { frontmatter: Record<string, unknown>; body: string } {\n const normalized = content.replace(/\\r\\n/g, '\\n')\n const match = normalized.match(/^---\\n([\\s\\S]*?)\\n---\\n?([\\s\\S]*)$/)\n if (!match) return { frontmatter: {}, body: normalized }\n\n const frontmatterStr = match[1]!\n const body = match[2]!.trim()\n const frontmatter: Record<string, unknown> = {}\n\n let currentKey: string | null = null\n let currentArray: string[] | null = null\n\n for (const line of frontmatterStr.split('\\n')) {\n if (/^\\s+-\\s+/.test(line) && currentKey) {\n const value = line.replace(/^\\s+-\\s+/, '').trim()\n if (!currentArray) currentArray = []\n currentArray.push(value)\n continue\n }\n\n if (currentKey && currentArray) {\n frontmatter[currentKey] = currentArray\n currentKey = null\n currentArray = null\n }\n\n const kvMatch = line.match(/^([\\w][\\w.-]*)\\s*:\\s*(.*)$/)\n if (!kvMatch) continue\n\n const key = kvMatch[1]!\n const rawValue = kvMatch[2]!.trim()\n\n if (rawValue === '') {\n currentKey = key\n currentArray = []\n continue\n }\n\n if (rawValue.startsWith('[') && rawValue.endsWith(']')) {\n const items = rawValue.slice(1, -1).split(',').map(s => s.trim()).filter(Boolean)\n frontmatter[key] = items\n continue\n }\n\n frontmatter[key] = parseYamlValue(rawValue)\n }\n\n if (currentKey && currentArray) {\n frontmatter[currentKey] = currentArray\n }\n\n return { frontmatter, body }\n}\n\n/** Serialize data + body into markdown frontmatter format */\nexport function serializeMarkdownFrontmatter(data: Record<string, unknown>, body: string): string {\n const trimmedBody = body.trimStart()\n if (trimmedBody.startsWith('---')) {\n const endIdx = trimmedBody.indexOf('---', 3)\n if (endIdx > 0) {\n const bodyFmContent = trimmedBody.slice(3, endIdx).trim()\n const afterFm = trimmedBody.slice(endIdx + 3)\n\n const lines: string[] = ['---']\n lines.push(...serializeYamlFields(data))\n if (bodyFmContent) {\n const modelKeys = new Set(Object.keys(data))\n for (const line of bodyFmContent.split('\\n')) {\n if (line.length > 0 && line[0] !== ' ' && line[0] !== '-') {\n const colonIdx = line.indexOf(':')\n const lineKey = colonIdx > 0 ? line.slice(0, colonIdx).trim() : ''\n if (lineKey && modelKeys.has(lineKey)) continue\n }\n lines.push(line)\n }\n }\n lines.push('---')\n if (afterFm.trim()) {\n lines.push(afterFm.trimStart())\n }\n lines.push('')\n return lines.join('\\n')\n }\n }\n\n const lines: string[] = ['---']\n lines.push(...serializeYamlFields(data))\n lines.push('---')\n lines.push('')\n if (body) {\n lines.push(body)\n lines.push('')\n }\n return lines.join('\\n')\n}\n\n// ─── Repository provider contracts ───\n//\n// Provider-agnostic engine contracts used by @contentrain/mcp. Exposed from\n// @contentrain/types so third-party tools can implement a custom\n// RepoProvider without taking a dependency on @contentrain/mcp.\nexport type {\n ApplyPlanInput,\n Branch,\n Commit,\n CommitAuthor,\n FileChange,\n FileDiff,\n MergeResult,\n ProviderCapabilities,\n RepoProvider,\n RepoReader,\n RepoWriter,\n} from './provider.js'\nexport { LOCAL_CAPABILITIES } from './provider.js'\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/provider.ts","../src/index.ts"],"sourcesContent":["import type { SyncResult } from './index.js'\n\n// ─── Repository Provider Contracts ───\n//\n// Shared interfaces for the provider-agnostic content repository model used\n// by @contentrain/mcp. They live in @contentrain/types so third-party tools\n// can implement a custom RepoProvider (e.g. for a private git host, an\n// internal service, a mock in a test suite) without depending on MCP\n// internals.\n//\n// @contentrain/mcp re-exports every symbol here from\n// @contentrain/mcp/core/contracts so existing consumers do not have to\n// migrate imports.\n\n// ─── File change ───\n\n/**\n * A single file change within a plan.\n *\n * - `content: string` — write or overwrite the file with this UTF-8 content.\n * - `content: null` — delete the file.\n *\n * Paths are content-root relative, use forward slashes, and must not contain\n * `..` segments or absolute anchors. Providers are responsible for resolving\n * paths against their backing store (worktree, git tree, etc.).\n */\nexport interface FileChange {\n path: string\n content: string | null\n}\n\n// ─── Capabilities ───\n\n/**\n * Capabilities describe what a provider can and cannot do. Operations check\n * required capabilities before running. Normalize extract needs `sourceRead`;\n * normalize reuse needs `sourceWrite`; submit needs `pushRemote`; AST scans\n * need `astScan` (which implies a local working tree).\n *\n * The consistent position is: all git hosts are commodity MIT providers; the\n * distinction between providers is operational (how they read/write), not\n * commercial. Enterprise features live in Studio, not in capability gates.\n */\nexport interface ProviderCapabilities {\n /** Provider backs onto a local worktree and can selectively sync changes into the developer's working tree. */\n localWorktree: boolean\n /** Provider can read arbitrary source files outside `.contentrain/`. Required for normalize extract. */\n sourceRead: boolean\n /** Provider can write arbitrary source files outside `.contentrain/`. Required for normalize reuse. */\n sourceWrite: boolean\n /** Provider can push commits to a remote. Required for submit. */\n pushRemote: boolean\n /** Provider detects branch protection rules on the remote. */\n branchProtection: boolean\n /** Provider can open a pull request as a merge fallback when branch protection blocks direct merge. */\n pullRequestFallback: boolean\n /** Provider can execute AST scanners against source files. Implies local disk access. */\n astScan: boolean\n}\n\n/** Capability set for the LocalProvider (simple-git + worktree). */\nexport const LOCAL_CAPABILITIES: ProviderCapabilities = {\n localWorktree: true,\n sourceRead: true,\n sourceWrite: true,\n pushRemote: true,\n branchProtection: false,\n pullRequestFallback: false,\n astScan: true,\n}\n\n// ─── Reader ───\n\n/**\n * Read-only interface to a content repository.\n *\n * Paths are relative to the repository's content root (e.g.\n * `.contentrain/config.json`). The `ref` parameter is a branch name, tag,\n * or commit SHA. Providers that operate on a single working tree\n * (LocalReader) ignore `ref`; API-backed providers use it to resolve the\n * correct revision.\n *\n * `readFile` and `listDirectory` deliberately have different error semantics:\n * - `readFile` THROWS when the file is missing so callers must opt into\n * tolerance explicitly (typically with a try/catch returning a default).\n * - `listDirectory` returns `[]` for a missing directory because the empty\n * case is the common, uninteresting one.\n */\nexport interface RepoReader {\n /**\n * Read a file's contents as UTF-8.\n * @throws when the file does not exist or cannot be read.\n */\n readFile(path: string, ref?: string): Promise<string>\n\n /**\n * List file and directory names directly under `path`. Does not recurse.\n * Returns an empty array when the directory does not exist.\n */\n listDirectory(path: string, ref?: string): Promise<string[]>\n\n /** Check whether a file or directory exists at `path`. */\n fileExists(path: string, ref?: string): Promise<boolean>\n}\n\n// ─── Writer ───\n\nexport interface CommitAuthor {\n name: string\n email: string\n}\n\nexport interface Commit {\n sha: string\n message: string\n author: CommitAuthor\n timestamp: string\n}\n\n/**\n * Input to `applyPlan`. Represents a single atomic commit: all changes land\n * in one commit on `branch`, created from `base` if it does not yet exist.\n */\nexport interface ApplyPlanInput {\n /** Branch name to commit to. Created from `base` if missing. */\n branch: string\n /** File additions, modifications and deletions to apply in a single commit. */\n changes: FileChange[]\n /** Commit message. */\n message: string\n /** Commit author. */\n author: CommitAuthor\n /**\n * Optional base branch. Defaults to the Contentrain content-tracking\n * branch (`CONTENTRAIN_BRANCH` — the `contentrain` ref) — NOT the\n * repository's default branch. This is the single source of truth for\n * content state; every feature branch forks from it. Pass an explicit\n * `base` only when you know you want to bypass the invariant.\n */\n base?: string\n}\n\n/**\n * Write-side interface. Providers implement this to persist a set of file\n * changes as a single atomic commit. LocalProvider writes through a worktree\n * and `git commit`; API-backed providers post to the Git Data API or\n * equivalent.\n */\nexport interface RepoWriter {\n applyPlan(input: ApplyPlanInput): Promise<Commit>\n}\n\n// ─── Branch / diff / merge ───\n\nexport interface Branch {\n name: string\n sha: string\n protected?: boolean\n}\n\nexport interface FileDiff {\n path: string\n status: 'added' | 'modified' | 'removed'\n before: string | null\n after: string | null\n}\n\nexport interface MergeResult {\n merged: boolean\n sha: string | null\n pullRequestUrl: string | null\n /**\n * Selective-sync bookkeeping — only populated by providers that back onto\n * a local worktree (LocalProvider). Remote-API providers (GitHub, GitLab,\n * etc.) omit it because they do not touch a developer's working tree.\n */\n sync?: SyncResult\n}\n\n// ─── Provider (full surface) ───\n\n/**\n * A content repository provider — the unified surface that MCP tools drive.\n *\n * Implementations wrap a git backend:\n *\n * - `LocalProvider` — simple-git + temp worktree + selective sync\n * - `GitHubProvider` — Octokit Git Data API (no clone)\n * - `GitLabProvider` — gitbeaker REST client (no clone)\n * - `BitbucketProvider` — planned, coming soon\n *\n * Providers are commodity and all live in MIT.\n */\nexport interface RepoProvider extends RepoReader, RepoWriter {\n readonly capabilities: ProviderCapabilities\n\n listBranches(prefix?: string): Promise<Branch[]>\n createBranch(name: string, fromRef?: string): Promise<void>\n deleteBranch(name: string): Promise<void>\n getBranchDiff(branch: string, base?: string): Promise<FileDiff[]>\n mergeBranch(branch: string, into: string): Promise<MergeResult>\n isMerged(branch: string, into?: string): Promise<boolean>\n getDefaultBranch(): Promise<string>\n}\n","// ─── Type System ───\n\nexport type FieldType =\n | 'string' | 'text' | 'email' | 'url' | 'slug' | 'color' | 'phone' | 'code' | 'icon'\n | 'markdown' | 'richtext'\n | 'number' | 'integer' | 'decimal' | 'percent' | 'rating'\n | 'boolean'\n | 'date' | 'datetime'\n | 'image' | 'video' | 'file'\n | 'relation' | 'relations'\n | 'select' | 'array' | 'object'\n\nexport type ModelKind = 'singleton' | 'collection' | 'document' | 'dictionary'\nexport type ContentStatus = 'draft' | 'in_review' | 'published' | 'rejected' | 'archived'\nexport type ContentSource = 'agent' | 'human' | 'import'\nexport type WorkflowMode = 'auto-merge' | 'review'\n// Meta-frameworks\nexport type StackType =\n | 'nuxt' | 'next' | 'astro' | 'sveltekit' | 'remix' | 'analog'\n // Plain frameworks\n | 'vue' | 'react' | 'svelte' | 'solid' | 'angular'\n // Mobile\n | 'react-native' | 'expo' | 'flutter'\n // Backend\n | 'node' | 'express' | 'fastify' | 'nestjs' | 'django' | 'rails' | 'laravel' | 'go' | 'rust' | 'dotnet'\n // Static site generators\n | 'hugo' | 'jekyll' | 'eleventy'\n // Desktop\n | 'electron' | 'tauri'\n // Catch-all\n | 'other'\n\nexport type Platform = 'web' | 'mobile' | 'api' | 'desktop' | 'static' | 'other'\nexport type ContextSource = 'mcp-local' | 'mcp-studio' | 'studio-ui'\nexport type CollectionRuntimeFormat = 'map' | 'array'\n\n// ─── Field Definition ───\n\nexport interface FieldDef {\n type: FieldType\n required?: boolean\n unique?: boolean\n default?: unknown\n min?: number\n max?: number\n pattern?: string\n options?: string[]\n model?: string | string[]\n items?: string | FieldDef\n fields?: Record<string, FieldDef>\n accept?: string\n maxSize?: number\n description?: string\n}\n\n// ─── Model Definition ───\n\nexport type LocaleStrategy = 'file' | 'suffix' | 'directory' | 'none'\n\nexport interface ModelDefinition {\n id: string\n name: string\n kind: ModelKind\n domain: string\n i18n: boolean\n description?: string\n fields?: Record<string, FieldDef>\n /** Framework-relative path for content files (e.g. \"content/blog\", \"locales\"). When set, content is written here instead of .contentrain/content/ */\n content_path?: string\n /** How locale is encoded in file names. Default: \"file\" ({dir}/{locale}.json or {dir}/{slug}/{locale}.md) */\n locale_strategy?: LocaleStrategy\n}\n\n// ─── Config ───\n\nexport interface ContentrainConfig {\n version: number\n platform?: Platform\n stack: StackType\n workflow: WorkflowMode\n repository?: {\n /**\n * Git host backing this project's remote. Widens as new providers ship\n * in @contentrain/mcp — `github` and `gitlab` are currently supported.\n * The value is informational for tooling: the concrete provider the\n * MCP server talks to is chosen at server construction time, not from\n * this config.\n */\n provider: 'github' | 'gitlab'\n owner: string\n name: string\n default_branch: string\n }\n locales: {\n default: string\n supported: string[]\n }\n domains: string[]\n assets_path?: string\n /** Days a merged `cr/*` branch is kept before lazy cleanup. Default: 30. */\n branchRetention?: number\n /** Unmerged `cr/*` branch count that triggers a warning. Default: 50. */\n branchWarnLimit?: number\n /** Unmerged `cr/*` branch count that blocks new writes. Default: 80. */\n branchBlockLimit?: number\n}\n\n// ─── Vocabulary ───\n\nexport interface Vocabulary {\n version: number\n terms: Record<string, Record<string, string>>\n}\n\n// ─── Metadata ───\n\nexport interface EntryMeta {\n status: ContentStatus\n source: ContentSource\n updated_by: string\n approved_by?: string | null\n version?: string\n publish_at?: string\n expire_at?: string\n}\n\nexport type SingletonMeta = EntryMeta\nexport type CollectionMeta = Record<string, EntryMeta>\nexport type DocumentMeta = EntryMeta\nexport type DictionaryMeta = EntryMeta\n\n// ─── Asset ───\n\nexport interface AssetEntry {\n path: string\n type: string\n size: number\n alt?: string\n}\n\n// ─── Validation ───\n\nexport interface ValidationError {\n severity: 'error' | 'warning' | 'notice'\n model?: string\n locale?: string\n entry?: string\n slug?: string\n field?: string\n message: string\n}\n\nexport interface ValidationResult {\n valid: boolean\n errors: ValidationError[]\n}\n\n// ─── Content Types (Storage vs Output) ───\n\n// Storage formats — how content is written to disk (canonical JSON)\nexport type SingletonContentFile = Record<string, unknown>\nexport type CollectionContentFile = Record<string, Record<string, unknown>>\nexport type DictionaryContentFile = Record<string, string>\n// Document storage = markdown file (frontmatter + body), not JSON\n\n// Output formats — how MCP/SDK returns content to consumers\nexport type CollectionEntry = { id: string } & Record<string, unknown>\nexport type CollectionContentOutput = CollectionEntry[]\n\n/** Document entry as returned by MCP/SDK — parsed markdown with frontmatter */\nexport interface DocumentEntry {\n slug: string\n frontmatter: Record<string, unknown>\n body: string\n}\n\nexport type DocumentContentOutput = DocumentEntry[]\n\n/** Polymorphic relation storage — used when model field is string[] (multiple targets) */\nexport interface PolymorphicRelationRef {\n model: string\n ref: string\n}\n\n// ─── Model Summary ───\n\n/** Lightweight model info for listing and status operations */\nexport interface ModelSummary {\n id: string\n kind: ModelKind\n domain: string\n i18n: boolean\n fields: number\n}\n\n// ─── File Framework ───\n\n/** Source file framework — detected from extension for normalize/apply operations */\nexport type FileFramework = 'vue' | 'svelte' | 'jsx' | 'astro' | 'script'\n\n// ─── Path Conventions ───\n\n/** Root directory name for all Contentrain data */\nexport const CONTENTRAIN_DIR = '.contentrain' as const\n\n/**\n * Default path patterns for Contentrain projects.\n * Variables: {domain}, {modelId}, {locale}, {slug}\n *\n * When a model has `content_path` set, content files are written to\n * `{projectRoot}/{content_path}/` instead — but meta files always\n * remain under `.contentrain/meta/`.\n */\nexport const PATH_PATTERNS = {\n config: '.contentrain/config.json',\n context: '.contentrain/context.json',\n vocabulary: '.contentrain/vocabulary.json',\n model: '.contentrain/models/{modelId}.json',\n content: {\n singleton: '.contentrain/content/{domain}/{modelId}/{locale}.json',\n collection: '.contentrain/content/{domain}/{modelId}/{locale}.json',\n document: '.contentrain/content/{domain}/{slug}/{locale}.md',\n dictionary: '.contentrain/content/{domain}/{modelId}/{locale}.json',\n /** Non-i18n content (i18n: false) */\n noLocale: '.contentrain/content/{domain}/{modelId}/data.json',\n },\n meta: {\n singleton: '.contentrain/meta/{modelId}/{locale}.json',\n collection: '.contentrain/meta/{modelId}/{locale}.json',\n document: '.contentrain/meta/{modelId}/{slug}/{locale}.json',\n dictionary: '.contentrain/meta/{modelId}/{locale}.json',\n },\n} as const\n\n// ─── Validation Patterns ───\n\n/** Slug: lowercase alphanumeric with hyphens */\nexport const SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/\n/** Entry ID: alphanumeric, 1-40 chars, starts with alphanumeric */\nexport const ENTRY_ID_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,39}$/\n/** Locale: ISO 639-1 with optional region code */\nexport const LOCALE_PATTERN = /^[a-z]{2}(?:-[A-Z]{2})?$/\n\n// ─── Canonical Serialization ───\n\n/** Rules for deterministic JSON output — ensures stable git diffs */\nexport const CANONICAL_JSON = {\n indent: 2,\n encoding: 'utf-8',\n trailingNewline: true,\n omitNull: true,\n omitDefaults: true,\n sortKeys: true,\n} as const\n\n// ─── Scaffold ───\n\nexport interface ScaffoldTemplate {\n id: string\n models: ModelDefinition[]\n sample_content?: Record<string, Record<string, unknown>>\n vocabulary?: Record<string, Record<string, string>>\n}\n\n// ─── Scan Types ───\n\nexport type StringContext =\n | 'jsx_text' | 'jsx_attribute'\n | 'template_text' | 'template_attribute'\n | 'variable_assignment' | 'function_argument'\n | 'object_value' | 'other'\n\nexport type FileCategory = 'page' | 'component' | 'layout' | 'other'\n\nexport interface ScanCandidate {\n file: string\n line: number\n column: number\n value: string\n context: StringContext\n surrounding: string\n /** Content confidence score (0-1). Higher = more likely user-visible content. */\n contentScore: number\n /** All locations where this value appears (populated when dedup is enabled). */\n occurrences: Array<{ file: string; line: number }>\n}\n\nexport interface DuplicateGroup {\n value: string\n count: number\n occurrences: Array<{ file: string; line: number }>\n}\n\nexport interface GraphNode {\n file: string\n category: FileCategory\n components?: string[]\n imports: string[]\n used_by: string[]\n strings: number\n}\n\nexport interface ProjectGraph {\n pages: GraphNode[]\n components: GraphNode[]\n layouts: GraphNode[]\n orphan_files: string[]\n stats: {\n total_files: number\n total_components: number\n total_pages: number\n total_strings_estimate: number\n }\n}\n\nexport interface ScanCandidatesResult {\n candidates: ScanCandidate[]\n duplicates: DuplicateGroup[]\n stats: {\n files_scanned: number\n raw_strings_found: number\n skipped: number\n low_confidence: number\n unique_candidates: number\n candidates_returned: number\n has_more: boolean\n skip_reasons: Record<string, number>\n }\n}\n\nexport interface ScanSummaryResult {\n total_files: number\n total_candidates_estimate: number\n by_directory: Record<string, { files: number; candidates: number }>\n top_repeated: Array<{ value: string; count: number }>\n sampling_note?: string\n file_types: Record<string, number>\n}\n\n// ─── Normalize Plan ───\n\nexport interface NormalizePlan {\n version: number\n status: 'pending' | 'approved' | 'rejected'\n created_at: string\n approved_at?: string\n agent: string\n scan_stats: {\n files_scanned: number\n raw_strings: number\n candidates_sent: number\n extracted: number\n skipped: number\n }\n models: NormalizePlanModel[]\n extractions: NormalizePlanExtraction[]\n patches: NormalizePlanPatch[]\n approved_models?: string[]\n}\n\nexport interface NormalizePlanModel {\n id: string\n kind: ModelKind\n domain: string\n i18n?: boolean\n fields: Record<string, FieldDef>\n}\n\nexport interface NormalizePlanExtraction {\n value: string\n file: string\n line: number\n model: string\n field: string\n locale?: string\n}\n\nexport interface NormalizePlanPatch {\n file: string\n line: number\n old_value: string\n new_expression: string\n import_statement?: string\n}\n\n// ─── Context ───\n\nexport interface ContextJson {\n version: string\n lastOperation: {\n tool: string\n model: string\n locale: string\n entries?: string[]\n timestamp: string\n source: ContextSource\n }\n stats: {\n models: number\n entries: number\n locales: string[]\n lastSync: string\n }\n}\n\n// ─── Git Transaction Types ───\n\n/** Standard name for the dedicated content branch */\nexport const CONTENTRAIN_BRANCH = 'contentrain' as const\n\n/** Result of selective file sync to developer's working tree */\nexport interface SyncResult {\n /** Files successfully synced to working tree */\n synced: string[]\n /** Files skipped due to uncommitted local changes */\n skipped: string[]\n /** Human-readable warning if files were skipped */\n warning?: string\n}\n\n/** Structured error for git operations with actionable guidance */\nexport interface ContentrainError {\n /** Machine-readable error code */\n code: string\n /** Human-readable error message */\n message: string\n /** Guidance for AI agents on how to handle this error */\n agent_hint: string\n /** Command or action the developer should take */\n developer_action: string\n}\n\n// ─── Validate: Pure Functions ───\n\n/** Common patterns for detecting potential secrets in content values */\nexport const SECRET_PATTERNS: ReadonlyArray<RegExp> = [\n /sk_/, /pk_/, /api_key/i, /apikey/i,\n /ghp_/, /gho_/, /Bearer /,\n /postgres:\\/\\//, /mysql:\\/\\//, /mongodb:\\/\\//,\n /-----BEGIN/, /AKIA/, /aws_secret/i,\n]\n\n/** Validate a slug — returns error message or null if valid */\nexport function validateSlug(slug: string): string | null {\n if (!slug) return 'Slug is required'\n if (!SLUG_PATTERN.test(slug)) return `Invalid slug \"${slug}\": must be kebab-case alphanumeric (a-z, 0-9, hyphens)`\n if (slug.startsWith('.') || slug.includes('..')) return `Invalid slug \"${slug}\": path traversal not allowed`\n return null\n}\n\n/** Validate an entry ID — returns error message or null if valid */\nexport function validateEntryId(id: string): string | null {\n if (!ENTRY_ID_PATTERN.test(id)) return `Invalid entry ID \"${id}\": must be 1-40 alphanumeric characters (hyphens and underscores allowed)`\n return null\n}\n\n/** Validate a locale code against pattern and config — returns error message or null if valid */\nexport function validateLocale(locale: string, config: ContentrainConfig): string | null {\n if (!LOCALE_PATTERN.test(locale)) return `Invalid locale \"${locale}\": must be ISO 639-1 format (e.g. \"en\", \"tr\", \"pt-BR\")`\n if (!config.locales.supported.includes(locale)) {\n return `Locale \"${locale}\" is not in supported locales [${config.locales.supported.join(', ')}]. Update config first.`\n }\n return null\n}\n\n/** Detect potential secrets in a value — returns validation errors if found */\nexport function detectSecrets(value: unknown): ValidationError[] {\n if (typeof value !== 'string') return []\n if (SECRET_PATTERNS.some(p => p.test(value))) {\n return [{ severity: 'error', message: 'Potential secret detected in value' }]\n }\n return []\n}\n\nfunction fieldTypeMatches(value: unknown, fieldDef: FieldDef): boolean {\n if (value === null || value === undefined) return true\n\n switch (fieldDef.type) {\n case 'string':\n case 'text':\n case 'email':\n case 'url':\n case 'slug':\n case 'color':\n case 'phone':\n case 'code':\n case 'icon':\n case 'markdown':\n case 'richtext':\n case 'date':\n case 'datetime':\n case 'image':\n case 'video':\n case 'file':\n case 'select':\n return typeof value === 'string'\n\n case 'number':\n case 'integer':\n case 'decimal':\n case 'percent':\n case 'rating':\n return typeof value === 'number'\n\n case 'boolean':\n return typeof value === 'boolean'\n\n case 'relation':\n return typeof value === 'string'\n\n case 'relations':\n case 'array':\n return Array.isArray(value)\n\n case 'object':\n return typeof value === 'object' && !Array.isArray(value)\n\n default:\n return true\n }\n}\n\nfunction checkMinMax(value: unknown, fieldDef: FieldDef): string | null {\n if (fieldDef.min !== undefined) {\n if (typeof value === 'number' && value < fieldDef.min) {\n return `Value ${value} is below minimum ${fieldDef.min}`\n }\n if (typeof value === 'string' && value.length < fieldDef.min) {\n return `String length ${value.length} is below minimum ${fieldDef.min}`\n }\n if (Array.isArray(value) && value.length < fieldDef.min) {\n return `Array length ${value.length} is below minimum ${fieldDef.min}`\n }\n }\n if (fieldDef.max !== undefined) {\n if (typeof value === 'number' && value > fieldDef.max) {\n return `Value ${value} is above maximum ${fieldDef.max}`\n }\n if (typeof value === 'string' && value.length > fieldDef.max) {\n return `String length ${value.length} is above maximum ${fieldDef.max}`\n }\n if (Array.isArray(value) && value.length > fieldDef.max) {\n return `Array length ${value.length} is above maximum ${fieldDef.max}`\n }\n }\n return null\n}\n\n/**\n * Validate a field value against its FieldDef schema.\n * Checks: required, type match, min/max, pattern, select options.\n * Does NOT check: secrets (use detectSecrets), uniqueness (stateful), relations (I/O).\n */\nexport function validateFieldValue(value: unknown, fieldDef: FieldDef): ValidationError[] {\n const issues: ValidationError[] = []\n\n if (fieldDef.required && (value === undefined || value === null || value === '')) {\n issues.push({ severity: 'error', message: 'Required field is missing or empty' })\n return issues\n }\n\n if (value === undefined || value === null) return issues\n\n if (!fieldTypeMatches(value, fieldDef)) {\n issues.push({ severity: 'error', message: `Type mismatch: expected ${fieldDef.type}, got ${typeof value}` })\n return issues\n }\n\n const minMaxErr = checkMinMax(value, fieldDef)\n if (minMaxErr) {\n issues.push({ severity: 'error', message: minMaxErr })\n }\n\n if (fieldDef.pattern && typeof value === 'string') {\n try {\n const regex = new RegExp(fieldDef.pattern)\n if (!regex.test(value)) {\n issues.push({ severity: 'error', message: `Value \"${value}\" does not match pattern /${fieldDef.pattern}/` })\n }\n } catch {\n issues.push({ severity: 'warning', message: `Invalid pattern regex: ${fieldDef.pattern}` })\n }\n }\n\n if (fieldDef.type === 'select' && fieldDef.options && typeof value === 'string') {\n if (!fieldDef.options.includes(value)) {\n issues.push({ severity: 'error', message: `Value \"${value}\" is not in allowed options: [${fieldDef.options.join(', ')}]` })\n }\n }\n\n return issues\n}\n\n// ─── Serialize: Pure Functions ───\n\n/** Recursively sort object keys — respects optional fieldOrder for top-level keys */\nexport function sortKeys(obj: unknown, fieldOrder?: string[]): unknown {\n if (obj === null || obj === undefined) return undefined\n if (Array.isArray(obj)) return obj.map(item => sortKeys(item, fieldOrder))\n if (typeof obj !== 'object') return obj\n\n const record = obj as Record<string, unknown>\n const sorted: Record<string, unknown> = {}\n\n const keys = fieldOrder\n ? [...new Set([...fieldOrder, ...Object.keys(record).toSorted()])]\n : Object.keys(record).toSorted()\n\n for (const key of keys) {\n if (!(key in record)) continue\n const val = record[key]\n if (val === null || val === undefined) continue\n sorted[key] = sortKeys(val)\n }\n\n return sorted\n}\n\n/** Canonical JSON serialization — deterministic output for stable git diffs */\nexport function canonicalStringify(data: unknown, fieldOrder?: string[]): string {\n const sorted = sortKeys(data, fieldOrder)\n return `${JSON.stringify(sorted, null, 2)}\\n`\n}\n\n/** Generate a 12-character hex entry ID */\nexport function generateEntryId(): string {\n const hex = '0123456789abcdef'\n let id = ''\n for (let i = 0; i < 12; i++) {\n id += hex[Math.floor(Math.random() * 16)]\n }\n return id\n}\n\n// ─── Markdown Frontmatter ───\n\nfunction parseYamlValue(raw: string): unknown {\n if (raw === 'true') return true\n if (raw === 'false') return false\n if (raw === 'null') return null\n if (/^-?\\d+$/.test(raw)) return parseInt(raw, 10)\n if (/^-?\\d+\\.\\d+$/.test(raw)) return parseFloat(raw)\n if ((raw.startsWith('\"') && raw.endsWith('\"')) || (raw.startsWith(\"'\") && raw.endsWith(\"'\"))) {\n return raw.slice(1, -1)\n }\n return raw\n}\n\nfunction yamlScalar(value: unknown): string {\n const str = String(value)\n if (str.includes(':') || str.includes('#') || str.includes('{') || str.includes('}')\n || str.includes('[') || str.includes(']') || str.includes('*') || str.includes('&')\n || str.includes('!') || str.includes('|') || str.includes('>') || str.includes(\"'\")\n || str.includes('\"') || str.includes('%') || str.includes('@') || str.includes('`')\n || str.startsWith('-') || str.startsWith('?')\n || str === 'true' || str === 'false' || str === 'null' || str === 'yes' || str === 'no'\n || str === '') {\n return `\"${str.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`\n }\n return str\n}\n\nfunction serializeYamlValue(value: unknown, indent: number): string[] {\n const pad = ' '.repeat(indent)\n if (value === null || value === undefined) return []\n if (typeof value === 'object' && !Array.isArray(value)) {\n const lines: string[] = []\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n if (v === null || v === undefined) continue\n if (typeof v === 'object' && !Array.isArray(v)) {\n lines.push(`${pad}${k}:`)\n lines.push(...serializeYamlValue(v, indent + 1))\n } else if (Array.isArray(v)) {\n lines.push(`${pad}${k}:`)\n for (const item of v) {\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n const nested = serializeYamlValue(item, indent + 2)\n if (nested.length > 0) {\n lines.push(`${pad} - ${nested[0]!.trimStart()}`)\n lines.push(...nested.slice(1))\n }\n } else {\n lines.push(`${pad} - ${yamlScalar(item)}`)\n }\n }\n } else {\n lines.push(`${pad}${k}: ${yamlScalar(v)}`)\n }\n }\n return lines\n }\n if (Array.isArray(value)) {\n const lines: string[] = []\n for (const item of value) {\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n const nested = serializeYamlValue(item, indent + 1)\n if (nested.length > 0) {\n lines.push(`${pad}- ${nested[0]!.trimStart()}`)\n lines.push(...nested.slice(1))\n }\n } else {\n lines.push(`${pad}- ${yamlScalar(item)}`)\n }\n }\n return lines\n }\n return [`${pad}${yamlScalar(value)}`]\n}\n\nfunction serializeYamlFields(data: Record<string, unknown>): string[] {\n const lines: string[] = []\n for (const [key, value] of Object.entries(data)) {\n if (key === 'body') continue\n if (value === null || value === undefined) continue\n if (typeof value === 'object' && !Array.isArray(value)) {\n lines.push(`${key}:`)\n lines.push(...serializeYamlValue(value, 1))\n } else if (Array.isArray(value)) {\n lines.push(`${key}:`)\n for (const item of value) {\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n const nested = serializeYamlValue(item, 2)\n if (nested.length > 0) {\n lines.push(` - ${nested[0]!.trimStart()}`)\n lines.push(...nested.slice(1))\n }\n } else {\n lines.push(` - ${yamlScalar(item)}`)\n }\n }\n } else {\n lines.push(`${key}: ${yamlScalar(value)}`)\n }\n }\n return lines\n}\n\n/** Parse markdown frontmatter — extracts YAML frontmatter and body from a markdown string */\nexport function parseMarkdownFrontmatter(content: string): { frontmatter: Record<string, unknown>; body: string } {\n const normalized = content.replace(/\\r\\n/g, '\\n')\n const match = normalized.match(/^---\\n([\\s\\S]*?)\\n---\\n?([\\s\\S]*)$/)\n if (!match) return { frontmatter: {}, body: normalized }\n\n const frontmatterStr = match[1]!\n const body = match[2]!.trim()\n const frontmatter: Record<string, unknown> = {}\n\n let currentKey: string | null = null\n let currentArray: string[] | null = null\n\n for (const line of frontmatterStr.split('\\n')) {\n if (/^\\s+-\\s+/.test(line) && currentKey) {\n const value = line.replace(/^\\s+-\\s+/, '').trim()\n if (!currentArray) currentArray = []\n currentArray.push(value)\n continue\n }\n\n if (currentKey && currentArray) {\n frontmatter[currentKey] = currentArray\n currentKey = null\n currentArray = null\n }\n\n const kvMatch = line.match(/^([\\w][\\w.-]*)\\s*:\\s*(.*)$/)\n if (!kvMatch) continue\n\n const key = kvMatch[1]!\n const rawValue = kvMatch[2]!.trim()\n\n if (rawValue === '') {\n currentKey = key\n currentArray = []\n continue\n }\n\n if (rawValue.startsWith('[') && rawValue.endsWith(']')) {\n const items = rawValue.slice(1, -1).split(',').map(s => s.trim()).filter(Boolean)\n frontmatter[key] = items\n continue\n }\n\n frontmatter[key] = parseYamlValue(rawValue)\n }\n\n if (currentKey && currentArray) {\n frontmatter[currentKey] = currentArray\n }\n\n return { frontmatter, body }\n}\n\n/** Serialize data + body into markdown frontmatter format */\nexport function serializeMarkdownFrontmatter(data: Record<string, unknown>, body: string): string {\n const trimmedBody = body.trimStart()\n if (trimmedBody.startsWith('---')) {\n const endIdx = trimmedBody.indexOf('---', 3)\n if (endIdx > 0) {\n const bodyFmContent = trimmedBody.slice(3, endIdx).trim()\n const afterFm = trimmedBody.slice(endIdx + 3)\n\n const lines: string[] = ['---']\n lines.push(...serializeYamlFields(data))\n if (bodyFmContent) {\n const modelKeys = new Set(Object.keys(data))\n for (const line of bodyFmContent.split('\\n')) {\n if (line.length > 0 && line[0] !== ' ' && line[0] !== '-') {\n const colonIdx = line.indexOf(':')\n const lineKey = colonIdx > 0 ? line.slice(0, colonIdx).trim() : ''\n if (lineKey && modelKeys.has(lineKey)) continue\n }\n lines.push(line)\n }\n }\n lines.push('---')\n if (afterFm.trim()) {\n lines.push(afterFm.trimStart())\n }\n lines.push('')\n return lines.join('\\n')\n }\n }\n\n const lines: string[] = ['---']\n lines.push(...serializeYamlFields(data))\n lines.push('---')\n lines.push('')\n if (body) {\n lines.push(body)\n lines.push('')\n }\n return lines.join('\\n')\n}\n\n// ─── Repository provider contracts ───\n//\n// Provider-agnostic engine contracts used by @contentrain/mcp. Exposed from\n// @contentrain/types so third-party tools can implement a custom\n// RepoProvider without taking a dependency on @contentrain/mcp.\nexport type {\n ApplyPlanInput,\n Branch,\n Commit,\n CommitAuthor,\n FileChange,\n FileDiff,\n MergeResult,\n ProviderCapabilities,\n RepoProvider,\n RepoReader,\n RepoWriter,\n} from './provider.js'\nexport { LOCAL_CAPABILITIES } from './provider.js'\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentrain/types",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "license": "MIT",
5
5
  "description": "Shared TypeScript types for Contentrain ecosystem",
6
6
  "type": "module",