octocms 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 (64) hide show
  1. package/dist/agentDocs-Z5BI2Y2G.js +38 -0
  2. package/dist/agentDocs-Z5BI2Y2G.js.map +1 -0
  3. package/dist/chunk-4MPOTHTY.js +9 -0
  4. package/dist/chunk-4MPOTHTY.js.map +1 -0
  5. package/dist/chunk-4VLN5EX2.js +9204 -0
  6. package/dist/chunk-4VLN5EX2.js.map +1 -0
  7. package/dist/chunk-6PHFHGTZ.js +35 -0
  8. package/dist/chunk-6PHFHGTZ.js.map +1 -0
  9. package/dist/chunk-7CFFE2I6.js +55 -0
  10. package/dist/chunk-7CFFE2I6.js.map +1 -0
  11. package/dist/chunk-B47VXAHT.js +28 -0
  12. package/dist/chunk-B47VXAHT.js.map +1 -0
  13. package/dist/chunk-BRTXBBVQ.js +46 -0
  14. package/dist/chunk-BRTXBBVQ.js.map +1 -0
  15. package/dist/chunk-C62C776U.js +79 -0
  16. package/dist/chunk-C62C776U.js.map +1 -0
  17. package/dist/chunk-I7KNSICQ.js +114 -0
  18. package/dist/chunk-I7KNSICQ.js.map +1 -0
  19. package/dist/chunk-Q73JSGXV.js +123 -0
  20. package/dist/chunk-Q73JSGXV.js.map +1 -0
  21. package/dist/chunk-W6QJTGBC.js +57 -0
  22. package/dist/chunk-W6QJTGBC.js.map +1 -0
  23. package/dist/cli/index.js +196 -0
  24. package/dist/cli/index.js.map +1 -0
  25. package/dist/components/public/index.d.mts +40 -0
  26. package/dist/components/public/index.js +401 -0
  27. package/dist/components/public/index.js.map +1 -0
  28. package/dist/config.d.mts +4 -0
  29. package/dist/config.js +13 -0
  30. package/dist/config.js.map +1 -0
  31. package/dist/defineConfig.d.mts +126 -0
  32. package/dist/defineConfig.js +8 -0
  33. package/dist/defineConfig.js.map +1 -0
  34. package/dist/dev-QY534GEH.js +87 -0
  35. package/dist/dev-QY534GEH.js.map +1 -0
  36. package/dist/index.d.mts +5 -0
  37. package/dist/index.js +17 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/init-UGUTJFFI.js +145 -0
  40. package/dist/init-UGUTJFFI.js.map +1 -0
  41. package/dist/jiti-VYEW7A6R.js +3068 -0
  42. package/dist/jiti-VYEW7A6R.js.map +1 -0
  43. package/dist/localReader-I2THES24.js +40 -0
  44. package/dist/localReader-I2THES24.js.map +1 -0
  45. package/dist/query.d.mts +112 -0
  46. package/dist/query.js +11 -0
  47. package/dist/query.js.map +1 -0
  48. package/dist/types.d.mts +352 -0
  49. package/dist/types.js +1 -0
  50. package/dist/types.js.map +1 -0
  51. package/dist/typesGen-WBC6CNBG.js +241 -0
  52. package/dist/typesGen-WBC6CNBG.js.map +1 -0
  53. package/dist/update-RMGZMS56.js +57 -0
  54. package/dist/update-RMGZMS56.js.map +1 -0
  55. package/dist/validate-OTJ6ULMP.js +297 -0
  56. package/dist/validate-OTJ6ULMP.js.map +1 -0
  57. package/dist/withOctoCMS.d.mts +6 -0
  58. package/dist/withOctoCMS.js +9 -0
  59. package/dist/withOctoCMS.js.map +1 -0
  60. package/docs/index.md +27 -0
  61. package/docs/overview.md +113 -0
  62. package/docs/schema.md +279 -0
  63. package/globals.css +198 -0
  64. package/package.json +116 -0
