@bobbykim/manguito-cms-cli 0.9.1 → 0.10.1

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.
@@ -25075,6 +25075,7 @@ function findSchemaDeprecations(registry2) {
25075
25075
  ...Object.values(registry2.paragraph_types)
25076
25076
  ];
25077
25077
  for (const owner of owners) {
25078
+ const instead = owner.schema_type === "paragraph-type" ? 'Use "one-to-one": a paragraph type cannot hold a many-to-many reference.' : 'Use "one-to-one" for a single item, or "many-to-many" for a list.';
25078
25079
  for (const field of owner.fields) {
25079
25080
  if (field.field_type !== "reference") continue;
25080
25081
  const c = field.ui_component;
@@ -25083,7 +25084,7 @@ function findSchemaDeprecations(registry2) {
25083
25084
  source_file: owner.source_file,
25084
25085
  type_name: owner.name,
25085
25086
  field_name: field.name,
25086
- message: `${owner.name}.${field.name} uses "one-to-many", which is deprecated for references. It holds a single item, the same as "one-to-one". Use "one-to-one" for a single item, or "many-to-many" for a list.`
25087
+ message: `${owner.name}.${field.name} uses "one-to-many", which is deprecated for references. It holds a single item, the same as "one-to-one". ${instead}`
25087
25088
  });
25088
25089
  }
25089
25090
  }
@@ -25306,11 +25307,27 @@ function validateCrossReferences(registry2, globalMaxFileSize) {
25306
25307
  errors.push(...checkDuplicateSchemaNames(registry2.all_schemas));
25307
25308
  errors.push(...checkFieldRefs(registry2));
25308
25309
  errors.push(...checkCircularParagraphRefs(registry2));
25310
+ errors.push(...checkParagraphRelations(registry2));
25309
25311
  if (globalMaxFileSize !== void 0) {
25310
25312
  errors.push(...checkMaxSizeLimit(registry2, globalMaxFileSize));
25311
25313
  }
25312
25314
  return errors;
25313
25315
  }
25316
+ function checkParagraphRelations(registry2) {
25317
+ const errors = [];
25318
+ for (const paragraph of Object.values(registry2.paragraph_types)) {
25319
+ for (const field of paragraph.fields) {
25320
+ if (field.field_type !== "reference" || !field.db_column?.junction) continue;
25321
+ errors.push({
25322
+ file: paragraph.source_file,
25323
+ code: "UNSUPPORTED_RELATION",
25324
+ message: `Field "${field.name}" in "${paragraph.name}" is a many-to-many reference, which paragraph types do not support: a paragraph belongs to one parent and is replaced on every save, so it cannot own links. For a single item, use "rel": "one-to-one". For a list, put the many-to-many field on the content or taxonomy type this paragraph appears in, or make the paragraph field that embeds it "one-to-many" with a "one-to-one" reference in each item.`,
25325
+ path: `fields[${field.order}].rel`
25326
+ });
25327
+ }
25328
+ }
25329
+ return errors;
25330
+ }
25314
25331
  function checkDuplicateSchemaNames(allSchemas) {
25315
25332
  const errors = [];
25316
25333
  const seen = /* @__PURE__ */ new Map();
@@ -12,7 +12,7 @@ import {
12
12
  isColumnBacked,
13
13
  relationCardinality,
14
14
  resolveRelationField
15
- } from "./chunk-L36JYVXK.js";
15
+ } from "./chunk-X7D2QPPO.js";
16
16
 
17
17
  // ../../node_modules/.pnpm/@whatwg-node+fetch@0.10.13/node_modules/@whatwg-node/fetch/dist/shouldSkipPonyfill.js
