v0.3.0 — entitlements catalog in PublicPoliciesResponse
Mirrors the Keysat migration 0014 server-side change. The product
object on listPublicPolicies() now includes entitlementsCatalog —
the closed list of {slug, name, description} the operator declared
on the product. SDK consumers' in-app tier pickers can render the
human-readable name ("AI summaries") with the description as a
tooltip instead of the raw slug ("ai_summaries").
New exports:
- EntitlementDef type
- PublicPoliciesResponse.product.entitlementsCatalog: EntitlementDef[]
Empty array on legacy products that don't have a catalog yet —
SDK consumers fall back to rendering the raw policy.entitlements
slugs directly. No breaking change to existing consumers.
Bumps to 0.3.0 minor since the surface is purely additive.
15/15 crosscheck tests still pass.
This commit is contained in:
@@ -16,6 +16,7 @@ export {
|
||||
type StartPurchaseOptions,
|
||||
type PublicPolicy,
|
||||
type PublicPoliciesResponse,
|
||||
type EntitlementDef,
|
||||
type RedeemFreeOptions,
|
||||
type RedeemFreeResponse,
|
||||
} from './online.js'
|
||||
|
||||
@@ -143,12 +143,35 @@ export interface PublicPolicy {
|
||||
trialDays: number
|
||||
}
|
||||
|
||||
/**
|
||||
* One entry in a product's entitlements catalog. Defined by the
|
||||
* operator in admin (Keysat migration 0014). Use
|
||||
* {@link EntitlementDef.name} as the human-readable label when
|
||||
* rendering an in-app tier picker — e.g. "AI summaries" instead
|
||||
* of the raw `ai_summaries` slug. {@link EntitlementDef.description}
|
||||
* is a one-sentence tooltip; may be empty.
|
||||
*/
|
||||
export interface EntitlementDef {
|
||||
slug: string
|
||||
name: string
|
||||
description: string
|
||||
}
|
||||
|
||||
export interface PublicPoliciesResponse {
|
||||
product: {
|
||||
slug: string
|
||||
name: string
|
||||
description: string
|
||||
basePriceSats: number
|
||||
/**
|
||||
* Closed list of entitlements this product offers, with display
|
||||
* names + descriptions for buyer-facing rendering. Empty array
|
||||
* when the operator hasn't defined a catalog (legacy "free-text"
|
||||
* mode — render the raw slugs from {@link PublicPolicy.entitlements}
|
||||
* directly, or replace underscores with spaces for a quick
|
||||
* fallback).
|
||||
*/
|
||||
entitlementsCatalog: EntitlementDef[]
|
||||
}
|
||||
policies: PublicPolicy[]
|
||||
}
|
||||
@@ -296,6 +319,13 @@ export class Client {
|
||||
name: product.name as string,
|
||||
description: (product.description as string) ?? '',
|
||||
basePriceSats: product.base_price_sats as number,
|
||||
entitlementsCatalog: (
|
||||
(product.entitlements_catalog as Array<Record<string, unknown>>) ?? []
|
||||
).map((c) => ({
|
||||
slug: c.slug as string,
|
||||
name: (c.name as string) ?? (c.slug as string),
|
||||
description: (c.description as string) ?? '',
|
||||
})),
|
||||
},
|
||||
policies: policies.map((p) => ({
|
||||
slug: p.slug as string,
|
||||
|
||||
Reference in New Issue
Block a user