@bettercms-ai/sdk 1.19.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.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _bettercms_ai_types from '@bettercms-ai/types';
2
- import { ContentPageResult, Content, DeliveredLayout, ContentModelField, BetterCMSErrorCode, LayoutStructureDocument, LayoutDataDocument, PageLayoutOverrideDocument, ManagementLayoutCommand, AuthUser, AuthSession, SignInInput, SignUpInput, Perspective, DeliveryEntry, DeliveryList, DeliveryPage, DeliveryComponent, PageMetaJson, SiteSeoDefaults, Page, MediaAsset, Form, FormSubmission, Workspace, ApiKey, ApiKeyPermission, ApiKeyTokenType } from '@bettercms-ai/types';
2
+ import { ContentPageResult, Content, DeliveredLayout, ContentModelField, BetterCMSErrorCode, LayoutStructureDocument, LayoutDataDocument, PageLayoutOverrideDocument, ManagementLayoutCommand, AuthUser, AuthSession, SignInInput, SignUpInput, Perspective, DeliveryEntry, DeliveryList, DeliveryPage, DeliveryComponent, PageMetaJson, DeliveryEntrySeo, SiteSeoDefaults, Page, MediaAsset, Form, FormSubmission, Workspace, ApiKey, ApiKeyPermission, ApiKeyTokenType } from '@bettercms-ai/types';
3
3
  export { ApiError, ApiKey, ApiKeyPermission, ApiKeyTokenType, AssertEqual, AuthSession, AuthUser, BetterCMSErrorCode, BlockType, ButtonBlock, ButtonProps, ColumnsBlock, ColumnsProps, Content, ContentBlock, ContentEntry, ContentModel, ContentModelField, ContentPageResult, ContentResponse, DeepReadonly, DeliveryComponent, DeliveryEntry, DeliveryList, DeliveryPage, Form, FormBlock, FormField, FormProps, FormSubmission, HeadingBlock, HeadingProps, ImageBlock, ImageProps, MediaAsset, Page, PageMetaJson, PaginatedResult, Perspective, Redirect, SignInInput, SignUpInput, SiteSeoDefaults, SpacerBlock, SpacerProps, TextBlock, TextProps, VideoBlock, VideoProps, Workspace, getBlockType, isBlock } from '@bettercms-ai/types';
4
4
  export { ImageFit, ImageFormat, ImageSource, ImageUrlBuilder, ImageUrlOptions, imageUrl, default as imageUrlBuilder } from '@bettercms-ai/image-url';
5
5
 
