@bettercms-ai/sdk 1.35.0 → 1.37.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/README.md CHANGED
@@ -119,6 +119,32 @@ Published reads never carry provenance, whatever `stega` is set to: the payload
119
119
  production build. Strip it yourself with `stripStega(value)` if you need the clean string, and
120
120
  decode it with `decodeStega(value)`.
121
121
 
122
+ ## Rich text
123
+
124
+ A rich-text field arrives as `{ format, value, html }` (or as a bare string, if the field was
125
+ switched from text). Render `html` with `rich()`, or render the structure (`value`) yourself:
126
+
127
+ ```ts
128
+ import { rich, plain, portableText, embeds, resolved } from "@bettercms-ai/sdk";
129
+
130
+ const entry = await client.getEntry<{ body: RichTextValue }>("launch");
131
+
132
+ rich(entry.data.body); // HTML for set:html / dangerouslySetInnerHTML: everything drawn
133
+ plain(entry.data.body); // text for <title>, meta description, alt
134
+
135
+ // Rendering the structure with @bettercms-ai/ui (or your own components):
136
+ <PortableText
137
+ value={portableText(entry.data.body) ?? entry.data.body}
138
+ embeds={embeds(entry.data.body) ?? undefined}
139
+ resolved={resolved(entry.data.body, entry) ?? undefined}
140
+ />;
141
+ ```
142
+
143
+ Related posts and author bios are resolved by the server for each response, from the published
144
+ entries, and never stored. An envelope value carries what it resolved to (`value.resolved`); a
145
+ Body stored as a bare block array cannot, so the entry carries the merged map beside `data`
146
+ (`entry.resolved`). `resolved(value, entry)` returns the value's own map, else the entry's.
147
+
122
148
  ## API
123
149
 
124
150
  ### `BetterCMS.site(options)`
@@ -127,7 +153,7 @@ decode it with `decodeStega(value)`.
127
153
  | --------- | ------ | -------- | -------------------------- |
128
154
  | `workspace` | `string` | Yes | — |
129
155
  | `apiKey` | `string` | No | — |
130
- | `baseUrl` | `string` | No | `https://api.bettercms.ai/v1` |
156
+ | `baseUrl` | `string` | No | `https://api.bettercms.ai/api/v1/delivery` |
131
157
 
132
158
  Returns a `BetterCMSDeliveryClient` instance.
133
159
 
package/dist/index.cjs CHANGED
@@ -61,6 +61,7 @@ __export(index_exports, {
61
61
  deletePage: () => deletePage,
62
62
  deleteSubmission: () => deleteSubmission,
63
63
  deleteWorkspace: () => deleteWorkspace,
64
+ embeds: () => embeds,
64
65
  encodeStega: () => encodeStega,
65
66
  entrySeoInput: () => entrySeoInput,
66
67
  formInitialValues: () => formInitialValues,
@@ -109,6 +110,7 @@ __export(index_exports, {
109
110
  resetPublishedContentCache: () => resetPublishedContentCache,
110
111
  resolveSeo: () => resolveSeo,
111
112
  resolveStega: () => resolveStega,
113
+ resolved: () => resolved,
112
114
  revokeApiKey: () => revokeApiKey,
113
115
  rich: () => rich,
114
116
  search: () => search,
@@ -280,7 +282,7 @@ async function listContent(client, opts) {
280
282
  perPage: String(opts?.perPage ?? 20)
281
283
  });
282
284
  const data = await client.fetchJSON(
283
- `${client.url("")}?${params2}`
285
+ `${client.pagesUrl()}?${params2}`
284
286
  );
285
287
  return data.data;
286
288
  }
@@ -305,7 +307,7 @@ function listContentAll(client, opts) {
305
307
  perPage: String(perPage)
306
308
  });
307
309
  const result = await client.fetchJSON(
308
- `${client.url("")}?${params2}`
310
+ `${client.pagesUrl()}?${params2}`
309
311
  );
310
312
  const pageData = result.data;
311
313
  if (!pageData?.items?.length) break;
@@ -361,6 +363,10 @@ var BetterCMSDeliveryClient = class {
361
363
  throw error;
362
364
  }
363
365
  }
