@contentrain/types 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -125,8 +125,12 @@ type FileFramework = 'vue' | 'svelte' | 'jsx' | 'astro' | 'script';
125
125
  /** Root directory name for all Contentrain data */
126
126
  declare const CONTENTRAIN_DIR: ".contentrain";
127
127
  /**
128
- * Standard path patterns for Contentrain projects.
128
+ * Default path patterns for Contentrain projects.
129
129
  * Variables: {domain}, {modelId}, {locale}, {slug}
130
+ *
131
+ * When a model has `content_path` set, content files are written to
132
+ * `{projectRoot}/{content_path}/` instead — but meta files always
133
+ * remain under `.contentrain/meta/`.
130
134
  */
131
135
  declare const PATH_PATTERNS: {
132
136
  readonly config: ".contentrain/config.json";
@@ -248,6 +252,28 @@ interface ContextJson {
248
252
  lastSync: string;
249
253
  };
250
254
  }
255
+ /** Standard name for the dedicated content branch */
256
+ declare const CONTENTRAIN_BRANCH: "contentrain";
257
+ /** Result of selective file sync to developer's working tree */
258
+ interface SyncResult {
259
+ /** Files successfully synced to working tree */
260
+ synced: string[];
261
+ /** Files skipped due to uncommitted local changes */
262
+ skipped: string[];
263
+ /** Human-readable warning if files were skipped */
264
+ warning?: string;
265
+ }
266
+ /** Structured error for git operations with actionable guidance */
267
+ interface ContentrainError {
268
+ /** Machine-readable error code */
269
+ code: string;
270
+ /** Human-readable error message */
271
+ message: string;
272
+ /** Guidance for AI agents on how to handle this error */
273
+ agent_hint: string;
274
+ /** Command or action the developer should take */
275
+ developer_action: string;
276
+ }
251
277
  //#endregion
252
- export { AssetEntry, CANONICAL_JSON, CONTENTRAIN_DIR, CollectionContentFile, CollectionContentOutput, CollectionEntry, CollectionMeta, CollectionRuntimeFormat, ContentSource, ContentStatus, ContentrainConfig, ContextJson, ContextSource, DictionaryContentFile, DictionaryMeta, DocumentContentOutput, DocumentEntry, DocumentMeta, DuplicateGroup, ENTRY_ID_PATTERN, EntryMeta, FieldDef, FieldType, FileCategory, FileFramework, GraphNode, LOCALE_PATTERN, LocaleStrategy, ModelDefinition, ModelKind, ModelSummary, PATH_PATTERNS, Platform, PolymorphicRelationRef, ProjectGraph, SLUG_PATTERN, ScaffoldTemplate, ScanCandidate, ScanCandidatesResult, ScanSummaryResult, SingletonContentFile, SingletonMeta, StackType, StringContext, ValidationError, ValidationResult, Vocabulary, WorkflowMode };
278
+ export { AssetEntry, CANONICAL_JSON, CONTENTRAIN_BRANCH, CONTENTRAIN_DIR, CollectionContentFile, CollectionContentOutput, CollectionEntry, CollectionMeta, CollectionRuntimeFormat, ContentSource, ContentStatus, ContentrainConfig, ContentrainError, ContextJson, ContextSource, DictionaryContentFile, DictionaryMeta, DocumentContentOutput, DocumentEntry, DocumentMeta, DuplicateGroup, ENTRY_ID_PATTERN, EntryMeta, FieldDef, FieldType, FileCategory, FileFramework, GraphNode, LOCALE_PATTERN, LocaleStrategy, ModelDefinition, ModelKind, ModelSummary, PATH_PATTERNS, Platform, PolymorphicRelationRef, ProjectGraph, SLUG_PATTERN, ScaffoldTemplate, ScanCandidate, ScanCandidatesResult, ScanSummaryResult, SingletonContentFile, SingletonMeta, StackType, StringContext, SyncResult, ValidationError, ValidationResult, Vocabulary, WorkflowMode };
253
279
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -2,8 +2,12 @@
2
2
  /** Root directory name for all Contentrain data */
