@bettercms-ai/sdk 1.6.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 +126 -0
- package/dist/index.cjs +1616 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1072 -0
- package/dist/index.d.ts +1072 -0
- package/dist/index.js +1507 -0
- package/dist/index.js.map +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/methods/getContent.ts","../src/methods/listContent.ts","../src/methods/listContentAll.ts","../src/delivery-client.ts","../src/methods/webhooks.ts","../src/admin-client.ts","../src/methods/management/content.ts","../src/methods/management/media.ts","../src/methods/management/forms.ts","../src/methods/management/components.ts","../src/management-client.ts","../src/auth.ts","../src/client.ts","../src/read-client.ts","../src/stega.ts","../src/seo.ts","../src/search.ts","../src/methods/admin/pages.ts","../src/methods/admin/media.ts","../src/methods/admin/forms.ts","../src/methods/admin/submissions.ts","../src/methods/admin/workspaces.ts","../src/methods/admin/api-keys.ts","../src/methods/admin/members.ts","../src/forms.ts"],"sourcesContent":["export { BetterCMS } from \"./client.js\";\nexport { BetterCMSError, ErrorCodes } from \"./errors.js\";\nexport { BetterCMSError as BCMSClientError, ErrorCodes as BCMSErrorCodes } from \"./errors.js\";\nexport { BetterCMSAdminClient } from \"./admin-client.js\";\nexport { BetterCMSManagementClient } from \"./management-client.js\";\nexport { BetterCMSDeliveryClient } from \"./delivery-client.js\";\n\n// Framework-agnostic typed read core (used by @bettercms-ai/astro + @bettercms-ai/next)\nexport { createClient } from \"./read-client.js\";\nexport type {\n BetterCMSReadClient,\n CreateClientOptions,\n GetEntryOptions,\n ListEntriesOptions,\n ListPagesOptions,\n} from \"./read-client.js\";\n\n// Visual editing — stega provenance codec (pairs with <VisualEditing> overlays)\nexport { encodeStega, decodeStega, stripStega } from \"./stega.js\";\nexport type { StegaPayload } from \"./stega.js\";\n\n// SEO — framework-agnostic page-over-site meta resolver (FLO-302). Next maps the\n// result to `Metadata` via `buildMetadata`; Astro reads the fields into <head>.\nexport { resolveSeo } from \"./seo.js\";\nexport type { SeoInput, ResolvedSeo } from \"./seo.js\";\n\n// Site Search — public visitor search (FLO-Site-Search)\nexport { search } from \"./search.js\";\nexport type { SearchHit, SearchOptions } from \"./search.js\";\n\n// Image URL builder — re-exported for one-stop SDK imports\nexport { default as imageUrlBuilder, imageUrl } from \"@bettercms-ai/image-url\";\nexport type {\n ImageUrlBuilder,\n ImageSource,\n ImageFormat,\n ImageFit,\n ImageUrlOptions,\n} from \"@bettercms-ai/image-url\";\nexport { signIn, signUp, signInWithGoogle, signInWithGithub } from \"./auth.js\";\nexport type { BetterCMSSiteOptions } from \"./client.js\";\nexport type { BetterCMSAdminOptions } from \"./admin-client.js\";\nexport type { BetterCMSManagementOptions } from \"./management-client.js\";\n\n// Management API methods\nexport {\n listModels,\n getModel,\n createModel,\n updateModel,\n createEntry,\n updateEntry,\n listManagedPages,\n createManagedPage,\n addPageFields,\n getManagedPage,\n setPageContent,\n addModelFields,\n listEntries,\n getEntry,\n} from \"./methods/management/content.js\";\nexport type {\n ManagementClient,\n ManagedContentModel,\n ManagedContentEntry,\n ManagedPage,\n CreateModelInput,\n UpdateModelInput,\n CreateEntryInput,\n UpdateEntryInput,\n CreateManagedPageInput,\n AddPageFieldsInput,\n SetPageContentInput,\n ListEntriesFilter,\n} from \"./methods/management/content.js\";\nexport type { UploadAssetInput, UploadedAsset } from \"./methods/management/media.js\";\n// Read-only management form discovery (the standalone fns are wrapped by the\n// management client as `listForms`/`getForm` methods — only the type is public to\n// avoid colliding with the admin-forms `listForms`/`getForm` exports below).\nexport type { ManagedForm, ManagedFormInput } from \"./methods/management/forms.js\";\nexport type {\n ManagedComponent,\n ManagedComponentInput,\n} from \"./methods/management/components.js\";\nexport type { ListContentOptions } from \"./methods/listContent.js\";\nexport type { ListContentAllOptions } from \"./methods/listContentAll.js\";\nexport type { SignUpInput, SignInInput } from \"@bettercms-ai/types\";\nexport type { AuthResult } from \"./auth.js\";\n\n// Admin methods\nexport type { PageListOptions, CreatePageInput, UpdatePageInput } from \"./methods/admin/pages.js\";\nexport { listPages, getPage, createPage, updatePage, deletePage, publishPage } from \"./methods/admin/pages.js\";\n\nexport type { MediaListOptions, MediaMetadata } from \"./methods/admin/media.js\";\nexport { listMedia, getMedia, uploadMedia, deleteMedia } from \"./methods/admin/media.js\";\n\nexport type { FormListOptions, CreateFormInput, FormFieldInput, UpdateFormInput } from \"./methods/admin/forms.js\";\nexport { listForms, getForm, createForm, updateForm, deleteForm } from \"./methods/admin/forms.js\";\n\nexport type { SubmissionListOptions } from \"./methods/admin/submissions.js\";\nexport { listSubmissions, getSubmission, deleteSubmission } from \"./methods/admin/submissions.js\";\n\nexport type { CreateWorkspaceInput, UpdateWorkspaceInput } from \"./methods/admin/workspaces.js\";\nexport { listWorkspaces, getWorkspace, createWorkspace, updateWorkspace, deleteWorkspace } from \"./methods/admin/workspaces.js\";\n\nexport type { CreateApiKeyInput, UpdateApiKeyInput, ApiKeyWithRaw, ApiKeyUsage } from \"./methods/admin/api-keys.js\";\nexport { listApiKeys, createApiKey, updateApiKey, regenerateApiKey, getApiKeyUsage, revokeApiKey } from \"./methods/admin/api-keys.js\";\n\nexport type { MemberRole, Member, PendingInvite } from \"./methods/admin/members.js\";\nexport { listMembers, getMember, inviteMember, updateMemberRole, removeMember } from \"./methods/admin/members.js\";\n\n// Public forms — headless rendering + submission for published/imported sites.\nexport { submitForm, shouldShowField, formInitialValues } from \"./forms.js\";\nexport type {\n DeliveryForm,\n DeliveryFormField,\n DeliveryFormFieldType,\n FormValue,\n FormValues,\n SubmitFormOptions,\n SubmitFormResult,\n FormSubmitError,\n} from \"./forms.js\";\n\n// Re-export all public types\nexport type {\n Workspace,\n Page,\n Perspective,\n DeliveryEntry,\n DeliveryPage,\n DeliveryList,\n PageMetaJson,\n SiteSeoDefaults,\n ContentBlock,\n HeadingBlock,\n HeadingProps,\n TextBlock,\n TextProps,\n ImageBlock,\n ImageProps,\n ButtonBlock,\n ButtonProps,\n SpacerBlock,\n SpacerProps,\n ColumnsBlock,\n ColumnsProps,\n VideoBlock,\n VideoProps,\n FormBlock,\n FormProps,\n BlockType,\n ContentEntry,\n ContentModel,\n ContentModelField,\n MediaAsset,\n Form,\n FormField,\n FormSubmission,\n Redirect,\n ApiKey,\n ApiKeyPermission,\n ApiKeyTokenType,\n AuthUser,\n AuthSession,\n BetterCMSErrorCode,\n ApiError,\n PaginatedResult,\n Content,\n ContentResponse,\n ContentPageResult,\n DeepReadonly,\n AssertEqual,\n} from \"@bettercms-ai/types\";\n\nexport { isBlock, getBlockType } from \"@bettercms-ai/types\";\n","import type { BetterCMSErrorCode } from \"@bettercms-ai/types\";\n\n/** Semantic error codes used by the SDK. */\nexport const ErrorCodes = {\n CONTENT_NOT_FOUND: \"CONTENT_NOT_FOUND\",\n UNAUTHORIZED: \"UNAUTHORIZED\",\n FORBIDDEN: \"FORBIDDEN\",\n RATE_LIMITED: \"RATE_LIMITED\",\n INTERNAL_ERROR: \"INTERNAL_ERROR\",\n VALIDATION_ERROR: \"VALIDATION_ERROR\",\n NETWORK_ERROR: \"NETWORK_ERROR\",\n ADMIN_NOT_IMPLEMENTED: \"ADMIN_NOT_IMPLEMENTED\",\n} as const;\n\nexport type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];\n\n/** Maps HTTP status codes to semantic error codes. */\nfunction statusToCode(status: number): BetterCMSErrorCode {\n if (status === 404) return ErrorCodes.CONTENT_NOT_FOUND;\n if (status === 401) return ErrorCodes.UNAUTHORIZED;\n if (status === 403) return ErrorCodes.FORBIDDEN;\n if (status === 429) return ErrorCodes.RATE_LIMITED;\n if (status >= 500) return ErrorCodes.INTERNAL_ERROR;\n if (status === 422) return ErrorCodes.VALIDATION_ERROR;\n return ErrorCodes.INTERNAL_ERROR;\n}\n\n/**\n * BetterCMSError — normalized SDK error with a semantic code.\n */\nexport class BetterCMSError extends Error {\n readonly status: number;\n readonly code: BetterCMSErrorCode;\n /**\n * Raw machine-readable `code` from the response body (e.g. \"PROJECT_DELETED\"),\n * when the API supplies one. Distinct from `code` (which is derived from the\n * HTTP status), this lets callers branch on a specific server condition that\n * shares a status with others (e.g. 409 slug-conflict vs 409 project-deleted).\n */\n readonly bodyCode?: string;\n\n constructor(message: string, status: number, code: BetterCMSErrorCode, bodyCode?: string) {\n super(message);\n this.name = \"BetterCMSError\";\n this.status = status;\n this.code = code;\n this.bodyCode = bodyCode;\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, BetterCMSError);\n }\n }\n\n toJSON() {\n return {\n name: this.name,\n message: this.message,\n status: this.status,\n code: this.code,\n bodyCode: this.bodyCode,\n };\n }\n\n /**\n * Factory — creates a BetterCMSError from a failed fetch Response. Reads the\n * body's `message` (or `error`) for the human message and `code` for a\n * machine-readable condition the SDK surfaces as `bodyCode`.\n */\n static async from(res: Response): Promise<BetterCMSError> {\n let message = res.statusText || \"An error occurred\";\n let bodyCode: string | undefined;\n try {\n const body = (await res.json()) as { message?: string; error?: string; code?: string };\n if (body?.message) message = body.message;\n else if (body?.error) message = body.error;\n if (body?.code) bodyCode = body.code;\n } catch {\n // ignore parse errors\n }\n return new BetterCMSError(message, res.status, statusToCode(res.status), bodyCode);\n }\n}\n","import type { ContentResponse } from \"@bettercms-ai/types\";\nimport type { BetterCMSDeliveryClient } from \"../client.js\";\n\n/**\n * Fetches a single published page by slug from the Delivery API.\n */\nexport async function getContent(\n client: BetterCMSDeliveryClient,\n slug: string\n): Promise<ContentResponse[\"data\"]> {\n const data = await client.fetchJSON<ContentResponse>(client.url(slug));\n return data.data;\n}\n","import type { ContentPageResult } from \"@bettercms-ai/types\";\nimport type { BetterCMSDeliveryClient } from \"../client.js\";\n\n/**\n * Options for {@link BetterCMSDeliveryClient.listContent}.\n */\nexport interface ListContentOptions {\n /** Page number (1-based). Defaults to 1. */\n page?: number;\n /** Items per page. Defaults to 20. */\n perPage?: number;\n}\n\n/**\n * Fetches a paginated list of published content pages.\n */\nexport async function listContent(\n client: BetterCMSDeliveryClient,\n opts?: ListContentOptions\n): Promise<ContentPageResult[\"data\"]> {\n const params = new URLSearchParams({\n page: String(opts?.page ?? 1),\n perPage: String(opts?.perPage ?? 20),\n });\n\n const data = await client.fetchJSON<ContentPageResult>(\n `${client.url(\"\")}?${params}`\n );\n return data.data;\n}\n","import type { Content, ContentPageResult } from \"@bettercms-ai/types\";\nimport type { BetterCMSDeliveryClient } from \"../client.js\";\nimport type { ListContentOptions } from \"./listContent.js\";\n\n/**\n * Options for {@link BetterCMSDeliveryClient.listContentAll}.\n */\nexport interface ListContentAllOptions extends ListContentOptions {}\n\n/**\n * An async iterator that transparently auto-paginates through all content.\n *\n * Usage:\n * ```ts\n * for await (const item of client.listContentAll()) { ... }\n * ```\n *\n * Or with the `all()` convenience:\n * ```ts\n * const items = await client.listContentAll().all({ limit: 500 });\n * ```\n */\nexport function listContentAll(\n client: BetterCMSDeliveryClient,\n opts?: ListContentAllOptions\n) {\n const perPage = opts?.perPage ?? 100;\n\n return {\n /**\n * Async iterator — yields Content items page by page.\n */\n async *[Symbol.asyncIterator](): AsyncIterableIterator<Content> {\n let page = opts?.page ?? 1;\n\n while (true) {\n if (page > 100) {\n throw new Error(\n \"listContentAll: exceeded 100 pages — possible infinite loop\"\n );\n }\n\n const params = new URLSearchParams({\n page: String(page),\n perPage: String(perPage),\n });\n const result = await client.fetchJSON<ContentPageResult>(\n `${client.url(\"\")}?${params}`\n );\n const pageData = result.data;\n\n if (!pageData?.items?.length) break;\n\n for (const item of pageData.items) {\n yield item;\n }\n\n if (!pageData?.hasNextPage) break;\n page++;\n }\n },\n\n /**\n * Convenience: collect all items into an array, optionally limited.\n */\n async all(options?: { limit?: number }): Promise<Content[]> {\n const items: Content[] = [];\n for await (const item of this) {\n items.push(item);\n if (options?.limit && items.length >= options.limit) break;\n }\n return items;\n },\n };\n}","/**\n * BetterCMSDeliveryClient — base client for the Delivery API.\n * Used by BetterCMS.site() and as the base class for BetterCMSAdminClient.\n *\n * @see client.ts for the BetterCMS factory\n */\n\nimport { BetterCMSError } from \"./errors.js\";\nimport { getContent } from \"./methods/getContent.js\";\nimport { listContent } from \"./methods/listContent.js\";\nimport { listContentAll } from \"./methods/listContentAll.js\";\n\nexport class BetterCMSDeliveryClient {\n readonly workspace: string;\n readonly baseUrl: string;\n private readonly apiKey?: string;\n\n constructor(opts: { workspace: string; apiKey?: string; baseUrl: string }) {\n this.workspace = opts.workspace;\n this.baseUrl = opts.baseUrl;\n this.apiKey = opts.apiKey;\n }\n\n getContent(slug: string) {\n return getContent(this, slug);\n }\n\n listContent(opts?: Parameters<typeof listContent>[1]) {\n return listContent(this, opts);\n }\n\n listContentAll(opts?: Parameters<typeof listContentAll>[1]) {\n return listContentAll(this, opts);\n }\n\n /** Build the full URL for a content path. */\n url(path: string): string {\n return `${this.baseUrl}/${this.workspace}/content/${path}`;\n }\n\n /** Build request headers, including auth if provided. */\n headers(): Record<string, string> {\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (this.apiKey) {\n headers[\"Authorization\"] = `Bearer ${this.apiKey}`;\n }\n return headers;\n }\n\n /**\n * Generic fetch helper — wraps a request with network-error handling\n * and throws a typed BetterCMSError on non-OK responses.\n */\n async fetchJSON<T>(url: string): Promise<T> {\n let res: Response;\n try {\n res = await globalThis.fetch(url, { headers: this.headers() });\n } catch (err) {\n throw new BetterCMSError(\n `Network error: ${err instanceof Error ? err.message : String(err)}`,\n 0,\n \"NETWORK_ERROR\",\n );\n }\n\n if (!res.ok) {\n throw await BetterCMSError.from(res);\n }\n\n return (await res.json()) as T;\n }\n}\n","/**\n * SDK webhook methods — create, list, delete, test webhooks.\n */\n\n/**\n * Webhook event types supported by BetterCMS.\n */\nexport type WebhookEvent =\n | \"content.publish\"\n | \"content.unpublish\"\n | \"content.created\"\n | \"content.updated\"\n | \"content.deleted\"\n | \"page.published\"\n | \"page.unpublished\"\n | \"page.created\"\n | \"page.updated\"\n | \"page.deleted\"\n | \"form.submitted\"\n | \"api_key.created\"\n | \"api_key.deleted\";\n\n/**\n * Webhook record returned from the API (without secret).\n */\nexport interface Webhook {\n id: string;\n projectId: string;\n workspaceId: string;\n name: string;\n url: string;\n events: WebhookEvent[];\n isActive: boolean;\n createdAt: string;\n updatedAt: string;\n}\n\n/**\n * Webhook with secret — returned only on create.\n */\nexport interface WebhookWithSecret extends Webhook {\n secret: string;\n}\n\n/**\n * Input for creating a webhook.\n */\nexport interface CreateWebhookInput {\n name: string;\n url: string;\n events?: WebhookEvent[];\n}\n\n/**\n * Input for updating a webhook.\n */\nexport interface UpdateWebhookInput {\n name?: string;\n url?: string;\n events?: WebhookEvent[];\n isActive?: boolean;\n}\n\n/**\n * Paginated list response.\n */\nexport interface WebhookListResponse {\n data: Webhook[];\n pagination: {\n page: number;\n limit: number;\n total: number;\n totalPages: number;\n };\n}\n\nexport interface WebhookClient {\n fetchJSON: <T>(url: string, init?: RequestInit) => Promise<T>;\n url: (path: string) => string;\n}\n\n/**\n * Add webhook methods to BetterCMSAdminClient.\n */\nexport function addWebhookMethods(client: WebhookClient) {\n return {\n /**\n * List webhooks for a project.\n */\n list: async (options?: { page?: number; limit?: number }): Promise<WebhookListResponse> => {\n const params = new URLSearchParams();\n if (options?.page) params.set(\"page\", String(options.page));\n if (options?.limit) params.set(\"limit\", String(options.limit));\n\n return client.fetchJSON<WebhookListResponse>(\n client.url(`/webhooks?${params}`),\n { method: \"GET\" },\n );\n },\n\n /**\n * Create a new webhook. Returns the webhook with secret (shown once).\n */\n create: async (input: CreateWebhookInput): Promise<WebhookWithSecret> => {\n return client.fetchJSON<WebhookWithSecret>(\n client.url(\"/webhooks\"),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(input),\n },\n );\n },\n\n /**\n * Get a single webhook.\n */\n get: async (webhookId: string): Promise<{ data: Webhook }> => {\n return client.fetchJSON<{ data: Webhook }>(\n client.url(`/webhooks/${webhookId}`),\n { method: \"GET\" },\n );\n },\n\n /**\n * Update a webhook.\n */\n update: async (\n webhookId: string,\n input: UpdateWebhookInput,\n ): Promise<{ data: Webhook }> => {\n return client.fetchJSON<{ data: Webhook }>(\n client.url(`/webhooks/${webhookId}`),\n {\n method: \"PATCH\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(input),\n },\n );\n },\n\n /**\n * Delete a webhook.\n */\n delete: async (webhookId: string): Promise<{ data: { id: string } }> => {\n return client.fetchJSON<{ data: { id: string } }>(\n client.url(`/webhooks/${webhookId}`),\n { method: \"DELETE\" },\n );\n },\n\n /**\n * Test a webhook delivery.\n */\n test: async (\n webhookId: string,\n event?: WebhookEvent,\n ): Promise<{ data: { delivered: boolean; status?: number } }> => {\n return client.fetchJSON<{ data: { delivered: boolean; status?: number } }>(\n client.url(`/webhooks/${webhookId}/test`),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ event: event ?? \"content.publish\" }),\n },\n );\n },\n };\n}","/**\n * BetterCMSAdminClient — typed SDK client for admin CRUD operations.\n *\n * Extends BetterCMSDeliveryClient but overrides:\n * - `headers()` — uses Bearer token auth instead of API key\n * - `fetchJSON()` — adds retry on 429/503 and 10s timeout per request\n *\n * @see openspec/changes/flo-6-backend-sdk-admin/specs/sdk-admin-client/spec.md\n */\n\nimport { BetterCMSDeliveryClient } from \"./delivery-client.js\";\nimport { BetterCMSError } from \"./errors.js\";\nimport { addWebhookMethods, type Webhook, type WebhookEvent, type CreateWebhookInput, type UpdateWebhookInput, type WebhookWithSecret, type WebhookListResponse } from \"./methods/webhooks.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.bettercms.ai/v1\";\nconst DEFAULT_TIMEOUT = 10_000;\nconst RETRY_STATUSES = [429, 503] as const;\nconst RETRY_DELAYS = [1_000, 2_000, 4_000] as const;\n\nexport interface BetterCMSAdminOptions {\n /** Base URL of the Admin API. Defaults to https://api.bettercms.ai/v1 */\n baseUrl?: string;\n /** BetterAuth session Bearer token. */\n token: string;\n /** Request timeout per attempt in ms. Defaults to 10000. */\n timeout?: number;\n}\n\n/**\n * Admin SDK client. Extends BetterCMSDeliveryClient so it reuses\n * workspace, baseUrl, url() from the base. Overrides headers() and\n * fetchJSON() for Bearer auth + retry/timeout.\n */\nexport class BetterCMSAdminClient extends BetterCMSDeliveryClient {\n readonly timeout: number;\n private readonly _token: string;\n\n constructor(options: BetterCMSAdminOptions) {\n // The base class requires { workspace, apiKey?, baseUrl }. We pass a dummy\n // workspace since admin endpoints are workspace-scoped via URL params.\n super({\n workspace: \"\",\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n });\n this._token = options.token;\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n }\n\n headers(): Record<string, string> {\n return {\n ...super.headers(),\n Authorization: `Bearer ${this._token}`,\n \"Content-Type\": \"application/json\",\n };\n }\n\n /**\n * Admin fetchJSON with retry (429, 503) and per-request timeout (AbortController).\n * Each retry gets a fresh timeout.\n */\n async fetchJSON<T>(url: string, init?: RequestInit): Promise<T> {\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= 3; attempt++) {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n let nonRetryable = false;\n\n try {\n const res = await globalThis.fetch(url, {\n ...init,\n headers: { ...this.headers(), ...(init?.headers ?? {}) },\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (res.ok) {\n return res.json() as T;\n }\n\n const shouldRetry = attempt < 3 && (RETRY_STATUSES as readonly number[]).includes(res.status);\n if (!shouldRetry) {\n nonRetryable = true;\n throw await BetterCMSError.from(res);\n }\n await sleep(RETRY_DELAYS[attempt] ?? 0);\n } catch (err) {\n clearTimeout(timeoutId);\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new BetterCMSError(\"Request timeout\", 408, \"NETWORK_ERROR\");\n }\n // If we threw a BetterCMSError from the try block (non-retryable), rethrow immediately\n if (nonRetryable) {\n throw err;\n }\n lastError = err;\n if (attempt < 3) {\n await sleep(RETRY_DELAYS[attempt] ?? 0);\n continue;\n }\n throw err;\n }\n }\n\n throw lastError ?? new BetterCMSError(\"Unreachable\", 0, \"NETWORK_ERROR\");\n }\n\n /** Build the admin API URL. */\n url(path: string): string {\n return `${this.baseUrl}${path}`;\n }\n\n /** Webhook management methods. */\n webhooks() {\n return addWebhookMethods(this);\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","/**\n * Management API SDK methods — programmatic content-model + content-entry authoring.\n *\n * These call /api/v1/management/content/* (key-auth, content:manage scope). The MCP\n * server wraps these. Mostly additive (create + update); delete is supported via\n * soft-delete (reversible, audit-logged) so agents can clean up their own mistakes.\n */\n\nimport type { ContentModelField } from \"@bettercms-ai/types\";\n\n/** Minimal client surface these methods need (satisfied by BetterCMSManagementClient). */\nexport interface ManagementClient {\n fetchJSON: <T>(url: string, init?: RequestInit) => Promise<T>;\n url: (path: string) => string;\n}\n\n/** A content model row as returned by the Management API (the full DB record). */\nexport interface ManagedContentModel {\n id: string;\n workspaceId: string;\n projectId: string | null;\n name: string;\n slug: string;\n description: string | null;\n fields: ContentModelField[];\n createdAt: string;\n updatedAt: string;\n deletedAt: string | null;\n}\n\n/** A content entry row as returned by the Management API (the full DB record). */\nexport interface ManagedContentEntry {\n id: string;\n workspaceId: string;\n projectId: string | null;\n contentModelId: string;\n pageId: string | null;\n slug: string;\n status: \"draft\" | \"published\";\n data: Record<string, unknown>;\n publishedAt: string | null;\n optimisticVersion: number;\n createdAt: string;\n updatedAt: string;\n deletedAt: string | null;\n}\n\n/** A page row as returned by the Management API. A page carries its own typed\n * schema (`fields`) plus `pageType`, and is project-scoped from the key. */\nexport interface ManagedPage {\n id: string;\n workspaceId: string;\n projectId: string | null;\n title: string;\n slug: string;\n metaTitle: string | null;\n metaDescription: string | null;\n status: \"draft\" | \"published\";\n pageType: \"singleton\" | \"dynamic\" | null;\n fields: ContentModelField[];\n optimisticVersion: number;\n createdAt: string;\n updatedAt: string;\n deletedAt: string | null;\n}\n\nexport interface CreateManagedPageInput {\n title: string;\n slug: string;\n pageType?: \"singleton\" | \"dynamic\";\n fields?: ContentModelField[];\n metaTitle?: string;\n metaDescription?: string;\n status?: \"draft\" | \"published\";\n}\n\n/** Append fields to an existing page's schema (additive — see addPageFields). */\nexport interface AddPageFieldsInput {\n addFields: ContentModelField[];\n}\n\nexport interface CreateModelInput {\n name: string;\n slug: string;\n description?: string;\n fields?: ContentModelField[];\n projectId?: string;\n}\n\nexport interface UpdateModelInput {\n name?: string;\n slug?: string;\n description?: string;\n fields?: ContentModelField[];\n}\n\nexport interface CreateEntryInput {\n contentModelId: string;\n slug?: string;\n status?: \"draft\" | \"published\";\n data?: Record<string, unknown>;\n pageId?: string | null;\n}\n\nexport interface UpdateEntryInput {\n slug?: string;\n status?: \"draft\" | \"published\";\n data?: Record<string, unknown>;\n pageId?: string | null;\n}\n\n/** Set a page's field VALUES (the actual content). For a singleton, upserts its one entry. */\nexport interface SetPageContentInput {\n data: Record<string, unknown>;\n status?: \"draft\" | \"published\";\n}\n\n/** Filter for listing content entries. */\nexport interface ListEntriesFilter {\n modelId?: string;\n pageId?: string;\n status?: \"draft\" | \"published\";\n}\n\n/** List content models (schemas) in the key's workspace. Excludes soft-deleted. */\nexport async function listModels(client: ManagementClient): Promise<ManagedContentModel[]> {\n const res = await client.fetchJSON<{ data: ManagedContentModel[] }>(\n client.url(\"/management/content/models\"),\n { method: \"GET\" },\n );\n return res.data;\n}\n\n/** Get a single content model by id. Needed for additive read-modify-write (e.g. add_field). */\nexport async function getModel(client: ManagementClient, id: string): Promise<ManagedContentModel> {\n const res = await client.fetchJSON<{ data: ManagedContentModel }>(\n client.url(`/management/content/models/${id}`),\n { method: \"GET\" },\n );\n return res.data;\n}\n\n/** List pages in the key's project (or workspace-level if the key is not project-scoped). */\nexport async function listManagedPages(client: ManagementClient): Promise<ManagedPage[]> {\n const res = await client.fetchJSON<{ data: ManagedPage[] }>(\n client.url(\"/management/pages\"),\n { method: \"GET\" },\n );\n return res.data;\n}\n\n/** Create a page (the page-first schema: title/slug/pageType/fields). Project-scoped from the key.\n * Supports both `singleton` and `dynamic` pageType. */\nexport async function createManagedPage(client: ManagementClient, input: CreateManagedPageInput): Promise<ManagedPage> {\n const res = await client.fetchJSON<{ data: ManagedPage }>(\n client.url(\"/management/pages\"),\n { method: \"POST\", body: JSON.stringify(input) },\n );\n return res.data;\n}\n\n/**\n * Append fields to an existing page's schema (additive read-append). The API\n * rejects keys that already exist, so this never overwrites or retypes a field.\n * Project-scoped from the key. Returns the updated page.\n */\nexport async function addPageFields(\n client: ManagementClient,\n id: string,\n input: AddPageFieldsInput,\n): Promise<ManagedPage> {\n const res = await client.fetchJSON<{ data: ManagedPage }>(\n client.url(`/management/pages/${id}`),\n { method: \"PATCH\", body: JSON.stringify(input) },\n );\n return res.data;\n}\n\n/** Get a single page by id INCLUDING its field schema + pageType. */\nexport async function getManagedPage(client: ManagementClient, id: string): Promise<ManagedPage> {\n const res = await client.fetchJSON<{ data: ManagedPage }>(\n client.url(`/management/pages/${id}`),\n { method: \"GET\" },\n );\n return res.data;\n}\n\n/**\n * Set a page's field VALUES. For a SINGLETON page this creates or updates its one\n * page-backed content entry (idempotent); for a dynamic page it upserts the entry\n * keyed by the page. Returns the resulting entry.\n */\nexport async function setPageContent(\n client: ManagementClient,\n id: string,\n input: SetPageContentInput,\n): Promise<ManagedContentEntry> {\n const res = await client.fetchJSON<{ data: ManagedContentEntry }>(\n client.url(`/management/pages/${id}/content`),\n { method: \"PUT\", body: JSON.stringify(input) },\n );\n return res.data;\n}\n\n/** Append fields to a content model's schema (additive — rejects existing keys). */\nexport async function addModelFields(\n client: ManagementClient,\n id: string,\n input: AddPageFieldsInput,\n): Promise<ManagedContentModel> {\n const res = await client.fetchJSON<{ data: ManagedContentModel }>(\n client.url(`/management/content/models/${id}/fields`),\n { method: \"POST\", body: JSON.stringify(input) },\n );\n return res.data;\n}\n\n/** List content entries (incl. drafts), optionally filtered by model/page/status. */\nexport async function listEntries(\n client: ManagementClient,\n filter?: ListEntriesFilter,\n): Promise<ManagedContentEntry[]> {\n const q = new URLSearchParams();\n if (filter?.modelId) q.set(\"modelId\", filter.modelId);\n if (filter?.pageId) q.set(\"pageId\", filter.pageId);\n if (filter?.status) q.set(\"status\", filter.status);\n const qs = q.toString();\n const res = await client.fetchJSON<{ data: ManagedContentEntry[] }>(\n client.url(`/management/content/entries${qs ? `?${qs}` : \"\"}`),\n { method: \"GET\" },\n );\n return res.data;\n}\n\n/** Get a single content entry by id INCLUDING its data (field values), incl. drafts. */\nexport async function getEntry(client: ManagementClient, id: string): Promise<ManagedContentEntry> {\n const res = await client.fetchJSON<{ data: ManagedContentEntry }>(\n client.url(`/management/content/entries/${id}`),\n { method: \"GET\" },\n );\n return res.data;\n}\n\n/** Create a content model (schema). */\nexport async function createModel(client: ManagementClient, input: CreateModelInput): Promise<ManagedContentModel> {\n const res = await client.fetchJSON<{ data: ManagedContentModel }>(\n client.url(\"/management/content/models\"),\n { method: \"POST\", body: JSON.stringify(input) },\n );\n return res.data;\n}\n\n/** Update a content model (additive — fields/name/slug/description). */\nexport async function updateModel(client: ManagementClient, id: string, input: UpdateModelInput): Promise<ManagedContentModel> {\n const res = await client.fetchJSON<{ data: ManagedContentModel }>(\n client.url(`/management/content/models/${id}`),\n { method: \"PATCH\", body: JSON.stringify(input) },\n );\n return res.data;\n}\n\n/** Create a content entry under a model. */\nexport async function createEntry(client: ManagementClient, input: CreateEntryInput): Promise<ManagedContentEntry> {\n const res = await client.fetchJSON<{ data: ManagedContentEntry }>(\n client.url(\"/management/content/entries\"),\n { method: \"POST\", body: JSON.stringify(input) },\n );\n return res.data;\n}\n\n/**\n * Update a content entry. If `opts.ifMatch` (current optimisticVersion) is supplied,\n * the update is optimistic-locked; omit it for programmatic last-write-wins.\n */\nexport async function updateEntry(\n client: ManagementClient,\n id: string,\n input: UpdateEntryInput,\n opts?: { ifMatch?: number },\n): Promise<ManagedContentEntry> {\n const headers: Record<string, string> = {};\n if (opts?.ifMatch !== undefined) headers[\"If-Match\"] = `W/\"${opts.ifMatch}\"`;\n const res = await client.fetchJSON<{ data: ManagedContentEntry }>(\n client.url(`/management/content/entries/${id}`),\n { method: \"PATCH\", body: JSON.stringify(input), headers },\n );\n return res.data;\n}\n\n// ── Delete (soft-delete, reversible, audit-logged) ────────────────────────────\n\n/** Soft-delete a page and its content entries. The page stops being served. */\nexport async function deleteManagedPage(client: ManagementClient, id: string): Promise<{ id: string }> {\n const res = await client.fetchJSON<{ data: { id: string } }>(\n client.url(`/management/pages/${id}`),\n { method: \"DELETE\" },\n );\n return res.data;\n}\n\n/** Soft-delete a single content entry. */\nexport async function deleteEntry(client: ManagementClient, id: string): Promise<{ id: string }> {\n const res = await client.fetchJSON<{ data: { id: string } }>(\n client.url(`/management/content/entries/${id}`),\n { method: \"DELETE\" },\n );\n return res.data;\n}\n\n/** Soft-delete a content model and its entries. */\nexport async function deleteModel(client: ManagementClient, id: string): Promise<{ id: string }> {\n const res = await client.fetchJSON<{ data: { id: string } }>(\n client.url(`/management/content/models/${id}`),\n { method: \"DELETE\" },\n );\n return res.data;\n}\n","/**\n * Management API SDK method — media upload (P2).\n *\n * uploadAsset() resolves bytes from a local file path OR a remote URL, then POSTs\n * them to /api/v1/management/media (media:write scope) and returns the stored\n * asset's stable CDN URL. The MCP `upload_asset` tool wraps this so an AI agent\n * can put repo/remote images into the Media Library and reference the URL in an\n * entry's image field.\n *\n * Local-file reads use a lazy `node:` import so browser bundles that never call\n * the localPath branch don't pull Node built-ins.\n */\n\nimport type { ManagementClient } from \"./content.js\";\n\nexport interface UploadAssetInput {\n /** Path to a local file (e.g. a repo image). Mutually exclusive with `url`. */\n localPath?: string;\n /** Remote image URL to ingest. Mutually exclusive with `localPath`. */\n url?: string;\n /** Override the stored filename (defaults to the source basename). */\n filename?: string;\n altText?: string;\n caption?: string;\n /** Target Media Library folder id (defaults to project root). */\n folderId?: string;\n}\n\nexport interface UploadedAsset {\n id: string;\n url: string;\n key: string;\n filename: string;\n}\n\nconst MIME_BY_EXT: Record<string, string> = {\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n svg: \"image/svg+xml\",\n avif: \"image/avif\",\n mp4: \"video/mp4\",\n webm: \"video/webm\",\n pdf: \"application/pdf\",\n};\n\nfunction basenameOf(p: string): string {\n const clean = p.split(/[?#]/)[0] ?? p;\n const seg = clean.split(/[\\\\/]/).pop();\n return seg && seg.length > 0 ? seg : \"asset\";\n}\n\nfunction mimeFromName(name: string): string {\n const ext = name.split(\".\").pop()?.toLowerCase() ?? \"\";\n return MIME_BY_EXT[ext] ?? \"application/octet-stream\";\n}\n\n/** Max redirect hops to follow when ingesting a remote URL. */\nconst MAX_REDIRECTS = 5;\n\n/**\n * Returns true if an IP literal points at a loopback, private, link-local, or\n * otherwise non-public range. Defends the URL-ingest path against SSRF: an\n * agent (or prompt injection) must not be able to reach localhost / cloud\n * metadata (169.254.169.254) / LAN services on the host the MCP runs on.\n */\nfunction isPrivateIp(ip: string): boolean {\n const addr = ip.trim().toLowerCase();\n // IPv4-mapped IPv6 (::ffff:127.0.0.1) → unwrap and test as IPv4.\n const mapped = addr.match(/^::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/);\n const v4 = mapped ? mapped[1] : addr;\n\n if (/^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(v4)) {\n const o = v4.split(\".\").map((n) => Number(n));\n if (o.some((n) => Number.isNaN(n) || n < 0 || n > 255)) return true;\n const [a, b] = o as [number, number, number, number];\n if (a === 0 || a === 127) return true; // this-host / loopback\n if (a === 10) return true; // RFC1918\n if (a === 172 && b >= 16 && b <= 31) return true; // RFC1918\n if (a === 192 && b === 168) return true; // RFC1918\n if (a === 169 && b === 254) return true; // link-local / metadata\n if (a === 100 && b >= 64 && b <= 127) return true; // CGNAT\n if (a >= 224) return true; // multicast + reserved\n return false;\n }\n\n // IPv6\n if (addr === \"::\" || addr === \"::1\") return true; // unspecified / loopback\n if (addr.startsWith(\"fe80\") || addr.startsWith(\"fe9\") || addr.startsWith(\"fea\") || addr.startsWith(\"feb\")) return true; // link-local\n if (/^f[cd]/.test(addr)) return true; // unique-local fc00::/7\n return false;\n}\n\n/**\n * Validates a remote-ingest URL: http(s) only, and every resolved address must\n * be public. Returns the resolved-safe URL object. Throws on any violation.\n */\nasync function assertPublicHttpUrl(raw: string): Promise<URL> {\n let u: URL;\n try {\n u = new URL(raw);\n } catch {\n throw new Error(`Invalid URL: ${raw}`);\n }\n if (u.protocol !== \"http:\" && u.protocol !== \"https:\") {\n throw new Error(`Refusing non-http(s) URL scheme: ${u.protocol}`);\n }\n const host = u.hostname.replace(/^\\[|\\]$/g, \"\");\n // If the host is already an IP literal, test it directly.\n if (/^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(host) || host.includes(\":\")) {\n if (isPrivateIp(host)) throw new Error(`Refusing private/loopback address: ${host}`);\n return u;\n }\n const { lookup } = await import(\"node:dns/promises\");\n const records = await lookup(host, { all: true });\n if (records.length === 0) throw new Error(`Could not resolve host: ${host}`);\n for (const r of records) {\n if (isPrivateIp(r.address)) {\n throw new Error(`Host ${host} resolves to a private/loopback address (${r.address}); refusing`);\n }\n }\n return u;\n}\n\n/** fetch() that follows redirects manually, re-validating each hop against the SSRF allowlist. */\nasync function safeFetch(raw: string): Promise<Response> {\n let target = raw;\n for (let hop = 0; hop <= MAX_REDIRECTS; hop++) {\n await assertPublicHttpUrl(target);\n const res = await globalThis.fetch(target, { redirect: \"manual\" });\n if (res.status >= 300 && res.status < 400) {\n const loc = res.headers.get(\"location\");\n if (!loc) return res;\n target = new URL(loc, target).toString();\n continue;\n }\n return res;\n }\n throw new Error(`Too many redirects ingesting ${raw}`);\n}\n\nexport async function uploadAsset(\n client: ManagementClient,\n input: UploadAssetInput,\n): Promise<UploadedAsset> {\n let bytes: Uint8Array;\n let mime: string;\n let filename: string;\n\n if (input.localPath) {\n // Block path traversal and home-dir expansion at the input layer; the MCP\n // runs with the user's privileges, so a poisoned `..`/`~` path could\n // otherwise exfiltrate arbitrary host files into a project asset.\n if (input.localPath.includes(\"..\") || /(^|[\\\\/])~($|[\\\\/])/.test(input.localPath)) {\n throw new Error(`Refusing localPath with traversal or home-dir reference: ${input.localPath}`);\n }\n const { readFile } = await import(\"node:fs/promises\");\n const buf = await readFile(input.localPath);\n bytes = new Uint8Array(buf);\n filename = input.filename ?? basenameOf(input.localPath);\n mime = mimeFromName(filename);\n } else if (input.url) {\n const res = await safeFetch(input.url);\n if (!res.ok) {\n throw new Error(`Failed to fetch ${input.url}: ${res.status}`);\n }\n bytes = new Uint8Array(await res.arrayBuffer());\n filename = input.filename ?? basenameOf(input.url);\n mime = res.headers.get(\"content-type\")?.split(\";\")[0]?.trim() || mimeFromName(filename);\n } else {\n throw new Error(\"uploadAsset requires either localPath or url\");\n }\n\n const params = new URLSearchParams({ filename });\n if (input.altText) params.set(\"altText\", input.altText);\n if (input.caption) params.set(\"caption\", input.caption);\n if (input.folderId) params.set(\"folderId\", input.folderId);\n\n const { data } = await client.fetchJSON<{ data: UploadedAsset }>(\n client.url(`/management/media?${params.toString()}`),\n {\n method: \"POST\",\n headers: { \"Content-Type\": mime },\n body: bytes,\n },\n );\n return data;\n}\n","/**\n * Management API SDK methods — read-only form discovery.\n *\n * These call /api/v1/management/forms (key-auth, content:manage scope). The MCP\n * server wraps these so an agent can list/read the forms built in the dashboard\n * and then embed the matching `<BcmsForm>` into the user's site code. Read-only by\n * design — form authoring + Google Sheets \"integrations\" stay dashboard-only.\n */\n\nimport type { DeliveryFormField } from \"../../forms.js\";\nimport type { ManagementClient } from \"./content.js\";\n\n/** A form as returned by the Management API — the public, render-only projection. */\nexport interface ManagedForm {\n id: string;\n projectId: string | null;\n name: string;\n description: string | null;\n fields: DeliveryFormField[];\n submitLabel?: string | null;\n successMessage?: string | null;\n redirectUrl?: string | null;\n turnstileEnabled?: boolean | null;\n honeypotField?: string | null;\n}\n\n/** List forms in the key's project (or workspace-level if the key is not project-scoped). */\nexport async function listForms(client: ManagementClient): Promise<ManagedForm[]> {\n const res = await client.fetchJSON<{ data: ManagedForm[] }>(\n client.url(\"/management/forms\"),\n { method: \"GET\" },\n );\n return res.data;\n}\n\n/** Get one form by id INCLUDING its field schema + settings. */\nexport async function getForm(client: ManagementClient, id: string): Promise<ManagedForm> {\n const res = await client.fetchJSON<{ data: ManagedForm }>(\n client.url(`/management/forms/${id}`),\n { method: \"GET\" },\n );\n return res.data;\n}\n\n/** Create/update input — mirrors the Management API form schema (fields are passed through). */\nexport interface ManagedFormInput {\n name?: string;\n description?: string;\n fields?: DeliveryFormField[];\n submitLabel?: string;\n successMessage?: string;\n redirectUrl?: string;\n}\n\n/** Create a form in the key's project. Returns the created form. */\nexport async function createForm(client: ManagementClient, input: ManagedFormInput): Promise<ManagedForm> {\n const res = await client.fetchJSON<{ data: ManagedForm }>(client.url(\"/management/forms\"), {\n method: \"POST\",\n body: JSON.stringify(input),\n });\n return res.data;\n}\n\n/** Update a form by id. Passing `fields` replaces the array. */\nexport async function updateForm(\n client: ManagementClient,\n id: string,\n input: ManagedFormInput,\n): Promise<ManagedForm> {\n const res = await client.fetchJSON<{ data: ManagedForm }>(client.url(`/management/forms/${id}`), {\n method: \"PATCH\",\n body: JSON.stringify(input),\n });\n return res.data;\n}\n","/**\n * Management API SDK methods — reusable components (discover + author).\n *\n * Call /api/v1/management/components (key-auth, content:manage). The MCP server wraps\n * these so an agent can list/read components and author new ones (blockJson + props).\n */\n\nimport type { ManagementClient } from \"./content.js\";\n\n/** A component as returned by the Management API (render + author shape). */\nexport interface ManagedComponent {\n id: string;\n projectId: string | null;\n name: string;\n slug: string;\n category: string;\n description: string | null;\n blockJson: unknown[];\n props: unknown[];\n thumbnail?: string | null;\n}\n\n/** Create/update input. `blockJson` is the ContentBlock tree; `props` the override allowlist. */\nexport interface ManagedComponentInput {\n name?: string;\n slug?: string;\n category?: string;\n description?: string;\n blockJson?: unknown[];\n props?: unknown[];\n}\n\nexport async function listComponents(client: ManagementClient): Promise<ManagedComponent[]> {\n const res = await client.fetchJSON<{ data: ManagedComponent[] }>(\n client.url(\"/management/components\"),\n { method: \"GET\" },\n );\n return res.data;\n}\n\nexport async function getComponent(client: ManagementClient, id: string): Promise<ManagedComponent> {\n const res = await client.fetchJSON<{ data: ManagedComponent }>(\n client.url(`/management/components/${id}`),\n { method: \"GET\" },\n );\n return res.data;\n}\n\nexport async function createComponent(\n client: ManagementClient,\n input: ManagedComponentInput,\n): Promise<ManagedComponent> {\n const res = await client.fetchJSON<{ data: ManagedComponent }>(client.url(\"/management/components\"), {\n method: \"POST\",\n body: JSON.stringify(input),\n });\n return res.data;\n}\n\nexport async function updateComponent(\n client: ManagementClient,\n id: string,\n input: ManagedComponentInput,\n): Promise<ManagedComponent> {\n const res = await client.fetchJSON<{ data: ManagedComponent }>(\n client.url(`/management/components/${id}`),\n { method: \"PATCH\", body: JSON.stringify(input) },\n );\n return res.data;\n}\n","/**\n * BetterCMSManagementClient — typed SDK client for the Management API.\n *\n * Authenticates with a content:manage scoped API key (X-API-Key) and targets\n * /api/v1/management/content/*. Used for programmatic schema + content authoring\n * (and wrapped by the MCP server). Mirrors BetterCMSAdminClient's retry/timeout,\n * but uses key auth instead of a BetterAuth Bearer token.\n */\n\nimport { BetterCMSDeliveryClient } from \"./delivery-client.js\";\nimport { BetterCMSError } from \"./errors.js\";\nimport {\n listModels,\n getModel,\n createModel,\n updateModel,\n createEntry,\n updateEntry,\n listManagedPages,\n createManagedPage,\n addPageFields,\n getManagedPage,\n setPageContent,\n addModelFields,\n listEntries,\n getEntry,\n deleteManagedPage,\n deleteEntry,\n deleteModel,\n type CreateModelInput,\n type UpdateModelInput,\n type CreateEntryInput,\n type UpdateEntryInput,\n type CreateManagedPageInput,\n type AddPageFieldsInput,\n type SetPageContentInput,\n type ListEntriesFilter,\n} from \"./methods/management/content.js\";\nimport {\n uploadAsset,\n type UploadAssetInput,\n type UploadedAsset,\n} from \"./methods/management/media.js\";\nimport {\n listForms,\n getForm,\n createForm,\n updateForm,\n type ManagedForm,\n type ManagedFormInput,\n} from \"./methods/management/forms.js\";\nimport {\n listComponents,\n getComponent,\n createComponent,\n updateComponent,\n type ManagedComponent,\n type ManagedComponentInput,\n} from \"./methods/management/components.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.bettercms.ai/v1\";\nconst DEFAULT_TIMEOUT = 10_000;\nconst RETRY_STATUSES = [429, 503] as const;\nconst RETRY_DELAYS = [1_000, 2_000, 4_000] as const;\n\nexport interface BetterCMSManagementOptions {\n /** Base URL of the Management API. Defaults to https://api.bettercms.ai/v1 */\n baseUrl?: string;\n /** A content:manage scoped API key. */\n apiKey: string;\n /** Request timeout per attempt in ms. Defaults to 10000. */\n timeout?: number;\n}\n\nexport class BetterCMSManagementClient extends BetterCMSDeliveryClient {\n readonly timeout: number;\n private readonly _apiKey: string;\n\n constructor(options: BetterCMSManagementOptions) {\n super({ workspace: \"\", baseUrl: options.baseUrl ?? DEFAULT_BASE_URL });\n this._apiKey = options.apiKey;\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n }\n\n headers(): Record<string, string> {\n return {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this._apiKey,\n };\n }\n\n /** Management API URL: baseUrl + path (path is workspace-scoped via the key). */\n url(path: string): string {\n return `${this.baseUrl}${path}`;\n }\n\n /** fetchJSON with retry (429, 503) + per-request timeout (mirrors the admin client). */\n async fetchJSON<T>(url: string, init?: RequestInit): Promise<T> {\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= 3; attempt++) {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n let nonRetryable = false;\n\n try {\n const res = await globalThis.fetch(url, {\n ...init,\n headers: { ...this.headers(), ...(init?.headers ?? {}) },\n signal: controller.signal,\n });\n clearTimeout(timeoutId);\n\n if (res.ok) {\n return res.json() as T;\n }\n\n const shouldRetry = attempt < 3 && (RETRY_STATUSES as readonly number[]).includes(res.status);\n if (!shouldRetry) {\n nonRetryable = true;\n throw await BetterCMSError.from(res);\n }\n await sleep(RETRY_DELAYS[attempt] ?? 0);\n } catch (err) {\n clearTimeout(timeoutId);\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new BetterCMSError(\"Request timeout\", 408, \"NETWORK_ERROR\");\n }\n if (nonRetryable) throw err;\n lastError = err;\n if (attempt < 3) {\n await sleep(RETRY_DELAYS[attempt] ?? 0);\n continue;\n }\n throw err;\n }\n }\n\n throw lastError ?? new BetterCMSError(\"Unreachable\", 0, \"NETWORK_ERROR\");\n }\n\n // ── Schema authoring ──────────────────────────────────────────────────────\n listModels() {\n return listModels(this);\n }\n getModel(id: string) {\n return getModel(this, id);\n }\n createModel(input: CreateModelInput) {\n return createModel(this, input);\n }\n updateModel(id: string, input: UpdateModelInput) {\n return updateModel(this, id, input);\n }\n\n // ── Page authoring (page-first: singleton + dynamic) ──────────────────────\n listPages() {\n return listManagedPages(this);\n }\n /** Get one page by id INCLUDING its field schema + pageType. */\n getPage(id: string) {\n return getManagedPage(this, id);\n }\n createPage(input: CreateManagedPageInput) {\n return createManagedPage(this, input);\n }\n /** Append fields to an existing page (additive — the API rejects existing keys). */\n addPageFields(id: string, input: AddPageFieldsInput) {\n return addPageFields(this, id, input);\n }\n /** Set a page's field VALUES — singleton pages get/update their one entry. */\n setPageContent(id: string, input: SetPageContentInput) {\n return setPageContent(this, id, input);\n }\n\n // ── Schema authoring (additive field append) ──────────────────────────────\n /** Append fields to a content model (additive — rejects existing keys). */\n addModelFields(id: string, input: AddPageFieldsInput) {\n return addModelFields(this, id, input);\n }\n\n // ── Content authoring ─────────────────────────────────────────────────────\n createEntry(input: CreateEntryInput) {\n return createEntry(this, input);\n }\n updateEntry(id: string, input: UpdateEntryInput, opts?: { ifMatch?: number }) {\n return updateEntry(this, id, input, opts);\n }\n\n // ── Delete (soft-delete, reversible, audit-logged) ─────────────────────────\n /** Soft-delete a page and its content entries. */\n deletePage(id: string) {\n return deleteManagedPage(this, id);\n }\n /** Soft-delete a single content entry. */\n deleteEntry(id: string) {\n return deleteEntry(this, id);\n }\n /** Soft-delete a content model and its entries. */\n deleteModel(id: string) {\n return deleteModel(this, id);\n }\n /** List content entries (incl. drafts), optionally filtered by model/page/status. */\n listEntries(filter?: ListEntriesFilter) {\n return listEntries(this, filter);\n }\n /** Get one content entry by id INCLUDING its data (incl. drafts). */\n getEntry(id: string) {\n return getEntry(this, id);\n }\n\n // ── Media (P2): upload an asset from a local path or URL, get its CDN URL ──\n uploadAsset(input: UploadAssetInput): Promise<UploadedAsset> {\n return uploadAsset(this, input);\n }\n\n // ── Forms (read-only): discover dashboard-built forms to embed into site code ──\n /** List forms in the key's project (or workspace-level). */\n listForms(): Promise<ManagedForm[]> {\n return listForms(this);\n }\n /** Get one form by id INCLUDING its field schema + settings. */\n getForm(id: string): Promise<ManagedForm> {\n return getForm(this, id);\n }\n /** Create a form in the key's project. */\n createForm(input: ManagedFormInput): Promise<ManagedForm> {\n return createForm(this, input);\n }\n /** Update a form by id (passing `fields` replaces the array). */\n updateForm(id: string, input: ManagedFormInput): Promise<ManagedForm> {\n return updateForm(this, id, input);\n }\n\n // ── Components: discover + author reusable symbols ──\n listComponents(): Promise<ManagedComponent[]> {\n return listComponents(this);\n }\n getComponent(id: string): Promise<ManagedComponent> {\n return getComponent(this, id);\n }\n createComponent(input: ManagedComponentInput): Promise<ManagedComponent> {\n return createComponent(this, input);\n }\n updateComponent(id: string, input: ManagedComponentInput): Promise<ManagedComponent> {\n return updateComponent(this, id, input);\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { BetterCMSAdminClient } from \"./admin-client.js\";\nimport { BetterCMSError } from \"./errors.js\";\nimport type { AuthUser, AuthSession, SignUpInput, SignInInput, AuthResponse } from \"@bettercms-ai/types\";\n\nconst AUTH_BASE_URL = \"https://api.bettercms.ai/api/v1/auth\";\nconst AUTH_URL = \"https://api.bettercms.ai/api/auth\";\n\nexport interface AuthResult {\n token: string;\n user: AuthUser;\n session: AuthSession;\n admin: BetterCMSAdminClient;\n signOut(): Promise<void>;\n}\n\nexport interface OAuthProvider {\n google: \"google\";\n github: \"github\";\n}\n\nasync function authFetch(url: string, body: object): Promise<AuthResponse> {\n const res = await globalThis.fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n throw await BetterCMSError.from(res);\n }\n\n return res.json() as Promise<AuthResponse>;\n}\n\n/** Sign in with email + password. Returns a session ready for API calls. */\nexport async function signIn(input: SignInInput): Promise<AuthResult> {\n const data = await authFetch(`${AUTH_BASE_URL}/sign-in`, input);\n return buildAuthResult(data);\n}\n\n/** Sign up with email + password + name. Returns a session ready for API calls. */\nexport async function signUp(input: SignUpInput): Promise<AuthResult> {\n const data = await authFetch(`${AUTH_BASE_URL}/sign-up`, input);\n return buildAuthResult(data);\n}\n\n/**\n * Initiate Google OAuth sign-in (browser flow) or verify a Google ID token (programmatic).\n *\n * Browser flow: Returns { url } — redirect the user to this URL.\n * Programmatic: Pass { idToken: { token: \"<google-id-token>\" } } — returns AuthResult directly.\n */\nexport async function signInWithGoogle(\n options?: { idToken?: { token: string; nonce?: string }; callbackURL?: string }\n): Promise<AuthResult & { url?: string; redirect?: boolean }> {\n const res = await globalThis.fetch(`${AUTH_URL}/sign-in/social`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n provider: \"google\",\n callbackURL: options?.callbackURL,\n idToken: options?.idToken,\n disableRedirect: !!options?.idToken,\n }),\n });\n\n if (!res.ok) {\n throw await BetterCMSError.from(res);\n }\n\n const data = (await res.json()) as { user: AuthUser; session: AuthSession; token: string; url?: string; redirect?: boolean };\n\n if (options?.idToken) {\n // Programmatic flow — return full AuthResult\n return { ...buildAuthResult(data), url: data.url, redirect: data.redirect };\n }\n\n // Browser flow — return url for client-side redirect\n return { ...buildAuthResult(data), url: data.url, redirect: data.redirect };\n}\n\n/**\n * Initiate GitHub OAuth sign-in (browser flow) or verify a GitHub OAuth token (programmatic).\n *\n * Browser flow: Returns { url } — redirect the user to this URL.\n * Programmatic: Pass { idToken: { token: \"<github-access-token>\" } } — returns AuthResult directly.\n */\nexport async function signInWithGithub(\n options?: { idToken?: { token: string; nonce?: string }; callbackURL?: string }\n): Promise<AuthResult & { url?: string; redirect?: boolean }> {\n const res = await globalThis.fetch(`${AUTH_URL}/sign-in/social`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n provider: \"github\",\n callbackURL: options?.callbackURL,\n idToken: options?.idToken,\n disableRedirect: !!options?.idToken,\n }),\n });\n\n if (!res.ok) {\n throw await BetterCMSError.from(res);\n }\n\n const data = (await res.json()) as { user: AuthUser; session: AuthSession; token: string; url?: string; redirect?: boolean };\n\n if (options?.idToken) {\n // Programmatic flow — return full AuthResult\n return { ...buildAuthResult(data), url: data.url, redirect: data.redirect };\n }\n\n // Browser flow — return url for client-side redirect\n return { ...buildAuthResult(data), url: data.url, redirect: data.redirect };\n}\n\nfunction buildAuthResult(data: AuthResponse): AuthResult {\n const admin = new BetterCMSAdminClient({ token: data.token });\n return {\n token: data.token,\n user: data.user,\n session: data.session,\n admin,\n signOut: async () => {\n await globalThis.fetch(`${AUTH_BASE_URL}/sign-out`, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${data.token}` },\n });\n },\n };\n}","import { BetterCMSAdminClient, type BetterCMSAdminOptions } from \"./admin-client.js\";\nimport { BetterCMSManagementClient, type BetterCMSManagementOptions } from \"./management-client.js\";\nimport { BetterCMSDeliveryClient } from \"./delivery-client.js\";\nimport { signIn, signUp, type AuthResult } from \"./auth.js\";\nimport type { SignInInput, SignUpInput } from \"@bettercms-ai/types\";\n\nconst DEFAULT_BASE_URL = \"https://api.bettercms.ai/v1\";\n\n/**\n * Options for {@link BetterCMS.site}.\n */\nexport interface BetterCMSSiteOptions {\n /** The workspace slug (e.g. \"rahul-project-one\"). */\n workspace: string;\n /** Optional API key for authenticated requests. */\n apiKey?: string;\n /** Base URL of the Delivery API. Defaults to https://api.bettercms.ai/v1. */\n baseUrl?: string;\n}\n\n/**\n * BetterCMS factory — returns a typed client for the Delivery API.\n */\nexport const BetterCMS = {\n /**\n * Returns a client for fetching published content.\n * `apiKey` is optional — public content works without one.\n */\n site(options: BetterCMSSiteOptions): BetterCMSDeliveryClient {\n return new BetterCMSDeliveryClient({\n workspace: options.workspace,\n apiKey: options.apiKey,\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n });\n },\n\n /**\n * Returns a typed client for admin CRUD operations.\n * Requires a BetterAuth session Bearer token.\n */\n admin(options: BetterCMSAdminOptions): BetterCMSAdminClient {\n return new BetterCMSAdminClient(options);\n },\n\n /**\n * Returns a typed client for the Management API (programmatic schema + content\n * authoring). Requires a content:manage scoped API key.\n */\n management(options: BetterCMSManagementOptions): BetterCMSManagementClient {\n return new BetterCMSManagementClient(options);\n },\n\n /**\n * Sign in with email + password. Returns a session ready for API calls.\n */\n async auth(options: SignInInput): Promise<AuthResult> {\n return signIn(options);\n },\n\n /**\n * Sign up with email + password + name. Returns a session ready for API calls.\n */\n async signUp(options: SignUpInput): Promise<AuthResult> {\n return signUp(options);\n },\n};\n\nexport { BetterCMSDeliveryClient };\nexport { BetterCMSManagementClient };\n","/**\n * createClient — framework-agnostic typed read client for the Delivery API.\n *\n * Shared by @bettercms-ai/astro and @bettercms-ai/next so the fetch/typing/retry\n * logic lives in one place. Read-only; for schema authoring use the\n * Management client, for sessions use the Admin client.\n *\n * const client = createClient({ apiUrl, workspace, apiKey });\n * await client.getPage(\"home\");\n * await client.listEntries({ model: \"post\", perPage: 50 });\n */\nimport type {\n DeliveryEntry,\n DeliveryList,\n DeliveryPage,\n Perspective,\n} from \"@bettercms-ai/types\";\nimport { BetterCMSError } from \"./errors.js\";\nimport type { DeliveryForm } from \"./forms.js\";\n\nconst RETRY_STATUSES = [429, 503] as const;\nconst RETRY_DELAYS = [250, 750, 1500];\nconst DEFAULT_TIMEOUT = 10_000;\n\nexport interface CreateClientOptions {\n /** Backend base, e.g. `https://api.bettercms.ai` (no trailing slash needed). */\n apiUrl: string;\n /** Workspace slug. */\n workspace: string;\n /** Delivery API key. Use a `content:read:draft` key for drafts. */\n apiKey?: string;\n /** Optional project scope for forms. */\n projectId?: string;\n /** `published` (default) or `drafts`. */\n perspective?: Perspective;\n /**\n * Preview-token JWT for token-based single-document draft reads via the\n * `/preview/:slug` endpoint. Only used when `perspective === \"drafts\"`.\n */\n previewToken?: string;\n /** Embed visual-editing stega provenance in draft reads (preview lane only). */\n stega?: boolean;\n /** Per-attempt timeout in ms. Defaults to 10000. */\n timeout?: number;\n}\n\nexport interface ListEntriesOptions {\n /** Filter by content-model slug. */\n model?: string;\n page?: number;\n perPage?: number;\n /** Reference hydration depth (lists cap at 1). */\n depth?: 0 | 1;\n /** Projection — field names to return. */\n select?: string[];\n}\n\nexport interface GetEntryOptions {\n depth?: 0 | 1 | 2;\n select?: string[];\n}\n\nexport interface ListPagesOptions {\n page?: number;\n perPage?: number;\n}\n\nexport interface BetterCMSReadClient {\n readonly perspective: Perspective;\n getEntry<T = Record<string, unknown>>(\n slug: string,\n opts?: GetEntryOptions,\n ): Promise<DeliveryEntry<T>>;\n listEntries<T = Record<string, unknown>>(\n opts?: ListEntriesOptions,\n ): Promise<DeliveryList<DeliveryEntry<T>>>;\n getPage(slug: string): Promise<DeliveryPage | null>;\n listPages(opts?: ListPagesOptions): Promise<DeliveryList<DeliveryPage>>;\n listForms(opts?: {\n projectId?: string;\n }): Promise<{ items: DeliveryForm[]; turnstileSiteKey: string | null }>;\n /** Build a deterministic Next/cache tag for a resource. */\n tag(resource: \"entry\" | \"page\" | \"forms\", id?: string): string;\n}\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\n/** Drop undefined values, stringify the rest into a query string. */\nfunction qs(params: Record<string, string | number | undefined>): string {\n const sp = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== \"\") sp.set(k, String(v));\n }\n const s = sp.toString();\n return s ? `?${s}` : \"\";\n}\n\n/**\n * Unwrap a `{ data: ... }` list/legacy envelope when present. A bare entry is\n * already the payload (it has `id`/`slug` and its own `data` field), so we only\n * unwrap when no payload markers are at the top level.\n */\nfunction unwrap<T>(json: unknown): T {\n if (json && typeof json === \"object\") {\n const o = json as Record<string, unknown>;\n const isPayload = \"id\" in o || \"slug\" in o || \"items\" in o;\n if (!isPayload && \"data\" in o) return o.data as T;\n }\n return json as T;\n}\n\nexport function createClient(options: CreateClientOptions): BetterCMSReadClient {\n const apiUrl = options.apiUrl.replace(/\\/+$/, \"\");\n const { workspace, apiKey, perspective = \"published\", previewToken } = options;\n const defaultProjectId = options.projectId;\n const timeout = options.timeout ?? DEFAULT_TIMEOUT;\n const base = `${apiUrl}/api/v1/delivery/${workspace}`;\n\n const headers = (): Record<string, string> => {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (apiKey) h[\"X-API-Key\"] = apiKey;\n return h;\n };\n\n async function fetchJSON<T>(url: string): Promise<T> {\n let lastError: unknown;\n for (let attempt = 0; attempt <= RETRY_DELAYS.length; attempt++) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeout);\n try {\n const res = await globalThis.fetch(url, {\n headers: headers(),\n signal: controller.signal,\n });\n clearTimeout(timer);\n if (res.ok) return (await res.json()) as T;\n\n const retryable =\n attempt < RETRY_DELAYS.length &&\n (RETRY_STATUSES as readonly number[]).includes(res.status);\n if (!retryable) throw await BetterCMSError.from(res);\n await sleep(RETRY_DELAYS[attempt] ?? 0);\n } catch (err) {\n clearTimeout(timer);\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new BetterCMSError(\"Request timeout\", 408, \"NETWORK_ERROR\");\n }\n if (err instanceof BetterCMSError) throw err;\n lastError = err;\n if (attempt < RETRY_DELAYS.length) {\n await sleep(RETRY_DELAYS[attempt] ?? 0);\n continue;\n }\n throw new BetterCMSError(\n `Network error: ${err instanceof Error ? err.message : String(err)}`,\n 0,\n \"NETWORK_ERROR\",\n );\n }\n }\n throw lastError ?? new BetterCMSError(\"Unreachable\", 0, \"NETWORK_ERROR\");\n }\n\n const draft = perspective === \"drafts\";\n\n return {\n perspective,\n\n async getEntry<T = Record<string, unknown>>(slug: string, opts?: GetEntryOptions) {\n const query = qs({\n depth: opts?.depth,\n select: opts?.select?.join(\",\"),\n });\n // Token-based draft reads go through the dedicated preview endpoint.\n const url =\n draft && previewToken\n ? `${apiUrl}/api/v1/preview/${encodeURIComponent(slug)}${qs({\n token: previewToken,\n depth: opts?.depth,\n select: opts?.select?.join(\",\"),\n stega: options.stega ? \"1\" : undefined,\n })}`\n : `${base}/content-entries/${encodeURIComponent(slug)}${query}`;\n return unwrap<DeliveryEntry<T>>(await fetchJSON(url));\n },\n\n async listEntries<T = Record<string, unknown>>(opts?: ListEntriesOptions) {\n const url = `${base}/content-entries${qs({\n model: opts?.model,\n page: opts?.page,\n perPage: opts?.perPage,\n depth: opts?.depth,\n select: opts?.select?.join(\",\"),\n })}`;\n return unwrap<DeliveryList<DeliveryEntry<T>>>(await fetchJSON(url));\n },\n\n async getPage(slug: string) {\n // No dedicated single-page delivery endpoint — scan the paginated list.\n let page = 1;\n for (;;) {\n const list = await this.listPages({ page, perPage: 100 });\n const found = list.items.find((p) => p.slug === slug);\n if (found) return found;\n if (!list.hasNextPage) return null;\n page += 1;\n }\n },\n\n async listPages(opts?: ListPagesOptions) {\n const url = `${base}/pages${qs({\n page: opts?.page,\n perPage: opts?.perPage,\n })}`;\n return unwrap<DeliveryList<DeliveryPage>>(await fetchJSON(url));\n },\n\n async listForms(opts?: { projectId?: string }) {\n const url = `${base}/forms${qs({\n projectId: opts?.projectId ?? defaultProjectId,\n })}`;\n return unwrap<{ items: DeliveryForm[]; turnstileSiteKey: string | null }>(\n await fetchJSON(url),\n );\n },\n\n tag(resource, id) {\n return id ? `bcms:${workspace}:${resource}:${id}` : `bcms:${workspace}:${resource}`;\n },\n };\n}\n","/**\n * Stega — embed invisible content-provenance into string values for visual\n * editing, then decode it in the browser overlay to open the right dashboard\n * editor. Uses zero-width characters so the payload is invisible and copy-safe.\n *\n * Scheme: `<clean text><START><bits…><END>` where each byte of the UTF-8 JSON\n * payload is 8 zero-width bits (ZERO=U+200B, ONE=U+200C), framed by START\n * (U+2060) and END (U+2061). The backend encodes draft responses; the overlay\n * decodes. Both sides MUST share this module's scheme.\n */\nconst ZERO = \"\";\nconst ONE = \"\";\nconst START = \"\";\nconst END = \"\";\nconst FRAME = new RegExp(`${START}([${ZERO}${ONE}]*)${END}`);\n\n/** Provenance describing where a string came from, for editor deep-linking. */\nexport interface StegaPayload {\n /** Workspace slug. */\n ws: string;\n type: \"entry\" | \"page\";\n /** Entry/page id. */\n id: string;\n slug: string;\n /** Field key (or block id) the value belongs to. */\n field: string;\n}\n\nfunction toBits(s: string): string {\n const bytes = new TextEncoder().encode(s);\n let out = \"\";\n for (const b of bytes) {\n for (let i = 7; i >= 0; i--) out += (b >> i) & 1 ? ONE : ZERO;\n }\n return out;\n}\n\nfunction fromBits(bits: string): string {\n const bytes: number[] = [];\n for (let i = 0; i + 8 <= bits.length; i += 8) {\n let b = 0;\n for (let j = 0; j < 8; j++) b = (b << 1) | (bits[i + j] === ONE ? 1 : 0);\n bytes.push(b);\n }\n return new TextDecoder().decode(new Uint8Array(bytes));\n}\n\n/** Append an invisible provenance payload to a string. */\nexport function encodeStega(clean: string, payload: StegaPayload): string {\n return `${clean}${START}${toBits(JSON.stringify(payload))}${END}`;\n}\n\n/** Extract `{ clean, payload }` from a stega-encoded string, or null if absent. */\nexport function decodeStega(value: string): { clean: string; payload: StegaPayload } | null {\n const m = value.match(FRAME);\n if (!m || m[1] == null) return null;\n try {\n const payload = JSON.parse(fromBits(m[1])) as StegaPayload;\n return { clean: value.replace(FRAME, \"\"), payload };\n } catch {\n return null;\n }\n}\n\n/** Remove any stega payload, returning the clean string. */\nexport function stripStega(value: string): string {\n return value.replace(FRAME, \"\");\n}\n","/**\n * resolveSeo — framework-agnostic page-over-site SEO merge for headless consumers.\n *\n * The single source of truth for \"per-page meta layered over project defaults\",\n * mirroring the server renderer's `mergeSeoMeta` so `*.bettercms.site` and headless\n * sites (@bettercms-ai/next, @bettercms-ai/astro) emit identical <head> SEO. Pure: empty\n * inputs collapse to empty strings (\"omit the tag\"), never fabricated values.\n *\n * const seo = resolveSeo(page, siteDefaults);\n * // → { title, description, canonical, og, twitter, jsonLd }\n *\n * Next consumers map this to a `Metadata` via `buildMetadata` (@bettercms-ai/next);\n * Astro consumers read the fields straight into `<head>`.\n */\nimport type { PageMetaJson, SiteSeoDefaults } from \"@bettercms-ai/types\";\n\n/** Minimal page shape `resolveSeo` reads — a `DeliveryPage`/`BetterCMSPage` satisfies it. */\nexport interface SeoInput {\n title: string;\n metaTitle?: string | null;\n metaDescription?: string | null;\n metaJson?: PageMetaJson | null;\n}\n\n/** Fully-resolved SEO values, page-over-site. Empty string ⇒ omit that tag. */\nexport interface ResolvedSeo {\n title: string;\n description: string;\n /** Canonical URL — page's own `canonical`, else \"\". Consumers may supply their own base. */\n canonical: string;\n og: {\n title: string;\n description: string;\n type: string;\n image: string;\n url: string;\n };\n twitter: {\n card: string;\n title: string;\n description: string;\n image: string;\n site: string;\n };\n /** JSON-LD nodes (site schema first, then the page's), already flattened + de-empted. */\n jsonLd: Array<Record<string, unknown>>;\n}\n\n/** Flatten one-or-many JSON-LD into a node array, dropping empty objects. */\nfunction jsonLdNodes(\n schema: Record<string, unknown> | Array<Record<string, unknown>> | undefined,\n): Array<Record<string, unknown>> {\n if (!schema) return [];\n const arr = Array.isArray(schema) ? schema : [schema];\n return arr.filter((node) => node && Object.keys(node).length > 0);\n}\n\n/**\n * Merge a page's own SEO over the site defaults. Identical precedence to the server's\n * `mergeSeoMeta`: page meta wins, then site defaults, then sensible fallbacks.\n */\nexport function resolveSeo(page: SeoInput, defaults: SiteSeoDefaults = {}): ResolvedSeo {\n const meta = page.metaJson ?? {};\n const title = page.metaTitle || page.title || \"\";\n const description = page.metaDescription || defaults.metaDescription || \"\";\n const ogImage = meta.og?.image || defaults.og?.image || defaults.ogImage || \"\";\n const ogTitle = meta.og?.title || title;\n const ogDescription = meta.og?.description || description;\n const twImage = meta.twitter?.image || ogImage;\n const canonical = meta.canonical || \"\";\n return {\n title,\n description,\n canonical,\n og: {\n title: ogTitle,\n description: ogDescription,\n type: meta.og?.type || defaults.og?.type || \"website\",\n image: ogImage,\n url: canonical,\n },\n twitter: {\n card: meta.twitter?.card || defaults.twitter?.card || (twImage ? \"summary_large_image\" : \"summary\"),\n title: meta.twitter?.title || ogTitle,\n description: meta.twitter?.description || ogDescription,\n image: twImage,\n site: defaults.twitterHandle || \"\",\n },\n jsonLd: [...jsonLdNodes(defaults.siteSchema), ...jsonLdNodes(meta.schema)],\n };\n}\n","/**\n * Public site search — the headless surface for the visitor-facing search box.\n *\n * Queries `GET /api/v1/delivery/search?project=…&q=…`, the same key-less public\n * endpoint the embeddable widget uses. Powers <BcmsSearch> in @bettercms-ai/next\n * and @bettercms-ai/astro, so the component and any custom UI never drift.\n *\n * `snippet` is HTML-safe: the server escapes the field content and keeps only the\n * <mark> highlight wrappers, so it can be rendered with dangerouslySetInnerHTML.\n */\n\nconst DEFAULT_BASE_URL = \"https://api.bettercms.ai\";\n\nexport interface SearchHit {\n title: string;\n slug: string;\n type: \"page\" | \"entry\";\n /** HTML-safe snippet with <mark> highlights around matched terms. */\n snippet: string;\n /** Site-relative URL, e.g. \"/about\". */\n url: string;\n}\n\nexport interface SearchOptions {\n /** The project id (from the dashboard's Site Search settings). */\n project: string;\n /** The query string. Calls with fewer than 1 char resolve to []. */\n q: string;\n /** Max hits, 1–20 (default 8). */\n limit?: number;\n /** API origin. Defaults to https://api.bettercms.ai. */\n baseUrl?: string;\n /** Injectable fetch for tests / non-browser runtimes. */\n fetchImpl?: typeof fetch;\n /** AbortSignal so callers can cancel a stale in-flight search. */\n signal?: AbortSignal;\n}\n\n/** Search a published site. Resolves with hits, or [] on an empty query / network error. */\nexport async function search(opts: SearchOptions): Promise<SearchHit[]> {\n const q = opts.q.trim();\n if (!q) return [];\n const baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n const doFetch = opts.fetchImpl ?? globalThis.fetch;\n const params = new URLSearchParams({ project: opts.project, q });\n if (opts.limit) params.set(\"limit\", String(opts.limit));\n\n try {\n const res = await doFetch(`${baseUrl}/api/v1/delivery/search?${params}`, { signal: opts.signal });\n if (!res.ok) return [];\n const json = (await res.json().catch(() => ({}))) as { hits?: SearchHit[] };\n return json.hits ?? [];\n } catch {\n return []; // network/abort → no results, never throw into a render path\n }\n}\n","/**\n * Admin pages methods.\n * @see openspec/changes/flo-6-backend-sdk-admin/specs/sdk-admin-client/spec.md\n */\n\nimport type { BetterCMSAdminClient } from \"../../admin-client.js\";\nimport type { Page } from \"@bettercms-ai/types\";\n\nexport interface PageListOptions {\n page?: number;\n limit?: number;\n}\n\nexport interface CreatePageInput {\n title: string;\n slug: string;\n metaTitle?: string;\n metaDescription?: string;\n status?: \"draft\" | \"published\";\n}\n\nexport interface UpdatePageInput extends Partial<CreatePageInput> {}\n\ninterface PaginatedMeta {\n page: number;\n limit: number;\n total: number;\n}\n\nexport interface PagesAdmin {\n list(opts?: PageListOptions): Promise<Page[]>;\n get(id: string): Promise<Page>;\n create(data: CreatePageInput): Promise<Page>;\n update(id: string, data: UpdatePageInput): Promise<Page>;\n delete(id: string): Promise<void>;\n publish(id: string): Promise<Page>;\n}\n\nfunction params(opts?: PageListOptions): string {\n const p = new URLSearchParams();\n if (opts?.page != null) p.set(\"page\", String(opts.page));\n if (opts?.limit != null) p.set(\"limit\", String(opts.limit));\n return p.toString() ? `?${p}` : \"\";\n}\n\nexport async function listPages(\n client: BetterCMSAdminClient,\n opts?: PageListOptions,\n): Promise<Page[]> {\n const res = await client.fetchJSON<{ data: Page[]; meta: PaginatedMeta }>(\n client.url(`/pages${params(opts)}`),\n );\n return res.data;\n}\n\nexport async function getPage(\n client: BetterCMSAdminClient,\n id: string,\n): Promise<Page> {\n const res = await client.fetchJSON<{ data: Page }>(client.url(`/pages/${id}`));\n return res.data;\n}\n\nexport async function createPage(\n client: BetterCMSAdminClient,\n data: CreatePageInput,\n): Promise<Page> {\n const res = await client.fetchJSON<{ data: Page }>(client.url(\"/pages\"), {\n method: \"POST\",\n body: JSON.stringify(data),\n });\n return res.data;\n}\n\nexport async function updatePage(\n client: BetterCMSAdminClient,\n id: string,\n data: UpdatePageInput,\n): Promise<Page> {\n const res = await client.fetchJSON<{ data: Page }>(client.url(`/pages/${id}`), {\n method: \"PATCH\",\n body: JSON.stringify(data),\n });\n return res.data;\n}\n\nexport async function deletePage(\n client: BetterCMSAdminClient,\n id: string,\n): Promise<void> {\n await client.fetchJSON(client.url(`/pages/${id}`), { method: \"DELETE\" });\n}\n\nexport async function publishPage(\n client: BetterCMSAdminClient,\n id: string,\n): Promise<Page> {\n const res = await client.fetchJSON<{ data: Page }>(client.url(`/pages/${id}/publish`), {\n method: \"POST\",\n });\n return res.data;\n}\n","/**\n * Admin media methods.\n * @see openspec/changes/flo-6-backend-sdk-admin/specs/sdk-admin-client/spec.md\n */\n\nimport type { BetterCMSAdminClient } from \"../../admin-client.js\";\nimport type { MediaAsset } from \"@bettercms-ai/types\";\n\nexport interface MediaListOptions {\n page?: number;\n limit?: number;\n}\n\nexport interface MediaMetadata {\n alt?: string;\n caption?: string;\n}\n\nexport interface MediaAdmin {\n list(opts?: MediaListOptions): Promise<MediaAsset[]>;\n get(id: string): Promise<MediaAsset>;\n upload(file: File, metadata?: MediaMetadata): Promise<MediaAsset>;\n delete(id: string): Promise<void>;\n}\n\nexport async function listMedia(\n client: BetterCMSAdminClient,\n opts?: MediaListOptions,\n): Promise<MediaAsset[]> {\n const p = new URLSearchParams();\n if (opts?.page != null) p.set(\"page\", String(opts.page));\n if (opts?.limit != null) p.set(\"limit\", String(opts.limit));\n const qs = p.toString() ? `?${p}` : \"\";\n const res = await client.fetchJSON<{ data: MediaAsset[]; meta: { page: number; limit: number; total: number } }>(\n client.url(`/media${qs}`),\n );\n return res.data;\n}\n\nexport async function getMedia(\n client: BetterCMSAdminClient,\n id: string,\n): Promise<MediaAsset> {\n const res = await client.fetchJSON<{ data: MediaAsset }>(client.url(`/media/${id}`));\n return res.data;\n}\n\nexport async function uploadMedia(\n client: BetterCMSAdminClient,\n file: File,\n metadata?: MediaMetadata,\n): Promise<MediaAsset> {\n const formData = new FormData();\n formData.append(\"file\", file);\n if (metadata?.alt) formData.append(\"alt\", metadata.alt);\n if (metadata?.caption) formData.append(\"caption\", metadata.caption);\n\n const res = await client.fetchJSON<{ data: MediaAsset }>(client.url(\"/media\"), {\n method: \"POST\",\n body: formData as unknown as string,\n });\n return res.data;\n}\n\nexport async function deleteMedia(\n client: BetterCMSAdminClient,\n id: string,\n): Promise<void> {\n await client.fetchJSON(client.url(`/media/${id}`), { method: \"DELETE\" });\n}\n","/**\n * Admin forms methods.\n * @see openspec/changes/flo-6-backend-sdk-admin/specs/sdk-admin-client/spec.md\n */\n\nimport type { BetterCMSAdminClient } from \"../../admin-client.js\";\nimport type { Form } from \"@bettercms-ai/types\";\n\nexport interface FormListOptions {\n page?: number;\n limit?: number;\n}\n\nexport interface CreateFormInput {\n name: string;\n description?: string;\n fields?: FormFieldInput[];\n submitLabel?: string;\n successMessage?: string;\n redirectUrl?: string;\n webhookUrl?: string;\n}\n\nexport interface FormFieldInput {\n key: string;\n label: string;\n type: \"text\" | \"email\" | \"textarea\" | \"select\" | \"checkbox\" | \"number\";\n placeholder?: string;\n required?: boolean;\n options?: string[];\n}\n\nexport interface UpdateFormInput extends Partial<Omit<CreateFormInput, \"fields\">> {\n fields?: FormFieldInput[];\n}\n\nexport interface FormsAdmin {\n list(opts?: FormListOptions): Promise<Form[]>;\n get(id: string): Promise<Form>;\n create(data: CreateFormInput): Promise<Form>;\n update(id: string, data: UpdateFormInput): Promise<Form>;\n delete(id: string): Promise<void>;\n}\n\nexport async function listForms(\n client: BetterCMSAdminClient,\n opts?: FormListOptions,\n): Promise<Form[]> {\n const p = new URLSearchParams();\n if (opts?.page != null) p.set(\"page\", String(opts.page));\n if (opts?.limit != null) p.set(\"limit\", String(opts.limit));\n const qs = p.toString() ? `?${p}` : \"\";\n const res = await client.fetchJSON<{ data: Form[]; meta: { page: number; limit: number; total: number } }>(\n client.url(`/forms${qs}`),\n );\n return res.data;\n}\n\nexport async function getForm(\n client: BetterCMSAdminClient,\n id: string,\n): Promise<Form> {\n const res = await client.fetchJSON<{ data: Form }>(client.url(`/forms/${id}`));\n return res.data;\n}\n\nexport async function createForm(\n client: BetterCMSAdminClient,\n data: CreateFormInput,\n): Promise<Form> {\n const res = await client.fetchJSON<{ data: Form }>(client.url(\"/forms\"), {\n method: \"POST\",\n body: JSON.stringify(data),\n });\n return res.data;\n}\n\nexport async function updateForm(\n client: BetterCMSAdminClient,\n id: string,\n data: UpdateFormInput,\n): Promise<Form> {\n const res = await client.fetchJSON<{ data: Form }>(client.url(`/forms/${id}`), {\n method: \"PATCH\",\n body: JSON.stringify(data),\n });\n return res.data;\n}\n\nexport async function deleteForm(\n client: BetterCMSAdminClient,\n id: string,\n): Promise<void> {\n await client.fetchJSON(client.url(`/forms/${id}`), { method: \"DELETE\" });\n}\n","/**\n * Admin submissions methods.\n * @see openspec/changes/flo-6-backend-sdk-admin/specs/sdk-admin-client/spec.md\n */\n\nimport type { BetterCMSAdminClient } from \"../../admin-client.js\";\nimport type { FormSubmission } from \"@bettercms-ai/types\";\n\nexport interface SubmissionListOptions {\n page?: number;\n limit?: number;\n}\n\nexport interface SubmissionsAdmin {\n list(opts?: SubmissionListOptions): Promise<FormSubmission[]>;\n get(id: string): Promise<FormSubmission>;\n delete(id: string): Promise<void>;\n}\n\nexport async function listSubmissions(\n client: BetterCMSAdminClient,\n opts?: SubmissionListOptions,\n): Promise<FormSubmission[]> {\n const p = new URLSearchParams();\n if (opts?.page != null) p.set(\"page\", String(opts.page));\n if (opts?.limit != null) p.set(\"limit\", String(opts.limit));\n const qs = p.toString() ? `?${p}` : \"\";\n const res = await client.fetchJSON<{ data: FormSubmission[]; meta: { page: number; limit: number; total: number } }>(\n client.url(`/submissions${qs}`),\n );\n return res.data;\n}\n\nexport async function getSubmission(\n client: BetterCMSAdminClient,\n id: string,\n): Promise<FormSubmission> {\n const res = await client.fetchJSON<{ data: FormSubmission }>(client.url(`/submissions/${id}`));\n return res.data;\n}\n\nexport async function deleteSubmission(\n client: BetterCMSAdminClient,\n id: string,\n): Promise<void> {\n await client.fetchJSON(client.url(`/submissions/${id}`), { method: \"DELETE\" });\n}\n","/**\n * Admin workspaces methods.\n * @see openspec/changes/flo-6-backend-sdk-admin/specs/sdk-admin-client/spec.md\n */\n\nimport type { BetterCMSAdminClient } from \"../../admin-client.js\";\nimport type { Workspace } from \"@bettercms-ai/types\";\n\nexport interface WorkspacesAdmin {\n list(): Promise<Workspace[]>;\n get(id: string): Promise<Workspace>;\n create(data: CreateWorkspaceInput): Promise<Workspace>;\n update(id: string, data: UpdateWorkspaceInput): Promise<Workspace>;\n delete(id: string): Promise<void>;\n}\n\nexport interface CreateWorkspaceInput {\n name: string;\n slug: string;\n customDomain?: string;\n planId: string;\n}\n\nexport interface UpdateWorkspaceInput {\n name?: string;\n slug?: string;\n customDomain?: string | null;\n}\n\nexport async function listWorkspaces(\n client: BetterCMSAdminClient,\n): Promise<Workspace[]> {\n const res = await client.fetchJSON<{ data: Workspace[] }>(client.url(\"/workspaces\"));\n return res.data;\n}\n\nexport async function getWorkspace(\n client: BetterCMSAdminClient,\n id: string,\n): Promise<Workspace> {\n const res = await client.fetchJSON<{ data: Workspace }>(client.url(`/workspaces/${id}`));\n return res.data;\n}\n\nexport async function createWorkspace(\n client: BetterCMSAdminClient,\n data: CreateWorkspaceInput,\n): Promise<Workspace> {\n const res = await client.fetchJSON<{ data: Workspace }>(client.url(\"/workspaces\"), {\n method: \"POST\",\n body: JSON.stringify(data),\n });\n return res.data;\n}\n\nexport async function updateWorkspace(\n client: BetterCMSAdminClient,\n id: string,\n data: UpdateWorkspaceInput,\n): Promise<Workspace> {\n const res = await client.fetchJSON<{ data: Workspace }>(client.url(`/workspaces/${id}`), {\n method: \"PATCH\",\n body: JSON.stringify(data),\n });\n return res.data;\n}\n\nexport async function deleteWorkspace(\n client: BetterCMSAdminClient,\n id: string,\n): Promise<void> {\n await client.fetchJSON(client.url(`/workspaces/${id}`), { method: \"DELETE\" });\n}\n","/**\n * Admin API keys methods.\n * @see openspec/changes/flo-6-backend-sdk-admin/specs/sdk-admin-client/spec.md\n */\n\nimport type { BetterCMSAdminClient } from \"../../admin-client.js\";\nimport type { ApiKey, ApiKeyPermission, ApiKeyTokenType } from \"@bettercms-ai/types\";\n\n/** ApiKey with raw key — returned only on creation or regeneration. */\nexport interface ApiKeyWithRaw extends ApiKey {\n key: string;\n}\n\nexport interface CreateApiKeyInput {\n name: string;\n permissions?: ApiKeyPermission[];\n tokenType?: ApiKeyTokenType;\n description?: string;\n expiresAt?: string; // ISO 8601\n rateLimit?: number;\n}\n\nexport interface UpdateApiKeyInput {\n name?: string;\n permissions?: ApiKeyPermission[];\n tokenType?: ApiKeyTokenType;\n description?: string | null;\n expiresAt?: string | null;\n rateLimit?: number | null;\n}\n\nexport interface ApiKeyUsage {\n keyId: string;\n name: string;\n lastUsedAt: string | null;\n createdAt: string;\n totalRequests: number;\n}\n\nexport interface ApiKeysAdmin {\n list(): Promise<ApiKey[]>;\n create(data: CreateApiKeyInput): Promise<ApiKeyWithRaw>;\n update(id: string, data: UpdateApiKeyInput): Promise<ApiKey>;\n regenerate(id: string): Promise<ApiKeyWithRaw>;\n usage(id: string): Promise<ApiKeyUsage>;\n revoke(id: string): Promise<void>;\n}\n\nexport async function listApiKeys(\n client: BetterCMSAdminClient,\n): Promise<ApiKey[]> {\n const res = await client.fetchJSON<{ data: ApiKey[] }>(client.url(\"/api-keys\"));\n return res.data;\n}\n\nexport async function createApiKey(\n client: BetterCMSAdminClient,\n data: CreateApiKeyInput,\n): Promise<ApiKeyWithRaw> {\n const res = await client.fetchJSON<{ data: ApiKeyWithRaw }>(client.url(\"/api-keys\"), {\n method: \"POST\",\n body: JSON.stringify(data),\n });\n return res.data;\n}\n\nexport async function updateApiKey(\n client: BetterCMSAdminClient,\n id: string,\n data: UpdateApiKeyInput,\n): Promise<ApiKey> {\n const res = await client.fetchJSON<{ data: ApiKey }>(client.url(`/api-keys/${id}`), {\n method: \"PATCH\",\n body: JSON.stringify(data),\n });\n return res.data;\n}\n\nexport async function regenerateApiKey(\n client: BetterCMSAdminClient,\n id: string,\n): Promise<ApiKeyWithRaw> {\n const res = await client.fetchJSON<{ data: ApiKeyWithRaw }>(client.url(`/api-keys/${id}/regenerate`), {\n method: \"POST\",\n });\n return res.data;\n}\n\nexport async function getApiKeyUsage(\n client: BetterCMSAdminClient,\n id: string,\n): Promise<ApiKeyUsage> {\n const res = await client.fetchJSON<{ data: ApiKeyUsage }>(client.url(`/api-keys/${id}/usage`));\n return res.data;\n}\n\nexport async function revokeApiKey(\n client: BetterCMSAdminClient,\n id: string,\n): Promise<void> {\n await client.fetchJSON(client.url(`/api-keys/${id}`), { method: \"DELETE\" });\n}","/**\n * Admin members methods.\n * @see openspec/changes/flo-6-backend-sdk-admin/specs/sdk-admin-client/spec.md\n */\n\nimport type { BetterCMSAdminClient } from \"../../admin-client.js\";\n\nexport type MemberRole = \"owner\" | \"admin\" | \"editor\" | \"viewer\";\n\nexport interface Member {\n id: string;\n userId: string;\n email: string | null;\n name: string | null;\n role: MemberRole;\n joinedAt: string;\n}\n\nexport interface PendingInvite {\n id: string;\n email: string;\n role: MemberRole;\n expiresAt: string;\n}\n\nexport interface MembersAdmin {\n list(workspaceId: string, opts?: { page?: number; limit?: number }): Promise<Member[]>;\n get(workspaceId: string, memberId: string): Promise<Member>;\n invite(workspaceId: string, data: { email: string; role: MemberRole }): Promise<PendingInvite>;\n updateRole(workspaceId: string, memberId: string, role: MemberRole): Promise<Member>;\n remove(workspaceId: string, memberId: string): Promise<void>;\n}\n\nfunction qs(opts?: { page?: number; limit?: number }): string {\n const p = new URLSearchParams();\n if (opts?.page != null) p.set(\"page\", String(opts.page));\n if (opts?.limit != null) p.set(\"limit\", String(opts.limit));\n return p.toString() ? `?${p}` : \"\";\n}\n\nexport async function listMembers(\n client: BetterCMSAdminClient,\n workspaceId: string,\n opts?: { page?: number; limit?: number },\n): Promise<Member[]> {\n const res = await client.fetchJSON<{ data: Member[]; meta: { page: number; limit: number; total: number } }>(\n client.url(`/workspaces/${workspaceId}/members${qs(opts)}`),\n );\n return res.data;\n}\n\nexport async function getMember(\n client: BetterCMSAdminClient,\n workspaceId: string,\n memberId: string,\n): Promise<Member> {\n const res = await client.fetchJSON<{ data: Member }>(\n client.url(`/workspaces/${workspaceId}/members/${memberId}`),\n );\n return res.data;\n}\n\nexport async function inviteMember(\n client: BetterCMSAdminClient,\n workspaceId: string,\n data: { email: string; role: MemberRole },\n): Promise<PendingInvite> {\n const res = await client.fetchJSON<{ data: PendingInvite }>(\n client.url(`/workspaces/${workspaceId}/members/invite`),\n { method: \"POST\", body: JSON.stringify(data) },\n );\n return res.data;\n}\n\nexport async function updateMemberRole(\n client: BetterCMSAdminClient,\n workspaceId: string,\n memberId: string,\n role: MemberRole,\n): Promise<Member> {\n const res = await client.fetchJSON<{ data: Member }>(\n client.url(`/workspaces/${workspaceId}/members/${memberId}`),\n { method: \"PATCH\", body: JSON.stringify({ role }) },\n );\n return res.data;\n}\n\nexport async function removeMember(\n client: BetterCMSAdminClient,\n workspaceId: string,\n memberId: string,\n): Promise<void> {\n await client.fetchJSON(\n client.url(`/workspaces/${workspaceId}/members/${memberId}`),\n { method: \"DELETE\" },\n );\n}\n","/**\n * Public forms — the headless integration surface for sites built on or imported\n * into BetterCMS (the \"render it yourself\" model, like Sanity's delivery API).\n *\n * Form definitions ship in the build-time content snapshot (`bcms-content.json` →\n * `forms` / `turnstileSiteKey`) and from `GET /api/v1/delivery/:workspace/forms`.\n * A site renders them with its own components (see `@bettercms-ai/next`'s <BcmsForm>)\n * and posts here. No API key — the endpoint is Turnstile-gated (Webflow model).\n *\n * This module is the single source of truth for the delivered form shape + the\n * pure logic (conditional visibility, initial values) the renderers share, so the\n * vanilla embed and the React component never drift.\n */\n\nimport { BetterCMSError, ErrorCodes } from \"./errors.js\";\n\n/** Field types the delivery API serializes (superset of the admin builder). */\nexport type DeliveryFormFieldType =\n | \"text\"\n | \"email\"\n | \"phone\"\n | \"url\"\n | \"number\"\n | \"date\"\n | \"textarea\"\n | \"select\"\n | \"checkbox\"\n | \"consent\"\n | \"hidden\";\n\nexport interface DeliveryFormField {\n key: string;\n label: string;\n type: DeliveryFormFieldType;\n placeholder?: string;\n required?: boolean;\n options?: string[];\n defaultValue?: string;\n /** Conditional visibility — render this field only when another field equals `equals`. */\n showIf?: { field: string; equals: string };\n}\n\n/** A form as delivered to a published/imported site. Mirrors the delivery `/forms` payload. */\nexport interface DeliveryForm {\n id: string;\n name: string;\n fields: DeliveryFormField[];\n submitLabel?: string;\n successMessage?: string;\n redirectUrl?: string;\n turnstileEnabled?: boolean;\n honeypotField?: string | null;\n}\n\nexport type FormValue = string | boolean;\nexport type FormValues = Record<string, FormValue>;\n\nconst DEFAULT_BASE_URL = \"https://api.bettercms.ai\";\n\n/**\n * Conditional visibility. A `showIf` field is shown only when its trigger field's\n * current value equals the target; non-conditional fields are always shown. The\n * renderer must skip hidden fields when collecting/validating so a hidden required\n * field never blocks submit.\n */\nexport function shouldShowField(field: DeliveryFormField, values: FormValues): boolean {\n if (!field.showIf) return true;\n return String(values[field.showIf.field] ?? \"\") === field.showIf.equals;\n}\n\n/**\n * Build the initial value map: checkbox/consent default to false, every other field\n * to its `defaultValue`, with `prefill` (e.g. URL query params) taking precedence.\n */\nexport function formInitialValues(\n form: DeliveryForm,\n prefill: Record<string, string> = {},\n): FormValues {\n const values: FormValues = {};\n for (const field of form.fields) {\n if (field.type === \"checkbox\" || field.type === \"consent\") {\n values[field.key] = false;\n } else {\n values[field.key] = prefill[field.key] ?? field.defaultValue ?? \"\";\n }\n }\n return values;\n}\n\nexport interface SubmitFormOptions {\n formId: string;\n data: FormValues;\n /** Cloudflare Turnstile token; required when the form has `turnstileEnabled`. */\n turnstileToken?: string;\n /** API origin. Defaults to https://api.bettercms.ai. */\n baseUrl?: string;\n /** Injectable fetch for tests / non-browser runtimes. */\n fetchImpl?: typeof fetch;\n}\n\nexport interface SubmitFormResult {\n id: string;\n}\n\n/** A submit failure that carries per-field validation messages from the API (HTTP 400). */\nexport type FormSubmitError = BetterCMSError & { fieldErrors?: Record<string, string> };\n\n/**\n * Submit a public form. Resolves with the new submission id, or throws a\n * BetterCMSError — field-level validation errors are attached as `.fieldErrors`.\n */\nexport async function submitForm(opts: SubmitFormOptions): Promise<SubmitFormResult> {\n const baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n const doFetch = opts.fetchImpl ?? globalThis.fetch;\n const body: Record<string, unknown> = { data: opts.data };\n if (opts.turnstileToken) body[\"cf-turnstile-response\"] = opts.turnstileToken;\n\n let res: Response;\n try {\n res = await doFetch(`${baseUrl}/api/v1/forms/public/${opts.formId}/submissions`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n } catch (err) {\n throw new BetterCMSError(\n `Network error: ${err instanceof Error ? err.message : String(err)}`,\n 0,\n ErrorCodes.NETWORK_ERROR,\n );\n }\n\n if (!res.ok) {\n // `.from` reads the body for message/code; clone so we can still read `errors`.\n const error = (await BetterCMSError.from(res.clone())) as FormSubmitError;\n const body = (await res.json().catch(() => ({}))) as { errors?: Record<string, string> };\n if (body.errors) error.fieldErrors = body.errors;\n throw error;\n }\n\n const json = (await res.json().catch(() => ({}))) as { id?: string | number };\n return { id: String(json.id ?? \"\") };\n}\n"],"mappings":"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","names":["createForm","getForm","listForms","updateForm","params","params","params","qs","params","DEFAULT_BASE_URL","DEFAULT_TIMEOUT","RETRY_STATUSES","RETRY_DELAYS","sleep","DEFAULT_BASE_URL","RETRY_STATUSES","RETRY_DELAYS","DEFAULT_TIMEOUT","sleep","params","DEFAULT_BASE_URL","params","qs","listForms","qs","getForm","createForm","updateForm","qs","qs","DEFAULT_BASE_URL","body"]}
|