@bettercms-ai/sdk 1.36.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
@@ -110,6 +110,7 @@ __export(index_exports, {
110
110
  resetPublishedContentCache: () => resetPublishedContentCache,
111
111
  resolveSeo: () => resolveSeo,
112
112
  resolveStega: () => resolveStega,
113
+ resolved: () => resolved,
113
114
  revokeApiKey: () => revokeApiKey,
114
115
  rich: () => rich,
115
116
  search: () => search,
@@ -281,7 +282,7 @@ async function listContent(client, opts) {
281
282
  perPage: String(opts?.perPage ?? 20)
282
283
  });
283
284
  const data = await client.fetchJSON(
284
- `${client.url("")}?${params2}`
285
+ `${client.pagesUrl()}?${params2}`
285
286
  );
286
287
  return data.data;
287
288
  }
@@ -306,7 +307,7 @@ function listContentAll(client, opts) {
306
307
  perPage: String(perPage)
307
308
  });
308
309
  const result = await client.fetchJSON(
309
- `${client.url("")}?${params2}`
310
+ `${client.pagesUrl()}?${params2}`
310
311
  );
311
312
  const pageData = result.data;
312
313
  if (!pageData?.items?.length) break;
@@ -362,6 +363,10 @@ var BetterCMSDeliveryClient = class {
362
363
  throw error;
363
364
  }
364
365
  }
366
+ /** The published pages list (paginated). */
367
+ pagesUrl() {
368
+ return `${this.baseUrl}/${this.workspace}/pages`;
369
+ }
365
370
  /** Build the full URL for a content path. */
366
371
  url(path) {
367
372
  return `${this.baseUrl}/${this.workspace}/content/${path}`;
@@ -498,7 +503,7 @@ function addWebhookMethods(client, projectId) {
498
503
  }
499
504
 
500
505
  // src/admin-client.ts
501
- var DEFAULT_BASE_URL = "https://api.bettercms.ai/v1";
506
+ var DEFAULT_BASE_URL = "https://api.bettercms.ai/api/v1";
502
507
  var BetterCMSAdminClient = class extends BetterCMSDeliveryClient {
503
508
  _token;
504
509
  constructor(options) {
@@ -974,7 +979,7 @@ async function publishManagedLayout(client, input) {
974
979
  }
975
980
 
976
981
  // src/management-client.ts
977
- var DEFAULT_BASE_URL2 = "https://api.bettercms.ai/v1";
982
+ var DEFAULT_BASE_URL2 = "https://api.bettercms.ai/api/v1";
978
983
  var DEFAULT_TIMEOUT2 = 1e4;
979
984
  var BetterCMSManagementClient = class extends BetterCMSDeliveryClient {
980
985
  timeout;
@@ -1254,7 +1259,7 @@ function buildAuthResult(data) {
1254
1259
  }
1255
1260
 
1256
1261
  // src/client.ts
1257
- var DEFAULT_BASE_URL3 = "https://api.bettercms.ai/v1";
1262
+ var DEFAULT_BASE_URL3 = "https://api.bettercms.ai/api/v1/delivery";
1258
1263
  var BetterCMS = {
1259
1264
  /**
1260
1265
  * Returns a client for fetching published content.
@@ -1398,7 +1403,7 @@ function createClient(options) {
1398
1403
  return {
1399
1404
  perspective,
1400
1405
  async getEntry(slug, opts) {
1401
- 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({
1402
1407
  token: previewToken,
1403
1408
  depth: opts?.depth,
1404
1409
  select: opts?.select?.join(","),
@@ -1591,6 +1596,14 @@ function embeds(value) {
1591
1596
  const e = value.embeds;
1592
1597
  return typeof e === "object" && e !== null && typeof e.cards === "object" && e.cards !== null ? e : null;
1593
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
+ }
1594
1607
  function isRichText(value) {
1595
1608
  return typeof value === "object" && value !== null && !Array.isArray(value) && ("html" in value || "format" in value);
1596
1609
  }
@@ -2189,6 +2202,7 @@ function inEditor(win = globalThis.window) {
2189
2202
  resetPublishedContentCache,
2190
2203
  resolveSeo,
2191
2204
  resolveStega,
2205
+ resolved,
2192
2206
  revokeApiKey,
2193
2207
  rich,
2194
2208
  search,