expo-iap 5.2.3 → 5.2.4
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/build/kit-api.d.ts.map +1 -1
- package/build/kit-api.js +13 -38
- package/build/kit-api.js.map +1 -1
- package/openiap-versions.json +1 -1
- package/package.json +1 -1
- package/src/kit-api.ts +23 -46
package/build/kit-api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kit-api.d.ts","sourceRoot":"","sources":["../src/kit-api.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"kit-api.d.ts","sourceRoot":"","sources":["../src/kit-api.ts"],"names":[],"mappings":"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"}
|
package/build/kit-api.js
CHANGED
|
@@ -4,15 +4,11 @@
|
|
|
4
4
|
// reachable from both LLM tools and end-user apps without each
|
|
5
5
|
// duplicating the URL layout.
|
|
6
6
|
const DEFAULT_BASE_URL = "https://kit.openiap.dev";
|
|
7
|
-
// Merge
|
|
8
|
-
// optionally `content-type`). When
|
|
9
|
-
//
|
|
10
|
-
// `Headers`
|
|
11
|
-
//
|
|
12
|
-
// the operator wires up `fetchImpl` without a `Headers` polyfill —
|
|
13
|
-
// we fall back to a case-insensitive merge into a plain record so
|
|
14
|
-
// the request still goes through. Either way, caller-set values take
|
|
15
|
-
// precedence over kit defaults.
|
|
7
|
+
// Merge the request's internal headers with kit defaults (`accept`,
|
|
8
|
+
// optionally `content-type`). When `Headers` is missing — older React
|
|
9
|
+
// Native builds where the operator wires up `fetchImpl` without a
|
|
10
|
+
// `Headers` polyfill — the internal request sites use plain records,
|
|
11
|
+
// so a small case-insensitive merge is sufficient.
|
|
16
12
|
function mergeHeaders(callerHeaders, hasBody) {
|
|
17
13
|
if (typeof Headers === "function") {
|
|
18
14
|
const merged = new Headers(callerHeaders);
|
|
@@ -23,37 +19,17 @@ function mergeHeaders(callerHeaders, hasBody) {
|
|
|
23
19
|
}
|
|
24
20
|
return merged;
|
|
25
21
|
}
|
|
26
|
-
// Plain-object fallback path. Build a case-insensitive name map
|
|
27
|
-
//
|
|
28
|
-
// or plain record) and re-emit as a record `fetchImpl` accepts.
|
|
22
|
+
// Plain-object fallback path. Build a case-insensitive name map and
|
|
23
|
+
// re-emit it as a record `fetchImpl` accepts.
|
|
29
24
|
const lower = new Map();
|
|
30
25
|
const setIfAbsent = (name, value) => {
|
|
31
26
|
const key = name.toLowerCase();
|
|
32
27
|
if (!lower.has(key))
|
|
33
28
|
lower.set(key, { name, value });
|
|
34
29
|
};
|
|
35
|
-
const setForce = (name, value) => {
|
|
36
|
-
const key = name.toLowerCase();
|
|
37
|
-
lower.set(key, { name, value });
|
|
38
|
-
};
|
|
39
30
|
if (callerHeaders) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
setForce(name, value);
|
|
43
|
-
}
|
|
44
|
-
else if (typeof callerHeaders.forEach === "function") {
|
|
45
|
-
// `Headers`-like (without being our `typeof Headers === "function"`
|
|
46
|
-
// global). RN polyfills sometimes attach `Headers` only to
|
|
47
|
-
// request/response instances rather than the global scope.
|
|
48
|
-
// Standard signature is `forEach((value, key, parent))`; we
|
|
49
|
-
// bind the first two positionally so a polyfill that omits
|
|
50
|
-
// the third argument still works. `key` is the header name.
|
|
51
|
-
callerHeaders.forEach((value, key) => setForce(key, value));
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
for (const [name, value] of Object.entries(callerHeaders)) {
|
|
55
|
-
setForce(name, value);
|
|
56
|
-
}
|
|
31
|
+
for (const [name, value] of Object.entries(callerHeaders)) {
|
|
32
|
+
lower.set(name.toLowerCase(), { name, value });
|
|
57
33
|
}
|
|
58
34
|
}
|
|
59
35
|
setIfAbsent("accept", "application/json");
|
|
@@ -89,11 +65,10 @@ export function kitApi(options) {
|
|
|
89
65
|
// constructor: older React Native runtimes ship `fetch` (or a
|
|
90
66
|
// polyfill via `fetchImpl`) without exposing `Headers` globally.
|
|
91
67
|
// The prior implementation crashed before the first request on
|
|
92
|
-
// those runtimes. We use `new Headers()` when available
|
|
93
|
-
//
|
|
94
|
-
//
|
|
95
|
-
//
|
|
96
|
-
// the same name.
|
|
68
|
+
// those runtimes. We use `new Headers()` when available and
|
|
69
|
+
// otherwise fall back to a small case-insensitive merge into a
|
|
70
|
+
// plain record. Either way, kit defaults only apply when the
|
|
71
|
+
// internal request hasn't set the same name.
|
|
97
72
|
const headers = mergeHeaders(init?.headers, init?.body != null);
|
|
98
73
|
// Prepend a leading slash if `path` is missing one. Today's
|
|
99
74
|
// call sites all hard-code the leading "/", but normalizing here
|
package/build/kit-api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kit-api.js","sourceRoot":"","sources":["../src/kit-api.ts"],"names":[],"mappings":"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","sourcesContent":["// Tiny fetch wrapper around kit's `/v1` HTTP surface for use by the JS\n// SDK consumers (react-native-iap + expo-iap). Mirrors the shape of\n// `packages/mcp-server/src/kit-client.ts` so the same operations are\n// reachable from both LLM tools and end-user apps without each\n// duplicating the URL layout.\n\nexport type KitApiOptions = {\n apiKey: string;\n baseUrl?: string;\n // Optional fetch override for runtimes without a global (older RN\n // builds) or for injection in tests.\n fetchImpl?: (input: string, init?: RequestInit) => Promise<Response>;\n /** Optional AsyncStorage-compatible persistent cache for direct client\n * payload reads. Cache failures never change a successful API result. */\n clientPayloadCache?: KitClientPayloadCache;\n};\n\nexport type KitClientPayloadCache = {\n getItem: (key: string) => Promise<string | null> | string | null;\n setItem: (key: string, value: string) => Promise<void> | void;\n removeItem?: (key: string) => Promise<void> | void;\n};\n\nexport type KitClientPayloadOptions = {\n /** Revalidate a cached payload with its scoped ETag. Without this flag,\n * a valid persistent entry is returned without a network request. */\n refresh?: boolean;\n};\n\nexport type KitSubscription = {\n id: string;\n productId: string;\n platform: \"IOS\" | \"Android\";\n state: string;\n expiresAt?: number;\n renewsAt?: number;\n willRenew?: boolean;\n cancellationReason?: string;\n currency?: string;\n priceAmountMicros?: number;\n startedAt: number;\n updatedAt: number;\n purchaseToken: string;\n userId?: string;\n};\n\nexport type EntitlementsResponse = {\n userId: string;\n productIds: string[];\n subscriptions: KitSubscription[];\n};\n\nexport type StatusResponse = {\n active: boolean;\n subscription: KitSubscription | null;\n};\n\nexport type KitProductPlatform = \"IOS\" | \"Android\";\n\nexport type KitProductClientPayload = {\n format: \"toml\" | \"json\" | \"text\";\n body: string;\n version: number;\n updatedAt: number;\n};\n\nexport type KitProductOffer = {\n id: string;\n kind:\n | \"FreeTrial\"\n | \"IntroPayUpFront\"\n | \"IntroPayAsYouGo\"\n | \"PromotionalOffer\"\n | \"BasePlan\";\n duration?: string;\n numberOfPeriods?: number;\n priceAmountMicros?: number;\n currency?: string;\n};\n\nexport type KitProduct = {\n productId: string;\n platform: KitProductPlatform;\n type: \"Subscription\" | \"NonConsumable\" | \"Consumable\";\n title: string;\n description?: string;\n priceAmountMicros?: number;\n currency?: string;\n state: \"Draft\" | \"Ready\" | \"Active\" | \"Removed\";\n storeRef?: string;\n subscriptionGroupId?: string;\n subscriptionGroupName?: string;\n billingPeriod?: \"P1W\" | \"P1M\" | \"P2M\" | \"P3M\" | \"P6M\" | \"P1Y\";\n offers?: KitProductOffer[];\n updatedAt: number;\n clientPayload?: KitProductClientPayload;\n};\n\nexport type KitProductsOptions = {\n platform?: KitProductPlatform;\n /** Include public client payload bodies in a bounded platform page. */\n includeClientPayload?: boolean;\n /** Page size for every catalog read (default 25, maximum 50). */\n limit?: number;\n /** Opaque cursor returned as `nextCursor` by the previous page. */\n cursor?: string;\n};\n\nexport type KitProductsResponse = {\n products: KitProduct[];\n hasMore: boolean;\n /** Present when a catalog page has another page. */\n nextCursor?: string;\n};\n\nexport type KitClientPayloadResponse = {\n clientPayload: KitProductClientPayload;\n};\n\ntype CachedClientPayload = KitClientPayloadResponse & {\n etag?: string;\n};\n\nconst DEFAULT_BASE_URL = \"https://kit.openiap.dev\";\n\n// Merge caller-supplied headers with kit defaults (`accept`,\n// optionally `content-type`). When the runtime exposes a global\n// `Headers` constructor we use it directly so callers passing a\n// `Headers` instance (a `HeadersInit`) keep that exact instance's\n// values. When `Headers` is missing — older React Native builds where\n// the operator wires up `fetchImpl` without a `Headers` polyfill —\n// we fall back to a case-insensitive merge into a plain record so\n// the request still goes through. Either way, caller-set values take\n// precedence over kit defaults.\nfunction mergeHeaders(\n callerHeaders: HeadersInit | undefined,\n hasBody: boolean,\n): HeadersInit {\n if (typeof Headers === \"function\") {\n const merged = new Headers(callerHeaders);\n if (!merged.has(\"accept\")) merged.set(\"accept\", \"application/json\");\n if (hasBody && !merged.has(\"content-type\")) {\n merged.set(\"content-type\", \"application/json\");\n }\n return merged;\n }\n // Plain-object fallback path. Build a case-insensitive name map\n // from whatever the caller passed (Headers-shaped, array-of-pairs,\n // or plain record) and re-emit as a record `fetchImpl` accepts.\n const lower = new Map<string, { name: string; value: string }>();\n const setIfAbsent = (name: string, value: string) => {\n const key = name.toLowerCase();\n if (!lower.has(key)) lower.set(key, { name, value });\n };\n const setForce = (name: string, value: string) => {\n const key = name.toLowerCase();\n lower.set(key, { name, value });\n };\n if (callerHeaders) {\n if (Array.isArray(callerHeaders)) {\n for (const [name, value] of callerHeaders) setForce(name, value);\n } else if (\n typeof (callerHeaders as { forEach?: unknown }).forEach === \"function\"\n ) {\n // `Headers`-like (without being our `typeof Headers === \"function\"`\n // global). RN polyfills sometimes attach `Headers` only to\n // request/response instances rather than the global scope.\n // Standard signature is `forEach((value, key, parent))`; we\n // bind the first two positionally so a polyfill that omits\n // the third argument still works. `key` is the header name.\n (\n callerHeaders as {\n forEach: (cb: (value: string, key: string) => void) => void;\n }\n ).forEach((value, key) => setForce(key, value));\n } else {\n for (const [name, value] of Object.entries(\n callerHeaders as Record<string, string>,\n )) {\n setForce(name, value);\n }\n }\n }\n setIfAbsent(\"accept\", \"application/json\");\n if (hasBody) setIfAbsent(\"content-type\", \"application/json\");\n const out: Record<string, string> = {};\n for (const { name, value } of lower.values()) out[name] = value;\n return out;\n}\n\nexport class KitApiError extends Error {\n constructor(\n readonly status: number,\n readonly body: unknown,\n message: string,\n ) {\n super(message);\n this.name = \"KitApiError\";\n }\n}\n\nexport function kitApi(options: KitApiOptions) {\n const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, \"\");\n const fetchImpl: (input: string, init?: RequestInit) => Promise<Response> =\n (() => {\n if (options.fetchImpl) return options.fetchImpl;\n if (typeof fetch === \"function\") {\n return (input: string, init?: RequestInit) => fetch(input, init);\n }\n throw new Error(\n \"kitApi requires a fetch implementation. Pass `fetchImpl` for runtimes without a global fetch.\",\n );\n })();\n\n async function request(path: string, init?: RequestInit): Promise<Response> {\n // Normalize headers without depending on a global `Headers`\n // constructor: older React Native runtimes ship `fetch` (or a\n // polyfill via `fetchImpl`) without exposing `Headers` globally.\n // The prior implementation crashed before the first request on\n // those runtimes. We use `new Headers()` when available (preserves\n // caller-supplied `Headers` instances exactly), and otherwise fall\n // back to a small case-insensitive merge into a plain record.\n // Either way, kit defaults only apply when the caller hasn't set\n // the same name.\n const headers = mergeHeaders(init?.headers, init?.body != null);\n // Prepend a leading slash if `path` is missing one. Today's\n // call sites all hard-code the leading \"/\", but normalizing here\n // makes the helper safe for future additions and matches the\n // already-stripped `baseUrl` (PR #124\n // (https://github.com/hyodotdev/openiap/pull/124) review).\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n return fetchImpl(`${baseUrl}${normalizedPath}`, {\n ...init,\n headers,\n });\n }\n\n async function parseResponse<T>(\n response: Response,\n path: string,\n ): Promise<T> {\n const text = await response.text();\n // Empty body normalizes to null so callers expecting JSON\n // (status / entitlements / list*) don't get a truthy \"\"\n // and crash on property access.\n let parsed: unknown = null;\n let parseError: unknown = null;\n if (text) {\n try {\n parsed = JSON.parse(text);\n } catch (error) {\n // Non-JSON body (a misconfigured proxy returning HTML, a\n // CDN-injected error page, etc.) on a 2xx response would\n // otherwise reach the caller as `parsed = text` and crash\n // on property access via `parsed as T`. Throw a structured\n // KitApiError instead so callers see a typed failure.\n parseError = error;\n }\n }\n if (!response.ok) {\n // Surface the raw body (text or parsed) on the error path so\n // operators can read the upstream error message verbatim.\n throw new KitApiError(\n response.status,\n parsed ?? text,\n `kit ${path} returned ${response.status}`,\n );\n }\n if (parseError) {\n throw new KitApiError(\n response.status,\n text,\n `kit ${path} returned a non-JSON ${response.status} body (${\n parseError instanceof Error ? parseError.message : String(parseError)\n })`,\n );\n }\n return parsed as T;\n }\n\n async function call<T>(path: string, init?: RequestInit): Promise<T> {\n return parseResponse<T>(await request(path, init), path);\n }\n\n function clientPayloadCacheKey(\n productId: string,\n platform: KitProductPlatform,\n ): string {\n return [\n \"iapkit-client-payload-v1\",\n baseUrl,\n options.apiKey,\n platform,\n productId,\n ]\n .map(encodeURIComponent)\n .join(\":\");\n }\n\n async function readCachedClientPayload(\n cacheKey: string,\n ): Promise<CachedClientPayload | null> {\n if (!options.clientPayloadCache) return null;\n try {\n const raw = await options.clientPayloadCache.getItem(cacheKey);\n if (!raw) return null;\n const candidate = JSON.parse(raw) as Partial<CachedClientPayload>;\n const payload = candidate.clientPayload;\n if (\n !payload ||\n ![\"toml\", \"json\", \"text\"].includes(payload.format) ||\n typeof payload.body !== \"string\" ||\n !Number.isSafeInteger(payload.version) ||\n payload.version < 1 ||\n typeof payload.updatedAt !== \"number\" ||\n (candidate.etag !== undefined && typeof candidate.etag !== \"string\")\n ) {\n await options.clientPayloadCache.removeItem?.(cacheKey);\n return null;\n }\n return candidate as CachedClientPayload;\n } catch {\n return null;\n }\n }\n\n async function writeCachedClientPayload(\n cacheKey: string,\n value: CachedClientPayload,\n ): Promise<void> {\n try {\n await options.clientPayloadCache?.setItem(\n cacheKey,\n JSON.stringify(value),\n );\n } catch {\n // Persistence is an optimization. A device storage failure must not\n // turn a successful IAPKit read into an application error.\n }\n }\n\n async function removeCachedClientPayload(cacheKey: string): Promise<void> {\n try {\n await options.clientPayloadCache?.removeItem?.(cacheKey);\n } catch {\n // See writeCachedClientPayload: cache maintenance is best effort.\n }\n }\n\n return {\n apiKey: options.apiKey,\n baseUrl,\n\n /** GET /v1/subscriptions/status — the `active` boolean is the\n * fastest gate for \"is this user paying?\". */\n status: (userId: string) =>\n call<StatusResponse>(\n `/v1/subscriptions/status/${encodeURIComponent(options.apiKey)}?userId=${encodeURIComponent(userId)}`,\n ),\n\n /** GET /v1/subscriptions/entitlements — every productId the user\n * is entitled to. Use this when feature gating depends on which\n * specific tier the user owns. */\n entitlements: (userId: string) =>\n call<EntitlementsResponse>(\n `/v1/subscriptions/entitlements/${encodeURIComponent(options.apiKey)}?userId=${encodeURIComponent(userId)}`,\n ),\n\n /** GET /v1/products — read the store-synced catalog. Client payloads\n * are excluded unless explicitly requested because they may add up to\n * 16 KiB per product. */\n products: (productOptions: KitProductsOptions = {}) => {\n if (\n productOptions.includeClientPayload === true &&\n !productOptions.platform\n ) {\n throw new Error(\n \"kitApi.products requires platform when includeClientPayload is true\",\n );\n }\n const query = new URLSearchParams();\n if (productOptions.platform) {\n query.set(\"platform\", productOptions.platform);\n }\n if (productOptions.includeClientPayload !== undefined) {\n query.set(\n \"includeClientPayload\",\n String(productOptions.includeClientPayload),\n );\n }\n if (productOptions.limit !== undefined) {\n query.set(\"limit\", String(productOptions.limit));\n }\n if (productOptions.cursor !== undefined) {\n query.set(\"cursor\", productOptions.cursor);\n }\n const encodedQuery = query.toString();\n const suffix = encodedQuery ? `?${encodedQuery}` : \"\";\n return call<KitProductsResponse>(\n `/v1/products/${encodeURIComponent(options.apiKey)}${suffix}`,\n );\n },\n\n /** GET one public client payload by its store-specific natural key.\n * Payloads are app-facing data; never store secrets in them. */\n clientPayload: async (\n productId: string,\n platform: KitProductPlatform,\n payloadOptions: KitClientPayloadOptions = {},\n ) => {\n const path = `/v1/products/${encodeURIComponent(options.apiKey)}/${encodeURIComponent(productId)}/client-payload?platform=${encodeURIComponent(platform)}`;\n const cacheKey = clientPayloadCacheKey(productId, platform);\n const cached = await readCachedClientPayload(cacheKey);\n if (cached && payloadOptions.refresh !== true) {\n return { clientPayload: cached.clientPayload };\n }\n const response = await request(path, {\n ...(cached?.etag ? { headers: { \"If-None-Match\": cached.etag } } : {}),\n });\n if (response.status === 304 && cached) {\n return { clientPayload: cached.clientPayload };\n }\n try {\n const result = await parseResponse<KitClientPayloadResponse>(\n response,\n path,\n );\n await writeCachedClientPayload(cacheKey, {\n ...result,\n ...(response.headers.get(\"etag\")\n ? { etag: response.headers.get(\"etag\")! }\n : {}),\n });\n return result;\n } catch (error) {\n if (error instanceof KitApiError && error.status === 404) {\n await removeCachedClientPayload(cacheKey);\n }\n throw error;\n }\n },\n\n /** POST /v1/subscriptions/bind-user — call after a successful\n * verifyReceipt so kit knows which userId owns the verified\n * `purchaseToken`. Idempotent. */\n bindUser: (purchaseToken: string, userId: string) =>\n call<{ ok: boolean; bound: boolean }>(\n `/v1/subscriptions/bind-user/${encodeURIComponent(options.apiKey)}`,\n {\n method: \"POST\",\n body: JSON.stringify({ purchaseToken, userId }),\n },\n ),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"kit-api.js","sourceRoot":"","sources":["../src/kit-api.ts"],"names":[],"mappings":"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","sourcesContent":["// Tiny fetch wrapper around kit's `/v1` HTTP surface for use by the JS\n// SDK consumers (react-native-iap + expo-iap). Mirrors the shape of\n// `packages/mcp-server/src/kit-client.ts` so the same operations are\n// reachable from both LLM tools and end-user apps without each\n// duplicating the URL layout.\n\nexport type KitApiOptions = {\n apiKey: string;\n baseUrl?: string;\n // Optional fetch override for runtimes without a global (older RN\n // builds) or for injection in tests.\n fetchImpl?: (input: string, init?: RequestInit) => Promise<Response>;\n /** Optional AsyncStorage-compatible persistent cache for direct client\n * payload reads. Cache failures never change a successful API result. */\n clientPayloadCache?: KitClientPayloadCache;\n};\n\nexport type KitClientPayloadCache = {\n getItem: (key: string) => Promise<string | null> | string | null;\n setItem: (key: string, value: string) => Promise<void> | void;\n removeItem?: (key: string) => Promise<void> | void;\n};\n\nexport type KitClientPayloadOptions = {\n /** Revalidate a cached payload with its scoped ETag. Without this flag,\n * a valid persistent entry is returned without a network request. */\n refresh?: boolean;\n};\n\nexport type KitSubscription = {\n id: string;\n productId: string;\n platform: \"IOS\" | \"Android\";\n state: string;\n expiresAt?: number;\n renewsAt?: number;\n willRenew?: boolean;\n cancellationReason?: string;\n currency?: string;\n priceAmountMicros?: number;\n startedAt: number;\n updatedAt: number;\n purchaseToken: string;\n userId?: string;\n};\n\nexport type EntitlementsResponse = {\n userId: string;\n productIds: string[];\n subscriptions: KitSubscription[];\n};\n\nexport type StatusResponse = {\n active: boolean;\n subscription: KitSubscription | null;\n};\n\nexport type KitProductPlatform = \"IOS\" | \"Android\";\n\nexport type KitProductClientPayload = {\n format: \"toml\" | \"json\" | \"text\";\n body: string;\n version: number;\n updatedAt: number;\n};\n\nexport type KitProductOffer = {\n id: string;\n kind:\n | \"FreeTrial\"\n | \"IntroPayUpFront\"\n | \"IntroPayAsYouGo\"\n | \"PromotionalOffer\"\n | \"BasePlan\";\n duration?: string;\n numberOfPeriods?: number;\n priceAmountMicros?: number;\n currency?: string;\n};\n\nexport type KitProduct = {\n productId: string;\n platform: KitProductPlatform;\n type: \"Subscription\" | \"NonConsumable\" | \"Consumable\";\n title: string;\n description?: string;\n priceAmountMicros?: number;\n currency?: string;\n state: \"Draft\" | \"Ready\" | \"Active\" | \"Removed\";\n storeRef?: string;\n subscriptionGroupId?: string;\n subscriptionGroupName?: string;\n billingPeriod?: \"P1W\" | \"P1M\" | \"P2M\" | \"P3M\" | \"P6M\" | \"P1Y\";\n offers?: KitProductOffer[];\n updatedAt: number;\n clientPayload?: KitProductClientPayload;\n};\n\nexport type KitProductsOptions = {\n platform?: KitProductPlatform;\n /** Include public client payload bodies in a bounded platform page. */\n includeClientPayload?: boolean;\n /** Page size for every catalog read (default 25, maximum 50). */\n limit?: number;\n /** Opaque cursor returned as `nextCursor` by the previous page. */\n cursor?: string;\n};\n\nexport type KitProductsResponse = {\n products: KitProduct[];\n hasMore: boolean;\n /** Present when a catalog page has another page. */\n nextCursor?: string;\n};\n\nexport type KitClientPayloadResponse = {\n clientPayload: KitProductClientPayload;\n};\n\ntype CachedClientPayload = KitClientPayloadResponse & {\n etag?: string;\n};\n\ntype InternalRequestInit = Omit<RequestInit, \"headers\"> & {\n headers?: Record<string, string>;\n};\n\nconst DEFAULT_BASE_URL = \"https://kit.openiap.dev\";\n\n// Merge the request's internal headers with kit defaults (`accept`,\n// optionally `content-type`). When `Headers` is missing — older React\n// Native builds where the operator wires up `fetchImpl` without a\n// `Headers` polyfill — the internal request sites use plain records,\n// so a small case-insensitive merge is sufficient.\nfunction mergeHeaders(\n callerHeaders: Record<string, string> | undefined,\n hasBody: boolean,\n): HeadersInit {\n if (typeof Headers === \"function\") {\n const merged = new Headers(callerHeaders);\n if (!merged.has(\"accept\")) merged.set(\"accept\", \"application/json\");\n if (hasBody && !merged.has(\"content-type\")) {\n merged.set(\"content-type\", \"application/json\");\n }\n return merged;\n }\n // Plain-object fallback path. Build a case-insensitive name map and\n // re-emit it as a record `fetchImpl` accepts.\n const lower = new Map<string, { name: string; value: string }>();\n const setIfAbsent = (name: string, value: string) => {\n const key = name.toLowerCase();\n if (!lower.has(key)) lower.set(key, { name, value });\n };\n if (callerHeaders) {\n for (const [name, value] of Object.entries(callerHeaders)) {\n lower.set(name.toLowerCase(), { name, value });\n }\n }\n setIfAbsent(\"accept\", \"application/json\");\n if (hasBody) setIfAbsent(\"content-type\", \"application/json\");\n const out: Record<string, string> = {};\n for (const { name, value } of lower.values()) out[name] = value;\n return out;\n}\n\nexport class KitApiError extends Error {\n constructor(\n readonly status: number,\n readonly body: unknown,\n message: string,\n ) {\n super(message);\n this.name = \"KitApiError\";\n }\n}\n\nexport function kitApi(options: KitApiOptions) {\n const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, \"\");\n const fetchImpl: (input: string, init?: RequestInit) => Promise<Response> =\n (() => {\n if (options.fetchImpl) return options.fetchImpl;\n if (typeof fetch === \"function\") {\n return (input: string, init?: RequestInit) => fetch(input, init);\n }\n throw new Error(\n \"kitApi requires a fetch implementation. Pass `fetchImpl` for runtimes without a global fetch.\",\n );\n })();\n\n async function request(\n path: string,\n init?: InternalRequestInit,\n ): Promise<Response> {\n // Normalize headers without depending on a global `Headers`\n // constructor: older React Native runtimes ship `fetch` (or a\n // polyfill via `fetchImpl`) without exposing `Headers` globally.\n // The prior implementation crashed before the first request on\n // those runtimes. We use `new Headers()` when available and\n // otherwise fall back to a small case-insensitive merge into a\n // plain record. Either way, kit defaults only apply when the\n // internal request hasn't set the same name.\n const headers = mergeHeaders(init?.headers, init?.body != null);\n // Prepend a leading slash if `path` is missing one. Today's\n // call sites all hard-code the leading \"/\", but normalizing here\n // makes the helper safe for future additions and matches the\n // already-stripped `baseUrl` (PR #124\n // (https://github.com/hyodotdev/openiap/pull/124) review).\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n return fetchImpl(`${baseUrl}${normalizedPath}`, {\n ...init,\n headers,\n });\n }\n\n async function parseResponse<T>(\n response: Response,\n path: string,\n ): Promise<T> {\n const text = await response.text();\n // Empty body normalizes to null so callers expecting JSON\n // (status / entitlements / list*) don't get a truthy \"\"\n // and crash on property access.\n let parsed: unknown = null;\n let parseError: unknown = null;\n if (text) {\n try {\n parsed = JSON.parse(text);\n } catch (error) {\n // Non-JSON body (a misconfigured proxy returning HTML, a\n // CDN-injected error page, etc.) on a 2xx response would\n // otherwise reach the caller as `parsed = text` and crash\n // on property access via `parsed as T`. Throw a structured\n // KitApiError instead so callers see a typed failure.\n parseError = error;\n }\n }\n if (!response.ok) {\n // Surface the raw body (text or parsed) on the error path so\n // operators can read the upstream error message verbatim.\n throw new KitApiError(\n response.status,\n parsed ?? text,\n `kit ${path} returned ${response.status}`,\n );\n }\n if (parseError) {\n throw new KitApiError(\n response.status,\n text,\n `kit ${path} returned a non-JSON ${response.status} body (${\n parseError instanceof Error ? parseError.message : String(parseError)\n })`,\n );\n }\n return parsed as T;\n }\n\n async function call<T>(path: string, init?: InternalRequestInit): Promise<T> {\n return parseResponse<T>(await request(path, init), path);\n }\n\n function clientPayloadCacheKey(\n productId: string,\n platform: KitProductPlatform,\n ): string {\n return [\n \"iapkit-client-payload-v1\",\n baseUrl,\n options.apiKey,\n platform,\n productId,\n ]\n .map(encodeURIComponent)\n .join(\":\");\n }\n\n async function readCachedClientPayload(\n cacheKey: string,\n ): Promise<CachedClientPayload | null> {\n if (!options.clientPayloadCache) return null;\n try {\n const raw = await options.clientPayloadCache.getItem(cacheKey);\n if (!raw) return null;\n const candidate = JSON.parse(raw) as Partial<CachedClientPayload>;\n const payload = candidate.clientPayload;\n if (\n !payload ||\n ![\"toml\", \"json\", \"text\"].includes(payload.format) ||\n typeof payload.body !== \"string\" ||\n !Number.isSafeInteger(payload.version) ||\n payload.version < 1 ||\n typeof payload.updatedAt !== \"number\" ||\n (candidate.etag !== undefined && typeof candidate.etag !== \"string\")\n ) {\n await options.clientPayloadCache.removeItem?.(cacheKey);\n return null;\n }\n return candidate as CachedClientPayload;\n } catch {\n return null;\n }\n }\n\n async function writeCachedClientPayload(\n cacheKey: string,\n value: CachedClientPayload,\n ): Promise<void> {\n try {\n await options.clientPayloadCache?.setItem(\n cacheKey,\n JSON.stringify(value),\n );\n } catch {\n // Persistence is an optimization. A device storage failure must not\n // turn a successful IAPKit read into an application error.\n }\n }\n\n async function removeCachedClientPayload(cacheKey: string): Promise<void> {\n try {\n await options.clientPayloadCache?.removeItem?.(cacheKey);\n } catch {\n // See writeCachedClientPayload: cache maintenance is best effort.\n }\n }\n\n return {\n apiKey: options.apiKey,\n baseUrl,\n\n /** GET /v1/subscriptions/status — the `active` boolean is the\n * fastest gate for \"is this user paying?\". */\n status: (userId: string) =>\n call<StatusResponse>(\n `/v1/subscriptions/status/${encodeURIComponent(options.apiKey)}?userId=${encodeURIComponent(userId)}`,\n ),\n\n /** GET /v1/subscriptions/entitlements — every productId the user\n * is entitled to. Use this when feature gating depends on which\n * specific tier the user owns. */\n entitlements: (userId: string) =>\n call<EntitlementsResponse>(\n `/v1/subscriptions/entitlements/${encodeURIComponent(options.apiKey)}?userId=${encodeURIComponent(userId)}`,\n ),\n\n /** GET /v1/products — read the store-synced catalog. Client payloads\n * are excluded unless explicitly requested because they may add up to\n * 16 KiB per product. */\n products: (productOptions: KitProductsOptions = {}) => {\n if (\n productOptions.includeClientPayload === true &&\n !productOptions.platform\n ) {\n throw new Error(\n \"kitApi.products requires platform when includeClientPayload is true\",\n );\n }\n const query = new URLSearchParams();\n if (productOptions.platform) {\n query.set(\"platform\", productOptions.platform);\n }\n if (productOptions.includeClientPayload !== undefined) {\n query.set(\n \"includeClientPayload\",\n String(productOptions.includeClientPayload),\n );\n }\n if (productOptions.limit !== undefined) {\n query.set(\"limit\", String(productOptions.limit));\n }\n if (productOptions.cursor !== undefined) {\n query.set(\"cursor\", productOptions.cursor);\n }\n const encodedQuery = query.toString();\n const suffix = encodedQuery ? `?${encodedQuery}` : \"\";\n return call<KitProductsResponse>(\n `/v1/products/${encodeURIComponent(options.apiKey)}${suffix}`,\n );\n },\n\n /** GET one public client payload by its store-specific natural key.\n * Payloads are app-facing data; never store secrets in them. */\n clientPayload: async (\n productId: string,\n platform: KitProductPlatform,\n payloadOptions: KitClientPayloadOptions = {},\n ) => {\n const path = `/v1/products/${encodeURIComponent(options.apiKey)}/${encodeURIComponent(productId)}/client-payload?platform=${encodeURIComponent(platform)}`;\n const cacheKey = clientPayloadCacheKey(productId, platform);\n const cached = await readCachedClientPayload(cacheKey);\n if (cached && payloadOptions.refresh !== true) {\n return { clientPayload: cached.clientPayload };\n }\n const response = await request(path, {\n ...(cached?.etag ? { headers: { \"If-None-Match\": cached.etag } } : {}),\n });\n if (response.status === 304 && cached) {\n return { clientPayload: cached.clientPayload };\n }\n try {\n const result = await parseResponse<KitClientPayloadResponse>(\n response,\n path,\n );\n await writeCachedClientPayload(cacheKey, {\n ...result,\n ...(response.headers.get(\"etag\")\n ? { etag: response.headers.get(\"etag\")! }\n : {}),\n });\n return result;\n } catch (error) {\n if (error instanceof KitApiError && error.status === 404) {\n await removeCachedClientPayload(cacheKey);\n }\n throw error;\n }\n },\n\n /** POST /v1/subscriptions/bind-user — call after a successful\n * verifyReceipt so kit knows which userId owns the verified\n * `purchaseToken`. Idempotent. */\n bindUser: (purchaseToken: string, userId: string) =>\n call<{ ok: boolean; bound: boolean }>(\n `/v1/subscriptions/bind-user/${encodeURIComponent(options.apiKey)}`,\n {\n method: \"POST\",\n body: JSON.stringify({ purchaseToken, userId }),\n },\n ),\n };\n}\n"]}
|
package/openiap-versions.json
CHANGED
package/package.json
CHANGED
package/src/kit-api.ts
CHANGED
|
@@ -121,19 +121,19 @@ type CachedClientPayload = KitClientPayloadResponse & {
|
|
|
121
121
|
etag?: string;
|
|
122
122
|
};
|
|
123
123
|
|
|
124
|
+
type InternalRequestInit = Omit<RequestInit, "headers"> & {
|
|
125
|
+
headers?: Record<string, string>;
|
|
126
|
+
};
|
|
127
|
+
|
|
124
128
|
const DEFAULT_BASE_URL = "https://kit.openiap.dev";
|
|
125
129
|
|
|
126
|
-
// Merge
|
|
127
|
-
// optionally `content-type`). When
|
|
128
|
-
//
|
|
129
|
-
// `Headers`
|
|
130
|
-
//
|
|
131
|
-
// the operator wires up `fetchImpl` without a `Headers` polyfill —
|
|
132
|
-
// we fall back to a case-insensitive merge into a plain record so
|
|
133
|
-
// the request still goes through. Either way, caller-set values take
|
|
134
|
-
// precedence over kit defaults.
|
|
130
|
+
// Merge the request's internal headers with kit defaults (`accept`,
|
|
131
|
+
// optionally `content-type`). When `Headers` is missing — older React
|
|
132
|
+
// Native builds where the operator wires up `fetchImpl` without a
|
|
133
|
+
// `Headers` polyfill — the internal request sites use plain records,
|
|
134
|
+
// so a small case-insensitive merge is sufficient.
|
|
135
135
|
function mergeHeaders(
|
|
136
|
-
callerHeaders:
|
|
136
|
+
callerHeaders: Record<string, string> | undefined,
|
|
137
137
|
hasBody: boolean,
|
|
138
138
|
): HeadersInit {
|
|
139
139
|
if (typeof Headers === "function") {
|
|
@@ -144,41 +144,16 @@ function mergeHeaders(
|
|
|
144
144
|
}
|
|
145
145
|
return merged;
|
|
146
146
|
}
|
|
147
|
-
// Plain-object fallback path. Build a case-insensitive name map
|
|
148
|
-
//
|
|
149
|
-
// or plain record) and re-emit as a record `fetchImpl` accepts.
|
|
147
|
+
// Plain-object fallback path. Build a case-insensitive name map and
|
|
148
|
+
// re-emit it as a record `fetchImpl` accepts.
|
|
150
149
|
const lower = new Map<string, { name: string; value: string }>();
|
|
151
150
|
const setIfAbsent = (name: string, value: string) => {
|
|
152
151
|
const key = name.toLowerCase();
|
|
153
152
|
if (!lower.has(key)) lower.set(key, { name, value });
|
|
154
153
|
};
|
|
155
|
-
const setForce = (name: string, value: string) => {
|
|
156
|
-
const key = name.toLowerCase();
|
|
157
|
-
lower.set(key, { name, value });
|
|
158
|
-
};
|
|
159
154
|
if (callerHeaders) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
} else if (
|
|
163
|
-
typeof (callerHeaders as { forEach?: unknown }).forEach === "function"
|
|
164
|
-
) {
|
|
165
|
-
// `Headers`-like (without being our `typeof Headers === "function"`
|
|
166
|
-
// global). RN polyfills sometimes attach `Headers` only to
|
|
167
|
-
// request/response instances rather than the global scope.
|
|
168
|
-
// Standard signature is `forEach((value, key, parent))`; we
|
|
169
|
-
// bind the first two positionally so a polyfill that omits
|
|
170
|
-
// the third argument still works. `key` is the header name.
|
|
171
|
-
(
|
|
172
|
-
callerHeaders as {
|
|
173
|
-
forEach: (cb: (value: string, key: string) => void) => void;
|
|
174
|
-
}
|
|
175
|
-
).forEach((value, key) => setForce(key, value));
|
|
176
|
-
} else {
|
|
177
|
-
for (const [name, value] of Object.entries(
|
|
178
|
-
callerHeaders as Record<string, string>,
|
|
179
|
-
)) {
|
|
180
|
-
setForce(name, value);
|
|
181
|
-
}
|
|
155
|
+
for (const [name, value] of Object.entries(callerHeaders)) {
|
|
156
|
+
lower.set(name.toLowerCase(), { name, value });
|
|
182
157
|
}
|
|
183
158
|
}
|
|
184
159
|
setIfAbsent("accept", "application/json");
|
|
@@ -212,16 +187,18 @@ export function kitApi(options: KitApiOptions) {
|
|
|
212
187
|
);
|
|
213
188
|
})();
|
|
214
189
|
|
|
215
|
-
async function request(
|
|
190
|
+
async function request(
|
|
191
|
+
path: string,
|
|
192
|
+
init?: InternalRequestInit,
|
|
193
|
+
): Promise<Response> {
|
|
216
194
|
// Normalize headers without depending on a global `Headers`
|
|
217
195
|
// constructor: older React Native runtimes ship `fetch` (or a
|
|
218
196
|
// polyfill via `fetchImpl`) without exposing `Headers` globally.
|
|
219
197
|
// The prior implementation crashed before the first request on
|
|
220
|
-
// those runtimes. We use `new Headers()` when available
|
|
221
|
-
//
|
|
222
|
-
//
|
|
223
|
-
//
|
|
224
|
-
// the same name.
|
|
198
|
+
// those runtimes. We use `new Headers()` when available and
|
|
199
|
+
// otherwise fall back to a small case-insensitive merge into a
|
|
200
|
+
// plain record. Either way, kit defaults only apply when the
|
|
201
|
+
// internal request hasn't set the same name.
|
|
225
202
|
const headers = mergeHeaders(init?.headers, init?.body != null);
|
|
226
203
|
// Prepend a leading slash if `path` is missing one. Today's
|
|
227
204
|
// call sites all hard-code the leading "/", but normalizing here
|
|
@@ -278,7 +255,7 @@ export function kitApi(options: KitApiOptions) {
|
|
|
278
255
|
return parsed as T;
|
|
279
256
|
}
|
|
280
257
|
|
|
281
|
-
async function call<T>(path: string, init?:
|
|
258
|
+
async function call<T>(path: string, init?: InternalRequestInit): Promise<T> {
|
|
282
259
|
return parseResponse<T>(await request(path, init), path);
|
|
283
260
|
}
|
|
284
261
|
|