@contentrain/mcp 3.0.3 → 3.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.
Files changed (162) hide show
  1. package/README.md +6 -3
  2. package/dist/{annotations-C-tQVmot.mjs → annotations-CXHPnS-M.mjs} +8 -1
  3. package/dist/annotations-CXHPnS-M.mjs.map +1 -0
  4. package/dist/{apply-manager-BybvnUVC.mjs → apply-manager-DsNq7Zhm.mjs} +7 -7
  5. package/dist/{apply-manager-BybvnUVC.mjs.map → apply-manager-DsNq7Zhm.mjs.map} +1 -1
  6. package/dist/{astro-parser-Cb9uuBpW.mjs → astro-parser-dhFgc2wA.mjs} +3 -3
  7. package/dist/{astro-parser-Cb9uuBpW.mjs.map → astro-parser-dhFgc2wA.mjs.map} +1 -1
  8. package/dist/{availability-Dgcmvv99.mjs → availability-DYHNoP0_.mjs} +5 -1
  9. package/dist/availability-DYHNoP0_.mjs.map +1 -0
  10. package/dist/{branch-lifecycle-DhzHfzs3.d.mts → branch-lifecycle-DGlgjnC7.d.mts} +32 -2
  11. package/dist/branch-lifecycle-DGlgjnC7.d.mts.map +1 -0
  12. package/dist/{branch-lifecycle-B6PXZ2N7.mjs → branch-lifecycle-DUOoyNWn.mjs} +32 -4
  13. package/dist/branch-lifecycle-DUOoyNWn.mjs.map +1 -0
  14. package/dist/{compiler-B6hNQeCC.mjs → compiler-CR9F0wZZ.mjs} +2 -2
  15. package/dist/{compiler-B6hNQeCC.mjs.map → compiler-CR9F0wZZ.mjs.map} +1 -1
  16. package/dist/{compiler-sfc.cjs-8yY7b5bx.mjs → compiler-sfc.cjs-Cpexs92i.mjs} +2 -2
  17. package/dist/{compiler-sfc.cjs-8yY7b5bx.mjs.map → compiler-sfc.cjs-Cpexs92i.mjs.map} +1 -1
  18. package/dist/{config-VlRKRwAS.mjs → config-B8a4JBT1.mjs} +2 -2
  19. package/dist/{config-VlRKRwAS.mjs.map → config-B8a4JBT1.mjs.map} +1 -1
  20. package/dist/{content-manager-Dn4tqDw1.d.mts → content-manager-Bx94DXSF.d.mts} +2 -2
  21. package/dist/{content-manager-Dn4tqDw1.d.mts.map → content-manager-Bx94DXSF.d.mts.map} +1 -1
  22. package/dist/{context-C3x6I3cE.mjs → context-CxpTATh4.mjs} +7 -7
  23. package/dist/context-CxpTATh4.mjs.map +1 -0
  24. package/dist/core/apply-manager.mjs +10 -11
  25. package/dist/core/config.d.mts +1 -1
  26. package/dist/core/config.mjs +2 -2
  27. package/dist/core/content-manager.d.mts +1 -1
  28. package/dist/core/content-manager.mjs +3 -3
  29. package/dist/core/context.d.mts +1 -1
  30. package/dist/core/context.mjs +5 -6
  31. package/dist/core/contracts/index.d.mts +1 -1
  32. package/dist/core/doctor.mjs +8 -8
  33. package/dist/core/graph-builder.mjs +3 -3
  34. package/dist/core/meta-manager.mjs +2 -2
  35. package/dist/core/model-manager.d.mts +1 -1
  36. package/dist/core/model-manager.mjs +3 -3
  37. package/dist/core/ops/index.d.mts +17 -29
  38. package/dist/core/ops/index.d.mts.map +1 -1
  39. package/dist/core/ops/index.mjs +9 -6
  40. package/dist/core/overlay-reader.d.mts +1 -1
  41. package/dist/core/overlay-reader.mjs +1 -1
  42. package/dist/core/scan-config.mjs +2 -2
  43. package/dist/core/scanner.mjs +4 -4
  44. package/dist/core/validator/index.d.mts +1 -1
  45. package/dist/core/validator/index.mjs +5 -5
  46. package/dist/{detect-B0oXbQaP.mjs → detect-CI32ynpq.mjs} +2 -2
  47. package/dist/{detect-B0oXbQaP.mjs.map → detect-CI32ynpq.mjs.map} +1 -1
  48. package/dist/{doctor-DNPuGgcg.mjs → doctor-B7G0oFxO.mjs} +7 -7
  49. package/dist/{doctor-DNPuGgcg.mjs.map → doctor-B7G0oFxO.mjs.map} +1 -1
  50. package/dist/errors-BmLE-JSC.mjs +55 -0
  51. package/dist/errors-BmLE-JSC.mjs.map +1 -0
  52. package/dist/{errors-CvBS12e7.mjs → errors-DLkAWnzQ.mjs} +1 -1
  53. package/dist/{errors-CvBS12e7.mjs.map → errors-DLkAWnzQ.mjs.map} +1 -1
  54. package/dist/{fs-DLbVB-Ek.mjs → fs-DJv5G8uL.mjs} +1 -1
  55. package/dist/{fs-DLbVB-Ek.mjs.map → fs-DJv5G8uL.mjs.map} +1 -1
  56. package/dist/git/branch-lifecycle.d.mts +2 -2
  57. package/dist/git/branch-lifecycle.mjs +5 -5
  58. package/dist/git/errors.d.mts +30 -0
  59. package/dist/git/errors.d.mts.map +1 -0
  60. package/dist/git/errors.mjs +2 -0
  61. package/dist/git/identity.mjs +1 -1
  62. package/dist/git/reconcile.d.mts +49 -0
  63. package/dist/git/reconcile.d.mts.map +1 -0
  64. package/dist/git/reconcile.mjs +13 -0
  65. package/dist/git/transaction.d.mts +60 -15
  66. package/dist/git/transaction.d.mts.map +1 -1
  67. package/dist/git/transaction.mjs +10 -11
  68. package/dist/{graph-builder-BEocwW13.mjs → graph-builder-C9NS7y-a.mjs} +3 -3
  69. package/dist/{graph-builder-BEocwW13.mjs.map → graph-builder-C9NS7y-a.mjs.map} +1 -1
  70. package/dist/{id-BjhaIxTL.mjs → id-CjGMPP1k.mjs} +2 -2
  71. package/dist/{id-BjhaIxTL.mjs.map → id-CjGMPP1k.mjs.map} +1 -1
  72. package/dist/{identity-D8QoGxhT.mjs → identity-CxAB9Qb8.mjs} +1 -1
  73. package/dist/{identity-D8QoGxhT.mjs.map → identity-CxAB9Qb8.mjs.map} +1 -1
  74. package/dist/index-_HJVkDJa.d.mts +85 -0
  75. package/dist/index-_HJVkDJa.d.mts.map +1 -0
  76. package/dist/index.mjs +24 -22
  77. package/dist/index.mjs.map +1 -1
  78. package/dist/{local-Db5X9mjZ.mjs → local-bnn6yrG7.mjs} +83 -8
  79. package/dist/local-bnn6yrG7.mjs.map +1 -0
  80. package/dist/{meta-manager-B_Se183X.mjs → meta-manager-g3shoZES.mjs} +2 -2
  81. package/dist/{meta-manager-B_Se183X.mjs.map → meta-manager-g3shoZES.mjs.map} +1 -1
  82. package/dist/{model-manager-DgyKMjLN.mjs → model-manager-DqwL8ptm.mjs} +66 -5
  83. package/dist/model-manager-DqwL8ptm.mjs.map +1 -0
  84. package/dist/{node-DUGiIkv1.mjs → node-CpLm3qr6.mjs} +1 -1
  85. package/dist/{node-DUGiIkv1.mjs.map → node-CpLm3qr6.mjs.map} +1 -1
  86. package/dist/{ops-BzbThweu.mjs → ops-BfrdZ6GK.mjs} +24 -34
  87. package/dist/ops-BfrdZ6GK.mjs.map +1 -0
  88. package/dist/{overlay-reader-CkU_pGXZ.mjs → overlay-reader-Bx1YxGXq.mjs} +1 -1
  89. package/dist/{overlay-reader-CkU_pGXZ.mjs.map → overlay-reader-Bx1YxGXq.mjs.map} +1 -1
  90. package/dist/{paths-CdPPWpbG.mjs → paths-C6_C1gLp.mjs} +1 -1
  91. package/dist/{paths-CdPPWpbG.mjs.map → paths-C6_C1gLp.mjs.map} +1 -1
  92. package/dist/providers/github/index.d.mts +10 -1
  93. package/dist/providers/github/index.d.mts.map +1 -1
  94. package/dist/providers/github/index.mjs +104 -4
  95. package/dist/providers/github/index.mjs.map +1 -1
  96. package/dist/providers/gitlab/index.d.mts +8 -1
  97. package/dist/providers/gitlab/index.d.mts.map +1 -1
  98. package/dist/providers/gitlab/index.mjs +15 -2
  99. package/dist/providers/gitlab/index.mjs.map +1 -1
  100. package/dist/providers/local/index.d.mts +26 -2
  101. package/dist/providers/local/index.d.mts.map +1 -1
  102. package/dist/providers/local/index.mjs +13 -12
  103. package/dist/reconcile-D5FTVW5z.mjs +1704 -0
  104. package/dist/reconcile-D5FTVW5z.mjs.map +1 -0
  105. package/dist/reconcile-M7KBZtdn.mjs +249 -0
  106. package/dist/reconcile-M7KBZtdn.mjs.map +1 -0
  107. package/dist/{scan-config-Dx49nCqk.mjs → scan-config-C5zzygeH.mjs} +2 -2
  108. package/dist/{scan-config-Dx49nCqk.mjs.map → scan-config-C5zzygeH.mjs.map} +1 -1
  109. package/dist/{scanner-BSvXjfkp.mjs → scanner-CEiT8Tgx.mjs} +7 -7
  110. package/dist/{scanner-BSvXjfkp.mjs.map → scanner-CEiT8Tgx.mjs.map} +1 -1
  111. package/dist/server/http/index.d.mts +1 -1
  112. package/dist/server/http/index.mjs +24 -22
  113. package/dist/server/http/index.mjs.map +1 -1
  114. package/dist/{server-B7QA0Q1M.mjs → server-B6abaEU2.mjs} +343 -227
  115. package/dist/server-B6abaEU2.mjs.map +1 -0
  116. package/dist/{server-CLPNnhYL.d.mts → server-SDsD0XGM.d.mts} +2 -2
  117. package/dist/{server-CLPNnhYL.d.mts.map → server-SDsD0XGM.d.mts.map} +1 -1
  118. package/dist/server.d.mts +1 -1
  119. package/dist/server.mjs +24 -22
  120. package/dist/{source-map-generator-DhjiQdV3.mjs → source-map-generator-Clb2Eqse.mjs} +1 -1
  121. package/dist/{source-map-generator-DhjiQdV3.mjs.map → source-map-generator-Clb2Eqse.mjs.map} +1 -1
  122. package/dist/{svelte-parser-CwySu9yn.mjs → svelte-parser-CBN7Jxb7.mjs} +3 -3
  123. package/dist/{svelte-parser-CwySu9yn.mjs.map → svelte-parser-CBN7Jxb7.mjs.map} +1 -1
  124. package/dist/templates/index.mjs +1 -1
  125. package/dist/{templates-CAkTIRkE.mjs → templates-BZbohJc8.mjs} +1 -1
  126. package/dist/{templates-CAkTIRkE.mjs.map → templates-BZbohJc8.mjs.map} +1 -1
  127. package/dist/testing/memory-provider.d.mts +26 -1
  128. package/dist/testing/memory-provider.d.mts.map +1 -1
  129. package/dist/testing/memory-provider.mjs +62 -2
  130. package/dist/testing/memory-provider.mjs.map +1 -1
  131. package/dist/tools/annotations.d.mts.map +1 -1
  132. package/dist/tools/annotations.mjs +1 -1
  133. package/dist/tools/availability.d.mts.map +1 -1
  134. package/dist/tools/availability.mjs +1 -1
  135. package/dist/{transaction-BW9ektWu.mjs → transaction-BxDiiakv.mjs} +128 -64
  136. package/dist/transaction-BxDiiakv.mjs.map +1 -0
  137. package/dist/tsx-parser-DOQpJVgK.mjs +2 -0
  138. package/dist/{tsx-parser-BvsK6lyG.mjs → tsx-parser-go5V9zoc.mjs} +1 -1
  139. package/dist/{tsx-parser-BvsK6lyG.mjs.map → tsx-parser-go5V9zoc.mjs.map} +1 -1
  140. package/dist/util/detect.mjs +2 -2
  141. package/dist/util/fs.mjs +1 -1
  142. package/dist/util/id.mjs +1 -1
  143. package/dist/{validator-0sJ9vh1j.mjs → validator-B2GhPM3L.mjs} +5 -6
  144. package/dist/{validator-0sJ9vh1j.mjs.map → validator-B2GhPM3L.mjs.map} +1 -1
  145. package/dist/{vue-parser-auedZiJG.mjs → vue-parser-5Mp8w-mb.mjs} +3 -3
  146. package/dist/{vue-parser-auedZiJG.mjs.map → vue-parser-5Mp8w-mb.mjs.map} +1 -1
  147. package/package.json +13 -5
  148. package/dist/annotations-C-tQVmot.mjs.map +0 -1
  149. package/dist/availability-Dgcmvv99.mjs.map +0 -1
  150. package/dist/branch-lifecycle-B6PXZ2N7.mjs.map +0 -1
  151. package/dist/branch-lifecycle-DhzHfzs3.d.mts.map +0 -1
  152. package/dist/context-C3x6I3cE.mjs.map +0 -1
  153. package/dist/local-Db5X9mjZ.mjs.map +0 -1
  154. package/dist/model-manager-DgyKMjLN.mjs.map +0 -1
  155. package/dist/ops-BzbThweu.mjs.map +0 -1
  156. package/dist/paths-CmVw5Cw2.mjs +0 -65
  157. package/dist/paths-CmVw5Cw2.mjs.map +0 -1
  158. package/dist/serialization-tmgfFBOh.mjs +0 -2
  159. package/dist/server-B7QA0Q1M.mjs.map +0 -1
  160. package/dist/transaction-BW9ektWu.mjs.map +0 -1
  161. package/dist/tsx-parser-Byc7HlJ8.mjs +0 -2
  162. /package/dist/{index-BWbTJlXm.d.mts → index-ByrVsRJE.d.mts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"templates-CAkTIRkE.mjs","names":[],"sources":["../src/templates/blog.ts","../src/templates/landing.ts","../src/templates/docs.ts","../src/templates/ecommerce.ts","../src/templates/saas.ts","../src/templates/i18n.ts","../src/templates/mobile.ts","../src/templates/index.ts"],"sourcesContent":["import type { ScaffoldTemplate } from '@contentrain/types'\n\nexport const blogTemplate: ScaffoldTemplate = {\n id: 'blog',\n models: [\n {\n id: 'blog-post',\n name: 'Blog Post',\n kind: 'document',\n domain: 'blog',\n i18n: true,\n title_field: 'title',\n fields: {\n title: { type: 'string', required: true, max: 120, label: 'Title', order: 10 },\n slug: { type: 'slug', required: true, unique: true, label: 'Slug', order: 20 },\n excerpt: { type: 'text', max: 280, label: 'Excerpt', order: 30 },\n cover: { type: 'image', label: 'Cover', order: 40 },\n author: { type: 'relation', model: 'authors', required: true, label: 'Author', order: 50 },\n category: { type: 'relation', model: 'categories', label: 'Category', order: 60 },\n tags: { type: 'array', items: 'string', label: 'Tags', order: 70 },\n published_at: { type: 'datetime', label: 'Published at', order: 80 },\n },\n },\n {\n id: 'categories',\n name: 'Categories',\n kind: 'collection',\n domain: 'blog',\n i18n: true,\n title_field: 'name',\n fields: {\n name: { type: 'string', required: true, label: 'Name', order: 10 },\n slug: { type: 'slug', required: true, unique: true, label: 'Slug', order: 20 },\n description: { type: 'text', label: 'Description', order: 30 },\n },\n },\n {\n id: 'authors',\n name: 'Authors',\n kind: 'collection',\n domain: 'blog',\n i18n: false,\n title_field: 'name',\n fields: {\n name: { type: 'string', required: true, label: 'Name', order: 10 },\n email: { type: 'email', label: 'Email', order: 20 },\n bio: { type: 'text', label: 'Bio', order: 30 },\n avatar: { type: 'image', label: 'Avatar', order: 40 },\n social: {\n type: 'object',\n fields: {\n twitter: { type: 'url', label: 'Twitter', order: 10 },\n linkedin: { type: 'url', label: 'Linkedin', order: 20 },\n github: { type: 'url', label: 'Github', order: 30 },\n },\n },\n },\n },\n ],\n sample_content: {\n categories: {\n en: {\n 'cat-engineering': { name: 'Engineering', slug: 'engineering', description: 'Technical deep dives' },\n 'cat-product': { name: 'Product', slug: 'product', description: 'Product updates and news' },\n },\n },\n authors: {\n data: {\n 'author-1': { name: 'Team', email: 'team@example.com', bio: 'The team behind the product' },\n },\n },\n },\n vocabulary: {\n 'read-more': { en: 'Read More' },\n 'published-on': { en: 'Published on' },\n 'by-author': { en: 'By' },\n 'categories': { en: 'Categories' },\n 'tags': { en: 'Tags' },\n },\n}\n","import type { ScaffoldTemplate } from '@contentrain/types'\n\nexport const landingTemplate: ScaffoldTemplate = {\n id: 'landing',\n models: [\n {\n id: 'hero',\n name: 'Hero Section',\n kind: 'singleton',\n domain: 'marketing',\n i18n: true,\n title_field: 'title',\n fields: {\n title: { type: 'string', required: true, max: 120, label: 'Title', order: 10 },\n subtitle: { type: 'text', max: 280, label: 'Subtitle', order: 20 },\n cta_text: { type: 'string', label: 'CTA text', order: 30 },\n cta_url: { type: 'url', label: 'CTA URL', order: 40 },\n background: { type: 'image', label: 'Background', order: 50 },\n },\n },\n {\n id: 'features',\n name: 'Features Section',\n kind: 'singleton',\n domain: 'marketing',\n i18n: true,\n title_field: 'title',\n fields: {\n title: { type: 'string', required: true, label: 'Title', order: 10 },\n subtitle: { type: 'text', label: 'Subtitle', order: 20 },\n items: {\n type: 'array',\n items: {\n type: 'object',\n fields: {\n title: { type: 'string', required: true, label: 'Title', order: 10 },\n description: { type: 'text', label: 'Description', order: 20 },\n icon: { type: 'icon', label: 'Icon', order: 30 },\n },\n },\n },\n },\n },\n {\n id: 'pricing',\n name: 'Pricing Plans',\n kind: 'collection',\n domain: 'marketing',\n i18n: true,\n title_field: 'name',\n fields: {\n name: { type: 'string', required: true, label: 'Name', order: 10 },\n price: { type: 'number', required: true, label: 'Price', order: 20 },\n currency: { type: 'string', default: 'USD', label: 'Currency', order: 30 },\n period: { type: 'select', options: ['monthly', 'yearly'], label: 'Period', order: 40 },\n features: { type: 'array', items: 'string', label: 'Features', order: 50 },\n highlighted: { type: 'boolean', default: false, label: 'Highlighted', order: 60 },\n },\n },\n {\n id: 'faq',\n name: 'FAQ',\n kind: 'collection',\n domain: 'marketing',\n i18n: true,\n title_field: 'question',\n fields: {\n question: { type: 'string', required: true, label: 'Question', order: 10 },\n answer: { type: 'text', required: true, label: 'Answer', order: 20 },\n order: { type: 'integer', label: 'Order', order: 30 },\n },\n },\n {\n id: 'testimonials',\n name: 'Testimonials',\n kind: 'collection',\n domain: 'marketing',\n i18n: true,\n title_field: 'name',\n fields: {\n name: { type: 'string', required: true, label: 'Name', order: 10 },\n role: { type: 'string', label: 'Role', order: 20 },\n company: { type: 'string', label: 'Company', order: 30 },\n quote: { type: 'text', required: true, label: 'Quote', order: 40 },\n avatar: { type: 'image', label: 'Avatar', order: 50 },\n rating: { type: 'rating', label: 'Rating', order: 60 },\n },\n },\n ],\n sample_content: {\n hero: {\n en: {\n title: 'Build something amazing',\n subtitle: 'The fastest way to launch your product',\n cta_text: 'Get Started',\n cta_url: '/signup',\n },\n },\n pricing: {\n en: {\n 'plan-free': { name: 'Free', price: 0, currency: 'USD', period: 'monthly', features: ['1 project', 'Basic support'], highlighted: false },\n 'plan-pro': { name: 'Pro', price: 29, currency: 'USD', period: 'monthly', features: ['Unlimited projects', 'Priority support', 'Advanced analytics'], highlighted: true },\n },\n },\n },\n vocabulary: {\n 'get-started': { en: 'Get Started' },\n 'learn-more': { en: 'Learn More' },\n 'per-month': { en: '/month' },\n 'most-popular': { en: 'Most Popular' },\n },\n}\n","import type { ScaffoldTemplate } from '@contentrain/types'\n\nexport const docsTemplate: ScaffoldTemplate = {\n id: 'docs',\n models: [\n {\n id: 'doc-page',\n name: 'Documentation Page',\n kind: 'document',\n domain: 'docs',\n i18n: true,\n title_field: 'title',\n fields: {\n title: { type: 'string', required: true, max: 120, label: 'Title', order: 10 },\n slug: { type: 'slug', required: true, unique: true, label: 'Slug', order: 20 },\n category: { type: 'relation', model: 'doc-categories', label: 'Category', order: 30 },\n order: { type: 'integer', label: 'Order', order: 40 },\n excerpt: { type: 'text', max: 280, label: 'Excerpt', order: 50 },\n },\n },\n {\n id: 'doc-categories',\n name: 'Doc Categories',\n kind: 'collection',\n domain: 'docs',\n i18n: true,\n title_field: 'name',\n fields: {\n name: { type: 'string', required: true, label: 'Name', order: 10 },\n slug: { type: 'slug', required: true, unique: true, label: 'Slug', order: 20 },\n order: { type: 'integer', label: 'Order', order: 30 },\n },\n },\n ],\n sample_content: {\n 'doc-categories': {\n en: {\n 'cat-getting-started': { name: 'Getting Started', slug: 'getting-started', order: 1 },\n 'cat-guides': { name: 'Guides', slug: 'guides', order: 2 },\n 'cat-api': { name: 'API Reference', slug: 'api', order: 3 },\n },\n },\n },\n vocabulary: {\n 'on-this-page': { en: 'On This Page' },\n 'edit-this-page': { en: 'Edit this page' },\n 'next': { en: 'Next' },\n 'previous': { en: 'Previous' },\n },\n}\n","import type { ScaffoldTemplate } from '@contentrain/types'\n\nexport const ecommerceTemplate: ScaffoldTemplate = {\n id: 'ecommerce',\n models: [\n {\n id: 'products',\n name: 'Products',\n kind: 'collection',\n domain: 'shop',\n i18n: true,\n title_field: 'name',\n fields: {\n name: { type: 'string', required: true, label: 'Name', order: 10 },\n slug: { type: 'slug', required: true, unique: true, label: 'Slug', order: 20 },\n description: { type: 'text', label: 'Description', order: 30 },\n price: { type: 'decimal', required: true, label: 'Price', order: 40 },\n currency: { type: 'string', default: 'USD', label: 'Currency', order: 50 },\n image: { type: 'image', label: 'Image', order: 60 },\n category: { type: 'relation', model: 'product-categories', label: 'Category', order: 70 },\n brand: { type: 'relation', model: 'brands', label: 'Brand', order: 80 },\n in_stock: { type: 'boolean', default: true, label: 'In stock', order: 90 },\n },\n },\n {\n id: 'product-categories',\n name: 'Product Categories',\n kind: 'collection',\n domain: 'shop',\n i18n: true,\n title_field: 'name',\n fields: {\n name: { type: 'string', required: true, label: 'Name', order: 10 },\n slug: { type: 'slug', required: true, unique: true, label: 'Slug', order: 20 },\n description: { type: 'text', label: 'Description', order: 30 },\n image: { type: 'image', label: 'Image', order: 40 },\n },\n },\n {\n id: 'brands',\n name: 'Brands',\n kind: 'collection',\n domain: 'shop',\n i18n: false,\n title_field: 'name',\n fields: {\n name: { type: 'string', required: true, label: 'Name', order: 10 },\n slug: { type: 'slug', required: true, unique: true, label: 'Slug', order: 20 },\n logo: { type: 'image', label: 'Logo', order: 30 },\n website: { type: 'url', label: 'Website', order: 40 },\n },\n },\n ],\n sample_content: {\n 'product-categories': {\n en: {\n 'cat-electronics': { name: 'Electronics', slug: 'electronics', description: 'Electronic devices and accessories' },\n 'cat-clothing': { name: 'Clothing', slug: 'clothing', description: 'Apparel and fashion' },\n },\n },\n brands: {\n data: {\n 'brand-acme': { name: 'Acme Corp', slug: 'acme', website: 'https://example.com' },\n },\n },\n },\n vocabulary: {\n 'add-to-cart': { en: 'Add to Cart' },\n 'out-of-stock': { en: 'Out of Stock' },\n 'price': { en: 'Price' },\n 'category': { en: 'Category' },\n },\n}\n","import type { ScaffoldTemplate } from '@contentrain/types'\n\nexport const saasTemplate: ScaffoldTemplate = {\n id: 'saas',\n models: [\n {\n id: 'hero',\n name: 'Hero Section',\n kind: 'singleton',\n domain: 'marketing',\n i18n: true,\n title_field: 'title',\n fields: {\n title: { type: 'string', required: true, max: 120, label: 'Title', order: 10 },\n subtitle: { type: 'text', max: 280, label: 'Subtitle', order: 20 },\n cta_text: { type: 'string', label: 'CTA text', order: 30 },\n cta_url: { type: 'url', label: 'CTA URL', order: 40 },\n background: { type: 'image', label: 'Background', order: 50 },\n },\n },\n {\n id: 'features',\n name: 'Features',\n kind: 'singleton',\n domain: 'marketing',\n i18n: true,\n title_field: 'title',\n fields: {\n title: { type: 'string', required: true, label: 'Title', order: 10 },\n subtitle: { type: 'text', label: 'Subtitle', order: 20 },\n items: {\n type: 'array',\n items: {\n type: 'object',\n fields: {\n title: { type: 'string', required: true, label: 'Title', order: 10 },\n description: { type: 'text', label: 'Description', order: 20 },\n icon: { type: 'icon', label: 'Icon', order: 30 },\n },\n },\n },\n },\n },\n {\n id: 'pricing',\n name: 'Pricing Plans',\n kind: 'collection',\n domain: 'marketing',\n i18n: true,\n title_field: 'name',\n fields: {\n name: { type: 'string', required: true, label: 'Name', order: 10 },\n price: { type: 'number', required: true, label: 'Price', order: 20 },\n currency: { type: 'string', default: 'USD', label: 'Currency', order: 30 },\n period: { type: 'select', options: ['monthly', 'yearly'], label: 'Period', order: 40 },\n features: { type: 'array', items: 'string', label: 'Features', order: 50 },\n highlighted: { type: 'boolean', default: false, label: 'Highlighted', order: 60 },\n },\n },\n {\n id: 'changelog',\n name: 'Changelog',\n kind: 'document',\n domain: 'product',\n i18n: true,\n title_field: 'title',\n fields: {\n title: { type: 'string', required: true, label: 'Title', order: 10 },\n slug: { type: 'slug', required: true, unique: true, label: 'Slug', order: 20 },\n version: { type: 'string', label: 'Version', order: 30 },\n published_at: { type: 'date', label: 'Published at', order: 40 },\n tags: { type: 'array', items: 'string', label: 'Tags', order: 50 },\n },\n },\n {\n id: 'faq',\n name: 'FAQ',\n kind: 'collection',\n domain: 'marketing',\n i18n: true,\n title_field: 'question',\n fields: {\n question: { type: 'string', required: true, label: 'Question', order: 10 },\n answer: { type: 'text', required: true, label: 'Answer', order: 20 },\n order: { type: 'integer', label: 'Order', order: 30 },\n },\n },\n ],\n sample_content: {\n hero: {\n en: {\n title: 'Ship faster with our platform',\n subtitle: 'Everything you need to build, deploy, and scale',\n cta_text: 'Start Free Trial',\n cta_url: '/signup',\n },\n },\n pricing: {\n en: {\n 'plan-starter': { name: 'Starter', price: 0, currency: 'USD', period: 'monthly', features: ['Up to 3 projects', 'Community support'], highlighted: false },\n 'plan-team': { name: 'Team', price: 49, currency: 'USD', period: 'monthly', features: ['Unlimited projects', 'Priority support', 'Team collaboration'], highlighted: true },\n 'plan-enterprise': { name: 'Enterprise', price: 199, currency: 'USD', period: 'monthly', features: ['Everything in Team', 'SSO', 'SLA', 'Dedicated support'], highlighted: false },\n },\n },\n },\n vocabulary: {\n 'start-free': { en: 'Start Free Trial' },\n 'contact-sales': { en: 'Contact Sales' },\n 'per-month': { en: '/month' },\n 'changelog': { en: 'Changelog' },\n },\n}\n","import type { ScaffoldTemplate } from '@contentrain/types'\n\nexport const i18nTemplate: ScaffoldTemplate = {\n id: 'i18n',\n models: [\n {\n id: 'navigation',\n name: 'Navigation',\n kind: 'singleton',\n domain: 'ui',\n i18n: true,\n title_field: 'brand',\n fields: {\n brand: { type: 'string', required: true, label: 'Brand', order: 10 },\n items: {\n type: 'array',\n items: {\n type: 'object',\n fields: {\n label: { type: 'string', required: true, label: 'Label', order: 10 },\n url: { type: 'url', required: true, label: 'URL', order: 20 },\n },\n },\n },\n },\n },\n {\n id: 'form-labels',\n name: 'Form Labels',\n kind: 'singleton',\n domain: 'ui',\n i18n: true,\n title_field: 'name',\n fields: {\n name: { type: 'string', label: 'Name', order: 10 },\n email: { type: 'string', label: 'Email', order: 20 },\n password: { type: 'string', label: 'Password', order: 30 },\n submit: { type: 'string', label: 'Submit', order: 40 },\n cancel: { type: 'string', label: 'Cancel', order: 50 },\n },\n },\n {\n id: 'error-messages',\n name: 'Error Messages',\n kind: 'dictionary',\n domain: 'system',\n i18n: true,\n title_field: 'key',\n },\n {\n id: 'app-strings',\n name: 'App Strings',\n kind: 'dictionary',\n domain: 'system',\n i18n: true,\n title_field: 'key',\n },\n ],\n sample_content: {\n navigation: {\n en: {\n brand: 'My App',\n items: [\n { label: 'Home', url: '/' },\n { label: 'About', url: '/about' },\n { label: 'Contact', url: '/contact' },\n ],\n },\n },\n 'form-labels': {\n en: {\n name: 'Name',\n email: 'Email',\n password: 'Password',\n submit: 'Submit',\n cancel: 'Cancel',\n },\n },\n 'error-messages': {\n en: {\n 'required-field': 'This field is required',\n 'invalid-email': 'Please enter a valid email',\n 'server-error': 'Something went wrong, please try again',\n },\n },\n 'app-strings': {\n en: {\n 'welcome': 'Welcome',\n 'loading': 'Loading...',\n 'no-results': 'No results found',\n },\n },\n },\n vocabulary: {\n 'language': { en: 'Language' },\n 'switch-locale': { en: 'Switch language' },\n },\n}\n","import type { ScaffoldTemplate } from '@contentrain/types'\n\nexport const mobileTemplate: ScaffoldTemplate = {\n id: 'mobile',\n models: [\n {\n id: 'app-strings',\n name: 'App Strings',\n kind: 'dictionary',\n domain: 'system',\n i18n: true,\n title_field: 'key',\n },\n {\n id: 'error-messages',\n name: 'Error Messages',\n kind: 'dictionary',\n domain: 'system',\n i18n: true,\n title_field: 'key',\n },\n {\n id: 'onboarding',\n name: 'Onboarding Screens',\n kind: 'collection',\n domain: 'app',\n i18n: true,\n title_field: 'title',\n fields: {\n title: { type: 'string', required: true, label: 'Title', order: 10 },\n description: { type: 'text', label: 'Description', order: 20 },\n image: { type: 'image', label: 'Image', order: 30 },\n order: { type: 'integer', required: true, label: 'Order', order: 40 },\n },\n },\n ],\n sample_content: {\n 'app-strings': {\n en: {\n 'welcome': 'Welcome',\n 'loading': 'Loading...',\n 'retry': 'Retry',\n 'ok': 'OK',\n 'cancel': 'Cancel',\n },\n },\n 'error-messages': {\n en: {\n 'network-error': 'No internet connection',\n 'server-error': 'Something went wrong',\n 'auth-error': 'Please sign in again',\n },\n },\n onboarding: {\n en: {\n 'step-1': { title: 'Welcome', description: 'Get started with our app', order: 1 },\n 'step-2': { title: 'Discover', description: 'Explore all features', order: 2 },\n 'step-3': { title: 'Ready', description: 'You are all set!', order: 3 },\n },\n },\n },\n vocabulary: {\n 'get-started': { en: 'Get Started' },\n 'skip': { en: 'Skip' },\n 'next': { en: 'Next' },\n },\n}\n","import type { ScaffoldTemplate } from '@contentrain/types'\nimport { blogTemplate } from './blog.js'\nimport { landingTemplate } from './landing.js'\nimport { docsTemplate } from './docs.js'\nimport { ecommerceTemplate } from './ecommerce.js'\nimport { saasTemplate } from './saas.js'\nimport { i18nTemplate } from './i18n.js'\nimport { mobileTemplate } from './mobile.js'\n\nconst templates: Record<string, ScaffoldTemplate> = {\n blog: blogTemplate,\n landing: landingTemplate,\n docs: docsTemplate,\n ecommerce: ecommerceTemplate,\n saas: saasTemplate,\n i18n: i18nTemplate,\n mobile: mobileTemplate,\n}\n\nexport function getTemplate(id: string): ScaffoldTemplate | null {\n return templates[id] ?? null\n}\n\nexport function listTemplates(): string[] {\n return Object.keys(templates)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"templates-BZbohJc8.mjs","names":[],"sources":["../src/templates/blog.ts","../src/templates/landing.ts","../src/templates/docs.ts","../src/templates/ecommerce.ts","../src/templates/saas.ts","../src/templates/i18n.ts","../src/templates/mobile.ts","../src/templates/index.ts"],"sourcesContent":["import type { ScaffoldTemplate } from '@contentrain/types'\n\nexport const blogTemplate: ScaffoldTemplate = {\n id: 'blog',\n models: [\n {\n id: 'blog-post',\n name: 'Blog Post',\n kind: 'document',\n domain: 'blog',\n i18n: true,\n title_field: 'title',\n fields: {\n title: { type: 'string', required: true, max: 120, label: 'Title', order: 10 },\n slug: { type: 'slug', required: true, unique: true, label: 'Slug', order: 20 },\n excerpt: { type: 'text', max: 280, label: 'Excerpt', order: 30 },\n cover: { type: 'image', label: 'Cover', order: 40 },\n author: { type: 'relation', model: 'authors', required: true, label: 'Author', order: 50 },\n category: { type: 'relation', model: 'categories', label: 'Category', order: 60 },\n tags: { type: 'array', items: 'string', label: 'Tags', order: 70 },\n published_at: { type: 'datetime', label: 'Published at', order: 80 },\n },\n },\n {\n id: 'categories',\n name: 'Categories',\n kind: 'collection',\n domain: 'blog',\n i18n: true,\n title_field: 'name',\n fields: {\n name: { type: 'string', required: true, label: 'Name', order: 10 },\n slug: { type: 'slug', required: true, unique: true, label: 'Slug', order: 20 },\n description: { type: 'text', label: 'Description', order: 30 },\n },\n },\n {\n id: 'authors',\n name: 'Authors',\n kind: 'collection',\n domain: 'blog',\n i18n: false,\n title_field: 'name',\n fields: {\n name: { type: 'string', required: true, label: 'Name', order: 10 },\n email: { type: 'email', label: 'Email', order: 20 },\n bio: { type: 'text', label: 'Bio', order: 30 },\n avatar: { type: 'image', label: 'Avatar', order: 40 },\n social: {\n type: 'object',\n fields: {\n twitter: { type: 'url', label: 'Twitter', order: 10 },\n linkedin: { type: 'url', label: 'Linkedin', order: 20 },\n github: { type: 'url', label: 'Github', order: 30 },\n },\n },\n },\n },\n ],\n sample_content: {\n categories: {\n en: {\n 'cat-engineering': { name: 'Engineering', slug: 'engineering', description: 'Technical deep dives' },\n 'cat-product': { name: 'Product', slug: 'product', description: 'Product updates and news' },\n },\n },\n authors: {\n data: {\n 'author-1': { name: 'Team', email: 'team@example.com', bio: 'The team behind the product' },\n },\n },\n },\n vocabulary: {\n 'read-more': { en: 'Read More' },\n 'published-on': { en: 'Published on' },\n 'by-author': { en: 'By' },\n 'categories': { en: 'Categories' },\n 'tags': { en: 'Tags' },\n },\n}\n","import type { ScaffoldTemplate } from '@contentrain/types'\n\nexport const landingTemplate: ScaffoldTemplate = {\n id: 'landing',\n models: [\n {\n id: 'hero',\n name: 'Hero Section',\n kind: 'singleton',\n domain: 'marketing',\n i18n: true,\n title_field: 'title',\n fields: {\n title: { type: 'string', required: true, max: 120, label: 'Title', order: 10 },\n subtitle: { type: 'text', max: 280, label: 'Subtitle', order: 20 },\n cta_text: { type: 'string', label: 'CTA text', order: 30 },\n cta_url: { type: 'url', label: 'CTA URL', order: 40 },\n background: { type: 'image', label: 'Background', order: 50 },\n },\n },\n {\n id: 'features',\n name: 'Features Section',\n kind: 'singleton',\n domain: 'marketing',\n i18n: true,\n title_field: 'title',\n fields: {\n title: { type: 'string', required: true, label: 'Title', order: 10 },\n subtitle: { type: 'text', label: 'Subtitle', order: 20 },\n items: {\n type: 'array',\n items: {\n type: 'object',\n fields: {\n title: { type: 'string', required: true, label: 'Title', order: 10 },\n description: { type: 'text', label: 'Description', order: 20 },\n icon: { type: 'icon', label: 'Icon', order: 30 },\n },\n },\n },\n },\n },\n {\n id: 'pricing',\n name: 'Pricing Plans',\n kind: 'collection',\n domain: 'marketing',\n i18n: true,\n title_field: 'name',\n fields: {\n name: { type: 'string', required: true, label: 'Name', order: 10 },\n price: { type: 'number', required: true, label: 'Price', order: 20 },\n currency: { type: 'string', default: 'USD', label: 'Currency', order: 30 },\n period: { type: 'select', options: ['monthly', 'yearly'], label: 'Period', order: 40 },\n features: { type: 'array', items: 'string', label: 'Features', order: 50 },\n highlighted: { type: 'boolean', default: false, label: 'Highlighted', order: 60 },\n },\n },\n {\n id: 'faq',\n name: 'FAQ',\n kind: 'collection',\n domain: 'marketing',\n i18n: true,\n title_field: 'question',\n fields: {\n question: { type: 'string', required: true, label: 'Question', order: 10 },\n answer: { type: 'text', required: true, label: 'Answer', order: 20 },\n order: { type: 'integer', label: 'Order', order: 30 },\n },\n },\n {\n id: 'testimonials',\n name: 'Testimonials',\n kind: 'collection',\n domain: 'marketing',\n i18n: true,\n title_field: 'name',\n fields: {\n name: { type: 'string', required: true, label: 'Name', order: 10 },\n role: { type: 'string', label: 'Role', order: 20 },\n company: { type: 'string', label: 'Company', order: 30 },\n quote: { type: 'text', required: true, label: 'Quote', order: 40 },\n avatar: { type: 'image', label: 'Avatar', order: 50 },\n rating: { type: 'rating', label: 'Rating', order: 60 },\n },\n },\n ],\n sample_content: {\n hero: {\n en: {\n title: 'Build something amazing',\n subtitle: 'The fastest way to launch your product',\n cta_text: 'Get Started',\n cta_url: '/signup',\n },\n },\n pricing: {\n en: {\n 'plan-free': { name: 'Free', price: 0, currency: 'USD', period: 'monthly', features: ['1 project', 'Basic support'], highlighted: false },\n 'plan-pro': { name: 'Pro', price: 29, currency: 'USD', period: 'monthly', features: ['Unlimited projects', 'Priority support', 'Advanced analytics'], highlighted: true },\n },\n },\n },\n vocabulary: {\n 'get-started': { en: 'Get Started' },\n 'learn-more': { en: 'Learn More' },\n 'per-month': { en: '/month' },\n 'most-popular': { en: 'Most Popular' },\n },\n}\n","import type { ScaffoldTemplate } from '@contentrain/types'\n\nexport const docsTemplate: ScaffoldTemplate = {\n id: 'docs',\n models: [\n {\n id: 'doc-page',\n name: 'Documentation Page',\n kind: 'document',\n domain: 'docs',\n i18n: true,\n title_field: 'title',\n fields: {\n title: { type: 'string', required: true, max: 120, label: 'Title', order: 10 },\n slug: { type: 'slug', required: true, unique: true, label: 'Slug', order: 20 },\n category: { type: 'relation', model: 'doc-categories', label: 'Category', order: 30 },\n order: { type: 'integer', label: 'Order', order: 40 },\n excerpt: { type: 'text', max: 280, label: 'Excerpt', order: 50 },\n },\n },\n {\n id: 'doc-categories',\n name: 'Doc Categories',\n kind: 'collection',\n domain: 'docs',\n i18n: true,\n title_field: 'name',\n fields: {\n name: { type: 'string', required: true, label: 'Name', order: 10 },\n slug: { type: 'slug', required: true, unique: true, label: 'Slug', order: 20 },\n order: { type: 'integer', label: 'Order', order: 30 },\n },\n },\n ],\n sample_content: {\n 'doc-categories': {\n en: {\n 'cat-getting-started': { name: 'Getting Started', slug: 'getting-started', order: 1 },\n 'cat-guides': { name: 'Guides', slug: 'guides', order: 2 },\n 'cat-api': { name: 'API Reference', slug: 'api', order: 3 },\n },\n },\n },\n vocabulary: {\n 'on-this-page': { en: 'On This Page' },\n 'edit-this-page': { en: 'Edit this page' },\n 'next': { en: 'Next' },\n 'previous': { en: 'Previous' },\n },\n}\n","import type { ScaffoldTemplate } from '@contentrain/types'\n\nexport const ecommerceTemplate: ScaffoldTemplate = {\n id: 'ecommerce',\n models: [\n {\n id: 'products',\n name: 'Products',\n kind: 'collection',\n domain: 'shop',\n i18n: true,\n title_field: 'name',\n fields: {\n name: { type: 'string', required: true, label: 'Name', order: 10 },\n slug: { type: 'slug', required: true, unique: true, label: 'Slug', order: 20 },\n description: { type: 'text', label: 'Description', order: 30 },\n price: { type: 'decimal', required: true, label: 'Price', order: 40 },\n currency: { type: 'string', default: 'USD', label: 'Currency', order: 50 },\n image: { type: 'image', label: 'Image', order: 60 },\n category: { type: 'relation', model: 'product-categories', label: 'Category', order: 70 },\n brand: { type: 'relation', model: 'brands', label: 'Brand', order: 80 },\n in_stock: { type: 'boolean', default: true, label: 'In stock', order: 90 },\n },\n },\n {\n id: 'product-categories',\n name: 'Product Categories',\n kind: 'collection',\n domain: 'shop',\n i18n: true,\n title_field: 'name',\n fields: {\n name: { type: 'string', required: true, label: 'Name', order: 10 },\n slug: { type: 'slug', required: true, unique: true, label: 'Slug', order: 20 },\n description: { type: 'text', label: 'Description', order: 30 },\n image: { type: 'image', label: 'Image', order: 40 },\n },\n },\n {\n id: 'brands',\n name: 'Brands',\n kind: 'collection',\n domain: 'shop',\n i18n: false,\n title_field: 'name',\n fields: {\n name: { type: 'string', required: true, label: 'Name', order: 10 },\n slug: { type: 'slug', required: true, unique: true, label: 'Slug', order: 20 },\n logo: { type: 'image', label: 'Logo', order: 30 },\n website: { type: 'url', label: 'Website', order: 40 },\n },\n },\n ],\n sample_content: {\n 'product-categories': {\n en: {\n 'cat-electronics': { name: 'Electronics', slug: 'electronics', description: 'Electronic devices and accessories' },\n 'cat-clothing': { name: 'Clothing', slug: 'clothing', description: 'Apparel and fashion' },\n },\n },\n brands: {\n data: {\n 'brand-acme': { name: 'Acme Corp', slug: 'acme', website: 'https://example.com' },\n },\n },\n },\n vocabulary: {\n 'add-to-cart': { en: 'Add to Cart' },\n 'out-of-stock': { en: 'Out of Stock' },\n 'price': { en: 'Price' },\n 'category': { en: 'Category' },\n },\n}\n","import type { ScaffoldTemplate } from '@contentrain/types'\n\nexport const saasTemplate: ScaffoldTemplate = {\n id: 'saas',\n models: [\n {\n id: 'hero',\n name: 'Hero Section',\n kind: 'singleton',\n domain: 'marketing',\n i18n: true,\n title_field: 'title',\n fields: {\n title: { type: 'string', required: true, max: 120, label: 'Title', order: 10 },\n subtitle: { type: 'text', max: 280, label: 'Subtitle', order: 20 },\n cta_text: { type: 'string', label: 'CTA text', order: 30 },\n cta_url: { type: 'url', label: 'CTA URL', order: 40 },\n background: { type: 'image', label: 'Background', order: 50 },\n },\n },\n {\n id: 'features',\n name: 'Features',\n kind: 'singleton',\n domain: 'marketing',\n i18n: true,\n title_field: 'title',\n fields: {\n title: { type: 'string', required: true, label: 'Title', order: 10 },\n subtitle: { type: 'text', label: 'Subtitle', order: 20 },\n items: {\n type: 'array',\n items: {\n type: 'object',\n fields: {\n title: { type: 'string', required: true, label: 'Title', order: 10 },\n description: { type: 'text', label: 'Description', order: 20 },\n icon: { type: 'icon', label: 'Icon', order: 30 },\n },\n },\n },\n },\n },\n {\n id: 'pricing',\n name: 'Pricing Plans',\n kind: 'collection',\n domain: 'marketing',\n i18n: true,\n title_field: 'name',\n fields: {\n name: { type: 'string', required: true, label: 'Name', order: 10 },\n price: { type: 'number', required: true, label: 'Price', order: 20 },\n currency: { type: 'string', default: 'USD', label: 'Currency', order: 30 },\n period: { type: 'select', options: ['monthly', 'yearly'], label: 'Period', order: 40 },\n features: { type: 'array', items: 'string', label: 'Features', order: 50 },\n highlighted: { type: 'boolean', default: false, label: 'Highlighted', order: 60 },\n },\n },\n {\n id: 'changelog',\n name: 'Changelog',\n kind: 'document',\n domain: 'product',\n i18n: true,\n title_field: 'title',\n fields: {\n title: { type: 'string', required: true, label: 'Title', order: 10 },\n slug: { type: 'slug', required: true, unique: true, label: 'Slug', order: 20 },\n version: { type: 'string', label: 'Version', order: 30 },\n published_at: { type: 'date', label: 'Published at', order: 40 },\n tags: { type: 'array', items: 'string', label: 'Tags', order: 50 },\n },\n },\n {\n id: 'faq',\n name: 'FAQ',\n kind: 'collection',\n domain: 'marketing',\n i18n: true,\n title_field: 'question',\n fields: {\n question: { type: 'string', required: true, label: 'Question', order: 10 },\n answer: { type: 'text', required: true, label: 'Answer', order: 20 },\n order: { type: 'integer', label: 'Order', order: 30 },\n },\n },\n ],\n sample_content: {\n hero: {\n en: {\n title: 'Ship faster with our platform',\n subtitle: 'Everything you need to build, deploy, and scale',\n cta_text: 'Start Free Trial',\n cta_url: '/signup',\n },\n },\n pricing: {\n en: {\n 'plan-starter': { name: 'Starter', price: 0, currency: 'USD', period: 'monthly', features: ['Up to 3 projects', 'Community support'], highlighted: false },\n 'plan-team': { name: 'Team', price: 49, currency: 'USD', period: 'monthly', features: ['Unlimited projects', 'Priority support', 'Team collaboration'], highlighted: true },\n 'plan-enterprise': { name: 'Enterprise', price: 199, currency: 'USD', period: 'monthly', features: ['Everything in Team', 'SSO', 'SLA', 'Dedicated support'], highlighted: false },\n },\n },\n },\n vocabulary: {\n 'start-free': { en: 'Start Free Trial' },\n 'contact-sales': { en: 'Contact Sales' },\n 'per-month': { en: '/month' },\n 'changelog': { en: 'Changelog' },\n },\n}\n","import type { ScaffoldTemplate } from '@contentrain/types'\n\nexport const i18nTemplate: ScaffoldTemplate = {\n id: 'i18n',\n models: [\n {\n id: 'navigation',\n name: 'Navigation',\n kind: 'singleton',\n domain: 'ui',\n i18n: true,\n title_field: 'brand',\n fields: {\n brand: { type: 'string', required: true, label: 'Brand', order: 10 },\n items: {\n type: 'array',\n items: {\n type: 'object',\n fields: {\n label: { type: 'string', required: true, label: 'Label', order: 10 },\n url: { type: 'url', required: true, label: 'URL', order: 20 },\n },\n },\n },\n },\n },\n {\n id: 'form-labels',\n name: 'Form Labels',\n kind: 'singleton',\n domain: 'ui',\n i18n: true,\n title_field: 'name',\n fields: {\n name: { type: 'string', label: 'Name', order: 10 },\n email: { type: 'string', label: 'Email', order: 20 },\n password: { type: 'string', label: 'Password', order: 30 },\n submit: { type: 'string', label: 'Submit', order: 40 },\n cancel: { type: 'string', label: 'Cancel', order: 50 },\n },\n },\n {\n id: 'error-messages',\n name: 'Error Messages',\n kind: 'dictionary',\n domain: 'system',\n i18n: true,\n title_field: 'key',\n },\n {\n id: 'app-strings',\n name: 'App Strings',\n kind: 'dictionary',\n domain: 'system',\n i18n: true,\n title_field: 'key',\n },\n ],\n sample_content: {\n navigation: {\n en: {\n brand: 'My App',\n items: [\n { label: 'Home', url: '/' },\n { label: 'About', url: '/about' },\n { label: 'Contact', url: '/contact' },\n ],\n },\n },\n 'form-labels': {\n en: {\n name: 'Name',\n email: 'Email',\n password: 'Password',\n submit: 'Submit',\n cancel: 'Cancel',\n },\n },\n 'error-messages': {\n en: {\n 'required-field': 'This field is required',\n 'invalid-email': 'Please enter a valid email',\n 'server-error': 'Something went wrong, please try again',\n },\n },\n 'app-strings': {\n en: {\n 'welcome': 'Welcome',\n 'loading': 'Loading...',\n 'no-results': 'No results found',\n },\n },\n },\n vocabulary: {\n 'language': { en: 'Language' },\n 'switch-locale': { en: 'Switch language' },\n },\n}\n","import type { ScaffoldTemplate } from '@contentrain/types'\n\nexport const mobileTemplate: ScaffoldTemplate = {\n id: 'mobile',\n models: [\n {\n id: 'app-strings',\n name: 'App Strings',\n kind: 'dictionary',\n domain: 'system',\n i18n: true,\n title_field: 'key',\n },\n {\n id: 'error-messages',\n name: 'Error Messages',\n kind: 'dictionary',\n domain: 'system',\n i18n: true,\n title_field: 'key',\n },\n {\n id: 'onboarding',\n name: 'Onboarding Screens',\n kind: 'collection',\n domain: 'app',\n i18n: true,\n title_field: 'title',\n fields: {\n title: { type: 'string', required: true, label: 'Title', order: 10 },\n description: { type: 'text', label: 'Description', order: 20 },\n image: { type: 'image', label: 'Image', order: 30 },\n order: { type: 'integer', required: true, label: 'Order', order: 40 },\n },\n },\n ],\n sample_content: {\n 'app-strings': {\n en: {\n 'welcome': 'Welcome',\n 'loading': 'Loading...',\n 'retry': 'Retry',\n 'ok': 'OK',\n 'cancel': 'Cancel',\n },\n },\n 'error-messages': {\n en: {\n 'network-error': 'No internet connection',\n 'server-error': 'Something went wrong',\n 'auth-error': 'Please sign in again',\n },\n },\n onboarding: {\n en: {\n 'step-1': { title: 'Welcome', description: 'Get started with our app', order: 1 },\n 'step-2': { title: 'Discover', description: 'Explore all features', order: 2 },\n 'step-3': { title: 'Ready', description: 'You are all set!', order: 3 },\n },\n },\n },\n vocabulary: {\n 'get-started': { en: 'Get Started' },\n 'skip': { en: 'Skip' },\n 'next': { en: 'Next' },\n },\n}\n","import type { ScaffoldTemplate } from '@contentrain/types'\nimport { blogTemplate } from './blog.js'\nimport { landingTemplate } from './landing.js'\nimport { docsTemplate } from './docs.js'\nimport { ecommerceTemplate } from './ecommerce.js'\nimport { saasTemplate } from './saas.js'\nimport { i18nTemplate } from './i18n.js'\nimport { mobileTemplate } from './mobile.js'\n\nconst templates: Record<string, ScaffoldTemplate> = {\n blog: blogTemplate,\n landing: landingTemplate,\n docs: docsTemplate,\n ecommerce: ecommerceTemplate,\n saas: saasTemplate,\n i18n: i18nTemplate,\n mobile: mobileTemplate,\n}\n\nexport function getTemplate(id: string): ScaffoldTemplate | null {\n return templates[id] ?? null\n}\n\nexport function listTemplates(): string[] {\n return Object.keys(templates)\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { a as FileChange, g as RepoProvider, h as ProviderCapabilities, m as MergeResult, n as Branch, o as FileDiff, r as Commit, t as ApplyPlanInput, y as WriteReadiness } from "../index-BWbTJlXm.mjs";
1
+ import { a as FileChange, g as RepoProvider, h as ProviderCapabilities, i as CommitAuthor, m as MergeResult, n as Branch, o as FileDiff, r as Commit, t as ApplyPlanInput, y as WriteReadiness } from "../index-ByrVsRJE.mjs";
2
2
 
3
3
  //#region src/testing/memory-provider.d.ts
4
4
  interface MemoryProviderOptions {
@@ -13,12 +13,21 @@ interface MemoryProviderOptions {
13
13
  interface RecordedCommit extends Commit {
14
14
  branch: string;
15
15
  changes: FileChange[];
16
+ /** Present only on merge commits written by `createMergeCommit`: [ours, theirs]. */
17
+ parents?: [string, string];
16
18
  }
17
19
  declare class MemoryProvider implements RepoProvider {
18
20
  readonly capabilities: ProviderCapabilities;
19
21
  /** Every commit in order, with its changes — the assertion surface. */
20
22
  readonly commits: RecordedCommit[];
21
23
  private readonly refs;
24
+ /**
25
+ * Snapshot of the source tree at the moment each branch forked — what a
26
+ * commit DAG would encode as the fork commit. This is exactly the
27
+ * information `getMergeBase` needs, recorded eagerly because trees carry
28
+ * no parent pointers here.
29
+ */
30
+ private readonly forkPoints;
22
31
  private writeReadiness;
23
32
  private sequence;
24
33
  constructor(options?: MemoryProviderOptions);
@@ -44,6 +53,22 @@ declare class MemoryProvider implements RepoProvider {
44
53
  }): Promise<MergeResult>;
45
54
  isMerged(branch: string, into?: string): Promise<boolean>;
46
55
  getDefaultBranch(): Promise<string>;
56
+ /**
57
+ * The fork snapshot as a readable ref. When `b` forked from `a` (or the
58
+ * reverse), the recorded fork tree IS the merge base; it is registered
59
+ * under a synthetic `membase/<branch>` ref so the three-way readers can
60
+ * bind to it like any other ref. Unrelated refs → null, like git.
61
+ */
62
+ getMergeBase(refA: string, refB: string): Promise<string | null>;
63
+ createMergeCommit(input: {
64
+ branch: string;
65
+ ours: string;
66
+ theirs: string;
67
+ changes: FileChange[];
68
+ message: string;
69
+ author: CommitAuthor;
70
+ }): Promise<Commit>;
71
+ private registerBase;
47
72
  private tree;
48
73
  private readWorkflow;
49
74
  }
@@ -1 +1 @@
1
- {"version":3,"file":"memory-provider.d.mts","names":[],"sources":["../../src/testing/memory-provider.ts"],"mappings":";;;UAuDiB,qBAAA;;EAEf,KAAA,GAAQ,MAAA;EAF4B;EAIpC,YAAA,GAAe,OAAA,CAAQ,oBAAA;EAFf;EAIR,cAAA,GAAiB,cAAA;AAAA;;UAIF,cAAA,SAAuB,MAAA;EACtC,MAAA;EACA,OAAA,EAAS,UAAA;AAAA;AAAA,cAKE,cAAA,YAA0B,YAAA;EAAA,SAC5B,YAAA,EAAc,oBAAA;EAdA;EAAA,SAiBd,OAAA,EAAS,cAAA;EAAA,iBAED,IAAA;EAAA,QACT,cAAA;EAAA,QACA,QAAA;cAEI,OAAA,GAAS,qBAAA;EAjBS;EA0B9B,QAAA,CAAS,GAAA,YAAmC,MAAA;EA1BA;EAiC5C,KAAA,CAAM,GAAA;EAhCN;EAqCA,IAAA,CAAK,IAAA,UAAc,OAAA,UAAiB,GAAA;EApC3B;EAyCT,iBAAA,CAAkB,SAAA,EAAW,cAAA;EAM7B,QAAA,CAAS,IAAA,UAAc,GAAA,YAAe,OAAA;EAQtC,aAAA,CAAc,IAAA,UAAc,GAAA,YAAe,OAAA;EAa3C,UAAA,CAAW,IAAA,UAAc,GAAA,YAAe,OAAA;EAcxC,mBAAA,CAAA,GAAuB,OAAA,CAAQ,cAAA;EAIzB,SAAA,CAAU,KAAA,EAAO,cAAA,GAAiB,OAAA,CAAQ,MAAA;EAkChD,YAAA,CAAa,MAAA,YAAkB,OAAA,CAAQ,MAAA;EAQvC,YAAA,CAAa,IAAA,UAAc,OAAA,YAAmB,OAAA;EAK9C,YAAA,CAAa,IAAA,WAAe,OAAA;EAK5B,aAAA,CAAc,MAAA,UAAgB,IAAA,YAAgB,OAAA,CAAQ,QAAA;EAetD,WAAA,CAAY,MAAA,UAAgB,IAAA,UAAc,IAAA;IAAS,kBAAA;EAAA,IAAiC,OAAA,CAAQ,WAAA;EAY5F,QAAA,CAAS,MAAA,UAAgB,IAAA,YAAgB,OAAA;EAUzC,gBAAA,CAAA,GAAoB,OAAA;EAAA,QAMZ,IAAA;EAAA,QASM,YAAA;AAAA"}
1
+ {"version":3,"file":"memory-provider.d.mts","names":[],"sources":["../../src/testing/memory-provider.ts"],"mappings":";;;UAyDiB,qBAAA;;EAEf,KAAA,GAAQ,MAAA;EAF4B;EAIpC,YAAA,GAAe,OAAA,CAAQ,oBAAA;EAFf;EAIR,cAAA,GAAiB,cAAA;AAAA;;UAIF,cAAA,SAAuB,MAAA;EACtC,MAAA;EACA,OAAA,EAAS,UAAA;EAVD;EAYR,OAAA;AAAA;AAAA,cAKW,cAAA,YAA0B,YAAA;EAAA,SAC5B,YAAA,EAAc,oBAAA;EAdN;EAAA,SAiBR,OAAA,EAAS,cAAA;EAAA,iBAED,IAAA;EAfF;;;;;;EAAA,iBAsBE,UAAA;EAAA,QACT,cAAA;EAAA,QACA,QAAA;cAEI,OAAA,GAAS,qBAAA;EAtBd;EA+BP,QAAA,CAAS,GAAA,YAAmC,MAAA;EA1BlB;EAiC1B,KAAA,CAAM,GAAA;EAhCiB;EAqCvB,IAAA,CAAK,IAAA,UAAc,OAAA,UAAiB,GAAA;EArBf;EA0BrB,iBAAA,CAAkB,SAAA,EAAW,cAAA;EAM7B,QAAA,CAAS,IAAA,UAAc,GAAA,YAAe,OAAA;EAQtC,aAAA,CAAc,IAAA,UAAc,GAAA,YAAe,OAAA;EAa3C,UAAA,CAAW,IAAA,UAAc,GAAA,YAAe,OAAA;EAcxC,mBAAA,CAAA,GAAuB,OAAA,CAAQ,cAAA;EAIzB,SAAA,CAAU,KAAA,EAAO,cAAA,GAAiB,OAAA,CAAQ,MAAA;EAqChD,YAAA,CAAa,MAAA,YAAkB,OAAA,CAAQ,MAAA;EAQvC,YAAA,CAAa,IAAA,UAAc,OAAA,YAAmB,OAAA;EAO9C,YAAA,CAAa,IAAA,WAAe,OAAA;EAM5B,aAAA,CAAc,MAAA,UAAgB,IAAA,YAAgB,OAAA,CAAQ,QAAA;EAetD,WAAA,CAAY,MAAA,UAAgB,IAAA,UAAc,IAAA;IAAS,kBAAA;EAAA,IAAiC,OAAA,CAAQ,WAAA;EAY5F,QAAA,CAAS,MAAA,UAAgB,IAAA,YAAgB,OAAA;EAUzC,gBAAA,CAAA,GAAoB,OAAA;EArC0B;;;;;;EAiD9C,YAAA,CAAa,IAAA,UAAc,IAAA,WAAe,OAAA;EAc1C,iBAAA,CAAkB,KAAA;IAChB,MAAA;IACA,IAAA;IACA,MAAA;IACA,OAAA,EAAS,UAAA;IACT,OAAA;IACA,MAAA,EAAQ,YAAA;EAAA,IACN,OAAA,CAAQ,MAAA;EAAA,QAyBJ,YAAA;EAAA,QAMA,IAAA;EAAA,QASM,YAAA;AAAA"}
@@ -35,13 +35,21 @@ const MEMORY_CAPABILITIES = {
35
35
  pushRemote: false,
36
36
  branchProtection: false,
37
37
  pullRequestFallback: false,
38
- astScan: false
38
+ astScan: false,
39
+ mergeCommit: true
39
40
  };
40
41
  var MemoryProvider = class {
41
42
  capabilities;
42
43
  /** Every commit in order, with its changes — the assertion surface. */
43
44
  commits = [];
44
45
  refs = /* @__PURE__ */ new Map();
46
+ /**
47
+ * Snapshot of the source tree at the moment each branch forked — what a
48
+ * commit DAG would encode as the fork commit. This is exactly the
49
+ * information `getMergeBase` needs, recorded eagerly because trees carry
50
+ * no parent pointers here.
51
+ */
52
+ forkPoints = /* @__PURE__ */ new Map();
45
53
  writeReadiness;
46
54
  sequence = 0;
47
55
  constructor(options = {}) {
@@ -97,6 +105,10 @@ var MemoryProvider = class {
97
105
  }
98
106
  async applyPlan(input) {
99
107
  const base = input.base ?? CONTENTRAIN_BRANCH;
108
+ if (!this.refs.has(input.branch)) this.forkPoints.set(input.branch, {
109
+ from: base,
110
+ tree: new Map(this.tree(base))
111
+ });
100
112
  const tree = new Map(this.refs.get(input.branch) ?? this.tree(base));
101
113
  for (const change of input.changes) if (change.content === null) tree.delete(normalize(change.path));
102
114
  else tree.set(normalize(change.path), change.content);
@@ -124,11 +136,17 @@ var MemoryProvider = class {
124
136
  })));
125
137
  }
126
138
  createBranch(name, fromRef) {
127
- this.refs.set(name, new Map(this.tree(fromRef ?? CONTENTRAIN_BRANCH)));
139
+ const from = fromRef ?? CONTENTRAIN_BRANCH;
140
+ this.forkPoints.set(name, {
141
+ from,
142
+ tree: new Map(this.tree(from))
143
+ });
144
+ this.refs.set(name, new Map(this.tree(from)));
128
145
  return Promise.resolve();
129
146
  }
130
147
  deleteBranch(name) {
131
148
  this.refs.delete(name);
149
+ this.forkPoints.delete(name);
132
150
  return Promise.resolve();
133
151
  }
134
152
  getBranchDiff(branch, base) {
@@ -178,6 +196,43 @@ var MemoryProvider = class {
178
196
  getDefaultBranch() {
179
197
  return Promise.resolve("main");
180
198
  }
199
+ /**
200
+ * The fork snapshot as a readable ref. When `b` forked from `a` (or the
201
+ * reverse), the recorded fork tree IS the merge base; it is registered
202
+ * under a synthetic `membase/<branch>` ref so the three-way readers can
203
+ * bind to it like any other ref. Unrelated refs → null, like git.
204
+ */
205
+ getMergeBase(refA, refB) {
206
+ if (refA === refB) return Promise.resolve(refA);
207
+ const viaB = this.forkPoints.get(refB);
208
+ if (viaB && viaB.from === refA) return Promise.resolve(this.registerBase(refB, viaB.tree));
209
+ const viaA = this.forkPoints.get(refA);
210
+ if (viaA && viaA.from === refB) return Promise.resolve(this.registerBase(refA, viaA.tree));
211
+ if (viaA && viaB && viaA.from === viaB.from && treesEqual(viaA.tree, viaB.tree)) return Promise.resolve(this.registerBase(refA, viaA.tree));
212
+ return Promise.resolve(null);
213
+ }
214
+ createMergeCommit(input) {
215
+ const tree = new Map(this.tree(input.branch));
216
+ for (const change of input.changes) if (change.content === null) tree.delete(normalize(change.path));
217
+ else tree.set(normalize(change.path), change.content);
218
+ this.refs.set(input.branch, tree);
219
+ const commit = {
220
+ sha: `mem${(++this.sequence).toString().padStart(9, "0")}`,
221
+ message: input.message,
222
+ author: input.author,
223
+ timestamp: new Date(Date.UTC(2026, 0, 1, 0, 0, this.sequence)).toISOString(),
224
+ branch: input.branch,
225
+ changes: input.changes,
226
+ parents: [input.ours, input.theirs]
227
+ };
228
+ this.commits.push(commit);
229
+ return Promise.resolve(commit);
230
+ }
231
+ registerBase(branch, tree) {
232
+ const ref = `membase/${branch}`;
233
+ this.refs.set(ref, new Map(tree));
234
+ return ref;
235
+ }
181
236
  tree(ref) {
182
237
  let tree = this.refs.get(ref);
183
238
  if (!tree) {
@@ -199,6 +254,11 @@ var MemoryProvider = class {
199
254
  function normalize(path) {
200
255
  return path.replace(/\\/g, "/").replace(/^\.\//, "").replace(/^\/+/, "").replace(/\/+$/, "");
201
256
  }
257
+ function treesEqual(a, b) {
258
+ if (a.size !== b.size) return false;
259
+ for (const [path, content] of a) if (b.get(path) !== content) return false;
260
+ return true;
261
+ }
202
262
  //#endregion
203
263
  export { MemoryProvider };
204
264
 
@@ -1 +1 @@
1
- {"version":3,"file":"memory-provider.mjs","names":[],"sources":["../../src/testing/memory-provider.ts"],"sourcesContent":["import { CONTENTRAIN_BRANCH } from '@contentrain/types'\nimport type {\n ApplyPlanInput,\n Branch,\n Commit,\n FileChange,\n FileDiff,\n MergeResult,\n ProviderCapabilities,\n RepoProvider,\n WriteReadiness,\n} from '../core/contracts/index.js'\n\n/**\n * MemoryProvider — a complete `RepoProvider` backed by `Map`s.\n *\n * Why this exists: the write-side tool tests were spending their entire\n * wall-clock in `posix_spawn`. A `contentrain_init` costs 33 git subprocesses\n * and a content save 26, and on macOS each one is dominated by fork cost\n * rather than by git. Tests that assert \"does model_save reject an invalid\n * field type\" were paying for worktree creation, merge and ref surgery to\n * find out.\n *\n * None of that is what those tests are about. The provider contract is the\n * seam the engine was already built around — `@contentrain/types` names \"a\n * mock in a test suite\" as a legitimate implementation — so this fills it in\n * and the tool layer runs unchanged, with zero subprocesses.\n *\n * What it is faithful about, because tests depend on it:\n * - branches are real snapshots, forked from `base` at fork time, so a\n * write to a `cr/*` branch is invisible on `contentrain` until it merges\n * - the workflow decision reads the project's own `config.json`, so\n * auto-merge and review are both genuinely exercised\n * - `listDirectory` returns immediate children only, and directories\n * without a trailing entry still report as existing, matching `readdir`\n *\n * What it deliberately does not model: conflicts, worktrees, selective sync\n * into a developer's working tree, and anything else whose behaviour is a\n * property of git rather than of Contentrain. A test that needs those needs a\n * real repository — keep those, and only those, on the git fixture path.\n */\n\nconst MEMORY_CAPABILITIES: ProviderCapabilities = {\n // True: this provider owns the merge decision, exactly as a worktree does.\n // The tool layer branches on this to choose the auto-merge path, which is\n // the path most write tests are actually about.\n localWorktree: true,\n sourceRead: true,\n sourceWrite: true,\n pushRemote: false,\n branchProtection: false,\n pullRequestFallback: false,\n astScan: false,\n}\n\nexport interface MemoryProviderOptions {\n /** Seed files, keyed by repo-relative path. */\n files?: Record<string, string>\n /** Override the capability set — e.g. to exercise the remote-provider path. */\n capabilities?: Partial<ProviderCapabilities>\n /** Refuse writes, as a local repo does under branch pressure. */\n writeReadiness?: WriteReadiness\n}\n\n/** A commit as recorded by the provider, with the changes that produced it. */\nexport interface RecordedCommit extends Commit {\n branch: string\n changes: FileChange[]\n}\n\ntype Tree = Map<string, string>\n\nexport class MemoryProvider implements RepoProvider {\n readonly capabilities: ProviderCapabilities\n\n /** Every commit in order, with its changes — the assertion surface. */\n readonly commits: RecordedCommit[] = []\n\n private readonly refs = new Map<string, Tree>()\n private writeReadiness: WriteReadiness\n private sequence = 0\n\n constructor(options: MemoryProviderOptions = {}) {\n this.capabilities = { ...MEMORY_CAPABILITIES, ...options.capabilities }\n this.writeReadiness = options.writeReadiness ?? { blocked: false }\n this.refs.set(CONTENTRAIN_BRANCH, new Map(Object.entries(options.files ?? {})))\n }\n\n // ─── Inspection (test surface, not part of RepoProvider) ───\n\n /** Whole tree of a ref as a plain object — snapshot-friendly. */\n snapshot(ref: string = CONTENTRAIN_BRANCH): Record<string, string> {\n return Object.fromEntries([...(this.refs.get(ref) ?? new Map())].toSorted(\n ([a], [b]) => a.localeCompare(b, 'en'),\n ))\n }\n\n /** Every path on a ref, sorted. */\n paths(ref: string = CONTENTRAIN_BRANCH): string[] {\n return [...(this.refs.get(ref) ?? new Map()).keys()].toSorted((a, b) => a.localeCompare(b, 'en'))\n }\n\n /** Seed or overwrite a file without going through a commit. */\n seed(path: string, content: string, ref: string = CONTENTRAIN_BRANCH): void {\n this.tree(ref).set(path, content)\n }\n\n /** Start refusing (or accepting) writes, as branch pressure would. */\n setWriteReadiness(readiness: WriteReadiness): void {\n this.writeReadiness = readiness\n }\n\n // ─── RepoReader ───\n\n readFile(path: string, ref?: string): Promise<string> {\n const content = this.tree(ref ?? CONTENTRAIN_BRANCH).get(normalize(path))\n if (content === undefined) {\n return Promise.reject(new Error(`ENOENT: no such file, open '${path}'`))\n }\n return Promise.resolve(content)\n }\n\n listDirectory(path: string, ref?: string): Promise<string[]> {\n const prefix = normalize(path) === '' ? '' : `${normalize(path)}/`\n const names = new Set<string>()\n for (const key of this.tree(ref ?? CONTENTRAIN_BRANCH).keys()) {\n if (!key.startsWith(prefix)) continue\n const rest = key.slice(prefix.length)\n if (rest === '') continue\n // Immediate child only: a nested path contributes its directory name.\n names.add(rest.split('/')[0]!)\n }\n return Promise.resolve([...names].toSorted((a, b) => a.localeCompare(b, 'en')))\n }\n\n fileExists(path: string, ref?: string): Promise<boolean> {\n const target = normalize(path)\n const tree = this.tree(ref ?? CONTENTRAIN_BRANCH)\n if (tree.has(target)) return Promise.resolve(true)\n // Directories exist implicitly, the way they do on a filesystem.\n const prefix = `${target}/`\n for (const key of tree.keys()) {\n if (key.startsWith(prefix)) return Promise.resolve(true)\n }\n return Promise.resolve(false)\n }\n\n // ─── RepoWriter ───\n\n checkWriteReadiness(): Promise<WriteReadiness> {\n return Promise.resolve(this.writeReadiness)\n }\n\n async applyPlan(input: ApplyPlanInput): Promise<Commit> {\n const base = input.base ?? CONTENTRAIN_BRANCH\n // Fork at write time, like a real branch: the feature branch sees base as\n // it is now, and later base commits do not leak into it.\n const tree = new Map(this.refs.get(input.branch) ?? this.tree(base))\n for (const change of input.changes) {\n if (change.content === null) tree.delete(normalize(change.path))\n else tree.set(normalize(change.path), change.content)\n }\n this.refs.set(input.branch, tree)\n\n const workflow = input.workflowOverride ?? await this.readWorkflow(base)\n const autoMerge = this.capabilities.localWorktree && workflow === 'auto-merge'\n if (autoMerge) this.refs.set(base, new Map(tree))\n\n const commit: RecordedCommit = {\n sha: `mem${(++this.sequence).toString().padStart(9, '0')}`,\n message: input.message,\n author: input.author,\n // Fixed, not `new Date()`: a timestamp that moves makes every snapshot\n // assertion a false failure.\n timestamp: new Date(Date.UTC(2026, 0, 1, 0, 0, this.sequence)).toISOString(),\n branch: input.branch,\n changes: input.changes,\n ...(this.capabilities.localWorktree\n ? { workflowAction: autoMerge ? 'auto-merged' as const : 'pending-review' as const }\n : {}),\n }\n this.commits.push(commit)\n return commit\n }\n\n // ─── Branches ───\n\n listBranches(prefix?: string): Promise<Branch[]> {\n const names = [...this.refs.keys()].filter(n => !prefix || n.startsWith(prefix))\n return Promise.resolve(names.toSorted((a, b) => a.localeCompare(b, 'en')).map(name => ({\n name,\n sha: this.commits.findLast(c => c.branch === name)?.sha ?? 'mem000000000',\n })))\n }\n\n createBranch(name: string, fromRef?: string): Promise<void> {\n this.refs.set(name, new Map(this.tree(fromRef ?? CONTENTRAIN_BRANCH)))\n return Promise.resolve()\n }\n\n deleteBranch(name: string): Promise<void> {\n this.refs.delete(name)\n return Promise.resolve()\n }\n\n getBranchDiff(branch: string, base?: string): Promise<FileDiff[]> {\n const head = this.tree(branch)\n const root = this.tree(base ?? CONTENTRAIN_BRANCH)\n const diffs: FileDiff[] = []\n for (const [path, after] of head) {\n const before = root.get(path) ?? null\n if (before === after) continue\n diffs.push({ path, status: before === null ? 'added' : 'modified', before, after })\n }\n for (const [path, before] of root) {\n if (!head.has(path)) diffs.push({ path, status: 'removed', before, after: null })\n }\n return Promise.resolve(diffs.toSorted((a, b) => a.path.localeCompare(b.path, 'en')))\n }\n\n mergeBranch(branch: string, into: string, opts?: { removeSourceBranch?: boolean }): Promise<MergeResult> {\n const source = this.refs.get(branch)\n if (!source) return Promise.resolve({ merged: false, sha: null, pullRequestUrl: null })\n this.refs.set(into, new Map(source))\n if (opts?.removeSourceBranch) this.refs.delete(branch)\n return Promise.resolve({\n merged: true,\n sha: this.commits.findLast(c => c.branch === branch)?.sha ?? null,\n pullRequestUrl: null,\n })\n }\n\n isMerged(branch: string, into?: string): Promise<boolean> {\n const head = this.refs.get(branch)\n if (!head) return Promise.resolve(true)\n const target = this.tree(into ?? CONTENTRAIN_BRANCH)\n for (const [path, content] of head) {\n if (target.get(path) !== content) return Promise.resolve(false)\n }\n return Promise.resolve(true)\n }\n\n getDefaultBranch(): Promise<string> {\n return Promise.resolve('main')\n }\n\n // ─── Internals ───\n\n private tree(ref: string): Tree {\n let tree = this.refs.get(ref)\n if (!tree) {\n tree = new Map()\n this.refs.set(ref, tree)\n }\n return tree\n }\n\n private async readWorkflow(ref: string): Promise<'auto-merge' | 'review'> {\n try {\n const raw = await this.readFile('.contentrain/config.json', ref)\n const workflow = (JSON.parse(raw) as { workflow?: unknown }).workflow\n return workflow === 'review' ? 'review' : 'auto-merge'\n } catch {\n return 'auto-merge'\n }\n }\n}\n\n/** Repo-relative, forward-slash, no leading `./` — the contract's path shape. */\nfunction normalize(path: string): string {\n return path.replace(/\\\\/g, '/').replace(/^\\.\\//, '').replace(/^\\/+/, '').replace(/\\/+$/, '')\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"memory-provider.mjs","names":[],"sources":["../../src/testing/memory-provider.ts"],"sourcesContent":["import { CONTENTRAIN_BRANCH } from '@contentrain/types'\nimport type {\n ApplyPlanInput,\n Branch,\n Commit,\n CommitAuthor,\n FileChange,\n FileDiff,\n MergeResult,\n ProviderCapabilities,\n RepoProvider,\n WriteReadiness,\n} from '../core/contracts/index.js'\n\n/**\n * MemoryProvider — a complete `RepoProvider` backed by `Map`s.\n *\n * Why this exists: the write-side tool tests were spending their entire\n * wall-clock in `posix_spawn`. A `contentrain_init` costs 33 git subprocesses\n * and a content save 26, and on macOS each one is dominated by fork cost\n * rather than by git. Tests that assert \"does model_save reject an invalid\n * field type\" were paying for worktree creation, merge and ref surgery to\n * find out.\n *\n * None of that is what those tests are about. The provider contract is the\n * seam the engine was already built around — `@contentrain/types` names \"a\n * mock in a test suite\" as a legitimate implementation — so this fills it in\n * and the tool layer runs unchanged, with zero subprocesses.\n *\n * What it is faithful about, because tests depend on it:\n * - branches are real snapshots, forked from `base` at fork time, so a\n * write to a `cr/*` branch is invisible on `contentrain` until it merges\n * - the workflow decision reads the project's own `config.json`, so\n * auto-merge and review are both genuinely exercised\n * - `listDirectory` returns immediate children only, and directories\n * without a trailing entry still report as existing, matching `readdir`\n *\n * What it deliberately does not model: conflicts, worktrees, selective sync\n * into a developer's working tree, and anything else whose behaviour is a\n * property of git rather than of Contentrain. A test that needs those needs a\n * real repository — keep those, and only those, on the git fixture path.\n */\n\nconst MEMORY_CAPABILITIES: ProviderCapabilities = {\n // True: this provider owns the merge decision, exactly as a worktree does.\n // The tool layer branches on this to choose the auto-merge path, which is\n // the path most write tests are actually about.\n localWorktree: true,\n sourceRead: true,\n sourceWrite: true,\n pushRemote: false,\n branchProtection: false,\n pullRequestFallback: false,\n astScan: false,\n mergeCommit: true,\n}\n\nexport interface MemoryProviderOptions {\n /** Seed files, keyed by repo-relative path. */\n files?: Record<string, string>\n /** Override the capability set — e.g. to exercise the remote-provider path. */\n capabilities?: Partial<ProviderCapabilities>\n /** Refuse writes, as a local repo does under branch pressure. */\n writeReadiness?: WriteReadiness\n}\n\n/** A commit as recorded by the provider, with the changes that produced it. */\nexport interface RecordedCommit extends Commit {\n branch: string\n changes: FileChange[]\n /** Present only on merge commits written by `createMergeCommit`: [ours, theirs]. */\n parents?: [string, string]\n}\n\ntype Tree = Map<string, string>\n\nexport class MemoryProvider implements RepoProvider {\n readonly capabilities: ProviderCapabilities\n\n /** Every commit in order, with its changes — the assertion surface. */\n readonly commits: RecordedCommit[] = []\n\n private readonly refs = new Map<string, Tree>()\n /**\n * Snapshot of the source tree at the moment each branch forked — what a\n * commit DAG would encode as the fork commit. This is exactly the\n * information `getMergeBase` needs, recorded eagerly because trees carry\n * no parent pointers here.\n */\n private readonly forkPoints = new Map<string, { from: string, tree: Tree }>()\n private writeReadiness: WriteReadiness\n private sequence = 0\n\n constructor(options: MemoryProviderOptions = {}) {\n this.capabilities = { ...MEMORY_CAPABILITIES, ...options.capabilities }\n this.writeReadiness = options.writeReadiness ?? { blocked: false }\n this.refs.set(CONTENTRAIN_BRANCH, new Map(Object.entries(options.files ?? {})))\n }\n\n // ─── Inspection (test surface, not part of RepoProvider) ───\n\n /** Whole tree of a ref as a plain object — snapshot-friendly. */\n snapshot(ref: string = CONTENTRAIN_BRANCH): Record<string, string> {\n return Object.fromEntries([...(this.refs.get(ref) ?? new Map())].toSorted(\n ([a], [b]) => a.localeCompare(b, 'en'),\n ))\n }\n\n /** Every path on a ref, sorted. */\n paths(ref: string = CONTENTRAIN_BRANCH): string[] {\n return [...(this.refs.get(ref) ?? new Map()).keys()].toSorted((a, b) => a.localeCompare(b, 'en'))\n }\n\n /** Seed or overwrite a file without going through a commit. */\n seed(path: string, content: string, ref: string = CONTENTRAIN_BRANCH): void {\n this.tree(ref).set(path, content)\n }\n\n /** Start refusing (or accepting) writes, as branch pressure would. */\n setWriteReadiness(readiness: WriteReadiness): void {\n this.writeReadiness = readiness\n }\n\n // ─── RepoReader ───\n\n readFile(path: string, ref?: string): Promise<string> {\n const content = this.tree(ref ?? CONTENTRAIN_BRANCH).get(normalize(path))\n if (content === undefined) {\n return Promise.reject(new Error(`ENOENT: no such file, open '${path}'`))\n }\n return Promise.resolve(content)\n }\n\n listDirectory(path: string, ref?: string): Promise<string[]> {\n const prefix = normalize(path) === '' ? '' : `${normalize(path)}/`\n const names = new Set<string>()\n for (const key of this.tree(ref ?? CONTENTRAIN_BRANCH).keys()) {\n if (!key.startsWith(prefix)) continue\n const rest = key.slice(prefix.length)\n if (rest === '') continue\n // Immediate child only: a nested path contributes its directory name.\n names.add(rest.split('/')[0]!)\n }\n return Promise.resolve([...names].toSorted((a, b) => a.localeCompare(b, 'en')))\n }\n\n fileExists(path: string, ref?: string): Promise<boolean> {\n const target = normalize(path)\n const tree = this.tree(ref ?? CONTENTRAIN_BRANCH)\n if (tree.has(target)) return Promise.resolve(true)\n // Directories exist implicitly, the way they do on a filesystem.\n const prefix = `${target}/`\n for (const key of tree.keys()) {\n if (key.startsWith(prefix)) return Promise.resolve(true)\n }\n return Promise.resolve(false)\n }\n\n // ─── RepoWriter ───\n\n checkWriteReadiness(): Promise<WriteReadiness> {\n return Promise.resolve(this.writeReadiness)\n }\n\n async applyPlan(input: ApplyPlanInput): Promise<Commit> {\n const base = input.base ?? CONTENTRAIN_BRANCH\n // Fork at write time, like a real branch: the feature branch sees base as\n // it is now, and later base commits do not leak into it.\n if (!this.refs.has(input.branch)) {\n this.forkPoints.set(input.branch, { from: base, tree: new Map(this.tree(base)) })\n }\n const tree = new Map(this.refs.get(input.branch) ?? this.tree(base))\n for (const change of input.changes) {\n if (change.content === null) tree.delete(normalize(change.path))\n else tree.set(normalize(change.path), change.content)\n }\n this.refs.set(input.branch, tree)\n\n const workflow = input.workflowOverride ?? await this.readWorkflow(base)\n const autoMerge = this.capabilities.localWorktree && workflow === 'auto-merge'\n if (autoMerge) this.refs.set(base, new Map(tree))\n\n const commit: RecordedCommit = {\n sha: `mem${(++this.sequence).toString().padStart(9, '0')}`,\n message: input.message,\n author: input.author,\n // Fixed, not `new Date()`: a timestamp that moves makes every snapshot\n // assertion a false failure.\n timestamp: new Date(Date.UTC(2026, 0, 1, 0, 0, this.sequence)).toISOString(),\n branch: input.branch,\n changes: input.changes,\n ...(this.capabilities.localWorktree\n ? { workflowAction: autoMerge ? 'auto-merged' as const : 'pending-review' as const }\n : {}),\n }\n this.commits.push(commit)\n return commit\n }\n\n // ─── Branches ───\n\n listBranches(prefix?: string): Promise<Branch[]> {\n const names = [...this.refs.keys()].filter(n => !prefix || n.startsWith(prefix))\n return Promise.resolve(names.toSorted((a, b) => a.localeCompare(b, 'en')).map(name => ({\n name,\n sha: this.commits.findLast(c => c.branch === name)?.sha ?? 'mem000000000',\n })))\n }\n\n createBranch(name: string, fromRef?: string): Promise<void> {\n const from = fromRef ?? CONTENTRAIN_BRANCH\n this.forkPoints.set(name, { from, tree: new Map(this.tree(from)) })\n this.refs.set(name, new Map(this.tree(from)))\n return Promise.resolve()\n }\n\n deleteBranch(name: string): Promise<void> {\n this.refs.delete(name)\n this.forkPoints.delete(name)\n return Promise.resolve()\n }\n\n getBranchDiff(branch: string, base?: string): Promise<FileDiff[]> {\n const head = this.tree(branch)\n const root = this.tree(base ?? CONTENTRAIN_BRANCH)\n const diffs: FileDiff[] = []\n for (const [path, after] of head) {\n const before = root.get(path) ?? null\n if (before === after) continue\n diffs.push({ path, status: before === null ? 'added' : 'modified', before, after })\n }\n for (const [path, before] of root) {\n if (!head.has(path)) diffs.push({ path, status: 'removed', before, after: null })\n }\n return Promise.resolve(diffs.toSorted((a, b) => a.path.localeCompare(b.path, 'en')))\n }\n\n mergeBranch(branch: string, into: string, opts?: { removeSourceBranch?: boolean }): Promise<MergeResult> {\n const source = this.refs.get(branch)\n if (!source) return Promise.resolve({ merged: false, sha: null, pullRequestUrl: null })\n this.refs.set(into, new Map(source))\n if (opts?.removeSourceBranch) this.refs.delete(branch)\n return Promise.resolve({\n merged: true,\n sha: this.commits.findLast(c => c.branch === branch)?.sha ?? null,\n pullRequestUrl: null,\n })\n }\n\n isMerged(branch: string, into?: string): Promise<boolean> {\n const head = this.refs.get(branch)\n if (!head) return Promise.resolve(true)\n const target = this.tree(into ?? CONTENTRAIN_BRANCH)\n for (const [path, content] of head) {\n if (target.get(path) !== content) return Promise.resolve(false)\n }\n return Promise.resolve(true)\n }\n\n getDefaultBranch(): Promise<string> {\n return Promise.resolve('main')\n }\n\n // ─── Reconcile (optional RepoProvider members) ───\n\n /**\n * The fork snapshot as a readable ref. When `b` forked from `a` (or the\n * reverse), the recorded fork tree IS the merge base; it is registered\n * under a synthetic `membase/<branch>` ref so the three-way readers can\n * bind to it like any other ref. Unrelated refs → null, like git.\n */\n getMergeBase(refA: string, refB: string): Promise<string | null> {\n if (refA === refB) return Promise.resolve(refA)\n const viaB = this.forkPoints.get(refB)\n if (viaB && viaB.from === refA) return Promise.resolve(this.registerBase(refB, viaB.tree))\n const viaA = this.forkPoints.get(refA)\n if (viaA && viaA.from === refB) return Promise.resolve(this.registerBase(refA, viaA.tree))\n // Siblings forked from the same source: their common ancestor is the\n // earlier of the two snapshots; either is correct only when equal.\n if (viaA && viaB && viaA.from === viaB.from && treesEqual(viaA.tree, viaB.tree)) {\n return Promise.resolve(this.registerBase(refA, viaA.tree))\n }\n return Promise.resolve(null)\n }\n\n createMergeCommit(input: {\n branch: string\n ours: string\n theirs: string\n changes: FileChange[]\n message: string\n author: CommitAuthor\n }): Promise<Commit> {\n // Changes apply on top of ours' tree — the planner's output is\n // authoritative for content paths, exactly as the contract states.\n const tree = new Map(this.tree(input.branch))\n for (const change of input.changes) {\n if (change.content === null) tree.delete(normalize(change.path))\n else tree.set(normalize(change.path), change.content)\n }\n this.refs.set(input.branch, tree)\n\n const commit: RecordedCommit = {\n sha: `mem${(++this.sequence).toString().padStart(9, '0')}`,\n message: input.message,\n author: input.author,\n timestamp: new Date(Date.UTC(2026, 0, 1, 0, 0, this.sequence)).toISOString(),\n branch: input.branch,\n changes: input.changes,\n parents: [input.ours, input.theirs],\n }\n this.commits.push(commit)\n return Promise.resolve(commit)\n }\n\n // ─── Internals ───\n\n private registerBase(branch: string, tree: Tree): string {\n const ref = `membase/${branch}`\n this.refs.set(ref, new Map(tree))\n return ref\n }\n\n private tree(ref: string): Tree {\n let tree = this.refs.get(ref)\n if (!tree) {\n tree = new Map()\n this.refs.set(ref, tree)\n }\n return tree\n }\n\n private async readWorkflow(ref: string): Promise<'auto-merge' | 'review'> {\n try {\n const raw = await this.readFile('.contentrain/config.json', ref)\n const workflow = (JSON.parse(raw) as { workflow?: unknown }).workflow\n return workflow === 'review' ? 'review' : 'auto-merge'\n } catch {\n return 'auto-merge'\n }\n }\n}\n\n/** Repo-relative, forward-slash, no leading `./` — the contract's path shape. */\nfunction normalize(path: string): string {\n return path.replace(/\\\\/g, '/').replace(/^\\.\\//, '').replace(/^\\/+/, '').replace(/\\/+$/, '')\n}\n\nfunction treesEqual(a: Tree, b: Tree): boolean {\n if (a.size !== b.size) return false\n for (const [path, content] of a) {\n if (b.get(path) !== content) return false\n }\n return true\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"annotations.d.mts","names":[],"sources":["../../src/tools/annotations.ts"],"mappings":";;;;;AAcA;;;;;AAiNA;;;;;cAjNa,gBAAA,EAAkB,MAAA,SAAe,eAAA;;;;;;;;cAiNjC,UAAA"}
1
+ {"version":3,"file":"annotations.d.mts","names":[],"sources":["../../src/tools/annotations.ts"],"mappings":";;;;;AAcA;;;;;AAwNA;;;;;cAxNa,gBAAA,EAAkB,MAAA,SAAe,eAAA;;;;;;;;cAwNjC,UAAA"}
@@ -1,2 +1,2 @@
1
- import { n as TOOL_NAMES, t as TOOL_ANNOTATIONS } from "../annotations-C-tQVmot.mjs";
1
+ import { n as TOOL_NAMES, t as TOOL_ANNOTATIONS } from "../annotations-CXHPnS-M.mjs";
2
2
  export { TOOL_ANNOTATIONS, TOOL_NAMES };
@@ -1 +1 @@
1
- {"version":3,"file":"availability.d.mts","names":[],"sources":["../../src/tools/availability.ts"],"mappings":";;;;;AAgBA;;;;;;;;;;AASA;;UATiB,gBAAA;EASuC;EAPtD,WAAA;EAO8B;EAL9B,YAAA,mBAA+B,oBAAA;EAKO;EAHtC,KAAA;AAAA;AAAA,cAGW,iBAAA,EAAmB,QAAA,CAAS,MAAA,SAAe,gBAAA;;;AA6BxD;;;;iBAAgB,eAAA,CACd,IAAA,UACA,QAAA;EAAY,YAAA,EAAc,oBAAA;EAAsB,KAAA;AAAA,GAChD,WAAA"}
1
+ {"version":3,"file":"availability.d.mts","names":[],"sources":["../../src/tools/availability.ts"],"mappings":";;;;;AAgBA;;;;;;;;;;AASA;;UATiB,gBAAA;EASuC;EAPtD,WAAA;EAO8B;EAL9B,YAAA,mBAA+B,oBAAA;EAKO;EAHtC,KAAA;AAAA;AAAA,cAGW,iBAAA,EAAmB,QAAA,CAAS,MAAA,SAAe,gBAAA;;;AA8BxD;;;;iBAAgB,eAAA,CACd,IAAA,UACA,QAAA;EAAY,YAAA,EAAc,oBAAA;EAAsB,KAAA;AAAA,GAChD,WAAA"}
@@ -1,2 +1,2 @@
1
- import { n as isToolAvailable, t as TOOL_REQUIREMENTS } from "../availability-Dgcmvv99.mjs";
1
+ import { n as isToolAvailable, t as TOOL_REQUIREMENTS } from "../availability-DYHNoP0_.mjs";
2
2
  export { TOOL_REQUIREMENTS, isToolAvailable };