@bobbykim/manguito-cms-api 0.8.1 → 0.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1281,6 +1281,46 @@ async function loadParagraphRows(db, registry, pType, parentId, fieldName) {
1281
1281
  }
1282
1282
  return rows;
1283
1283
  }
1284
+ async function loadRelationsForEdit(db, registry, fields, id, row) {
1285
+ for (const f of fields) {
1286
+ if (f.db_column === null) {
1287
+ const comp = f.ui_component;
1288
+ if (comp.component !== "paragraph-embed" || !comp.ref) continue;
1289
+ const pType = registry.paragraph_types[comp.ref];
1290
+ if (!pType) continue;
1291
+ row[f.name] = oneOrMany(relationCardinality3(f) ?? "many", await loadParagraphRows(db, registry, pType, id, f.name));
1292
+ } else if (f.db_column.junction) {
1293
+ const j = f.db_column.junction;
1294
+ const r = await db.execute(
1295
+ sql4`SELECT ${sql4.raw(quoteIdent3(j.right_column))} FROM ${sql4.raw(quoteIdent3(j.table_name))} WHERE ${sql4.raw(quoteIdent3(j.left_column))} = ${id}`
1296
+ );
1297
+ row[f.name] = r.rows.map((linked) => linked[j.right_column]);
1298
+ }
1299
+ }
1300
+ }
1301
+ async function valuesForPublishCheck(db, registry, requiredFields, id, storedLabels, body) {
1302
+ const stored = { ...storedLabels };
1303
+ if (db) await loadRelationsForEdit(db, registry, requiredFields.filter((f) => !(f.name in body)), id, stored);
1304
+ return { ...stored, ...body };
1305
+ }
1306
+ async function persistRelationFields(db, registry, fields, body, itemId, ownerTable) {
1307
+ const deltas = [];
1308
+ for (const f of fields) {
1309
+ if (!(f.name in body)) continue;
1310
+ if (f.db_column === null) {
1311
+ const comp = f.ui_component;
1312
+ if (comp.component !== "paragraph-embed" || !comp.ref) continue;
1313
+ const pType = registry.paragraph_types[comp.ref];
1314
+ if (!pType) continue;
1315
+ deltas.push(await persistParagraphField(db, itemId, ownerTable, f.name, pType, paragraphItems(f, body[f.name]), registry));
1316
+ } else if (f.db_column.junction) {
1317
+ const value = body[f.name];
1318
+ const relatedIds = Array.isArray(value) ? value.filter((v) => typeof v === "string") : [];
1319
+ await persistJunctionField(db, itemId, f.db_column.junction, relatedIds);
1320
+ }
1321
+ }
1322
+ return deltas;
1323
+ }
1284
1324
  async function lookupBasePathId(db, pathOrName) {
1285
1325
  const r = await db.execute(
1286
1326
  sql4`SELECT id FROM base_paths WHERE path = ${pathOrName} OR name = ${pathOrName} LIMIT 1`
@@ -1436,26 +1476,7 @@ function registerAdminContentRoutes(app, registry, repos, projectors, mediaRepo,
1436
1476
  404
1437
1477
  );
1438
1478
  }
1439
- if (db) {
1440
- const row = item;
1441
- for (const f of contentType.fields) {
1442
- if (f.db_column === null) {
1443
- const comp = f.ui_component;
1444
- if (comp.component !== "paragraph-embed" || !comp.ref) continue;
1445
- const pType = registry.paragraph_types[comp.ref];
1446
- if (!pType) continue;
1447
- row[f.name] = oneOrMany(relationCardinality3(f) ?? "many", await loadParagraphRows(db, registry, pType, id, f.name));
1448
- } else if (f.db_column.junction) {
1449
- const j = f.db_column.junction;
1450
- const r = await db.execute(
1451
- sql4`SELECT ${sql4.raw(quoteIdent3(j.right_column))} FROM ${sql4.raw(quoteIdent3(j.table_name))} WHERE ${sql4.raw(quoteIdent3(j.left_column))} = ${id}`
1452
- );
1453
- row[f.name] = r.rows.map(
1454
- (row2) => row2[j.right_column]
1455
- );
1456
- }
1457
- }
1458
- }
1479
+ if (db) await loadRelationsForEdit(db, registry, contentType.fields, id, item);
1459
1480
  const data = projectRow(item, typeName, projectors);
1460
1481
  return c.json({ ok: true, data });
1461
1482
  }
@@ -1546,10 +1567,6 @@ function registerAdminContentRoutes(app, registry, repos, projectors, mediaRepo,
1546
1567
  });
1547
1568
  if (publishDeny) return publishDeny;
1548
1569
  }
