@tinkerlandai/indiana-sdk 0.8.0 → 0.8.3
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/CHANGELOG.md +14 -0
- package/README.md +67 -20
- package/README.zh-CN.md +66 -19
- package/dist/ai-usage-BV-FlgWr.d.ts +247 -0
- package/dist/{ai-usage-Bigjb8MS.d.ts → api-B3FIE41b.d.ts} +554 -423
- package/dist/chunk-2QPETWDX.js +1 -0
- package/dist/chunk-ANOOBDW5.js +350 -0
- package/dist/chunk-BNU6IG3F.js +1 -0
- package/dist/chunk-GRLMT5PR.js +1 -0
- package/dist/chunk-LMR2TM3X.js +1 -0
- package/dist/chunk-OBYJWIRB.js +1 -0
- package/dist/{chunk-G2R56FKU.js → chunk-SHSNIJJM.js} +1 -1
- package/dist/{chunk-OVMNCZYC.js → chunk-SOQO2RDZ.js} +1 -1
- package/dist/chunk-VVV3JNS3.js +1 -0
- package/dist/{chunk-YAFMBXIE.js → chunk-X747SY26.js} +1 -1
- package/dist/chunk-Y32NPIYY.js +1 -0
- package/dist/chunk-ZT66RIFU.js +10 -0
- package/dist/{configuration-sync-VFbY1pCN.d.ts → configuration-sync-DNvKXHk-.d.ts} +25 -25
- package/dist/{content-K2HCZVC2.js → content-J3FKZTGT.js} +1 -1
- package/dist/{errors-BpCmukJr.d.ts → errors-C8lRYZ0n.d.ts} +49 -2
- package/dist/{funnel-runtime-start-DKcTCRrd.d.ts → funnel-local-client-wbz-4gFx.d.ts} +701 -6055
- package/dist/funnel-runtime-host-C5P5JTV3.js +1 -0
- package/dist/index.d.ts +1831 -1901
- package/dist/index.js +1 -1
- package/dist/native-shell.js +1 -1
- package/dist/openrouter.d.ts +4 -3
- package/dist/openrouter.js +1 -1
- package/dist/page.d.ts +7 -7
- package/dist/page.js +1 -1
- package/dist/paywall-3GIRKSHN.js +1 -0
- package/dist/popup.d.ts +2 -2
- package/dist/popup.js +1 -1
- package/dist/react-native.d.ts +97 -4
- package/dist/react-native.js +1 -1
- package/dist/screen-renderer-5FPYVSPW.js +1 -0
- package/dist/server.d.ts +4648 -8
- package/dist/server.js +1 -1
- package/dist/src-BMJCIMIF.js +1 -0
- package/dist/visual.js +1 -1
- package/package.json +3 -3
- package/dist/chunk-2A6UYUFA.js +0 -1
- package/dist/chunk-3BQFJANQ.js +0 -1
- package/dist/chunk-3ENVRJE6.js +0 -350
- package/dist/chunk-A3N4ZZTM.js +0 -7
- package/dist/chunk-AE4CUTUE.js +0 -1
- package/dist/chunk-CXYOZSOF.js +0 -1
- package/dist/funnel-runtime-host-HNZ47TZW.js +0 -1
- package/dist/paywall-PD62B2AY.js +0 -1
- package/dist/src-4MRSESVS.js +0 -1
- package/dist/{chunk-6X42DWOM.js → chunk-DSPLGTQI.js} +0 -0
- package/dist/{chunk-S5TVMQRC.js → chunk-EXCPE2XH.js} +0 -0
- package/dist/{customer-page-BrCZxcaQ.d.ts → customer-page-WUQVK_tp.d.ts} +4 -4
- package/dist/{screen-BazUOjwM.d.ts → screen-BpAejkn0.d.ts} +267 -267
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
Release facts and artifact evidence: [SDK release ledger](../../docs/sdk-releases.md).
|
|
4
4
|
|
|
5
|
+
## 0.8.3 — 2026-10-26
|
|
6
|
+
|
|
7
|
+
- Refresh sanitized custom HTML fallback content when Product availability changes.
|
|
8
|
+
- Preserve the selected Product across empty availability refreshes, keeping purchase disabled while that Product is unavailable.
|
|
9
|
+
- Synchronize the shared Web and native renderers with the current Product selection rules.
|
|
10
|
+
- Align Server SDK request helpers with the committed messaging contract.
|
|
11
|
+
|
|
12
|
+
## 0.8.1 — 2026-10-25
|
|
13
|
+
|
|
14
|
+
- Organize SDK implementations by capability while preserving public entry points and interfaces.
|
|
15
|
+
- Consolidate Funnel observed state, pending-command and purchase recovery, and shared request validation without changing credential or execution authority.
|
|
16
|
+
- Share Paywall binding and purchase-observation rules across hosts; keep rendering independent of authenticated clients.
|
|
17
|
+
- Keep the current mutation schema in durable command storage and remove an invalid comparison against the unsupported `evaluate` operation.
|
|
18
|
+
|
|
5
19
|
## 0.8.0 — 2026-10-24
|
|
6
20
|
|
|
7
21
|
- Resolve independent Pages, Popups and Banners and render them through the explicit `mountContent` host entry.
|
package/README.md
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
# @tinkerlandai/indiana-sdk
|
|
2
2
|
|
|
3
|
+
These examples use SDK 0.8.1 with `https://api.dev.tinker.cash` and test App credentials (protocol 0.8). Check [environment state](../../docs/development-status.md) before switching. The SDK default remains the production API, so set `baseUrl` explicitly for these examples.
|
|
4
|
+
|
|
3
5
|
[简体中文](./README.zh-CN.md)
|
|
4
6
|
|
|
5
|
-
The Indiana business SDK
|
|
7
|
+
The Indiana business SDK groups its capabilities as **Identity, Commerce, GrowthBook, Analytics, Delivery (Offering, Paywall, Page, Popup and Banner), and Funnel**, over shared protocol, transport, configuration, rendering and recovery foundations. These responsibilities follow the existing L0–L4 architecture; language packages and entry points implement different subsets. The browser/native client and merchant-server entries share contracts and core behavior while retaining separate credentials and allowed operations. Indianapolis is the backend runtime they call; it is not the merchant's server SDK.
|
|
6
8
|
|
|
7
9
|
**IAM source scanning, generation, validation and upload belong to the independent build package `@tinkerlandai/indiana-iam`.** This business SDK retains only the runtime release binding used by GB visual changes. See [SDK boundaries](../../docs/sdk-architecture.md) and the [IAM package](../iam/README.md).
|
|
8
10
|
|
|
9
11
|
```sh
|
|
10
|
-
npm install --save-exact @tinkerlandai/indiana-sdk@0.8.
|
|
12
|
+
npm install --save-exact @tinkerlandai/indiana-sdk@0.8.1
|
|
11
13
|
```
|
|
12
14
|
|
|
13
|
-
SDK 0.8.
|
|
15
|
+
SDK 0.8.1 requires HTTP protocol 0.8. Install a version that matches your runtime; publishing a package does not deploy the server. Publication and accepted environment scope are recorded in the [release ledger](../../docs/sdk-releases.md) and [development status](../../docs/development-status.md).
|
|
14
16
|
|
|
15
17
|
The data/session layer handles public JSON, integrity checks and authenticated operations. The presentation host composes that layer with the packaged screen renderer; the renderer receives supplied data and emits action intents. Client display entry points load presentation lazily. The `/server` entry has no screen presentation dependency and uses a scoped Server Key only on your backend. A local SDK guard never replaces runtime authorization or verified payment completion. Console preview supplies simulated data/session results to the same presentation host.
|
|
16
18
|
|
|
@@ -30,7 +32,7 @@ The SDK sends current protocol and SDK version headers and validates the protoco
|
|
|
30
32
|
| ---------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
31
33
|
| `@tinkerlandai/indiana-sdk` | Browser Customer, Funnel, Feature, and standalone Paywall clients |
|
|
32
34
|
| `@tinkerlandai/indiana-sdk/server` | Trusted Node.js backend, Customer Sessions, business writes, and Funnel decisions |
|
|
33
|
-
| `@tinkerlandai/indiana-sdk/react-native` | Portable Customer core and authenticated-backend usage relay; no DOM presentation
|
|
35
|
+
| `@tinkerlandai/indiana-sdk/react-native` | Portable Customer core and authenticated-backend usage relay; no DOM presentation |
|
|
34
36
|
| `@tinkerlandai/indiana-sdk/popup` | Standalone screen rendering, sanitization, and previews |
|
|
35
37
|
| `@tinkerlandai/indiana-sdk/openrouter` | Optional OpenRouter usage integration; requires its peer dependency |
|
|
36
38
|
| `@tinkerlandai/indiana-sdk/native-shell` | Static Funnel shell assets for native WebViews |
|
|
@@ -39,21 +41,23 @@ The SDK sends current protocol and SDK version headers and validates the protoco
|
|
|
39
41
|
|
|
40
42
|
The same package supports JavaScript and TypeScript and includes type declarations. Internal `@indiana/contracts` code is bundled; consumers do not install private workspace packages. Swift and Kotlin use their own package ecosystems and are released separately.
|
|
41
43
|
|
|
44
|
+
For an independent **Page, Popup or Banner resource**, import `createIndiana` and `mountContent` from the root entry, resolve it with `indiana.resolveContent(...)`, then mount the result. `/page` runs GB URL redirect experiments on an existing merchant page; `/visual` applies GB visual changes to that page. `/popup` exposes lower-level screen rendering and preview primitives. Its name does not select or resolve a Popup resource. The public import paths stay unchanged; see [entry ownership](../../docs/sdk-architecture.md#public-entry-points-and-capability-ownership).
|
|
45
|
+
|
|
42
46
|
The separate [Python server SDK](../python/README.md) provides synchronous and asynchronous Customer, holdings, entitlement-check and usage clients against the same current HTTP protocol. It is distributed from `https://tinker.cash/sdk/python` (not PyPI) and is not part of this npm package.
|
|
43
47
|
|
|
44
|
-
The [Go server SDK](../go/README.md) provides the same initial capabilities with typed responses, Context cancellation and goroutine-safe client reuse. It is installed with `go get tinker.cash/sdk/go` through the default Go module proxy and
|
|
48
|
+
The [Go server SDK](../go/README.md) provides the same initial capabilities with typed responses, Context cancellation and goroutine-safe client reuse. It is installed with `go get tinker.cash/sdk/go` through the default Go module proxy and shares the release version with the other business SDKs.
|
|
45
49
|
|
|
46
50
|
## API origin and test services
|
|
47
51
|
|
|
48
52
|
The canonical repository policy, including production/test domain roles, package tags and test-host configuration, is [SDK API entry and development testing](../../docs/sdk-endpoints-and-testing.md).
|
|
49
53
|
|
|
50
|
-
Omitting `baseUrl` selects `https://api.tinker.cash`. This applies to Customer/Server, Funnel, Feature, Paywall, page and visual clients. `createConfigurationSync` also defaults its optional `origin` to that address. Swift `IndianaConfiguration(scope: ...)` and Kotlin `IndianaConfiguration(scope = ...)`
|
|
54
|
+
Omitting `baseUrl` selects `https://api.tinker.cash`. This applies to Customer/Server, Funnel, Feature, Paywall, page and visual clients. `createConfigurationSync` also defaults its optional `origin` to that address. Swift `IndianaConfiguration(scope: ...)` and Kotlin `IndianaConfiguration(scope = ...)` uses the same default and shared release version. Explicit `baseURL` / `baseUrl` still overrides it. Funnel and Paywall shells and renderers are packaged locally; their executable code is not downloaded from that API origin.
|
|
51
55
|
|
|
52
56
|
Both `beta` and `latest` versions published with this default use the production API address. Tags select package versions, not deployments. Our test apps must explicitly set `baseUrl: "https://api.dev.tinker.cash"` and configuration-sync `origin` to the same address. `dev.tinker.cash` is the test main site/Admin, not the Go API entry. The API hosts forward through Vercel to their respective Go Indianapolis services; routing and business readiness have separate acceptance.
|
|
53
57
|
|
|
54
58
|
For our own testing, always require a test-service address instead of relying on the production default:
|
|
55
59
|
|
|
56
|
-
|
|
60
|
+
Set `INDIANA_TEST_BASE_URL=https://api.dev.tinker.cash` and use the native Cloud SQL test App/Key. A production Key or a retained Supabase Key cannot authenticate against that test environment.
|
|
57
61
|
|
|
58
62
|
```ts
|
|
59
63
|
const testBaseUrl = process.env.INDIANA_TEST_BASE_URL;
|
|
@@ -74,7 +78,7 @@ const configuration = createConfigurationSync({
|
|
|
74
78
|
|
|
75
79
|
Use the same explicit address for every client in a test run, including Funnel start/controllers and page/visual clients. Environment variables are read by the host, not automatically by the SDK. Sandbox/Live selects business scope inside the chosen service; it does not select a deployment or database. Never retry against another service automatically after an error or unknown command result.
|
|
76
80
|
|
|
77
|
-
|
|
81
|
+
For maintainer checks, use the [SDK testing guide](../../docs/sdk-selfserve.md#maintainer-api-origin-testing). SDK contract fixtures and actual GOP business tests have separate owners.
|
|
78
82
|
|
|
79
83
|
## Create a Customer Session from a trusted backend
|
|
80
84
|
|
|
@@ -111,7 +115,7 @@ const { holdings } = await indiana.readHoldings();
|
|
|
111
115
|
indiana.reset();
|
|
112
116
|
```
|
|
113
117
|
|
|
114
|
-
Indiana maintains an active Customer session through ordinary SDK requests, using the same token and session row. The validity window is 24 hours with a 30-day absolute limit; there is no merchant renewal timer or additional refresh token. Revocation and issuer expiry still apply, and an expired authorization needs a new verified login.
|
|
118
|
+
Indiana maintains an active Customer session through ordinary SDK requests, using the same token and session row. The validity window is 24 hours with a 30-day absolute limit; there is no merchant renewal timer or additional refresh token. Revocation and issuer expiry still apply, and an expired authorization needs a new verified login. See [Customer credentials](../../docs/customer-credentials.md).
|
|
115
119
|
|
|
116
120
|
Customer updates are partial patches and do not use a Customer revision. When a Guest signs in to an existing Customer, the response reports `switched: true`. Resources and history keep their original owner; create a new Session/Funnel for the target Customer. Guest financial facts are not merged.
|
|
117
121
|
|
|
@@ -182,7 +186,7 @@ Sessions retain Sticky assignments in memory. Supply `stickyBucketAssignmentDocs
|
|
|
182
186
|
|
|
183
187
|
Evaluation is untracked by default. `{ track: true }` invokes configured `onExperimentViewed`/`onFeatureUsage` callbacks once per native assignment/value in that session after successful evaluation and Sticky persistence. Connect callbacks to the existing event tracker only when the result is actually used. Callback errors reach `onError`; event delivery/retries remain the tracker's responsibility, and evaluation does not manufacture durable exposure or usage receipts.
|
|
184
188
|
|
|
185
|
-
Mixed graphs, resource/Bundle outputs and expired configurations fail explicitly. There is no automatic remote execution. `decide()` retains its server-side idempotency, committed receipts and financial checks; local output never grants a Coupon, purchase, entitlement or campaign frequency promise.
|
|
189
|
+
Mixed graphs, resource/Bundle outputs and expired configurations fail explicitly. There is no automatic remote execution. `decide()` retains its server-side idempotency, committed receipts and financial checks; local output never grants a Coupon, purchase, entitlement or campaign frequency promise.
|
|
186
190
|
|
|
187
191
|
### Standalone Feature delivery
|
|
188
192
|
|
|
@@ -209,7 +213,7 @@ unsubscribe();
|
|
|
209
213
|
flags.destroy();
|
|
210
214
|
```
|
|
211
215
|
|
|
212
|
-
|
|
216
|
+
The selected environment's integration settings control behavior events, experiment exposures and Feature usage independently. New environments enable only exposure collection; existing environments retain all three. `flush()` includes a `skipped` count for intentionally disabled collection. The database rechecks every batch, including direct SDK/server and Funnel ingestion. Running experiment/Bandit dependencies prevent incompatible collection changes. These controls do not delete history or affect commercial usage accounting.
|
|
213
217
|
|
|
214
218
|
Flags default to local evaluation; Owner/Admin can switch each flag to server evaluation. Server-evaluated flags deliver only keys and results, using the caller's fallback until the first result arrives. Attribute changes immediately discard old results. List hashes are not a secrecy boundary. Local Funnels cannot depend on server-evaluated flags; mode switches also check active historical Runs. `identify` / `reset` release the previous identity's Feature instances and event queue.
|
|
215
219
|
|
|
@@ -228,7 +232,7 @@ This beta does not certify complete commercial or production operation. Remainin
|
|
|
228
232
|
- Complete delivery for `claimRewardProduct`.
|
|
229
233
|
- Real Apple/Google store acceptance. Independent purchase/restore contracts and partial services do not certify store acceptance. `createNativeReceiptClient().recover()` uses `subscriptions/native/restore`.
|
|
230
234
|
|
|
231
|
-
|
|
235
|
+
Implemented commercial operations use the original credential, permission, scope and configured-provider checks in both Sandbox and Live. An unsupported operation returns 501; a provider configuration or business precondition is not a migration allowlist.
|
|
232
236
|
|
|
233
237
|
## AI usage
|
|
234
238
|
|
|
@@ -240,7 +244,7 @@ Publishing to npm does not deploy Web services, apply database migrations, or re
|
|
|
240
244
|
|
|
241
245
|
See the [SDK release ledger](https://github.com/tinkerlandai/Indiana/blob/main/docs/sdk-releases.md) for versions and immutable publication evidence, and the [developer documentation](https://tinker.cash/docs?lang=en) for integration guides.
|
|
242
246
|
|
|
243
|
-
## Shared public configuration
|
|
247
|
+
## Shared public configuration
|
|
244
248
|
|
|
245
249
|
Use one manager per trusted origin and exact App/environment for Features, canonical Funnel files and enabled page experiments. Use a matching runtime and an explicitly reviewed public configuration publication.
|
|
246
250
|
|
|
@@ -278,7 +282,7 @@ Optional browser persistence defaults to localStorage and contains only public b
|
|
|
278
282
|
|
|
279
283
|
## Local Funnel execution
|
|
280
284
|
|
|
281
|
-
Local and Remote share the authoritative Indiana Run, command/action receipts, business services and Queue recovery.
|
|
285
|
+
Local and Remote share the authoritative Indiana Run, command/action receipts, business services and Queue recovery. A Local host predicts pure Condition/Feature/Experiment paths for display, then sends a `commit_segment` advance signal. GOP recomputes the accepted path from the Run inputs and approved public GB configuration. Remote evaluates on GOP without client configuration. Independent `evaluateFunnelNode` and advisory `.local()` helpers have no business effects.
|
|
282
286
|
|
|
283
287
|
```ts
|
|
284
288
|
import {
|
|
@@ -309,21 +313,21 @@ started.controller.reset();
|
|
|
309
313
|
|
|
310
314
|
Merchant backends use the same adapter from `/server`, with their original Server Key as `credential` and the Indiana Customer UUID as `customerId`. Each Run request proves the original live issuing Key in a server-only header; it is never saved in a pending command or exposed to the renderer. The ordinary `createFunnelRunController` accepts `serverKey` only on a merchant backend. Customer clients continue proving their original Customer identity with `identify(customerToken)`; they cannot override it.
|
|
311
315
|
|
|
312
|
-
|
|
316
|
+
A Flow `commit_segment` carries only its retained request ID, parked node/visit/revision, policy revision and configuration generation. Caller steps, results and boundaries are not accepted. The SDK prediction yields to the server response; response-loss recovery preserves the original command identity. Customer Coupon claims still require `offers:resolve` and explicit `selfClaimEnabled`; merchant grants retain `offers:grant`. The independent Coupon issuer owns eligibility, inventory, possession and expiry.
|
|
313
317
|
|
|
314
|
-
After
|
|
318
|
+
After an advance signal is accepted, actions, waits, retries and recovery use the same GOP driver and Cloud Tasks / Cloud Scheduler as Remote. A disconnected host does not cancel accepted work. Before the required signal arrives, the Run remains parked. The bounded SDK loop settles up to 32 calculation boundaries per call; longer chains continue on a later read.
|
|
315
319
|
|
|
316
320
|
### Shared UI host
|
|
317
321
|
|
|
318
|
-
Screens, live Customer/Coupon data, shown acknowledgements, Paywall and external-task handling use the same Run controller and UI host. Canonical node/command history uses the common recording limits.
|
|
322
|
+
Screens, live Customer/Coupon data, shown acknowledgements, Paywall and external-task handling use the same Run controller and UI host. Canonical node/command history uses the common recording limits. Recovery uses authoritative Run, command and business receipts, without an observation-upload API or a second storage authority. There is no second host business state machine, `invoke` adapter, Local checkpoint owner, `browserFunnelStorage` or Local presentation controller.
|
|
319
323
|
|
|
320
|
-
|
|
324
|
+
Recovery uses the original Run Token and command identities. Do not turn an unknown business outcome into a new start/request ID. The SDK does not import legacy checkpoints. A mode change never rewrites a Run's accepted policy or commands; resolve that original Run before starting another intent.
|
|
321
325
|
|
|
322
|
-
The native renderer shell uses the same pure JavaScript calculation adapter and native Run-command bridge; credentials remain in the native session. A headless Swift/Kotlin session exposes the pending calculation and does not silently calculate it remotely. Wire schemas and the renderer shell are generated together. Installing the package does not migrate a database or deploy a runtime. Browser, provider, capacity and native-store acceptance remain separate.
|
|
326
|
+
The native renderer shell uses the same pure JavaScript calculation adapter and native Run-command bridge; credentials remain in the native session. A headless Swift/Kotlin session exposes the pending calculation and does not silently calculate it remotely. Wire schemas and the renderer shell are generated together. Installing the package does not migrate a database or deploy a runtime. Browser, provider, capacity and native-store acceptance remain separate.
|
|
323
327
|
|
|
324
328
|
## Funnel-scoped resource requests
|
|
325
329
|
|
|
326
|
-
Formal Local Runs submit
|
|
330
|
+
Formal Local Runs submit advance signals to Indiana; the canonical executor supplies the original Run/node/visit/receipt when it issues a Coupon or performs commerce. An application consuming a pure Funnel result can bind its Customer client explicitly:
|
|
327
331
|
|
|
328
332
|
```ts
|
|
329
333
|
const resources = indiana.forFunnel({ funnelId, versionId });
|
|
@@ -331,3 +335,46 @@ await resources.claimCoupon(couponId, savedRequestId);
|
|
|
331
335
|
```
|
|
332
336
|
|
|
333
337
|
The scoped client automatically carries that fixed Funnel context into Coupon claims, Offering/Paywall resolution and attach quotes. Indiana recomputes only the requested Funnel using trusted facts; caller-reported branches are not permission. Independent `indiana.claimCoupon(...)` remains available under Coupon-owned self-claim rules. Reuse the same request ID and input after an unknown response; accepted commands retain their original result after a later Funnel pause.
|
|
338
|
+
|
|
339
|
+
## Standalone Pages, Popups and Banners
|
|
340
|
+
|
|
341
|
+
Publish a Banner with no required inputs and a declared `continue` action. Issue a Customer Token with `content:read`, then explicitly resolve and mount it. Use the matching `kind` for Page or Popup.
|
|
342
|
+
|
|
343
|
+
```ts
|
|
344
|
+
import {
|
|
345
|
+
createIndiana,
|
|
346
|
+
mountContent,
|
|
347
|
+
type ContentActionIntent,
|
|
348
|
+
} from "@tinkerlandai/indiana-sdk";
|
|
349
|
+
|
|
350
|
+
export async function showBanner(
|
|
351
|
+
container: HTMLElement,
|
|
352
|
+
customerToken: string,
|
|
353
|
+
contentId: string,
|
|
354
|
+
onContinue: (intent: ContentActionIntent) => Promise<void>,
|
|
355
|
+
) {
|
|
356
|
+
const indiana = createIndiana({
|
|
357
|
+
baseUrl: "https://api.dev.tinker.cash",
|
|
358
|
+
scope: { projectId: "<TEST_APP_UUID>", environment: "sandbox" },
|
|
359
|
+
});
|
|
360
|
+
indiana.identify(customerToken);
|
|
361
|
+
const { content } = await indiana.resolveContent({
|
|
362
|
+
kind: "banner",
|
|
363
|
+
selector: { type: "resource", id: contentId },
|
|
364
|
+
});
|
|
365
|
+
const host = await mountContent(container, {
|
|
366
|
+
content,
|
|
367
|
+
actions: { continue: onContinue },
|
|
368
|
+
onError: console.error,
|
|
369
|
+
});
|
|
370
|
+
return {
|
|
371
|
+
retryAction: host.retryAction,
|
|
372
|
+
destroy() {
|
|
373
|
+
host.destroy();
|
|
374
|
+
indiana.reset();
|
|
375
|
+
},
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
Provide every declared action handler. `onContinue` uses `intent.requestId` as its backend idempotency key; `retryAction()` reuses that intent after a failure. Call `destroy()` on unmount, sign-out or account change. The host renders content and emits intents; your backend still authorizes and executes business actions.
|
package/README.zh-CN.md
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
[English](./README.md)
|
|
2
2
|
|
|
3
|
+
本页使用 SDK 0.8.1、`https://api.dev.tinker.cash` 与测试 App 凭据(协议 0.8)。切换前核对[环境状态](../../docs/development-status.md)。SDK 默认仍指向生产 API,本页示例必须显式设置 `baseUrl`。
|
|
4
|
+
|
|
3
5
|
# @tinkerlandai/indiana-sdk
|
|
4
6
|
|
|
5
|
-
业务 SDK
|
|
7
|
+
业务 SDK 按职责分为 **身份、商业、GrowthBook、Analytics、内容交付(Offering、Paywall、Page、Popup、Banner)和 Funnel 六组能力**,共用协议、传输、配置、渲染与恢复等基础设施。分类沿用系统的 L0–L4 归属,各语言包和入口支持的子集不同。客户端与商户服务端共用契约和核心行为,凭据及可执行操作分开。Indianapolis 是它们调用的 SDK 运行服务,不是商户安装的服务端 SDK。
|
|
6
8
|
|
|
7
9
|
**IAM 的源码扫描、生成、校验和上传属于独立构建包 `@tinkerlandai/indiana-iam`。** 普通业务 SDK 只保留 GB visual 应用页面变更所需的运行时 release 绑定。完整定义见 [SDK 边界](../../docs/sdk-architecture.md) 与 [IAM 构建包](../iam/README.md)。
|
|
8
10
|
|
|
9
11
|
```sh
|
|
10
|
-
npm install --save-exact @tinkerlandai/indiana-sdk@0.8.
|
|
12
|
+
npm install --save-exact @tinkerlandai/indiana-sdk@0.8.1
|
|
11
13
|
```
|
|
12
14
|
|
|
13
|
-
SDK 0.8.
|
|
15
|
+
SDK 0.8.1 要求 HTTP 协议 0.8。安装版本须与运行服务匹配;发布包不会部署服务端。实际发布、标签与环境验收范围见 [SDK 发布总账](../../docs/sdk-releases.md) 和 [开发状态](../../docs/development-status.md)。
|
|
14
16
|
|
|
15
17
|
数据/会话层负责公开 JSON、完整性校验和鉴权操作;展示宿主将会话接口接入打包的屏幕渲染器,渲染器消费已提供的数据并返回动作意图。客户端按需加载展示;`/server` 入口使用商户后端的受限 Server Key,不加载屏幕展示。SDK 本地检查不替代运行时授权或付款核实。后台 Preview 为同一个展示宿主提供模拟会话和数据。
|
|
16
18
|
|
|
@@ -20,13 +22,13 @@ React Native 使用独立包 `@tinkerlandai/indiana-react-native`,原 `@tinker
|
|
|
20
22
|
|
|
21
23
|
## Funnel Local / Remote 统一执行
|
|
22
24
|
|
|
23
|
-
Local / Remote
|
|
25
|
+
Local / Remote 共用 Indiana Run、command/action 回执、业务服务、幂等和恢复。Local SDK 只预测纯条件、Feature/实验路径用于展示,再提交 `commit_segment` 推进信号;GOP 根据 Run 输入和批准的公共 GB 配置重算并接受路径。Remote 在 GOP 计算,不依赖客户端公共配置。
|
|
24
26
|
|
|
25
27
|
`createLocalFunnelClient().start({ requestId, locale, parameters })` 返回 `runToken` 和同一个 `controller`,传给 `showFunnelRun` 即可。原 Server Key 的商户服务端另外指定原 Indiana Customer UUID;浏览器使用 Customer Token,不能改写 Customer。恢复必须使用安全保存的原 Run token,不能把旧 Local checkpoint 或未知发券结果转换为一个新请求身份。
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
推进信号尚未提交时,Run 停车并释放 Worker,仍需 Local 宿主返回;信号受理后,后台业务操作通过 GOP 的 Cloud Tasks/Cloud Scheduler 恢复。Local SDK 不直接发券,也没有第二套业务执行器。独立 Coupon API 保留自己的自领政策、权限、资格、库存、幂等和有效期,不要求创建 Funnel。
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
Flow `commit_segment` 只包含固定 requestId、停车位置 nodeId/visit/revision、policyRevision 和 generation,不接受调用方步骤、计算结果或边界。SDK 的展示预测服从服务器受理结果;回包丢失使用原命令身份恢复。原生渲染壳复用同一纯求值器与 Run bridge;无界面 Swift/Kotlin 返回待本地推进状态,不自动改成 Remote。详见[Local 执行](README.md#local-funnel-execution)。
|
|
30
32
|
|
|
31
33
|
## 版本兼容与支持
|
|
32
34
|
|
|
@@ -40,32 +42,34 @@ SDK 发送当前协议及 SDK 版本请求头,并校验成功响应的协议
|
|
|
40
42
|
| ---------------------------------------- | ----------------------------------------------------------- |
|
|
41
43
|
| `@tinkerlandai/indiana-sdk` | 浏览器 Customer、Funnel、Feature 与独立 Paywall 客户端 |
|
|
42
44
|
| `@tinkerlandai/indiana-sdk/server` | 可信 Node.js 后端、Customer Session、业务写入和 Funnel 决策 |
|
|
43
|
-
| `@tinkerlandai/indiana-sdk/react-native` | Customer 核心和经认证业务后端转发的用量上报,不含 DOM 展示
|
|
45
|
+
| `@tinkerlandai/indiana-sdk/react-native` | Customer 核心和经认证业务后端转发的用量上报,不含 DOM 展示 |
|
|
44
46
|
| `@tinkerlandai/indiana-sdk/popup` | 独立屏幕渲染、清洗和预览 |
|
|
45
47
|
| `@tinkerlandai/indiana-sdk/openrouter` | 可选 OpenRouter 用量集成,需要安装对应 peer dependency |
|
|
46
48
|
| `@tinkerlandai/indiana-sdk/native-shell` | 原生 WebView 的静态 Funnel shell 资源;不代表商店购买验收 |
|
|
47
49
|
| `@tinkerlandai/indiana-sdk/page` | 匿名商户页面的网址实验;使用公开的 App environment ID |
|
|
48
50
|
| `@tinkerlandai/indiana-sdk/visual` | 匿名商户页面的视觉实验及曝光采集;使用公开的环境 ID |
|
|
49
51
|
|
|
50
|
-
JavaScript 与 TypeScript 共用本包,声明文件随包提供。内部 `@indiana/contracts` 在构建时内联,接入方无需安装私有包。Swift 和 Kotlin
|
|
52
|
+
JavaScript 与 TypeScript 共用本包,声明文件随包提供。内部 `@indiana/contracts` 在构建时内联,接入方无需安装私有包。Swift 和 Kotlin 使用各自的包管理生态与独立产物。
|
|
53
|
+
|
|
54
|
+
展示独立的 **Page、Popup 或 Banner 资源**,从主入口导入 `createIndiana` 和 `mountContent`,先用 `indiana.resolveContent(...)` 解析,再挂载结果。`/page` 用于商户现有页面的 GB 网址跳转实验,`/visual` 用于该页面的 GB 视觉修改;`/popup` 提供底层屏幕渲染与预览工具,不负责选择或解析 Popup 资源。现有公开导入路径保持不变,详见[入口职责](../../docs/sdk-architecture.md#public-entry-points-and-capability-ownership)。
|
|
51
55
|
|
|
52
56
|
独立的 [Python 服务端 SDK](../python/README.md) 使用同一当前 HTTP 协议,提供同步、异步 Customer、持仓/权益检查和用量上报。它从 `https://tinker.cash/sdk/python` 分发(不在 PyPI),不属于这个 npm 包。
|
|
53
57
|
|
|
54
|
-
[Go 服务端 SDK](../go/README.md) 提供同样的首版能力,使用类型化响应、Context 取消和 goroutine 并发复用客户端。通过 Go 默认模块代理以 `go get tinker.cash/sdk/go`
|
|
58
|
+
[Go 服务端 SDK](../go/README.md) 提供同样的首版能力,使用类型化响应、Context 取消和 goroutine 并发复用客户端。通过 Go 默认模块代理以 `go get tinker.cash/sdk/go` 安装,与其他业务 SDK 共用发行版本。
|
|
55
59
|
|
|
56
60
|
## API 默认地址与自测
|
|
57
61
|
|
|
58
62
|
默认地址、四个域名、版本标签和测试配置的持续规范见 [SDK API 入口与开发测试规范](../../docs/sdk-endpoints-and-testing.md)。
|
|
59
63
|
|
|
60
|
-
省略 `baseUrl` 时默认请求 `https://api.tinker.cash`;Customer/Server、Funnel、Feature、Paywall、页面与视觉实验客户端共用此入口。公共配置同步的 `origin` 也可省略并使用同一默认值。Swift `IndianaConfiguration(scope: ...)`、Kotlin `IndianaConfiguration(scope = ...)`
|
|
64
|
+
省略 `baseUrl` 时默认请求 `https://api.tinker.cash`;Customer/Server、Funnel、Feature、Paywall、页面与视觉实验客户端共用此入口。公共配置同步的 `origin` 也可省略并使用同一默认值。Swift `IndianaConfiguration(scope: ...)`、Kotlin `IndianaConfiguration(scope = ...)` 采用同一默认地址与统一发行版本;仍可显式覆盖 `baseURL`/`baseUrl`。Funnel/Paywall 的壳和渲染器随 SDK 本地打包,不从 API origin 下载可执行代码。
|
|
61
65
|
|
|
62
|
-
包含此默认值的版本无论标记为 `beta` 或 `latest`,都使用生产 API
|
|
66
|
+
包含此默认值的版本无论标记为 `beta` 或 `latest`,都使用生产 API 地址。标签选择包版本,不选择服务环境。两套 API 入口经 Vercel 转发到各自 Go Indianapolis,入口和业务就绪分别验收。
|
|
63
67
|
|
|
64
68
|
我们自己测试时,宿主必须显式要求 `INDIANA_TEST_BASE_URL`,缺失就报错,不回落生产默认值。同一轮 Server、Customer、Funnel、页面/视觉客户端的 `baseUrl` 和配置同步的 `origin` 使用同一个测试地址;环境变量由宿主读取,SDK 不自动读取。`environment: "sandbox"` 只选择该服务内的业务环境,不选择部署或数据库。
|
|
65
69
|
|
|
66
|
-
测试 API 地址为 `https://api.dev.tinker.cash`,测试主站/Admin 使用 `dev.tinker.cash`。测试应用配置 `INDIANA_TEST_BASE_URL=https://api.dev.tinker.cash
|
|
70
|
+
测试 API 地址为 `https://api.dev.tinker.cash`,测试主站/Admin 使用 `dev.tinker.cash`。测试应用配置 `INDIANA_TEST_BASE_URL=https://api.dev.tinker.cash`,使用测试环境自己的 App/Key,并核验权限与集成配置。默认地址保持生产 `https://api.tinker.cash`,由测试应用显式覆盖。
|
|
67
71
|
|
|
68
|
-
|
|
72
|
+
维护者验证入口见[测试流程](../../docs/sdk-selfserve.md#maintainer-api-origin-testing)。SDK 契约夹具与真实 GOP 业务测试分别负责,不以旧版本通过数描述当前能力。
|
|
69
73
|
|
|
70
74
|
## 从可信后端创建 Customer Session
|
|
71
75
|
|
|
@@ -102,7 +106,7 @@ const { holdings } = await indiana.readHoldings();
|
|
|
102
106
|
indiana.reset();
|
|
103
107
|
```
|
|
104
108
|
|
|
105
|
-
Indiana 在普通 SDK
|
|
109
|
+
Indiana 在普通 SDK 请求中延续同一 Customer 会话和 Token,默认有效窗口 24 小时、最长 30 天;无需商户续期定时器,也不增加 Refresh Token。撤销和 Key 到期继续生效,授权过期后需要重新认证。见[Customer 凭据](../../docs/customer-credentials.md)。
|
|
106
110
|
|
|
107
111
|
Customer 使用原始业务字段;资料更新是部分 patch,没有 Customer revision。Guest 登录到已有 Customer 时返回 `switched: true`,资源和历史保留原归属,接入方应为目标 Customer 创建新 Session/Funnel;不合并旧 Guest 的财务事实。
|
|
108
112
|
|
|
@@ -217,7 +221,7 @@ Stripe 环境的 `autumn` 模式由 Indiana 执行;`record_only` 返回交给
|
|
|
217
221
|
- `claimRewardProduct` 的完整交付。
|
|
218
222
|
- Apple/Google 真实商店验收。当前独立购买/恢复的协议及部分服务实现不代表商店已验收;`createNativeReceiptClient().recover()` 使用 `subscriptions/native/restore`,不再发送旧 Funnel 原生恢复命令。
|
|
219
223
|
|
|
220
|
-
Live
|
|
224
|
+
已实现商业能力在 Sandbox 与 Live 均沿用原凭据、权限、作用域和真实 Provider 配置检查。未实现操作返回 501;缺少配置或业务前置条件不等于迁移期白名单。
|
|
221
225
|
|
|
222
226
|
## AI 用量
|
|
223
227
|
|
|
@@ -229,11 +233,11 @@ npm 发布不部署 Web 服务、不应用数据库迁移,也不发布 Swift
|
|
|
229
233
|
|
|
230
234
|
版本、冻结产物哈希和 registry 回读见 [发布总账](../../docs/sdk-releases.md);当前架构与实现边界见 [开发状态](../../docs/development-status.md)。
|
|
231
235
|
|
|
232
|
-
##
|
|
236
|
+
## 共享公共配置
|
|
233
237
|
|
|
234
238
|
源码新增 `createConfigurationSync({ origin, scope })`;`scope` 必须明确包含 `projectId`、`environment` 和 `environmentId`。将同一个实例作为 `configuration` 传给 `createIndiana`、Funnel start/Run controller 和 `createPageExperiments`,共用清单、文件缓存、并发请求和更新通知。`/server` 导出的 `createSynchronizedFunnelLocalEvaluator(configuration, funnelId)` 使用同一份规范 Funnel 文件与 GB 代次进行纯判断,保留仅可信服务端执行的边界。
|
|
235
239
|
|
|
236
|
-
|
|
240
|
+
公共配置由匹配运行端发布。公共文件不需要 Customer 凭据;业务操作沿用原凭据和服务端资格检查。完整调用见[英文说明](README.md#shared-public-configuration)。
|
|
237
241
|
|
|
238
242
|
初始化总等待不超过 5 秒;活跃消费者共用 12–15 秒轮询,并在回前台/联网后刷新。Local 控制状态自源站验证起最多有效 60 秒,旧 304 或失败不能续期。暂停/过期后停止新本地判断及客户屏幕;冷启动离线时,仅凭持久缓存不能恢复 active 权限。Indiana Run 的命令与观察直接读取服务端状态,独立于 CDN 控制有效期。
|
|
239
243
|
|
|
@@ -243,12 +247,55 @@ npm 发布不部署 Web 服务、不应用数据库迁移,也不发布 Swift
|
|
|
243
247
|
|
|
244
248
|
`showFunnelRun(container, { client: started.controller })` 在 Local / Remote 都接收同一个服务器 Run controller。屏幕、Customer / Product / Coupon 数据、shown 回执、Paywall、外部任务和未知结果重试共用后端路径。宿主销毁只卸载 UI;停止一个 Run 需要显式提交 Close。Console 私有预览仍是无真实业务效果的模拟。
|
|
245
249
|
|
|
246
|
-
|
|
250
|
+
步骤回执和执行上限共用同一 Contract 与服务器记录;恢复使用原 Run、命令及业务回执。Local 不使用本地 checkpoint 或直接 Coupon 调用持有流程业务义务。独立 `claimCoupon`/`grantOffer` 继续由 Coupon 校验资格、额度、权限和有效期。
|
|
247
251
|
|
|
248
|
-
|
|
252
|
+
完整调用和恢复要求见[统一执行说明](README.md#local-funnel-execution)。
|
|
249
253
|
|
|
250
254
|
## Funnel 资源上下文
|
|
251
255
|
|
|
252
256
|
正式 Local Run 由服务端执行原业务动作,自动携带原 Run、node、visit 和 receipt。消费纯 Funnel 结果时,使用 `indiana.forFunnel({ funnelId, versionId })` 获取固定上下文的客户端;其领取、Offering/Paywall 解析和购买报价自动携带这一个 Funnel。服务端以可信事实复算指定流程,不扫描其他 Funnel。
|
|
253
257
|
|
|
254
258
|
不带上下文的 `indiana.claimCoupon(...)` 仍按 Coupon 自身规则独立领取。未知结果使用原 requestId 和原输入重试;已接受命令在 Funnel 后续暂停时仍返回原结果。
|
|
259
|
+
|
|
260
|
+
## 独立 Page、Popup 与 Banner
|
|
261
|
+
|
|
262
|
+
先发布一个没有必填输入、声明 `continue` 动作的 Banner。Customer Token 需要 `content:read` 权限,再显式读取和挂载。Page/Popup 使用相应 `kind`。
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
import {
|
|
266
|
+
createIndiana,
|
|
267
|
+
mountContent,
|
|
268
|
+
type ContentActionIntent,
|
|
269
|
+
} from "@tinkerlandai/indiana-sdk";
|
|
270
|
+
|
|
271
|
+
export async function showBanner(
|
|
272
|
+
container: HTMLElement,
|
|
273
|
+
customerToken: string,
|
|
274
|
+
contentId: string,
|
|
275
|
+
onContinue: (intent: ContentActionIntent) => Promise<void>,
|
|
276
|
+
) {
|
|
277
|
+
const indiana = createIndiana({
|
|
278
|
+
baseUrl: "https://api.dev.tinker.cash",
|
|
279
|
+
scope: { projectId: "<TEST_APP_UUID>", environment: "sandbox" },
|
|
280
|
+
});
|
|
281
|
+
indiana.identify(customerToken);
|
|
282
|
+
const { content } = await indiana.resolveContent({
|
|
283
|
+
kind: "banner",
|
|
284
|
+
selector: { type: "resource", id: contentId },
|
|
285
|
+
});
|
|
286
|
+
const host = await mountContent(container, {
|
|
287
|
+
content,
|
|
288
|
+
actions: { continue: onContinue },
|
|
289
|
+
onError: console.error,
|
|
290
|
+
});
|
|
291
|
+
return {
|
|
292
|
+
retryAction: host.retryAction,
|
|
293
|
+
destroy() {
|
|
294
|
+
host.destroy();
|
|
295
|
+
indiana.reset();
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
每个声明动作都需要同名 handler。`onContinue` 用 `intent.requestId` 作为业务后端的幂等键;失败后 `retryAction()` 重用原意图。卸载、退出或换号时调用 `destroy()`。宿主只渲染和发出意图,业务后端仍负责鉴权与执行。
|