@tinkerlandai/indiana-sdk 0.7.0 → 0.8.1
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 +13 -1
- package/README.md +73 -25
- package/README.zh-CN.md +77 -25
- package/dist/ai-usage-JoM7ZWk-.d.ts +247 -0
- package/dist/{ai-usage-BsrSG955.d.ts → api-JVC7x2FV.d.ts} +337 -386
- package/dist/chunk-3BQFJANQ.js +1 -0
- package/dist/chunk-56AYS7RS.js +1 -0
- package/dist/{chunk-6MO6Y24B.js → chunk-6HG7U6AU.js} +1 -1
- package/dist/chunk-AE4CUTUE.js +1 -0
- package/dist/chunk-AEUFCOFG.js +1 -0
- package/dist/chunk-F767CM3T.js +7 -0
- package/dist/chunk-KSNOXNTC.js +1 -0
- package/dist/{chunk-4AWSZWZD.js → chunk-USLZX2ZA.js} +1 -1
- package/dist/{chunk-YAFMBXIE.js → chunk-X747SY26.js} +1 -1
- package/dist/chunk-X7JJAEQQ.js +350 -0
- package/dist/chunk-YWFNWK7C.js +1 -0
- package/dist/{configuration-sync-Bvd956GL.d.ts → configuration-sync-BexM2qbg.d.ts} +17 -18
- package/dist/content-YNL2CRJZ.js +1 -0
- package/dist/{customer-page-B4LkIr5q.d.ts → customer-page-WUQVK_tp.d.ts} +276 -3
- package/dist/{funnel-runtime-start-ChVYbLzV.d.ts → funnel-local-client-D1Fe7CZ6.d.ts} +2507 -8137
- package/dist/funnel-runtime-host-CAMI6BJS.js +1 -0
- package/dist/index.d.ts +13578 -13442
- package/dist/index.js +1 -1
- package/dist/native-shell.js +1 -1
- package/dist/openrouter.d.ts +5 -3
- package/dist/openrouter.js +1 -1
- package/dist/page.d.ts +4 -4
- package/dist/page.js +1 -1
- package/dist/paywall-MXRMMF3R.js +1 -0
- package/dist/popup.d.ts +3 -271
- package/dist/popup.js +1 -350
- package/dist/react-native.d.ts +7 -7
- package/dist/react-native.js +1 -1
- package/dist/{screen-iFngkxaL.d.ts → screen-i6eHL11m.d.ts} +120 -117
- package/dist/screen-renderer-P7MLBHY5.js +1 -0
- package/dist/server.d.ts +4645 -8
- package/dist/server.js +1 -1
- package/dist/src-G7UQB3QE.js +1 -0
- package/dist/visual.d.ts +5 -2
- package/dist/visual.js +2 -2
- package/package.json +3 -9
- package/dist/chunk-3SONNXFG.js +0 -1
- package/dist/chunk-467Z5ISI.js +0 -11
- package/dist/chunk-4K25DELJ.js +0 -1
- package/dist/chunk-HD74AAFS.js +0 -1
- package/dist/chunk-J4RHVU3W.js +0 -1
- package/dist/chunk-NOFNOHUI.js +0 -1
- package/dist/chunk-QO4YQLZ4.js +0 -1
- package/dist/chunk-U6S6AZM6.js +0 -1
- package/dist/chunk-WCFVNF5D.js +0 -1
- package/dist/client-F6UPJMHR.js +0 -1
- package/dist/controls-XG46TKUU.js +0 -2
- package/dist/funnel-runtime-host-26QI2W3S.js +0 -1
- package/dist/iam.d.ts +0 -131
- package/dist/iam.js +0 -1
- package/dist/paywall-WKOHBYW7.js +0 -1
- package/dist/src-UHLPVD6E.js +0 -1
- /package/dist/{chunk-6X42DWOM.js → chunk-DSPLGTQI.js} +0 -0
- /package/dist/{chunk-S5TVMQRC.js → chunk-EXCPE2XH.js} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
Release facts and artifact evidence: [SDK release ledger](../../docs/sdk-releases.md).
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 0.8.1 — 2026-10-25
|
|
6
|
+
|
|
7
|
+
- Organize SDK implementations by capability while preserving public entry points and interfaces.
|
|
8
|
+
- Consolidate Funnel observed state, pending-command and purchase recovery, and shared request validation without changing credential or execution authority.
|
|
9
|
+
- Share Paywall binding and purchase-observation rules across hosts; keep rendering independent of authenticated clients.
|
|
10
|
+
- Keep the current mutation schema in durable command storage and remove an invalid comparison against the unsupported `evaluate` operation.
|
|
11
|
+
|
|
12
|
+
## 0.8.0 — 2026-10-24
|
|
13
|
+
|
|
14
|
+
- Resolve independent Pages, Popups and Banners and render them through the explicit `mountContent` host entry.
|
|
15
|
+
- Send a Flow Local `commit_segment` as an advance signal with only the parked position, policy revision and configuration generation; the server calculates and accepts the pure path. The local walk is a display-only `controller.prediction` that clears when the accepted response arrives. A pending 0.7 `commit_segment` left in `funnelCommandStorage` is re-derived from the Run's current position instead of replayed. Uses HTTP protocol 0.8; protocol 0.7 is refused.
|
|
16
|
+
- Evaluate every Funnel GB node, Local and Remote, against one attribute view: the Run attributes without raw `parameters`, `answers` or `results`, plus the registered `variables` at that node.
|
|
17
|
+
- Remove the `./iam` entry. Build-time IAM generation moves to `@tinkerlandai/indiana-iam`; the visual entry exports `loadAppManifestRelease` and keeps the `appManifestRelease` option for binding a page to its IAM release.
|
|
6
18
|
|
|
7
19
|
## 0.7.0 — 2026-10-23
|
|
8
20
|
|
package/README.md
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
# @tinkerlandai/indiana-sdk
|
|
2
2
|
|
|
3
|
-
[
|
|
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
4
|
|
|
5
|
-
|
|
5
|
+
[简体中文](./README.zh-CN.md)
|
|
6
6
|
|
|
7
|
-
|
|
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.
|
|
8
8
|
|
|
9
|
-
|
|
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).
|
|
10
10
|
|
|
11
11
|
```sh
|
|
12
|
-
npm install --save-exact @tinkerlandai/indiana-sdk@0.
|
|
12
|
+
npm install --save-exact @tinkerlandai/indiana-sdk@0.8.1
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
|
|
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).
|
|
16
|
+
|
|
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
|
|
|
17
19
|
## React Native core
|
|
18
20
|
|
|
@@ -22,14 +24,15 @@ Use the independent `@tinkerlandai/indiana-react-native` package. The `@tinkerla
|
|
|
22
24
|
|
|
23
25
|
During `0.x`, only the current protocol is supported. Starting with `1.0`, compatibility is preserved within each stable major version. Once the next stable major is published, the preceding stable major remains supported for at least 12 calendar months, with at least 180 days' public notice before retirement. The later deadline applies. See the [support policy](https://tinker.cash/docs/release-notes#support-policy).
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
The SDK sends current protocol and SDK version headers and validates the protocol declared by successful responses. Old 0.x protocols are not converted into the current contract. Updating source code does not change an existing npm artifact or deploy a server.
|
|
26
28
|
|
|
27
|
-
##
|
|
29
|
+
## Public entry points
|
|
28
30
|
|
|
29
31
|
| Import | Purpose |
|
|
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 |
|
|
35
|
+
| `@tinkerlandai/indiana-sdk/react-native` | Portable Customer core and authenticated-backend usage relay; no DOM presentation |
|
|
33
36
|
| `@tinkerlandai/indiana-sdk/popup` | Standalone screen rendering, sanitization, and previews |
|
|
34
37
|
| `@tinkerlandai/indiana-sdk/openrouter` | Optional OpenRouter usage integration; requires its peer dependency |
|
|
35
38
|
| `@tinkerlandai/indiana-sdk/native-shell` | Static Funnel shell assets for native WebViews |
|
|
@@ -38,21 +41,23 @@ Version `0.6.4` sends protocol and SDK version headers and validates the protoco
|
|
|
38
41
|
|
|
39
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.
|
|
40
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
|
+
|
|
41
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.
|
|
42
47
|
|
|
43
|
-
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.
|
|
44
49
|
|
|
45
50
|
## API origin and test services
|
|
46
51
|
|
|
47
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).
|
|
48
53
|
|
|
49
|
-
|
|
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.
|
|
50
55
|
|
|
51
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.
|
|
52
57
|
|
|
53
58
|
For our own testing, always require a test-service address instead of relying on the production default:
|
|
54
59
|
|
|
55
|
-
|
|
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.
|
|
56
61
|
|
|
57
62
|
```ts
|
|
58
63
|
const testBaseUrl = process.env.INDIANA_TEST_BASE_URL;
|
|
@@ -73,7 +78,7 @@ const configuration = createConfigurationSync({
|
|
|
73
78
|
|
|
74
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.
|
|
75
80
|
|
|
76
|
-
|
|
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.
|
|
77
82
|
|
|
78
83
|
## Create a Customer Session from a trusted backend
|
|
79
84
|
|
|
@@ -110,7 +115,7 @@ const { holdings } = await indiana.readHoldings();
|
|
|
110
115
|
indiana.reset();
|
|
111
116
|
```
|
|
112
117
|
|
|
113
|
-
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).
|
|
114
119
|
|
|
115
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.
|
|
116
121
|
|
|
@@ -181,7 +186,7 @@ Sessions retain Sticky assignments in memory. Supply `stickyBucketAssignmentDocs
|
|
|
181
186
|
|
|
182
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.
|
|
183
188
|
|
|
184
|
-
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.
|
|
185
190
|
|
|
186
191
|
### Standalone Feature delivery
|
|
187
192
|
|
|
@@ -208,7 +213,7 @@ unsubscribe();
|
|
|
208
213
|
flags.destroy();
|
|
209
214
|
```
|
|
210
215
|
|
|
211
|
-
|
|
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.
|
|
212
217
|
|
|
213
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.
|
|
214
219
|
|
|
@@ -227,7 +232,7 @@ This beta does not certify complete commercial or production operation. Remainin
|
|
|
227
232
|
- Complete delivery for `claimRewardProduct`.
|
|
228
233
|
- Real Apple/Google store acceptance. Independent purchase/restore contracts and partial services do not certify store acceptance. `createNativeReceiptClient().recover()` uses `subscriptions/native/restore`.
|
|
229
234
|
|
|
230
|
-
|
|
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.
|
|
231
236
|
|
|
232
237
|
## AI usage
|
|
233
238
|
|
|
@@ -239,9 +244,9 @@ Publishing to npm does not deploy Web services, apply database migrations, or re
|
|
|
239
244
|
|
|
240
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.
|
|
241
246
|
|
|
242
|
-
## Shared public configuration
|
|
247
|
+
## Shared public configuration
|
|
243
248
|
|
|
244
|
-
Use one manager per trusted origin and exact App/environment for Features, canonical Funnel files and enabled page experiments.
|
|
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.
|
|
245
250
|
|
|
246
251
|
```ts
|
|
247
252
|
import {
|
|
@@ -277,7 +282,7 @@ Optional browser persistence defaults to localStorage and contains only public b
|
|
|
277
282
|
|
|
278
283
|
## Local Funnel execution
|
|
279
284
|
|
|
280
|
-
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.
|
|
281
286
|
|
|
282
287
|
```ts
|
|
283
288
|
import {
|
|
@@ -308,21 +313,21 @@ started.controller.reset();
|
|
|
308
313
|
|
|
309
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.
|
|
310
315
|
|
|
311
|
-
|
|
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.
|
|
312
317
|
|
|
313
|
-
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.
|
|
314
319
|
|
|
315
320
|
### Shared UI host
|
|
316
321
|
|
|
317
|
-
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.
|
|
318
323
|
|
|
319
|
-
|
|
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.
|
|
320
325
|
|
|
321
|
-
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.
|
|
322
327
|
|
|
323
328
|
## Funnel-scoped resource requests
|
|
324
329
|
|
|
325
|
-
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:
|
|
326
331
|
|
|
327
332
|
```ts
|
|
328
333
|
const resources = indiana.forFunnel({ funnelId, versionId });
|
|
@@ -330,3 +335,46 @@ await resources.claimCoupon(couponId, savedRequestId);
|
|
|
330
335
|
```
|
|
331
336
|
|
|
332
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,66 +1,75 @@
|
|
|
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
|
|
|
7
|
+
业务 SDK 按职责分为 **身份、商业、GrowthBook、Analytics、内容交付(Offering、Paywall、Page、Popup、Banner)和 Funnel 六组能力**,共用协议、传输、配置、渲染与恢复等基础设施。分类沿用系统的 L0–L4 归属,各语言包和入口支持的子集不同。客户端与商户服务端共用契约和核心行为,凭据及可执行操作分开。Indianapolis 是它们调用的 SDK 运行服务,不是商户安装的服务端 SDK。
|
|
8
|
+
|
|
9
|
+
**IAM 的源码扫描、生成、校验和上传属于独立构建包 `@tinkerlandai/indiana-iam`。** 普通业务 SDK 只保留 GB visual 应用页面变更所需的运行时 release 绑定。完整定义见 [SDK 边界](../../docs/sdk-architecture.md) 与 [IAM 构建包](../iam/README.md)。
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install --save-exact @tinkerlandai/indiana-sdk@0.8.1
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
SDK 0.8.1 要求 HTTP 协议 0.8。安装版本须与运行服务匹配;发布包不会部署服务端。实际发布、标签与环境验收范围见 [SDK 发布总账](../../docs/sdk-releases.md) 和 [开发状态](../../docs/development-status.md)。
|
|
16
|
+
|
|
17
|
+
数据/会话层负责公开 JSON、完整性校验和鉴权操作;展示宿主将会话接口接入打包的屏幕渲染器,渲染器消费已提供的数据并返回动作意图。客户端按需加载展示;`/server` 入口使用商户后端的受限 Server Key,不加载屏幕展示。SDK 本地检查不替代运行时授权或付款核实。后台 Preview 为同一个展示宿主提供模拟会话和数据。
|
|
18
|
+
|
|
5
19
|
## React Native 核心入口
|
|
6
20
|
|
|
7
21
|
React Native 使用独立包 `@tinkerlandai/indiana-react-native`,原 `@tinkerlandai/indiana-sdk/react-native` 子入口共用同一实现。两者均支持 Customer Token 身份接入、权益读取和经业务后端转发的用量上报。此入口无需 DOM,不包含原生 UI 或内购桥接。参见[移动端 SDK 安装与示例](../../docs/mobile-sdk.md)。
|
|
8
22
|
|
|
9
23
|
## Funnel Local / Remote 统一执行
|
|
10
24
|
|
|
11
|
-
Local / Remote
|
|
25
|
+
Local / Remote 共用 Indiana Run、command/action 回执、业务服务、幂等和恢复。Local SDK 只预测纯条件、Feature/实验路径用于展示,再提交 `commit_segment` 推进信号;GOP 根据 Run 输入和批准的公共 GB 配置重算并接受路径。Remote 在 GOP 计算,不依赖客户端公共配置。
|
|
12
26
|
|
|
13
27
|
`createLocalFunnelClient().start({ requestId, locale, parameters })` 返回 `runToken` 和同一个 `controller`,传给 `showFunnelRun` 即可。原 Server Key 的商户服务端另外指定原 Indiana Customer UUID;浏览器使用 Customer Token,不能改写 Customer。恢复必须使用安全保存的原 Run token,不能把旧 Local checkpoint 或未知发券结果转换为一个新请求身份。
|
|
14
28
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
步骤记录共用后端限制;历史 `report_progress` 仍是调用方观察,不能当成发券证明。原生渲染壳复用同一个 JS 纯求值器及原生 Run bridge;无界面 Swift/Kotlin 会明确返回待本地求值,不自动切换 Remote。详细使用和迁移边界见[英文说明](README.md#local-funnel-execution)及统一回执。安装本包不会自动迁移数据库或部署服务;浏览器、支付渠道、容量和原生商店验收分别记录。
|
|
18
|
-
|
|
19
|
-
本包版本为 **0.6.4/协议 0.6**,须配套同协议运行时和数据库。Remote Funnel 返回当前页面 JSON,与 Local 共用渲染器,完整 Remote 图和私有规则仍在服务端。公开 npm 0.6.0 已通过 `api.dev.tinker.cash` 的 21 项基础操作,foundation readiness 为 200;Funnel、公共配置、支付执行和生产业务仍有独立验收边界。实际发布、标签和环境状态见[SDK 发布总账](../../docs/sdk-releases.md)。
|
|
29
|
+
推进信号尚未提交时,Run 停车并释放 Worker,仍需 Local 宿主返回;信号受理后,后台业务操作通过 GOP 的 Cloud Tasks/Cloud Scheduler 恢复。Local SDK 不直接发券,也没有第二套业务执行器。独立 Coupon API 保留自己的自领政策、权限、资格、库存、幂等和有效期,不要求创建 Funnel。
|
|
20
30
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
```sh
|
|
24
|
-
npm install --save-exact @tinkerlandai/indiana-sdk@0.6.4
|
|
25
|
-
```
|
|
31
|
+
Flow `commit_segment` 只包含固定 requestId、停车位置 nodeId/visit/revision、policyRevision 和 generation,不接受调用方步骤、计算结果或边界。SDK 的展示预测服从服务器受理结果;回包丢失使用原命令身份恢复。原生渲染壳复用同一纯求值器与 Run bridge;无界面 Swift/Kotlin 返回待本地推进状态,不自动改成 Remote。详见[Local 执行](README.md#local-funnel-execution)。
|
|
26
32
|
|
|
27
33
|
## 版本兼容与支持
|
|
28
34
|
|
|
29
35
|
当前 0.x 仅支持当前协议;1.0 起同一主版本内保持兼容。新稳定主版本发布后,旧稳定主版本至少继续支持 12 个日历月,停止支持提前至少 180 天公开通知,实际日期取两者中较晚者。详见 [版本与支持政策](../../docs/sdk-versioning-and-support.md) 和公开开发文档 `/docs/release-notes#support-policy`。
|
|
30
36
|
|
|
31
|
-
|
|
37
|
+
SDK 发送当前协议及 SDK 版本请求头,并校验成功响应的协议声明;旧 0.x 协议不会自动转换成当前协议。源码更新不会修改已有 npm 包,也不会自动部署服务端。
|
|
32
38
|
|
|
33
|
-
##
|
|
39
|
+
## 公开入口
|
|
34
40
|
|
|
35
41
|
| 导入入口 | 用途 |
|
|
36
42
|
| ---------------------------------------- | ----------------------------------------------------------- |
|
|
37
43
|
| `@tinkerlandai/indiana-sdk` | 浏览器 Customer、Funnel、Feature 与独立 Paywall 客户端 |
|
|
38
44
|
| `@tinkerlandai/indiana-sdk/server` | 可信 Node.js 后端、Customer Session、业务写入和 Funnel 决策 |
|
|
45
|
+
| `@tinkerlandai/indiana-sdk/react-native` | Customer 核心和经认证业务后端转发的用量上报,不含 DOM 展示 |
|
|
39
46
|
| `@tinkerlandai/indiana-sdk/popup` | 独立屏幕渲染、清洗和预览 |
|
|
40
47
|
| `@tinkerlandai/indiana-sdk/openrouter` | 可选 OpenRouter 用量集成,需要安装对应 peer dependency |
|
|
41
48
|
| `@tinkerlandai/indiana-sdk/native-shell` | 原生 WebView 的静态 Funnel shell 资源;不代表商店购买验收 |
|
|
42
49
|
| `@tinkerlandai/indiana-sdk/page` | 匿名商户页面的网址实验;使用公开的 App environment ID |
|
|
43
50
|
| `@tinkerlandai/indiana-sdk/visual` | 匿名商户页面的视觉实验及曝光采集;使用公开的环境 ID |
|
|
44
51
|
|
|
45
|
-
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)。
|
|
46
55
|
|
|
47
56
|
独立的 [Python 服务端 SDK](../python/README.md) 使用同一当前 HTTP 协议,提供同步、异步 Customer、持仓/权益检查和用量上报。它从 `https://tinker.cash/sdk/python` 分发(不在 PyPI),不属于这个 npm 包。
|
|
48
57
|
|
|
49
|
-
[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 共用发行版本。
|
|
50
59
|
|
|
51
60
|
## API 默认地址与自测
|
|
52
61
|
|
|
53
62
|
默认地址、四个域名、版本标签和测试配置的持续规范见 [SDK API 入口与开发测试规范](../../docs/sdk-endpoints-and-testing.md)。
|
|
54
63
|
|
|
55
|
-
|
|
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 下载可执行代码。
|
|
56
65
|
|
|
57
|
-
包含此默认值的版本无论标记为 `beta` 或 `latest`,都使用生产 API
|
|
66
|
+
包含此默认值的版本无论标记为 `beta` 或 `latest`,都使用生产 API 地址。标签选择包版本,不选择服务环境。两套 API 入口经 Vercel 转发到各自 Go Indianapolis,入口和业务就绪分别验收。
|
|
58
67
|
|
|
59
68
|
我们自己测试时,宿主必须显式要求 `INDIANA_TEST_BASE_URL`,缺失就报错,不回落生产默认值。同一轮 Server、Customer、Funnel、页面/视觉客户端的 `baseUrl` 和配置同步的 `origin` 使用同一个测试地址;环境变量由宿主读取,SDK 不自动读取。`environment: "sandbox"` 只选择该服务内的业务环境,不选择部署或数据库。
|
|
60
69
|
|
|
61
|
-
测试 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`,由测试应用显式覆盖。
|
|
62
71
|
|
|
63
|
-
|
|
72
|
+
维护者验证入口见[测试流程](../../docs/sdk-selfserve.md#maintainer-api-origin-testing)。SDK 契约夹具与真实 GOP 业务测试分别负责,不以旧版本通过数描述当前能力。
|
|
64
73
|
|
|
65
74
|
## 从可信后端创建 Customer Session
|
|
66
75
|
|
|
@@ -97,7 +106,7 @@ const { holdings } = await indiana.readHoldings();
|
|
|
97
106
|
indiana.reset();
|
|
98
107
|
```
|
|
99
108
|
|
|
100
|
-
Indiana 在普通 SDK
|
|
109
|
+
Indiana 在普通 SDK 请求中延续同一 Customer 会话和 Token,默认有效窗口 24 小时、最长 30 天;无需商户续期定时器,也不增加 Refresh Token。撤销和 Key 到期继续生效,授权过期后需要重新认证。见[Customer 凭据](../../docs/customer-credentials.md)。
|
|
101
110
|
|
|
102
111
|
Customer 使用原始业务字段;资料更新是部分 patch,没有 Customer revision。Guest 登录到已有 Customer 时返回 `switched: true`,资源和历史保留原归属,接入方应为目标 Customer 创建新 Session/Funnel;不合并旧 Guest 的财务事实。
|
|
103
112
|
|
|
@@ -212,7 +221,7 @@ Stripe 环境的 `autumn` 模式由 Indiana 执行;`record_only` 返回交给
|
|
|
212
221
|
- `claimRewardProduct` 的完整交付。
|
|
213
222
|
- Apple/Google 真实商店验收。当前独立购买/恢复的协议及部分服务实现不代表商店已验收;`createNativeReceiptClient().recover()` 使用 `subscriptions/native/restore`,不再发送旧 Funnel 原生恢复命令。
|
|
214
223
|
|
|
215
|
-
Live
|
|
224
|
+
已实现商业能力在 Sandbox 与 Live 均沿用原凭据、权限、作用域和真实 Provider 配置检查。未实现操作返回 501;缺少配置或业务前置条件不等于迁移期白名单。
|
|
216
225
|
|
|
217
226
|
## AI 用量
|
|
218
227
|
|
|
@@ -224,11 +233,11 @@ npm 发布不部署 Web 服务、不应用数据库迁移,也不发布 Swift
|
|
|
224
233
|
|
|
225
234
|
版本、冻结产物哈希和 registry 回读见 [发布总账](../../docs/sdk-releases.md);当前架构与实现边界见 [开发状态](../../docs/development-status.md)。
|
|
226
235
|
|
|
227
|
-
##
|
|
236
|
+
## 共享公共配置
|
|
228
237
|
|
|
229
238
|
源码新增 `createConfigurationSync({ origin, scope })`;`scope` 必须明确包含 `projectId`、`environment` 和 `environmentId`。将同一个实例作为 `configuration` 传给 `createIndiana`、Funnel start/Run controller 和 `createPageExperiments`,共用清单、文件缓存、并发请求和更新通知。`/server` 导出的 `createSynchronizedFunnelLocalEvaluator(configuration, funnelId)` 使用同一份规范 Funnel 文件与 GB 代次进行纯判断,保留仅可信服务端执行的边界。
|
|
230
239
|
|
|
231
|
-
|
|
240
|
+
公共配置由匹配运行端发布。公共文件不需要 Customer 凭据;业务操作沿用原凭据和服务端资格检查。完整调用见[英文说明](README.md#shared-public-configuration)。
|
|
232
241
|
|
|
233
242
|
初始化总等待不超过 5 秒;活跃消费者共用 12–15 秒轮询,并在回前台/联网后刷新。Local 控制状态自源站验证起最多有效 60 秒,旧 304 或失败不能续期。暂停/过期后停止新本地判断及客户屏幕;冷启动离线时,仅凭持久缓存不能恢复 active 权限。Indiana Run 的命令与观察直接读取服务端状态,独立于 CDN 控制有效期。
|
|
234
243
|
|
|
@@ -238,12 +247,55 @@ npm 发布不部署 Web 服务、不应用数据库迁移,也不发布 Swift
|
|
|
238
247
|
|
|
239
248
|
`showFunnelRun(container, { client: started.controller })` 在 Local / Remote 都接收同一个服务器 Run controller。屏幕、Customer / Product / Coupon 数据、shown 回执、Paywall、外部任务和未知结果重试共用后端路径。宿主销毁只卸载 UI;停止一个 Run 需要显式提交 Close。Console 私有预览仍是无真实业务效果的模拟。
|
|
240
249
|
|
|
241
|
-
|
|
250
|
+
步骤回执和执行上限共用同一 Contract 与服务器记录;恢复使用原 Run、命令及业务回执。Local 不使用本地 checkpoint 或直接 Coupon 调用持有流程业务义务。独立 `claimCoupon`/`grantOffer` 继续由 Coupon 校验资格、额度、权限和有效期。
|
|
242
251
|
|
|
243
|
-
|
|
252
|
+
完整调用和恢复要求见[统一执行说明](README.md#local-funnel-execution)。
|
|
244
253
|
|
|
245
254
|
## Funnel 资源上下文
|
|
246
255
|
|
|
247
256
|
正式 Local Run 由服务端执行原业务动作,自动携带原 Run、node、visit 和 receipt。消费纯 Funnel 结果时,使用 `indiana.forFunnel({ funnelId, versionId })` 获取固定上下文的客户端;其领取、Offering/Paywall 解析和购买报价自动携带这一个 Funnel。服务端以可信事实复算指定流程,不扫描其他 Funnel。
|
|
248
257
|
|
|
249
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()`。宿主只渲染和发出意图,业务后端仍负责鉴权与执行。
|