contentrain 0.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/LICENSE +21 -0
- package/README.md +168 -0
- package/dist/context-An3xrvcP.mjs +50 -0
- package/dist/diff-otz0kGqT.mjs +116 -0
- package/dist/doctor-DyKjAIKH.mjs +187 -0
- package/dist/generate-DDEDRLdy.mjs +76 -0
- package/dist/index.mjs +21 -0
- package/dist/init-D5L_7bKE.mjs +415 -0
- package/dist/serve-CaCZMeHF.mjs +111 -0
- package/dist/serve-ui/assets/AgentPromptGroup.vue_vue_type_script_setup_true_lang-Dy-5bpEY.js +16 -0
- package/dist/serve-ui/assets/AppLayout-CJFq2ApF.js +16 -0
- package/dist/serve-ui/assets/BranchDetailPage-DzSu3JlE.js +17 -0
- package/dist/serve-ui/assets/BranchesPage-ZSG-l44J.js +6 -0
- package/dist/serve-ui/assets/CollapsibleTrigger.vue_vue_type_script_setup_true_lang-C4oejwcu.js +1 -0
- package/dist/serve-ui/assets/Collection-zzx9pNd2.js +6 -0
- package/dist/serve-ui/assets/ConfigProvider-BGjDLViI.js +1 -0
- package/dist/serve-ui/assets/ContentListPage-DTFaQB8N.js +51 -0
- package/dist/serve-ui/assets/ContentListPage-vXxAeSg8.css +1 -0
- package/dist/serve-ui/assets/ContentPage-4sQsAlY2.js +1 -0
- package/dist/serve-ui/assets/DashboardPage-CZDlnvAE.js +21 -0
- package/dist/serve-ui/assets/DialogTitle.vue_vue_type_script_setup_true_lang-CBu_dmA6.js +1 -0
- package/dist/serve-ui/assets/Input.vue_vue_type_script_setup_true_lang-otPltlZG.js +6 -0
- package/dist/serve-ui/assets/ModelDetailPage-BMquKCtH.js +49 -0
- package/dist/serve-ui/assets/ModelsPage-C_K-aWXf.js +1 -0
- package/dist/serve-ui/assets/NormalizePage-CHkT6yLV.js +11 -0
- package/dist/serve-ui/assets/PageHeader.vue_vue_type_script_setup_true_lang-C7aWxNSw.js +11 -0
- package/dist/serve-ui/assets/Presence-cbB6AqkQ.js +3 -0
- package/dist/serve-ui/assets/Separator.vue_vue_type_script_setup_true_lang-fePFl24S.js +1 -0
- package/dist/serve-ui/assets/StudioHint.vue_vue_type_script_setup_true_lang-B45TG2r1.js +6 -0
- package/dist/serve-ui/assets/TrustBadge.vue_vue_type_script_setup_true_lang-CgoQGS6k.js +11 -0
- package/dist/serve-ui/assets/ValidatePage-BW8DO6WC.js +21 -0
- package/dist/serve-ui/assets/arrow-down-DqOfGL7C.js +6 -0
- package/dist/serve-ui/assets/arrow-left-BRvgeveW.js +6 -0
- package/dist/serve-ui/assets/book-marked-D8StxRZP.js +6 -0
- package/dist/serve-ui/assets/book-open-BrGAe3tk.js +6 -0
- package/dist/serve-ui/assets/box-7olVZr5D.js +6 -0
- package/dist/serve-ui/assets/chevron-down-B9YdCtsj.js +6 -0
- package/dist/serve-ui/assets/chevron-right-DFKsmZVd.js +6 -0
- package/dist/serve-ui/assets/content-BQE3NEm5.js +1 -0
- package/dist/serve-ui/assets/database-BGEFn4Oq.js +6 -0
- package/dist/serve-ui/assets/file-code-BGiS4dun.js +6 -0
- package/dist/serve-ui/assets/file-text-BDHXQ95W.js +6 -0
- package/dist/serve-ui/assets/getActiveElement-FUKBWQwh.js +1 -0
- package/dist/serve-ui/assets/git-branch-DdE7bk9-.js +6 -0
- package/dist/serve-ui/assets/git-merge-iStuJS69.js +6 -0
- package/dist/serve-ui/assets/hash-B-ibLpM1.js +6 -0
- package/dist/serve-ui/assets/index-C-RjMzFm.css +1 -0
- package/dist/serve-ui/assets/index-CoUshYEB.js +80 -0
- package/dist/serve-ui/assets/index-WHgvdYOs.js +1 -0
- package/dist/serve-ui/assets/languages-BTcd2Rl1.js +6 -0
- package/dist/serve-ui/assets/model-empty-state-B6AM4bil.js +1 -0
- package/dist/serve-ui/assets/plus-D8Nd3YnG.js +11 -0
- package/dist/serve-ui/assets/project-B1qSm0Fz.js +1 -0
- package/dist/serve-ui/assets/scan-search-DGPL_VJu.js +6 -0
- package/dist/serve-ui/assets/settings-DL-0RaxD.js +6 -0
- package/dist/serve-ui/assets/shield-check-CUL7KkSA.js +6 -0
- package/dist/serve-ui/assets/trash-2-83QhL6-T.js +11 -0
- package/dist/serve-ui/assets/useDirection-Cd3C7VdT.js +1 -0
- package/dist/serve-ui/assets/useFormatters-DgWFpsAv.js +1 -0
- package/dist/serve-ui/assets/useId-C0uR6mdj.js +1 -0
- package/dist/serve-ui/assets/useNonce-DTGvzOJz.js +1 -0
- package/dist/serve-ui/assets/useWatch-COpVIQvm.js +1 -0
- package/dist/serve-ui/favicon.svg +19 -0
- package/dist/serve-ui/for-developers-1.svg +65 -0
- package/dist/serve-ui/icon-color.svg +18 -0
- package/dist/serve-ui/index.html +17 -0
- package/dist/serve-ui/logo/color-icon-black-text.svg +65 -0
- package/dist/serve-ui/logo/color-icon-white-text.svg +61 -0
- package/dist/serve-ui/merge-1.svg +131 -0
- package/dist/serve-ui/merge-2.svg +161 -0
- package/dist/serve-ui/model-empty-state.svg +12 -0
- package/dist/serve-ui/select-data-type.svg +23 -0
- package/dist/server-DW0KXB0T.mjs +607 -0
- package/dist/status-kF5miVty.mjs +122 -0
- package/dist/ui-B5mXontH.mjs +33 -0
- package/dist/validate-DnVamp3p.mjs +155 -0
- package/package.json +66 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { n as requireInitialized, r as resolveProjectRoot, t as loadProjectContext } from "./context-An3xrvcP.mjs";
|
|
2
|
+
import { i as pc, n as formatPercent, r as formatTable, t as formatCount } from "./ui-B5mXontH.mjs";
|
|
3
|
+
import { defineCommand } from "citty";
|
|
4
|
+
import { intro, log, outro } from "@clack/prompts";
|
|
5
|
+
import { simpleGit } from "simple-git";
|
|
6
|
+
import { countEntries, readModel } from "@contentrain/mcp/core/model-manager";
|
|
7
|
+
import { validateProject } from "@contentrain/mcp/core/validator";
|
|
8
|
+
//#region src/commands/status.ts
|
|
9
|
+
var status_default = defineCommand({
|
|
10
|
+
meta: {
|
|
11
|
+
name: "status",
|
|
12
|
+
description: "Show project status overview"
|
|
13
|
+
},
|
|
14
|
+
args: {
|
|
15
|
+
root: {
|
|
16
|
+
type: "string",
|
|
17
|
+
description: "Project root path",
|
|
18
|
+
required: false
|
|
19
|
+
},
|
|
20
|
+
json: {
|
|
21
|
+
type: "boolean",
|
|
22
|
+
description: "JSON output for CI",
|
|
23
|
+
required: false
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
async run({ args }) {
|
|
27
|
+
const projectRoot = await resolveProjectRoot(args.root);
|
|
28
|
+
const ctx = await loadProjectContext(projectRoot);
|
|
29
|
+
if (args.json) {
|
|
30
|
+
const jsonResult = {
|
|
31
|
+
initialized: ctx.initialized,
|
|
32
|
+
config: ctx.config,
|
|
33
|
+
models: ctx.models,
|
|
34
|
+
context: ctx.context
|
|
35
|
+
};
|
|
36
|
+
if (ctx.initialized && ctx.config) {
|
|
37
|
+
try {
|
|
38
|
+
const validation = await validateProject(projectRoot, {});
|
|
39
|
+
jsonResult["validation"] = {
|
|
40
|
+
valid: validation.valid,
|
|
41
|
+
errors: validation.summary.errors,
|
|
42
|
+
warnings: validation.summary.warnings
|
|
43
|
+
};
|
|
44
|
+
} catch {}
|
|
45
|
+
try {
|
|
46
|
+
jsonResult["pending_branches"] = (await simpleGit(projectRoot).branch(["--list", "contentrain/*"])).all;
|
|
47
|
+
} catch {}
|
|
48
|
+
}
|
|
49
|
+
process.stdout.write(JSON.stringify(jsonResult, null, 2));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
intro(pc.bold("contentrain status"));
|
|
53
|
+
if (!ctx.initialized) {
|
|
54
|
+
log.warning("Project not initialized. Run `contentrain init` to get started.");
|
|
55
|
+
outro("");
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
requireInitialized(ctx);
|
|
59
|
+
log.info(pc.bold("Configuration"));
|
|
60
|
+
log.message(` Stack: ${pc.cyan(ctx.config.stack)}`);
|
|
61
|
+
log.message(` Locales: ${ctx.config.locales.supported.map((l) => l === ctx.config.locales.default ? pc.green(`${l} (default)`) : l).join(", ")}`);
|
|
62
|
+
log.message(` Domains: ${ctx.config.domains.join(", ")}`);
|
|
63
|
+
log.message(` Workflow: ${ctx.config.workflow === "auto-merge" ? pc.green("auto-merge") : pc.yellow("review")}`);
|
|
64
|
+
if (ctx.models.length > 0) {
|
|
65
|
+
log.info(pc.bold(`\nModels (${ctx.models.length})`));
|
|
66
|
+
const rows = [];
|
|
67
|
+
for (const model of ctx.models) {
|
|
68
|
+
const full = await readModel(projectRoot, model.id);
|
|
69
|
+
if (!full) continue;
|
|
70
|
+
const counts = await countEntries(projectRoot, full);
|
|
71
|
+
const defaultCount = counts.locales[ctx.config.locales.default] ?? 0;
|
|
72
|
+
let i18nStatus = "—";
|
|
73
|
+
if (model.i18n && ctx.config.locales.supported.length > 1) {
|
|
74
|
+
const completions = ctx.config.locales.supported.filter((l) => l !== ctx.config.locales.default).map((l) => counts.locales[l] ?? 0);
|
|
75
|
+
i18nStatus = formatPercent(completions.length > 0 ? completions.reduce((a, b) => a + b, 0) / completions.length : 0, defaultCount);
|
|
76
|
+
}
|
|
77
|
+
rows.push([
|
|
78
|
+
model.id,
|
|
79
|
+
model.kind,
|
|
80
|
+
model.domain,
|
|
81
|
+
String(counts.total),
|
|
82
|
+
model.i18n ? i18nStatus : "—"
|
|
83
|
+
]);
|
|
84
|
+
}
|
|
85
|
+
log.message(formatTable([
|
|
86
|
+
"Model",
|
|
87
|
+
"Kind",
|
|
88
|
+
"Domain",
|
|
89
|
+
"Entries",
|
|
90
|
+
"i18n"
|
|
91
|
+
], rows));
|
|
92
|
+
} else log.message(" No models yet. Run `contentrain init` with a template or create models.");
|
|
93
|
+
try {
|
|
94
|
+
const branches = await simpleGit(projectRoot).branch(["--list", "contentrain/*"]);
|
|
95
|
+
if (branches.all.length > 0) {
|
|
96
|
+
const count = branches.all.length;
|
|
97
|
+
if (count >= 80) {
|
|
98
|
+
log.error(pc.bold(`\nBLOCKED: ${count} active contentrain branches (limit: 80)`));
|
|
99
|
+
log.message(` New writes are blocked. Merge or delete old branches with ${pc.cyan("contentrain diff")}.`);
|
|
100
|
+
} else if (count >= 50) {
|
|
101
|
+
log.warning(pc.bold(`\nWARNING: ${count} active contentrain branches (limit: 50)`));
|
|
102
|
+
log.message(` Consider merging or deleting old branches with ${pc.cyan("contentrain diff")}.`);
|
|
103
|
+
} else log.info(pc.bold(`\nPending branches (${count})`));
|
|
104
|
+
for (const branch of branches.all) log.message(` ${pc.yellow("●")} ${branch}`);
|
|
105
|
+
log.message(` Run ${pc.cyan("contentrain diff")} to review.`);
|
|
106
|
+
}
|
|
107
|
+
} catch {}
|
|
108
|
+
if (ctx.context?.lastOperation) {
|
|
109
|
+
const op = ctx.context.lastOperation;
|
|
110
|
+
log.info(pc.bold("\nLast operation"));
|
|
111
|
+
log.message(` ${op.tool} → ${op.model || "(init)"} @ ${new Date(op.timestamp).toLocaleString()}`);
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
const result = await validateProject(projectRoot);
|
|
115
|
+
if (result.summary.errors > 0) log.warning(`\n${formatCount(result.summary.errors, "validation error")}. Run ${pc.cyan("contentrain validate --fix")} to fix.`);
|
|
116
|
+
else log.success("\nValidation: clean");
|
|
117
|
+
} catch {}
|
|
118
|
+
outro("");
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
//#endregion
|
|
122
|
+
export { status_default as default };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import pc from "picocolors";
|
|
2
|
+
//#region src/utils/ui.ts
|
|
3
|
+
function severityColor(severity) {
|
|
4
|
+
switch (severity) {
|
|
5
|
+
case "error": return pc.red;
|
|
6
|
+
case "warning": return pc.yellow;
|
|
7
|
+
case "notice": return pc.blue;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function formatCount(n, singular, plural) {
|
|
11
|
+
return `${n} ${n === 1 ? singular : plural ?? `${singular}s`}`;
|
|
12
|
+
}
|
|
13
|
+
function formatPercent(part, total) {
|
|
14
|
+
if (total === 0) return "—";
|
|
15
|
+
const pct = Math.round(part / total * 100);
|
|
16
|
+
return (pct === 100 ? pc.green : pct >= 75 ? pc.yellow : pc.red)(`${pct}%`);
|
|
17
|
+
}
|
|
18
|
+
function padRight(str, len) {
|
|
19
|
+
return str.length >= len ? str : str + " ".repeat(len - str.length);
|
|
20
|
+
}
|
|
21
|
+
function formatTable(headers, rows) {
|
|
22
|
+
const widths = headers.map((h, i) => Math.max(h.length, ...rows.map((r) => (r[i] ?? "").length)));
|
|
23
|
+
return [
|
|
24
|
+
headers.map((h, i) => padRight(h, widths[i] ?? h.length)).join(" "),
|
|
25
|
+
widths.map((w) => "─".repeat(w)).join("──"),
|
|
26
|
+
...rows.map((row) => row.map((cell, i) => padRight(cell, widths[i] ?? cell.length)).join(" "))
|
|
27
|
+
].join("\n");
|
|
28
|
+
}
|
|
29
|
+
function statusIcon(pass) {
|
|
30
|
+
return pass ? pc.green("✓") : pc.red("✗");
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { severityColor as a, pc as i, formatPercent as n, statusIcon as o, formatTable as r, formatCount as t };
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { n as requireInitialized, r as resolveProjectRoot, t as loadProjectContext } from "./context-An3xrvcP.mjs";
|
|
2
|
+
import { a as severityColor, i as pc, t as formatCount } from "./ui-B5mXontH.mjs";
|
|
3
|
+
import { defineCommand } from "citty";
|
|
4
|
+
import { intro, isCancel, log, outro, select, spinner } from "@clack/prompts";
|
|
5
|
+
import { writeContext } from "@contentrain/mcp/core/context";
|
|
6
|
+
import { buildBranchName, createTransaction } from "@contentrain/mcp/git/transaction";
|
|
7
|
+
import { validateProject } from "@contentrain/mcp/core/validator";
|
|
8
|
+
//#region src/commands/validate.ts
|
|
9
|
+
var validate_default = defineCommand({
|
|
10
|
+
meta: {
|
|
11
|
+
name: "validate",
|
|
12
|
+
description: "Validate project content against schemas"
|
|
13
|
+
},
|
|
14
|
+
args: {
|
|
15
|
+
root: {
|
|
16
|
+
type: "string",
|
|
17
|
+
description: "Project root path",
|
|
18
|
+
required: false
|
|
19
|
+
},
|
|
20
|
+
fix: {
|
|
21
|
+
type: "boolean",
|
|
22
|
+
description: "Auto-fix issues",
|
|
23
|
+
required: false
|
|
24
|
+
},
|
|
25
|
+
interactive: {
|
|
26
|
+
type: "boolean",
|
|
27
|
+
description: "Interactive fix mode",
|
|
28
|
+
required: false
|
|
29
|
+
},
|
|
30
|
+
json: {
|
|
31
|
+
type: "boolean",
|
|
32
|
+
description: "JSON output for CI",
|
|
33
|
+
required: false
|
|
34
|
+
},
|
|
35
|
+
model: {
|
|
36
|
+
type: "string",
|
|
37
|
+
description: "Validate single model",
|
|
38
|
+
required: false
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
async run({ args }) {
|
|
42
|
+
const projectRoot = await resolveProjectRoot(args.root);
|
|
43
|
+
requireInitialized(await loadProjectContext(projectRoot));
|
|
44
|
+
if (!args.json) intro(pc.bold("contentrain validate"));
|
|
45
|
+
const s = !args.json ? spinner() : null;
|
|
46
|
+
s?.start("Validating...");
|
|
47
|
+
let result;
|
|
48
|
+
if (args.fix) {
|
|
49
|
+
const { checkBranchHealth } = await import("@contentrain/mcp/git/branch-lifecycle");
|
|
50
|
+
const health = await checkBranchHealth(projectRoot);
|
|
51
|
+
if (health.blocked) {
|
|
52
|
+
s?.stop("Blocked");
|
|
53
|
+
log.error(health.message);
|
|
54
|
+
outro("");
|
|
55
|
+
process.exitCode = 1;
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const tx = await createTransaction(projectRoot, buildBranchName("fix", "validate"));
|
|
59
|
+
try {
|
|
60
|
+
await tx.write(async (wt) => {
|
|
61
|
+
result = await validateProject(wt, {
|
|
62
|
+
model: args.model,
|
|
63
|
+
fix: true
|
|
64
|
+
});
|
|
65
|
+
await writeContext(wt, {
|
|
66
|
+
tool: "contentrain_validate",
|
|
67
|
+
model: args.model ?? "*"
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
await tx.commit("[contentrain] validate: auto-fix");
|
|
71
|
+
await tx.complete();
|
|
72
|
+
} finally {
|
|
73
|
+
await tx.cleanup();
|
|
74
|
+
}
|
|
75
|
+
} else result = await validateProject(projectRoot, {
|
|
76
|
+
model: args.model,
|
|
77
|
+
fix: false
|
|
78
|
+
});
|
|
79
|
+
s?.stop("Validation complete");
|
|
80
|
+
if (args.json) {
|
|
81
|
+
process.stdout.write(JSON.stringify(result, null, 2));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
log.info(pc.bold("Summary"));
|
|
85
|
+
log.message(` Models checked: ${result.summary.models_checked}`);
|
|
86
|
+
log.message(` Entries checked: ${result.summary.entries_checked}`);
|
|
87
|
+
log.message(` Errors: ${result.summary.errors > 0 ? pc.red(String(result.summary.errors)) : pc.green("0")}`);
|
|
88
|
+
log.message(` Warnings: ${result.summary.warnings > 0 ? pc.yellow(String(result.summary.warnings)) : pc.green("0")}`);
|
|
89
|
+
log.message(` Notices: ${result.summary.notices > 0 ? pc.blue(String(result.summary.notices)) : "0"}`);
|
|
90
|
+
if (args.fix && result.fixed > 0) log.success(`Fixed ${result.fixed} issue(s)`);
|
|
91
|
+
if (result.issues.length > 0) {
|
|
92
|
+
log.info(pc.bold("\nIssues"));
|
|
93
|
+
for (const issue of result.issues) {
|
|
94
|
+
const prefix = severityColor(issue.severity)(`[${issue.severity.toUpperCase()}]`);
|
|
95
|
+
const location = [
|
|
96
|
+
issue.model,
|
|
97
|
+
issue.field,
|
|
98
|
+
issue.entry
|
|
99
|
+
].filter(Boolean).join(" → ");
|
|
100
|
+
log.message(` ${prefix} ${location}: ${issue.message}`);
|
|
101
|
+
}
|
|
102
|
+
if (args.interactive && result.issues.some((i) => i.severity === "error" || i.severity === "warning")) {
|
|
103
|
+
log.info("\n" + pc.bold("Interactive fix mode"));
|
|
104
|
+
const fixChoice = await select({
|
|
105
|
+
message: "How would you like to proceed?",
|
|
106
|
+
options: [{
|
|
107
|
+
value: "fix-all",
|
|
108
|
+
label: "Fix all auto-fixable issues"
|
|
109
|
+
}, {
|
|
110
|
+
value: "skip",
|
|
111
|
+
label: "Skip — I'll fix manually"
|
|
112
|
+
}]
|
|
113
|
+
});
|
|
114
|
+
if (!isCancel(fixChoice) && fixChoice === "fix-all") {
|
|
115
|
+
const fixS = spinner();
|
|
116
|
+
fixS.start("Fixing issues...");
|
|
117
|
+
const fixBranch = buildBranchName("fix", "validate");
|
|
118
|
+
const fixTx = await createTransaction(projectRoot, fixBranch);
|
|
119
|
+
let fixResult;
|
|
120
|
+
try {
|
|
121
|
+
await fixTx.write(async (wt) => {
|
|
122
|
+
fixResult = await validateProject(wt, {
|
|
123
|
+
model: args.model,
|
|
124
|
+
fix: true
|
|
125
|
+
});
|
|
126
|
+
await writeContext(wt, {
|
|
127
|
+
tool: "contentrain_validate",
|
|
128
|
+
model: args.model ?? "*"
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
await fixTx.commit("[contentrain] validate: interactive auto-fix");
|
|
132
|
+
await fixTx.complete();
|
|
133
|
+
} finally {
|
|
134
|
+
await fixTx.cleanup();
|
|
135
|
+
}
|
|
136
|
+
fixS.stop(`Fixed ${fixResult.fixed} issue(s)`);
|
|
137
|
+
const { readConfig } = await import("@contentrain/mcp/core/config");
|
|
138
|
+
if ((await readConfig(projectRoot))?.workflow === "review") log.info(`Fixes committed to branch ${pc.cyan(fixBranch)}. Run ${pc.cyan("contentrain diff")} to review and merge.`);
|
|
139
|
+
else {
|
|
140
|
+
const recheck = await validateProject(projectRoot, { model: args.model });
|
|
141
|
+
if (recheck.summary.errors === 0) log.success("All errors resolved!");
|
|
142
|
+
else log.warning(`${formatCount(recheck.summary.errors, "error")} remaining (may need manual fix)`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (result.valid) outro(pc.green("Project is valid!"));
|
|
148
|
+
else {
|
|
149
|
+
outro(pc.yellow(`${formatCount(result.summary.errors, "error")}, ${formatCount(result.summary.warnings, "warning")}`));
|
|
150
|
+
if (!args.fix && !args.interactive) log.message(`Run ${pc.cyan("contentrain validate --fix")} to auto-fix.`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
//#endregion
|
|
155
|
+
export { validate_default as default };
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "contentrain",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "CLI for Contentrain — AI content governance infrastructure",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/contentrain/contentrain-ai.git",
|
|
10
|
+
"directory": "packages/cli"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/contentrain/contentrain-ai/tree/main/packages/cli",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/contentrain/contentrain-ai/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"contentrain",
|
|
18
|
+
"cli",
|
|
19
|
+
"mcp",
|
|
20
|
+
"content-governance",
|
|
21
|
+
"ai",
|
|
22
|
+
"i18n",
|
|
23
|
+
"cms"
|
|
24
|
+
],
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"bin": {
|
|
29
|
+
"contentrain": "./dist/index.mjs"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist"
|
|
33
|
+
],
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@clack/prompts": "^0.10.0",
|
|
36
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
37
|
+
"chokidar": "^4.0.0",
|
|
38
|
+
"citty": "^0.1.0",
|
|
39
|
+
"consola": "^3.4.0",
|
|
40
|
+
"crossws": "^0.3.0",
|
|
41
|
+
"h3": "^1.15.0",
|
|
42
|
+
"picocolors": "^1.1.0",
|
|
43
|
+
"simple-git": "^3.27.0",
|
|
44
|
+
"ws": "^8.18.0",
|
|
45
|
+
"@contentrain/rules": "0.1.0",
|
|
46
|
+
"@contentrain/types": "0.1.0",
|
|
47
|
+
"@contentrain/mcp": "1.0.0",
|
|
48
|
+
"@contentrain/query": "5.0.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/ws": "^8.5.0",
|
|
52
|
+
"@types/node": "^22.0.0",
|
|
53
|
+
"tsdown": "^0.21.0",
|
|
54
|
+
"typescript": "^5.7.0",
|
|
55
|
+
"vitest": "^3.0.0"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"build": "tsdown src/index.ts --format esm && cd src/serve-ui && npx vite build",
|
|
59
|
+
"build:cli-only": "tsdown src/index.ts --format esm",
|
|
60
|
+
"build:ui-only": "cd src/serve-ui && npx vite build",
|
|
61
|
+
"dev": "tsdown src/index.ts --format esm --watch",
|
|
62
|
+
"test": "vitest run",
|
|
63
|
+
"typecheck": "tsc --noEmit",
|
|
64
|
+
"clean": "rm -rf dist"
|
|
65
|
+
}
|
|
66
|
+
}
|