@@ -0,0 +1,35 @@
1
+ // cli/lib/logger.ts
2
+ var RESET = "\x1B[0m";
3
+ var BOLD = "\x1B[1m";
4
+ var DIM = "\x1B[2m";
5
+ var RED = "\x1B[31m";
6
+ var GREEN = "\x1B[32m";
7
+ var YELLOW = "\x1B[33m";
8
+ var CYAN = "\x1B[36m";
9
+ var fmt = {
10
+ bold: (s) => `${BOLD}${s}${RESET}`,
11
+ dim: (s) => `${DIM}${s}${RESET}`,
12
+ red: (s) => `${RED}${s}${RESET}`,
13
+ green: (s) => `${GREEN}${s}${RESET}`,
14
+ yellow: (s) => `${YELLOW}${s}${RESET}`,
15
+ cyan: (s) => `${CYAN}${s}${RESET}`
16
+ };
17
+ var log = {
18
+ info: (msg) => console.log(` ${msg}`),
19
+ success: (msg) => console.log(` ${fmt.green("\u2713")} ${msg}`),
20
+ warn: (msg) => console.log(` ${fmt.yellow("\u26A0")} ${msg}`),
21
+ error: (msg) => console.error(` ${fmt.red("\u2717")} ${msg}`),
22
+ step: (msg) => console.log(` ${fmt.cyan("\u21BB")} ${msg}`),
23
+ blank: () => console.log(),
24
+ header: (title) => {
25
+ console.log();
26
+ console.log(` ${fmt.bold(`OctoCMS`)} \u2014 ${title}`);
27
+ console.log();
28
+ }
29
+ };
30
+
31
+ export {
32
+ fmt,
33
+ log
34
+ };
35
+ //# sourceMappingURL=chunk-6PHFHGTZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../cli/lib/logger.ts"],"sourcesContent":["/* eslint-disable no-console */\n/** ANSI color helpers for CLI output. No external dependencies. */\n\nconst RESET = '\\x1b[0m';\nconst BOLD = '\\x1b[1m';\nconst DIM = '\\x1b[2m';\nconst RED = '\\x1b[31m';\nconst GREEN = '\\x1b[32m';\nconst YELLOW = '\\x1b[33m';\nconst CYAN = '\\x1b[36m';\n\nexport const fmt = {\n bold: (s: string) => `${BOLD}${s}${RESET}`,\n dim: (s: string) => `${DIM}${s}${RESET}`,\n red: (s: string) => `${RED}${s}${RESET}`,\n green: (s: string) => `${GREEN}${s}${RESET}`,\n yellow: (s: string) => `${YELLOW}${s}${RESET}`,\n cyan: (s: string) => `${CYAN}${s}${RESET}`,\n};\n\nexport const log = {\n info: (msg: string) => console.log(` ${msg}`),\n success: (msg: string) => console.log(` ${fmt.green('✓')} ${msg}`),\n warn: (msg: string) => console.log(` ${fmt.yellow('⚠')} ${msg}`),\n error: (msg: string) => console.error(` ${fmt.red('✗')} ${msg}`),\n step: (msg: string) => console.log(` ${fmt.cyan('↻')} ${msg}`),\n blank: () => console.log(),\n header: (title: string) => {\n console.log();\n console.log(` ${fmt.bold(`OctoCMS`)} — ${title}`);\n console.log();\n },\n};\n"],"mappings":";AAGA,IAAM,QAAQ;AACd,IAAM,OAAO;AACb,IAAM,MAAM;AACZ,IAAM,MAAM;AACZ,IAAM,QAAQ;AACd,IAAM,SAAS;AACf,IAAM,OAAO;AAEN,IAAM,MAAM;AAAA,EACjB,MAAM,CAAC,MAAc,GAAG,IAAI,GAAG,CAAC,GAAG,KAAK;AAAA,EACxC,KAAK,CAAC,MAAc,GAAG,GAAG,GAAG,CAAC,GAAG,KAAK;AAAA,EACtC,KAAK,CAAC,MAAc,GAAG,GAAG,GAAG,CAAC,GAAG,KAAK;AAAA,EACtC,OAAO,CAAC,MAAc,GAAG,KAAK,GAAG,CAAC,GAAG,KAAK;AAAA,EAC1C,QAAQ,CAAC,MAAc,GAAG,MAAM,GAAG,CAAC,GAAG,KAAK;AAAA,EAC5C,MAAM,CAAC,MAAc,GAAG,IAAI,GAAG,CAAC,GAAG,KAAK;AAC1C;AAEO,IAAM,MAAM;AAAA,EACjB,MAAM,CAAC,QAAgB,QAAQ,IAAI,KAAK,GAAG,EAAE;AAAA,EAC7C,SAAS,CAAC,QAAgB,QAAQ,IAAI,KAAK,IAAI,MAAM,QAAG,CAAC,IAAI,GAAG,EAAE;AAAA,EAClE,MAAM,CAAC,QAAgB,QAAQ,IAAI,KAAK,IAAI,OAAO,QAAG,CAAC,IAAI,GAAG,EAAE;AAAA,EAChE,OAAO,CAAC,QAAgB,QAAQ,MAAM,KAAK,IAAI,IAAI,QAAG,CAAC,IAAI,GAAG,EAAE;AAAA,EAChE,MAAM,CAAC,QAAgB,QAAQ,IAAI,KAAK,IAAI,KAAK,QAAG,CAAC,IAAI,GAAG,EAAE;AAAA,EAC9D,OAAO,MAAM,QAAQ,IAAI;AAAA,EACzB,QAAQ,CAAC,UAAkB;AACzB,YAAQ,IAAI;AACZ,YAAQ,IAAI,KAAK,IAAI,KAAK,SAAS,CAAC,WAAM,KAAK,EAAE;AACjD,YAAQ,IAAI;AAAA,EACd;AACF;","names":[]}
@@ -0,0 +1,55 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __defProps = Object.defineProperties;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
11
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
12
+ var __spreadValues = (a, b) => {
13
+ for (var prop in b || (b = {}))
14
+ if (__hasOwnProp.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ if (__getOwnPropSymbols)
17
+ for (var prop of __getOwnPropSymbols(b)) {
18
+ if (__propIsEnum.call(b, prop))
19
+ __defNormalProp(a, prop, b[prop]);
20
+ }
21
+ return a;
22
+ };
23
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
24
+ var __commonJS = (cb, mod) => function __require() {
25
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
26
+ };
27
+ var __export = (target, all) => {
28
+ for (var name in all)
29
+ __defProp(target, name, { get: all[name], enumerable: true });
30
+ };
31
+ var __copyProps = (to, from, except, desc) => {
32
+ if (from && typeof from === "object" || typeof from === "function") {
33
+ for (let key of __getOwnPropNames(from))
34
+ if (!__hasOwnProp.call(to, key) && key !== except)
35
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
36
+ }
37
+ return to;
38
+ };
39
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
40
+ // If the importer is in node compatibility mode or this is not an ESM
41
+ // file that has been converted to a CommonJS file using a Babel-
42
+ // compatible transform (i.e. "__esModule" has not been set), then set
43
+ // "default" to the CommonJS "module.exports" for node compatibility.
44
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
45
+ mod
46
+ ));
47
+
48
+ export {
49
+ __spreadValues,
50
+ __spreadProps,
51
+ __commonJS,
52
+ __export,
53
+ __toESM
54
+ };
55
+ //# sourceMappingURL=chunk-7CFFE2I6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,28 @@
1
+ // lib/configStore.ts
2
+ var _config = null;
3
+ function setConfig(config) {
4
+ _config = config;
5
+ }
6
+ function getConfig() {
7
+ if (!_config) {
8
+ throw new Error(
9
+ "OctoCMS config not initialized. Make sure withOctoCMS(nextConfig, config) is called in next.config.ts and cms/__generated__/configInit.ts is imported in your admin layout."
10
+ );
11
+ }
12
+ return _config;
13
+ }
14
+
15
+ // lib/githubContentMode.ts
16
+ function isProductionMode() {
17
+ if (process.env.CMS_FORCE_GITHUB_API === "true") {
18
+ return true;
19
+ }
20
+ return process.env.NODE_ENV === "production";
21
+ }
22
+
23
+ export {
24
+ setConfig,
25
+ getConfig,
26
+ isProductionMode
27
+ };
28
+ //# sourceMappingURL=chunk-B47VXAHT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../lib/configStore.ts","../lib/githubContentMode.ts"],"sourcesContent":["import type { Config } from '../types';\n\nlet _config: Config | null = null;\n\n/**\n * Register the app config. Called once by `withOctoCMS()` in `next.config.ts`\n * and by the generated `cms/__generated__/configInit.ts` side-effect module\n * (ensures the singleton is populated even in serverless cold starts).\n */\nexport function setConfig(config: Config): void {\n _config = config;\n}\n\n/**\n * Read the registered app config. Throws if `setConfig()` has not been called.\n *\n * All `octocms/` code that needs the runtime config should call this function\n * instead of importing directly from the consumer's `cms/octocms.config.ts`.\n */\nexport function getConfig(): Config {\n if (!_config) {\n throw new Error(\n 'OctoCMS config not initialized. Make sure withOctoCMS(nextConfig, config) is called in next.config.ts ' +\n 'and cms/__generated__/configInit.ts is imported in your admin layout.',\n );\n }\n return _config;\n}\n","/**\n * True when public content reads use the GitHub API (`NODE_ENV=production` or `CMS_FORCE_GITHUB_API=true`).\n * Shared by env validation (including `next.config.ts`) and `@/app/cms/github` / `cms/query`.\n */\nexport function isProductionMode(): boolean {\n if (process.env.CMS_FORCE_GITHUB_API === 'true') {\n return true;\n }\n\n return process.env.NODE_ENV === 'production';\n}\n"],"mappings":";AAEA,IAAI,UAAyB;AAOtB,SAAS,UAAU,QAAsB;AAC9C,YAAU;AACZ;AAQO,SAAS,YAAoB;AAClC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACA,SAAO;AACT;;;ACvBO,SAAS,mBAA4B;AAC1C,MAAI,QAAQ,IAAI,yBAAyB,QAAQ;AAC/C,WAAO;AAAA,EACT;AAEA,SAAO,QAAQ,IAAI,aAAa;AAClC;","names":[]}
@@ -0,0 +1,46 @@
1
+ import {
2
+ isProductionMode,
3
+ setConfig
4
+ } from "./chunk-B47VXAHT.js";
5
+ import {
6
+ __spreadValues
7
+ } from "./chunk-7CFFE2I6.js";
8
+
9
+ // lib/deploymentEnv.ts
10
+ var trimOrEmpty = (value) => typeof value === "string" ? value.trim() : "";
11
+ function getProductionEnvIssues() {
12
+ if (process.env.NODE_ENV !== "production") {
13
+ return [];
14
+ }
15
+ const missing = [];
16
+ if (!trimOrEmpty(process.env.NEXTAUTH_SECRET)) missing.push("NEXTAUTH_SECRET");
17
+ if (!trimOrEmpty(process.env.GITHUB_ID)) missing.push("GITHUB_ID");
18
+ if (!trimOrEmpty(process.env.GITHUB_SECRET)) missing.push("GITHUB_SECRET");
19
+ if (!trimOrEmpty(process.env.NEXTAUTH_URL)) missing.push("NEXTAUTH_URL");
20
+ if (isProductionMode()) {
21
+ if (!trimOrEmpty(process.env.GITHUB_REPO_OWNER)) missing.push("GITHUB_REPO_OWNER");
22
+ if (!trimOrEmpty(process.env.GITHUB_REPO_NAME)) missing.push("GITHUB_REPO_NAME");
23
+ }
24
+ return missing;
25
+ }
26
+ function assertProductionEnvOrThrow() {
27
+ const missing = getProductionEnvIssues();
28
+ if (missing.length === 0) return;
29
+ throw new Error(
30
+ `Missing required environment variables for production: ${missing.join(", ")}. See README.md (Production requirements) and docs/deployment-errors.md.`
31
+ );
32
+ }
33
+
34
+ // withOctoCMS.ts
35
+ function withOctoCMS(nextConfig = {}, octoConfig) {
36
+ setConfig(octoConfig);
37
+ if (process.env.NODE_ENV === "production") {
38
+ assertProductionEnvOrThrow();
39
+ }
40
+ return __spreadValues({}, nextConfig);
41
+ }
42
+
43
+ export {
44
+ withOctoCMS
45
+ };
46
+ //# sourceMappingURL=chunk-BRTXBBVQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../lib/deploymentEnv.ts","../withOctoCMS.ts"],"sourcesContent":["import { isProductionMode } from './githubContentMode';\n\nconst trimOrEmpty = (value: string | undefined): string => (typeof value === 'string' ? value.trim() : '');\n\n/**\n * Returns env var names that are missing or blank for the current process mode.\n * In non-production, returns an empty array.\n */\nexport function getProductionEnvIssues(): string[] {\n if (process.env.NODE_ENV !== 'production') {\n return [];\n }\n\n const missing: string[] = [];\n\n if (!trimOrEmpty(process.env.NEXTAUTH_SECRET)) missing.push('NEXTAUTH_SECRET');\n if (!trimOrEmpty(process.env.GITHUB_ID)) missing.push('GITHUB_ID');\n if (!trimOrEmpty(process.env.GITHUB_SECRET)) missing.push('GITHUB_SECRET');\n if (!trimOrEmpty(process.env.NEXTAUTH_URL)) missing.push('NEXTAUTH_URL');\n\n if (isProductionMode()) {\n if (!trimOrEmpty(process.env.GITHUB_REPO_OWNER)) missing.push('GITHUB_REPO_OWNER');\n if (!trimOrEmpty(process.env.GITHUB_REPO_NAME)) missing.push('GITHUB_REPO_NAME');\n }\n\n return missing;\n}\n\nexport function assertProductionEnvOrThrow(): void {\n const missing = getProductionEnvIssues();\n if (missing.length === 0) return;\n\n throw new Error(\n `Missing required environment variables for production: ${missing.join(', ')}. ` +\n 'See README.md (Production requirements) and docs/deployment-errors.md.',\n );\n}\n","import type { NextConfig } from 'next';\nimport type { Config } from './types';\nimport { assertProductionEnvOrThrow } from './lib/deploymentEnv';\nimport { setConfig } from './lib/configStore';\n\nexport function withOctoCMS(nextConfig: NextConfig = {}, octoConfig: Config): NextConfig {\n setConfig(octoConfig);\n\n if (process.env.NODE_ENV === 'production') {\n assertProductionEnvOrThrow();\n }\n\n return {\n ...nextConfig,\n };\n}\n"],"mappings":";;;;;;;;;AAEA,IAAM,cAAc,CAAC,UAAuC,OAAO,UAAU,WAAW,MAAM,KAAK,IAAI;AAMhG,SAAS,yBAAmC;AACjD,MAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,UAAoB,CAAC;AAE3B,MAAI,CAAC,YAAY,QAAQ,IAAI,eAAe,EAAG,SAAQ,KAAK,iBAAiB;AAC7E,MAAI,CAAC,YAAY,QAAQ,IAAI,SAAS,EAAG,SAAQ,KAAK,WAAW;AACjE,MAAI,CAAC,YAAY,QAAQ,IAAI,aAAa,EAAG,SAAQ,KAAK,eAAe;AACzE,MAAI,CAAC,YAAY,QAAQ,IAAI,YAAY,EAAG,SAAQ,KAAK,cAAc;AAEvE,MAAI,iBAAiB,GAAG;AACtB,QAAI,CAAC,YAAY,QAAQ,IAAI,iBAAiB,EAAG,SAAQ,KAAK,mBAAmB;AACjF,QAAI,CAAC,YAAY,QAAQ,IAAI,gBAAgB,EAAG,SAAQ,KAAK,kBAAkB;AAAA,EACjF;AAEA,SAAO;AACT;AAEO,SAAS,6BAAmC;AACjD,QAAM,UAAU,uBAAuB;AACvC,MAAI,QAAQ,WAAW,EAAG;AAE1B,QAAM,IAAI;AAAA,IACR,0DAA0D,QAAQ,KAAK,IAAI,CAAC;AAAA,EAE9E;AACF;;;AC/BO,SAAS,YAAY,aAAyB,CAAC,GAAG,YAAgC;AACvF,YAAU,UAAU;AAEpB,MAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,+BAA2B;AAAA,EAC7B;AAEA,SAAO,mBACF;AAEP;","names":[]}
@@ -0,0 +1,79 @@
1
+ // cli/lib/project.ts
2
+ import { existsSync, readFileSync } from "fs";
3
+ import { dirname, join } from "path";
4
+ function resolveProjectRoot(startDir) {
5
+ let dir = startDir != null ? startDir : process.cwd();
6
+ for (; ; ) {
7
+ const nextConfigPath = join(dir, "next.config.ts");
8
+ if (existsSync(nextConfigPath) && readFileSync(nextConfigPath, "utf8").includes("withOctoCMS")) {
9
+ return dir;
10
+ }
11
+ const parent = dirname(dir);
12
+ if (parent === dir) {
13
+ throw new Error("Could not find next.config.ts with withOctoCMS \u2014 are you inside an OctoCMS project?");
14
+ }
15
+ dir = parent;
16
+ }
17
+ }
18
+ async function loadProjectConfig(projectRoot) {
19
+ const { createJiti } = await import("./jiti-VYEW7A6R.js");
20
+ const jiti = createJiti(join(projectRoot, "__cli_loader__.ts"), {
21
+ fsCache: false,
22
+ moduleCache: false,
23
+ alias: {
24
+ "octocms/": join(projectRoot, "octocms/")
25
+ }
26
+ });
27
+ const mod = await jiti.import(join(projectRoot, "cms", "octocms.config.ts"), {
28
+ default: true,
29
+ try: true
30
+ });
31
+ if (!mod || !mod.configOctoCMS) {
32
+ throw new Error("cms/octocms.config.ts must export a `configOctoCMS` object (use defineConfig())");
33
+ }
34
+ return mod.configOctoCMS;
35
+ }
36
+ async function loadCollections(projectRoot) {
37
+ const { createJiti } = await import("./jiti-VYEW7A6R.js");
38
+ const jiti = createJiti(join(projectRoot, "__cli_loader__.ts"), {
39
+ fsCache: false,
40
+ moduleCache: false,
41
+ alias: {
42
+ "octocms/": join(projectRoot, "octocms/")
43
+ }
44
+ });
45
+ const mod = await jiti.import(join(projectRoot, "octocms/admin/consts.ts"), {
46
+ default: true,
47
+ try: true
48
+ });
49
+ if (!mod || !Array.isArray(mod.COLLECTIONS)) {
50
+ throw new Error("Could not load COLLECTIONS from octocms/admin/consts.ts");
51
+ }
52
+ return mod.COLLECTIONS;
53
+ }
54
+ async function loadFieldTypes(projectRoot) {
55
+ const { createJiti } = await import("./jiti-VYEW7A6R.js");
56
+ const jiti = createJiti(join(projectRoot, "__cli_loader__.ts"), {
57
+ fsCache: false,
58
+ moduleCache: false,
59
+ alias: {
60
+ "octocms/": join(projectRoot, "octocms/")
61
+ }
62
+ });
63
+ const mod = await jiti.import(join(projectRoot, "octocms/admin/consts.ts"), {
64
+ default: true,
65
+ try: true
66
+ });
67
+ if (!mod || !Array.isArray(mod.FIELD_TYPES)) {
68
+ throw new Error("Could not load FIELD_TYPES from octocms/admin/consts.ts");
69
+ }
70
+ return mod.FIELD_TYPES;
71
+ }
72
+
73
+ export {
74
+ resolveProjectRoot,
75
+ loadProjectConfig,
76
+ loadCollections,
77
+ loadFieldTypes
78
+ };
79
+ //# sourceMappingURL=chunk-C62C776U.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../cli/lib/project.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'fs';\nimport { dirname, join } from 'path';\n\n/**\n * Walk up from `startDir` until we find a directory containing a\n * `next.config.ts` that includes `withOctoCMS`.\n * Returns the absolute path to the project root.\n */\nexport function resolveProjectRoot(startDir?: string): string {\n let dir = startDir ?? process.cwd();\n for (;;) {\n const nextConfigPath = join(dir, 'next.config.ts');\n if (existsSync(nextConfigPath) && readFileSync(nextConfigPath, 'utf8').includes('withOctoCMS')) {\n return dir;\n }\n const parent = dirname(dir);\n if (parent === dir) {\n throw new Error('Could not find next.config.ts with withOctoCMS — are you inside an OctoCMS project?');\n }\n dir = parent;\n }\n}\n\n/**\n * Load the CMS config from a project root. Uses `jiti` to handle TypeScript\n * files and tsconfig path aliases at runtime.\n */\nexport async function loadProjectConfig(projectRoot: string) {\n // Dynamic import so jiti stays an optional peer when published\n const { createJiti } = await import('jiti');\n const jiti = createJiti(join(projectRoot, '__cli_loader__.ts'), {\n fsCache: false,\n moduleCache: false,\n alias: {\n 'octocms/': join(projectRoot, 'octocms/'),\n },\n });\n const mod = (await jiti.import(join(projectRoot, 'cms', 'octocms.config.ts'), {\n default: true,\n try: true,\n })) as Record<string, unknown> | undefined;\n if (!mod || !mod.configOctoCMS) {\n throw new Error('cms/octocms.config.ts must export a `configOctoCMS` object (use defineConfig())');\n }\n return mod.configOctoCMS as import('../../types').Config;\n}\n\n/**\n * Load the COLLECTIONS array from `octocms/admin/consts.ts`.\n */\nexport async function loadCollections(projectRoot: string): Promise<readonly string[]> {\n const { createJiti } = await import('jiti');\n const jiti = createJiti(join(projectRoot, '__cli_loader__.ts'), {\n fsCache: false,\n moduleCache: false,\n alias: {\n 'octocms/': join(projectRoot, 'octocms/'),\n },\n });\n const mod = (await jiti.import(join(projectRoot, 'octocms/admin/consts.ts'), {\n default: true,\n try: true,\n })) as Record<string, unknown> | undefined;\n if (!mod || !Array.isArray(mod.COLLECTIONS)) {\n throw new Error('Could not load COLLECTIONS from octocms/admin/consts.ts');\n }\n return mod.COLLECTIONS as readonly string[];\n}\n\n/**\n * Load FIELD_TYPES from `octocms/admin/consts.ts`.\n */\nexport async function loadFieldTypes(projectRoot: string): Promise<readonly string[]> {\n const { createJiti } = await import('jiti');\n const jiti = createJiti(join(projectRoot, '__cli_loader__.ts'), {\n fsCache: false,\n moduleCache: false,\n alias: {\n 'octocms/': join(projectRoot, 'octocms/'),\n },\n });\n const mod = (await jiti.import(join(projectRoot, 'octocms/admin/consts.ts'), {\n default: true,\n try: true,\n })) as Record<string, unknown> | undefined;\n if (!mod || !Array.isArray(mod.FIELD_TYPES)) {\n throw new Error('Could not load FIELD_TYPES from octocms/admin/consts.ts');\n }\n return mod.FIELD_TYPES as readonly string[];\n}\n"],"mappings":";AAAA,SAAS,YAAY,oBAAoB;AACzC,SAAS,SAAS,YAAY;AAOvB,SAAS,mBAAmB,UAA2B;AAC5D,MAAI,MAAM,8BAAY,QAAQ,IAAI;AAClC,aAAS;AACP,UAAM,iBAAiB,KAAK,KAAK,gBAAgB;AACjD,QAAI,WAAW,cAAc,KAAK,aAAa,gBAAgB,MAAM,EAAE,SAAS,aAAa,GAAG;AAC9F,aAAO;AAAA,IACT;AACA,UAAM,SAAS,QAAQ,GAAG;AAC1B,QAAI,WAAW,KAAK;AAClB,YAAM,IAAI,MAAM,0FAAqF;AAAA,IACvG;AACA,UAAM;AAAA,EACR;AACF;AAMA,eAAsB,kBAAkB,aAAqB;AAE3D,QAAM,EAAE,WAAW,IAAI,MAAM,OAAO,oBAAM;AAC1C,QAAM,OAAO,WAAW,KAAK,aAAa,mBAAmB,GAAG;AAAA,IAC9D,SAAS;AAAA,IACT,aAAa;AAAA,IACb,OAAO;AAAA,MACL,YAAY,KAAK,aAAa,UAAU;AAAA,IAC1C;AAAA,EACF,CAAC;AACD,QAAM,MAAO,MAAM,KAAK,OAAO,KAAK,aAAa,OAAO,mBAAmB,GAAG;AAAA,IAC5E,SAAS;AAAA,IACT,KAAK;AAAA,EACP,CAAC;AACD,MAAI,CAAC,OAAO,CAAC,IAAI,eAAe;AAC9B,UAAM,IAAI,MAAM,iFAAiF;AAAA,EACnG;AACA,SAAO,IAAI;AACb;AAKA,eAAsB,gBAAgB,aAAiD;AACrF,QAAM,EAAE,WAAW,IAAI,MAAM,OAAO,oBAAM;AAC1C,QAAM,OAAO,WAAW,KAAK,aAAa,mBAAmB,GAAG;AAAA,IAC9D,SAAS;AAAA,IACT,aAAa;AAAA,IACb,OAAO;AAAA,MACL,YAAY,KAAK,aAAa,UAAU;AAAA,IAC1C;AAAA,EACF,CAAC;AACD,QAAM,MAAO,MAAM,KAAK,OAAO,KAAK,aAAa,yBAAyB,GAAG;AAAA,IAC3E,SAAS;AAAA,IACT,KAAK;AAAA,EACP,CAAC;AACD,MAAI,CAAC,OAAO,CAAC,MAAM,QAAQ,IAAI,WAAW,GAAG;AAC3C,UAAM,IAAI,MAAM,yDAAyD;AAAA,EAC3E;AACA,SAAO,IAAI;AACb;AAKA,eAAsB,eAAe,aAAiD;AACpF,QAAM,EAAE,WAAW,IAAI,MAAM,OAAO,oBAAM;AAC1C,QAAM,OAAO,WAAW,KAAK,aAAa,mBAAmB,GAAG;AAAA,IAC9D,SAAS;AAAA,IACT,aAAa;AAAA,IACb,OAAO;AAAA,MACL,YAAY,KAAK,aAAa,UAAU;AAAA,IAC1C;AAAA,EACF,CAAC;AACD,QAAM,MAAO,MAAM,KAAK,OAAO,KAAK,aAAa,yBAAyB,GAAG;AAAA,IAC3E,SAAS;AAAA,IACT,KAAK;AAAA,EACP,CAAC;AACD,MAAI,CAAC,OAAO,CAAC,MAAM,QAAQ,IAAI,WAAW,GAAG;AAC3C,UAAM,IAAI,MAAM,yDAAyD;AAAA,EAC3E;AACA,SAAO,IAAI;AACb;","names":[]}
@@ -0,0 +1,114 @@
1
+ // cli/lib/templates.ts
2
+ var adminLayoutTemplate = `import '../../../cms/__generated__/configInit';
3
+ import 'octocms/globals.css';
4
+ import '@mdxeditor/editor/style.css';
5
+
6
+ export { AdminLayout as default, metadata } from 'octocms/admin/pages/AdminLayout';
7
+ `;
8
+ var adminPageTemplate = `export { AdminApp as default } from 'octocms/admin/AdminApp';
9
+ `;
10
+ function octoConfigTemplate(opts) {
11
+ const gitBlock = opts.pointerBranch ? ` git: {
12
+ baseBranch: '${opts.baseBranch}',
13
+ publishedPointerBranch: '${opts.pointerBranch}',
14
+ },` : ` git: { baseBranch: '${opts.baseBranch}' },`;
15
+ return `import type { Config } from 'octocms/types';
16
+ import { defineConfig } from 'octocms/config';
17
+
18
+ const _typedConfigOctoCMS = defineConfig({
19
+ projectName: '${opts.projectName}',
20
+ ${gitBlock}
21
+ contentFolder: 'cms/content',
22
+ mediaFolder: 'public/media',
23
+ mediaAllowedFormats: ['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg', 'avif'],
24
+ collections: {
25
+ post: {
26
+ label: 'Posts',
27
+ hasMany: true,
28
+ fields: {
29
+ title: { label: 'Title', format: 'string', entryTitle: true, required: true },
30
+ slug: { label: 'Slug', format: 'slug', slugSource: 'title', required: true },
31
+ body: { label: 'Body', format: 'markdown' },
32
+ publishedAt: { label: 'Published At', format: 'datetime', defaultNow: true },
33
+ },
34
+ },
35
+ },
36
+ });
37
+
38
+ export const configOctoCMS: Config = _typedConfigOctoCMS;
39
+ export type OctoConfig = typeof _typedConfigOctoCMS;
40
+ `;
41
+ }
42
+ function nextConfigTemplate() {
43
+ return `import type { NextConfig } from 'next';
44
+ import { withOctoCMS } from 'octocms/config';
45
+ import { configOctoCMS } from './cms/octocms.config';
46
+
47
+ export { configOctoCMS } from './cms/octocms.config';
48
+ export type { OctoConfig } from './cms/octocms.config';
49
+
50
+ const nextConfig: NextConfig = {};
51
+
52
+ export default withOctoCMS(nextConfig, configOctoCMS);
53
+ `;
54
+ }
55
+ function demoPostJson(id) {
56
+ const now = (/* @__PURE__ */ new Date()).toISOString();
57
+ return JSON.stringify(
58
+ {
59
+ sys: { id, type: "post", status: "merged" },
60
+ fields: {
61
+ title: "Hello World",
62
+ slug: "hello-world",
63
+ publishedAt: now
64
+ }
65
+ },
66
+ null,
67
+ 2
68
+ );
69
+ }
70
+ var demoPostMarkdown = `# Hello World
71
+
72
+ Welcome to your new OctoCMS site! This is a demo post.
73
+
74
+ Edit this content in the CMS admin panel at \`/cms\`.
75
+ `;
76
+ var AGENT_DOCS_MARKER = "<!-- octocms:agent-docs -->";
77
+ function agentsMdSection() {
78
+ return `${AGENT_DOCS_MARKER}
79
+ ## OctoCMS \u2014 AI Content Management
80
+
81
+ For tasks that involve creating, editing, or deleting CMS content directly (without the admin UI), read the auto-generated agent docs:
82
+
83
+ - **\`octocms/docs/overview.md\`** \u2014 How to find, create, update, and delete content entries via file operations
84
+ - **\`octocms/docs/schema.md\`** \u2014 Per-collection field definitions, example JSON, and file path conventions
85
+
86
+ These docs are generated from \`cms/octocms.config.ts\`. Regenerate after schema changes: \`npm run agent-docs:gen\`.`;
87
+ }
88
+ function agentsMdTemplate() {
89
+ return `# Project Guidelines
90
+
91
+ ${agentsMdSection()}
92
+ `;
93
+ }
94
+ function tsconfigPaths() {
95
+ return {
96
+ "cms/__generated__": ["./cms/__generated__/index.ts"],
97
+ "cms/__generated__/*": ["./cms/__generated__/*"],
98
+ "octocms/*": ["./octocms/*"],
99
+ "@/*": ["./src/*"]
100
+ };
101
+ }
102
+
103
+ export {
104
+ adminLayoutTemplate,
105
+ adminPageTemplate,
106
+ octoConfigTemplate,
107
+ nextConfigTemplate,
108
+ demoPostJson,
109
+ demoPostMarkdown,
110
+ agentsMdSection,
111
+ agentsMdTemplate,
112
+ tsconfigPaths
113
+ };
114
+ //# sourceMappingURL=chunk-I7KNSICQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../cli/lib/templates.ts"],"sourcesContent":["/**\n * File templates used by `octocms init` and `octocms update`.\n */\n\nexport const adminLayoutTemplate = `import '../../../cms/__generated__/configInit';\nimport 'octocms/globals.css';\nimport '@mdxeditor/editor/style.css';\n\nexport { AdminLayout as default, metadata } from 'octocms/admin/pages/AdminLayout';\n`;\n\nexport const adminPageTemplate = `export { AdminApp as default } from 'octocms/admin/AdminApp';\n`;\n\nexport function octoConfigTemplate(opts: { projectName: string; baseBranch: string; pointerBranch?: string }): string {\n const gitBlock = opts.pointerBranch\n ? ` git: {\\n baseBranch: '${opts.baseBranch}',\\n publishedPointerBranch: '${opts.pointerBranch}',\\n },`\n : ` git: { baseBranch: '${opts.baseBranch}' },`;\n\n return `import type { Config } from 'octocms/types';\nimport { defineConfig } from 'octocms/config';\n\nconst _typedConfigOctoCMS = defineConfig({\n projectName: '${opts.projectName}',\n${gitBlock}\n contentFolder: 'cms/content',\n mediaFolder: 'public/media',\n mediaAllowedFormats: ['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg', 'avif'],\n collections: {\n post: {\n label: 'Posts',\n hasMany: true,\n fields: {\n title: { label: 'Title', format: 'string', entryTitle: true, required: true },\n slug: { label: 'Slug', format: 'slug', slugSource: 'title', required: true },\n body: { label: 'Body', format: 'markdown' },\n publishedAt: { label: 'Published At', format: 'datetime', defaultNow: true },\n },\n },\n },\n});\n\nexport const configOctoCMS: Config = _typedConfigOctoCMS;\nexport type OctoConfig = typeof _typedConfigOctoCMS;\n`;\n}\n\nexport function nextConfigTemplate(): string {\n return `import type { NextConfig } from 'next';\nimport { withOctoCMS } from 'octocms/config';\nimport { configOctoCMS } from './cms/octocms.config';\n\nexport { configOctoCMS } from './cms/octocms.config';\nexport type { OctoConfig } from './cms/octocms.config';\n\nconst nextConfig: NextConfig = {};\n\nexport default withOctoCMS(nextConfig, configOctoCMS);\n`;\n}\n\nexport function demoPostJson(id: string): string {\n const now = new Date().toISOString();\n return JSON.stringify(\n {\n sys: { id, type: 'post', status: 'merged' },\n fields: {\n title: 'Hello World',\n slug: 'hello-world',\n publishedAt: now,\n },\n },\n null,\n 2,\n );\n}\n\nexport const demoPostMarkdown = `# Hello World\n\nWelcome to your new OctoCMS site! This is a demo post.\n\nEdit this content in the CMS admin panel at \\`/cms\\`.\n`;\n\nconst AGENT_DOCS_MARKER = '<!-- octocms:agent-docs -->';\n\nexport function agentsMdSection(): string {\n return `${AGENT_DOCS_MARKER}\n## OctoCMS — AI Content Management\n\nFor tasks that involve creating, editing, or deleting CMS content directly (without the admin UI), read the auto-generated agent docs:\n\n- **\\`octocms/docs/overview.md\\`** — How to find, create, update, and delete content entries via file operations\n- **\\`octocms/docs/schema.md\\`** — Per-collection field definitions, example JSON, and file path conventions\n\nThese docs are generated from \\`cms/octocms.config.ts\\`. Regenerate after schema changes: \\`npm run agent-docs:gen\\`.`;\n}\n\nexport function agentsMdTemplate(): string {\n return `# Project Guidelines\n\n${agentsMdSection()}\n`;\n}\n\nexport function tsconfigPaths(): Record<string, string[]> {\n return {\n 'cms/__generated__': ['./cms/__generated__/index.ts'],\n 'cms/__generated__/*': ['./cms/__generated__/*'],\n 'octocms/*': ['./octocms/*'],\n '@/*': ['./src/*'],\n };\n}\n"],"mappings":";AAIO,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAO5B,IAAM,oBAAoB;AAAA;AAG1B,SAAS,mBAAmB,MAAmF;AACpH,QAAM,WAAW,KAAK,gBAClB;AAAA,mBAA8B,KAAK,UAAU;AAAA,+BAAoC,KAAK,aAAa;AAAA,QACnG,yBAAyB,KAAK,UAAU;AAE5C,SAAO;AAAA;AAAA;AAAA;AAAA,kBAIS,KAAK,WAAW;AAAA,EAChC,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqBV;AAEO,SAAS,qBAA6B;AAC3C,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWT;AAEO,SAAS,aAAa,IAAoB;AAC/C,QAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,SAAO,KAAK;AAAA,IACV;AAAA,MACE,KAAK,EAAE,IAAI,MAAM,QAAQ,QAAQ,SAAS;AAAA,MAC1C,QAAQ;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAOhC,IAAM,oBAAoB;AAEnB,SAAS,kBAA0B;AACxC,SAAO,GAAG,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAS7B;AAEO,SAAS,mBAA2B;AACzC,SAAO;AAAA;AAAA,EAEP,gBAAgB,CAAC;AAAA;AAEnB;AAEO,SAAS,gBAA0C;AACxD,SAAO;AAAA,IACL,qBAAqB,CAAC,8BAA8B;AAAA,IACpD,uBAAuB,CAAC,uBAAuB;AAAA,IAC/C,aAAa,CAAC,aAAa;AAAA,IAC3B,OAAO,CAAC,SAAS;AAAA,EACnB;AACF;","names":[]}
@@ -0,0 +1,123 @@
1
+ // cli/lib/validateConfig.ts
2
+ var VALID_IDENTIFIER = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
3
+ function validateConfig(config, collectionNames) {
4
+ for (const key of collectionNames) {
5
+ const col = config.collections[key];
6
+ if (!col) {
7
+ throw new Error(`validate \u2014 collection "${key}" is listed but not defined in config.collections`);
8
+ }
9
+ const fieldEntries = Object.entries(col.fields);
10
+ if (fieldEntries.length === 0) {
11
+ throw new Error(`validate \u2014 collection "${key}" must have at least one field`);
12
+ }
13
+ for (const [fieldName, field] of fieldEntries) {
14
+ if (!VALID_IDENTIFIER.test(fieldName)) {
15
+ throw new Error(`validate \u2014 collection "${key}" field "${fieldName}" is not a valid TypeScript identifier`);
16
+ }
17
+ validateField(collectionNames, key, fieldName, field, col.fields);
18
+ }
19
+ }
20
+ }
21
+ function validateField(collectionNames, collectionKey, fieldName, field, allFields) {
22
+ var _a, _b, _c, _d, _e;
23
+ const ctx = `collection "${collectionKey}" field "${fieldName}"`;
24
+ if (field.format !== "string" && "list" in field && field.list === true) {
25
+ throw new Error(`validate \u2014 ${ctx} has list: true but format is not "string"`);
26
+ }
27
+ if (field.format === "slug") {
28
+ const source = field.slugSource;
29
+ if (source) {
30
+ const src = allFields[source];
31
+ const ok = src && (src.format === "string" && src.list !== true || src.format === "text");
32
+ if (!ok) {
33
+ throw new Error(`validate \u2014 ${ctx} slugSource must name a non-list string or text field`);
34
+ }
35
+ } else {
36
+ const entryTitleCount = Object.values(allFields).filter((f) => f.entryTitle).length;
37
+ if (entryTitleCount !== 1) {
38
+ throw new Error(`validate \u2014 ${ctx} needs slugSource or exactly one entryTitle field`);
39
+ }
40
+ }
41
+ }
42
+ if (field.format === "select") {
43
+ if (!((_a = field.options) == null ? void 0 : _a.length)) {
44
+ throw new Error(`validate \u2014 ${ctx} select field needs at least one option`);
45
+ }
46
+ const values = field.options.map((o) => o.value);
47
+ const uniq = new Set(values);
48
+ if (uniq.size !== values.length) {
49
+ throw new Error(`validate \u2014 ${ctx} select options must have unique values`);
50
+ }
51
+ if (field.multiple === true) {
52
+ if (field.defaultOption != null) {
53
+ throw new Error(`validate \u2014 ${ctx} use defaultOptions with multiple, not defaultOption`);
54
+ }
55
+ if (field.defaultOptions) {
56
+ for (const v of field.defaultOptions) {
57
+ if (!uniq.has(v)) {
58
+ throw new Error(`validate \u2014 ${ctx} defaultOptions value "${v}" is not an option`);
59
+ }
60
+ }
61
+ }
62
+ } else {
63
+ if (field.defaultOptions != null && field.defaultOptions.length > 0) {
64
+ throw new Error(`validate \u2014 ${ctx} use defaultOption for single select, not defaultOptions`);
65
+ }
66
+ if (field.defaultOption != null && !uniq.has(field.defaultOption)) {
67
+ throw new Error(`validate \u2014 ${ctx} defaultOption is not among options`);
68
+ }
69
+ }
70
+ }
71
+ if (field.format === "reference") {
72
+ const refCols = (_b = field.reference) == null ? void 0 : _b.collections;
73
+ if (refCols) {
74
+ for (const rc of refCols) {
75
+ if (!collectionNames.includes(rc)) {
76
+ throw new Error(`validate \u2014 ${ctx} reference.collections includes unknown collection "${rc}"`);
77
+ }
78
+ }
79
+ }
80
+ if (((_c = field.reference) == null ? void 0 : _c.cardinality) != null && field.reference.cardinality !== "one" && field.reference.cardinality !== "many") {
81
+ throw new Error(`validate \u2014 ${ctx} reference.cardinality must be "one" or "many"`);
82
+ }
83
+ if (field.collection != null && !collectionNames.includes(field.collection)) {
84
+ throw new Error(`validate \u2014 ${ctx} legacy collection prop references unknown collection "${field.collection}"`);
85
+ }
86
+ }
87
+ if (field.format === "conditional") {
88
+ if (!((_e = (_d = field.conditional) == null ? void 0 : _d.branches) == null ? void 0 : _e.length)) {
89
+ throw new Error(`validate \u2014 ${ctx} conditional field must have at least one branch`);
90
+ }
91
+ const branchKeys = /* @__PURE__ */ new Set();
92
+ for (const branch of field.conditional.branches) {
93
+ if (branchKeys.has(branch.key)) {
94
+ throw new Error(`validate \u2014 ${ctx} conditional branch key "${branch.key}" is duplicated`);
95
+ }
96
+ branchKeys.add(branch.key);
97
+ if (isReferenceBranch(branch)) {
98
+ if (!collectionNames.includes(branch.collection)) {
99
+ throw new Error(
100
+ `validate \u2014 ${ctx} conditional branch "${branch.key}" references unknown collection "${branch.collection}"`
101
+ );
102
+ }
103
+ } else if (branch.fields) {
104
+ for (const [subName, subField] of Object.entries(branch.fields)) {
105
+ if (!VALID_IDENTIFIER.test(subName)) {
106
+ throw new Error(
107
+ `validate \u2014 ${ctx} conditional branch "${branch.key}" field "${subName}" is not a valid TypeScript identifier`
108
+ );
109
+ }
110
+ validateField(collectionNames, collectionKey, `${fieldName}.${branch.key}.${subName}`, subField, allFields);
111
+ }
112
+ }
113
+ }
114
+ }
115
+ }
116
+ function isReferenceBranch(branch) {
117
+ return "collection" in branch && typeof branch.collection === "string";
118
+ }
119
+
120
+ export {
121
+ validateConfig
122
+ };
123
+ //# sourceMappingURL=chunk-Q73JSGXV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../cli/lib/validateConfig.ts"],"sourcesContent":["/**\n * CMS config validation — validates the schema configuration object.\n *\n * Shared between the CLI (`octocms types:gen`, `octocms validate`) and the\n * codegen scripts (`scripts/generate-types.ts`, `scripts/generate-docs.ts`).\n *\n * Moved here from `scripts/lib/validate-config.ts` as part of Phase 4 (CLI).\n */\n\nimport type { CollectionField, ConditionalBranchConfig, Config } from '../../types';\n\n// TS identifier: starts with letter/$/_, followed by word chars\nconst VALID_IDENTIFIER = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;\n\n/**\n * Validate a CMS config object. Throws on the first invalid rule.\n *\n * Shared between `generate-docs.ts` and `generate-types.ts` so every\n * codegen script applies the same checks before emitting output.\n */\nexport function validateConfig(config: Config, collectionNames: readonly string[]): void {\n for (const key of collectionNames) {\n const col = config.collections[key as keyof typeof config.collections];\n if (!col) {\n throw new Error(`validate — collection \"${key}\" is listed but not defined in config.collections`);\n }\n\n const fieldEntries = Object.entries(col.fields);\n\n if (fieldEntries.length === 0) {\n throw new Error(`validate — collection \"${key}\" must have at least one field`);\n }\n\n for (const [fieldName, field] of fieldEntries) {\n if (!VALID_IDENTIFIER.test(fieldName)) {\n throw new Error(`validate — collection \"${key}\" field \"${fieldName}\" is not a valid TypeScript identifier`);\n }\n\n validateField(collectionNames, key, fieldName, field, col.fields);\n }\n }\n}\n\nfunction validateField(\n collectionNames: readonly string[],\n collectionKey: string,\n fieldName: string,\n field: CollectionField,\n allFields: Record<string, CollectionField>,\n): void {\n const ctx = `collection \"${collectionKey}\" field \"${fieldName}\"`;\n\n // list: true only on format: 'string'\n if (field.format !== 'string' && 'list' in field && (field as { list?: boolean }).list === true) {\n throw new Error(`validate — ${ctx} has list: true but format is not \"string\"`);\n }\n\n // slug validation\n if (field.format === 'slug') {\n const source = field.slugSource;\n if (source) {\n const src = allFields[source];\n const ok = src && ((src.format === 'string' && src.list !== true) || src.format === 'text');\n if (!ok) {\n throw new Error(`validate — ${ctx} slugSource must name a non-list string or text field`);\n }\n } else {\n const entryTitleCount = Object.values(allFields).filter((f) => f.entryTitle).length;\n if (entryTitleCount !== 1) {\n throw new Error(`validate — ${ctx} needs slugSource or exactly one entryTitle field`);\n }\n }\n }\n\n // select validation\n if (field.format === 'select') {\n if (!field.options?.length) {\n throw new Error(`validate — ${ctx} select field needs at least one option`);\n }\n const values = field.options.map((o) => o.value);\n const uniq = new Set(values);\n if (uniq.size !== values.length) {\n throw new Error(`validate — ${ctx} select options must have unique values`);\n }\n if (field.multiple === true) {\n if (field.defaultOption != null) {\n throw new Error(`validate — ${ctx} use defaultOptions with multiple, not defaultOption`);\n }\n if (field.defaultOptions) {\n for (const v of field.defaultOptions) {\n if (!uniq.has(v)) {\n throw new Error(`validate — ${ctx} defaultOptions value \"${v}\" is not an option`);\n }\n }\n }\n } else {\n if (field.defaultOptions != null && field.defaultOptions.length > 0) {\n throw new Error(`validate — ${ctx} use defaultOption for single select, not defaultOptions`);\n }\n if (field.defaultOption != null && !uniq.has(field.defaultOption)) {\n throw new Error(`validate — ${ctx} defaultOption is not among options`);\n }\n }\n }\n\n // reference validation\n if (field.format === 'reference') {\n const refCols = field.reference?.collections;\n if (refCols) {\n for (const rc of refCols) {\n if (!collectionNames.includes(rc)) {\n throw new Error(`validate — ${ctx} reference.collections includes unknown collection \"${rc}\"`);\n }\n }\n }\n if (\n field.reference?.cardinality != null &&\n field.reference.cardinality !== 'one' &&\n field.reference.cardinality !== 'many'\n ) {\n throw new Error(`validate — ${ctx} reference.cardinality must be \"one\" or \"many\"`);\n }\n // Legacy `collection` prop\n if (field.collection != null && !collectionNames.includes(field.collection)) {\n throw new Error(`validate — ${ctx} legacy collection prop references unknown collection \"${field.collection}\"`);\n }\n }\n\n // conditional validation\n if (field.format === 'conditional') {\n if (!field.conditional?.branches?.length) {\n throw new Error(`validate — ${ctx} conditional field must have at least one branch`);\n }\n const branchKeys = new Set<string>();\n for (const branch of field.conditional.branches) {\n if (branchKeys.has(branch.key)) {\n throw new Error(`validate — ${ctx} conditional branch key \"${branch.key}\" is duplicated`);\n }\n branchKeys.add(branch.key);\n\n if (isReferenceBranch(branch)) {\n if (!collectionNames.includes(branch.collection)) {\n throw new Error(\n `validate — ${ctx} conditional branch \"${branch.key}\" references unknown collection \"${branch.collection}\"`,\n );\n }\n } else if (branch.fields) {\n for (const [subName, subField] of Object.entries(branch.fields)) {\n if (!VALID_IDENTIFIER.test(subName)) {\n throw new Error(\n `validate — ${ctx} conditional branch \"${branch.key}\" field \"${subName}\" is not a valid TypeScript identifier`,\n );\n }\n validateField(collectionNames, collectionKey, `${fieldName}.${branch.key}.${subName}`, subField, allFields);\n }\n }\n }\n }\n}\n\nfunction isReferenceBranch(\n branch: ConditionalBranchConfig,\n): branch is ConditionalBranchConfig & { collection: string } {\n return 'collection' in branch && typeof branch.collection === 'string';\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,57 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __defProps = Object.defineProperties;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
11
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
12
+ var __spreadValues = (a, b) => {
13
+ for (var prop in b || (b = {}))
14
+ if (__hasOwnProp.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ if (__getOwnPropSymbols)
17
+ for (var prop of __getOwnPropSymbols(b)) {
18
+ if (__propIsEnum.call(b, prop))
19
+ __defNormalProp(a, prop, b[prop]);
20
+ }
21
+ return a;
22
+ };
23
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
24
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
25
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
26
+ }) : x)(function(x) {
27
+ if (typeof require !== "undefined") return require.apply(this, arguments);
28
+ throw Error('Dynamic require of "' + x + '" is not supported');
29
+ });
30
+ var __commonJS = (cb, mod) => function __require2() {
31
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
32
+ };
33
+ var __copyProps = (to, from, except, desc) => {
34
+ if (from && typeof from === "object" || typeof from === "function") {
35
+ for (let key of __getOwnPropNames(from))
36
+ if (!__hasOwnProp.call(to, key) && key !== except)
37
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
38
+ }
39
+ return to;
40
+ };
41
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
42
+ // If the importer is in node compatibility mode or this is not an ESM
43
+ // file that has been converted to a CommonJS file using a Babel-
44
+ // compatible transform (i.e. "__esModule" has not been set), then set
45
+ // "default" to the CommonJS "module.exports" for node compatibility.
46
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
47
+ mod
48
+ ));
49
+
50
+ export {
51
+ __spreadValues,
52
+ __spreadProps,
53
+ __require,
54
+ __commonJS,
55
+ __toESM
56
+ };
57
+ //# sourceMappingURL=chunk-W6QJTGBC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}