366
+ /** The published pages list (paginated). */
367
+ pagesUrl() {
368
+ return `${this.baseUrl}/${this.workspace}/pages`;
369
+ }
364
370
  /** Build the full URL for a content path. */
365
371
  url(path) {
366
372
  return `${this.baseUrl}/${this.workspace}/content/${path}`;
@@ -497,7 +503,7 @@ function addWebhookMethods(client, projectId) {
497
503
  }
498
504
 
499
505
  // src/admin-client.ts
500
- var DEFAULT_BASE_URL = "https://api.bettercms.ai/v1";
506
+ var DEFAULT_BASE_URL = "https://api.bettercms.ai/api/v1";
501
507
  var BetterCMSAdminClient = class extends BetterCMSDeliveryClient {
502
508
  _token;
503
509
  constructor(options) {
@@ -973,7 +979,7 @@ async function publishManagedLayout(client, input) {
973
979
  }
974
980
 
975
981
  // src/management-client.ts
976
- var DEFAULT_BASE_URL2 = "https://api.bettercms.ai/v1";
982
+ var DEFAULT_BASE_URL2 = "https://api.bettercms.ai/api/v1";
977
983
  var DEFAULT_TIMEOUT2 = 1e4;
978
984
  var BetterCMSManagementClient = class extends BetterCMSDeliveryClient {
979
985
  timeout;
@@ -1253,7 +1259,7 @@ function buildAuthResult(data) {
1253
1259
  }
1254
1260
 
1255
1261
  // src/client.ts
1256
- var DEFAULT_BASE_URL3 = "https://api.bettercms.ai/v1";
1262
+ var DEFAULT_BASE_URL3 = "https://api.bettercms.ai/api/v1/delivery";
1257
1263
  var BetterCMS = {
1258
1264
  /**
1259
1265
  * Returns a client for fetching published content.
@@ -1397,7 +1403,7 @@ function createClient(options) {
1397
1403
  return {
1398
1404
  perspective,
1399
1405
  async getEntry(slug, opts) {
1400
- const url = draft && previewToken ? `${apiUrl}/api/v1/preview/${encodeURIComponent(slug)}${qs({
1406
+ const url = draft && previewToken && tokenSlug(previewToken) === slug ? `${apiUrl}/api/v1/preview/${encodeURIComponent(slug)}${qs({
1401
1407
  token: previewToken,
1402
1408
  depth: opts?.depth,
1403
1409
  select: opts?.select?.join(","),
@@ -1585,6 +1591,19 @@ function portableText(value) {
1585
1591
  const v = value;
1586
1592
  return v.format === PORTABLE_TEXT_FORMAT && Array.isArray(v.value) ? v.value : null;
1587
1593
  }
1594
+ function embeds(value) {
1595
+ if (!isRichText(value)) return null;
1596
+ const e = value.embeds;
1597
+ return typeof e === "object" && e !== null && typeof e.cards === "object" && e.cards !== null ? e : null;
1598
+ }
1599
+ var resolvedMap = (r) => typeof r === "object" && r !== null && !Array.isArray(r) ? r : null;
1600
+ function resolved(value, entry) {
1601
+ const own = isRichText(value) ? resolvedMap(value.resolved) : null;
1602
+ if (own) return own;
1603
+ if (entry) return resolvedMap(entry.resolved);
1604
+ const v = value;
1605
+ return v && typeof v === "object" && !Array.isArray(v) && "data" in v ? resolvedMap(v.resolved) : null;
1606
+ }
1588
1607
  function isRichText(value) {
1589
1608
  return typeof value === "object" && value !== null && !Array.isArray(value) && ("html" in value || "format" in value);
1590
1609
  }
@@ -2134,6 +2153,7 @@ function inEditor(win = globalThis.window) {
2134
2153
  deletePage,
2135
2154
  deleteSubmission,
2136
2155
  deleteWorkspace,
2156
+ embeds,
2137
2157
  encodeStega,
2138
2158
  entrySeoInput,
2139
2159
  formInitialValues,
@@ -2182,6 +2202,7 @@ function inEditor(win = globalThis.window) {
2182
2202
  resetPublishedContentCache,
2183
2203
  resolveSeo,
2184
2204
  resolveStega,
2205
+ resolved,
2185
2206
  revokeApiKey,
2186
2207
  rich,
2187
2208
  search,