@contentrail/cli 0.0.0-stage → 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.
Files changed (80) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +81 -2
  3. package/bin/contentrail.js +5 -0
  4. package/dist/cli.d.ts +7 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +203 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/collections/load.d.ts +6 -0
  9. package/dist/collections/load.d.ts.map +1 -0
  10. package/dist/collections/load.js +57 -0
  11. package/dist/collections/load.js.map +1 -0
  12. package/dist/commands/build.d.ts +5 -0
  13. package/dist/commands/build.d.ts.map +1 -0
  14. package/dist/commands/build.js +46 -0
  15. package/dist/commands/build.js.map +1 -0
  16. package/dist/commands/doctor.d.ts +4 -0
  17. package/dist/commands/doctor.d.ts.map +1 -0
  18. package/dist/commands/doctor.js +136 -0
  19. package/dist/commands/doctor.js.map +1 -0
  20. package/dist/commands/init.d.ts +11 -0
  21. package/dist/commands/init.d.ts.map +1 -0
  22. package/dist/commands/init.js +129 -0
  23. package/dist/commands/init.js.map +1 -0
  24. package/dist/commands/status.d.ts +4 -0
  25. package/dist/commands/status.d.ts.map +1 -0
  26. package/dist/commands/status.js +67 -0
  27. package/dist/commands/status.js.map +1 -0
  28. package/dist/commands/validate.d.ts +9 -0
  29. package/dist/commands/validate.d.ts.map +1 -0
  30. package/dist/commands/validate.js +84 -0
  31. package/dist/commands/validate.js.map +1 -0
  32. package/dist/config/load.d.ts +11 -0
  33. package/dist/config/load.d.ts.map +1 -0
  34. package/dist/config/load.js +33 -0
  35. package/dist/config/load.js.map +1 -0
  36. package/dist/config/schema.d.ts +3 -0
  37. package/dist/config/schema.d.ts.map +1 -0
  38. package/dist/config/schema.js +34 -0
  39. package/dist/config/schema.js.map +1 -0
  40. package/dist/config/types.d.ts +14 -0
  41. package/dist/config/types.d.ts.map +1 -0
  42. package/dist/config/types.js +8 -0
  43. package/dist/config/types.js.map +1 -0
  44. package/dist/detect/framework.d.ts +13 -0
  45. package/dist/detect/framework.d.ts.map +1 -0
  46. package/dist/detect/framework.js +52 -0
  47. package/dist/detect/framework.js.map +1 -0
  48. package/dist/editor/validate-config.d.ts +10 -0
  49. package/dist/editor/validate-config.d.ts.map +1 -0
  50. package/dist/editor/validate-config.js +135 -0
  51. package/dist/editor/validate-config.js.map +1 -0
  52. package/dist/exit-codes.d.ts +9 -0
  53. package/dist/exit-codes.d.ts.map +1 -0
  54. package/dist/exit-codes.js +8 -0
  55. package/dist/exit-codes.js.map +1 -0
  56. package/dist/index.d.ts +11 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +11 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/util/fs.d.ts +7 -0
  61. package/dist/util/fs.d.ts.map +1 -0
  62. package/dist/util/fs.js +27 -0
  63. package/dist/util/fs.js.map +1 -0
  64. package/dist/util/paths.d.ts +7 -0
  65. package/dist/util/paths.d.ts.map +1 -0
  66. package/dist/util/paths.js +23 -0
  67. package/dist/util/paths.js.map +1 -0
  68. package/dist/util/print.d.ts +7 -0
  69. package/dist/util/print.d.ts.map +1 -0
  70. package/dist/util/print.js +14 -0
  71. package/dist/util/print.js.map +1 -0
  72. package/dist/util/redact.d.ts +10 -0
  73. package/dist/util/redact.d.ts.map +1 -0
  74. package/dist/util/redact.js +19 -0
  75. package/dist/util/redact.js.map +1 -0
  76. package/dist/util/spawn.d.ts +11 -0
  77. package/dist/util/spawn.d.ts.map +1 -0
  78. package/dist/util/spawn.js +32 -0
  79. package/dist/util/spawn.js.map +1 -0
  80. package/package.json +52 -3