18
18
  var require_shouldSkipPonyfill = __commonJS({
package/dist/index.js CHANGED
@@ -54,7 +54,7 @@ import {
54
54
  validateCrossReferences,
55
55
  verifyPassword,
56
56
  walkSchemaDirectory
57
- } from "./chunk-L36JYVXK.js";
57
+ } from "./chunk-X7D2QPPO.js";
58
58
 
59
59
  // ../../node_modules/.pnpm/postgres-array@2.0.0/node_modules/postgres-array/index.js
60
60
  var require_postgres_array = __commonJS({
@@ -18721,6 +18721,11 @@ async function runBuild(options, deps) {
18721
18721
  parsedRoles
18722
18722
  );
18723
18723
  printSchemaDeprecations(findSchemaDeprecations(registry));
18724
+ const crossRefErrors = validateCrossReferences(registry, config2.api.media?.max_file_size);
18725
+ if (crossRefErrors.length > 0) {
18726
+ printValidationErrors(crossRefErrors, "Schema reference errors", "manguito build");
18727
+ process.exit(1);
18728
+ }
18724
18729
  const versions = loadProjectVersionModel(resolveSchemaConfig(cwd, config2), registry);
18725
18730
  if (!versions.ok) {
18726
18731
  printValidationErrors(versions.errors, "Version model errors", "manguito build");
@@ -24604,7 +24609,7 @@ function registerUserRoutes(app, db, requirePermission, requireHierarchy) {
24604
24609
  }
24605
24610
  var API_VERSION = (() => {
24606
24611
  try {
24607
- return "0.8.3";
24612
+ return "0.8.4";
24608
24613
  } catch {
24609
24614
  return "0.0.0";
24610
24615
  }
@@ -25287,7 +25292,7 @@ function createCmsApp(options) {
25287
25292
  handler: null,
25288
25293
  error: null
25289
25294
  }));
25290
- const ready = import("./handler-VEOWJRAL-6WUFNANJ.js").then(({ createGraphQLHandler }) => {
25295
+ const ready = import("./handler-VEOWJRAL-OU66YS5U.js").then(({ createGraphQLHandler }) => {
25291
25296
  gqlPasses.forEach((pass, i) => {
25292
25297
  const mount = mounts[i];
25293
25298
  try {
@@ -25565,13 +25570,18 @@ async function runDev(options, deps) {
25565
25570
  await mkdir2(manguitoDir, { recursive: true });
25566
25571
  const drizzleConfigPath = resolve6(manguitoDir, "drizzle.config.ts");
25567
25572
  const needsSeed = !await db.tableExists("users");
25568
- const bootstrapRegistry = await parseAllSchemas(cwd, config2);
25573
+ const loaded = loadValidatedSchema(cwd, config2);
25574
+ if (!loaded.ok) {
25575
+ printValidationErrors(loaded.errors, "Schema errors", "manguito validate");
25576
+ process.exit(1);
25577
+ }
25578
+ const { registry, versionModel } = loaded.value;
25569
25579
  await generateDrizzleConfig(config2, manguitoDir);
25570
- await writeFile9(join11(manguitoDir, "schema.ts"), generateSchemaFile(bootstrapRegistry), "utf8");
25580
+ await writeFile9(join11(manguitoDir, "schema.ts"), generateSchemaFile(registry), "utf8");
25571
25581
  await runDevMigration(drizzleConfigPath);
25572
25582
  printSuccess(needsSeed ? "Schema tables created" : "Schema tables up to date");
25573
25583
  if (needsSeed) {
25574
- await seedSystemTables(db.getDb(), bootstrapRegistry);
25584
+ await seedSystemTables(db.getDb(), registry);
25575
25585
  printSuccess("System tables seeded");
25576
25586
  }
25577
25587
  const adminCountResult = await db.getDb().execute(sql`
@@ -25604,7 +25614,6 @@ async function runDev(options, deps) {
25604
25614
  process.stdout.write("\n");
25605
25615
  printSuccess("Admin account created");
25606
25616
  }
25607
- const registry = bootstrapRegistry;
25608
25617
  const contentCount = Object.keys(registry.content_types).length;
25609
25618
  const paragraphCount = Object.keys(registry.paragraph_types).length;
25610
25619
  const taxonomyCount = Object.keys(registry.taxonomy_types).length;
@@ -25615,12 +25624,6 @@ async function runDev(options, deps) {
25615
25624
  await generateRoutes2(registry, manguitoDir);
25616
25625
  await generateForms(registry, join11(manguitoDir, "forms"));
25617
25626
  await generateNav(registry, manguitoDir);
25618
- const versionsResult = loadProjectVersionModel(resolveSchemaConfig(cwd, config2), registry);
25619
- if (!versionsResult.ok) {
25620
- printValidationErrors(versionsResult.errors, "Version model errors", "manguito validate");
25621
- process.exit(1);
25622
- }
25623
- const versionModel = reduceVersionModel(versionsResult.value.model);
25624
25627
  const resolverMap = await loadProgrammaticResolvers(cwd, config2.programmatic.dir);
25625
25628
  const adapter = createCmsApp({
25626
25629
  name: config2.name,
@@ -25708,7 +25711,7 @@ async function runDev(options, deps) {
25708
25711
  void (async () => {
25709
25712
  for await (const event of watcher) {
25710
25713
  if (event.filename && /\.(json|ya?ml)$/.test(event.filename)) {
25711
- await onSchemaFileChange({
25714
+ await reloadSafely({
25712
25715
  cwd,
25713
25716
  config: config2,
25714
25717
  manguitoDir,
@@ -25728,7 +25731,7 @@ async function runDev(options, deps) {
25728
25731
  void (async () => {
25729
25732
  for await (const event of progWatcher) {
25730
25733
  if (event.filename && /\.(ts|mjs|js)$/.test(event.filename)) {
25731
- await onSchemaFileChange({
25734
+ await reloadSafely({
25732
25735
  cwd,
25733
25736
  config: config2,
25734
25737
  manguitoDir,
@@ -25744,28 +25747,32 @@ async function runDev(options, deps) {
25744
25747
  })();
25745
25748
  }
25746
25749
  }
25750
+ async function reloadSafely(args) {
25751
+ try {
25752
+ await onSchemaFileChange(args);
25753
+ } catch (err) {
25754
+ process.stderr.write(
25755
+ `\u26A0 Reload failed: ${err instanceof Error ? err.message : String(err)}
25756
+ \u26A0 Still serving the previous version.
25757
+ `
25758
+ );
25759
+ }
25760
+ }
25747
25761
  async function onSchemaFileChange(args) {
25748
25762
  const { cwd, config: config2, manguitoDir, drizzleConfigPath, db, updateFetch, getResolvers } = args;
25749
- let registry;
25750
- try {
25751
- registry = await parseAllSchemas(cwd, config2);
25752
- } catch {
25753
- process.stderr.write("\u26A0 Schema parse error \u2014 changes not applied.\n");
25763
+ const loaded = loadValidatedSchema(cwd, config2);
25764
+ if (!loaded.ok) {
25765
+ printValidationErrors(loaded.errors, "Schema errors", "manguito validate");
25766
+ process.stderr.write("\u26A0 Changes not applied.\n");
25754
25767
  return;
25755
25768
  }
25769
+ const { registry, versionModel } = loaded.value;
25756
25770
  await generateDrizzleConfig(config2, manguitoDir);
25757
25771
  await writeFile9(join11(manguitoDir, "schema.ts"), generateSchemaFile(registry), "utf8");
25758
25772
  await generateSchemaRegistry(registry, manguitoDir);
25759
25773
  await generateRoutes2(registry, manguitoDir);
25760
25774
  await generateForms(registry, join11(manguitoDir, "forms"));
25761
25775
  await generateNav(registry, manguitoDir);
25762
- const versionsResult = loadProjectVersionModel(resolveSchemaConfig(cwd, config2), registry);
25763
- if (!versionsResult.ok) {
25764
- printValidationErrors(versionsResult.errors, "Version model errors", "manguito validate");
25765
- process.stderr.write("\u26A0 Changes not applied.\n");
25766
- return;
25767
- }
25768
- const versionModel = reduceVersionModel(versionsResult.value.model);
25769
25776
  try {
25770
25777
  await runDevMigration(drizzleConfigPath);
25771
25778
  } catch (err) {
@@ -25790,46 +25797,40 @@ async function onSchemaFileChange(args) {
25790
25797
  updateFetch((req) => newAdapter.app.fetch(req));
25791
25798
  printSuccess("Schema updated");
25792
25799
  }
25793
- async function parseAllSchemas(cwd, config2) {
25800
+ function loadValidatedSchema(cwd, config2) {
25801
+ const parsed = parseAllSchemas(cwd, config2);
25802
+ if (!parsed.ok) return parsed;
25803
+ const registry = parsed.value;
25804
+ const crossRefErrors = validateCrossReferences(registry, config2.api.media?.max_file_size);
25805
+ if (crossRefErrors.length > 0) return { ok: false, errors: crossRefErrors };
25806
+ const versions = loadProjectVersionModel(resolveSchemaConfig(cwd, config2), registry);
25807
+ if (!versions.ok) return { ok: false, errors: versions.errors };
25808
+ printSchemaDeprecations(findSchemaDeprecations(registry));
25809
+ return { ok: true, value: { registry, versionModel: reduceVersionModel(versions.value.model) } };
25810
+ }
25811
+ function parseAllSchemas(cwd, config2) {
25812
+ const errors = [];
25794
25813
  const parsedSchemas = [];
25795
25814
  const walkResult = walkSchemaDirectory(config2.schema);
25796
25815
  if (!walkResult.ok) {
25797
- printGuidedError("Schema directory errors \u2014 run `manguito validate` for details.");
25798
- process.exit(1);
25799
- }
25800
- for (const file of walkResult.value) {
25801
- const parseResult = parseSchema(file.raw, file.schema_type, file.path);
25802
- if (!parseResult.ok) {
25803
- printGuidedError("Schema parse errors \u2014 run `manguito validate` for details.");
25804
- process.exit(1);
25816
+ errors.push(...walkResult.errors);
25817
+ } else {
25818
+ for (const file of walkResult.value) {
25819
+ const parseResult = parseSchema(file.raw, file.schema_type, file.path);
25820
+ if (parseResult.ok) parsedSchemas.push(parseResult.schema);
25821
+ else errors.push(...parseResult.errors);
25805
25822
  }
25806
- parsedSchemas.push(parseResult.schema);
25807
25823
  }
25808
25824
  const rolesPath = resolve6(cwd, config2.schema.base_path, "roles.json");
25809
25825
  const rolesLoad = loadSchemaFile(rolesPath);
25810
- if (!rolesLoad.ok) {
25811
- printGuidedError("Could not read roles.json.");
25812
- process.exit(1);
25813
- }
25814
- const rolesResult = parseRoles(rolesLoad.value, rolesPath);
25815
- if (!rolesResult.ok) {
25816
- printGuidedError("roles.json parse errors \u2014 run `manguito validate` for details.");
25817
- process.exit(1);
25818
- }
25826
+ const rolesResult = rolesLoad.ok ? parseRoles(rolesLoad.value, rolesPath) : rolesLoad;
25827
+ if (!rolesResult.ok) errors.push(...rolesResult.errors);
25819
25828
  const routesPath = resolve6(cwd, config2.schema.base_path, "routes.json");
25820
25829
  const routesLoad = loadSchemaFile(routesPath);
25821
- if (!routesLoad.ok) {
25822
- printGuidedError("Could not read routes.json.");
25823
- process.exit(1);
25824
- }
25825
- const routesResult = parseRoutes(routesLoad.value, routesPath);
25826
- if (!routesResult.ok) {
25827
- printGuidedError("routes.json parse errors \u2014 run `manguito validate` for details.");
25828
- process.exit(1);
25829
- }
25830
- const registry = buildSchemaRegistry(parsedSchemas, routesResult.value, rolesResult.value);
25831
- printSchemaDeprecations(findSchemaDeprecations(registry));
25832
- return registry;
25830
+ const routesResult = routesLoad.ok ? parseRoutes(routesLoad.value, routesPath) : routesLoad;
25831
+ if (!routesResult.ok) errors.push(...routesResult.errors);
25832
+ if (errors.length > 0 || !rolesResult.ok || !routesResult.ok) return { ok: false, errors };
25833
+ return { ok: true, value: buildSchemaRegistry(parsedSchemas, routesResult.value, rolesResult.value) };
25833
25834
  }
25834
25835
  function resolveAdminRoot2(cwd) {
25835
25836
  const cwdRequire = createRequire2(join11(cwd, "package.json"));
@@ -26544,7 +26545,13 @@ function loadWorkingRegistry(cwd, config2, command) {
26544
26545
  printValidationErrors(allErrors, "Schema parse errors", command);
26545
26546
  process.exit(1);
26546
26547
  }
26547
- return buildSchemaRegistry(parsedSchemas, parsedRoutes, parsedRoles);
26548
+ const registry = buildSchemaRegistry(parsedSchemas, parsedRoutes, parsedRoles);
26549
+ const crossRefErrors = validateCrossReferences(registry, config2.api.media?.max_file_size);
26550
+ if (crossRefErrors.length > 0) {
26551
+ printValidationErrors(crossRefErrors, "Schema reference errors", command);
26552
+ process.exit(1);
26553
+ }
26554
+ return registry;
26548
26555
  }
26549
26556
 
26550
26557
  // src/commands/version-report.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobbykim/manguito-cms-cli",
3
- "version": "0.9.1",
3
+ "version": "0.10.1",
4
4
  "license": "MIT",
5
5
  "author": "Bobby Kim <bobby.sihun.kim@gmail.com>",
6
6
  "homepage": "https://github.com/bobbykim89/manguito-cms",
@@ -29,10 +29,10 @@
29
29
  "tsup": "^8.5.1",
30
30
  "typescript": "^6.0.3",
31
31
  "vite": "^8.1.3",
32
- "@bobbykim/manguito-cms-admin": "0.5.2",
33
- "@bobbykim/manguito-cms-core": "0.8.0",
34
- "@bobbykim/manguito-cms-api": "0.8.3",
35
- "@bobbykim/manguito-cms-db": "0.1.8"
32
+ "@bobbykim/manguito-cms-admin": "0.5.3",
33
+ "@bobbykim/manguito-cms-api": "0.8.4",
34
+ "@bobbykim/manguito-cms-db": "0.1.9",
35
+ "@bobbykim/manguito-cms-core": "0.9.0"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/node": "^25.9.5",