@contentrain/mcp 3.0.2 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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-DdxWpNBH.mjs → server-BtzVY7yp.mjs} +343 -227
- package/dist/server-BtzVY7yp.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-DdxWpNBH.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,4 +1,4 @@
|
|
|
1
|
-
import { a as readJson, t as contentrainDir } from "./fs-
|
|
1
|
+
import { a as readJson, t as contentrainDir } from "./fs-DJv5G8uL.mjs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
//#region src/core/config.ts
|
|
4
4
|
const CONFIG_PATH = ".contentrain/config.json";
|
|
@@ -40,4 +40,4 @@ async function readVocabulary(input) {
|
|
|
40
40
|
//#endregion
|
|
41
41
|
export { readVocabulary as n, readConfig as t };
|
|
42
42
|
|
|
43
|
-
//# sourceMappingURL=config-
|
|
43
|
+
//# sourceMappingURL=config-B8a4JBT1.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-
|
|
1
|
+
{"version":3,"file":"config-B8a4JBT1.mjs","names":[],"sources":["../src/core/config.ts"],"sourcesContent":["import type { ContentrainConfig, Vocabulary } from '@contentrain/types'\nimport { join } from 'node:path'\nimport { contentrainDir, readJson } from '../util/fs.js'\nimport type { RepoReader } from './contracts/index.js'\n\nconst CONFIG_PATH = '.contentrain/config.json'\nconst VOCABULARY_PATH = '.contentrain/vocabulary.json'\n\nasync function readJsonViaReader<T>(reader: RepoReader, path: string): Promise<T | null> {\n try {\n return JSON.parse(await reader.readFile(path)) as T\n } catch {\n return null\n }\n}\n\nfunction normaliseConfig(raw: Partial<ContentrainConfig> | null): ContentrainConfig | null {\n if (!raw) return null\n return {\n version: raw.version ?? 1,\n stack: raw.stack ?? 'other',\n workflow: raw.workflow ?? 'auto-merge',\n locales: {\n default: raw.locales?.default ?? 'en',\n supported: raw.locales?.supported ?? [raw.locales?.default ?? 'en'],\n },\n domains: raw.domains ?? [],\n repository: raw.repository,\n assets_path: raw.assets_path,\n branchRetention: raw.branchRetention,\n branchWarnLimit: raw.branchWarnLimit,\n branchBlockLimit: raw.branchBlockLimit,\n remoteBranchCleanup: raw.remoteBranchCleanup,\n }\n}\n\n/**\n * Read `.contentrain/config.json` and normalise it with safe defaults.\n *\n * Accepts either a legacy `projectRoot` string (LocalReader is constructed\n * internally) or any `RepoReader` — tool handlers pass their provider so\n * the same logic resolves against local fs or the GitHub Git Data API.\n */\nexport function readConfig(projectRoot: string): Promise<ContentrainConfig | null>\nexport function readConfig(reader: RepoReader): Promise<ContentrainConfig | null>\nexport async function readConfig(input: string | RepoReader): Promise<ContentrainConfig | null> {\n if (typeof input === 'string') {\n const raw = await readJson<Partial<ContentrainConfig>>(join(contentrainDir(input), 'config.json'))\n return normaliseConfig(raw)\n }\n const raw = await readJsonViaReader<Partial<ContentrainConfig>>(input, CONFIG_PATH)\n return normaliseConfig(raw)\n}\n\n/**\n * Read `.contentrain/vocabulary.json`. Same dual signature as {@link readConfig}.\n */\nexport function readVocabulary(projectRoot: string): Promise<Vocabulary | null>\nexport function readVocabulary(reader: RepoReader): Promise<Vocabulary | null>\nexport async function readVocabulary(input: string | RepoReader): Promise<Vocabulary | null> {\n if (typeof input === 'string') {\n return readJson<Vocabulary>(join(contentrainDir(input), 'vocabulary.json'))\n }\n return readJsonViaReader<Vocabulary>(input, VOCABULARY_PATH)\n}\n"],"mappings":";;;AAKA,MAAM,cAAc;AACpB,MAAM,kBAAkB;AAExB,eAAe,kBAAqB,QAAoB,MAAiC;AACvF,KAAI;AACF,SAAO,KAAK,MAAM,MAAM,OAAO,SAAS,KAAK,CAAC;SACxC;AACN,SAAO;;;AAIX,SAAS,gBAAgB,KAAkE;AACzF,KAAI,CAAC,IAAK,QAAO;AACjB,QAAO;EACL,SAAS,IAAI,WAAW;EACxB,OAAO,IAAI,SAAS;EACpB,UAAU,IAAI,YAAY;EAC1B,SAAS;GACP,SAAS,IAAI,SAAS,WAAW;GACjC,WAAW,IAAI,SAAS,aAAa,CAAC,IAAI,SAAS,WAAW,KAAK;GACpE;EACD,SAAS,IAAI,WAAW,EAAE;EAC1B,YAAY,IAAI;EAChB,aAAa,IAAI;EACjB,iBAAiB,IAAI;EACrB,iBAAiB,IAAI;EACrB,kBAAkB,IAAI;EACtB,qBAAqB,IAAI;EAC1B;;AAYH,eAAsB,WAAW,OAA+D;AAC9F,KAAI,OAAO,UAAU,SAEnB,QAAO,gBADK,MAAM,SAAqC,KAAK,eAAe,MAAM,EAAE,cAAc,CAAC,CACvE;AAG7B,QAAO,gBADK,MAAM,kBAA8C,OAAO,YAAY,CACxD;;AAQ7B,eAAsB,eAAe,OAAwD;AAC3F,KAAI,OAAO,UAAU,SACnB,QAAO,SAAqB,KAAK,eAAe,MAAM,EAAE,kBAAkB,CAAC;AAE7E,QAAO,kBAA8B,OAAO,gBAAgB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as RepoReader } from "./index-
|
|
1
|
+
import { _ as RepoReader } from "./index-ByrVsRJE.mjs";
|
|
2
2
|
import { ContentrainConfig, LocaleStrategy, ModelDefinition, Vocabulary, parseMarkdownFrontmatter as parseFrontmatter, serializeMarkdownFrontmatter as serializeFrontmatter, validateEntryId as validateEntryId$1, validateLocale as validateLocale$1, validateSlug as validateSlug$1 } from "@contentrain/types";
|
|
3
3
|
|
|
4
4
|
//#region src/core/content-manager.d.ts
|
|
@@ -65,4 +65,4 @@ declare function readContent(projectRoot: string, model: ModelDefinition, opts:
|
|
|
65
65
|
}): Promise<unknown>;
|
|
66
66
|
//#endregion
|
|
67
67
|
export { validateEntryId$1 as _, ListOpts as a, writeContent as b, deleteContent as c, readContent as d, resolveContentDir as f, serializeFrontmatter as g, resolveMdFilePath as h, DeleteOpts as i, listContent as l, resolveLocaleStrategy as m, ContentFileModel as n, LocaleStrategyModel as o, resolveJsonFilePath as p, ContentPathModel as r, WriteResult as s, ContentEntry as t, parseFrontmatter as u, validateLocale$1 as v, validateSlug$1 as y };
|
|
68
|
-
//# sourceMappingURL=content-manager-
|
|
68
|
+
//# sourceMappingURL=content-manager-Bx94DXSF.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-manager-
|
|
1
|
+
{"version":3,"file":"content-manager-Bx94DXSF.d.mts","names":[],"sources":["../src/core/content-manager.ts"],"mappings":";;;;KAyBY,gBAAA,GAAmB,IAAA,CAAK,eAAA;AAAA,KACxB,mBAAA,GAAsB,IAAA,CAAK,eAAA;AAAA,KAC3B,gBAAA,GAAmB,IAAA,CAAK,eAAA;AAAA,iBAEpB,iBAAA,CAAkB,WAAA,UAAqB,KAAA,EAAO,gBAAA;AAAA,iBAO9C,qBAAA,CAAsB,KAAA,EAAO,mBAAA,GAAsB,cAAA;;iBAKnD,mBAAA,CAAoB,GAAA,UAAa,KAAA,EAAO,gBAAA,EAAkB,MAAA;;iBAc1D,iBAAA,CAAkB,GAAA,UAAa,KAAA,EAAO,IAAA,CAAK,eAAA,+BAA8C,MAAA,UAAgB,IAAA;AAAA,UAexG,YAAA;EACf,EAAA;EACA,IAAA;EACA,MAAA;EACA,IAAA,EAAM,MAAA;AAAA;AAAA,UAGS,WAAA;EACf,MAAA;EACA,EAAA;EACA,IAAA;EACA,MAAA;EACA,UAAA;AAAA;AAAA,UAGe,UAAA;EACf,EAAA;EACA,IAAA;EACA,MAAA;EACA,IAAA;EArD2C;EAuD3C,aAAA;AAAA;AAAA,UAGe,QAAA;EACf,MAAA;EACA,MAAA,GAAS,MAAA;EACT,OAAA;EACA,KAAA;EACA,MAAA;AAAA;AAAA,iBAKoB,YAAA,CACpB,WAAA,UACA,KAAA,EAAO,eAAA,EACP,OAAA,EAAS,YAAA,IACT,MAAA,EAAQ,iBAAA,EACR,UAAA,GAAa,UAAA,UACZ,OAAA,CAAQ,WAAA;AAAA,iBAuJW,aAAA,CACpB,WAAA,UACA,KAAA,EAAO,eAAA,EACP,IAAA,EAAM,UAAA,GACL,OAAA;;;;AAlNH;;;;;;;;;;;;iBA+VgB,WAAA,CACd,WAAA,UACA,KAAA,EAAO,eAAA,EACP,IAAA,EAAM,QAAA,EACN,MAAA,EAAQ,iBAAA,GACP,OAAA;AAAA,iBACa,WAAA,CACd,MAAA,EAAQ,UAAA,EACR,KAAA,EAAO,eAAA,EACP,IAAA,EAAM,QAAA,EACN,MAAA,EAAQ,iBAAA,GACP,OAAA;AAAA,iBA0QmB,WAAA,CACpB,WAAA,UACA,KAAA,EAAO,eAAA,EACP,IAAA;EAAQ,MAAA;EAAgB,OAAA;EAAkB,IAAA;AAAA,IACzC,OAAA"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as readJson, s as writeJson, t as contentrainDir } from "./fs-
|
|
3
|
-
import { t as readConfig } from "./config-
|
|
4
|
-
import { c as listModels, i as countEntries, l as readModel } from "./model-manager-DgyKMjLN.mjs";
|
|
1
|
+
import { c as listModels, i as countEntries, l as readModel } from "./model-manager-DqwL8ptm.mjs";
|
|
2
|
+
import { a as readJson, s as writeJson, t as contentrainDir } from "./fs-DJv5G8uL.mjs";
|
|
3
|
+
import { t as readConfig } from "./config-B8a4JBT1.mjs";
|
|
5
4
|
import { join } from "node:path";
|
|
5
|
+
import { canonicalStringify as canonicalStringify$1, parseMarkdownFrontmatter as parseMarkdownFrontmatter$1, serializeMarkdownFrontmatter as serializeMarkdownFrontmatter$1 } from "@contentrain/types";
|
|
6
6
|
//#region src/core/context.ts
|
|
7
7
|
const CONTEXT_PATH = ".contentrain/context.json";
|
|
8
8
|
async function readContext(input) {
|
|
@@ -90,7 +90,7 @@ async function buildContextChange(reader, operation, source, opts) {
|
|
|
90
90
|
}
|
|
91
91
|
return {
|
|
92
92
|
path: CONTEXT_PATH,
|
|
93
|
-
content: canonicalStringify({
|
|
93
|
+
content: canonicalStringify$1({
|
|
94
94
|
version: "1",
|
|
95
95
|
lastOperation: {
|
|
96
96
|
tool: operation.tool,
|
|
@@ -110,6 +110,6 @@ async function buildContextChange(reader, operation, source, opts) {
|
|
|
110
110
|
};
|
|
111
111
|
}
|
|
112
112
|
//#endregion
|
|
113
|
-
export { readContext as n, writeContext as r, buildContextChange as t };
|
|
113
|
+
export { serializeMarkdownFrontmatter$1 as a, parseMarkdownFrontmatter$1 as i, readContext as n, canonicalStringify$1 as o, writeContext as r, buildContextChange as t };
|
|
114
114
|
|
|
115
|
-
//# sourceMappingURL=context-
|
|
115
|
+
//# sourceMappingURL=context-CxpTATh4.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-CxpTATh4.mjs","names":["canonicalStringify"],"sources":["../src/core/context.ts"],"sourcesContent":["import type { ContextJson, ContextSource } from '@contentrain/types'\nimport { join } from 'node:path'\nimport { contentrainDir, readJson, writeJson } from '../util/fs.js'\nimport type { FileChange, RepoReader } from './contracts/index.js'\nimport { canonicalStringify } from './serialization/index.js'\nimport { listModels, readModel, countEntries } from './model-manager.js'\nimport { readConfig } from './config.js'\n\nconst CONTEXT_PATH = '.contentrain/context.json'\n\n/**\n * Pre-computed stats a caller can pass to {@link buildContextChange} to skip\n * the model/entry scan. `entries` is nullable — a `null` is dropped from the\n * emitted context.json by {@link canonicalStringify}, exactly as a failed\n * scan is today.\n */\nexport interface ContextStats {\n models: number\n entries: number | null\n}\n\n/**\n * Read the committed `.contentrain/context.json` payload written by the\n * most recent content or model operation. Returns `null` when the file\n * does not exist (fresh project, or reader lookup failure).\n *\n * Dual signature — the local flow passes a `projectRoot` string, remote\n * flows (GitHubProvider, GitLabProvider, any custom `RepoReader`) pass\n * the reader directly so `contentrain_status` over HTTP can still\n * report the last operation + stats.\n */\nexport function readContext(projectRoot: string): Promise<ContextJson | null>\nexport function readContext(reader: RepoReader): Promise<ContextJson | null>\nexport async function readContext(input: string | RepoReader): Promise<ContextJson | null> {\n if (typeof input === 'string') {\n return readJson<ContextJson>(join(contentrainDir(input), 'context.json'))\n }\n try {\n const raw = await input.readFile(CONTEXT_PATH)\n return JSON.parse(raw) as ContextJson\n } catch {\n return null\n }\n}\n\nfunction resolveSource(explicit?: ContextSource): ContextSource {\n if (explicit) return explicit\n return process.env['CONTENTRAIN_SOURCE'] === 'mcp-studio' ? 'mcp-studio' : 'mcp-local'\n}\n\nasync function computeEntriesCount(projectRoot: string): Promise<number | null> {\n try {\n const models = await listModels(projectRoot)\n const fullModels = await Promise.all(models.map(m => readModel(projectRoot, m.id)))\n const counts = await Promise.all(\n fullModels\n .filter((m): m is NonNullable<typeof m> => m !== null)\n .map(m => countEntries(projectRoot, m)),\n )\n return counts.reduce((acc, c) => acc + c.total, 0)\n } catch {\n return null\n }\n}\n\nexport async function writeContext(\n projectRoot: string,\n operation: { tool: string, model: string, locale?: string, entries?: string[] },\n): Promise<void> {\n const models = await listModels(projectRoot)\n const config = await readConfig(projectRoot)\n const locales = config?.locales.supported ?? ['en']\n const totalEntries = await computeEntriesCount(projectRoot)\n const source = resolveSource()\n\n const context: ContextJson = {\n version: '1',\n lastOperation: {\n tool: operation.tool,\n model: operation.model,\n locale: operation.locale ?? config?.locales.default ?? 'en',\n entries: operation.entries,\n timestamp: new Date().toISOString(),\n source,\n },\n stats: {\n models: models.length,\n entries: totalEntries as number,\n locales,\n lastSync: new Date().toISOString(),\n },\n }\n\n await writeJson(join(contentrainDir(projectRoot), 'context.json'), context)\n}\n\n/**\n * Build a FileChange for `.contentrain/context.json` that remote providers\n * (GitHubProvider over HTTP, for example) can slot into their plan. The\n * local write path still uses {@link writeContext} directly because its\n * transaction layer writes into the post-apply worktree with real stats.\n *\n * Remote providers (Phase 5.5+) now also get accurate entry counts: the\n * reader-based {@link countEntries} walks each model over the provider's\n * read surface. GitHubProvider pays an extra round trip per model; the\n * payoff is a context.json that matches what the local write path emits,\n * so cross-provider merges stay deterministic.\n *\n * A caller that already knows the model/entry counts (e.g. Studio deriving\n * them from its own index) can pass `opts.stats` to skip that O(models·\n * locales) scan entirely — only `readConfig` remains, for the locale list\n * and the `lastOperation.locale` default. The emitted context.json is\n * byte-identical to the scanned variant for the same logical state.\n */\nexport async function buildContextChange(\n reader: RepoReader,\n operation: { tool: string, model: string, locale?: string, entries?: string[] },\n source?: ContextSource,\n opts?: { stats?: ContextStats },\n): Promise<FileChange> {\n const config = await readConfig(reader)\n const locales = config?.locales.supported ?? ['en']\n\n let modelCount: number\n let totalEntries: number | null\n if (opts?.stats) {\n modelCount = opts.stats.models\n totalEntries = opts.stats.entries\n } else {\n const models = await listModels(reader)\n modelCount = models.length\n try {\n const fullModels = await Promise.all(models.map(m => readModel(reader, m.id)))\n const counts = await Promise.all(\n fullModels\n .filter((m): m is NonNullable<typeof m> => m !== null)\n .map(m => countEntries(reader, m)),\n )\n totalEntries = counts.reduce((acc, c) => acc + c.total, 0)\n } catch {\n totalEntries = null\n }\n }\n\n const context: ContextJson = {\n version: '1',\n lastOperation: {\n tool: operation.tool,\n model: operation.model,\n locale: operation.locale ?? config?.locales.default ?? 'en',\n entries: operation.entries,\n timestamp: new Date().toISOString(),\n source: resolveSource(source),\n },\n stats: {\n models: modelCount,\n entries: totalEntries as number,\n locales,\n lastSync: new Date().toISOString(),\n },\n }\n\n return {\n path: CONTEXT_PATH,\n content: canonicalStringify(context),\n }\n}\n"],"mappings":";;;;;;AAQA,MAAM,eAAe;AAyBrB,eAAsB,YAAY,OAAyD;AACzF,KAAI,OAAO,UAAU,SACnB,QAAO,SAAsB,KAAK,eAAe,MAAM,EAAE,eAAe,CAAC;AAE3E,KAAI;EACF,MAAM,MAAM,MAAM,MAAM,SAAS,aAAa;AAC9C,SAAO,KAAK,MAAM,IAAI;SAChB;AACN,SAAO;;;AAIX,SAAS,cAAc,UAAyC;AAC9D,KAAI,SAAU,QAAO;AACrB,QAAO,QAAQ,IAAI,0BAA0B,eAAe,eAAe;;AAG7E,eAAe,oBAAoB,aAA6C;AAC9E,KAAI;EACF,MAAM,SAAS,MAAM,WAAW,YAAY;EAC5C,MAAM,aAAa,MAAM,QAAQ,IAAI,OAAO,KAAI,MAAK,UAAU,aAAa,EAAE,GAAG,CAAC,CAAC;AAMnF,UALe,MAAM,QAAQ,IAC3B,WACG,QAAQ,MAAkC,MAAM,KAAK,CACrD,KAAI,MAAK,aAAa,aAAa,EAAE,CAAC,CAC1C,EACa,QAAQ,KAAK,MAAM,MAAM,EAAE,OAAO,EAAE;SAC5C;AACN,SAAO;;;AAIX,eAAsB,aACpB,aACA,WACe;CACf,MAAM,SAAS,MAAM,WAAW,YAAY;CAC5C,MAAM,SAAS,MAAM,WAAW,YAAY;CAC5C,MAAM,UAAU,QAAQ,QAAQ,aAAa,CAAC,KAAK;CACnD,MAAM,eAAe,MAAM,oBAAoB,YAAY;CAC3D,MAAM,SAAS,eAAe;CAE9B,MAAM,UAAuB;EAC3B,SAAS;EACT,eAAe;GACb,MAAM,UAAU;GAChB,OAAO,UAAU;GACjB,QAAQ,UAAU,UAAU,QAAQ,QAAQ,WAAW;GACvD,SAAS,UAAU;GACnB,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC;GACD;EACD,OAAO;GACL,QAAQ,OAAO;GACf,SAAS;GACT;GACA,2BAAU,IAAI,MAAM,EAAC,aAAa;GACnC;EACF;AAED,OAAM,UAAU,KAAK,eAAe,YAAY,EAAE,eAAe,EAAE,QAAQ;;;;;;;;;;;;;;;;;;;;AAqB7E,eAAsB,mBACpB,QACA,WACA,QACA,MACqB;CACrB,MAAM,SAAS,MAAM,WAAW,OAAO;CACvC,MAAM,UAAU,QAAQ,QAAQ,aAAa,CAAC,KAAK;CAEnD,IAAI;CACJ,IAAI;AACJ,KAAI,MAAM,OAAO;AACf,eAAa,KAAK,MAAM;AACxB,iBAAe,KAAK,MAAM;QACrB;EACL,MAAM,SAAS,MAAM,WAAW,OAAO;AACvC,eAAa,OAAO;AACpB,MAAI;GACF,MAAM,aAAa,MAAM,QAAQ,IAAI,OAAO,KAAI,MAAK,UAAU,QAAQ,EAAE,GAAG,CAAC,CAAC;AAM9E,mBALe,MAAM,QAAQ,IAC3B,WACG,QAAQ,MAAkC,MAAM,KAAK,CACrD,KAAI,MAAK,aAAa,QAAQ,EAAE,CAAC,CACrC,EACqB,QAAQ,KAAK,MAAM,MAAM,EAAE,OAAO,EAAE;UACpD;AACN,kBAAe;;;AAsBnB,QAAO;EACL,MAAM;EACN,SAASA,qBApBkB;GAC3B,SAAS;GACT,eAAe;IACb,MAAM,UAAU;IAChB,OAAO,UAAU;IACjB,QAAQ,UAAU,UAAU,QAAQ,QAAQ,WAAW;IACvD,SAAS,UAAU;IACnB,4BAAW,IAAI,MAAM,EAAC,aAAa;IACnC,QAAQ,cAAc,OAAO;IAC9B;GACD,OAAO;IACL,QAAQ;IACR,SAAS;IACT;IACA,2BAAU,IAAI,MAAM,EAAC,aAAa;IACnC;GACF,CAIqC;EACrC"}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import "../
|
|
2
|
-
import "../
|
|
3
|
-
import "../
|
|
4
|
-
import "../
|
|
5
|
-
import "../config-
|
|
6
|
-
import "../
|
|
7
|
-
import "../
|
|
8
|
-
import "../
|
|
9
|
-
import "../
|
|
10
|
-
import "../
|
|
11
|
-
import { a as detectFileFramework, c as validatePatchPath, i as checkSyntax, n as applyExtract, o as replaceInLine, r as applyReuse, s as validateFrameworkExpression, t as PATCHABLE_EXTENSIONS } from "../apply-manager-BybvnUVC.mjs";
|
|
1
|
+
import "../context-CxpTATh4.mjs";
|
|
2
|
+
import "../model-manager-DqwL8ptm.mjs";
|
|
3
|
+
import "../fs-DJv5G8uL.mjs";
|
|
4
|
+
import "../meta-manager-g3shoZES.mjs";
|
|
5
|
+
import "../config-B8a4JBT1.mjs";
|
|
6
|
+
import "../identity-CxAB9Qb8.mjs";
|
|
7
|
+
import "../branch-lifecycle-DUOoyNWn.mjs";
|
|
8
|
+
import "../id-CjGMPP1k.mjs";
|
|
9
|
+
import "../transaction-BxDiiakv.mjs";
|
|
10
|
+
import { a as detectFileFramework, c as validatePatchPath, i as checkSyntax, n as applyExtract, o as replaceInLine, r as applyReuse, s as validateFrameworkExpression, t as PATCHABLE_EXTENSIONS } from "../apply-manager-DsNq7Zhm.mjs";
|
|
12
11
|
export { PATCHABLE_EXTENSIONS, applyExtract, applyReuse, checkSyntax, detectFileFramework, replaceInLine, validateFrameworkExpression, validatePatchPath };
|
package/dist/core/config.d.mts
CHANGED
package/dist/core/config.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import "../fs-
|
|
2
|
-
import { n as readVocabulary, t as readConfig } from "../config-
|
|
1
|
+
import "../fs-DJv5G8uL.mjs";
|
|
2
|
+
import { n as readVocabulary, t as readConfig } from "../config-B8a4JBT1.mjs";
|
|
3
3
|
export { readConfig, readVocabulary };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as validateEntryId, a as ListOpts, b as writeContent, c as deleteContent, d as readContent, f as resolveContentDir, g as serializeFrontmatter, h as resolveMdFilePath, i as DeleteOpts, l as listContent, m as resolveLocaleStrategy, n as ContentFileModel, o as LocaleStrategyModel, p as resolveJsonFilePath, r as ContentPathModel, s as WriteResult, t as ContentEntry, u as parseFrontmatter, v as validateLocale, y as validateSlug } from "../content-manager-
|
|
1
|
+
import { _ as validateEntryId, a as ListOpts, b as writeContent, c as deleteContent, d as readContent, f as resolveContentDir, g as serializeFrontmatter, h as resolveMdFilePath, i as DeleteOpts, l as listContent, m as resolveLocaleStrategy, n as ContentFileModel, o as LocaleStrategyModel, p as resolveJsonFilePath, r as ContentPathModel, s as WriteResult, t as ContentEntry, u as parseFrontmatter, v as validateLocale, y as validateSlug } from "../content-manager-Bx94DXSF.mjs";
|
|
2
2
|
export { ContentEntry, ContentFileModel, ContentPathModel, DeleteOpts, ListOpts, LocaleStrategyModel, WriteResult, deleteContent, listContent, parseFrontmatter, readContent, resolveContentDir, resolveJsonFilePath, resolveLocaleStrategy, resolveMdFilePath, serializeFrontmatter, validateEntryId, validateLocale, validateSlug, writeContent };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "../
|
|
2
|
-
import "../
|
|
3
|
-
import
|
|
1
|
+
import { C as validateLocale, S as validateEntryId, T as writeContent, _ as resolveContentDir, b as resolveMdFilePath, g as readContent, h as parseFrontmatter, m as listContent, p as deleteContent, v as resolveJsonFilePath, w as validateSlug, x as serializeFrontmatter, y as resolveLocaleStrategy } from "../model-manager-DqwL8ptm.mjs";
|
|
2
|
+
import "../fs-DJv5G8uL.mjs";
|
|
3
|
+
import "../meta-manager-g3shoZES.mjs";
|
|
4
4
|
export { deleteContent, listContent, parseFrontmatter, readContent, resolveContentDir, resolveJsonFilePath, resolveLocaleStrategy, resolveMdFilePath, serializeFrontmatter, validateEntryId, validateLocale, validateSlug, writeContent };
|
package/dist/core/context.d.mts
CHANGED
package/dist/core/context.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import "../
|
|
2
|
-
import "../
|
|
3
|
-
import "../
|
|
4
|
-
import "../
|
|
5
|
-
import "../
|
|
6
|
-
import { n as readContext, r as writeContext, t as buildContextChange } from "../context-C3x6I3cE.mjs";
|
|
1
|
+
import { n as readContext, r as writeContext, t as buildContextChange } from "../context-CxpTATh4.mjs";
|
|
2
|
+
import "../model-manager-DqwL8ptm.mjs";
|
|
3
|
+
import "../fs-DJv5G8uL.mjs";
|
|
4
|
+
import "../meta-manager-g3shoZES.mjs";
|
|
5
|
+
import "../config-B8a4JBT1.mjs";
|
|
7
6
|
export { buildContextChange, readContext, writeContext };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as RepoReader, a as FileChange, c as MediaAsset, d as MediaListResult, f as MediaProvider, g as RepoProvider, h as ProviderCapabilities, i as CommitAuthor, l as MediaIngestInput, m as MergeResult, n as Branch, o as FileDiff, p as MediaUpdateInput, r as Commit, s as LOCAL_CAPABILITIES, t as ApplyPlanInput, u as MediaListOptions, v as RepoWriter, y as WriteReadiness } from "../../index-
|
|
1
|
+
import { _ as RepoReader, a as FileChange, c as MediaAsset, d as MediaListResult, f as MediaProvider, g as RepoProvider, h as ProviderCapabilities, i as CommitAuthor, l as MediaIngestInput, m as MergeResult, n as Branch, o as FileDiff, p as MediaUpdateInput, r as Commit, s as LOCAL_CAPABILITIES, t as ApplyPlanInput, u as MediaListOptions, v as RepoWriter, y as WriteReadiness } from "../../index-ByrVsRJE.mjs";
|
|
2
2
|
export { ApplyPlanInput, Branch, Commit, CommitAuthor, FileChange, FileDiff, LOCAL_CAPABILITIES, MediaAsset, MediaIngestInput, MediaListOptions, MediaListResult, MediaProvider, MediaUpdateInput, MergeResult, ProviderCapabilities, RepoProvider, RepoReader, RepoWriter, WriteReadiness };
|
package/dist/core/doctor.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import "../
|
|
2
|
-
import "../
|
|
3
|
-
import "../
|
|
4
|
-
import "../config-
|
|
5
|
-
import "../
|
|
6
|
-
import "../
|
|
7
|
-
import "../scan-config-
|
|
8
|
-
import { t as runDoctor } from "../doctor-
|
|
1
|
+
import "../model-manager-DqwL8ptm.mjs";
|
|
2
|
+
import "../fs-DJv5G8uL.mjs";
|
|
3
|
+
import "../meta-manager-g3shoZES.mjs";
|
|
4
|
+
import "../config-B8a4JBT1.mjs";
|
|
5
|
+
import "../identity-CxAB9Qb8.mjs";
|
|
6
|
+
import "../branch-lifecycle-DUOoyNWn.mjs";
|
|
7
|
+
import "../scan-config-C5zzygeH.mjs";
|
|
8
|
+
import { t as runDoctor } from "../doctor-B7G0oFxO.mjs";
|
|
9
9
|
export { runDoctor };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "../fs-
|
|
2
|
-
import "../scan-config-
|
|
3
|
-
import { t as buildGraph } from "../graph-builder-
|
|
1
|
+
import "../fs-DJv5G8uL.mjs";
|
|
2
|
+
import "../scan-config-C5zzygeH.mjs";
|
|
3
|
+
import { t as buildGraph } from "../graph-builder-C9NS7y-a.mjs";
|
|
4
4
|
export { buildGraph };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import "../fs-
|
|
2
|
-
import { a as writeMeta, i as readMeta, n as deleteMeta, o as writeMetaEntries, r as mergeEntryMeta, t as applyStatusChange } from "../meta-manager-
|
|
1
|
+
import "../fs-DJv5G8uL.mjs";
|
|
2
|
+
import { a as writeMeta, i as readMeta, n as deleteMeta, o as writeMetaEntries, r as mergeEntryMeta, t as applyStatusChange } from "../meta-manager-g3shoZES.mjs";
|
|
3
3
|
export { applyStatusChange, deleteMeta, mergeEntryMeta, readMeta, writeMeta, writeMetaEntries };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "../
|
|
2
|
-
import "../
|
|
3
|
-
import
|
|
1
|
+
import { a as deleteModel, c as listModels, d as validateModelDefinition, f as writeModel, i as countEntries, l as readModel, n as MODEL_FIELD_ORDER, o as fieldDefZodSchema, r as checkReferences, s as inferTitleField, t as FIELD_TYPE_ENUM, u as titleFieldIssues } from "../model-manager-DqwL8ptm.mjs";
|
|
2
|
+
import "../fs-DJv5G8uL.mjs";
|
|
3
|
+
import "../meta-manager-g3shoZES.mjs";
|
|
4
4
|
export { FIELD_TYPE_ENUM, MODEL_FIELD_ORDER, checkReferences, countEntries, deleteModel, fieldDefZodSchema, inferTitleField, listModels, readModel, titleFieldIssues, validateModelDefinition, writeModel };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { _ as RepoReader, a as FileChange } from "../../index-
|
|
2
|
-
import { t as ContentEntry } from "../../content-manager-
|
|
1
|
+
import { _ as RepoReader, a as FileChange } from "../../index-ByrVsRJE.mjs";
|
|
2
|
+
import { t as ContentEntry } from "../../content-manager-Bx94DXSF.mjs";
|
|
3
|
+
import { a as ContentSaveEntryResult, i as ReconcileResult, n as ReconcileInput, o as ContentSavePlan, r as ReconcilePlan, s as OpPlan, t as planReconcile } from "../../index-_HJVkDJa.mjs";
|
|
3
4
|
import { ContentrainConfig, ModelDefinition, Vocabulary } from "@contentrain/types";
|
|
4
5
|
|
|
5
6
|
//#region src/core/ops/apply-to-worktree.d.ts
|
|
@@ -19,32 +20,6 @@ import { ContentrainConfig, ModelDefinition, Vocabulary } from "@contentrain/typ
|
|
|
19
20
|
*/
|
|
20
21
|
declare function applyChangesToWorktree(worktree: string, changes: readonly FileChange[]): Promise<void>;
|
|
21
22
|
//#endregion
|
|
22
|
-
//#region src/core/ops/types.d.ts
|
|
23
|
-
/**
|
|
24
|
-
* Generic plan envelope. Every `planXxx` operation in `core/ops/` returns
|
|
25
|
-
* this shape: a set of atomic file changes plus a typed result payload. The
|
|
26
|
-
* caller (tool handler or Studio engine) applies the changes through a
|
|
27
|
-
* `RepoProvider` and uses `result` for the tool response.
|
|
28
|
-
*
|
|
29
|
-
* See `.internal/refactor/00-principles.md` §5.1 for the plan/apply pattern.
|
|
30
|
-
*/
|
|
31
|
-
interface OpPlan<TResult = unknown> {
|
|
32
|
-
/** File additions, modifications and deletions, sorted by path for determinism. */
|
|
33
|
-
changes: FileChange[];
|
|
34
|
-
/** Operation-specific result payload (IDs of entries touched, etc.). */
|
|
35
|
-
result: TResult;
|
|
36
|
-
/** Soft warnings the caller should surface to the user. */
|
|
37
|
-
advisories: string[];
|
|
38
|
-
}
|
|
39
|
-
interface ContentSaveEntryResult {
|
|
40
|
-
action: 'created' | 'updated';
|
|
41
|
-
id?: string;
|
|
42
|
-
slug?: string;
|
|
43
|
-
locale: string;
|
|
44
|
-
advisories?: string[];
|
|
45
|
-
}
|
|
46
|
-
type ContentSavePlan = OpPlan<ContentSaveEntryResult[]>;
|
|
47
|
-
//#endregion
|
|
48
23
|
//#region src/core/ops/content-delete.d.ts
|
|
49
24
|
interface ContentDeleteInput {
|
|
50
25
|
model: ModelDefinition;
|
|
@@ -173,6 +148,19 @@ declare function documentFilePath(model: Pick<ModelDefinition, 'id' | 'domain' |
|
|
|
173
148
|
*/
|
|
174
149
|
declare function metaFilePath(model: Pick<ModelDefinition, 'id' | 'kind' | 'i18n'>, locale: string, defaultLocale: string, slug?: string): string;
|
|
175
150
|
//#endregion
|
|
151
|
+
//#region src/core/bind-ref.d.ts
|
|
152
|
+
/**
|
|
153
|
+
* Pin a `RepoReader` to one ref. The reconcile planner takes three of these
|
|
154
|
+
* (merge-base / contentrain / base branch) and stays entirely ignorant of
|
|
155
|
+
* refs — executors and tools decide what to bind, the planner just reads.
|
|
156
|
+
*
|
|
157
|
+
* For readers that honour the per-call `ref?` parameter (GitHub, GitLab)
|
|
158
|
+
* this is the whole story; a reader that ignores it (LocalReader reads the
|
|
159
|
+
* working tree) needs a ref-aware implementation instead — see
|
|
160
|
+
* `git/ref-reader.ts`.
|
|
161
|
+
*/
|
|
162
|
+
declare function bindRef(reader: RepoReader, ref: string): RepoReader;
|
|
163
|
+
//#endregion
|
|
176
164
|
//#region src/core/ops/vocabulary-save.d.ts
|
|
177
165
|
interface VocabularySaveInput {
|
|
178
166
|
/**
|
|
@@ -210,5 +198,5 @@ declare function planVocabularySave(reader: RepoReader, input: VocabularySaveInp
|
|
|
210
198
|
/** Build the FileChange[] to remove vocabulary terms. */
|
|
211
199
|
declare function planVocabularyDelete(reader: RepoReader, input: VocabularyDeleteInput): Promise<VocabularyDeletePlan>;
|
|
212
200
|
//#endregion
|
|
213
|
-
export { type ContentDeleteInput, type ContentDeletePlan, type ContentSaveEntryResult, type ContentSavePlan, type ModelDeleteInput, type ModelDeletePlan, type ModelSaveInput, type ModelSavePlan, type ModelSaveResult, type OpPlan, type VocabularyDeleteInput, type VocabularyDeletePlan, type VocabularySaveInput, type VocabularySavePlan, applyChangesToWorktree, contentDirPath, contentFilePath, documentFilePath, metaFilePath, planContentDelete, planContentSave, planModelDelete, planModelSave, planVocabularyDelete, planVocabularySave };
|
|
201
|
+
export { type ContentDeleteInput, type ContentDeletePlan, type ContentSaveEntryResult, type ContentSavePlan, type ModelDeleteInput, type ModelDeletePlan, type ModelSaveInput, type ModelSavePlan, type ModelSaveResult, type OpPlan, type ReconcileInput, type ReconcilePlan, type ReconcileResult, type VocabularyDeleteInput, type VocabularyDeletePlan, type VocabularySaveInput, type VocabularySavePlan, applyChangesToWorktree, bindRef, contentDirPath, contentFilePath, documentFilePath, metaFilePath, planContentDelete, planContentSave, planModelDelete, planModelSave, planReconcile, planVocabularyDelete, planVocabularySave };
|
|
214
202
|
//# sourceMappingURL=index.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/core/ops/apply-to-worktree.ts","../../../src/core/ops/
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/core/ops/apply-to-worktree.ts","../../../src/core/ops/content-delete.ts","../../../src/core/ops/content-save.ts","../../../src/core/ops/model-delete.ts","../../../src/core/ops/model-save.ts","../../../src/core/ops/paths.ts","../../../src/core/bind-ref.ts","../../../src/core/ops/vocabulary-save.ts"],"mappings":";;;;;;;;;;;AAkBA;;;;;;;;;iBAAsB,sBAAA,CAAuB,QAAA,UAAkB,OAAA,WAAkB,UAAA,KAAe,OAAA;;;UCX/E,kBAAA;EACf,KAAA,EAAO,eAAA;EACP,EAAA;EACA,IAAA;EACA,MAAA;EACA,IAAA;EDMqG;;;;ECDrG,aAAA;AAAA;AAAA,KAGU,iBAAA,GAAoB,MAAA;;;;AAbhC;;;;;;;;;;iBAuDsB,iBAAA,CACpB,MAAA,EAAQ,UAAA,EACR,KAAA,EAAO,kBAAA,GACN,OAAA,CAAQ,iBAAA;;;UCpDD,SAAA;EACR,KAAA,EAAO,eAAA;EACP,OAAA,EAAS,YAAA;EACT,MAAA,EAAQ,iBAAA;EACR,UAAA,GAAa,UAAA;EFCwF;;;;;;EEMrG,YAAA;AAAA;;;ADjBF;;;;;;;iBC6BsB,eAAA,CAAgB,MAAA,EAAQ,UAAA,EAAY,KAAA,EAAO,SAAA,GAAY,OAAA,CAAQ,eAAA;;;UChCpE,gBAAA;EACf,KAAA,EAAO,eAAA;AAAA;AAAA,KAGG,eAAA,GAAkB,MAAA;;;;;;;;;;;;;AFD9B;;iBEiBsB,eAAA,CAAgB,MAAA,EAAQ,UAAA,EAAY,KAAA,EAAO,gBAAA,GAAmB,OAAA,CAAQ,eAAA;;;UClB3E,cAAA;EACf,KAAA,EAAO,eAAA;AAAA;AAAA,UAGQ,eAAA;EACf,MAAA;EACA,EAAA;AAAA;AAAA,KAGU,aAAA,GAAgB,MAAA,CAAO,eAAA;;;;;;;;;AHRnC;iBGmBsB,aAAA,CAAc,MAAA,EAAQ,UAAA,EAAY,KAAA,EAAO,cAAA,GAAiB,OAAA,CAAQ,aAAA;;;;;;;;AJRxF;;;;;;;;;;;;iBKEgB,cAAA,CACd,KAAA,EAAO,IAAA,CAAK,eAAA;AAAA,iBAUE,eAAA,CACd,KAAA,EAAO,IAAA,CAAK,eAAA,2EACZ,MAAA;AAAA,iBAac,gBAAA,CACd,KAAA,EAAO,IAAA,CAAK,eAAA,kEACZ,MAAA,UACA,IAAA;;;;;;;;;;;iBAuBc,YAAA,CACd,KAAA,EAAO,IAAA,CAAK,eAAA,2BACZ,MAAA,UACA,aAAA,UACA,IAAA;;;;;;;;AL1DF;;;;;iBMNgB,OAAA,CAAQ,MAAA,EAAQ,UAAA,EAAY,GAAA,WAAc,UAAA;;;UCFzC,mBAAA;;;;APQjB;;EOFE,KAAA,EAAO,MAAA,SAAe,MAAA;AAAA;AAAA,UAGP,qBAAA;EPDgE;EOG/E,KAAA;AAAA;AAAA,UAGe,oBAAA;EACf,KAAA;EACA,OAAA;EACA,KAAA;AAAA;AAAA,UAGe,sBAAA;EACf,OAAA;EACA,OAAA;EACA,KAAA;AAAA;AAAA,KAGU,kBAAA,GAAqB,MAAA,CAAO,oBAAA;AAAA,KAC5B,oBAAA,GAAuB,MAAA,CAAO,sBAAA;;;;;;;ANjB1C;;iBM2EsB,kBAAA,CACpB,MAAA,EAAQ,UAAA,EACR,KAAA,EAAO,mBAAA,GACN,OAAA,CAAQ,kBAAA;;iBA2DW,oBAAA,CACpB,MAAA,EAAQ,UAAA,EACR,KAAA,EAAO,qBAAA,GACN,OAAA,CAAQ,oBAAA"}
|
package/dist/core/ops/index.mjs
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import "../../
|
|
3
|
-
import {
|
|
4
|
-
import "../../
|
|
5
|
-
import "../../
|
|
6
|
-
|
|
1
|
+
import { n as applyChangesToWorktree, t as planReconcile } from "../../reconcile-D5FTVW5z.mjs";
|
|
2
|
+
import "../../context-CxpTATh4.mjs";
|
|
3
|
+
import { A as metaFilePath, D as contentDirPath, O as contentFilePath, k as documentFilePath } from "../../model-manager-DqwL8ptm.mjs";
|
|
4
|
+
import { a as planModelDelete, i as planModelSave, n as planVocabularySave, o as planContentSave, r as bindRef, s as planContentDelete, t as planVocabularyDelete } from "../../ops-BfrdZ6GK.mjs";
|
|
5
|
+
import "../../fs-DJv5G8uL.mjs";
|
|
6
|
+
import "../../meta-manager-g3shoZES.mjs";
|
|
7
|
+
import "../../config-B8a4JBT1.mjs";
|
|
8
|
+
import "../../validator-B2GhPM3L.mjs";
|
|
9
|
+
export { applyChangesToWorktree, bindRef, contentDirPath, contentFilePath, documentFilePath, metaFilePath, planContentDelete, planContentSave, planModelDelete, planModelSave, planReconcile, planVocabularyDelete, planVocabularySave };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as OverlayReader } from "../overlay-reader-
|
|
1
|
+
import { t as OverlayReader } from "../overlay-reader-Bx1YxGXq.mjs";
|
|
2
2
|
export { OverlayReader };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import "../fs-
|
|
2
|
-
import { a as classifyFile, i as autoDetectSourceDirs, n as SCAN_EXTENSIONS, o as discoverFiles, r as SCAN_IGNORE_DIRS, t as MAX_SCAN_FILES } from "../scan-config-
|
|
1
|
+
import "../fs-DJv5G8uL.mjs";
|
|
2
|
+
import { a as classifyFile, i as autoDetectSourceDirs, n as SCAN_EXTENSIONS, o as discoverFiles, r as SCAN_IGNORE_DIRS, t as MAX_SCAN_FILES } from "../scan-config-C5zzygeH.mjs";
|
|
3
3
|
export { MAX_SCAN_FILES, SCAN_EXTENSIONS, SCAN_IGNORE_DIRS, autoDetectSourceDirs, classifyFile, discoverFiles };
|
package/dist/core/scanner.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "../fs-
|
|
2
|
-
import "../scan-config-
|
|
3
|
-
import { n as scanSummary, t as scanCandidates } from "../scanner-
|
|
4
|
-
import "../tsx-parser-
|
|
1
|
+
import "../fs-DJv5G8uL.mjs";
|
|
2
|
+
import "../scan-config-C5zzygeH.mjs";
|
|
3
|
+
import { n as scanSummary, t as scanCandidates } from "../scanner-CEiT8Tgx.mjs";
|
|
4
|
+
import "../tsx-parser-go5V9zoc.mjs";
|
|
5
5
|
export { scanCandidates, scanSummary };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as RepoReader } from "../../index-
|
|
1
|
+
import { _ as RepoReader } from "../../index-ByrVsRJE.mjs";
|
|
2
2
|
import { EntryMeta, FieldDef, ModelDefinition, ValidationError, ValidationResult } from "@contentrain/types";
|
|
3
3
|
|
|
4
4
|
//#region src/core/validator/entry.d.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "../../
|
|
2
|
-
import "../../
|
|
3
|
-
import "../../
|
|
4
|
-
import "../../
|
|
5
|
-
import { i as validateContent, n as validateScheduleFields, r as checkRelationIntegrity, t as validateProject } from "../../validator-
|
|
1
|
+
import "../../model-manager-DqwL8ptm.mjs";
|
|
2
|
+
import "../../fs-DJv5G8uL.mjs";
|
|
3
|
+
import "../../meta-manager-g3shoZES.mjs";
|
|
4
|
+
import "../../config-B8a4JBT1.mjs";
|
|
5
|
+
import { i as validateContent, n as validateScheduleFields, r as checkRelationIntegrity, t as validateProject } from "../../validator-B2GhPM3L.mjs";
|
|
6
6
|
export { checkRelationIntegrity, validateContent, validateProject, validateScheduleFields };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as readJson, o as readText, r as pathExists } from "./fs-
|
|
1
|
+
import { a as readJson, o as readText, r as pathExists } from "./fs-DJv5G8uL.mjs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import { readdir } from "node:fs/promises";
|
|
4
4
|
//#region src/util/detect.ts
|
|
@@ -452,4 +452,4 @@ async function collectAllDeps(projectRoot) {
|
|
|
452
452
|
//#endregion
|
|
453
453
|
export { detectStackInfo as n, inferPlatform as r, detectStack as t };
|
|
454
454
|
|
|
455
|
-
//# sourceMappingURL=detect-
|
|
455
|
+
//# sourceMappingURL=detect-CI32ynpq.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detect-B0oXbQaP.mjs","names":[],"sources":["../src/util/detect.ts"],"sourcesContent":["import type { StackType, Platform } from '@contentrain/types'\nimport { join, dirname } from 'node:path'\nimport { readdir } from 'node:fs/promises'\nimport { readJson, pathExists, readText } from './fs.js'\n\ninterface PackageJson {\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n workspaces?: string[] | { packages: string[] }\n}\n\nexport interface StackInfo {\n stack: StackType\n platform: Platform\n name: string\n description: string\n monorepo: boolean\n monorepoTool?: string\n features: string[]\n}\n\nconst STACK_META: Record<StackType, { name: string; description: string }> = {\n // Meta-frameworks\n nuxt: { name: 'Nuxt', description: 'Vue meta-framework with SSR/SSG' },\n next: { name: 'Next.js', description: 'React framework with SSR/SSG' },\n astro: { name: 'Astro', description: 'Content-first web framework' },\n sveltekit: { name: 'SvelteKit', description: 'Svelte meta-framework' },\n remix: { name: 'Remix', description: 'Full-stack React framework' },\n analog: { name: 'Analog', description: 'Angular meta-framework' },\n // Plain frameworks\n vue: { name: 'Vue', description: 'Progressive JavaScript framework' },\n react: { name: 'React', description: 'UI library for web and native' },\n svelte: { name: 'Svelte', description: 'Compile-time UI framework' },\n solid: { name: 'Solid', description: 'Reactive UI library' },\n angular: { name: 'Angular', description: 'Platform for web applications' },\n // Mobile\n 'react-native': { name: 'React Native', description: 'Cross-platform mobile framework' },\n expo: { name: 'Expo', description: 'React Native toolchain' },\n flutter: { name: 'Flutter', description: 'Cross-platform UI toolkit (Dart)' },\n // Backend\n node: { name: 'Node.js', description: 'Server-side JavaScript runtime' },\n express: { name: 'Express', description: 'Minimal Node.js web framework' },\n fastify: { name: 'Fastify', description: 'Fast Node.js web framework' },\n nestjs: { name: 'NestJS', description: 'Progressive Node.js framework' },\n django: { name: 'Django', description: 'Python web framework' },\n rails: { name: 'Rails', description: 'Ruby web framework' },\n laravel: { name: 'Laravel', description: 'PHP web framework' },\n go: { name: 'Go', description: 'Go programming language' },\n rust: { name: 'Rust', description: 'Rust programming language' },\n dotnet: { name: '.NET', description: 'Microsoft .NET platform' },\n // Static\n hugo: { name: 'Hugo', description: 'Go-based static site generator' },\n jekyll: { name: 'Jekyll', description: 'Ruby-based static site generator' },\n eleventy: { name: 'Eleventy', description: 'JavaScript static site generator' },\n // Desktop\n electron: { name: 'Electron', description: 'Cross-platform desktop apps' },\n tauri: { name: 'Tauri', description: 'Lightweight desktop apps (Rust)' },\n // Catch-all\n other: { name: 'Other', description: 'Unknown or unsupported framework' },\n}\n\nexport function inferPlatform(stack: StackType): Platform {\n switch (stack) {\n case 'nuxt': case 'next': case 'astro': case 'sveltekit': case 'remix': case 'analog':\n case 'vue': case 'react': case 'svelte': case 'solid': case 'angular':\n return 'web'\n case 'react-native': case 'expo': case 'flutter':\n return 'mobile'\n case 'node': case 'express': case 'fastify': case 'nestjs':\n case 'django': case 'rails': case 'laravel': case 'go': case 'rust': case 'dotnet':\n return 'api'\n case 'electron': case 'tauri':\n return 'desktop'\n case 'hugo': case 'jekyll': case 'eleventy':\n return 'static'\n default:\n return 'other'\n }\n}\n\n/** Backward-compatible: returns just the StackType string */\nexport async function detectStack(projectRoot: string): Promise<StackType> {\n const info = await detectStackInfo(projectRoot)\n return info.stack\n}\n\n/** Rich detection: stack + platform + monorepo + features */\nexport async function detectStackInfo(projectRoot: string): Promise<StackInfo> {\n let stack = await detectFromDeps(projectRoot)\n\n // Walk up for monorepo root if local didn't match\n if (stack === 'other') {\n let dir = dirname(projectRoot)\n for (let i = 0; i < 5; i++) {\n const pkg = await readJson<PackageJson>(join(dir, 'package.json'))\n if (pkg?.workspaces) {\n const rootStack = await detectFromDeps(dir)\n if (rootStack !== 'other') {\n stack = rootStack\n break\n }\n }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n }\n\n // Look DOWN into the workspaces. The walk above handles \"I am inside a\n // package, find the monorepo root\"; this handles the opposite and more\n // common case — projectRoot IS the monorepo root, whose package.json holds\n // only tooling (turbo, nx) while the frameworks live in apps/* and\n // packages/*. Without this a Next.js monorepo reports `other`, and the\n // stack is what picks the replacement conventions during normalize.\n if (stack === 'other') {\n stack = await detectFromWorkspaces(projectRoot)\n }\n\n // Non-JS detection if still 'other'\n if (stack === 'other') {\n stack = await detectNonJs(projectRoot)\n }\n\n const mono = await detectMonorepo(projectRoot)\n const features = await detectFeatures(projectRoot)\n const meta = STACK_META[stack]\n\n return {\n stack,\n platform: inferPlatform(stack),\n name: meta.name,\n description: meta.description,\n monorepo: mono.isMonorepo,\n monorepoTool: mono.tool,\n features,\n }\n}\n\nasync function detectFromDeps(dir: string): Promise<StackType> {\n const pkg = await readJson<PackageJson>(join(dir, 'package.json'))\n if (!pkg) return 'other'\n\n const allDeps = { ...pkg.dependencies, ...pkg.devDependencies }\n\n // Meta-frameworks (check BEFORE plain frameworks)\n if ('nuxt' in allDeps) return 'nuxt'\n if ('next' in allDeps) return 'next'\n if ('astro' in allDeps) return 'astro'\n if ('@sveltejs/kit' in allDeps) return 'sveltekit'\n if ('@remix-run/node' in allDeps || 'remix' in allDeps) return 'remix'\n if ('@analogjs/platform' in allDeps) return 'analog'\n\n // Mobile (check before plain react)\n if ('expo' in allDeps) return 'expo'\n if ('react-native' in allDeps) return 'react-native'\n\n // Plain frameworks\n if ('vue' in allDeps) return 'vue'\n if ('svelte' in allDeps) return 'svelte'\n if ('solid-js' in allDeps) return 'solid'\n if ('@angular/core' in allDeps) return 'angular'\n if ('react' in allDeps) return 'react'\n\n // Desktop\n if ('electron' in allDeps) return 'electron'\n if ('@tauri-apps/api' in allDeps) return 'tauri'\n\n // Backend (Node.js)\n if ('@nestjs/core' in allDeps) return 'nestjs'\n if ('fastify' in allDeps) return 'fastify'\n if ('express' in allDeps) return 'express'\n\n // Static site generators\n if ('@11ty/eleventy' in allDeps) return 'eleventy'\n\n // Generic Node.js (has package.json but no framework)\n if ('node' in (pkg.dependencies ?? {})) return 'node'\n\n return 'other'\n}\n\n/**\n * Ranked by how strongly the stack determines content conventions — a\n * meta-framework dictates the i18n setup and the replacement expression,\n * a plain UI library does not. Frequency would be the wrong tie-break: a\n * monorepo with one Next app and two React packages is a Next project.\n */\nconst STACK_PRIORITY: readonly StackType[] = [\n 'nuxt', 'next', 'astro', 'sveltekit', 'remix', 'analog',\n 'expo', 'react-native',\n 'vue', 'react', 'svelte', 'solid', 'angular',\n 'electron', 'tauri',\n 'nestjs', 'fastify', 'express',\n 'eleventy', 'node',\n]\n\n/** Cap the fan-out so a large monorepo cannot turn detection into a crawl. */\nconst MAX_WORKSPACE_DIRS = 50\n\n/**\n * Workspace globs from `pnpm-workspace.yaml` or the `workspaces` field.\n *\n * The pnpm file is parsed line by line rather than with a YAML library: we\n * need exactly one list of strings with a fixed shape, and a parser\n * dependency for that is not worth the install size.\n */\nasync function readWorkspacePatterns(root: string): Promise<string[]> {\n const pnpm = await readText(join(root, 'pnpm-workspace.yaml'))\n if (pnpm) {\n const patterns: string[] = []\n let inPackages = false\n for (const raw of pnpm.split('\\n')) {\n const line = raw.replace(/#.*$/, '').trimEnd()\n if (/^packages:\\s*$/.test(line)) { inPackages = true; continue }\n if (!inPackages) continue\n const item = /^\\s+-\\s*['\"]?([^'\"]+?)['\"]?\\s*$/.exec(line)\n if (item?.[1]) { patterns.push(item[1]); continue }\n if (line.trim() !== '') break // a new top-level key ends the list\n }\n if (patterns.length > 0) return patterns\n }\n\n const pkg = await readJson<PackageJson>(join(root, 'package.json'))\n const ws = pkg?.workspaces\n if (Array.isArray(ws)) return ws\n if (ws && Array.isArray(ws.packages)) return ws.packages\n return []\n}\n\n/**\n * Expand workspace patterns to directories. Only a trailing `*` segment is\n * expanded — that covers `apps/*` and `packages/*`, which is what real\n * workspace files use. Deeper globs and negations are skipped rather than\n * half-supported.\n */\nasync function listWorkspaceDirs(root: string): Promise<string[]> {\n const patterns = (await readWorkspacePatterns(root)).filter(p => !p.startsWith('!'))\n\n const expanded = await Promise.all(patterns.map(async (pattern) => {\n const star = pattern.indexOf('*')\n if (star === -1) return [join(root, pattern)]\n const base = join(root, pattern.slice(0, star).replace(/\\/+$/, ''))\n try {\n const entries = await readdir(base, { withFileTypes: true })\n return entries.filter(e => e.isDirectory()).map(e => join(base, e.name))\n } catch {\n return []\n }\n }))\n\n return expanded.flat().slice(0, MAX_WORKSPACE_DIRS)\n}\n\n/** Highest-priority stack across the workspace packages. */\nasync function detectFromWorkspaces(root: string): Promise<StackType> {\n const dirs = await listWorkspaceDirs(root)\n if (dirs.length === 0) return 'other'\n\n const found = new Set(await Promise.all(dirs.map(d => detectFromDeps(d))))\n return STACK_PRIORITY.find(s => found.has(s)) ?? 'other'\n}\n\nasync function detectNonJs(projectRoot: string): Promise<StackType> {\n // Go\n if (await pathExists(join(projectRoot, 'go.mod'))) return 'go'\n\n // Rust\n if (await pathExists(join(projectRoot, 'Cargo.toml'))) return 'rust'\n\n // Python\n for (const f of ['requirements.txt', 'pyproject.toml', 'setup.py']) {\n if (await pathExists(join(projectRoot, f))) {\n // Check for Django\n try {\n const content = await readText(join(projectRoot, f))\n if (content?.includes('django') || content?.includes('Django')) return 'django'\n } catch { /* ignore */ }\n return 'other' // Generic Python — no specific stack type yet\n }\n }\n\n // Ruby\n if (await pathExists(join(projectRoot, 'Gemfile'))) {\n try {\n const content = await readText(join(projectRoot, 'Gemfile'))\n if (content?.includes('rails')) return 'rails'\n } catch { /* ignore */ }\n return 'other'\n }\n\n // .NET\n const dotnetFiles = ['*.csproj', '*.sln']\n for (const pattern of dotnetFiles) {\n if (pattern === '*.csproj' && await pathExists(join(projectRoot, 'Program.cs'))) return 'dotnet'\n if (pattern === '*.sln' && await pathExists(join(projectRoot, 'Program.cs'))) return 'dotnet'\n }\n\n // PHP / Laravel\n if (await pathExists(join(projectRoot, 'composer.json'))) {\n try {\n const composer = await readJson<Record<string, unknown>>(join(projectRoot, 'composer.json'))\n const require = composer?.require as Record<string, string> | undefined\n if (require?.['laravel/framework']) return 'laravel'\n } catch { /* ignore */ }\n return 'other'\n }\n\n // Flutter (Dart)\n if (await pathExists(join(projectRoot, 'pubspec.yaml'))) return 'flutter'\n\n // Hugo\n if (await pathExists(join(projectRoot, 'hugo.toml'))) return 'hugo'\n if (await pathExists(join(projectRoot, 'config.toml'))) {\n try {\n const content = await readText(join(projectRoot, 'config.toml'))\n if (content?.includes('baseURL') || content?.includes('hugo')) return 'hugo'\n } catch { /* ignore */ }\n }\n\n // Jekyll\n if (await pathExists(join(projectRoot, '_config.yml'))) return 'jekyll'\n\n return 'other'\n}\n\nasync function detectMonorepo(projectRoot: string): Promise<{ isMonorepo: boolean; tool?: string }> {\n if (await pathExists(join(projectRoot, 'pnpm-workspace.yaml'))) return { isMonorepo: true, tool: 'pnpm workspaces' }\n if (await pathExists(join(projectRoot, 'lerna.json'))) return { isMonorepo: true, tool: 'Lerna' }\n if (await pathExists(join(projectRoot, 'nx.json'))) return { isMonorepo: true, tool: 'Nx' }\n if (await pathExists(join(projectRoot, 'turbo.json'))) return { isMonorepo: true, tool: 'Turborepo' }\n\n const pkg = await readJson<PackageJson>(join(projectRoot, 'package.json'))\n if (pkg?.workspaces) return { isMonorepo: true, tool: 'npm/yarn workspaces' }\n\n // Walk up\n let dir = dirname(projectRoot)\n for (let i = 0; i < 5; i++) {\n if (await pathExists(join(dir, 'pnpm-workspace.yaml'))) return { isMonorepo: true, tool: 'pnpm workspaces' }\n if (await pathExists(join(dir, 'lerna.json'))) return { isMonorepo: true, tool: 'Lerna' }\n if (await pathExists(join(dir, 'nx.json'))) return { isMonorepo: true, tool: 'Nx' }\n if (await pathExists(join(dir, 'turbo.json'))) return { isMonorepo: true, tool: 'Turborepo' }\n const parentPkg = await readJson<PackageJson>(join(dir, 'package.json'))\n if (parentPkg?.workspaces) return { isMonorepo: true, tool: 'npm/yarn workspaces' }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n\n return { isMonorepo: false }\n}\n\nasync function detectFeatures(projectRoot: string): Promise<string[]> {\n const features: string[] = []\n const allDeps = await collectAllDeps(projectRoot)\n\n if ('typescript' in allDeps || await pathExists(join(projectRoot, 'tsconfig.json'))) features.push('TypeScript')\n\n const i18nLibs = ['vue-i18n', '@nuxtjs/i18n', 'next-intl', 'react-intl', 'i18next', 'react-i18next']\n for (const lib of i18nLibs) {\n if (lib in allDeps) { features.push(`i18n (${lib})`); break }\n }\n\n if ('tailwindcss' in allDeps) features.push('Tailwind CSS')\n else if ('sass' in allDeps || 'scss' in allDeps) features.push('Sass/SCSS')\n\n if ('vitest' in allDeps) features.push('Vitest')\n else if ('jest' in allDeps) features.push('Jest')\n\n if ('pinia' in allDeps) features.push('Pinia')\n else if ('zustand' in allDeps) features.push('Zustand')\n else if ('@reduxjs/toolkit' in allDeps || 'redux' in allDeps) features.push('Redux')\n\n return features\n}\n\nasync function collectAllDeps(projectRoot: string): Promise<Record<string, string>> {\n const pkg = await readJson<PackageJson>(join(projectRoot, 'package.json'))\n const allDeps: Record<string, string> = { ...pkg?.dependencies, ...pkg?.devDependencies }\n\n let dir = dirname(projectRoot)\n for (let i = 0; i < 5; i++) {\n const parentPkg = await readJson<PackageJson>(join(dir, 'package.json'))\n if (parentPkg?.workspaces) {\n Object.assign(allDeps, parentPkg.dependencies, parentPkg.devDependencies)\n break\n }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n\n // Same blind spot as stack detection: at a monorepo root the interesting\n // dependencies (the i18n library above all) sit in the workspace packages,\n // not in the root manifest. Reporting \"no i18n\" for a project that has it\n // would send normalize down the wrong path.\n const workspaceDirs = await listWorkspaceDirs(projectRoot)\n if (workspaceDirs.length > 0) {\n const pkgs = await Promise.all(\n workspaceDirs.map(d => readJson<PackageJson>(join(d, 'package.json'))),\n )\n for (const wsPkg of pkgs) {\n if (wsPkg) Object.assign(allDeps, wsPkg.dependencies, wsPkg.devDependencies)\n }\n }\n\n return allDeps\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"detect-CI32ynpq.mjs","names":[],"sources":["../src/util/detect.ts"],"sourcesContent":["import type { StackType, Platform } from '@contentrain/types'\nimport { join, dirname } from 'node:path'\nimport { readdir } from 'node:fs/promises'\nimport { readJson, pathExists, readText } from './fs.js'\n\ninterface PackageJson {\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n workspaces?: string[] | { packages: string[] }\n}\n\nexport interface StackInfo {\n stack: StackType\n platform: Platform\n name: string\n description: string\n monorepo: boolean\n monorepoTool?: string\n features: string[]\n}\n\nconst STACK_META: Record<StackType, { name: string; description: string }> = {\n // Meta-frameworks\n nuxt: { name: 'Nuxt', description: 'Vue meta-framework with SSR/SSG' },\n next: { name: 'Next.js', description: 'React framework with SSR/SSG' },\n astro: { name: 'Astro', description: 'Content-first web framework' },\n sveltekit: { name: 'SvelteKit', description: 'Svelte meta-framework' },\n remix: { name: 'Remix', description: 'Full-stack React framework' },\n analog: { name: 'Analog', description: 'Angular meta-framework' },\n // Plain frameworks\n vue: { name: 'Vue', description: 'Progressive JavaScript framework' },\n react: { name: 'React', description: 'UI library for web and native' },\n svelte: { name: 'Svelte', description: 'Compile-time UI framework' },\n solid: { name: 'Solid', description: 'Reactive UI library' },\n angular: { name: 'Angular', description: 'Platform for web applications' },\n // Mobile\n 'react-native': { name: 'React Native', description: 'Cross-platform mobile framework' },\n expo: { name: 'Expo', description: 'React Native toolchain' },\n flutter: { name: 'Flutter', description: 'Cross-platform UI toolkit (Dart)' },\n // Backend\n node: { name: 'Node.js', description: 'Server-side JavaScript runtime' },\n express: { name: 'Express', description: 'Minimal Node.js web framework' },\n fastify: { name: 'Fastify', description: 'Fast Node.js web framework' },\n nestjs: { name: 'NestJS', description: 'Progressive Node.js framework' },\n django: { name: 'Django', description: 'Python web framework' },\n rails: { name: 'Rails', description: 'Ruby web framework' },\n laravel: { name: 'Laravel', description: 'PHP web framework' },\n go: { name: 'Go', description: 'Go programming language' },\n rust: { name: 'Rust', description: 'Rust programming language' },\n dotnet: { name: '.NET', description: 'Microsoft .NET platform' },\n // Static\n hugo: { name: 'Hugo', description: 'Go-based static site generator' },\n jekyll: { name: 'Jekyll', description: 'Ruby-based static site generator' },\n eleventy: { name: 'Eleventy', description: 'JavaScript static site generator' },\n // Desktop\n electron: { name: 'Electron', description: 'Cross-platform desktop apps' },\n tauri: { name: 'Tauri', description: 'Lightweight desktop apps (Rust)' },\n // Catch-all\n other: { name: 'Other', description: 'Unknown or unsupported framework' },\n}\n\nexport function inferPlatform(stack: StackType): Platform {\n switch (stack) {\n case 'nuxt': case 'next': case 'astro': case 'sveltekit': case 'remix': case 'analog':\n case 'vue': case 'react': case 'svelte': case 'solid': case 'angular':\n return 'web'\n case 'react-native': case 'expo': case 'flutter':\n return 'mobile'\n case 'node': case 'express': case 'fastify': case 'nestjs':\n case 'django': case 'rails': case 'laravel': case 'go': case 'rust': case 'dotnet':\n return 'api'\n case 'electron': case 'tauri':\n return 'desktop'\n case 'hugo': case 'jekyll': case 'eleventy':\n return 'static'\n default:\n return 'other'\n }\n}\n\n/** Backward-compatible: returns just the StackType string */\nexport async function detectStack(projectRoot: string): Promise<StackType> {\n const info = await detectStackInfo(projectRoot)\n return info.stack\n}\n\n/** Rich detection: stack + platform + monorepo + features */\nexport async function detectStackInfo(projectRoot: string): Promise<StackInfo> {\n let stack = await detectFromDeps(projectRoot)\n\n // Walk up for monorepo root if local didn't match\n if (stack === 'other') {\n let dir = dirname(projectRoot)\n for (let i = 0; i < 5; i++) {\n const pkg = await readJson<PackageJson>(join(dir, 'package.json'))\n if (pkg?.workspaces) {\n const rootStack = await detectFromDeps(dir)\n if (rootStack !== 'other') {\n stack = rootStack\n break\n }\n }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n }\n\n // Look DOWN into the workspaces. The walk above handles \"I am inside a\n // package, find the monorepo root\"; this handles the opposite and more\n // common case — projectRoot IS the monorepo root, whose package.json holds\n // only tooling (turbo, nx) while the frameworks live in apps/* and\n // packages/*. Without this a Next.js monorepo reports `other`, and the\n // stack is what picks the replacement conventions during normalize.\n if (stack === 'other') {\n stack = await detectFromWorkspaces(projectRoot)\n }\n\n // Non-JS detection if still 'other'\n if (stack === 'other') {\n stack = await detectNonJs(projectRoot)\n }\n\n const mono = await detectMonorepo(projectRoot)\n const features = await detectFeatures(projectRoot)\n const meta = STACK_META[stack]\n\n return {\n stack,\n platform: inferPlatform(stack),\n name: meta.name,\n description: meta.description,\n monorepo: mono.isMonorepo,\n monorepoTool: mono.tool,\n features,\n }\n}\n\nasync function detectFromDeps(dir: string): Promise<StackType> {\n const pkg = await readJson<PackageJson>(join(dir, 'package.json'))\n if (!pkg) return 'other'\n\n const allDeps = { ...pkg.dependencies, ...pkg.devDependencies }\n\n // Meta-frameworks (check BEFORE plain frameworks)\n if ('nuxt' in allDeps) return 'nuxt'\n if ('next' in allDeps) return 'next'\n if ('astro' in allDeps) return 'astro'\n if ('@sveltejs/kit' in allDeps) return 'sveltekit'\n if ('@remix-run/node' in allDeps || 'remix' in allDeps) return 'remix'\n if ('@analogjs/platform' in allDeps) return 'analog'\n\n // Mobile (check before plain react)\n if ('expo' in allDeps) return 'expo'\n if ('react-native' in allDeps) return 'react-native'\n\n // Plain frameworks\n if ('vue' in allDeps) return 'vue'\n if ('svelte' in allDeps) return 'svelte'\n if ('solid-js' in allDeps) return 'solid'\n if ('@angular/core' in allDeps) return 'angular'\n if ('react' in allDeps) return 'react'\n\n // Desktop\n if ('electron' in allDeps) return 'electron'\n if ('@tauri-apps/api' in allDeps) return 'tauri'\n\n // Backend (Node.js)\n if ('@nestjs/core' in allDeps) return 'nestjs'\n if ('fastify' in allDeps) return 'fastify'\n if ('express' in allDeps) return 'express'\n\n // Static site generators\n if ('@11ty/eleventy' in allDeps) return 'eleventy'\n\n // Generic Node.js (has package.json but no framework)\n if ('node' in (pkg.dependencies ?? {})) return 'node'\n\n return 'other'\n}\n\n/**\n * Ranked by how strongly the stack determines content conventions — a\n * meta-framework dictates the i18n setup and the replacement expression,\n * a plain UI library does not. Frequency would be the wrong tie-break: a\n * monorepo with one Next app and two React packages is a Next project.\n */\nconst STACK_PRIORITY: readonly StackType[] = [\n 'nuxt', 'next', 'astro', 'sveltekit', 'remix', 'analog',\n 'expo', 'react-native',\n 'vue', 'react', 'svelte', 'solid', 'angular',\n 'electron', 'tauri',\n 'nestjs', 'fastify', 'express',\n 'eleventy', 'node',\n]\n\n/** Cap the fan-out so a large monorepo cannot turn detection into a crawl. */\nconst MAX_WORKSPACE_DIRS = 50\n\n/**\n * Workspace globs from `pnpm-workspace.yaml` or the `workspaces` field.\n *\n * The pnpm file is parsed line by line rather than with a YAML library: we\n * need exactly one list of strings with a fixed shape, and a parser\n * dependency for that is not worth the install size.\n */\nasync function readWorkspacePatterns(root: string): Promise<string[]> {\n const pnpm = await readText(join(root, 'pnpm-workspace.yaml'))\n if (pnpm) {\n const patterns: string[] = []\n let inPackages = false\n for (const raw of pnpm.split('\\n')) {\n const line = raw.replace(/#.*$/, '').trimEnd()\n if (/^packages:\\s*$/.test(line)) { inPackages = true; continue }\n if (!inPackages) continue\n const item = /^\\s+-\\s*['\"]?([^'\"]+?)['\"]?\\s*$/.exec(line)\n if (item?.[1]) { patterns.push(item[1]); continue }\n if (line.trim() !== '') break // a new top-level key ends the list\n }\n if (patterns.length > 0) return patterns\n }\n\n const pkg = await readJson<PackageJson>(join(root, 'package.json'))\n const ws = pkg?.workspaces\n if (Array.isArray(ws)) return ws\n if (ws && Array.isArray(ws.packages)) return ws.packages\n return []\n}\n\n/**\n * Expand workspace patterns to directories. Only a trailing `*` segment is\n * expanded — that covers `apps/*` and `packages/*`, which is what real\n * workspace files use. Deeper globs and negations are skipped rather than\n * half-supported.\n */\nasync function listWorkspaceDirs(root: string): Promise<string[]> {\n const patterns = (await readWorkspacePatterns(root)).filter(p => !p.startsWith('!'))\n\n const expanded = await Promise.all(patterns.map(async (pattern) => {\n const star = pattern.indexOf('*')\n if (star === -1) return [join(root, pattern)]\n const base = join(root, pattern.slice(0, star).replace(/\\/+$/, ''))\n try {\n const entries = await readdir(base, { withFileTypes: true })\n return entries.filter(e => e.isDirectory()).map(e => join(base, e.name))\n } catch {\n return []\n }\n }))\n\n return expanded.flat().slice(0, MAX_WORKSPACE_DIRS)\n}\n\n/** Highest-priority stack across the workspace packages. */\nasync function detectFromWorkspaces(root: string): Promise<StackType> {\n const dirs = await listWorkspaceDirs(root)\n if (dirs.length === 0) return 'other'\n\n const found = new Set(await Promise.all(dirs.map(d => detectFromDeps(d))))\n return STACK_PRIORITY.find(s => found.has(s)) ?? 'other'\n}\n\nasync function detectNonJs(projectRoot: string): Promise<StackType> {\n // Go\n if (await pathExists(join(projectRoot, 'go.mod'))) return 'go'\n\n // Rust\n if (await pathExists(join(projectRoot, 'Cargo.toml'))) return 'rust'\n\n // Python\n for (const f of ['requirements.txt', 'pyproject.toml', 'setup.py']) {\n if (await pathExists(join(projectRoot, f))) {\n // Check for Django\n try {\n const content = await readText(join(projectRoot, f))\n if (content?.includes('django') || content?.includes('Django')) return 'django'\n } catch { /* ignore */ }\n return 'other' // Generic Python — no specific stack type yet\n }\n }\n\n // Ruby\n if (await pathExists(join(projectRoot, 'Gemfile'))) {\n try {\n const content = await readText(join(projectRoot, 'Gemfile'))\n if (content?.includes('rails')) return 'rails'\n } catch { /* ignore */ }\n return 'other'\n }\n\n // .NET\n const dotnetFiles = ['*.csproj', '*.sln']\n for (const pattern of dotnetFiles) {\n if (pattern === '*.csproj' && await pathExists(join(projectRoot, 'Program.cs'))) return 'dotnet'\n if (pattern === '*.sln' && await pathExists(join(projectRoot, 'Program.cs'))) return 'dotnet'\n }\n\n // PHP / Laravel\n if (await pathExists(join(projectRoot, 'composer.json'))) {\n try {\n const composer = await readJson<Record<string, unknown>>(join(projectRoot, 'composer.json'))\n const require = composer?.require as Record<string, string> | undefined\n if (require?.['laravel/framework']) return 'laravel'\n } catch { /* ignore */ }\n return 'other'\n }\n\n // Flutter (Dart)\n if (await pathExists(join(projectRoot, 'pubspec.yaml'))) return 'flutter'\n\n // Hugo\n if (await pathExists(join(projectRoot, 'hugo.toml'))) return 'hugo'\n if (await pathExists(join(projectRoot, 'config.toml'))) {\n try {\n const content = await readText(join(projectRoot, 'config.toml'))\n if (content?.includes('baseURL') || content?.includes('hugo')) return 'hugo'\n } catch { /* ignore */ }\n }\n\n // Jekyll\n if (await pathExists(join(projectRoot, '_config.yml'))) return 'jekyll'\n\n return 'other'\n}\n\nasync function detectMonorepo(projectRoot: string): Promise<{ isMonorepo: boolean; tool?: string }> {\n if (await pathExists(join(projectRoot, 'pnpm-workspace.yaml'))) return { isMonorepo: true, tool: 'pnpm workspaces' }\n if (await pathExists(join(projectRoot, 'lerna.json'))) return { isMonorepo: true, tool: 'Lerna' }\n if (await pathExists(join(projectRoot, 'nx.json'))) return { isMonorepo: true, tool: 'Nx' }\n if (await pathExists(join(projectRoot, 'turbo.json'))) return { isMonorepo: true, tool: 'Turborepo' }\n\n const pkg = await readJson<PackageJson>(join(projectRoot, 'package.json'))\n if (pkg?.workspaces) return { isMonorepo: true, tool: 'npm/yarn workspaces' }\n\n // Walk up\n let dir = dirname(projectRoot)\n for (let i = 0; i < 5; i++) {\n if (await pathExists(join(dir, 'pnpm-workspace.yaml'))) return { isMonorepo: true, tool: 'pnpm workspaces' }\n if (await pathExists(join(dir, 'lerna.json'))) return { isMonorepo: true, tool: 'Lerna' }\n if (await pathExists(join(dir, 'nx.json'))) return { isMonorepo: true, tool: 'Nx' }\n if (await pathExists(join(dir, 'turbo.json'))) return { isMonorepo: true, tool: 'Turborepo' }\n const parentPkg = await readJson<PackageJson>(join(dir, 'package.json'))\n if (parentPkg?.workspaces) return { isMonorepo: true, tool: 'npm/yarn workspaces' }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n\n return { isMonorepo: false }\n}\n\nasync function detectFeatures(projectRoot: string): Promise<string[]> {\n const features: string[] = []\n const allDeps = await collectAllDeps(projectRoot)\n\n if ('typescript' in allDeps || await pathExists(join(projectRoot, 'tsconfig.json'))) features.push('TypeScript')\n\n const i18nLibs = ['vue-i18n', '@nuxtjs/i18n', 'next-intl', 'react-intl', 'i18next', 'react-i18next']\n for (const lib of i18nLibs) {\n if (lib in allDeps) { features.push(`i18n (${lib})`); break }\n }\n\n if ('tailwindcss' in allDeps) features.push('Tailwind CSS')\n else if ('sass' in allDeps || 'scss' in allDeps) features.push('Sass/SCSS')\n\n if ('vitest' in allDeps) features.push('Vitest')\n else if ('jest' in allDeps) features.push('Jest')\n\n if ('pinia' in allDeps) features.push('Pinia')\n else if ('zustand' in allDeps) features.push('Zustand')\n else if ('@reduxjs/toolkit' in allDeps || 'redux' in allDeps) features.push('Redux')\n\n return features\n}\n\nasync function collectAllDeps(projectRoot: string): Promise<Record<string, string>> {\n const pkg = await readJson<PackageJson>(join(projectRoot, 'package.json'))\n const allDeps: Record<string, string> = { ...pkg?.dependencies, ...pkg?.devDependencies }\n\n let dir = dirname(projectRoot)\n for (let i = 0; i < 5; i++) {\n const parentPkg = await readJson<PackageJson>(join(dir, 'package.json'))\n if (parentPkg?.workspaces) {\n Object.assign(allDeps, parentPkg.dependencies, parentPkg.devDependencies)\n break\n }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n\n // Same blind spot as stack detection: at a monorepo root the interesting\n // dependencies (the i18n library above all) sit in the workspace packages,\n // not in the root manifest. Reporting \"no i18n\" for a project that has it\n // would send normalize down the wrong path.\n const workspaceDirs = await listWorkspaceDirs(projectRoot)\n if (workspaceDirs.length > 0) {\n const pkgs = await Promise.all(\n workspaceDirs.map(d => readJson<PackageJson>(join(d, 'package.json'))),\n )\n for (const wsPkg of pkgs) {\n if (wsPkg) Object.assign(allDeps, wsPkg.dependencies, wsPkg.devDependencies)\n }\n }\n\n return allDeps\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { r as
|
|
3
|
-
import { t as readConfig } from "./config-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { i as autoDetectSourceDirs, o as discoverFiles } from "./scan-config-
|
|
1
|
+
import { _ as resolveContentDir, c as listModels, d as validateModelDefinition, l as readModel, v as resolveJsonFilePath, y as resolveLocaleStrategy } from "./model-manager-DqwL8ptm.mjs";
|
|
2
|
+
import { a as readJson, i as readDir, o as readText, r as pathExists, t as contentrainDir } from "./fs-DJv5G8uL.mjs";
|
|
3
|
+
import { t as readConfig } from "./config-B8a4JBT1.mjs";
|
|
4
|
+
import { r as createGit } from "./identity-CxAB9Qb8.mjs";
|
|
5
|
+
import { c as listRemoteCrBranches, n as checkBranchHealth } from "./branch-lifecycle-DUOoyNWn.mjs";
|
|
6
|
+
import { i as autoDetectSourceDirs, o as discoverFiles } from "./scan-config-C5zzygeH.mjs";
|
|
7
7
|
import { join } from "node:path";
|
|
8
8
|
import { readdir, stat } from "node:fs/promises";
|
|
9
9
|
//#region src/core/doctor.ts
|
|
@@ -393,4 +393,4 @@ async function analyzeMissingLocaleKeys(projectRoot, config) {
|
|
|
393
393
|
//#endregion
|
|
394
394
|
export { runDoctor as t };
|
|
395
395
|
|
|
396
|
-
//# sourceMappingURL=doctor-
|
|
396
|
+
//# sourceMappingURL=doctor-B7G0oFxO.mjs.map
|