3
3
  const CONTENTRAIN_DIR = ".contentrain";
4
4
  /**
5
- * Standard path patterns for Contentrain projects.
5
+ * Default path patterns for Contentrain projects.
6
6
  * Variables: {domain}, {modelId}, {locale}, {slug}
7
+ *
8
+ * When a model has `content_path` set, content files are written to
9
+ * `{projectRoot}/{content_path}/` instead — but meta files always
10
+ * remain under `.contentrain/meta/`.
7
11
  */
8
12
  const PATH_PATTERNS = {
9
13
  config: ".contentrain/config.json",
@@ -39,7 +43,9 @@ const CANONICAL_JSON = {
39
43
  omitDefaults: true,
40
44
  sortKeys: true
41
45
  };
46
+ /** Standard name for the dedicated content branch */
47
+ const CONTENTRAIN_BRANCH = "contentrain";
42
48
  //#endregion
43
- export { CANONICAL_JSON, CONTENTRAIN_DIR, ENTRY_ID_PATTERN, LOCALE_PATTERN, PATH_PATTERNS, SLUG_PATTERN };
49
+ export { CANONICAL_JSON, CONTENTRAIN_BRANCH, CONTENTRAIN_DIR, ENTRY_ID_PATTERN, LOCALE_PATTERN, PATH_PATTERNS, SLUG_PATTERN };
44
50
 
45
51
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["// ─── 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 provider: 'github'\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 * Standard path patterns for Contentrain projects.\n * Variables: {domain}, {modelId}, {locale}, {slug}\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}\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 after_filtering: number\n candidates_returned: number\n has_more: boolean\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// ─── 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"],"mappings":";;AA+LA,MAAa,kBAAkB;;;;;AAM/B,MAAa,gBAAgB;CAC3B,QAAQ;CACR,SAAS;CACT,YAAY;CACZ,OAAO;CACP,SAAS;EACP,WAAW;EACX,YAAY;EACZ,UAAU;EACV,YAAY;EAEZ,UAAU;EACX;CACD,MAAM;EACJ,WAAW;EACX,YAAY;EACZ,UAAU;EACV,YAAY;EACb;CACF;;AAKD,MAAa,eAAe;;AAE5B,MAAa,mBAAmB;;AAEhC,MAAa,iBAAiB;;AAK9B,MAAa,iBAAiB;CAC5B,QAAQ;CACR,UAAU;CACV,iBAAiB;CACjB,UAAU;CACV,cAAc;CACd,UAAU;CACX"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["// ─── 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 provider: 'github'\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}\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 after_filtering: number\n candidates_returned: number\n has_more: boolean\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// ─── 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"],"mappings":";;AA+LA,MAAa,kBAAkB;;;;;;;;;AAU/B,MAAa,gBAAgB;CAC3B,QAAQ;CACR,SAAS;CACT,YAAY;CACZ,OAAO;CACP,SAAS;EACP,WAAW;EACX,YAAY;EACZ,UAAU;EACV,YAAY;EAEZ,UAAU;EACX;CACD,MAAM;EACJ,WAAW;EACX,YAAY;EACZ,UAAU;EACV,YAAY;EACb;CACF;;AAKD,MAAa,eAAe;;AAE5B,MAAa,mBAAmB;;AAEhC,MAAa,iBAAiB;;AAK9B,MAAa,iBAAiB;CAC5B,QAAQ;CACR,UAAU;CACV,iBAAiB;CACjB,UAAU;CACV,cAAc;CACd,UAAU;CACX;;AAsGD,MAAa,qBAAqB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentrain/types",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "license": "MIT",
5
5
  "description": "Shared TypeScript types for Contentrain ecosystem",
6
6
  "type": "module",