@contentrain/mcp 1.2.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/README.md +93 -25
  2. package/dist/annotations-Clhbw2lh.mjs +126 -0
  3. package/dist/annotations-Clhbw2lh.mjs.map +1 -0
  4. package/dist/{apply-manager-BkPMfpsN.mjs → apply-manager-D5ym5Jba.mjs} +7 -7
  5. package/dist/{apply-manager-BkPMfpsN.mjs.map → apply-manager-D5ym5Jba.mjs.map} +1 -1
  6. package/dist/{astro-parser-BJ-54JGe.mjs → astro-parser-B-nLl0zE.mjs} +3 -3
  7. package/dist/{astro-parser-BJ-54JGe.mjs.map → astro-parser-B-nLl0zE.mjs.map} +1 -1
  8. package/dist/{branch-lifecycle-wGJg25LT.mjs → branch-lifecycle-CFVpTpNT.mjs} +33 -3
  9. package/dist/{branch-lifecycle-wGJg25LT.mjs.map → branch-lifecycle-CFVpTpNT.mjs.map} +1 -1
  10. package/dist/{compiler-rIC4ETHv.mjs → compiler-k4yttlzM.mjs} +2 -2
  11. package/dist/{compiler-rIC4ETHv.mjs.map → compiler-k4yttlzM.mjs.map} +1 -1
  12. package/dist/{compiler-sfc.cjs-BbD04rn_.mjs → compiler-sfc.cjs-D0d_OicF.mjs} +2 -2
  13. package/dist/{compiler-sfc.cjs-BbD04rn_.mjs.map → compiler-sfc.cjs-D0d_OicF.mjs.map} +1 -1
  14. package/dist/config-BIl5Ybj0.mjs +40 -0
  15. package/dist/config-BIl5Ybj0.mjs.map +1 -0
  16. package/dist/content-manager-DqDLSNQ-.d.mts +63 -0
  17. package/dist/content-manager-DqDLSNQ-.d.mts.map +1 -0
  18. package/dist/context-J0OU9Nfp.mjs +102 -0
  19. package/dist/context-J0OU9Nfp.mjs.map +1 -0
  20. package/dist/contracts-DfL0BfrD.mjs +2 -0
  21. package/dist/core/apply-manager.mjs +10 -10
  22. package/dist/core/config.d.mts +13 -0
  23. package/dist/core/config.d.mts.map +1 -1
  24. package/dist/core/config.mjs +2 -3
  25. package/dist/core/content-manager.d.mts +2 -45
  26. package/dist/core/content-manager.mjs +3 -4
  27. package/dist/core/context.d.mts +32 -2
  28. package/dist/core/context.d.mts.map +1 -1
  29. package/dist/core/context.mjs +7 -7
  30. package/dist/core/contracts/index.d.mts +2 -0
  31. package/dist/core/contracts/index.mjs +2 -0
  32. package/dist/core/doctor.d.mts +76 -0
  33. package/dist/core/doctor.d.mts.map +1 -0
  34. package/dist/core/doctor.mjs +8 -0
  35. package/dist/core/graph-builder.mjs +3 -4
  36. package/dist/core/meta-manager.mjs +2 -3
  37. package/dist/core/model-manager.d.mts +34 -1
  38. package/dist/core/model-manager.d.mts.map +1 -1
  39. package/dist/core/model-manager.mjs +3 -4
  40. package/dist/core/ops/index.d.mts +137 -0
  41. package/dist/core/ops/index.d.mts.map +1 -0
  42. package/dist/core/ops/index.mjs +4 -0
  43. package/dist/core/overlay-reader.d.mts +42 -0
  44. package/dist/core/overlay-reader.d.mts.map +1 -0
  45. package/dist/core/overlay-reader.mjs +2 -0
  46. package/dist/core/scan-config.mjs +2 -3
  47. package/dist/core/scanner.mjs +4 -5
  48. package/dist/core/validator/index.d.mts +129 -0
  49. package/dist/core/validator/index.d.mts.map +1 -0
  50. package/dist/core/validator/index.mjs +6 -0
  51. package/dist/{detect-DinOQAmK.mjs → detect-DL9mFmaS.mjs} +2 -2
  52. package/dist/{detect-DinOQAmK.mjs.map → detect-DL9mFmaS.mjs.map} +1 -1
  53. package/dist/doctor-CgBoT6h1.mjs +338 -0
  54. package/dist/doctor-CgBoT6h1.mjs.map +1 -0
  55. package/dist/{fs-BnIQ4dKj.mjs → fs-DLbVB-Ek.mjs} +2 -2
  56. package/dist/fs-DLbVB-Ek.mjs.map +1 -0
  57. package/dist/git/branch-lifecycle.d.mts +30 -1
  58. package/dist/git/branch-lifecycle.d.mts.map +1 -1
  59. package/dist/git/branch-lifecycle.mjs +4 -5
  60. package/dist/git/transaction.d.mts +2 -2
  61. package/dist/git/transaction.d.mts.map +1 -1
  62. package/dist/git/transaction.mjs +8 -8
  63. package/dist/{graph-builder-tM7zj-SX.mjs → graph-builder-DXv2JEp-.mjs} +3 -3
  64. package/dist/{graph-builder-tM7zj-SX.mjs.map → graph-builder-DXv2JEp-.mjs.map} +1 -1
  65. package/dist/{id-DV_T9Ic8.mjs → id-CIO9s0x_.mjs} +1 -1
  66. package/dist/{id-DV_T9Ic8.mjs.map → id-CIO9s0x_.mjs.map} +1 -1
  67. package/dist/index-D0wQJSgs.d.mts +2 -0
  68. package/dist/index.mjs +22 -17
  69. package/dist/index.mjs.map +1 -1
  70. package/dist/local-DvP4Y4T-.mjs +182 -0
  71. package/dist/local-DvP4Y4T-.mjs.map +1 -0
  72. package/dist/{meta-manager--0IwAPCl.mjs → meta-manager-C900rEyG.mjs} +2 -2
  73. package/dist/{meta-manager--0IwAPCl.mjs.map → meta-manager-C900rEyG.mjs.map} +1 -1
  74. package/dist/{model-manager-DW_fOGRM.mjs → model-manager-BhLsUgaB.mjs} +241 -49
  75. package/dist/model-manager-BhLsUgaB.mjs.map +1 -0
  76. package/dist/{node-Cbq5eR5i.mjs → node-DN9hZeil.mjs} +1 -1
  77. package/dist/{node-Cbq5eR5i.mjs.map → node-DN9hZeil.mjs.map} +1 -1
  78. package/dist/ops-DjEWi5Wa.mjs +486 -0
  79. package/dist/ops-DjEWi5Wa.mjs.map +1 -0
  80. package/dist/overlay-reader-DOdyDRIv.mjs +74 -0
  81. package/dist/overlay-reader-DOdyDRIv.mjs.map +1 -0
  82. package/dist/paths-C3xNyc7z.mjs +52 -0
  83. package/dist/paths-C3xNyc7z.mjs.map +1 -0
  84. package/dist/paths-CYl5vCBD.mjs +54 -0
  85. package/dist/paths-CYl5vCBD.mjs.map +1 -0
  86. package/dist/providers/github/index.d.mts +201 -0
  87. package/dist/providers/github/index.d.mts.map +1 -0
  88. package/dist/providers/github/index.mjs +494 -0
  89. package/dist/providers/github/index.mjs.map +1 -0
  90. package/dist/providers/gitlab/index.d.mts +158 -0
  91. package/dist/providers/gitlab/index.d.mts.map +1 -0
  92. package/dist/providers/gitlab/index.mjs +361 -0
  93. package/dist/providers/gitlab/index.mjs.map +1 -0
  94. package/dist/providers/local/index.d.mts +106 -0
  95. package/dist/providers/local/index.d.mts.map +1 -0
  96. package/dist/providers/local/index.mjs +12 -0
  97. package/dist/{scan-config-QgnJ1-52.mjs → scan-config-jC6XmiqF.mjs} +2 -2
  98. package/dist/{scan-config-QgnJ1-52.mjs.map → scan-config-jC6XmiqF.mjs.map} +1 -1
  99. package/dist/{scanner-DUoXnmtI.mjs → scanner-DKMwc03k.mjs} +7 -7
  100. package/dist/{scanner-DUoXnmtI.mjs.map → scanner-DKMwc03k.mjs.map} +1 -1
  101. package/dist/serialization-B1CEzR4H.mjs +2 -0
  102. package/dist/server/http/index.d.mts +107 -0
  103. package/dist/server/http/index.d.mts.map +1 -0
  104. package/dist/server/http/index.mjs +248 -0
  105. package/dist/server/http/index.mjs.map +1 -0
  106. package/dist/{server-Dtq8vqbK.mjs → server-BkhhtEE2.mjs} +486 -355
  107. package/dist/server-BkhhtEE2.mjs.map +1 -0
  108. package/dist/server-WqGx6ait.d.mts +50 -0
  109. package/dist/server-WqGx6ait.d.mts.map +1 -0
  110. package/dist/server.d.mts +2 -7
  111. package/dist/server.mjs +22 -17
  112. package/dist/{source-map-generator-DpO-ejrt.mjs → source-map-generator-BWDva49I.mjs} +1 -1
  113. package/dist/{source-map-generator-DpO-ejrt.mjs.map → source-map-generator-BWDva49I.mjs.map} +1 -1
  114. package/dist/{svelte-parser-1bBcMx3T.mjs → svelte-parser-Dr9mmZuk.mjs} +3 -3
  115. package/dist/{svelte-parser-1bBcMx3T.mjs.map → svelte-parser-Dr9mmZuk.mjs.map} +1 -1
  116. package/dist/templates/index.mjs +1 -1
  117. package/dist/{templates-bRPzYq4M.mjs → templates-VrLVqfe5.mjs} +1 -1
  118. package/dist/{templates-bRPzYq4M.mjs.map → templates-VrLVqfe5.mjs.map} +1 -1
  119. package/dist/testing/conformance.d.mts +59 -0
  120. package/dist/testing/conformance.d.mts.map +1 -0
  121. package/dist/testing/conformance.mjs +59 -0
  122. package/dist/testing/conformance.mjs.map +1 -0
  123. package/dist/tools/annotations.d.mts +24 -0
  124. package/dist/tools/annotations.d.mts.map +1 -0
  125. package/dist/tools/annotations.mjs +2 -0
  126. package/dist/{transaction-C_Pvux78.mjs → transaction-DgkNgWSI.mjs} +61 -32
  127. package/dist/transaction-DgkNgWSI.mjs.map +1 -0
  128. package/dist/tsx-parser-BOMZE_yQ.mjs +2 -0
  129. package/dist/{tsx-parser-BWiMGAIR.mjs → tsx-parser-CQc6nr-o.mjs} +1 -1
  130. package/dist/{tsx-parser-BWiMGAIR.mjs.map → tsx-parser-CQc6nr-o.mjs.map} +1 -1
  131. package/dist/util/detect.mjs +2 -3
  132. package/dist/util/fs.mjs +1 -2
  133. package/dist/util/id.mjs +1 -1
  134. package/dist/validator-B0nNRFeU.mjs +906 -0
  135. package/dist/validator-B0nNRFeU.mjs.map +1 -0
  136. package/dist/{vue-parser-DTPTN3Yb.mjs → vue-parser-COgjArqv.mjs} +3 -3
  137. package/dist/{vue-parser-DTPTN3Yb.mjs.map → vue-parser-COgjArqv.mjs.map} +1 -1
  138. package/package.json +82 -23
  139. package/testing/conformance/01-new-collection-entry/expected/.contentrain/config.json +15 -0
  140. package/testing/conformance/01-new-collection-entry/expected/.contentrain/content/blog/blog/en.json +6 -0
  141. package/testing/conformance/01-new-collection-entry/expected/.contentrain/context.json +22 -0
  142. package/testing/conformance/01-new-collection-entry/expected/.contentrain/meta/blog/en.json +7 -0
  143. package/testing/conformance/01-new-collection-entry/expected/.contentrain/models/blog.json +16 -0
  144. package/testing/conformance/01-new-collection-entry/scenario.json +19 -0
  145. package/testing/conformance/01-new-collection-entry/setup/.contentrain/config.json +15 -0
  146. package/testing/conformance/01-new-collection-entry/setup/.contentrain/models/blog.json +16 -0
  147. package/testing/conformance/02-new-singleton/expected/.contentrain/config.json +15 -0
  148. package/testing/conformance/02-new-singleton/expected/.contentrain/content/marketing/hero/en.json +4 -0
  149. package/testing/conformance/02-new-singleton/expected/.contentrain/context.json +22 -0
  150. package/testing/conformance/02-new-singleton/expected/.contentrain/meta/hero/en.json +5 -0
  151. package/testing/conformance/02-new-singleton/expected/.contentrain/models/hero.json +16 -0
  152. package/testing/conformance/02-new-singleton/scenario.json +18 -0
  153. package/testing/conformance/02-new-singleton/setup/.contentrain/config.json +15 -0
  154. package/testing/conformance/02-new-singleton/setup/.contentrain/models/hero.json +16 -0
  155. package/testing/conformance/03-new-dictionary/expected/.contentrain/config.json +15 -0
  156. package/testing/conformance/03-new-dictionary/expected/.contentrain/content/marketing/ui-strings/en.json +5 -0
  157. package/testing/conformance/03-new-dictionary/expected/.contentrain/context.json +22 -0
  158. package/testing/conformance/03-new-dictionary/expected/.contentrain/meta/ui-strings/en.json +5 -0
  159. package/testing/conformance/03-new-dictionary/expected/.contentrain/models/ui-strings.json +7 -0
  160. package/testing/conformance/03-new-dictionary/scenario.json +19 -0
  161. package/testing/conformance/03-new-dictionary/setup/.contentrain/config.json +15 -0
  162. package/testing/conformance/03-new-dictionary/setup/.contentrain/models/ui-strings.json +7 -0
  163. package/testing/conformance/README.md +77 -0
  164. package/testing/conformance/scenarios.json +36 -0
  165. package/dist/config-B5kc2oeV.mjs +0 -27
  166. package/dist/config-B5kc2oeV.mjs.map +0 -1
  167. package/dist/context-DIDt_TxX.mjs +0 -46
  168. package/dist/context-DIDt_TxX.mjs.map +0 -1
  169. package/dist/core/content-manager.d.mts.map +0 -1
  170. package/dist/core/validator.d.mts +0 -23
  171. package/dist/core/validator.d.mts.map +0 -1
  172. package/dist/core/validator.mjs +0 -7
  173. package/dist/fs-BnIQ4dKj.mjs.map +0 -1
  174. package/dist/model-manager-DW_fOGRM.mjs.map +0 -1
  175. package/dist/serializer-CnHTtmc1.mjs +0 -2
  176. package/dist/server-Dtq8vqbK.mjs.map +0 -1
  177. package/dist/server.d.mts.map +0 -1
  178. package/dist/transaction-C_Pvux78.mjs.map +0 -1
  179. package/dist/tsx-parser-BFLv292Y.mjs +0 -2
  180. package/dist/util/serializer.d.mts +0 -2
  181. package/dist/util/serializer.mjs +0 -2
  182. package/dist/validator-SQYUV2JP.mjs +0 -581
  183. package/dist/validator-SQYUV2JP.mjs.map +0 -1