@@ -223,6 +223,8 @@ interface ManagedContentModel {
223
223
  name: string;
224
224
  slug: string;
225
225
  description: string | null;
226
+ /** Public URL of one entry, e.g. `/blog/:slug` (`:slug` is the entry's slug). Null = none. */
227
+ urlPattern?: string | null;
226
228
  fields: ContentModelField[];
227
229
  createdAt: string;
228
230
  updatedAt: string;
@@ -274,6 +276,11 @@ interface CreateManagedPageInput {
274
276
  /** Append fields to an existing page's schema (additive — see addPageFields). */
275
277
  interface AddPageFieldsInput {
276
278
  addFields: ContentModelField[];
279
+ /**
280
+ * Optional insertion point: the key of an existing TOP-LEVEL field to insert after. Omit to
281
+ * append (the default). An unknown key is refused by the API, never silently appended.
282
+ */
283
+ after?: string;
277
284
  }
278
285
  interface CreateModelInput {
279
286
  name: string;
@@ -289,12 +296,27 @@ interface CreateModelInput {
289
296
  * a block would orphan every entry it already has.
290
297
  */
291
298
  kind?: "model" | "block";
299
+ /** Editor-only field grouping. Fields join one with `fieldsetId`. Order is the array index. */
300
+ fieldsets?: ModelFieldset[];
301
+ /** Public URL of one entry, e.g. `/blog/:slug`: starts with `/`, contains `:slug` exactly once. */
302
+ urlPattern?: string | null;
303
+ }
304
+ /** A named, editor-only group of a model's fields. Same shape as the dashboard's `Fieldset`. */
305
+ interface ModelFieldset {
306
+ id: string;
307
+ name: string;
308
+ /** One line shown under the card title in the editor, at most 500 characters. */
309
+ description?: string;
292
310
  }
293
311
  interface UpdateModelInput {
294
312
  name?: string;
295
313
  slug?: string;
296
314
  description?: string;
297
315
  fields?: ContentModelField[];
316
+ /** Replaces the fieldset list. `null` drops every fieldset. Sent alone, it leaves `fields` untouched. */
317
+ fieldsets?: ModelFieldset[] | null;
318
+ /** Public URL of one entry, e.g. `/blog/:slug`. `null` (or "") clears it. */
319
+ urlPattern?: string | null;
298
320
  }
299
321
  interface CreateEntryInput {
300
322
  contentModelId: string;
@@ -308,6 +330,27 @@ interface UpdateEntryInput {
308
330
  status?: "draft" | "published";
309
331
  data?: Record<string, unknown>;
310
332
  pageId?: string | null;
333
+ /** The entry's native SEO. Merges into what is stored: an omitted key is kept, null or "" clears it. */
334
+ meta?: {
335
+ metaTitle?: string | null;
336
+ metaDescription?: string | null;
337
+ noindex?: boolean;
338
+ canonical?: string | null;
339
+ og?: {
340
+ title?: string | null;
341
+ description?: string | null;
342
+ image?: string | null;
343
+ type?: string | null;
344
+ } | null;
345
+ twitter?: {
346
+ card?: string | null;
347
+ title?: string | null;
348
+ description?: string | null;
349
+ image?: string | null;
350
+ } | null;
351
+ schemaType?: string | null;
352
+ schema?: Record<string, unknown> | Array<Record<string, unknown>> | null;
353
+ };
311
354
  }
312
355
  /** Set a page's field VALUES (the actual content). For a singleton, upserts its one entry. */
313
356
  interface SetPageContentInput {
@@ -385,6 +428,12 @@ interface UploadAssetInput {
385
428
  filename?: string;
386
429
  altText?: string;
387
430
  caption?: string;
431
+ /**
432
+ * Video/audio only: the spoken words (≤ 100,000 characters). Stored on the asset and published
433
+ * wherever the file is used. Sent as a second JSON call after the upload, because it is too
434
+ * long for the upload's query string.
435
+ */
436
+ transcript?: string;
388
437
  /** Target Media Library folder id (defaults to project root). */
389
438
  folderId?: string;
390
439
  }
@@ -393,6 +442,27 @@ interface UploadedAsset {
393
442
  url: string;
394
443
  key: string;
395
444
  filename: string;
445
+ /** Present when a transcript was written with the upload. */
446
+ transcript?: string;
447
+ }
448
+ /** Describe an existing asset. `null` clears a field; an omitted key is left alone. */
449
+ interface UpdateAssetInput {
450
+ altText?: string | null;
451
+ caption?: string | null;
452
+ /** Video/audio only, ≤ 100,000 characters. */
453
+ transcript?: string | null;
454
+ }
455
+ interface ManagedMediaAsset {
456
+ id: string;
457
+ url: string;
458
+ filename: string;
459
+ mimeType: string;
460
+ sizeBytes: number;
461
+ altText: string | null;
462
+ caption: string | null;
463
+ transcript: string | null;
464
+ folderId: string | null;
465
+ createdAt: string;
396
466
  }
397
467
 
398
468
  /** Semantic error codes used by the SDK. */
@@ -840,6 +910,8 @@ declare class BetterCMSManagementClient extends BetterCMSDeliveryClient {
840
910
  /** Get one content entry by id INCLUDING its data (incl. drafts). */
841
911
  getEntry(id: string): Promise<ManagedContentEntry>;
842
912
  uploadAsset(input: UploadAssetInput): Promise<UploadedAsset>;
913
+ /** Set an asset's alt text, caption or transcript (video/audio only). `null` clears. */
914
+ updateAsset(id: string, input: UpdateAssetInput): Promise<ManagedMediaAsset>;
843
915
  /** List forms in the key's project (or workspace-level). */
844
916
  listForms(): Promise<ManagedForm[]>;
845
917
  /** Get one form by id INCLUDING its field schema + settings. */
@@ -1213,6 +1285,10 @@ interface SeoInput {
1213
1285
  metaTitle?: string | null;
1214
1286
  metaDescription?: string | null;
1215
1287
  metaJson?: PageMetaJson | null;
1288
+ /** `"home"` makes the Automatic JSON-LD a WebSite, as the hosted renderer does. */
1289
+ slug?: string | null;
1290
+ /** Exclude from search engines. Surfaces as `ResolvedSeo.noindex` / `robots`. */
1291
+ noindex?: boolean | null;
1216
1292
  }
1217
1293
  /** Fully-resolved SEO values, page-over-site. Empty string ⇒ omit that tag. */
1218
1294
  interface ResolvedSeo {
@@ -1238,9 +1314,33 @@ interface ResolvedSeo {
1238
1314
  image: string;
1239
1315
  site: string;
1240
1316
  };
1241
- /** JSON-LD nodes (site schema first, then the page's), already flattened + de-empted. */
1317
+ /**
1318
+ * JSON-LD nodes (site schema first, then the page's), already flattened + de-empted. The page's
1319
+ * part follows the renderer's precedence: Custom (`metaJson.schema`) > `metaJson.schemaType` >
1320
+ * Automatic (WebPage; WebSite on the home page).
1321
+ */
1242
1322
  jsonLd: Array<Record<string, unknown>>;
1323
+ /** True when the page is excluded from search engines (the renderer's `<meta name="robots" content="noindex">`). */
1324
+ noindex: boolean;
1325
+ /** `noindex` in the `{ index, follow }` shape Next's `Metadata.robots` takes. */
1326
+ robots: {
1327
+ index: boolean;
1328
+ follow: boolean;
1329
+ };
1243
1330
  }
1331
+ /**
1332
+ * A Delivery API entry as a `resolveSeo` input. The server already resolved the collection
1333
+ * template's `{{field}}` tokens for this entry and merged the entry's own SEO over it, so this is
1334
+ * a reshape, not a resolver:
1335
+ *
1336
+ * const entry = await bcms.getEntry("astro");
1337
+ * const seo = resolveSeo(entrySeoInput(entry), siteDefaults, { siteUrl, path: `/tags/${entry.slug}` });
1338
+ * // seo.jsonLd holds the template's schema, resolved for this entry
1339
+ */
1340
+ declare function entrySeoInput(entry: {
1341
+ slug: string;
1342
+ seo?: DeliveryEntrySeo | null;
1343
+ }): SeoInput;
1244
1344
  /** Where this page lives, so a canonical can be derived when the page sets none. */
1245
1345
  interface SeoLocation {
1246
1346
  /** Absolute site origin, e.g. `https://acme.com`. Trailing slash optional. */
@@ -1480,4 +1580,4 @@ declare function inviteMember(client: BetterCMSAdminClient, workspaceId: string,
1480
1580
  declare function updateMemberRole(client: BetterCMSAdminClient, workspaceId: string, memberId: string, role: MemberRole): Promise<Member>;
1481
1581
  declare function removeMember(client: BetterCMSAdminClient, workspaceId: string, memberId: string): Promise<void>;
1482
1582
 
1483
- export { type AddPageFieldsInput, type ApiKeyUsage, type ApiKeyWithRaw, type AuthResult, BetterCMSError as BCMSClientError, ErrorCodes as BCMSErrorCodes, BetterCMS, BetterCMSAdminClient, type BetterCMSAdminOptions, BetterCMSDeliveryClient, BetterCMSError, BetterCMSManagementClient, type BetterCMSManagementOptions, type BetterCMSReadClient, type BetterCMSSiteOptions, type CommandManagedLayoutInput, type CreateApiKeyInput, type CreateClientOptions, type CreateEntryInput, type CreateFormInput, type CreateManagedPageInput, type CreateModelInput, type CreatePageInput, type CreateWorkspaceInput, type DeliveryForm, type DeliveryFormField, type DeliveryFormFieldType, ErrorCodes, type ExtractionCandidate, type FormFieldInput, type FormListOptions, type FormSubmitError, type FormValue, type FormValues, type GetEntryOptions, type GetManagedLayoutOptions, type ListContentAllOptions, type ListContentOptions, type ListEntriesFilter, type ListEntriesOptions, type ListPagesOptions, type ManagedComponent, type ManagedComponentInput, type ManagedComponentSummary, type ManagedContentEntry, type ManagedContentModel, type ManagedForm, type ManagedFormInput, type ManagedLayoutClient, type ManagedLayoutDocument, type ManagedPage, type ManagementClient, type MediaListOptions, type MediaMetadata, type Member, type MemberRole, PORTABLE_TEXT_FORMAT, type PageListOptions, type PendingInvite, type PublishManagedLayoutInput, type ResolvedSeo, type RichTextValue, type SearchHit, type SearchOptions, type SeoInput, type SeoLocation, type SeoMeta, type SeoMetaInput, type SetPageContentInput, type StegaPayload, type SubmissionListOptions, type SubmitFormOptions, type SubmitFormResult, type TextOrRich, type UpdateApiKeyInput, type UpdateEntryInput, type UpdateFormInput, type UpdateModelInput, type UpdatePageInput, type UpdateWorkspaceInput, type UploadAssetInput, type UploadedAsset, type WriteContentInput, addModelFields, addPageFields, asStringArray, commandManagedLayout, createApiKey, createClient, createEntry, createForm, createManagedPage, createModel, createPage, createWorkspace, decodeStega, deleteForm, deleteMedia, deletePage, deleteSubmission, deleteWorkspace, encodeStega, formInitialValues, getApiKeyUsage, getEntry, getForm, getManagedLayout, getManagedPage, getMedia, getMember, getModel, getPage, getSubmission, getWorkspace, inviteMember, isMultiValueField, isRichText, listApiKeys, listEntries, listForms, listManagedPages, listMedia, listMembers, listModels, listPages, listSubmissions, listWorkspaces, plain, portableText, publishManagedLayout, publishPage, regenerateApiKey, removeMember, resolveSeo, revokeApiKey, rich, search, setPageContent, shouldShowField, signIn, signInWithGithub, signInWithGoogle, signUp, stripStega, submitForm, toggleOption, updateApiKey, updateEntry, updateForm, updateMemberRole, updateModel, updatePage, updateWorkspace, uploadMedia };
1583
+ export { type AddPageFieldsInput, type ApiKeyUsage, type ApiKeyWithRaw, type AuthResult, BetterCMSError as BCMSClientError, ErrorCodes as BCMSErrorCodes, BetterCMS, BetterCMSAdminClient, type BetterCMSAdminOptions, BetterCMSDeliveryClient, BetterCMSError, BetterCMSManagementClient, type BetterCMSManagementOptions, type BetterCMSReadClient, type BetterCMSSiteOptions, type CommandManagedLayoutInput, type CreateApiKeyInput, type CreateClientOptions, type CreateEntryInput, type CreateFormInput, type CreateManagedPageInput, type CreateModelInput, type CreatePageInput, type CreateWorkspaceInput, type DeliveryForm, type DeliveryFormField, type DeliveryFormFieldType, ErrorCodes, type ExtractionCandidate, type FormFieldInput, type FormListOptions, type FormSubmitError, type FormValue, type FormValues, type GetEntryOptions, type GetManagedLayoutOptions, type ListContentAllOptions, type ListContentOptions, type ListEntriesFilter, type ListEntriesOptions, type ListPagesOptions, type ManagedComponent, type ManagedComponentInput, type ManagedComponentSummary, type ManagedContentEntry, type ManagedContentModel, type ManagedForm, type ManagedFormInput, type ManagedLayoutClient, type ManagedLayoutDocument, type ManagedMediaAsset, type ManagedPage, type ManagementClient, type MediaListOptions, type MediaMetadata, type Member, type MemberRole, PORTABLE_TEXT_FORMAT, type PageListOptions, type PendingInvite, type PublishManagedLayoutInput, type ResolvedSeo, type RichTextValue, type SearchHit, type SearchOptions, type SeoInput, type SeoLocation, type SeoMeta, type SeoMetaInput, type SetPageContentInput, type StegaPayload, type SubmissionListOptions, type SubmitFormOptions, type SubmitFormResult, type TextOrRich, type UpdateApiKeyInput, type UpdateAssetInput, type UpdateEntryInput, type UpdateFormInput, type UpdateModelInput, type UpdatePageInput, type UpdateWorkspaceInput, type UploadAssetInput, type UploadedAsset, type WriteContentInput, addModelFields, addPageFields, asStringArray, commandManagedLayout, createApiKey, createClient, createEntry, createForm, createManagedPage, createModel, createPage, createWorkspace, decodeStega, deleteForm, deleteMedia, deletePage, deleteSubmission, deleteWorkspace, encodeStega, entrySeoInput, formInitialValues, getApiKeyUsage, getEntry, getForm, getManagedLayout, getManagedPage, getMedia, getMember, getModel, getPage, getSubmission, getWorkspace, inviteMember, isMultiValueField, isRichText, listApiKeys, listEntries, listForms, listManagedPages, listMedia, listMembers, listModels, listPages, listSubmissions, listWorkspaces, plain, portableText, publishManagedLayout, publishPage, regenerateApiKey, removeMember, resolveSeo, revokeApiKey, rich, search, setPageContent, shouldShowField, signIn, signInWithGithub, signInWithGoogle, signUp, stripStega, submitForm, toggleOption, updateApiKey, updateEntry, updateForm, updateMemberRole, updateModel, updatePage, updateWorkspace, uploadMedia };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _bettercms_ai_types from '@bettercms-ai/types';
2
- import { ContentPageResult, Content, DeliveredLayout, ContentModelField, BetterCMSErrorCode, LayoutStructureDocument, LayoutDataDocument, PageLayoutOverrideDocument, ManagementLayoutCommand, AuthUser, AuthSession, SignInInput, SignUpInput, Perspective, DeliveryEntry, DeliveryList, DeliveryPage, DeliveryComponent, PageMetaJson, SiteSeoDefaults, Page, MediaAsset, Form, FormSubmission, Workspace, ApiKey, ApiKeyPermission, ApiKeyTokenType } from '@bettercms-ai/types';
2
+ import { ContentPageResult, Content, DeliveredLayout, ContentModelField, BetterCMSErrorCode, LayoutStructureDocument, LayoutDataDocument, PageLayoutOverrideDocument, ManagementLayoutCommand, AuthUser, AuthSession, SignInInput, SignUpInput, Perspective, DeliveryEntry, DeliveryList, DeliveryPage, DeliveryComponent, PageMetaJson, DeliveryEntrySeo, SiteSeoDefaults, Page, MediaAsset, Form, FormSubmission, Workspace, ApiKey, ApiKeyPermission, ApiKeyTokenType } from '@bettercms-ai/types';
3
3
  export { ApiError, ApiKey, ApiKeyPermission, ApiKeyTokenType, AssertEqual, AuthSession, AuthUser, BetterCMSErrorCode, BlockType, ButtonBlock, ButtonProps, ColumnsBlock, ColumnsProps, Content, ContentBlock, ContentEntry, ContentModel, ContentModelField, ContentPageResult, ContentResponse, DeepReadonly, DeliveryComponent, DeliveryEntry, DeliveryList, DeliveryPage, Form, FormBlock, FormField, FormProps, FormSubmission, HeadingBlock, HeadingProps, ImageBlock, ImageProps, MediaAsset, Page, PageMetaJson, PaginatedResult, Perspective, Redirect, SignInInput, SignUpInput, SiteSeoDefaults, SpacerBlock, SpacerProps, TextBlock, TextProps, VideoBlock, VideoProps, Workspace, getBlockType, isBlock } from '@bettercms-ai/types';
4
4
  export { ImageFit, ImageFormat, ImageSource, ImageUrlBuilder, ImageUrlOptions, imageUrl, default as imageUrlBuilder } from '@bettercms-ai/image-url';
5
5
 
@@ -223,6 +223,8 @@ interface ManagedContentModel {
223
223
  name: string;
224
224
  slug: string;
225
225
  description: string | null;
226
+ /** Public URL of one entry, e.g. `/blog/:slug` (`:slug` is the entry's slug). Null = none. */
227
+ urlPattern?: string | null;
226
228
  fields: ContentModelField[];
227
229
  createdAt: string;
228
230
  updatedAt: string;
@@ -274,6 +276,11 @@ interface CreateManagedPageInput {
274
276
  /** Append fields to an existing page's schema (additive — see addPageFields). */
275
277
  interface AddPageFieldsInput {
276
278
  addFields: ContentModelField[];
279
+ /**
280
+ * Optional insertion point: the key of an existing TOP-LEVEL field to insert after. Omit to
281
+ * append (the default). An unknown key is refused by the API, never silently appended.
282
+ */
283
+ after?: string;
277
284
  }
278
285
  interface CreateModelInput {
279
286
  name: string;
@@ -289,12 +296,27 @@ interface CreateModelInput {
289
296
  * a block would orphan every entry it already has.
290
297
  */
291
298
  kind?: "model" | "block";
299
+ /** Editor-only field grouping. Fields join one with `fieldsetId`. Order is the array index. */
300
+ fieldsets?: ModelFieldset[];
301
+ /** Public URL of one entry, e.g. `/blog/:slug`: starts with `/`, contains `:slug` exactly once. */
302
+ urlPattern?: string | null;
303
+ }
304
+ /** A named, editor-only group of a model's fields. Same shape as the dashboard's `Fieldset`. */
305
+ interface ModelFieldset {
306
+ id: string;
307
+ name: string;
308
+ /** One line shown under the card title in the editor, at most 500 characters. */
309
+ description?: string;
292
310
  }
293
311
  interface UpdateModelInput {
294
312
  name?: string;
295
313
  slug?: string;
296
314
  description?: string;
297
315
  fields?: ContentModelField[];
316
+ /** Replaces the fieldset list. `null` drops every fieldset. Sent alone, it leaves `fields` untouched. */
317
+ fieldsets?: ModelFieldset[] | null;
318
+ /** Public URL of one entry, e.g. `/blog/:slug`. `null` (or "") clears it. */
319
+ urlPattern?: string | null;
298
320
  }
299
321
  interface CreateEntryInput {
300
322
  contentModelId: string;
@@ -308,6 +330,27 @@ interface UpdateEntryInput {
308
330
  status?: "draft" | "published";
309
331
  data?: Record<string, unknown>;
310
332
  pageId?: string | null;
333
+ /** The entry's native SEO. Merges into what is stored: an omitted key is kept, null or "" clears it. */
334
+ meta?: {
335
+ metaTitle?: string | null;
336
+ metaDescription?: string | null;
337
+ noindex?: boolean;
338
+ canonical?: string | null;
339
+ og?: {
340
+ title?: string | null;
341
+ description?: string | null;
342
+ image?: string | null;
343
+ type?: string | null;
344
+ } | null;
345
+ twitter?: {
346
+ card?: string | null;
347
+ title?: string | null;
348
+ description?: string | null;
349
+ image?: string | null;
350
+ } | null;
351
+ schemaType?: string | null;
352
+ schema?: Record<string, unknown> | Array<Record<string, unknown>> | null;
353
+ };
311
354
  }
312
355
  /** Set a page's field VALUES (the actual content). For a singleton, upserts its one entry. */
313
356
  interface SetPageContentInput {
@@ -385,6 +428,12 @@ interface UploadAssetInput {
385
428
  filename?: string;
386
429
  altText?: string;
387
430
  caption?: string;
431
+ /**
432
+ * Video/audio only: the spoken words (≤ 100,000 characters). Stored on the asset and published
433
+ * wherever the file is used. Sent as a second JSON call after the upload, because it is too
434
+ * long for the upload's query string.
435
+ */
436
+ transcript?: string;
388
437
  /** Target Media Library folder id (defaults to project root). */
389
438
  folderId?: string;
390
439
  }
@@ -393,6 +442,27 @@ interface UploadedAsset {
393
442
  url: string;
394
443
  key: string;
395
444
  filename: string;
445
+ /** Present when a transcript was written with the upload. */
446
+ transcript?: string;
447
+ }
448
+ /** Describe an existing asset. `null` clears a field; an omitted key is left alone. */
449
+ interface UpdateAssetInput {
450
+ altText?: string | null;
451
+ caption?: string | null;
452
+ /** Video/audio only, ≤ 100,000 characters. */
453
+ transcript?: string | null;
454
+ }
455
+ interface ManagedMediaAsset {
456
+ id: string;
457
+ url: string;
458
+ filename: string;
459
+ mimeType: string;
460
+ sizeBytes: number;
461
+ altText: string | null;
462
+ caption: string | null;
463
+ transcript: string | null;
464
+ folderId: string | null;
465
+ createdAt: string;
396
466
  }
397
467
 
398
468
  /** Semantic error codes used by the SDK. */
@@ -840,6 +910,8 @@ declare class BetterCMSManagementClient extends BetterCMSDeliveryClient {
840
910
  /** Get one content entry by id INCLUDING its data (incl. drafts). */
841
911
  getEntry(id: string): Promise<ManagedContentEntry>;
842
912
  uploadAsset(input: UploadAssetInput): Promise<UploadedAsset>;
913
+ /** Set an asset's alt text, caption or transcript (video/audio only). `null` clears. */
914
+ updateAsset(id: string, input: UpdateAssetInput): Promise<ManagedMediaAsset>;
843
915
  /** List forms in the key's project (or workspace-level). */
844
916
  listForms(): Promise<ManagedForm[]>;
845
917
  /** Get one form by id INCLUDING its field schema + settings. */
@@ -1213,6 +1285,10 @@ interface SeoInput {
1213
1285
  metaTitle?: string | null;
1214
1286
  metaDescription?: string | null;
1215
1287
  metaJson?: PageMetaJson | null;
1288
+ /** `"home"` makes the Automatic JSON-LD a WebSite, as the hosted renderer does. */
1289
+ slug?: string | null;
1290
+ /** Exclude from search engines. Surfaces as `ResolvedSeo.noindex` / `robots`. */
1291
+ noindex?: boolean | null;
1216
1292
  }
1217
1293
  /** Fully-resolved SEO values, page-over-site. Empty string ⇒ omit that tag. */
1218
1294
  interface ResolvedSeo {
@@ -1238,9 +1314,33 @@ interface ResolvedSeo {
1238
1314
  image: string;
1239
1315
  site: string;
1240
1316
  };
1241
- /** JSON-LD nodes (site schema first, then the page's), already flattened + de-empted. */
1317
+ /**
1318
+ * JSON-LD nodes (site schema first, then the page's), already flattened + de-empted. The page's
1319
+ * part follows the renderer's precedence: Custom (`metaJson.schema`) > `metaJson.schemaType` >
1320
+ * Automatic (WebPage; WebSite on the home page).
1321
+ */
1242
1322
  jsonLd: Array<Record<string, unknown>>;
1323
+ /** True when the page is excluded from search engines (the renderer's `<meta name="robots" content="noindex">`). */
1324
+ noindex: boolean;
1325
+ /** `noindex` in the `{ index, follow }` shape Next's `Metadata.robots` takes. */
1326
+ robots: {
1327
+ index: boolean;
1328
+ follow: boolean;
1329
+ };
1243
1330
  }
1331
+ /**
1332
+ * A Delivery API entry as a `resolveSeo` input. The server already resolved the collection
1333
+ * template's `{{field}}` tokens for this entry and merged the entry's own SEO over it, so this is
1334
+ * a reshape, not a resolver:
1335
+ *
1336
+ * const entry = await bcms.getEntry("astro");
1337
+ * const seo = resolveSeo(entrySeoInput(entry), siteDefaults, { siteUrl, path: `/tags/${entry.slug}` });
1338
+ * // seo.jsonLd holds the template's schema, resolved for this entry
1339
+ */
1340
+ declare function entrySeoInput(entry: {
1341
+ slug: string;
1342
+ seo?: DeliveryEntrySeo | null;
1343
+ }): SeoInput;
1244
1344
  /** Where this page lives, so a canonical can be derived when the page sets none. */
1245
1345
  interface SeoLocation {
1246
1346
  /** Absolute site origin, e.g. `https://acme.com`. Trailing slash optional. */
@@ -1480,4 +1580,4 @@ declare function inviteMember(client: BetterCMSAdminClient, workspaceId: string,
1480
1580
  declare function updateMemberRole(client: BetterCMSAdminClient, workspaceId: string, memberId: string, role: MemberRole): Promise<Member>;
1481
1581
  declare function removeMember(client: BetterCMSAdminClient, workspaceId: string, memberId: string): Promise<void>;
1482
1582
 
1483
- export { type AddPageFieldsInput, type ApiKeyUsage, type ApiKeyWithRaw, type AuthResult, BetterCMSError as BCMSClientError, ErrorCodes as BCMSErrorCodes, BetterCMS, BetterCMSAdminClient, type BetterCMSAdminOptions, BetterCMSDeliveryClient, BetterCMSError, BetterCMSManagementClient, type BetterCMSManagementOptions, type BetterCMSReadClient, type BetterCMSSiteOptions, type CommandManagedLayoutInput, type CreateApiKeyInput, type CreateClientOptions, type CreateEntryInput, type CreateFormInput, type CreateManagedPageInput, type CreateModelInput, type CreatePageInput, type CreateWorkspaceInput, type DeliveryForm, type DeliveryFormField, type DeliveryFormFieldType, ErrorCodes, type ExtractionCandidate, type FormFieldInput, type FormListOptions, type FormSubmitError, type FormValue, type FormValues, type GetEntryOptions, type GetManagedLayoutOptions, type ListContentAllOptions, type ListContentOptions, type ListEntriesFilter, type ListEntriesOptions, type ListPagesOptions, type ManagedComponent, type ManagedComponentInput, type ManagedComponentSummary, type ManagedContentEntry, type ManagedContentModel, type ManagedForm, type ManagedFormInput, type ManagedLayoutClient, type ManagedLayoutDocument, type ManagedPage, type ManagementClient, type MediaListOptions, type MediaMetadata, type Member, type MemberRole, PORTABLE_TEXT_FORMAT, type PageListOptions, type PendingInvite, type PublishManagedLayoutInput, type ResolvedSeo, type RichTextValue, type SearchHit, type SearchOptions, type SeoInput, type SeoLocation, type SeoMeta, type SeoMetaInput, type SetPageContentInput, type StegaPayload, type SubmissionListOptions, type SubmitFormOptions, type SubmitFormResult, type TextOrRich, type UpdateApiKeyInput, type UpdateEntryInput, type UpdateFormInput, type UpdateModelInput, type UpdatePageInput, type UpdateWorkspaceInput, type UploadAssetInput, type UploadedAsset, type WriteContentInput, addModelFields, addPageFields, asStringArray, commandManagedLayout, createApiKey, createClient, createEntry, createForm, createManagedPage, createModel, createPage, createWorkspace, decodeStega, deleteForm, deleteMedia, deletePage, deleteSubmission, deleteWorkspace, encodeStega, formInitialValues, getApiKeyUsage, getEntry, getForm, getManagedLayout, getManagedPage, getMedia, getMember, getModel, getPage, getSubmission, getWorkspace, inviteMember, isMultiValueField, isRichText, listApiKeys, listEntries, listForms, listManagedPages, listMedia, listMembers, listModels, listPages, listSubmissions, listWorkspaces, plain, portableText, publishManagedLayout, publishPage, regenerateApiKey, removeMember, resolveSeo, revokeApiKey, rich, search, setPageContent, shouldShowField, signIn, signInWithGithub, signInWithGoogle, signUp, stripStega, submitForm, toggleOption, updateApiKey, updateEntry, updateForm, updateMemberRole, updateModel, updatePage, updateWorkspace, uploadMedia };
1583
+ export { type AddPageFieldsInput, type ApiKeyUsage, type ApiKeyWithRaw, type AuthResult, BetterCMSError as BCMSClientError, ErrorCodes as BCMSErrorCodes, BetterCMS, BetterCMSAdminClient, type BetterCMSAdminOptions, BetterCMSDeliveryClient, BetterCMSError, BetterCMSManagementClient, type BetterCMSManagementOptions, type BetterCMSReadClient, type BetterCMSSiteOptions, type CommandManagedLayoutInput, type CreateApiKeyInput, type CreateClientOptions, type CreateEntryInput, type CreateFormInput, type CreateManagedPageInput, type CreateModelInput, type CreatePageInput, type CreateWorkspaceInput, type DeliveryForm, type DeliveryFormField, type DeliveryFormFieldType, ErrorCodes, type ExtractionCandidate, type FormFieldInput, type FormListOptions, type FormSubmitError, type FormValue, type FormValues, type GetEntryOptions, type GetManagedLayoutOptions, type ListContentAllOptions, type ListContentOptions, type ListEntriesFilter, type ListEntriesOptions, type ListPagesOptions, type ManagedComponent, type ManagedComponentInput, type ManagedComponentSummary, type ManagedContentEntry, type ManagedContentModel, type ManagedForm, type ManagedFormInput, type ManagedLayoutClient, type ManagedLayoutDocument, type ManagedMediaAsset, type ManagedPage, type ManagementClient, type MediaListOptions, type MediaMetadata, type Member, type MemberRole, PORTABLE_TEXT_FORMAT, type PageListOptions, type PendingInvite, type PublishManagedLayoutInput, type ResolvedSeo, type RichTextValue, type SearchHit, type SearchOptions, type SeoInput, type SeoLocation, type SeoMeta, type SeoMetaInput, type SetPageContentInput, type StegaPayload, type SubmissionListOptions, type SubmitFormOptions, type SubmitFormResult, type TextOrRich, type UpdateApiKeyInput, type UpdateAssetInput, type UpdateEntryInput, type UpdateFormInput, type UpdateModelInput, type UpdatePageInput, type UpdateWorkspaceInput, type UploadAssetInput, type UploadedAsset, type WriteContentInput, addModelFields, addPageFields, asStringArray, commandManagedLayout, createApiKey, createClient, createEntry, createForm, createManagedPage, createModel, createPage, createWorkspace, decodeStega, deleteForm, deleteMedia, deletePage, deleteSubmission, deleteWorkspace, encodeStega, entrySeoInput, formInitialValues, getApiKeyUsage, getEntry, getForm, getManagedLayout, getManagedPage, getMedia, getMember, getModel, getPage, getSubmission, getWorkspace, inviteMember, isMultiValueField, isRichText, listApiKeys, listEntries, listForms, listManagedPages, listMedia, listMembers, listModels, listPages, listSubmissions, listWorkspaces, plain, portableText, publishManagedLayout, publishPage, regenerateApiKey, removeMember, resolveSeo, revokeApiKey, rich, search, setPageContent, shouldShowField, signIn, signInWithGithub, signInWithGoogle, signUp, stripStega, submitForm, toggleOption, updateApiKey, updateEntry, updateForm, updateMemberRole, updateModel, updatePage, updateWorkspace, uploadMedia };
package/dist/index.js CHANGED
@@ -558,6 +558,13 @@ async function deleteModel(client, id) {
558
558
  }
559
559
 
560
560
  // src/methods/management/media.ts
561
+ async function updateAsset(client, id, input) {
562
+ const { data } = await client.fetchJSON(
563
+ client.url(`/management/media/${encodeURIComponent(id)}`),
564
+ { method: "PATCH", body: JSON.stringify(input) }
565
+ );
566
+ return data;
567
+ }
561
568
  var MIME_BY_EXT = {
562
569
  png: "image/png",
563
570
  jpg: "image/jpeg",
@@ -685,6 +692,10 @@ async function uploadAsset(client, input) {
685
692
  body: bytes
686
693
  }
687
694
  );
695
+ if (input.transcript && input.transcript.trim()) {
696
+ await updateAsset(client, data.id, { transcript: input.transcript });
697
+ return { ...data, transcript: input.transcript };
698
+ }
688
699
  return data;
689
700
  }
690
701
 
@@ -946,6 +957,10 @@ var BetterCMSManagementClient = class extends BetterCMSDeliveryClient {
946
957
  uploadAsset(input) {
947
958
  return uploadAsset(this, input);
948
959
  }
960
+ /** Set an asset's alt text, caption or transcript (video/audio only). `null` clears. */
961
+ updateAsset(id, input) {
962
+ return updateAsset(this, id, input);
963
+ }
949
964
  // ── Forms (read-only): discover dashboard-built forms to embed into site code ──
950
965
  /** List forms in the key's project (or workspace-level). */
951
966
  listForms() {
@@ -1414,6 +1429,68 @@ function jsonLdNodes(schema) {
1414
1429
  }
1415
1430
  return out;
1416
1431
  }
1432
+ var SCHEMA_TYPE_CHOICES = [
1433
+ "WebPage",
1434
+ "AboutPage",
1435
+ "ContactPage",
1436
+ "CollectionPage",
1437
+ "Blog",
1438
+ "BlogPosting",
1439
+ "Article",
1440
+ "Product",
1441
+ "FAQPage",
1442
+ "Event",
1443
+ "Organization",
1444
+ "LocalBusiness"
1445
+ ];
1446
+ function compact(node) {
1447
+ return Object.fromEntries(Object.entries(node).filter(([, value]) => value != null && value !== ""));
1448
+ }
1449
+ function schemaNode(type, { name, description, image, url }) {
1450
+ switch (type) {
1451
+ case "BlogPosting":
1452
+ case "Article":
1453
+ return compact({ "@type": type, headline: name, description, image, url, mainEntityOfPage: url });
1454
+ case "Product":
1455
+ case "Event":
1456
+ return compact({ "@type": type, name, description, image, url });
1457
+ case "FAQPage":
1458
+ case "WebSite":
1459
+ return compact({ "@type": type, name, description, url });
1460
+ case "Organization":
1461
+ return compact({ "@type": type, name, description, url, logo: image });
1462
+ default:
1463
+ return compact({ "@type": type, name, description, url, image });
1464
+ }
1465
+ }
1466
+ function pageJsonLd(page, meta, canonical, siteSchema) {
1467
+ const custom = jsonLdNodes(meta.schema);
1468
+ if (custom.length > 0) return custom;
1469
+ const props = {
1470
+ name: (page.metaTitle || page.title || "").trim(),
1471
+ description: (page.metaDescription || "").trim(),
1472
+ image: (meta.og?.image || "").trim(),
1473
+ url: canonical.trim()
1474
+ };
1475
+ const schemaType = meta.schemaType;
1476
+ if (typeof schemaType === "string" && SCHEMA_TYPE_CHOICES.includes(schemaType)) {
1477
+ return [schemaNode(schemaType, props)];
1478
+ }
1479
+ if (page.slug === "home") {
1480
+ return jsonLdNodes(siteSchema).length > 0 ? [] : [schemaNode("WebSite", props)];
1481
+ }
1482
+ return [schemaNode("WebPage", props)];
1483
+ }
1484
+ function entrySeoInput(entry) {
1485
+ const { metaTitle, metaDescription, noindex, ...metaJson } = entry.seo ?? {};
1486
+ return {
1487
+ title: metaTitle || entry.slug,
1488
+ metaTitle: metaTitle ?? null,
1489
+ metaDescription: metaDescription ?? null,
1490
+ metaJson,
1491
+ noindex: noindex === true
1492
+ };
1493
+ }
1417
1494
  function resolveSeo(page, defaults = {}, location = {}) {
1418
1495
  const meta = page.metaJson ?? {};
1419
1496
  const title = page.metaTitle || page.title || "";
@@ -1441,7 +1518,9 @@ function resolveSeo(page, defaults = {}, location = {}) {
1441
1518
  image: twImage,
1442
1519
  site: defaults.twitterHandle || ""
1443
1520
  },
1444
- jsonLd: [...jsonLdNodes(defaults.siteSchema), ...jsonLdNodes(meta.schema)]
1521
+ jsonLd: [...jsonLdNodes(defaults.siteSchema), ...pageJsonLd(page, meta, canonical, defaults.siteSchema)],
1522
+ noindex: page.noindex === true,
1523
+ robots: { index: page.noindex !== true, follow: true }
1445
1524
  };
1446
1525
  }
1447
1526
 
@@ -1784,6 +1863,7 @@ export {
1784
1863
  deleteSubmission,
1785
1864
  deleteWorkspace,
1786
1865
  encodeStega,
1866
+ entrySeoInput,
1787
1867
  formInitialValues,
1788
1868
  getApiKeyUsage,
1789
1869
  getBlockType,