@plenary/client 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/query.ts","../src/errors.ts","../src/client.ts","../src/webhook.ts"],"sourcesContent":["import type {\n Where,\n WhereCondition,\n FilterTree,\n Sort,\n Hydrate,\n ReadOptions,\n ListOptions,\n} from \"./types.js\";\n\n/** The known `where:` operators; anything else on a condition object is passed through. */\nconst OPERATORS = new Set([\n \"$eq\",\n \"$ne\",\n \"$lt\",\n \"$lte\",\n \"$gt\",\n \"$gte\",\n \"$in\",\n \"$nin\",\n \"$like\",\n \"$ilike\",\n \"$is_null\",\n]);\n\n/** A value is a condition when it's a plain object whose keys are all operators. */\nfunction isCondition(value: unknown): value is WhereCondition {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n const keys = Object.keys(value);\n return keys.length > 0 && keys.every((k) => OPERATORS.has(k));\n}\n\nfunction encodeOperatorValue(op: string, value: unknown): string {\n if (op === \"$in\" || op === \"$nin\") {\n return Array.isArray(value) ? value.map(String).join(\",\") : String(value);\n }\n if (op === \"$is_null\") {\n return String(Boolean(value));\n }\n return String(value);\n}\n\nfunction appendWhere(params: URLSearchParams, where: Where): void {\n for (const [field, value] of Object.entries(where)) {\n if (isCondition(value)) {\n for (const [op, opValue] of Object.entries(value)) {\n params.append(`where:${field}.${op}`, encodeOperatorValue(op, opValue));\n }\n } else {\n // Bare value — the server assumes `$eq`.\n params.append(`where:${field}`, String(value));\n }\n }\n}\n\nfunction appendSort(params: URLSearchParams, sort: Sort): void {\n // Insertion order is the sort precedence (left-to-right).\n for (const [field, dir] of Object.entries(sort)) {\n params.append(`sort:${field}`, dir);\n }\n}\n\nfunction appendHydrate(params: URLSearchParams, hydrate: Hydrate): void {\n for (const [field, spec] of Object.entries(hydrate)) {\n params.append(`hydrate:${field}`, spec === \"*\" ? \"*\" : spec.join(\",\"));\n }\n}\n\n/** Base context every request carries: which site and locale. */\nexport interface QueryBase {\n siteKey: string;\n locale: string;\n}\n\nfunction appendCommon(params: URLSearchParams, base: QueryBase, opts: ReadOptions): void {\n params.set(\"site_key\", opts.siteKey ?? base.siteKey);\n params.set(\"locale\", opts.locale ?? base.locale);\n\n if (opts.include && opts.exclude) {\n throw new Error(\"plenary: `include` and `exclude` are mutually exclusive\");\n }\n if (opts.include?.length) params.set(\"include\", opts.include.join(\",\"));\n if (opts.exclude?.length) params.set(\"exclude\", opts.exclude.join(\",\"));\n if (opts.hydrate) appendHydrate(params, opts.hydrate);\n}\n\n/** Builds the query for a single-entry read (get / singleton). */\nexport function buildReadParams(base: QueryBase, opts: ReadOptions = {}): URLSearchParams {\n const params = new URLSearchParams();\n appendCommon(params, base, opts);\n return params;\n}\n\n/** Builds the query for a list read, including filters, sort, and pagination. */\nexport function buildListParams(base: QueryBase, opts: ListOptions = {}): URLSearchParams {\n const params = new URLSearchParams();\n appendCommon(params, base, opts);\n\n if (opts.where && opts.filters) {\n throw new Error(\"plenary: `where` and `filters` are mutually exclusive\");\n }\n if (opts.filters) {\n params.set(\"filters\", JSON.stringify(opts.filters satisfies FilterTree));\n } else if (opts.where) {\n appendWhere(params, opts.where);\n }\n\n if (opts.sort) appendSort(params, opts.sort);\n if (opts.limit !== undefined) params.set(\"limit\", String(opts.limit));\n if (opts.offset !== undefined) params.set(\"offset\", String(opts.offset));\n if (opts.count) params.set(\"count\", \"true\");\n\n return params;\n}\n","/** The server's error envelope: `{ error: { code, vars? } }`. */\ninterface ServerErrorBody {\n error?: { code?: string; vars?: Record<string, unknown> };\n}\n\n/** Base error for a non-2xx response from the CMS. */\nexport class PlenaryError extends Error {\n readonly status: number;\n /** The server's i18n error code (e.g. `entry_query_limit_exceeded`), if any. */\n readonly code: string;\n /** Interpolation variables the server attached to the code. */\n readonly vars?: Record<string, unknown>;\n\n constructor(status: number, code: string, vars?: Record<string, unknown>) {\n super(`Plenary request failed (${status}): ${code}`);\n this.name = \"PlenaryError\";\n this.status = status;\n this.code = code;\n this.vars = vars;\n }\n}\n\n/** A 404 — model or entry not found (or hidden by a private model). */\nexport class PlenaryNotFoundError extends PlenaryError {\n constructor(code: string, vars?: Record<string, unknown>) {\n super(404, code, vars);\n this.name = \"PlenaryNotFoundError\";\n }\n}\n\n/** A 400/422 — malformed query or invalid input. */\nexport class PlenaryValidationError extends PlenaryError {\n constructor(status: number, code: string, vars?: Record<string, unknown>) {\n super(status, code, vars);\n this.name = \"PlenaryValidationError\";\n }\n}\n\n/** A 403 — the key may not read the requested site/resource. */\nexport class PlenaryForbiddenError extends PlenaryError {\n constructor(code: string, vars?: Record<string, unknown>) {\n super(403, code, vars);\n this.name = \"PlenaryForbiddenError\";\n }\n}\n\n/** Builds the right error subclass from a failed response's status and body. */\nexport function errorFromResponse(status: number, body: unknown): PlenaryError {\n const parsed = body as ServerErrorBody | null;\n const code = parsed?.error?.code ?? `http_${status}`;\n const vars = parsed?.error?.vars;\n switch (status) {\n case 404:\n return new PlenaryNotFoundError(code, vars);\n case 403:\n return new PlenaryForbiddenError(code, vars);\n case 400:\n case 422:\n return new PlenaryValidationError(status, code, vars);\n default:\n return new PlenaryError(status, code, vars);\n }\n}\n","import type {\n ClientConfig,\n Entry,\n ReadOptions,\n ListOptions,\n ListResult,\n PublicFormDefinition,\n FormSubmitOptions,\n FormSubmitResult,\n MediaDetail,\n} from \"./types.js\";\nimport { buildReadParams, buildListParams, type QueryBase } from \"./query.js\";\nimport { errorFromResponse } from \"./errors.js\";\n\n/** The content client returned by {@link createClient}. */\nexport interface PlenaryClient {\n /** Fetch a singleton model's entry. */\n getSingleton<TData = Record<string, unknown>>(\n modelKey: string,\n opts?: ReadOptions,\n ): Promise<Entry<TData>>;\n\n /** Fetch one entry of a collection/page by slug or UUID. */\n getEntry<TData = Record<string, unknown>>(\n modelKey: string,\n slugOrId: string,\n opts?: ReadOptions,\n ): Promise<Entry<TData>>;\n\n /** List entries of a collection/page model. */\n listEntries<TData = Record<string, unknown>>(\n modelKey: string,\n opts?: ListOptions,\n ): Promise<ListResult<TData>>;\n\n /**\n * Fetch a form's render-safe definition — the field list a renderer needs,\n * readable with a public delivery key.\n */\n getForm(formKey: string): Promise<PublicFormDefinition>;\n\n /** Submit a public form. */\n submitForm(\n formKey: string,\n data: Record<string, unknown>,\n opts?: FormSubmitOptions,\n ): Promise<FormSubmitResult>;\n\n /**\n * Fetch a media item's detail (URLs + variants). Requires a key that may read\n * media; a public delivery key cannot, so this is used in authoring/preview\n * contexts or by sites configured with a media-capable key.\n */\n getMedia(mediaId: string): Promise<MediaDetail>;\n}\n\nfunction joinUrl(baseUrl: string, path: string): string {\n return `${baseUrl.replace(/\\/+$/, \"\")}${path}`;\n}\n\nexport function createClient(config: ClientConfig): PlenaryClient {\n const base: QueryBase = { siteKey: config.siteKey, locale: config.locale };\n const doFetch = config.fetch ?? globalThis.fetch;\n\n async function request<T>(\n method: string,\n path: string,\n params: URLSearchParams,\n body?: unknown,\n ): Promise<{ data: T; response: Response }> {\n const url = `${joinUrl(config.baseUrl, path)}?${params.toString()}`;\n const headers: Record<string, string> = { \"X-API-KEY\": config.apiKey };\n if (body !== undefined) headers[\"Content-Type\"] = \"application/json\";\n\n const response = await doFetch(url, {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n\n const parsed = response.status === 204 ? null : await response.json().catch(() => null);\n if (!response.ok) {\n throw errorFromResponse(response.status, parsed);\n }\n return { data: parsed as T, response };\n }\n\n return {\n async getSingleton<TData>(modelKey: string, opts: ReadOptions = {}) {\n const params = buildReadParams(base, opts);\n const { data } = await request<Entry<TData>>(\n \"GET\",\n `/api/v1/content/${encodeURIComponent(modelKey)}`,\n params,\n );\n return data;\n },\n\n async getEntry<TData>(modelKey: string, slugOrId: string, opts: ReadOptions = {}) {\n const params = buildReadParams(base, opts);\n const { data } = await request<Entry<TData>>(\n \"GET\",\n `/api/v1/content/${encodeURIComponent(modelKey)}/${encodeURIComponent(slugOrId)}`,\n params,\n );\n return data;\n },\n\n async listEntries<TData>(modelKey: string, opts: ListOptions = {}) {\n const params = buildListParams(base, opts);\n const { data, response } = await request<Entry<TData>[]>(\n \"GET\",\n `/api/v1/content/${encodeURIComponent(modelKey)}`,\n params,\n );\n const result: ListResult<TData> = { items: data };\n const total = response.headers.get(\"X-Total-Count\");\n if (total !== null) result.total = Number(total);\n return result;\n },\n\n async getForm(formKey: string) {\n const { data } = await request<PublicFormDefinition>(\n \"GET\",\n `/api/v1/forms/${encodeURIComponent(formKey)}`,\n new URLSearchParams(),\n );\n return data;\n },\n\n async submitForm(\n formKey: string,\n data: Record<string, unknown>,\n opts: FormSubmitOptions = {},\n ) {\n const params = new URLSearchParams();\n params.set(\"site_key\", opts.siteKey ?? base.siteKey);\n const body: Record<string, unknown> = { data };\n if (opts.website !== undefined) body.website = opts.website;\n if (opts.ts !== undefined) body.ts = opts.ts;\n const { data: result } = await request<FormSubmitResult>(\n \"POST\",\n `/api/v1/forms/${encodeURIComponent(formKey)}/entries`,\n params,\n body,\n );\n return result;\n },\n\n async getMedia(mediaId: string) {\n const { data } = await request<MediaDetail>(\n \"GET\",\n `/api/v1/media/${encodeURIComponent(mediaId)}`,\n new URLSearchParams(),\n );\n return data;\n },\n };\n}\n","/**\n * Webhook consumer helpers: the payload types Plenary POSTs (docs/WEBHOOKS.md)\n * and framework-neutral verification/parsing. Plenary does not sign requests\n * yet; verification is a shared-secret comparison against a header or query\n * parameter. When HMAC signing ships, it slots in here without changing the\n * call sites.\n */\n\n/** The five entry lifecycle events a content-model webhook can subscribe to. */\nexport type EntryWebhookEvent =\n | \"entry.created\"\n | \"entry.updated\"\n | \"entry.published\"\n | \"entry.unpublished\"\n | \"entry.deleted\";\n\nexport const ENTRY_WEBHOOK_EVENTS: readonly EntryWebhookEvent[] = [\n \"entry.created\",\n \"entry.updated\",\n \"entry.published\",\n \"entry.unpublished\",\n \"entry.deleted\",\n];\n\n/** The event carried by the console's Test button. The body is otherwise an\n * ordinary entry or form payload, built from the model's most recent entry. */\nexport const WEBHOOK_TEST_EVENT = \"webhook.test\";\n\n/** Who caused the event. `label` survives the actor's deletion. */\nexport interface WebhookActor {\n type: \"user\" | \"api_key\" | \"system\";\n id?: string;\n label: string;\n}\n\n/** The entry's identity. Field selection never touches these. */\nexport interface WebhookEntryRef {\n id: string;\n site_key?: string;\n locale?: string;\n slug?: string;\n /** Directory path of the entry's folder (\"/\" at the model root). Does NOT\n * include the entry's own slug — join them to build a URL. */\n path?: string;\n status?: string;\n created_at?: string;\n updated_at?: string;\n published_at?: string;\n}\n\n/** A form entry's identity: no slug, locale, path, or publish state. */\nexport interface WebhookFormEntryRef {\n id: string;\n site_key?: string;\n status?: string;\n created_at?: string;\n source?: { ip?: string; user_agent?: string; referer?: string };\n}\n\n/** Payload for every `entry.*` event (and entry-shaped `webhook.test`). */\nexport interface EntryWebhookPayload<TData = Record<string, unknown>> {\n event: EntryWebhookEvent | typeof WEBHOOK_TEST_EVENT;\n delivery_id: string;\n occurred_at: string;\n webhook: { id: string; name?: string };\n model: { id: string; key?: string };\n entry: WebhookEntryRef;\n actor: WebhookActor;\n /** Paths that differ from the previous revision. Always present; empty for\n * `entry.created` and `entry.deleted`. */\n changed: string[];\n revision_id?: string;\n /** Field values per the webhook's field selection; absent for \"no field data\". */\n data?: TData;\n}\n\n/** Payload for `form.submitted` (and form-shaped `webhook.test`). */\nexport interface FormWebhookPayload<TData = Record<string, unknown>> {\n event: \"form.submitted\" | typeof WEBHOOK_TEST_EVENT;\n delivery_id: string;\n occurred_at: string;\n webhook: { id: string; name?: string };\n form: { id: string; key?: string };\n form_entry: WebhookFormEntryRef;\n data?: TData;\n}\n\nexport type WebhookPayload = EntryWebhookPayload | FormWebhookPayload;\n\nexport function isEntryWebhookPayload(p: WebhookPayload): p is EntryWebhookPayload {\n return \"entry\" in p;\n}\n\nexport function isFormWebhookPayload(p: WebhookPayload): p is FormWebhookPayload {\n return \"form_entry\" in p;\n}\n\n/** A request that is not a valid webhook delivery. `status` is the HTTP status\n * an endpoint should answer with — 4xx makes the delivery fail fast in the\n * console's delivery log instead of being retried for seven hours. */\nexport class PlenaryWebhookError extends Error {\n readonly status: number;\n\n constructor(status: number, message: string) {\n super(message);\n this.name = \"PlenaryWebhookError\";\n this.status = status;\n }\n}\n\n/** Constant-time comparison of a provided secret against the expected one. */\nexport function verifyWebhookSecret(\n provided: string | null | undefined,\n secret: string,\n): boolean {\n if (typeof provided !== \"string\") return false;\n const enc = new TextEncoder();\n const a = enc.encode(provided);\n const b = enc.encode(secret);\n let diff = a.length ^ b.length;\n const len = Math.max(a.length, b.length);\n for (let i = 0; i < len; i++) diff |= (a[i] ?? 0) ^ (b[i] ?? 0);\n return diff === 0;\n}\n\n/** Shape-checks a parsed JSON body and types it. Throws {@link PlenaryWebhookError}\n * (400) for anything that is not a Plenary webhook payload. */\nexport function parseWebhookPayload(body: unknown): WebhookPayload {\n const p = body as Record<string, unknown> | null;\n if (\n p === null ||\n typeof p !== \"object\" ||\n typeof p[\"event\"] !== \"string\" ||\n typeof p[\"delivery_id\"] !== \"string\" ||\n !(\"entry\" in p || \"form_entry\" in p)\n ) {\n throw new PlenaryWebhookError(400, \"Not a Plenary webhook payload\");\n }\n return p as unknown as WebhookPayload;\n}\n\n/** Options for {@link parseWebhookRequest}. */\nexport interface ParseWebhookOptions {\n /** The shared secret configured on the webhook (as a secret header or query\n * parameter in the console). */\n secret: string;\n /** Header the secret arrives in. Default `x-plenary-secret`. */\n secretHeader?: string;\n /** Query parameter checked when the header is absent. Default `secret`. */\n secretQuery?: string;\n}\n\n/**\n * Verifies and parses a webhook delivery from a Fetch-API `Request`:\n * POST only, secret in the configured header or query parameter, JSON body of\n * one of the two payload shapes. Throws {@link PlenaryWebhookError} with the\n * status the endpoint should answer (405, 401, or 400).\n */\nexport async function parseWebhookRequest(\n request: Request,\n options: ParseWebhookOptions,\n): Promise<WebhookPayload> {\n if (request.method !== \"POST\") {\n throw new PlenaryWebhookError(405, \"Method not allowed\");\n }\n const header = options.secretHeader ?? \"x-plenary-secret\";\n const query = options.secretQuery ?? \"secret\";\n const provided =\n request.headers.get(header) ?? new URL(request.url).searchParams.get(query);\n if (!verifyWebhookSecret(provided, options.secret)) {\n throw new PlenaryWebhookError(401, \"Invalid webhook secret\");\n }\n const body = await request.json().catch(() => {\n throw new PlenaryWebhookError(400, \"Body is not valid JSON\");\n });\n return parseWebhookPayload(body);\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@plenary/client",
3
+ "version": "0.1.0",
4
+ "description": "Plenary framework-free API client: content fetch, form submission, and query builder. (Phase 2)",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "main": "./dist/index.cjs",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "require": "./dist/index.cjs"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "dependencies": {
21
+ "@plenary/core": "0.1.0"
22
+ },
23
+ "license": "MIT",
24
+ "scripts": {
25
+ "build": "tsup",
26
+ "dev": "tsup --watch",
27
+ "test": "vitest run --passWithNoTests",
28
+ "typecheck": "tsc --noEmit"
29
+ }
30
+ }