@@ -0,0 +1,129 @@
1
+ import path from "node:path";
2
+ import { CONFIG_FILE_NAME, DEFAULT_CONFIG, } from "../config/types.js";
3
+ import { detectFrameworkFromPackage, readPackageJson, } from "../detect/framework.js";
4
+ import { ExitCode } from "../exit-codes.js";
5
+ import { ensureDir, writeFileSafe } from "../util/fs.js";
6
+ export async function runInit(options, log) {
7
+ const pkg = await readPackageJson(options.projectRoot);
8
+ if (pkg === null) {
9
+ log.error("No package.json found. Create a Node project (Astro or Vite) before running contentrail init.");
10
+ return ExitCode.Config;
11
+ }
12
+ const detected = detectFrameworkFromPackage(pkg);
13
+ const framework = options.framework === "astro" || options.framework === "vite"
14
+ ? options.framework
15
+ : detected === "unknown"
16
+ ? null
17
+ : detected;
18
+ if (framework === null) {
19
+ log.error("Unsupported or undetected framework. ContentRail Phase 6 supports Astro and Vite only.\n" +
20
+ "Install `astro` or `vite`, or pass `--framework astro|vite`.");
21
+ return ExitCode.Config;
22
+ }
23
+ if (detected === "unknown" &&
24
+ options.framework === undefined &&
25
+ !options.yes) {
26
+ log.warn(`No framework dependency detected; using --framework ${framework} from flags/defaults.`);
27
+ }
28
+ const collectionsPath = framework === "astro" ? "src/contentrail/config.ts" : "content/config.ts";
29
+ const config = {
30
+ ...DEFAULT_CONFIG,
31
+ framework,
32
+ collections: collectionsPath,
33
+ contentRoot: "content",
34
+ ...(options.withEditor ? { editorConfig: "contentrail.editor.json" } : {}),
35
+ };
36
+ const written = [];
37
+ const skipped = [];
38
+ const configResult = await writeFileSafe(path.join(options.projectRoot, CONFIG_FILE_NAME), `${JSON.stringify(config, null, 2)}\n`, { force: options.force });
39
+ (configResult === "written" ? written : skipped).push(CONFIG_FILE_NAME);
40
+ const collectionSource = collectionModuleSource();
41
+ const collectionResult = await writeFileSafe(path.join(options.projectRoot, collectionsPath), collectionSource, { force: options.force });
42
+ (collectionResult === "written" ? written : skipped).push(collectionsPath);
43
+ await ensureDir(path.join(options.projectRoot, "content", "articles"));
44
+ const sampleEntry = path.join(options.projectRoot, "content", "articles", "welcome.json");
45
+ const entryResult = await writeFileSafe(sampleEntry, `${JSON.stringify({
46
+ title: "Welcome",
47
+ slug: "welcome",
48
+ published: true,
49
+ summary: "First ContentRail entry.",
50
+ body: "Edit this JSON or use the ContentRail editor.",
51
+ }, null, 2)}\n`, { force: options.force });
52
+ (entryResult === "written" ? written : skipped).push("content/articles/welcome.json");
53
+ if (options.withEditor) {
54
+ const editorResult = await writeFileSafe(path.join(options.projectRoot, "contentrail.editor.json"), `${JSON.stringify({
55
+ collections: [
56
+ {
57
+ name: "articles",
58
+ label: "Articles",
59
+ titleField: "title",
60
+ fields: [
61
+ {
62
+ name: "title",
63
+ label: "Title",
64
+ widget: "text",
65
+ required: true,
66
+ order: 10,
67
+ },
68
+ {
69
+ name: "slug",
70
+ label: "Slug",
71
+ widget: "text",
72
+ required: true,
73
+ order: 20,
74
+ },
75
+ {
76
+ name: "published",
77
+ label: "Published",
78
+ widget: "boolean",
79
+ order: 30,
80
+ },
81
+ {
82
+ name: "summary",
83
+ label: "Summary",
84
+ widget: "textarea",
85
+ required: true,
86
+ order: 40,
87
+ },
88
+ {
89
+ name: "body",
90
+ label: "Body",
91
+ widget: "textarea",
92
+ required: true,
93
+ order: 50,
94
+ },
95
+ ],
96
+ },
97
+ ],
98
+ }, null, 2)}\n`, { force: options.force });
99
+ (editorResult === "written" ? written : skipped).push("contentrail.editor.json");
100
+ }
101
+ log.info(`ContentRail initialized for ${framework}.`);
102
+ if (written.length > 0) {
103
+ log.info(`Created:\n${written.map((item) => ` - ${item}`).join("\n")}`);
104
+ }
105
+ if (skipped.length > 0) {
106
+ log.info(`Left existing files unchanged (use --force to overwrite):\n${skipped
107
+ .map((item) => ` - ${item}`)
108
+ .join("\n")}`);
109
+ }
110
+ log.info("Next: add dependencies (@contentrail/core, framework integration), then run `contentrail validate`.");
111
+ return ExitCode.Success;
112
+ }
113
+ function collectionModuleSource() {
114
+ return `import { defineCollection } from "@contentrail/core";
115
+ import { z } from "zod";
116
+
117
+ export const articles = defineCollection({
118
+ name: "articles",
119
+ schema: z.object({
120
+ title: z.string().min(1),
121
+ slug: z.string().min(1),
122
+ published: z.boolean(),
123
+ summary: z.string().min(1),
124
+ body: z.string().min(1),
125
+ }),
126
+ });
127
+ `;
128
+ }
129
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { ExitCode } from "../exit-codes.js";
2
+ import type { Logger } from "../util/print.js";
3
+ export declare function runStatus(projectRoot: string, log: Logger): Promise<ExitCode>;
4
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG/C,wBAAsB,SAAS,CAC7B,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,QAAQ,CAAC,CA2EnB"}
@@ -0,0 +1,67 @@
1
+ import { loadCollectionsModule } from "../collections/load.js";
2
+ import { loadProject } from "../config/load.js";
3
+ import { detectFrameworkFromPackage, detectPackageManager, readPackageJson, resolveFramework, } from "../detect/framework.js";
4
+ import { ExitCode } from "../exit-codes.js";
5
+ import { pathExists } from "../util/fs.js";
6
+ import { runValidate } from "./validate.js";
7
+ export async function runStatus(projectRoot, log) {
8
+ const pkg = await readPackageJson(projectRoot);
9
+ const detected = detectFrameworkFromPackage(pkg);
10
+ const pm = await detectPackageManager(projectRoot);
11
+ log.info(`Project: ${projectRoot}`);
12
+ log.info(`Package manager: ${pm}`);
13
+ log.info(`Detected framework deps: ${detected}`);
14
+ let project;
15
+ try {
16
+ project = await loadProject(projectRoot);
17
+ }
18
+ catch (error) {
19
+ log.error(error instanceof Error ? error.message : String(error));
20
+ log.info("Local build readiness: no (missing/invalid config)");
21
+ log.info("Remote publishing configured: no");
22
+ return ExitCode.Config;
23
+ }
24
+ const framework = resolveFramework(project.config.framework, detected);
25
+ log.info(`Configured framework: ${project.config.framework} → ${framework}`);
26
+ log.info(`Content root: ${project.config.contentRoot}`);
27
+ log.info(`Collections module: ${project.config.collections}`);
28
+ log.info(`Build script: ${project.config.buildScript}`);
29
+ try {
30
+ const collections = await loadCollectionsModule(project.collectionsAbs);
31
+ log.info(`Collections: ${collections.map((collection) => collection.name).join(", ")}`);
32
+ }
33
+ catch (error) {
34
+ log.warn(`Collections: unavailable (${error instanceof Error ? error.message : String(error)})`);
35
+ }
36
+ const silentLog = {
37
+ info() { },
38
+ warn: log.warn,
39
+ error() { },
40
+ };
41
+ const validation = await runValidate(project, silentLog);
42
+ log.info(`Local validation: ${validation.code === ExitCode.Success ? "pass" : "fail"}`);
43
+ if (validation.errors.length > 0) {
44
+ for (const message of validation.errors.slice(0, 5)) {
45
+ log.warn(` - ${message}`);
46
+ }
47
+ if (validation.errors.length > 5) {
48
+ log.warn(` … and ${validation.errors.length - 5} more`);
49
+ }
50
+ }
51
+ const hasBuildScript = pkg?.scripts?.[project.config.buildScript] !== undefined;
52
+ const contentOk = await pathExists(project.contentRootAbs);
53
+ const buildReady = validation.code === ExitCode.Success &&
54
+ hasBuildScript &&
55
+ contentOk &&
56
+ framework !== "unknown";
57
+ log.info(`Local build readiness: ${buildReady ? "yes" : "no"}`);
58
+ const remoteConfigured = project.config.publishApiUrl !== undefined;
59
+ log.info(`Remote publishing configured: ${remoteConfigured ? "yes (URL present; live health not checked)" : "no"}`);
60
+ if (remoteConfigured) {
61
+ log.info(`publishApiUrl: ${project.config.publishApiUrl}`);
62
+ }
63
+ return validation.code === ExitCode.Success
64
+ ? ExitCode.Success
65
+ : ExitCode.Failure;
66
+ }
67
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { LoadedProject } from "../config/load.js";
2
+ import { ExitCode } from "../exit-codes.js";
3
+ import type { Logger } from "../util/print.js";
4
+ export interface ValidateResult {
5
+ readonly code: ExitCode;
6
+ readonly errors: string[];
7
+ }
8
+ export declare function runValidate(project: LoadedProject, log: Logger): Promise<ValidateResult>;
9
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE/C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,aAAa,EACtB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,cAAc,CAAC,CAqFzB"}
@@ -0,0 +1,84 @@
1
+ import { createLocalJsonSource, loadCollection, ContentReadError, } from "@contentrail/reader";
2
+ import { loadCollectionsModule } from "../collections/load.js";
3
+ import { validateEditorConfigFile } from "../editor/validate-config.js";
4
+ import { ExitCode } from "../exit-codes.js";
5
+ import { pathExists } from "../util/fs.js";
6
+ export async function runValidate(project, log) {
7
+ const errors = [];
8
+ if (!(await pathExists(project.contentRootAbs))) {
9
+ errors.push(`Content root does not exist: ${project.config.contentRoot}`);
10
+ }
11
+ let collections;
12
+ try {
13
+ collections = await loadCollectionsModule(project.collectionsAbs);
14
+ }
15
+ catch (error) {
16
+ errors.push(error instanceof Error ? error.message : String(error));
17
+ for (const message of errors) {
18
+ log.error(message);
19
+ }
20
+ return { code: ExitCode.Failure, errors };
21
+ }
22
+ if (await pathExists(project.contentRootAbs)) {
23
+ try {
24
+ const source = await createLocalJsonSource({
25
+ rootDir: project.contentRootAbs,
26
+ });
27
+ for (const collection of collections) {
28
+ try {
29
+ const entries = await loadCollection(source, collection);
30
+ const slugs = new Map();
31
+ for (const entry of entries) {
32
+ const data = entry.data;
33
+ if (typeof data.slug === "string") {
34
+ const prior = slugs.get(data.slug);
35
+ if (prior !== undefined) {
36
+ errors.push(`Duplicate slug "${data.slug}" in collection "${collection.name}" (entries "${prior}" and "${entry.id}").`);
37
+ }
38
+ else {
39
+ slugs.set(data.slug, entry.id);
40
+ }
41
+ }
42
+ }
43
+ log.info(`OK ${collection.name}: ${entries.length} entr${entries.length === 1 ? "y" : "ies"}`);
44
+ }
45
+ catch (error) {
46
+ if (error instanceof ContentReadError) {
47
+ const location = error.path !== undefined ? ` (${error.path})` : "";
48
+ errors.push(`${error.message}${location}`);
49
+ }
50
+ else {
51
+ errors.push(error instanceof Error ? error.message : String(error));
52
+ }
53
+ }
54
+ }
55
+ }
56
+ catch (error) {
57
+ errors.push(error instanceof Error ? error.message : String(error));
58
+ }
59
+ }
60
+ if (project.editorConfigAbs !== undefined) {
61
+ if (!(await pathExists(project.editorConfigAbs))) {
62
+ errors.push(`editorConfig not found: ${project.config.editorConfig ?? ""}`);
63
+ }
64
+ else {
65
+ const editorIssues = await validateEditorConfigFile(project.editorConfigAbs);
66
+ for (const issue of editorIssues) {
67
+ errors.push(`editorConfig ${issue.path}: ${issue.message}`);
68
+ }
69
+ if (editorIssues.length === 0) {
70
+ log.info(`OK editor config: ${project.config.editorConfig}`);
71
+ }
72
+ }
73
+ }
74
+ if (errors.length > 0) {
75
+ for (const message of errors) {
76
+ log.error(message);
77
+ }
78
+ log.error(`Validation failed with ${errors.length} error(s).`);
79
+ return { code: ExitCode.Failure, errors };
80
+ }
81
+ log.info("Validation passed.");
82
+ return { code: ExitCode.Success, errors };
83
+ }
84
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { type ContentRailProjectConfig } from "./types.js";
2
+ export interface LoadedProject {
3
+ readonly projectRoot: string;
4
+ readonly configPath: string;
5
+ readonly config: ContentRailProjectConfig;
6
+ readonly contentRootAbs: string;
7
+ readonly collectionsAbs: string;
8
+ readonly editorConfigAbs?: string;
9
+ }
10
+ export declare function loadProject(projectRoot: string): Promise<LoadedProject>;
11
+ //# sourceMappingURL=load.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/config/load.ts"],"names":[],"mappings":"AAIA,OAAO,EAAoB,KAAK,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAE7E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC;IAC1C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;CACnC;AAED,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAyC7E"}
@@ -0,0 +1,33 @@
1
+ import path from "node:path";
2
+ import { pathExists, readJsonFile } from "../util/fs.js";
3
+ import { resolveProjectPath } from "../util/paths.js";
4
+ import { parseProjectConfig } from "./schema.js";
5
+ import { CONFIG_FILE_NAME } from "./types.js";
6
+ export async function loadProject(projectRoot) {
7
+ const configPath = path.join(projectRoot, CONFIG_FILE_NAME);
8
+ if (!(await pathExists(configPath))) {
9
+ throw new Error(`Missing ${CONFIG_FILE_NAME} in ${projectRoot}. Run \`contentrail init\` first.`);
10
+ }
11
+ let raw;
12
+ try {
13
+ raw = await readJsonFile(configPath);
14
+ }
15
+ catch (error) {
16
+ throw new Error(`Unable to read ${CONFIG_FILE_NAME}: ${error instanceof Error ? error.message : String(error)}`);
17
+ }
18
+ const config = parseProjectConfig(raw);
19
+ const contentRootAbs = resolveProjectPath(projectRoot, config.contentRoot, "contentRoot");
20
+ const collectionsAbs = resolveProjectPath(projectRoot, config.collections, "collections");
21
+ const editorConfigAbs = config.editorConfig !== undefined
22
+ ? resolveProjectPath(projectRoot, config.editorConfig, "editorConfig")
23
+ : undefined;
24
+ return {
25
+ projectRoot,
26
+ configPath,
27
+ config,
28
+ contentRootAbs,
29
+ collectionsAbs,
30
+ ...(editorConfigAbs !== undefined ? { editorConfigAbs } : {}),
31
+ };
32
+ }
33
+ //# sourceMappingURL=load.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/config/load.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAiC,MAAM,YAAY,CAAC;AAW7E,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,WAAmB;IACnD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;IAC5D,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CACb,WAAW,gBAAgB,OAAO,WAAW,mCAAmC,CACjF,CAAC;IACJ,CAAC;IAED,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,YAAY,CAAC,UAAU,CAAC,CAAC;IACvC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,kBAAkB,gBAAgB,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAChG,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,cAAc,GAAG,kBAAkB,CACvC,WAAW,EACX,MAAM,CAAC,WAAW,EAClB,aAAa,CACd,CAAC;IACF,MAAM,cAAc,GAAG,kBAAkB,CACvC,WAAW,EACX,MAAM,CAAC,WAAW,EAClB,aAAa,CACd,CAAC;IACF,MAAM,eAAe,GACnB,MAAM,CAAC,YAAY,KAAK,SAAS;QAC/B,CAAC,CAAC,kBAAkB,CAAC,WAAW,EAAE,MAAM,CAAC,YAAY,EAAE,cAAc,CAAC;QACtE,CAAC,CAAC,SAAS,CAAC;IAEhB,OAAO;QACL,WAAW;QACX,UAAU;QACV,MAAM;QACN,cAAc;QACd,cAAc;QACd,GAAG,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9D,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ContentRailProjectConfig } from "./types.js";
2
+ export declare function parseProjectConfig(raw: unknown): ContentRailProjectConfig;
3
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAa3D,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,wBAAwB,CAqBzE"}
@@ -0,0 +1,34 @@
1
+ import { z } from "zod";
2
+ const configSchema = z
3
+ .object({
4
+ contentRoot: z.string().min(1).default("content"),
5
+ framework: z.enum(["astro", "vite", "auto"]).default("auto"),
6
+ collections: z.string().min(1),
7
+ buildScript: z.string().min(1).default("build"),
8
+ editorConfig: z.string().min(1).optional(),
9
+ publishApiUrl: z.string().url().optional(),
10
+ })
11
+ .strict();
12
+ export function parseProjectConfig(raw) {
13
+ const parsed = configSchema.safeParse(raw);
14
+ if (!parsed.success) {
15
+ const detail = parsed.error.issues
16
+ .map((issue) => `${issue.path.join(".") || "(root)"}: ${issue.message}`)
17
+ .join("; ");
18
+ throw new Error(`Invalid contentrail.config.json — ${detail}`);
19
+ }
20
+ const data = parsed.data;
21
+ return {
22
+ contentRoot: data.contentRoot,
23
+ framework: data.framework,
24
+ collections: data.collections,
25
+ buildScript: data.buildScript,
26
+ ...(data.editorConfig !== undefined
27
+ ? { editorConfig: data.editorConfig }
28
+ : {}),
29
+ ...(data.publishApiUrl !== undefined
30
+ ? { publishApiUrl: data.publishApiUrl }
31
+ : {}),
32
+ };
33
+ }
34
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,YAAY,GAAG,CAAC;KACnB,MAAM,CAAC;IACN,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;IACjD,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAC5D,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IAC/C,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC1C,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;CAC3C,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ,MAAM,UAAU,kBAAkB,CAAC,GAAY;IAC7C,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAC3C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM;aAC/B,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;aACvE,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,qCAAqC,MAAM,EAAE,CAAC,CAAC;IACjE,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IACzB,OAAO;QACL,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,GAAG,CAAC,IAAI,CAAC,YAAY,KAAK,SAAS;YACjC,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE;YACrC,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,IAAI,CAAC,aAAa,KAAK,SAAS;YAClC,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE;YACvC,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,14 @@
1
+ export type FrameworkKind = "astro" | "vite" | "auto";
2
+ export interface ContentRailProjectConfig {
3
+ readonly contentRoot: string;
4
+ readonly framework: FrameworkKind;
5
+ /** Module exporting ContentCollection values (named exports). */
6
+ readonly collections: string;
7
+ readonly buildScript: string;
8
+ readonly editorConfig?: string;
9
+ /** Optional Worker URL for structural doctor/status checks only. */
10
+ readonly publishApiUrl?: string;
11
+ }
12
+ export declare const CONFIG_FILE_NAME = "contentrail.config.json";
13
+ export declare const DEFAULT_CONFIG: ContentRailProjectConfig;
14
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEtD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,iEAAiE;IACjE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,oEAAoE;IACpE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,eAAO,MAAM,gBAAgB,4BAA4B,CAAC;AAE1D,eAAO,MAAM,cAAc,EAAE,wBAK5B,CAAC"}
@@ -0,0 +1,8 @@
1
+ export const CONFIG_FILE_NAME = "contentrail.config.json";
2
+ export const DEFAULT_CONFIG = {
3
+ contentRoot: "content",
4
+ framework: "auto",
5
+ collections: "content/config.ts",
6
+ buildScript: "build",
7
+ };
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"AAaA,MAAM,CAAC,MAAM,gBAAgB,GAAG,yBAAyB,CAAC;AAE1D,MAAM,CAAC,MAAM,cAAc,GAA6B;IACtD,WAAW,EAAE,SAAS;IACtB,SAAS,EAAE,MAAM;IACjB,WAAW,EAAE,mBAAmB;IAChC,WAAW,EAAE,OAAO;CACrB,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { FrameworkKind } from "../config/types.js";
2
+ export type DetectedFramework = "astro" | "vite" | "unknown";
3
+ export interface PackageJsonShape {
4
+ readonly name?: string;
5
+ readonly scripts?: Record<string, string>;
6
+ readonly dependencies?: Record<string, string>;
7
+ readonly devDependencies?: Record<string, string>;
8
+ }
9
+ export declare function readPackageJson(projectRoot: string): Promise<PackageJsonShape | null>;
10
+ export declare function detectFrameworkFromPackage(pkg: PackageJsonShape | null): DetectedFramework;
11
+ export declare function resolveFramework(configured: FrameworkKind, detected: DetectedFramework): DetectedFramework;
12
+ export declare function detectPackageManager(projectRoot: string): Promise<"pnpm" | "npm" | "yarn" | "unknown">;
13
+ //# sourceMappingURL=framework.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framework.d.ts","sourceRoot":"","sources":["../../src/detect/framework.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnD;AAED,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CASlC;AAED,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,gBAAgB,GAAG,IAAI,GAC3B,iBAAiB,CAqBnB;AAED,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,aAAa,EACzB,QAAQ,EAAE,iBAAiB,GAC1B,iBAAiB,CAKnB;AAED,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC,CAW9C"}
@@ -0,0 +1,52 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { pathExists } from "../util/fs.js";
4
+ export async function readPackageJson(projectRoot) {
5
+ const filePath = path.join(projectRoot, "package.json");
6
+ if (!(await pathExists(filePath))) {
7
+ return null;
8
+ }
9
+ const raw = JSON.parse(await fs.readFile(filePath, "utf8"));
10
+ return raw;
11
+ }
12
+ export function detectFrameworkFromPackage(pkg) {
13
+ if (pkg === null) {
14
+ return "unknown";
15
+ }
16
+ const deps = {
17
+ ...pkg.dependencies,
18
+ ...pkg.devDependencies,
19
+ };
20
+ const hasAstro = typeof deps.astro === "string";
21
+ const hasVite = typeof deps.vite === "string";
22
+ if (hasAstro && !hasVite) {
23
+ return "astro";
24
+ }
25
+ if (hasVite && !hasAstro) {
26
+ return "vite";
27
+ }
28
+ if (hasAstro && hasVite) {
29
+ // Astro projects often include Vite transitively as a direct dep too.
30
+ return "astro";
31
+ }
32
+ return "unknown";
33
+ }
34
+ export function resolveFramework(configured, detected) {
35
+ if (configured === "astro" || configured === "vite") {
36
+ return configured;
37
+ }
38
+ return detected;
39
+ }
40
+ export async function detectPackageManager(projectRoot) {
41
+ if (await pathExists(path.join(projectRoot, "pnpm-lock.yaml"))) {
42
+ return "pnpm";
43
+ }
44
+ if (await pathExists(path.join(projectRoot, "yarn.lock"))) {
45
+ return "yarn";
46
+ }
47
+ if (await pathExists(path.join(projectRoot, "package-lock.json"))) {
48
+ return "npm";
49
+ }
50
+ return "unknown";
51
+ }
52
+ //# sourceMappingURL=framework.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framework.js","sourceRoot":"","sources":["../../src/detect/framework.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAY3C,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,WAAmB;IAEnB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IACxD,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACpB,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAChB,CAAC;IACtB,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,GAA4B;IAE5B,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,IAAI,GAAG;QACX,GAAG,GAAG,CAAC,YAAY;QACnB,GAAG,GAAG,CAAC,eAAe;KACvB,CAAC;IACF,MAAM,QAAQ,GAAG,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC;IAChD,MAAM,OAAO,GAAG,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC;IAC9C,IAAI,QAAQ,IAAI,CAAC,OAAO,EAAE,CAAC;QACzB,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IAAI,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;QACzB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,QAAQ,IAAI,OAAO,EAAE,CAAC;QACxB,sEAAsE;QACtE,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,UAAyB,EACzB,QAA2B;IAE3B,IAAI,UAAU,KAAK,OAAO,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;QACpD,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,WAAmB;IAEnB,IAAI,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC;QAC/D,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC;QAC1D,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC;QAClE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,10 @@
1
+ export interface EditorValidationIssue {
2
+ readonly path: string;
3
+ readonly message: string;
4
+ }
5
+ /**
6
+ * Structural validation of ADR 019 editor metadata JSON.
7
+ * Does not load Preact or @contentrail/editor.
8
+ */
9
+ export declare function validateEditorConfigFile(absolutePath: string): Promise<EditorValidationIssue[]>;
10
+ //# sourceMappingURL=validate-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-config.d.ts","sourceRoot":"","sources":["../../src/editor/validate-config.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAmClC"}