@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.
- package/README.md +6 -3
- package/dist/{annotations-C-tQVmot.mjs → annotations-CXHPnS-M.mjs} +8 -1
- package/dist/annotations-CXHPnS-M.mjs.map +1 -0
- package/dist/{apply-manager-BybvnUVC.mjs → apply-manager-DsNq7Zhm.mjs} +7 -7
- package/dist/{apply-manager-BybvnUVC.mjs.map → apply-manager-DsNq7Zhm.mjs.map} +1 -1
- package/dist/{astro-parser-Cb9uuBpW.mjs → astro-parser-dhFgc2wA.mjs} +3 -3
- package/dist/{astro-parser-Cb9uuBpW.mjs.map → astro-parser-dhFgc2wA.mjs.map} +1 -1
- package/dist/{availability-Dgcmvv99.mjs → availability-DYHNoP0_.mjs} +5 -1
- package/dist/availability-DYHNoP0_.mjs.map +1 -0
- package/dist/{branch-lifecycle-DhzHfzs3.d.mts → branch-lifecycle-DGlgjnC7.d.mts} +32 -2
- package/dist/branch-lifecycle-DGlgjnC7.d.mts.map +1 -0
- package/dist/{branch-lifecycle-B6PXZ2N7.mjs → branch-lifecycle-DUOoyNWn.mjs} +32 -4
- package/dist/branch-lifecycle-DUOoyNWn.mjs.map +1 -0
- package/dist/{compiler-B6hNQeCC.mjs → compiler-CR9F0wZZ.mjs} +2 -2
- package/dist/{compiler-B6hNQeCC.mjs.map → compiler-CR9F0wZZ.mjs.map} +1 -1
- package/dist/{compiler-sfc.cjs-8yY7b5bx.mjs → compiler-sfc.cjs-Cpexs92i.mjs} +2 -2
- package/dist/{compiler-sfc.cjs-8yY7b5bx.mjs.map → compiler-sfc.cjs-Cpexs92i.mjs.map} +1 -1
- package/dist/{config-VlRKRwAS.mjs → config-B8a4JBT1.mjs} +2 -2
- package/dist/{config-VlRKRwAS.mjs.map → config-B8a4JBT1.mjs.map} +1 -1
- package/dist/{content-manager-Dn4tqDw1.d.mts → content-manager-Bx94DXSF.d.mts} +2 -2
- package/dist/{content-manager-Dn4tqDw1.d.mts.map → content-manager-Bx94DXSF.d.mts.map} +1 -1
- package/dist/{context-C3x6I3cE.mjs → context-CxpTATh4.mjs} +7 -7
- package/dist/context-CxpTATh4.mjs.map +1 -0
- package/dist/core/apply-manager.mjs +10 -11
- package/dist/core/config.d.mts +1 -1
- package/dist/core/config.mjs +2 -2
- package/dist/core/content-manager.d.mts +1 -1
- package/dist/core/content-manager.mjs +3 -3
- package/dist/core/context.d.mts +1 -1
- package/dist/core/context.mjs +5 -6
- package/dist/core/contracts/index.d.mts +1 -1
- package/dist/core/doctor.mjs +8 -8
- package/dist/core/graph-builder.mjs +3 -3
- package/dist/core/meta-manager.mjs +2 -2
- package/dist/core/model-manager.d.mts +1 -1
- package/dist/core/model-manager.mjs +3 -3
- package/dist/core/ops/index.d.mts +17 -29
- package/dist/core/ops/index.d.mts.map +1 -1
- package/dist/core/ops/index.mjs +9 -6
- package/dist/core/overlay-reader.d.mts +1 -1
- package/dist/core/overlay-reader.mjs +1 -1
- package/dist/core/scan-config.mjs +2 -2
- package/dist/core/scanner.mjs +4 -4
- package/dist/core/validator/index.d.mts +1 -1
- package/dist/core/validator/index.mjs +5 -5
- package/dist/{detect-B0oXbQaP.mjs → detect-CI32ynpq.mjs} +2 -2
- package/dist/{detect-B0oXbQaP.mjs.map → detect-CI32ynpq.mjs.map} +1 -1
- package/dist/{doctor-DNPuGgcg.mjs → doctor-B7G0oFxO.mjs} +7 -7
- package/dist/{doctor-DNPuGgcg.mjs.map → doctor-B7G0oFxO.mjs.map} +1 -1
- package/dist/errors-BmLE-JSC.mjs +55 -0
- package/dist/errors-BmLE-JSC.mjs.map +1 -0
- package/dist/{errors-CvBS12e7.mjs → errors-DLkAWnzQ.mjs} +1 -1
- package/dist/{errors-CvBS12e7.mjs.map → errors-DLkAWnzQ.mjs.map} +1 -1
- package/dist/{fs-DLbVB-Ek.mjs → fs-DJv5G8uL.mjs} +1 -1
- package/dist/{fs-DLbVB-Ek.mjs.map → fs-DJv5G8uL.mjs.map} +1 -1
- package/dist/git/branch-lifecycle.d.mts +2 -2
- package/dist/git/branch-lifecycle.mjs +5 -5
- package/dist/git/errors.d.mts +30 -0
- package/dist/git/errors.d.mts.map +1 -0
- package/dist/git/errors.mjs +2 -0
- package/dist/git/identity.mjs +1 -1
- package/dist/git/reconcile.d.mts +49 -0
- package/dist/git/reconcile.d.mts.map +1 -0
- package/dist/git/reconcile.mjs +13 -0
- package/dist/git/transaction.d.mts +60 -15
- package/dist/git/transaction.d.mts.map +1 -1
- package/dist/git/transaction.mjs +10 -11
- package/dist/{graph-builder-BEocwW13.mjs → graph-builder-C9NS7y-a.mjs} +3 -3
- package/dist/{graph-builder-BEocwW13.mjs.map → graph-builder-C9NS7y-a.mjs.map} +1 -1
- package/dist/{id-BjhaIxTL.mjs → id-CjGMPP1k.mjs} +2 -2
- package/dist/{id-BjhaIxTL.mjs.map → id-CjGMPP1k.mjs.map} +1 -1
- package/dist/{identity-D8QoGxhT.mjs → identity-CxAB9Qb8.mjs} +1 -1
- package/dist/{identity-D8QoGxhT.mjs.map → identity-CxAB9Qb8.mjs.map} +1 -1
- package/dist/index-_HJVkDJa.d.mts +85 -0
- package/dist/index-_HJVkDJa.d.mts.map +1 -0
- package/dist/index.mjs +24 -22
- package/dist/index.mjs.map +1 -1
- package/dist/{local-Db5X9mjZ.mjs → local-bnn6yrG7.mjs} +83 -8
- package/dist/local-bnn6yrG7.mjs.map +1 -0
- package/dist/{meta-manager-B_Se183X.mjs → meta-manager-g3shoZES.mjs} +2 -2
- package/dist/{meta-manager-B_Se183X.mjs.map → meta-manager-g3shoZES.mjs.map} +1 -1
- package/dist/{model-manager-DgyKMjLN.mjs → model-manager-DqwL8ptm.mjs} +66 -5
- package/dist/model-manager-DqwL8ptm.mjs.map +1 -0
- package/dist/{node-DUGiIkv1.mjs → node-CpLm3qr6.mjs} +1 -1
- package/dist/{node-DUGiIkv1.mjs.map → node-CpLm3qr6.mjs.map} +1 -1
- package/dist/{ops-BzbThweu.mjs → ops-BfrdZ6GK.mjs} +24 -34
- package/dist/ops-BfrdZ6GK.mjs.map +1 -0
- package/dist/{overlay-reader-CkU_pGXZ.mjs → overlay-reader-Bx1YxGXq.mjs} +1 -1
- package/dist/{overlay-reader-CkU_pGXZ.mjs.map → overlay-reader-Bx1YxGXq.mjs.map} +1 -1
- package/dist/{paths-CdPPWpbG.mjs → paths-C6_C1gLp.mjs} +1 -1
- package/dist/{paths-CdPPWpbG.mjs.map → paths-C6_C1gLp.mjs.map} +1 -1
- package/dist/providers/github/index.d.mts +10 -1
- package/dist/providers/github/index.d.mts.map +1 -1
- package/dist/providers/github/index.mjs +104 -4
- package/dist/providers/github/index.mjs.map +1 -1
- package/dist/providers/gitlab/index.d.mts +8 -1
- package/dist/providers/gitlab/index.d.mts.map +1 -1
- package/dist/providers/gitlab/index.mjs +15 -2
- package/dist/providers/gitlab/index.mjs.map +1 -1
- package/dist/providers/local/index.d.mts +26 -2
- package/dist/providers/local/index.d.mts.map +1 -1
- package/dist/providers/local/index.mjs +13 -12
- package/dist/reconcile-D5FTVW5z.mjs +1704 -0
- package/dist/reconcile-D5FTVW5z.mjs.map +1 -0
- package/dist/reconcile-M7KBZtdn.mjs +249 -0
- package/dist/reconcile-M7KBZtdn.mjs.map +1 -0
- package/dist/{scan-config-Dx49nCqk.mjs → scan-config-C5zzygeH.mjs} +2 -2
- package/dist/{scan-config-Dx49nCqk.mjs.map → scan-config-C5zzygeH.mjs.map} +1 -1
- package/dist/{scanner-BSvXjfkp.mjs → scanner-CEiT8Tgx.mjs} +7 -7
- package/dist/{scanner-BSvXjfkp.mjs.map → scanner-CEiT8Tgx.mjs.map} +1 -1
- package/dist/server/http/index.d.mts +1 -1
- package/dist/server/http/index.mjs +24 -22
- package/dist/server/http/index.mjs.map +1 -1
- package/dist/{server-B7QA0Q1M.mjs → server-B6abaEU2.mjs} +343 -227
- package/dist/server-B6abaEU2.mjs.map +1 -0
- package/dist/{server-CLPNnhYL.d.mts → server-SDsD0XGM.d.mts} +2 -2
- package/dist/{server-CLPNnhYL.d.mts.map → server-SDsD0XGM.d.mts.map} +1 -1
- package/dist/server.d.mts +1 -1
- package/dist/server.mjs +24 -22
- package/dist/{source-map-generator-DhjiQdV3.mjs → source-map-generator-Clb2Eqse.mjs} +1 -1
- package/dist/{source-map-generator-DhjiQdV3.mjs.map → source-map-generator-Clb2Eqse.mjs.map} +1 -1
- package/dist/{svelte-parser-CwySu9yn.mjs → svelte-parser-CBN7Jxb7.mjs} +3 -3
- package/dist/{svelte-parser-CwySu9yn.mjs.map → svelte-parser-CBN7Jxb7.mjs.map} +1 -1
- package/dist/templates/index.mjs +1 -1
- package/dist/{templates-CAkTIRkE.mjs → templates-BZbohJc8.mjs} +1 -1
- package/dist/{templates-CAkTIRkE.mjs.map → templates-BZbohJc8.mjs.map} +1 -1
- package/dist/testing/memory-provider.d.mts +26 -1
- package/dist/testing/memory-provider.d.mts.map +1 -1
- package/dist/testing/memory-provider.mjs +62 -2
- package/dist/testing/memory-provider.mjs.map +1 -1
- package/dist/tools/annotations.d.mts.map +1 -1
- package/dist/tools/annotations.mjs +1 -1
- package/dist/tools/availability.d.mts.map +1 -1
- package/dist/tools/availability.mjs +1 -1
- package/dist/{transaction-BW9ektWu.mjs → transaction-BxDiiakv.mjs} +128 -64
- package/dist/transaction-BxDiiakv.mjs.map +1 -0
- package/dist/tsx-parser-DOQpJVgK.mjs +2 -0
- package/dist/{tsx-parser-BvsK6lyG.mjs → tsx-parser-go5V9zoc.mjs} +1 -1
- package/dist/{tsx-parser-BvsK6lyG.mjs.map → tsx-parser-go5V9zoc.mjs.map} +1 -1
- package/dist/util/detect.mjs +2 -2
- package/dist/util/fs.mjs +1 -1
- package/dist/util/id.mjs +1 -1
- package/dist/{validator-0sJ9vh1j.mjs → validator-B2GhPM3L.mjs} +5 -6
- package/dist/{validator-0sJ9vh1j.mjs.map → validator-B2GhPM3L.mjs.map} +1 -1
- package/dist/{vue-parser-auedZiJG.mjs → vue-parser-5Mp8w-mb.mjs} +3 -3
- package/dist/{vue-parser-auedZiJG.mjs.map → vue-parser-5Mp8w-mb.mjs.map} +1 -1
- package/package.json +13 -5
- package/dist/annotations-C-tQVmot.mjs.map +0 -1
- package/dist/availability-Dgcmvv99.mjs.map +0 -1
- package/dist/branch-lifecycle-B6PXZ2N7.mjs.map +0 -1
- package/dist/branch-lifecycle-DhzHfzs3.d.mts.map +0 -1
- package/dist/context-C3x6I3cE.mjs.map +0 -1
- package/dist/local-Db5X9mjZ.mjs.map +0 -1
- package/dist/model-manager-DgyKMjLN.mjs.map +0 -1
- package/dist/ops-BzbThweu.mjs.map +0 -1
- package/dist/paths-CmVw5Cw2.mjs +0 -65
- package/dist/paths-CmVw5Cw2.mjs.map +0 -1
- package/dist/serialization-tmgfFBOh.mjs +0 -2
- package/dist/server-B7QA0Q1M.mjs.map +0 -1
- package/dist/transaction-BW9ektWu.mjs.map +0 -1
- package/dist/tsx-parser-Byc7HlJ8.mjs +0 -2
- /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-
|
|
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":";;;
|
|
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
|
-
|
|
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;;;;;
|
|
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-
|
|
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;;;
|
|
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-
|
|
1
|
+
import { n as isToolAvailable, t as TOOL_REQUIREMENTS } from "../availability-DYHNoP0_.mjs";
|
|
2
2
|
export { TOOL_REQUIREMENTS, isToolAvailable };
|