1549
- const paragraphFields = contentType.fields.filter((f) => f.db_column === null);
1550
- const junctionFields = contentType.fields.filter(
1551
- (f) => f.db_column !== null && f.db_column.junction !== void 0
1552
- );
1553
1570
  const columnBackedFields = contentType.fields.filter(isColumnBacked);
1554
1571
  const columnData = {
1555
1572
  published: body["published"] ?? false
@@ -1584,19 +1601,7 @@ function registerAdminContentRoutes(app, registry, repos, projectors, mediaRepo,
1584
1601
  const itemId = item["id"];
1585
1602
  const mediaDeltas = [topLevelMediaDelta(mediaFields, null, storageBody)];
1586
1603
  if (db) {
1587
- for (const f of paragraphFields) {
1588
- const comp = f.ui_component;
1589
- if (comp.component !== "paragraph-embed" || !comp.ref) continue;
1590
- const pType = registry.paragraph_types[comp.ref];
1591
- if (!pType) continue;
1592
- const items = paragraphItems(f, body[f.name]);
1593
- mediaDeltas.push(await persistParagraphField(db, itemId, contentType.db.table_name, f.name, pType, items, registry));
1594
- }
1595
- for (const f of junctionFields) {
1596
- const junction = f.db_column.junction;
1597
- const relatedIds = Array.isArray(body[f.name]) ? body[f.name].filter((v) => typeof v === "string") : [];
1598
- await persistJunctionField(db, itemId, junction, relatedIds);
1599
- }
1604
+ mediaDeltas.push(...await persistRelationFields(db, registry, contentType.fields, body, itemId, contentType.db.table_name));
1600
1605
  }
1601
1606
  await applyMediaReferenceDelta(mergeMediaDeltas(...mediaDeltas), mediaRepo);
1602
1607
  const data = projectRow(item, typeName, projectors);
@@ -1667,7 +1672,7 @@ function registerAdminContentRoutes(app, registry, repos, projectors, mediaRepo,
1667
1672
  const publishDeny = await requirePermission("content:edit")(c, async () => {
1668
1673
  });
1669
1674
  if (publishDeny) return publishDeny;
1670
- const merged = { ...fieldKeys.toLabels(existing), ...body };
1675
+ const merged = await valuesForPublishCheck(db, registry, requiredFields, id, fieldKeys.toLabels(existing), body);
1671
1676
  const fieldErrors = checkRequiredFields(requiredFields, merged);
1672
1677
  if (fieldErrors.length > 0) {
1673
1678
  return c.json(
@@ -1683,10 +1688,6 @@ function registerAdminContentRoutes(app, registry, repos, projectors, mediaRepo,
1683
1688
  );
1684
1689
  }
1685
1690
  }
1686
- const patchParagraphFields = contentType.fields.filter((f) => f.db_column === null);
1687
- const patchJunctionFields = contentType.fields.filter(
1688
- (f) => f.db_column !== null && f.db_column.junction !== void 0
1689
- );
1690
1691
  const patchColumnBackedFields = contentType.fields.filter(isColumnBacked);
1691
1692
  const patchData = {};
1692
1693
  if (!contentType.only_one && "slug" in body) patchData["slug"] = body["slug"];
@@ -1707,21 +1708,7 @@ function registerAdminContentRoutes(app, registry, repos, projectors, mediaRepo,
1707
1708
  topLevelMediaDelta(mediaFields, existing, storageBody)
1708
1709
  ];
1709
1710
  if (db) {
1710
- for (const f of patchParagraphFields) {
1711
- if (!(f.name in body)) continue;
1712
- const comp = f.ui_component;
1713
- if (comp.component !== "paragraph-embed" || !comp.ref) continue;
1714
- const pType = registry.paragraph_types[comp.ref];
1715
- if (!pType) continue;
1716
- const items = paragraphItems(f, body[f.name]);
1717
- mediaDeltas.push(await persistParagraphField(db, id, contentType.db.table_name, f.name, pType, items, registry));
1718
- }
1719
- for (const f of patchJunctionFields) {
1720
- if (!(f.name in body)) continue;
1721
- const junction = f.db_column.junction;
1722
- const relatedIds = Array.isArray(body[f.name]) ? body[f.name].filter((v) => typeof v === "string") : [];
1723
- await persistJunctionField(db, id, junction, relatedIds);
1724
- }
1711
+ mediaDeltas.push(...await persistRelationFields(db, registry, contentType.fields, body, id, contentType.db.table_name));
1725
1712
  }
1726
1713
  await applyMediaReferenceDelta(mergeMediaDeltas(...mediaDeltas), mediaRepo);
1727
1714
  const data = projectRow(updated, typeName, projectors);
@@ -1850,6 +1837,7 @@ function registerAdminContentRoutes(app, registry, repos, projectors, mediaRepo,
1850
1837
  404
1851
1838
  );
1852
1839
  }
1840
+ if (db) await loadRelationsForEdit(db, registry, taxonomyType.fields, id, item);
1853
1841
  const data = projectRow(item, typeName, projectors);
1854
1842
  return c.json({ ok: true, data });
1855
1843
  }
@@ -1881,7 +1869,6 @@ function registerAdminContentRoutes(app, registry, repos, projectors, mediaRepo,
1881
1869
  });
