@revturbine/sdk 0.11.16 → 0.11.17
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 +182 -0
- package/dist/headless.d.ts +372 -18
- package/dist/headless.js +2 -2
- package/dist/headless.js.map +1 -1
- package/dist/index.d.ts +372 -18
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/types/web-sdk/controllers.d.ts.map +1 -1
- package/dist/types/web-sdk/customer-side.d.ts +319 -5
- package/dist/types/web-sdk/customer-side.d.ts.map +1 -1
- package/dist/types/web-sdk/react/RevTurbineProvider.d.ts.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -47,6 +47,188 @@ also require a changelog entry.
|
|
|
47
47
|
|
|
48
48
|
---
|
|
49
49
|
|
|
50
|
+
## 0.11.17
|
|
51
|
+
|
|
52
|
+
### Checkout metadata helper, `checkout_started`, and decision context on interactions (plan 282 TASK-9, BL-0432)
|
|
53
|
+
|
|
54
|
+
**What changed.** Three additive changes to the browser SDK (`@revturbine/sdk`);
|
|
55
|
+
no existing signature narrows.
|
|
56
|
+
|
|
57
|
+
- **`checkoutMetadata(outputId)`** (new, `@public`) returns the Stripe Checkout
|
|
58
|
+
`revturbine_*` metadata bag for an output this SDK decided — user, account,
|
|
59
|
+
placement, decision, output, rule and target plan — plus
|
|
60
|
+
`client_reference_id` (the user id). Pass `metadata` as both the session's
|
|
61
|
+
`metadata` and `subscription_data.metadata`; the mirror is what reaches each
|
|
62
|
+
invoice's `parent.subscription_details.metadata`. A key the SDK does not hold
|
|
63
|
+
is absent, never empty; `null` for an output this SDK did not decide. New
|
|
64
|
+
types `RevTurbineCheckoutMetadata` and `RevTurbineCheckoutMetadataBag`.
|
|
65
|
+
- **`checkout_started`** (taxonomy v6, `@revt-eng/schema` 0.1.381) is emitted on
|
|
66
|
+
a `cta_clicked` whose CTA opens a plan picker or pricing page
|
|
67
|
+
(`CHECKOUT_STARTED_CTA_ACTION_TYPES`: `navigate_to_plans`, `view_plans`) with
|
|
68
|
+
`{ placement_id, payload_id, decision_id, plan_handle, rule_handle }`. Never
|
|
69
|
+
for `open_checkout_modal` — that CTA opens checkout directly ("on click"), so
|
|
70
|
+
its started count is its clicked count.
|
|
71
|
+
- **`trackTreatmentInteraction`** accepts optional `decisionId`,
|
|
72
|
+
`segmentHandles` and `segmentIds` (`RevTurbineTreatmentInteractionDecisionContext`;
|
|
73
|
+
the parameter type is now `RevTurbineTreatmentInteractionRequest`, a
|
|
74
|
+
superset of the previous `RevTurbineTreatmentInteractionInput`) and sends
|
|
75
|
+
them as `decision_id` / `segment_handles` / `segment_ids`. Segments are
|
|
76
|
+
handles: `segment_handles` is the effective set scaffold's `evaluateSegments`
|
|
77
|
+
built plus any hosted-resolved slugs — the analytics join key — and
|
|
78
|
+
`segment_ids` carries only the minted ids a hosted context supplied
|
|
79
|
+
(telemetry; omitted entirely in local mode). When not given, they are filled
|
|
80
|
+
from the output this SDK indexed for `payloadId`; a caller that gives none
|
|
81
|
+
and names no indexed output sends exactly the row it sent before. The React
|
|
82
|
+
controller's clicks and the output-addressed `convert()` / `dismiss()` /
|
|
83
|
+
`snooze()` carry them.
|
|
84
|
+
|
|
85
|
+
**Landed in** 0.11.17. **Fail-closed in** n/a — additive. The headless ports
|
|
86
|
+
(Python, Rust, `server-node`) carry only the re-vendored generated types for
|
|
87
|
+
the 0.1.381 pin; the cross-language parity corpus is untouched.
|
|
88
|
+
|
|
89
|
+
**Docs.** `guides/billing.mdx` "Where checkout fits" now documents the bag, the
|
|
90
|
+
`subscription_data.metadata` mirror, `client_reference_id`, and that Customer
|
|
91
|
+
metadata cannot be set from Checkout.
|
|
92
|
+
|
|
93
|
+
**Proving tests.** `web-sdk/checkout-metadata.test.ts`,
|
|
94
|
+
`web-sdk/checkout-started-emit.test.ts`,
|
|
95
|
+
`web-sdk/interaction-decision-context.test.ts`.
|
|
96
|
+
|
|
97
|
+
### `update({ usage })` now reaches usage and credit threshold placements and their usage tokens (BL-0402, BL-0409)
|
|
98
|
+
|
|
99
|
+
**What changed.** A behaviour fix in the browser SDK (`@revturbine/sdk`); no
|
|
100
|
+
signature changes. `update({ usage })` / `updateUsage()` wrote only the SDK's
|
|
101
|
+
private usage balances. `can()` and `getUsage()` read those balances, but the
|
|
102
|
+
placement resolver built its usage state from the user context's `usage`
|
|
103
|
+
entries alone, and took each entry's `limit` only from a per-entry field
|
|
104
|
+
(default `0`). The shared threshold gate fails closed on a missing or zero
|
|
105
|
+
limit. So `usage_threshold` and `credit_threshold` placements (the 80% usage
|
|
106
|
+
banner, the low-credits warning) never fired for app-reported usage, and
|
|
107
|
+
`{{usage_current}}` / `{{usage_limit}}` / `{{usage_remaining}}` /
|
|
108
|
+
`{{usage_percent}}` stayed stale or unresolved, while the gate and the meter
|
|
109
|
+
moved.
|
|
110
|
+
|
|
111
|
+
Placements now read one usage view, the same one `getUsage()` reports:
|
|
112
|
+
|
|
113
|
+
- **Used**: the balance the app reported through `update({ usage })` /
|
|
114
|
+
`updateUsage()` / `identify(…, { usage })` wins (the most recent write),
|
|
115
|
+
else the context entry's `amount`.
|
|
116
|
+
- **Limit**: the context entry's own `limit` wins, else the Playbook
|
|
117
|
+
allowance for the user's **current plan** (the plan-scoped `usage_limit`
|
|
118
|
+
rule's `limit_value` or `credits` rule's `allowance_value`, which is the
|
|
119
|
+
`limit` `getUsage()` already returned). An `unlimited` or absent allowance
|
|
120
|
+
means no threshold: the placement does not fire.
|
|
121
|
+
- **Tokens**: the SDK now fills the usage token family in decision content
|
|
122
|
+
from the same view. It fills `{{usage_current}}` whenever usage is known.
|
|
123
|
+
It fills `{{usage_limit}}`, `{{usage_remaining}}` and `{{usage_percent}}`
|
|
124
|
+
only when a positive limit is known, so an unlimited allowance leaves
|
|
125
|
+
those tokens untouched instead of rendering `0`. The `<unit>_usage_*`
|
|
126
|
+
forms and the aliases (`current_usage`, `current_limit`,
|
|
127
|
+
`remaining_usage`) are filled too. A registered entitlements provider
|
|
128
|
+
still supplies its own usage state, as before.
|
|
129
|
+
|
|
130
|
+
`can()` and `getUsage()` are unchanged. The headless server ports (Python,
|
|
131
|
+
Rust, `server-node`) take usage counters from the caller and are unaffected;
|
|
132
|
+
the cross-language parity corpus is untouched.
|
|
133
|
+
|
|
134
|
+
**Docs.** `tutorials/usage-quota-meter.mdx` and
|
|
135
|
+
`tutorials/low-credits-warning.mdx` now use the canonical flat Playbook rule
|
|
136
|
+
shape (`kind` + `limit_value` / `allowance_value`, handle-valued ids). The
|
|
137
|
+
old nested `type_fields` shape resolved no allowance, so neither tutorial's
|
|
138
|
+
banner could fire. The expected-behaviour table now matches what the SDK
|
|
139
|
+
does: the banner shows from 80%, and at 100% `can('api_calls')` denies.
|
|
140
|
+
|
|
141
|
+
**Proving test.** `web-sdk/usage-reaches-placements.test.ts`.
|
|
142
|
+
|
|
143
|
+
### App-supplied trial context now reaches trial placements, trial tokens and reverse-trial grants (BL-0403)
|
|
144
|
+
|
|
145
|
+
**What changed.** A behaviour fix in the browser SDK (`@revturbine/sdk`); no
|
|
146
|
+
signature changes. `user.trial` at init, `update({ trial })`,
|
|
147
|
+
`setUserContext({ trial })` and a server action's `userContext` result all
|
|
148
|
+
merged into the user context's `trial`, but neither trial reader looked there.
|
|
149
|
+
The placement resolver's plan state (which gates `trial_started`,
|
|
150
|
+
`trial_progress`, `trial_ending`, `trial_ended` and `trial_converted`
|
|
151
|
+
placements) and the reverse-trial entitlement grants read only the SDK's own
|
|
152
|
+
trial status, written by `localRuntime.initialData.trialStatus`, `hydrate()`,
|
|
153
|
+
`getTrialStatus()` and `setTrialInstances()`. So an app that supplied its
|
|
154
|
+
trial saw no trial placement fire, no reverse-trial grant apply, and
|
|
155
|
+
`{{trial_days_remaining}}` stay raw.
|
|
156
|
+
|
|
157
|
+
Both readers now use one trial view:
|
|
158
|
+
|
|
159
|
+
- **Sources.** The user context's `trial` (what the app supplies, plus the
|
|
160
|
+
authenticated client-context delivery, which merges its trial into the same
|
|
161
|
+
field) and the SDK trial status (`initialData.trialStatus`, `hydrate()`,
|
|
162
|
+
`getTrialStatus()`, `setTrialInstances()`).
|
|
163
|
+
- **Precedence: the most recent change wins**, the same rule the usage view
|
|
164
|
+
applies to reported balances (BL-0402). A server-delivered or hydrated
|
|
165
|
+
status wins when it arrives after the app's trial (an
|
|
166
|
+
`initialData.trialStatus` passed alongside init `user.trial` counts as
|
|
167
|
+
later). An app `update({ trial })` made after it wins over it. Re-sending
|
|
168
|
+
an unchanged trial is not a newer write, so passing the same trial on every
|
|
169
|
+
render never displaces a fresher server status. A source that was never
|
|
170
|
+
supplied does not compete.
|
|
171
|
+
- **Tokens.** The SDK now fills `{{trial_days_remaining}}` and
|
|
172
|
+
`{{trial_days_total}}` in decision content from the same plan state the
|
|
173
|
+
trial gate read. A token whose value is unknown is left untouched.
|
|
174
|
+
- **`getTrialStatus()`** in `local_only` mode with no `getTrialStatus`
|
|
175
|
+
resolver returns this trial view, the app-supplied trial included.
|
|
176
|
+
|
|
177
|
+
**React.** `<RevTurbineProvider>` no longer reports `trial`, `tiers`,
|
|
178
|
+
`payment_failed`, `payment_at_risk`, `instances`, `experiments`, `email_type`,
|
|
179
|
+
`derived_config_version`, `context_hash` or `derived_computed_at` in
|
|
180
|
+
`options.user` as "dropped unrecognized user-context key(s)" on mount. The SDK
|
|
181
|
+
constructor already merges them from `options.user`; the provider now forwards
|
|
182
|
+
only the identity fields `identify()` merges. Unknown keys and server-assigned
|
|
183
|
+
keys are still reported.
|
|
184
|
+
|
|
185
|
+
The headless server ports (Python, Rust, `server-node`) take an
|
|
186
|
+
already-derived trial status and are unaffected; the cross-language parity
|
|
187
|
+
corpus is untouched.
|
|
188
|
+
|
|
189
|
+
**Proving tests.** `web-sdk/trial-reaches-placements.test.ts`,
|
|
190
|
+
`web-sdk/react/RevTurbineProvider.identify-context.test.tsx`.
|
|
191
|
+
|
|
192
|
+
### Trial state no longer leaks across users; app-supplied trials fire lifecycle triggers; `getUserContext()` reports trial and billing fields (BL-0417)
|
|
193
|
+
|
|
194
|
+
**What changed.** Behaviour fixes in the browser SDK (`@revturbine/sdk`)
|
|
195
|
+
that follow up BL-0403. No signature changes.
|
|
196
|
+
|
|
197
|
+
- **Reset and user switch.** `resetIdentity()` / `resetUserContext()`
|
|
198
|
+
cleared the user context but kept the SDK trial status (from
|
|
199
|
+
`initialData.trialStatus`, `hydrate()`, `getTrialStatus()` or
|
|
200
|
+
`setTrialInstances()`). They also kept which trial source was newest and
|
|
201
|
+
the last lifecycle stage. So the next user saw the previous user's trial
|
|
202
|
+
placements, reverse-trial grants and `{{trial_days_*}}` tokens, and a
|
|
203
|
+
trial-less next user could emit `trial_expired`. A reset now clears all of
|
|
204
|
+
that, and the next user starts with no trial. Identifying a **different**
|
|
205
|
+
user without a reset (`identify()`, `setUserContext({ id })`, or a
|
|
206
|
+
`hydrate()` payload for another user) now drops the previous user's trial
|
|
207
|
+
(both sources) and usage (reported balances and context `usage`) before
|
|
208
|
+
merging the new user's values. The new user's own values still apply. Going
|
|
209
|
+
from anonymous to identified, or re-identifying the same user, keeps what
|
|
210
|
+
is held. Reported usage was already cleared on reset; only the
|
|
211
|
+
switch-without-reset path leaked it.
|
|
212
|
+
- **Lifecycle triggers.** `trial_midpoint`, `trial_expiring` and
|
|
213
|
+
`trial_expired` fired only from `getTrialStatus()` and
|
|
214
|
+
`setTrialInstances()`. The SDK now also runs the lifecycle evaluation
|
|
215
|
+
against the resolved trial view after every change that can move it:
|
|
216
|
+
`user.trial` at init, `update({ trial })`, `setUserContext`, a server
|
|
217
|
+
action's context, the client-context delivery, `hydrate()`, a reset, and a
|
|
218
|
+
Playbook load that turns the triggers on. The dedupe has not changed: a
|
|
219
|
+
stage fires only when it differs from the last stage seen. So an unchanged
|
|
220
|
+
trial, or both sources reporting the same threshold, fires once.
|
|
221
|
+
`enableTrialAutoTriggers: false` still silences them.
|
|
222
|
+
- **`getUserContext()`** now includes `trial` (the resolved trial view, the
|
|
223
|
+
one placements and grants decide with), `tiers`, `payment_failed`,
|
|
224
|
+
`payment_at_risk` and `instances` when they are held. The snapshot is a
|
|
225
|
+
copy, so changing it does not change SDK state.
|
|
226
|
+
|
|
227
|
+
The headless server ports are unaffected, and the cross-language parity
|
|
228
|
+
corpus is untouched.
|
|
229
|
+
|
|
230
|
+
**Proving test.** `web-sdk/trial-reset-lifecycle.test.ts`.
|
|
231
|
+
|
|
50
232
|
## 0.11.16
|
|
51
233
|
|
|
52
234
|
### Build fix, part two: the npm declaration build resolves `openapi-fetch` too (no API change)
|