@@ -0,0 +1,52 @@
1
+ //#region src/providers/shared/errors.ts
2
+ /**
3
+ * Unified "is this a 404?" helper for API-backed providers.
4
+ *
5
+ * Two common error shapes in the provider SDKs we use:
6
+ *
7
+ * - **Octokit** (`@octokit/rest`) — rejects with an `Error` that has a
8
+ * top-level `.status` number set to the HTTP status code.
9
+ * - **Gitbeaker** (`@gitbeaker/rest`) — rejects with a plain `Error` whose
10
+ * `.cause` includes `{ response: { status } }`.
11
+ *
12
+ * Both forms converge on `404` meaning "resource missing", so we check
13
+ * both shapes strictly. We deliberately do NOT fall back to substring
14
+ * matching on the error message — that leniency can silently mask other
15
+ * 404-like errors (forbidden repo, deleted project, rate limits) and
16
+ * produce the wrong answer. If either SDK ever stops populating the
17
+ * status field on a legitimate 404, the regression will surface in tests
18
+ * rather than being papered over at the reader layer.
19
+ */
20
+ function isNotFoundError(error) {
21
+ if (typeof error !== "object" || error === null) return false;
22
+ if (error.status === 404) return true;
23
+ return error.cause?.response?.status === 404;
24
+ }
25
+ //#endregion
26
+ //#region src/providers/shared/paths.ts
27
+ /**
28
+ * Normalise an optional contentRoot — strip leading/trailing slashes,
29
+ * treat `''`, `/` and `undefined` as "no prefix". Used by API-backed
30
+ * providers (GitHub, GitLab, future Bitbucket) to anchor content-relative
31
+ * paths against a repo subdirectory when Contentrain lives under a
32
+ * monorepo path like `apps/web/.contentrain/`.
33
+ */
34
+ function normaliseContentRoot(raw) {
35
+ if (!raw || raw === "/" || raw === "") return "";
36
+ return raw.replace(/^\/+|\/+$/g, "");
37
+ }
38
+ /**
39
+ * Resolve a content-root-relative path to a repo-relative path. The result
40
+ * always uses forward slashes and has no leading slash — the form every
41
+ * REST git API consumes for `file_path` / `path` query parameters and the
42
+ * Git Data API tree entries.
43
+ */
44
+ function resolveRepoPath(contentRoot, relativePath) {
45
+ const prefix = normaliseContentRoot(contentRoot);
46
+ const cleanPath = relativePath.replace(/^\/+/, "");
47
+ return prefix ? `${prefix}/${cleanPath}` : cleanPath;
48
+ }
49
+ //#endregion
50
+ export { isNotFoundError as n, resolveRepoPath as t };
51
+
52
+ //# sourceMappingURL=paths-C3xNyc7z.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths-C3xNyc7z.mjs","names":[],"sources":["../src/providers/shared/errors.ts","../src/providers/shared/paths.ts"],"sourcesContent":["/**\n * Unified \"is this a 404?\" helper for API-backed providers.\n *\n * Two common error shapes in the provider SDKs we use:\n *\n * - **Octokit** (`@octokit/rest`) — rejects with an `Error` that has a\n * top-level `.status` number set to the HTTP status code.\n * - **Gitbeaker** (`@gitbeaker/rest`) — rejects with a plain `Error` whose\n * `.cause` includes `{ response: { status } }`.\n *\n * Both forms converge on `404` meaning \"resource missing\", so we check\n * both shapes strictly. We deliberately do NOT fall back to substring\n * matching on the error message — that leniency can silently mask other\n * 404-like errors (forbidden repo, deleted project, rate limits) and\n * produce the wrong answer. If either SDK ever stops populating the\n * status field on a legitimate 404, the regression will surface in tests\n * rather than being papered over at the reader layer.\n */\nexport function isNotFoundError(error: unknown): boolean {\n if (typeof error !== 'object' || error === null) return false\n const direct = (error as { status?: number }).status\n if (direct === 404) return true\n const nested = (error as { cause?: { response?: { status?: number } } }).cause?.response?.status\n return nested === 404\n}\n","/**\n * Normalise an optional contentRoot — strip leading/trailing slashes,\n * treat `''`, `/` and `undefined` as \"no prefix\". Used by API-backed\n * providers (GitHub, GitLab, future Bitbucket) to anchor content-relative\n * paths against a repo subdirectory when Contentrain lives under a\n * monorepo path like `apps/web/.contentrain/`.\n */\nexport function normaliseContentRoot(raw?: string): string {\n if (!raw || raw === '/' || raw === '') return ''\n return raw.replace(/^\\/+|\\/+$/g, '')\n}\n\n/**\n * Resolve a content-root-relative path to a repo-relative path. The result\n * always uses forward slashes and has no leading slash — the form every\n * REST git API consumes for `file_path` / `path` query parameters and the\n * Git Data API tree entries.\n */\nexport function resolveRepoPath(contentRoot: string | undefined, relativePath: string): string {\n const prefix = normaliseContentRoot(contentRoot)\n const cleanPath = relativePath.replace(/^\\/+/, '')\n return prefix ? `${prefix}/${cleanPath}` : cleanPath\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAkBA,SAAgB,gBAAgB,OAAyB;AACvD,KAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AAExD,KADgB,MAA8B,WAC/B,IAAK,QAAO;AAE3B,QADgB,MAAyD,OAAO,UAAU,WACxE;;;;;;;;;;;AChBpB,SAAgB,qBAAqB,KAAsB;AACzD,KAAI,CAAC,OAAO,QAAQ,OAAO,QAAQ,GAAI,QAAO;AAC9C,QAAO,IAAI,QAAQ,cAAc,GAAG;;;;;;;;AAStC,SAAgB,gBAAgB,aAAiC,cAA8B;CAC7F,MAAM,SAAS,qBAAqB,YAAY;CAChD,MAAM,YAAY,aAAa,QAAQ,QAAQ,GAAG;AAClD,QAAO,SAAS,GAAG,OAAO,GAAG,cAAc"}
@@ -0,0 +1,54 @@
1
+ //#region src/core/ops/paths.ts
2
+ /**
3
+ * Content-root-relative path helpers for plan-API consumers.
4
+ *
5
+ * These mirror the logic inside `core/content-manager.ts:resolveJsonFilePath`
6
+ * but return forward-slash relative strings suitable for `FileChange.path`.
7
+ * Providers are responsible for resolving these against their backing store
8
+ * (worktree on disk for LocalProvider, git tree path for GitHubProvider, ...).
9
+ *
10
+ * Kept inline to `core/ops/` for now; when Faz 2 finishes migrating every op
11
+ * the legacy absolute-path helpers in `core/content-manager.ts` and
12
+ * `core/meta-manager.ts` will call into these (or be replaced entirely).
13
+ */
14
+ /**
15
+ * Content-root-relative content directory for a model (forward-slash paths).
16
+ * Mirrors `resolveContentDir` with an empty `projectRoot`, so reader-backed
17
+ * callers and plan-API consumers share the same path resolution.
18
+ */
19
+ function contentDirPath(model) {
20
+ if (model.content_path) return model.content_path;
21
+ return `.contentrain/content/${model.domain}/${model.id}`;
22
+ }
23
+ function contentDir(model) {
24
+ return contentDirPath(model);
25
+ }
26
+ function contentFilePath(model, locale) {
27
+ const dir = contentDir(model);
28
+ if (!model.i18n) return `${dir}/data.json`;
29
+ switch (model.locale_strategy ?? "file") {
30
+ case "suffix": return `${dir}/${model.id}.${locale}.json`;
31
+ case "directory": return `${dir}/${locale}/${model.id}.json`;
32
+ case "none": return `${dir}/${model.id}.json`;
33
+ default: return `${dir}/${locale}.json`;
34
+ }
35
+ }
36
+ function documentFilePath(model, locale, slug) {
37
+ const dir = contentDir(model);
38
+ if (!model.i18n) return `${dir}/${slug}.md`;
39
+ switch (model.locale_strategy ?? "file") {
40
+ case "suffix": return `${dir}/${slug}.${locale}.md`;
41
+ case "directory": return `${dir}/${locale}/${slug}.md`;
42
+ case "none": return `${dir}/${slug}.md`;
43
+ default: return `${dir}/${slug}/${locale}.md`;
44
+ }
45
+ }
46
+ function metaFilePath(model, locale, slug) {
47
+ const base = `.contentrain/meta/${model.id}`;
48
+ if (model.kind === "document" && slug) return `${base}/${slug}/${locale}.json`;
49
+ return `${base}/${locale}.json`;
50
+ }
51
+ //#endregion
52
+ export { metaFilePath as i, contentFilePath as n, documentFilePath as r, contentDirPath as t };
53
+
54
+ //# sourceMappingURL=paths-CYl5vCBD.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths-CYl5vCBD.mjs","names":[],"sources":["../src/core/ops/paths.ts"],"sourcesContent":["import type { ModelDefinition } from '@contentrain/types'\n\n/**\n * Content-root-relative path helpers for plan-API consumers.\n *\n * These mirror the logic inside `core/content-manager.ts:resolveJsonFilePath`\n * but return forward-slash relative strings suitable for `FileChange.path`.\n * Providers are responsible for resolving these against their backing store\n * (worktree on disk for LocalProvider, git tree path for GitHubProvider, ...).\n *\n * Kept inline to `core/ops/` for now; when Faz 2 finishes migrating every op\n * the legacy absolute-path helpers in `core/content-manager.ts` and\n * `core/meta-manager.ts` will call into these (or be replaced entirely).\n */\n\n/**\n * Content-root-relative content directory for a model (forward-slash paths).\n * Mirrors `resolveContentDir` with an empty `projectRoot`, so reader-backed\n * callers and plan-API consumers share the same path resolution.\n */\nexport function contentDirPath(\n model: Pick<ModelDefinition, 'domain' | 'id' | 'content_path'>,\n): string {\n if (model.content_path) return model.content_path\n return `.contentrain/content/${model.domain}/${model.id}`\n}\n\nfunction contentDir(model: Pick<ModelDefinition, 'domain' | 'id' | 'content_path'>): string {\n return contentDirPath(model)\n}\n\nexport function contentFilePath(\n model: Pick<ModelDefinition, 'id' | 'kind' | 'domain' | 'i18n' | 'content_path' | 'locale_strategy'>,\n locale: string,\n): string {\n const dir = contentDir(model)\n if (!model.i18n) return `${dir}/data.json`\n const strategy = model.locale_strategy ?? 'file'\n switch (strategy) {\n case 'suffix': return `${dir}/${model.id}.${locale}.json`\n case 'directory': return `${dir}/${locale}/${model.id}.json`\n case 'none': return `${dir}/${model.id}.json`\n default: return `${dir}/${locale}.json`\n }\n}\n\nexport function documentFilePath(\n model: Pick<ModelDefinition, 'id' | 'domain' | 'i18n' | 'content_path' | 'locale_strategy'>,\n locale: string,\n slug: string,\n): string {\n const dir = contentDir(model)\n if (!model.i18n) return `${dir}/${slug}.md`\n const strategy = model.locale_strategy ?? 'file'\n switch (strategy) {\n case 'suffix': return `${dir}/${slug}.${locale}.md`\n case 'directory': return `${dir}/${locale}/${slug}.md`\n case 'none': return `${dir}/${slug}.md`\n default: return `${dir}/${slug}/${locale}.md`\n }\n}\n\nexport function metaFilePath(\n model: Pick<ModelDefinition, 'id' | 'kind'>,\n locale: string,\n slug?: string,\n): string {\n const base = `.contentrain/meta/${model.id}`\n if (model.kind === 'document' && slug) {\n return `${base}/${slug}/${locale}.json`\n }\n return `${base}/${locale}.json`\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoBA,SAAgB,eACd,OACQ;AACR,KAAI,MAAM,aAAc,QAAO,MAAM;AACrC,QAAO,wBAAwB,MAAM,OAAO,GAAG,MAAM;;AAGvD,SAAS,WAAW,OAAwE;AAC1F,QAAO,eAAe,MAAM;;AAG9B,SAAgB,gBACd,OACA,QACQ;CACR,MAAM,MAAM,WAAW,MAAM;AAC7B,KAAI,CAAC,MAAM,KAAM,QAAO,GAAG,IAAI;AAE/B,SADiB,MAAM,mBAAmB,QAC1C;EACE,KAAK,SAAU,QAAO,GAAG,IAAI,GAAG,MAAM,GAAG,GAAG,OAAO;EACnD,KAAK,YAAa,QAAO,GAAG,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG;EACtD,KAAK,OAAQ,QAAO,GAAG,IAAI,GAAG,MAAM,GAAG;EACvC,QAAS,QAAO,GAAG,IAAI,GAAG,OAAO;;;AAIrC,SAAgB,iBACd,OACA,QACA,MACQ;CACR,MAAM,MAAM,WAAW,MAAM;AAC7B,KAAI,CAAC,MAAM,KAAM,QAAO,GAAG,IAAI,GAAG,KAAK;AAEvC,SADiB,MAAM,mBAAmB,QAC1C;EACE,KAAK,SAAU,QAAO,GAAG,IAAI,GAAG,KAAK,GAAG,OAAO;EAC/C,KAAK,YAAa,QAAO,GAAG,IAAI,GAAG,OAAO,GAAG,KAAK;EAClD,KAAK,OAAQ,QAAO,GAAG,IAAI,GAAG,KAAK;EACnC,QAAS,QAAO,GAAG,IAAI,GAAG,KAAK,GAAG,OAAO;;;AAI7C,SAAgB,aACd,OACA,QACA,MACQ;CACR,MAAM,OAAO,qBAAqB,MAAM;AACxC,KAAI,MAAM,SAAS,cAAc,KAC/B,QAAO,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO;AAEnC,QAAO,GAAG,KAAK,GAAG,OAAO"}
@@ -0,0 +1,201 @@
1
+ import { c as MergeResult, d as RepoReader, i as CommitAuthor, l as ProviderCapabilities, n as Branch, o as FileDiff, r as Commit, t as ApplyPlanInput, u as RepoProvider } from "../../index-D0wQJSgs.mjs";
2
+ import { Octokit } from "@octokit/rest";
3
+
4
+ //#region src/providers/github/app-auth.d.ts
5
+ /**
6
+ * GitHub App authentication helpers.
7
+ *
8
+ * Two entry points:
9
+ *
10
+ * - {@link signAppJwt} — mint a short-lived (10 min) GitHub App JWT from
11
+ * `appId` + `privateKey`. Used to authenticate app-level endpoints
12
+ * (listing installations, creating installation tokens).
13
+ *
14
+ * - {@link exchangeInstallationToken} — exchange an app JWT for a
15
+ * per-installation access token that can be passed straight to
16
+ * `Octokit({ auth: token })`. Installation tokens last ~1 hour and
17
+ * must be refreshed.
18
+ *
19
+ * Both helpers are pure — they never import `@octokit/rest` or
20
+ * `@octokit/auth-app`. Callers that want auto-refresh behaviour should
21
+ * either wire `@octokit/auth-app` as the `authStrategy` when constructing
22
+ * their own Octokit (see the embedding guide), or call
23
+ * `exchangeInstallationToken` on their own schedule.
24
+ */
25
+ interface AppAuthConfig {
26
+ /** GitHub App ID (numeric, from the app's settings page). */
27
+ appId: number;
28
+ /** PEM-encoded private key — the contents of the `.pem` the app issued. */
29
+ privateKey: string;
30
+ /** Installation the token should be scoped to. */
31
+ installationId: number;
32
+ }
33
+ interface InstallationTokenResult {
34
+ /** Opaque bearer token — pass to `new Octokit({ auth: token })`. */
35
+ token: string;
36
+ /** ISO 8601 expiry. Installation tokens expire after ~1 hour. */
37
+ expiresAt: string;
38
+ }
39
+ declare function signAppJwt(config: Pick<AppAuthConfig, 'appId' | 'privateKey'>): string;
40
+ /**
41
+ * Exchange an App JWT for an installation-scoped access token by calling
42
+ * GitHub's `POST /app/installations/{id}/access_tokens` endpoint.
43
+ *
44
+ * Uses `fetch` (Node ≥22 has it native) so the helper stays dependency-
45
+ * free. Throws on non-2xx responses with the GitHub-returned message.
46
+ */
47
+ declare function exchangeInstallationToken(config: AppAuthConfig, opts?: {
48
+ baseUrl?: string;
49
+ fetchImpl?: typeof globalThis.fetch;
50
+ }): Promise<InstallationTokenResult>;
51
+ //#endregion
52
+ //#region src/providers/github/capabilities.d.ts
53
+ /**
54
+ * Capability set for GitHubProvider.
55
+ *
56
+ * GitHub over the Git Data API has no working tree, so local worktree
57
+ * features, source-file access and AST scans are unavailable. Push /
58
+ * PR operations are free because every commit goes straight to the
59
+ * remote. Branch protection detection uses the Repos API.
60
+ *
61
+ * Tools that require `astScan`, `sourceRead` or `sourceWrite` must
62
+ * gracefully reject (with `capability_required`) when running against
63
+ * a GitHubProvider — this is the mechanism behind phase 6's normalize
64
+ * capability-gate.
65
+ */
66
+ declare const GITHUB_CAPABILITIES: ProviderCapabilities;
67
+ //#endregion
68
+ //#region src/providers/github/client.d.ts
69
+ /**
70
+ * GitHubClient — a typed alias for an `@octokit/rest` instance.
71
+ *
72
+ * We rely on the peer-installed `@octokit/rest` for its types only; the
73
+ * provider code never imports Octokit eagerly. Consumers install it
74
+ * themselves via the optional peer dependency; the factory in
75
+ * `factory.ts` `await import()`s Octokit at runtime so the rest of MCP
76
+ * stays usable without it.
77
+ */
78
+ type GitHubClient = Octokit;
79
+ //#endregion
80
+ //#region src/providers/github/types.d.ts
81
+ /**
82
+ * A reference to a GitHub repository.
83
+ *
84
+ * `contentRoot` is the repo-relative directory prefix where Contentrain
85
+ * content lives. For a flat content repo it stays `''`; for a monorepo
86
+ * where Contentrain is embedded (e.g. `apps/web/.contentrain/`) it holds
87
+ * that prefix. All reader/writer paths are joined against it.
88
+ */
89
+ interface RepoRef {
90
+ owner: string;
91
+ name: string;
92
+ contentRoot?: string;
93
+ }
94
+ /**
95
+ * Authentication options for the GitHub provider.
96
+ *
97
+ * - `pat` — a personal access token or fine-grained PAT. Simplest for
98
+ * self-hosted MCP or CI runners. Phase 5.1 ships with this mode only.
99
+ * - `app` — GitHub App installation auth (JWT + installation token
100
+ * exchange). Planned for Phase 5.2; see `.internal/refactor/
101
+ * 02-studio-handoff.md` S6 for how Studio's hosted MCP plugs in.
102
+ */
103
+ type GitHubAuth = {
104
+ type: 'pat';
105
+ token: string;
106
+ } | {
107
+ type: 'app';
108
+ appId: number;
109
+ privateKey: string;
110
+ installationId: number;
111
+ };
112
+ /** Default author used when a call does not provide one. */
113
+ declare const DEFAULT_GITHUB_AUTHOR: CommitAuthor;
114
+ //#endregion
115
+ //#region src/providers/github/provider.d.ts
116
+ /**
117
+ * GitHubProvider — `RepoProvider` backed by the Octokit-driven GitHub
118
+ * REST + Git Data APIs.
119
+ *
120
+ * The provider is transport-agnostic; it only talks to an `Octokit`
121
+ * instance passed into the constructor. The `createGitHubProvider`
122
+ * helper in `factory.ts` wraps the dynamic import so consumers never
123
+ * have to touch Octokit directly.
124
+ */
125
+ declare class GitHubProvider implements RepoProvider {
126
+ private readonly client;
127
+ readonly repo: RepoRef;
128
+ readonly capabilities: ProviderCapabilities;
129
+ private readonly reader;
130
+ constructor(client: GitHubClient, repo: RepoRef);
131
+ readFile(path: string, ref?: string): Promise<string>;
132
+ listDirectory(path: string, ref?: string): Promise<string[]>;
133
+ fileExists(path: string, ref?: string): Promise<boolean>;
134
+ applyPlan(input: ApplyPlanInput): Promise<Commit>;
135
+ listBranches(prefix?: string): Promise<Branch[]>;
136
+ createBranch(name: string, fromRef?: string): Promise<void>;
137
+ deleteBranch(name: string): Promise<void>;
138
+ getBranchDiff(branch: string, base?: string): Promise<FileDiff[]>;
139
+ mergeBranch(branch: string, into: string): Promise<MergeResult>;
140
+ isMerged(branch: string, into?: string): Promise<boolean>;
141
+ getDefaultBranch(): Promise<string>;
142
+ }
143
+ //#endregion
144
+ //#region src/providers/github/factory.d.ts
145
+ /**
146
+ * Create an Octokit-backed `GitHubClient` from an auth configuration.
147
+ *
148
+ * The `@octokit/rest` module is imported dynamically so it stays a pure
149
+ * optional peer dependency — self-hosted MCP on stdio can run without
150
+ * it. If the module is not installed, the import throws with a helpful
151
+ * hint pointing the operator at the peer dependency.
152
+ *
153
+ * Two auth modes:
154
+ *
155
+ * - `pat` — personal access token or fine-grained PAT. Simplest for
156
+ * self-hosted MCP or CI runners.
157
+ * - `app` — GitHub App installation auth. The factory mints a short-
158
+ * lived JWT, exchanges it for an installation token via
159
+ * `exchangeInstallationToken`, and instantiates Octokit with the
160
+ * resulting bearer. The returned token expires in ~1 hour; callers
161
+ * that need auto-refresh should instead inject their own Octokit
162
+ * built with `@octokit/auth-app`'s auth strategy and construct
163
+ * `GitHubProvider` directly. See the embedding guide for trade-offs.
164
+ */
165
+ declare function createGitHubClient(auth: GitHubAuth): Promise<GitHubClient>;
166
+ /**
167
+ * Factory for the full provider — instantiates an Octokit client and
168
+ * wraps it in a `GitHubProvider`. Consumers who already hold an Octokit
169
+ * instance (HTTP server injecting shared clients, tests, etc.) should
170
+ * instantiate `GitHubProvider` directly instead.
171
+ */
172
+ declare function createGitHubProvider(opts: {
173
+ auth: GitHubAuth;
174
+ repo: RepoRef;
175
+ }): Promise<GitHubProvider>;
176
+ //#endregion
177
+ //#region src/providers/github/reader.d.ts
178
+ /**
179
+ * GitHubReader — `RepoReader` backed by the GitHub Repos + Git Data APIs.
180
+ *
181
+ * Reads pass through `repos.getContent`; directories return a list of
182
+ * names, files return decoded UTF-8 text. Files larger than ~1 MB are
183
+ * fetched by blob SHA through `git.getBlob` because `getContent` omits
184
+ * the body in that case.
185
+ *
186
+ * `ref` is forwarded verbatim and may be a branch name, tag name or
187
+ * commit SHA. When omitted, GitHub resolves to the repository's default
188
+ * branch — which is usually wrong for Contentrain flows, so callers
189
+ * should always pass the explicit `contentrain` tracking branch.
190
+ */
191
+ declare class GitHubReader implements RepoReader {
192
+ private readonly client;
193
+ private readonly repo;
194
+ constructor(client: GitHubClient, repo: RepoRef);
195
+ readFile(path: string, ref?: string): Promise<string>;
196
+ listDirectory(path: string, ref?: string): Promise<string[]>;
197
+ fileExists(path: string, ref?: string): Promise<boolean>;
198
+ }
199
+ //#endregion
200
+ export { type AppAuthConfig, DEFAULT_GITHUB_AUTHOR, GITHUB_CAPABILITIES, type GitHubAuth, type GitHubClient, GitHubProvider, GitHubReader, type InstallationTokenResult, type RepoRef, createGitHubClient, createGitHubProvider, exchangeInstallationToken, signAppJwt };
201
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/providers/github/app-auth.ts","../../../src/providers/github/capabilities.ts","../../../src/providers/github/client.ts","../../../src/providers/github/types.ts","../../../src/providers/github/provider.ts","../../../src/providers/github/factory.ts","../../../src/providers/github/reader.ts"],"mappings":";;;;;;;;AAuBA;;;;;;;;;AASA;;;;;AAkBA;;UA3BiB,aAAA;EA2BsB;EAzBrC,KAAA;EAyBsC;EAvBtC,UAAA;EAuB4E;EArB5E,cAAA;AAAA;AAAA,UAGe,uBAAA;;EAEf,KAAA;EA4C6C;EA1C7C,SAAA;AAAA;AAAA,iBAcc,UAAA,CAAW,MAAA,EAAQ,IAAA,CAAK,aAAA;;;;;;;;iBA0BlB,yBAAA,CACpB,MAAA,EAAQ,aAAA,EACR,IAAA;EAAQ,OAAA;EAAkB,SAAA,UAAmB,UAAA,CAAW,KAAA;AAAA,IACvD,OAAA,CAAQ,uBAAA;;;;;;AAxDX;;;;;;;;;AASA;cCjBa,mBAAA,EAAqB,oBAAA;;;;;;ADQlC;;;;;;KEZY,YAAA,GAAe,OAAA;;;;;;AFY3B;;;;;UGbiB,OAAA;EACf,KAAA;EACA,IAAA;EACA,WAAA;AAAA;;;;;AHqCF;;;;;KGzBY,UAAA;EACN,IAAA;EAAa,KAAA;AAAA;EAEb,IAAA;EACA,KAAA;EACA,UAAA;EACA,cAAA;AAAA;;cAIO,qBAAA,EAAuB,YAAA;;;;AHZpC;;;;;;;;cIUa,cAAA,YAA0B,YAAA;EAAA,iBAKlB,MAAA;EAAA,SACD,IAAA,EAAM,OAAA;EAAA,SALf,YAAA,EAAc,oBAAA;EAAA,iBACN,MAAA;cAGE,MAAA,EAAQ,YAAA,EACT,IAAA,EAAM,OAAA;EAKxB,QAAA,CAAS,IAAA,UAAc,GAAA,YAAe,OAAA;EAGtC,aAAA,CAAc,IAAA,UAAc,GAAA,YAAe,OAAA;EAG3C,UAAA,CAAW,IAAA,UAAc,GAAA,YAAe,OAAA;EAIxC,SAAA,CAAU,KAAA,EAAO,cAAA,GAAiB,OAAA,CAAQ,MAAA;EAI1C,YAAA,CAAa,MAAA,YAAkB,OAAA,CAAQ,MAAA;EAGvC,YAAA,CAAa,IAAA,UAAc,OAAA,YAAmB,OAAA;EAI9C,YAAA,CAAa,IAAA,WAAe,OAAA;EAG5B,aAAA,CAAc,MAAA,UAAgB,IAAA,YAAgB,OAAA,CAAQ,QAAA;EAItD,WAAA,CAAY,MAAA,UAAgB,IAAA,WAAe,OAAA,CAAQ,WAAA;EAGnD,QAAA,CAAS,MAAA,UAAgB,IAAA,YAAgB,OAAA;EAIzC,gBAAA,CAAA,GAAoB,OAAA;AAAA;;;;AJxDtB;;;;;;;;;AASA;;;;;AAkBA;;;;;iBKzBsB,kBAAA,CAAmB,IAAA,EAAM,UAAA,GAAa,OAAA,CAAQ,YAAA;;;;ALmDpE;;;iBKhBsB,oBAAA,CAAqB,IAAA;EAAQ,IAAA,EAAM,UAAA;EAAY,IAAA,EAAM,OAAA;AAAA,IAAY,OAAA,CAAQ,cAAA;;;;ALrC/F;;;;;;;;;AASA;;;cMda,YAAA,YAAwB,UAAA;EAAA,iBAEhB,MAAA;EAAA,iBACA,IAAA;cADA,MAAA,EAAQ,YAAA,EACR,IAAA,EAAM,OAAA;EAGnB,QAAA,CAAS,IAAA,UAAc,GAAA,YAAe,OAAA;EAmCtC,aAAA,CAAc,IAAA,UAAc,GAAA,YAAe,OAAA;EAkB3C,UAAA,CAAW,IAAA,UAAc,GAAA,YAAe,OAAA;AAAA"}