@bettercms-ai/sdk 1.18.0 → 1.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -58,6 +58,7 @@ __export(index_exports, {
58
58
  deleteSubmission: () => deleteSubmission,
59
59
  deleteWorkspace: () => deleteWorkspace,
60
60
  encodeStega: () => encodeStega,
61
+ entrySeoInput: () => entrySeoInput,
61
62
  formInitialValues: () => formInitialValues,
62
63
  getApiKeyUsage: () => getApiKeyUsage,
63
64
  getBlockType: () => import_types.getBlockType,
@@ -154,13 +155,24 @@ var BetterCMSError = class _BetterCMSError extends Error {
154
155
  * hint which field or rule failed (FLO-474). Mirrors the forms client's `fieldErrors`.
155
156
  */
156
157
  fieldErrors;
157
- constructor(message, status, code, bodyCode, fieldErrors) {
158
+ /**
159
+ * The parsed response body, when there was one.
160
+ *
161
+ * Several refusals carry STRUCTURED detail that neither `message` nor `fieldErrors` can hold,
162
+ * and which is the whole point of the refusal: a component publish 409s with the full
163
+ * `readiness` tuple (what evidence is missing, whether a human still has to approve it) and
164
+ * 422s with the `issues` naming the Layouts it would break. Collapsing those to a sentence
165
+ * leaves a caller able to report that something failed and not what to do about it.
166
+ */
167
+ body;
168
+ constructor(message, status, code, bodyCode, fieldErrors, body) {
158
169
  super(message);
159
170
  this.name = "BetterCMSError";
160
171
  this.status = status;
161
172
  this.code = code;
162
173
  this.bodyCode = bodyCode;
163
174
  this.fieldErrors = fieldErrors;
175
+ this.body = body;
164
176
  if (Error.captureStackTrace) {
165
177
  Error.captureStackTrace(this, _BetterCMSError);
166
178
  }
@@ -187,6 +199,7 @@ var BetterCMSError = class _BetterCMSError extends Error {
187
199
  let bodyCode;
188
200
  let fieldErrors;
189
201
  let code = statusToCode(res.status);
202
+ let raw;
190
203
  try {
191
204
  const body = await res.json();
192
205
  if (body?.errors && typeof body.errors === "object") {
@@ -202,9 +215,10 @@ var BetterCMSError = class _BetterCMSError extends Error {
202
215
  if (field) message = `${field}: ${detail}`;
203
216
  }
204
217
  if (body?.code) bodyCode = body.code;
218
+ raw = body;
205
219
  } catch {
206
220
  }
207
- return new _BetterCMSError(message, res.status, code, bodyCode, fieldErrors);
221
+ return new _BetterCMSError(message, res.status, code, bodyCode, fieldErrors, raw);
208
222
  }
209
223
  };
210
224
 
@@ -664,6 +678,13 @@ async function deleteModel(client, id) {
664
678
  }
665
679
 
666
680
  // src/methods/management/media.ts
681
+ async function updateAsset(client, id, input) {
682
+ const { data } = await client.fetchJSON(
683
+ client.url(`/management/media/${encodeURIComponent(id)}`),
684
+ { method: "PATCH", body: JSON.stringify(input) }
685
+ );
686
+ return data;
687
+ }
667
688
  var MIME_BY_EXT = {
668
689
  png: "image/png",
669
690
  jpg: "image/jpeg",
@@ -791,6 +812,10 @@ async function uploadAsset(client, input) {
791
812
  body: bytes
792
813
  }
793
814
  );
815
+ if (input.transcript && input.transcript.trim()) {
816
+ await updateAsset(client, data.id, { transcript: input.transcript });
817
+ return { ...data, transcript: input.transcript };
818
+ }
794
819
  return data;
795
820
  }
796
821
 
@@ -825,9 +850,10 @@ async function updateForm(client, id, input) {
825
850
  }
826
851
 
827
852
  // src/methods/management/components.ts
828
- async function listComponents(client) {
853
+ async function listComponents(client, options) {
854
+ const query = options?.select ? `?select=${options.select}` : "";
829
855
  const res = await client.fetchJSON(
830
- client.url("/management/components"),
856
+ client.url(`/management/components${query}`),
831
857
  { method: "GET" }
832
858
  );
833
859
  return res.data;
@@ -1051,6 +1077,10 @@ var BetterCMSManagementClient = class extends BetterCMSDeliveryClient {
1051
1077
  uploadAsset(input) {
1052
1078
  return uploadAsset(this, input);
1053
1079
  }
1080
+ /** Set an asset's alt text, caption or transcript (video/audio only). `null` clears. */
1081
+ updateAsset(id, input) {
1082
+ return updateAsset(this, id, input);
1083
+ }
1054
1084
  // ── Forms (read-only): discover dashboard-built forms to embed into site code ──
1055
1085
  /** List forms in the key's project (or workspace-level). */
1056
1086
  listForms() {
@@ -1068,9 +1098,8 @@ var BetterCMSManagementClient = class extends BetterCMSDeliveryClient {
1068
1098
  updateForm(id, input) {
1069
1099
  return updateForm(this, id, input);
1070
1100
  }
1071
- // ── Components: discover + author reusable symbols ──
1072
- listComponents() {
1073
- return listComponents(this);
1101
+ listComponents(options) {
1102
+ return options?.select ? listComponents(this, { select: options.select }) : listComponents(this);
1074
1103
  }
1075
1104
  getComponent(id) {
1076
1105
  return getComponent(this, id);
@@ -1520,6 +1549,68 @@ function jsonLdNodes(schema) {
1520
1549
  }
1521
1550
  return out;
1522
1551
  }
1552
+ var SCHEMA_TYPE_CHOICES = [
1553
+ "WebPage",
1554
+ "AboutPage",
1555
+ "ContactPage",
1556
+ "CollectionPage",
1557
+ "Blog",
1558
+ "BlogPosting",
1559
+ "Article",
1560
+ "Product",
1561
+ "FAQPage",
1562
+ "Event",
1563
+ "Organization",
1564
+ "LocalBusiness"
1565
+ ];
1566
+ function compact(node) {
1567
+ return Object.fromEntries(Object.entries(node).filter(([, value]) => value != null && value !== ""));
1568
+ }
1569
+ function schemaNode(type, { name, description, image, url }) {
1570
+ switch (type) {
1571
+ case "BlogPosting":
1572
+ case "Article":
1573
+ return compact({ "@type": type, headline: name, description, image, url, mainEntityOfPage: url });
1574
+ case "Product":
1575
+ case "Event":
1576
+ return compact({ "@type": type, name, description, image, url });
1577
+ case "FAQPage":
1578
+ case "WebSite":
1579
+ return compact({ "@type": type, name, description, url });
1580
+ case "Organization":
1581
+ return compact({ "@type": type, name, description, url, logo: image });
1582
+ default:
1583
+ return compact({ "@type": type, name, description, url, image });
1584
+ }
1585
+ }
1586
+ function pageJsonLd(page, meta, canonical, siteSchema) {
1587
+ const custom = jsonLdNodes(meta.schema);
1588
+ if (custom.length > 0) return custom;
1589
+ const props = {
1590
+ name: (page.metaTitle || page.title || "").trim(),
1591
+ description: (page.metaDescription || "").trim(),
1592
+ image: (meta.og?.image || "").trim(),
1593
+ url: canonical.trim()
1594
+ };
1595
+ const schemaType = meta.schemaType;
1596
+ if (typeof schemaType === "string" && SCHEMA_TYPE_CHOICES.includes(schemaType)) {
1597
+ return [schemaNode(schemaType, props)];
1598
+ }
1599
+ if (page.slug === "home") {
1600
+ return jsonLdNodes(siteSchema).length > 0 ? [] : [schemaNode("WebSite", props)];
1601
+ }
1602
+ return [schemaNode("WebPage", props)];
1603
+ }
1604
+ function entrySeoInput(entry) {
1605
+ const { metaTitle, metaDescription, noindex, ...metaJson } = entry.seo ?? {};
1606
+ return {
1607
+ title: metaTitle || entry.slug,
1608
+ metaTitle: metaTitle ?? null,
1609
+ metaDescription: metaDescription ?? null,
1610
+ metaJson,
1611
+ noindex: noindex === true
1612
+ };
1613
+ }
1523
1614
  function resolveSeo(page, defaults = {}, location = {}) {
1524
1615
  const meta = page.metaJson ?? {};
1525
1616
  const title = page.metaTitle || page.title || "";
@@ -1547,7 +1638,9 @@ function resolveSeo(page, defaults = {}, location = {}) {
1547
1638
  image: twImage,
1548
1639
  site: defaults.twitterHandle || ""
1549
1640
  },
1550
- jsonLd: [...jsonLdNodes(defaults.siteSchema), ...jsonLdNodes(meta.schema)]
1641
+ jsonLd: [...jsonLdNodes(defaults.siteSchema), ...pageJsonLd(page, meta, canonical, defaults.siteSchema)],
1642
+ noindex: page.noindex === true,
1643
+ robots: { index: page.noindex !== true, follow: true }
1551
1644
  };
1552
1645
  }
1553
1646
 
@@ -1891,6 +1984,7 @@ var import_types = require("@bettercms-ai/types");
1891
1984
  deleteSubmission,
1892
1985
  deleteWorkspace,
1893
1986
  encodeStega,
1987
+ entrySeoInput,
1894
1988
  formInitialValues,
1895
1989
  getApiKeyUsage,
1896
1990
  getBlockType,