1882
1870
  if (publishDeny) return publishDeny;
1883
1871
  }
1884
- const taxParagraphFields = taxonomyType.fields.filter((f) => f.db_column === null);
1885
1872
  const taxColumnBackedFields = taxonomyType.fields.filter(isColumnBacked);
1886
1873
  const taxColumnData = {
1887
1874
  published: body["published"] ?? false
@@ -1895,14 +1882,7 @@ function registerAdminContentRoutes(app, registry, repos, projectors, mediaRepo,
1895
1882
  const taxItemId = item["id"];
1896
1883
  const mediaDeltas = [topLevelMediaDelta(mediaFields, null, storageBody)];
1897
1884
  if (db) {
1898
- for (const f of taxParagraphFields) {
1899
- const comp = f.ui_component;
1900
- if (comp.component !== "paragraph-embed" || !comp.ref) continue;
1901
- const pType = registry.paragraph_types[comp.ref];
1902
- if (!pType) continue;
1903
- const items = paragraphItems(f, body[f.name]);
1904
- mediaDeltas.push(await persistParagraphField(db, taxItemId, taxonomyType.db.table_name, f.name, pType, items, registry));
1905
- }
1885
+ mediaDeltas.push(...await persistRelationFields(db, registry, taxonomyType.fields, body, taxItemId, taxonomyType.db.table_name));
1906
1886
  }
1907
1887
  await applyMediaReferenceDelta(mergeMediaDeltas(...mediaDeltas), mediaRepo);
1908
1888
  const data = projectRow(item, typeName, projectors);
@@ -1929,7 +1909,7 @@ function registerAdminContentRoutes(app, registry, repos, projectors, mediaRepo,
1929
1909
  const publishDeny = await requirePermission("content:edit")(c, async () => {
1930
1910
  });
1931
1911
  if (publishDeny) return publishDeny;
1932
- const merged = { ...fieldKeys.toLabels(existing), ...body };
1912
+ const merged = await valuesForPublishCheck(db, registry, requiredFields, id, fieldKeys.toLabels(existing), body);
1933
1913
  const fieldErrors = checkRequiredFields(requiredFields, merged);
1934
1914
  if (fieldErrors.length > 0) {
1935
1915
  return c.json(
@@ -1945,7 +1925,6 @@ function registerAdminContentRoutes(app, registry, repos, projectors, mediaRepo,
1945
1925
  );
1946
1926
  }
1947
1927
  }
1948
- const taxPatchParagraphFields = taxonomyType.fields.filter((f) => f.db_column === null);
1949
1928
  const taxPatchColumnBackedFields = taxonomyType.fields.filter(isColumnBacked);
1950
1929
  const taxPatchData = {};
1951
1930
  if ("published" in body) taxPatchData["published"] = body["published"];
@@ -1965,15 +1944,7 @@ function registerAdminContentRoutes(app, registry, repos, projectors, mediaRepo,
1965
1944
  topLevelMediaDelta(mediaFields, existing, storageBody)
1966
1945
  ];
1967
1946
  if (db) {
1968
- for (const f of taxPatchParagraphFields) {
1969
- if (!(f.name in body)) continue;
1970
- const comp = f.ui_component;
1971
- if (comp.component !== "paragraph-embed" || !comp.ref) continue;
1972
- const pType = registry.paragraph_types[comp.ref];
1973
- if (!pType) continue;
1974
- const items = paragraphItems(f, body[f.name]);
1975
- mediaDeltas.push(await persistParagraphField(db, id, taxonomyType.db.table_name, f.name, pType, items, registry));
1976
- }
1947
+ mediaDeltas.push(...await persistRelationFields(db, registry, taxonomyType.fields, body, id, taxonomyType.db.table_name));
1977
1948
  }
1978
1949
  await applyMediaReferenceDelta(mergeMediaDeltas(...mediaDeltas), mediaRepo);
1979
1950
  const data = projectRow(updated, typeName, projectors);
@@ -2980,7 +2951,7 @@ function registerUserRoutes(app, db, requirePermission, requireHierarchy) {
2980
2951
  import { sql as sql7 } from "drizzle-orm";
2981
2952
  var API_VERSION = (() => {
2982
2953
  try {
2983
- return "0.8.1";
2954
+ return "0.8.3";
2984
2955
  } catch {
2985
2956
  return "0.0.0";
2986
2957
  }