@tinkerlandai/indiana-sdk 0.6.3 → 0.6.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/CHANGELOG.md +14 -2
- package/README.md +8 -4
- package/README.zh-CN.md +7 -3
- package/THIRD_PARTY_NOTICES.md +28 -0
- package/dist/{chunk-QG4GM4RI.js → chunk-2EJSV6BA.js} +1 -1
- package/dist/{chunk-YAMBRNJ2.js → chunk-63BWE27V.js} +1 -1
- package/dist/{chunk-FF3LWJ26.js → chunk-HTRQPMJO.js} +3 -3
- package/dist/chunk-QG3WUJG5.js +1 -0
- package/dist/errors-DrdTlPwf.d.ts +57 -0
- package/dist/{funnel-runtime-host-KPYLOYYN.js → funnel-runtime-host-NWS3URFA.js} +1 -1
- package/dist/{funnel-runtime-start-CVb2YonU.d.ts → funnel-runtime-start-sZ8ZCNlq.d.ts} +2 -55
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/openrouter.js +1 -1
- package/dist/{paywall-5WU6PX5C.js → paywall-4XZ6NDMY.js} +1 -1
- package/dist/react-native.d.ts +327 -0
- package/dist/react-native.js +1 -0
- package/dist/server.d.ts +3 -2
- package/dist/server.js +1 -1
- package/dist/{src-U7PBAUBN.js → src-WV6GZYWA.js} +1 -1
- package/package.json +10 -3
- package/dist/chunk-FVUPV6YE.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,9 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
Release facts and artifact evidence: [SDK release ledger](../../docs/sdk-releases.md).
|
|
4
4
|
|
|
5
|
-
## Unreleased
|
|
5
|
+
## Unreleased
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## 0.6.4 — 2026-10-23
|
|
8
|
+
|
|
9
|
+
- Publish JS, React Native, Python, Go, SwiftPM and Maven packages at the shared version 0.6.4, retaining HTTP protocol 0.6.
|
|
10
|
+
- Include the independent RN core and native Customer Token identity, entitlement checks and authenticated backend usage relay.
|
|
11
|
+
- Verify immutable public artifacts and fresh consumers for every package before completing the GitHub Release.
|
|
12
|
+
|
|
13
|
+
- Add the independent `@tinkerlandai/indiana-react-native` package and shared React Native core entry for Customer identity, holdings, entitlement checks and backend-mediated usage reporting.
|
|
14
|
+
|
|
15
|
+
## 0.6.3 — 2026-10-23
|
|
16
|
+
|
|
17
|
+
- Align JS, Python and Go package versions at 0.6.3; retain HTTP protocol 0.6 and immutable earlier releases.
|
|
18
|
+
- Bound optional persistent-cache reads and download the pinned Funnel and GB artifacts together, preserving the five-second initialization budget and artifact validation.
|
|
19
|
+
- Wait for the original display acknowledgement to settle and read the current Run before processing the first action; retain the original request identity during recovery.
|
|
8
20
|
|
|
9
21
|
## 0.6.2 — 2026-10-22
|
|
10
22
|
|
package/README.md
CHANGED
|
@@ -2,23 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
[简体中文](./README.zh-CN.md)
|
|
4
4
|
|
|
5
|
-
Version **0.6.
|
|
5
|
+
Version **0.6.3 / protocol 0.6** requires a matching Indiana runtime and database. Remote Funnel responses contain the current page's `ScreenDocument` JSON; Local and Remote use the same renderer, canonical Run, business receipts and Queue recovery. Remote graphs and private rules stay on the server.
|
|
6
6
|
|
|
7
|
-
Version 0.6.
|
|
7
|
+
Version 0.6.3 bounds optional persistent-cache reads, downloads the pinned Funnel and GB artifacts in parallel, and waits for the original display acknowledgement to settle before processing the first action. It preserves the five-second initialization budget, artifact verification, current-screen input patches and recovery after Back. Publication uses GitHub Actions with npm Trusted Publishing. Complete production browser and Stripe acceptance remains separate; see the [repair report](../../docs/deployment-receipts/20261022-sdk-funnel-repair/README.md).
|
|
8
8
|
|
|
9
9
|
Pin this package to a matching protocol 0.6 service. The published npm 0.6.0 package passes 21 foundation operations through `https://api.dev.tinker.cash`, with readiness 200 and correlated Go request logs; remaining capabilities and production business dependencies have separate gates. npm publication does not extend that accepted scope. Actual publication, tags and environment state are recorded in the [release ledger](../../docs/sdk-releases.md).
|
|
10
10
|
|
|
11
11
|
```sh
|
|
12
|
-
npm install --save-exact @tinkerlandai/indiana-sdk@0.6.
|
|
12
|
+
npm install --save-exact @tinkerlandai/indiana-sdk@0.6.3
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Indiana's JavaScript and TypeScript SDK supports browsers, Node.js, screen rendering and optional AI usage integrations. Environment collection controls and existing Invoice/billing-window contracts remain available. Older 0.x protocols are rejected before business execution.
|
|
16
16
|
|
|
17
|
+
## React Native core
|
|
18
|
+
|
|
19
|
+
Use the independent `@tinkerlandai/indiana-react-native` package. The `@tinkerlandai/indiana-sdk/react-native` subpath shares the same implementation. Both support Customer Token identity, holdings, entitlement checks and usage reporting through your authenticated backend. It requires no DOM or native UI/store bridge. See [mobile SDK installation and examples](../../docs/mobile-sdk.md).
|
|
20
|
+
|
|
17
21
|
## Version compatibility and support
|
|
18
22
|
|
|
19
23
|
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).
|
|
20
24
|
|
|
21
|
-
Version `0.6.
|
|
25
|
+
Version `0.6.3` sends protocol and SDK version headers and validates the protocol declared by successful responses. Headerless historical clients retain the fixed identity `0.2`; they do not follow the current protocol automatically. Updating source code does not change an existing npm artifact or deploy a server.
|
|
22
26
|
|
|
23
27
|
## One package, seven entry points
|
|
24
28
|
|
package/README.zh-CN.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
# @tinkerlandai/indiana-sdk
|
|
4
4
|
|
|
5
|
+
## React Native 核心入口
|
|
6
|
+
|
|
7
|
+
React Native 使用独立包 `@tinkerlandai/indiana-react-native`,原 `@tinkerlandai/indiana-sdk/react-native` 子入口共用同一实现。两者均支持 Customer Token 身份接入、权益读取和经业务后端转发的用量上报。此入口无需 DOM,不包含原生 UI 或内购桥接。参见[移动端 SDK 安装与示例](../../docs/mobile-sdk.md)。
|
|
8
|
+
|
|
5
9
|
## Funnel Local / Remote 统一执行
|
|
6
10
|
|
|
7
11
|
Local / Remote 只区分纯条件、Feature / 实验和 Feature 选择在哪里计算。正式流程都使用 Indiana 的同一个 Run、command/action 回执、业务服务、幂等和 Queue 恢复。Local SDK 计算结果并提交固定节点命令,后端领取并执行发券、等待、重试;Remote 在 Indiana 计算。Remote 不依赖公共 CDN 初始化。
|
|
@@ -12,12 +16,12 @@ Local / Remote 只区分纯条件、Feature / 实验和 Feature 选择在哪里
|
|
|
12
16
|
|
|
13
17
|
步骤记录共用后端限制;历史 `report_progress` 仍是调用方观察,不能当成发券证明。原生渲染壳复用同一个 JS 纯求值器及原生 Run bridge;无界面 Swift/Kotlin 会明确返回待本地求值,不自动切换 Remote。详细使用和迁移边界见[英文说明](README.md#local-funnel-execution)及统一回执。安装本包不会自动迁移数据库或部署服务;浏览器、支付渠道、容量和原生商店验收分别记录。
|
|
14
18
|
|
|
15
|
-
本包版本为 **0.6.
|
|
19
|
+
本包版本为 **0.6.3/协议 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)。
|
|
16
20
|
|
|
17
|
-
0.6.
|
|
21
|
+
0.6.3 限制可选持久缓存的读取等待,并行读取固定的 Funnel/GB 产物,在原展示命令结算后再处理首次点击。保留五秒初始化预算、产物校验、当前 Screen 输入 patch 和 Back 后恢复,通过 GitHub Actions 与 npm Trusted Publishing 发布。完整生产浏览器与 Stripe 验收分别记录,见[修复报告](../../docs/deployment-receipts/20261022-sdk-funnel-repair/README.md)。
|
|
18
22
|
|
|
19
23
|
```sh
|
|
20
|
-
npm install --save-exact @tinkerlandai/indiana-sdk@0.6.
|
|
24
|
+
npm install --save-exact @tinkerlandai/indiana-sdk@0.6.3
|
|
21
25
|
```
|
|
22
26
|
|
|
23
27
|
## 版本兼容与支持
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -71,3 +71,31 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
71
71
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
72
72
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
73
73
|
SOFTWARE.
|
|
74
|
+
|
|
75
|
+
# whatwg-url-minimum 0.2.0
|
|
76
|
+
|
|
77
|
+
Bundled URL implementation from https://github.com/expo/whatwg-url-minimum.
|
|
78
|
+
|
|
79
|
+
MIT License
|
|
80
|
+
|
|
81
|
+
Copyright (c) Phil Pluckthun,
|
|
82
|
+
Copyright (c) 650 Industries, Inc. (aka Expo),
|
|
83
|
+
Copyright (c) Sebastian Mayr
|
|
84
|
+
|
|
85
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
86
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
87
|
+
in the Software without restriction, including without limitation the rights
|
|
88
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
89
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
90
|
+
furnished to do so, subject to the following conditions:
|
|
91
|
+
|
|
92
|
+
The above copyright notice and this permission notice shall be included in all
|
|
93
|
+
copies or substantial portions of the Software.
|
|
94
|
+
|
|
95
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
96
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
97
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
98
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
99
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
100
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
101
|
+
SOFTWARE.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$d as M,_d as E,ae as j,be as O,ce as T}from"./chunk-
|
|
1
|
+
import{$d as M,_d as E,ae as j,be as O,ce as T}from"./chunk-HTRQPMJO.js";import{a as u}from"./chunk-5TEZEOHX.js";import{h as w}from"./chunk-RMJJOSVZ.js";import{z as t}from"zod";var _=E,V=t.string().regex(/^(0|[1-9]\d{0,5})(\.\d{1,12})?$/),C=t.strictObject(Object.fromEntries(_.map(i=>[i,t.number().int().nonnegative().max(1e9)]))),L=M,D=j,q=t.strictObject({modelId:L,source:t.enum(["models.dev","custom"]),fetchedAt:t.iso.datetime(),rates:O,contextTier:t.number().int().nonnegative(),markupPercent:D}),U=t.strictObject({pricing:q,tokens:C,quantity:w,digest:t.string().regex(/^[a-f0-9]{64}$/)}),z=i=>{let[s,o=""]=i.split(".");return BigInt(s)*10n**12n+BigInt(o.padEnd(12,"0"))};function $(i){if(typeof i!="number"||!Number.isFinite(i)||i<0)throw new u("AI_PRICE_UNAVAILABLE","A published token price is missing");let s=String(i),o=s.includes("e")?i.toFixed(12).replace(/0+$/,"").replace(/\.$/,""):s;if(Number(o)!==i||!V.safeParse(o).success)throw new u("AI_PRICE_UNAVAILABLE","Published price exceeds the supported precision");return o}var R=t.strictObject({input:t.number().nonnegative(),output:t.number().nonnegative(),cache_read:t.number().nonnegative().optional(),cache_write:t.number().nonnegative().optional(),reasoning:t.number().nonnegative().optional(),input_audio:t.number().nonnegative().optional(),output_audio:t.number().nonnegative().optional()}),F=R.extend({context_over_200k:t.unknown().optional(),tiers:t.array(R.extend({tier:t.strictObject({type:t.literal("context"),size:t.number().int().nonnegative()})})).max(20).refine(i=>new Set(i.map(s=>s.tier.size)).size===i.length).optional()});async function N(i,s,o){let d=new TextEncoder().encode(JSON.stringify({pricing:i,tokens:s,quantity:o}));return[...new Uint8Array(await crypto.subtle.digest("SHA-256",d))].map(m=>m.toString(16).padStart(2,"0")).join("")}function B(i,s){let o=0n;for(let c of _){if(!s[c])continue;let f=i.rates[c];if(f===void 0)throw new u("AI_PRICE_UNAVAILABLE",`No published price for ${c}; report exclusive token pools`);o+=z(f)*BigInt(s[c])}let[d,m="0"]=String(i.markupPercent).split("e"),r=(d.split(".")[1]?.length??0)-Number(m),e=10n**BigInt(Math.max(r,0)),n=BigInt(d.replace(".",""))*10n**BigInt(Math.max(-r,0)),g=100n*e+n,l=100n*e*1000000n,a=(o*g+l-1n)/l;return w.parse(`${a/1000000n}.${(a%1000000n).toString().padStart(6,"0")}`)}function K(i={}){if(typeof window<"u")throw new u("SERVER_ONLY","AI token pricing belongs on your backend");let s=T.parse({defaultMarkup:i.defaultMarkup??0,providerMarkups:i.providerMarkups??{},modelMarkups:i.modelMarkups??{},customModels:i.customModels??{}}),o=null,d=0;async function m(){if(!o||Date.now()>=d){d=Date.now()+15*6e4;let r=(async()=>{let e=await(i.fetch??fetch)("https://models.dev/api.json",{signal:AbortSignal.timeout(3e4)});if(!e.ok)throw new u("AI_PRICE_UNAVAILABLE","Models.dev pricing is unavailable");return{data:t.record(t.string(),t.object({models:t.record(t.string(),t.unknown())})).parse(await e.json()),fetchedAt:new Date().toISOString()}})().catch(e=>{throw o===r&&(o=null),e});o=r}return o}return{refreshPrices(){o=null,d=0},async quoteTokens(r){let e=L.parse(r.modelId),n=C.parse(r.tokens),[g,...l]=e.split("/"),a=s.customModels[e],c,f,p,y=0;if(a?.input!==void 0&&a.output!==void 0&&_.every(A=>n[A]===0||a[A]!==void 0))c={...a,input:a.input,output:a.output},f="custom",p=new Date().toISOString();else{let A=await m(),x=A.data[g]?.models[l.join("/")];if(!x)throw new u("AI_PRICE_UNAVAILABLE","Unknown model; configure a complete custom price");let{cost:I}=t.object({cost:F}).parse(x),P=n.input+n.cache_read+n.cache_write+n.input_audio;if(I.tiers===void 0&&I.context_over_200k!==void 0&&P>2e5)throw new u("AI_PRICE_UNAVAILABLE","A current context tier is required for this model");let b=I.tiers?.filter(k=>P>k.tier.size).sort((k,Q)=>Q.tier.size-k.tier.size)[0],v=b??I;b&&(y=b.tier.size),c=Object.fromEntries(_.filter(k=>v[k]!==void 0).map(k=>[k,$(v[k])])),c={...c,...a},f=a?"custom":"models.dev",p=A.fetchedAt}let h=q.parse({modelId:e,source:f,fetchedAt:p,rates:c,contextTier:y,markupPercent:s.modelMarkups[e]??s.providerMarkups[g]??s.defaultMarkup}),S=B(h,n);return U.parse({pricing:h,tokens:n,quantity:S,digest:await N(h,n,S)})},async trackTokens(r,e){let n=U.parse(e.quote);if(n.quantity!==B(n.pricing,n.tokens)||n.digest!==await N(n.pricing,n.tokens,n.quantity))throw new u("INVALID_REQUEST","AI quote changed after pricing");let g=e.properties??{},l=e.providerCostUsd===void 0?void 0:t.string().regex(/^(0|[1-9]\d{0,11})(\.\d{1,18})?$/).parse(e.providerCostUsd),a=e.generationId===void 0?void 0:t.string().min(1).max(120).parse(e.generationId),c=8+ +(l!==void 0)+ +(a!==void 0);if(Object.keys(g).some(p=>p.startsWith("ai_")))throw new u("INVALID_REQUEST","AI tracking reserves ai_ event properties");if(Object.keys(g).length>16-c)throw new u("INVALID_REQUEST","AI tracking properties exceed the available event budget");let f={operation:"consume",internal_feature_id:e.internal_feature_id,quantity:n.quantity,idempotencyKey:e.idempotencyKey,properties:{...g,...l!==void 0?{ai_provider_cost_usd:l}:{},...a!==void 0?{ai_generation_id:a}:{},ai_model:n.pricing.modelId,ai_source:n.pricing.source,ai_price_at:n.pricing.fetchedAt,ai_quote_hash:n.digest,ai_markup:String(n.pricing.markupPercent),ai_tier:String(n.pricing.contextTier),ai_tokens:_.map(p=>n.tokens[p]).join(","),ai_rates:"v1:"+_.map(p=>n.pricing.rates[p]===void 0?"-":z(n.pricing.rates[p]).toString(36)).join(",")},...e.entityId?{entityId:e.entityId}:{}};return r.mutateBalance({customerId:e.customerId,command:f})}}}async function Y(i,s,o={}){let{config:d,model_markups:m}=await i.readAiPricing(s);return K({defaultMarkup:d.default_markup??0,providerMarkups:Object.fromEntries(Object.entries(d.provider_markups??{}).map(([r,e])=>[r,e.markup])),modelMarkups:Object.fromEntries(Object.entries(m??{}).filter(([,r])=>r.markup!==void 0).map(([r,e])=>[r,e.markup])),customModels:Object.fromEntries(Object.entries(m??{}).filter(([,r])=>r.input_cost!==void 0||r.output_cost!==void 0).map(([r,e])=>[r,{...e.input_cost!==void 0?{input:String(e.input_cost)}:{},...e.output_cost!==void 0?{output:String(e.output_cost)}:{}}])),...o})}export{q as a,U as b,K as c,Y as d};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as we}from"./chunk-FVUPV6YE.js";import{$k as Ke,Bf as Ue,Ei as Ee,Ek as H,Fi as ke,Fk as je,Gd as Le,Jk as Pe,Kk as M,Lk as Je,Mk as Be,Nk as ze,Oi as Se,Ok as He,Pi as qe,Rh as be,Vf as ce,al as $e,bl as Qe,cl as Ye,hk as Ge,ui as te,xf as Ve,yf as Me}from"./chunk-FF3LWJ26.js";import{a as d}from"./chunk-5TEZEOHX.js";import{a as Ae}from"./chunk-S5TVMQRC.js";import{b as _e,h as ge}from"./chunk-ISUXYPYL.js";import{f as De,j as xe,m as Ne}from"./chunk-S2MSIA57.js";function yn(e){let n=null,i=null,t=0,m=0,y=new Set,o=null,u=null,r=new Set,s=()=>{for(let I of r)try{I()}catch{}},g={attributes:Ne.parse(e.attributes??{}),onFeatureUsage:e.onFeatureUsage?(I,P)=>{!y.has(I)&&(!n||!("analyticsConfig"in n)||n.analyticsConfig.featureUsageEnabled)&&e.onFeatureUsage(I,structuredClone(P))}:void 0,onExperimentViewed:e.onExperimentViewed?(I,P)=>(!n||!("analyticsConfig"in n)||n.analyticsConfig.experimentViewsEnabled)&&e.onExperimentViewed(structuredClone(I),structuredClone(P)):void 0,stickyBucketAssignmentDocs:structuredClone(e.stickyBucketAssignmentDocs),saveStickyBucketAssignmentDoc:e.saveStickyBucketAssignmentDoc?I=>e.saveStickyBucketAssignmentDoc(structuredClone(I)):void 0,trackedFeatureUsage:{},trackedExperiments:new Set},w=()=>({value:null,source:"unknownFeature",on:!1,off:!0,ruleId:""});function v(I,P=new Set){return y.has(I)?!o||!o.features[I]||["unknownFeature","cyclicPrerequisite"].includes(o.features[I].source):P.has(I)?!1:(P.add(I),(n?.features[I]?.rules??[]).some(F=>[...F.parentConditions??[],...(F.tracks??[]).flatMap(D=>D.experiment.parentConditions??[])].some(D=>v(D.id,P))))}let A=I=>{if(e.assertUsable?.(n?.generation),!n)throw new Error("Initialize the Feature client before evaluation");if(n.expiresAt&&Date.parse(n.expiresAt)<=Date.now())throw new Error("Feature configuration expired; refresh before evaluation");return o?.expiresAt&&Date.parse(o.expiresAt)<=Date.now()&&(o=null,g.features=n.features),y.has(I)?!o||o.expiresAt&&Date.parse(o.expiresAt)<=Date.now()?w():structuredClone(o.features[I]??w()):v(I)?w():structuredClone(xe(I,g))};async function E(){if(!n||!y.size)return;if(!e.evaluateRemote)throw new Error("Remote Feature evaluation requires a server loader");let I=m;if(u?.revision===I)return u.loading;let P=t,F=n,D=[...y],T=(async()=>{let _=Ue.parse(await e.evaluateRemote({attributes:structuredClone(g.attributes),features:D}));if(!(P!==t||I!==m||F!==n)){if(e.assertUsable?.(F.generation),_.generation!==F.generation)throw new Error("Feature configuration changed; refresh before evaluation");if(D.some(U=>!Object.hasOwn(_.features,U))||Object.keys(_.features).some(U=>!y.has(U)))throw new Error("Invalid remote Feature results");o=structuredClone(_),g.features={...F.features,...Object.fromEntries(Object.entries(o.features).map(([U,j])=>[U,{defaultValue:j.value}]))},s()}})();u={revision:I,loading:T};try{await T}finally{u?.loading===T&&(u=null)}}function S(){E().catch(I=>{try{e.onError?.(I)}catch{}})}async function V(){if(i)return i;let I=t,P=(async()=>{let F=await e.load(),D="remoteFeatures"in F?Ve.parse(F):null,T=D??ge.parse(F);if(T.scope.projectId!==e.scope.projectId||T.scope.environment!==e.scope.environment)throw new Error("Feature payload scope changed");if(I!==t)throw new Error("Feature client was reset");if(e.assertUsable&&n?.generation===T.generation){let{evaluatedAt:U,expiresAt:j,...oe}=n,{evaluatedAt:X,expiresAt:ee,...l}=T;if(M(oe)!==M(l))throw new Error("Immutable Feature generation changed content");return n.evaluatedAt=T.evaluatedAt,n.expiresAt=T.expiresAt,s(),(!o||o.expiresAt&&Date.parse(o.expiresAt)<=Date.now())&&S(),structuredClone(n)}let _=new Set(D?.remoteFeatures??[]);if([..._].some(U=>Object.hasOwn(T.features,U)))throw new Error("Remote Feature definitions must not be delivered locally");return n&&"analyticsConfig"in n&&"analyticsConfig"in T&&!n.analyticsConfig.experimentViewsEnabled&&D?.analyticsConfig.experimentViewsEnabled&&g.trackedExperiments?.clear(),n=structuredClone(T),y=_,o=null,u=null,m++,g.features=n.features,g.savedGroups=De(n.savedGroups),g.trackedFeatureUsage={},s(),S(),structuredClone(n)})();i=P;try{return await P}finally{i===P&&(i=null)}}return{init:V,refresh:V,refreshRemote:E,get generation(){return n?.generation??null},get expiresAt(){return n?.expiresAt??null},subscribe(I){return r.add(I),()=>{r.delete(I)}},setAttributes(I){g.attributes=Ne.parse(I),m++,o=null,u=null,g.features=n?.features??{},g.trackedFeatureUsage={},s(),S()},evalFeature:A,isOn(I){return A(I).on},isOff(I){return A(I).off},getFeatureValue(I,P){let F=A(I).value;return structuredClone(F===null?P:F)},reset(){t++,m++,i=null,u=null,n=null,o=null,y.clear(),g.features={},g.savedGroups={},g.stickyBucketAssignmentDocs={},g.attributes={},g.trackedFeatureUsage={},g.trackedExperiments?.clear(),s()}}}function Ze(e){let n,i,t=()=>new d("COMMAND_STORAGE_INVALID","Durable command storage is unavailable"),m=Promise.resolve().then(async()=>{if(n=e.storage??globalThis.localStorage,i=e.locks??globalThis.navigator?.locks,!n||!i||!globalThis.crypto?.subtle)throw t();let u=new TextEncoder().encode(JSON.stringify([new URL(e.baseUrl??Ae).href,e.runToken])),r=new Uint8Array(await crypto.subtle.digest("SHA-256",u));return"indiana.funnel.commands.v1."+Array.from(r,s=>s.toString(16).padStart(2,"0")).join("")});m.catch(()=>{});async function y(u){try{let r=await m;return await i.request(r,{mode:"exclusive"},()=>u(r))}catch(r){throw r instanceof d?r:t()}}function o(u){let r=n.getItem(u);if(r===null)return{revision:0,entry:null};if(r.length>1048576)throw t();let s=JSON.parse(r);if(!s||typeof s!="object"||!("revision"in s)||!("entry"in s)||!Number.isSafeInteger(s.revision)||Number(s.revision)<0)throw t();return{revision:Number(s.revision),entry:s.entry}}return{read:()=>y(o),write:(u,r)=>y(s=>{if(o(s).revision!==u)return null;if(!Number.isSafeInteger(u+1))throw t();return n.setItem(s,JSON.stringify({revision:u+1,entry:r})),u+1})}}function Rn(e,n){return n.type==="id"?e.customerId===n.value:e.externalUserId===n.value}function ye(e,n){if(e===n)return!0;if(Array.isArray(e)||Array.isArray(n))return Array.isArray(e)&&Array.isArray(n)&&e.length===n.length&&e.every((m,y)=>ye(m,n[y]));if(!e||!n||typeof e!="object"||typeof n!="object")return!1;let i=Object.entries(e),t=Object.entries(n);return i.length===t.length&&i.every(([m,y])=>Object.hasOwn(n,m)&&ye(y,Reflect.get(n,m)))}var de=(e,n)=>new d(e,n);function Fn(e){return Ke(e,de)}function ln(e,n,i){return Qe(e,n,i,de)}async function We(e,n){let i=n.instruction;if(i?.type!=="evaluate")throw new Error("Evaluation instruction required");if(!e)throw new d("CONFIGURATION_UNAVAILABLE","Local conditions require the shared public configuration manager");let t=await e.funnel(n.source.id,n.source.versionId);if(!t.growth||t.control.evaluationMode!=="local"||t.control.evaluationRevision!==i.policyRevision)throw new d("EVALUATION_MODE","Refresh the original Funnel evaluation policy");let{analyticsConfig:m,remoteFeatures:y,...o}=t.growth,u=Se({scope:{projectId:e.scope.projectId,environment:e.scope.environment},funnelId:n.source.id,versionId:n.source.versionId,evaluationMode:"local",evaluationRevision:i.policyRevision,document:t.document,payload:ge.parse(o)});if(e.scope.environmentId!==i.environmentId)throw new d("SCOPE_MISMATCH","Evaluation environment changed");let r=ln(u,n.nodeId,i);return e.assertFunnel(n.source.id,void 0,n.source.versionId),{generation:t.manifest.generation,result:r}}async function Xe(e,n){let i=n.instruction;if(i?.type!=="evaluate_segment")throw new Error("Local segment instruction required");if(!e)throw new d("CONFIGURATION_UNAVAILABLE","Local execution requires public configuration");let t=await e.funnel(n.source.id,n.source.versionId);if(!t.growth||t.control.evaluationMode!=="local"||t.control.evaluationRevision!==i.policyRevision)throw new d("EVALUATION_MODE","Refresh the original Funnel evaluation policy");if(e.scope.environmentId!==i.environmentId)throw new d("SCOPE_MISMATCH","Evaluation environment changed");let{analyticsConfig:m,remoteFeatures:y,...o}=t.growth,u=Se({scope:{projectId:e.scope.projectId,environment:e.scope.environment},funnelId:n.source.id,versionId:n.source.versionId,evaluationMode:"local",evaluationRevision:i.policyRevision,document:t.document,payload:ge.parse(o)}),r=cn(u,t.document,{...n,...i});return e.assertFunnel(n.source.id,void 0,n.source.versionId),{...r,generation:t.manifest.generation,policyRevision:i.policyRevision}}function cn(e,n,i){return Ye(e,n,i,de)}import{z as Q}from"zod";var en=te.refine(e=>!["start","get","review"].includes(e.operation)&&!("customerToken"in e),"Persist only the original mutation, without credentials").transform(e=>{if(e.operation==="start"||e.operation==="get"||e.operation==="review")throw new d("COMMAND_STORAGE_INVALID","Stored mutation required");return e}),nn=Q.strictObject({schemaVersion:Q.literal(1),scope:_e,runId:Q.uuid(),funnelId:Q.uuid(),versionId:Q.uuid(),command:en.optional(),closeCommand:en.refine(e=>e.operation==="close").optional(),purchase:Q.strictObject({receiptId:Q.uuid(),operationId:Q.uuid(),generation:Q.number().int().nonnegative()}).optional(),closed:Q.literal(!0).optional()}).refine(e=>!e.closeCommand||e.command&&e.command.operation!=="close"&&e.command.requestId!==e.closeCommand.requestId,"Close requires a separate request identity").refine(e=>e.command!==void 0||e.purchase!==void 0,"A recovery record requires an original obligation"),J=()=>new d("COMMAND_STORAGE_CONFLICT","Another host changed this Run's pending command"),Fe=(e,n)=>JSON.stringify(e)===JSON.stringify(n);function tn(e){let n=0,i=null,t=r=>JSON.stringify([r.scope,r.runId,r.funnelId,r.versionId]),m=Promise.resolve();async function y(){let r=await e.read();if(!Number.isSafeInteger(r.revision)||r.revision<0)throw new d("COMMAND_STORAGE_INVALID","Invalid command storage revision");return{revision:r.revision,entry:r.entry===null?null:nn.parse(r.entry)}}function o(r){let s=m.then(r);return m=s.catch(()=>{}),s}async function u(r){for(let s=0;s<4;s++){let g=await y();if(g.entry&&i!==null&&t(g.entry)!==i)throw J();let w=r(g.entry,g.revision);if(Fe(g.entry,w)){n=g.revision;return}let v=await e.write(g.revision,w);if(v!==null){if(!Number.isSafeInteger(v)||v<=g.revision)throw J();n=v;return}}throw J()}return{bind(r){let s=JSON.stringify([r.scope,r.runId,r.funnelId,r.versionId]);if(i!==null&&i!==s)throw J();i=s},async load(){let r=await y();return n=r.revision,i=r.entry?t(r.entry):null,r.entry},retain(r){let s=nn.parse(r),g=s.command;return!g||i!==null&&t(s)!==i?Promise.reject(J()):(i??=t(s),o(()=>u((w,v)=>{if(w&&!Fe(t(w),t(s)))throw J();if(!w){if(v!==n&&g.operation!=="close")throw J();return s}if(!w.command)return{...w,command:g,...g.operation==="close"?{closed:!0}:{}};if(g.operation==="close"&&w.command.operation!=="close"){if(w.command.requestId===g.requestId||w.closeCommand&&!Fe(w.closeCommand,g))throw J();return{...w,closeCommand:g,closed:!0}}if(!Fe(w.command,g))throw J();return w})))},observePurchase(r,s,g){return o(()=>u((w,v)=>{if(!w&&v!==n||w&&t(w)!==t({...r,schemaVersion:1}))throw J();if(w?.purchase&&w.purchase.generation>s.generation)return w;if(w?.purchase&&w.purchase.generation===s.generation&&w.purchase.operationId!==s.operationId)throw J();return g?!w?.purchase||w.purchase.operationId!==s.operationId?w:w.command?{...w,purchase:void 0}:null:{schemaVersion:1,...r,...w,purchase:s}}))},settle(r){return o(()=>u(s=>s?s.command&&"requestId"in s.command&&s.command.requestId===r?s.closeCommand?{...s,command:s.closeCommand,closeCommand:void 0}:s.purchase?{...s,command:void 0}:null:s.closeCommand&&"requestId"in s.closeCommand&&s.closeCommand.requestId===r?{...s,closeCommand:void 0}:s:null))}}}function fe(e){let{customerToken:n,...i}=e;return i}var dn=e=>!(e instanceof d)||e.status===void 0||e.status>=500||[401,425].includes(e.status);function rn(e){if(e={...e},typeof e.runToken!="string"||!/^gg_fr_[A-Za-z0-9_-]{43}$/.test(e.runToken))throw new d("INVALID_TOKEN","Run credential required");if(e.serverKey&&(typeof window<"u"||!/^gg_sk_[A-Za-z0-9_-]{32,128}$/.test(e.serverKey)))throw new d("SERVER_ONLY","Run Server-Key proof belongs to the merchant backend");let n=we({...e,...e.serverKey?{fetch:(l,c)=>{let N=new Headers(c?.headers);return N.set(ke,e.serverKey),(e.fetch??globalThis.fetch)(l,{...c,headers:N})}}:{},timeoutMs:e.timeoutMs??35e3});n.identify(e.runToken);let i,t=null,m=0,y=0,o=null,u=null,r=!1,s=null,g=!1,w=null,v=new Set,A=e.funnelCommandStorage??(typeof window<"u"&&window.isSecureContext?Ze(e):void 0),E=A&&tn(A),S,V=null,I=!1,P=E?E.load().then(l=>{if(I)throw new d("IDENTITY_CHANGED","Controller was reset during command restoration");if(V=l,!l)return;if(e.scope&&(l.scope.projectId!==e.scope.projectId||l.scope.environment!==e.scope.environment))throw new d("SCOPE_MISMATCH","Pending command belongs to another scope");if(S=l.purchase,r=l.closed===!0,!l.command)return;let c=te.parse(l.command);if(c.operation==="start"||c.operation==="get"||c.operation==="review")throw new d("COMMAND_STORAGE_INVALID","Stored mutation required");o=c,l.closeCommand&&(u=l.closeCommand,r=!0),c.operation==="close"&&(r=!0),g=!0}):Promise.resolve();P.catch(()=>{});async function F(l,c,N){E&&await P;let k=m,Y=t,a=Ee.parse(await n.request("funnels",te.parse(l)));if(l.operation==="review"&&!a.review)throw new d("INVALID_RESPONSE","Historical projection is missing");if(k!==m)throw new d("IDENTITY_CHANGED","Run identity changed during the request");if(a.runToken&&a.runToken!==e.runToken)throw new d("INVALID_RESPONSE","Run credential changed");let B=l.operation==="get"?l.settlementRequestId:"requestId"in l&&l.operation!=="start"?l.requestId:void 0;if(B&&a.settlement?.requestId!==B)throw new d("INVALID_RESPONSE","Exact command settlement is missing or belongs to another command");if(V&&(a.run.id!==V.runId||a.run.source.id!==V.funnelId||a.run.source.versionId!==V.versionId))throw new d("SCOPE_MISMATCH","Stored command belongs to another Run or Version");if(t&&(a.run.id!==t.id||a.run.source.type!==t.source.type||a.run.source.id!==t.source.id||a.run.source.versionId!==t.source.versionId||a.run.locale!==t.locale||!ye(a.run.parameters,t.parameters)))throw new d("INVALID_RESPONSE","Run version changed");if(e.funnelId&&a.run.source.id!==e.funnelId)throw new d("INVALID_RESPONSE","Run belongs to another Funnel");E?.bind({scope:a.scope,runId:a.run.id,funnelId:a.run.source.id,versionId:a.run.source.versionId}),A&&!e.scope&&(e.scope=a.scope);let K=a.run.paywall,z=K??a.purchase,me=z?.operation,pe=a.settlement&&(!K||K.purchaseRequestId===a.settlement.requestId)&&(!S||S.operationId===a.settlement.operationId)?a.settlement:void 0,ie=me?.operationId??z?.quote?.operationId??pe?.operationId,ae=z?.receiptId??pe?.receiptId,Ie=K?.selectionGeneration??S?.generation??0;if(E&&ie&&ae&&l.operation!=="review"&&(!t||a.run.revision>=t.revision)&&(N===void 0||N>=y)&&(!S||Ie>=S.generation)){let $={receiptId:ae,operationId:ie,generation:Ie},Ce=me?.status==="complete"||z?.canReselect===!0;await E.observePurchase({scope:a.scope,runId:a.run.id,funnelId:a.run.source.id,versionId:a.run.source.versionId},$,Ce),Ce?S?.operationId===$.operationId&&(S=void 0):S=$}if(!a.run.stopped&&["running","waiting"].includes(a.run.status)&&l.operation==="get"&&l.settlementRequestId)return a;let se=c?.(a),he=typeof se=="boolean"?se:se?await se:!1;if(["running","waiting"].includes(a.run.status)||(r=!0),l.operation==="review"&&t&&t!==Y&&a.run.revision<=t.revision||t&&a.run.revision===t.revision&&N!==void 0&&N<y||(l.operation==="review"&&!a.run.stopped&&["running","waiting"].includes(a.run.status)&&t&&a.run.nodeId===t.nodeId&&a.run.visit===t.visit&&a.run.revision===t.revision&&(a.run.screen=t.screen,(t.paywall?.quote?.operationId===a.review?.activeOperationId||!t.paywall?.quote&&a.review?.activeOperationId===null)&&(a.run.paywall=t.paywall)),t?.paywall&&a.run.paywall&&t.paywall.receiptId===a.run.paywall.receiptId&&(a.run.paywall.selectionGeneration??0)<(t.paywall.selectionGeneration??0)))return a;if(!t||a.run.revision>=t.revision)t=a.run;else if(!he)return a;if(t)for(let $ of v)try{$(structuredClone(t))}catch{}return a}async function D(l=o){if(E&&await P,!l)throw new d("INVALID_REQUEST","No command is pending");let c=l,N=m;if(E){if(!t||!e.scope)throw new d("COMMAND_STORAGE_INVALID","Read the original scoped Run before persisting a mutation");await E.retain({schemaVersion:1,scope:e.scope,runId:t.id,funnelId:t.source.id,versionId:t.source.versionId,command:fe(c)})}if(N!==m||o!==c&&u!==c)throw new d("IDENTITY_CHANGED","Run changed before command dispatch");let k={...c,...i?{customerToken:i}:{}},Y=g;g=!0;try{return await F(k,a=>{if(!a.settlement)throw new d("INVALID_RESPONSE","Exact command settlement is missing");if(a.settlement.requestId!==c.requestId)throw new d("INVALID_RESPONSE","Command settlement identity changed");if(N===m&&(o===c||u===c)&&a.run.pendingRequest?.requestId!==c.requestId&&a.settlement.state==="settled"&&(!r||c.operation==="close"||a.settlement?.state==="settled"&&!["running","waiting"].includes(a.run.status))){let B=()=>N!==m||o!==c&&u!==c?!1:(o===c&&(o=null),u===c&&(u=null),g=o!==null,V=null,!0);return E?E.settle(c.requestId).then(B):B()}return!1})}catch(a){throw N===m&&o===c&&!Y&&!dn(a)&&(E&&await E.settle(c.requestId),N===m&&o===c&&(o=null,g=!1,V=null)),a}}function T(l){let c=te.parse(l);if(c.operation==="start"||c.operation==="get"||c.operation==="review")throw new d("INVALID_REQUEST","Mutation required");if(t?.recoveryRestricted&&c.operation!=="close"&&c.operation!=="resume"&&o?.requestId!==c.requestId)throw new d("PRECONDITION_FAILED","Original Run requires restricted recovery");if(r&&c.operation!=="close"){if(o?.requestId===c.requestId)return ee.settle(c.requestId);throw new d("COMMAND_PENDING","Close preserves the original recovery record; settle it by identity")}if(c.operation==="close"&&o?.operation!=="close"){if(r=!0,u&&JSON.stringify(fe(u))!==JSON.stringify(fe(c)))throw new d("COMMAND_PENDING","Retry the original Close");if(u??=c,s)return s;let k=D(u);return s=k,k.then(()=>{s===k&&(s=null)},()=>{s===k&&(s=null)}),k}if(o){if(JSON.stringify(fe(o))!==JSON.stringify(fe(c)))throw new d("COMMAND_PENDING","Retry the original command before sending another");if(w)return w}else o=c,g=!1;let N=D();return w=N,N.then(()=>{w===N&&(w=null)},()=>{w===N&&(w=null)}),N}let _=null,U=new WeakMap;function j(l){let c=U.get(l);if(c)return c;let N=X(l);return U.set(l,N),N}let oe=!1;async function X(l){let c=await l;if(c.run.recoveryRestricted||!["evaluate","evaluate_segment"].includes(c.run.instruction?.type??""))return c;if(_)return _;oe=!0;let N=m,k=(async()=>{for(let Y=0;Y<32&&["evaluate","evaluate_segment"].includes(c.run.instruction?.type??"");Y++){if(o||r)return c;let a=c.run,B=c.run.instruction;if(B?.type==="evaluate_segment"){let z=await Xe(e.configuration,a);if(N!==m)throw new d("IDENTITY_CHANGED","Run identity changed during segment calculation");if(o||r)return c;if(t&&(t.revision!==a.revision||t.visit!==a.visit||t.nodeId!==a.nodeId))return F({operation:"get",...i?{customerToken:i}:{}});c=await T({operation:"commit_segment",requestId:be(a.id,a.visit,`segment:${a.revision}`),nodeId:a.nodeId,visit:a.visit,revision:a.revision,...z});continue}if(B?.type!=="evaluate")return c;let K=await We(e.configuration,a);if(N!==m)throw new d("IDENTITY_CHANGED","Run identity changed during evaluation");if(o||r)return c;if(t&&(t.revision!==a.revision||t.visit!==a.visit||t.nodeId!==a.nodeId))return F({operation:"get",...i?{customerToken:i}:{}});c=await T({operation:"evaluate",requestId:be(a.id,a.visit,"evaluation"),nodeId:a.nodeId,visit:a.visit,revision:a.revision,receiptId:B.receiptId,policyRevision:B.policyRevision,...K})}return c})();_=k;try{return await k}finally{_===k&&(_=null)}}let ee={get configuration(){return oe?e.configuration:void 0},get configurationReady(){return!0},get view(){return t?structuredClone(t):null},get pendingCommand(){let l=u??o;return l?structuredClone(fe(l)):null},get pendingCommands(){return[o,u].filter(l=>l!==null).map(l=>structuredClone(fe(l)))},get pendingPurchase(){return S?structuredClone(S):null},async settle(l){let c=await F({operation:"get",settlementRequestId:l,...i?{customerToken:i}:{}});if(c.settlement?.requestId!==l)throw new d("INVALID_RESPONSE","Exact command settlement is missing");return c.settlement.state==="settled"&&(E&&await E.settle(l),o?.requestId===l&&(o=null,g=!1),u?.requestId===l&&(u=null)),c},get webViewUrl(){return n.webViewUrl()},review(l){return F({operation:"review",...l?{receiptId:l}:{},...i?{customerToken:i}:{}},void 0,++y)},async get(l,c){E&&await P,c??=S&&{receiptId:S.receiptId,operationId:S.operationId};let N=++y;return j(F({operation:"get",...l?{data:l}:{},...c?{purchase:c}:{},...i?{customerToken:i}:{}},void 0,N))},resume(l=t?.pendingRequest?.requestId){return l?r?ee.settle(l):o?.requestId===l?j(T(o)):j(T({operation:"resume",requestId:l})):Promise.reject(new d("INVALID_REQUEST","No interrupted command is available"))},submit(l){return j(T(l))},retry(){return s||(u?D(u):r&&o?ee.settle(o.requestId):w?j(w):o?j(T(o)):Promise.reject(new d("INVALID_REQUEST","No command is pending")))},identify(l){if(!/^gg_ct_[A-Za-z0-9_-]{43}$/.test(l))throw new d("INVALID_TOKEN","Customer credential required");m++,i=l,n.identify(e.runToken)},subscribe(l){return v.add(l),()=>v.delete(l)},reset(){I=!0,m++,i=void 0,t=null,o=null,u=null,s=null,g=!1,w=null,n.reset(),v.clear()}};return ee}async function Zn(e,n){if(!/^gg_ct_[A-Za-z0-9_-]{43}$/.test(n.customerToken))throw new d("INVALID_TOKEN","A verified Customer credential is required");let i=we(e);i.identify(n.customerToken);let t=ce.resolvePaywall.request.parse({funnelId:n.funnelId,funnelVersionId:n.funnelVersionId,selector:n.paywallVersionId?{type:"version",versionId:n.paywallVersionId}:{type:"paywall",paywallId:n.paywallId},commerce:n.commerce,locale:n.locale,...n.requirement?{requirement:n.requirement}:{}}),m=null,y=null,o=null,u=null,r=null;async function s(){let v=ce.resolvePaywall,A=v.response.parse(await i.request(v.path,v.request.parse({...t,selector:m?{type:"version",versionId:m.id}:t.selector})));if(n.paywallVersionId?A.paywall.id!==n.paywallVersionId:A.paywall.paywallId!==n.paywallId)throw new d("INVALID_RESPONSE","The requested Paywall changed");if(m&&(A.paywall.id!==m.id||A.paywall.paywallId!==m.paywallId||A.paywall.offering.id!==m.offering.id))throw new d("INVALID_RESPONSE","The pinned Paywall or Offering Version changed");return m=A.paywall,structuredClone(m)}async function g(v){if(!y)throw new d("INVALID_REQUEST","A quoted purchase is required");let A=v==="read"?ce.readSubscriptionOperation:ce.attach,E=A.response.parse(await i.request(A.path,A.request.parse({operationId:y.operationId,...v==="read"?{}:{intent:v}})));if(E.operation.operationId!==y.operationId||E.operation.currency!==t.commerce.currency)throw new d("INVALID_RESPONSE","The purchase operation changed");return o?.status==="complete"&&E.operation.status!=="complete"||o&&o.status!=="pending"&&E.operation.status==="pending"||(o=E.operation),structuredClone(o)}let w={get view(){return m?structuredClone(m):null},get quote(){return y?structuredClone(y):null},get operation(){return o?structuredClone(o):null},get webViewUrl(){return i.webViewUrl()},refresh:s,async preview(v){if(!m)throw new d("INVALID_REQUEST","Load the Paywall first");let A=m.document.buttons[v.actionId];if(A?.type!=="checkout")throw new d("INVALID_REQUEST","Choose an authored purchase action");let E=Le(A.product,v.selection,m.capabilities);if(!E)throw new d("PRODUCT_UNAVAILABLE","Choose an available Product");let S=ce.previewAttach.request.parse({funnelId:t.funnelId,funnelVersionId:t.funnelVersionId,requestId:v.requestId,plans:[{productVersionId:E}],provider:t.commerce.provider,currency:t.commerce.currency,...v.offerId?{offerId:v.offerId}:{},...v.nativeOffer?{nativeOffer:v.nativeOffer}:{}}),V=JSON.stringify(S);if(u&&u!==V&&(!o||o.status==="pending"))throw new d("COMMAND_PENDING","Finish or cancel the original purchase before changing it");if(u===V){if(r)return r;if(y)return structuredClone(y)}u=V;let I=(async()=>{let P=ce.previewAttach,F=P.response.parse(await i.request(P.path,S));if(F.quote.currency!==t.commerce.currency||F.quote.provider!==t.commerce.provider||F.quote.lines.length!==1||F.quote.lines[0].productVersionId!==E)throw new d("INVALID_RESPONSE","The purchase quote changed its selected Product or presentment");return y=F.quote,o=null,structuredClone(y)})();r=I;try{return await I}finally{r===I&&(r=null)}},confirm:()=>g("confirm"),cancel:()=>g("cancel"),read:()=>g("read"),destroy(){i.reset(),m=null,y=null,o=null,u=null}};return await s(),w}import{z as gn}from"zod";import{z as ve}from"zod";var fn=ve.record(ve.string().regex(/^[a-f0-9]{64}$/),ve.strictObject({at:ve.number(),text:ve.string()})),on=2*1048576,mn=100;function pn(){try{return typeof window>"u"?void 0:window.localStorage}catch{return}}function an(e,n){let i=n===void 0?pn():n,t=Promise.resolve();async function m(o){if(!i)return null;let u;try{return await Promise.race([Promise.resolve().then(()=>i.getItem(o)),new Promise(r=>{u=setTimeout(()=>r(null),mn)})])}catch{return null}finally{clearTimeout(u)}}async function y(){try{let o=await m(`${e}:artifacts`);if(o&&o.length<=on)return fn.parse(JSON.parse(o))}catch{}return{}}return{async readManifest(){return m(e)},writeManifest(o){Promise.resolve().then(()=>i?.setItem(e,o)).catch(()=>{})},async readArtifact(o){let u=(await y())[o];return u&&Date.now()>=u.at&&Date.now()-u.at<=H.retentionMs?u.text:void 0},writeArtifact(o,u){i&&(t=t.catch(()=>{}).then(async()=>{let r=await y(),s=Date.now();r[o]={at:s,text:u};let g={},w=2,v=0;for(let[A,E]of Object.entries(r).sort(([,S],[,V])=>V.at-S.at)){if(E.at>s||s-E.at>H.retentionMs)continue;let S=new TextEncoder().encode(JSON.stringify({[A]:E})).byteLength;w+S>on||v>=128||(g[A]=E,w+=S,v++)}await i.setItem(`${e}:artifacts`,JSON.stringify(g))}).catch(()=>{}))}}}var R=(e,n)=>new d(e,n),re=()=>performance.now(),sn=e=>{typeof e=="object"&&"unref"in e&&e.unref()};function st(e){let n=je.parse(e.scope),i=new URL(e.origin??Ae);if(i.username||i.password||i.search||i.hash||i.pathname!=="/"||i.protocol!=="https:"&&!(i.protocol==="http:"&&["localhost","127.0.0.1","[::1]"].includes(i.hostname)))throw R("INVALID_URL","Configuration requires a trusted HTTPS origin");let t=new Set([i.origin,...(e.assetOrigins??[]).map(p=>{let f=new URL(p);if(f.protocol!=="https:"||f.username||f.password||f.search||f.hash||f.pathname!=="/")throw R("INVALID_URL","Invalid configuration asset origin");return f.origin})]),m=e.fetch??globalThis.fetch.bind(globalThis),y=`/api/v1/configuration/${n.environmentId}`,o=`indiana:configuration:1:${i.origin}:${M(n)}`,u=an(o,e.storage),r,s=0,g=0,w=!1,v=!1,A=0,E=0,S,V,I,P,F=0,D=new Set,T=new Set,_=new Map,U=new Map,j=0,oe=!1;function X(){for(let p of D)try{p()}catch{}}function ee(p){try{e.onError?.(p)}catch{}}let l=()=>!v&&!w&&!!r&&re()<s&&Date.now()<g;function c(){if(!l())throw R("CONFIGURATION_EXPIRED","Refresh configuration before using it")}function N(p,f){let C=new TextEncoder().encode(f).byteLength;if(!_.has(p)){for(;_.size&&(_.size>=128||j+C>H.maxCacheBytes);){let h=_.entries().next().value;j-=new TextEncoder().encode(h[1]).byteLength,_.delete(h[0])}_.set(p,f),j+=C}}async function k(p,f,C){if(Number(p.headers.get("content-length"))>f)throw R("INVALID_RESPONSE","Configuration exceeds its byte limit");let h=p.body?.getReader();if(!h)throw R("INVALID_RESPONSE","Configuration body is missing");let b=[],L=0;try{for(;;){C.throwIfAborted();let x=await h.read();if(x.done)break;if(L+=x.value.length,L>f)throw R("INVALID_RESPONSE","Configuration exceeds its byte limit");b.push(x.value)}}finally{await h.cancel().catch(()=>{})}C.throwIfAborted();let O=new Uint8Array(L),G=0;for(let x of b)O.set(x,G),G+=x.length;return new TextDecoder("utf-8",{fatal:!0}).decode(O)}function Y(p){let f=new URL(p,i);if(!t.has(f.origin)||f.username||f.password||f.hash||f.search)throw R("INVALID_URL","Configuration artifact origin is not trusted");return f.href}async function a(p,f,C=!1){let h=await m(Y(p),{method:"GET",credentials:"omit",redirect:"error",cache:C?"default":"no-cache",signal:f,headers:{}});if(h.status===429){let b=h.headers.get("retry-after")??"";F=/^\d+$/.test(b)?Number(b)*1e3:Math.max(0,Date.parse(b)-Date.now())||15e3}if(!h.ok&&h.status!==304)throw R(`CONFIGURATION_HTTP_${h.status}`,"Configuration synchronization failed");return h}function B(p,f,C){let h=Date.parse(p.headers.get("x-indiana-config-validated-at")??""),b=Date.parse(p.headers.get("x-indiana-config-valid-until")??""),L=Date.parse(p.headers.get("date")??""),O=p.headers.get("age"),G=O!==null&&/^\d+(\.\d+)?$/.test(O)?Number(O)*1e3:NaN;if(![h,b,L,G].every(Number.isFinite)||b<=h||b-h>H.maxControlAgeMs||h>L+1e3)throw R("INVALID_RESPONSE","Configuration freshness evidence is invalid");let q=Math.min(b-h,C.maxControlAgeSeconds*1e3,H.maxControlAgeMs)-Math.max(G,L-h,0)-(re()-f);if(q<=0)throw R("CONFIGURATION_EXPIRED","Configuration validation expired in transit");return re()+q}function K(){if(clearTimeout(I),clearTimeout(P),v||!D.size)return;l()&&(P=setTimeout(()=>{l()?K():X()},Math.max(1,s-re())),sn(P));let p=E?Math.min(15e3,1e3*2**Math.min(E-1,4)):Math.min(15e3,(r?.policy.refreshIntervalSeconds??15)*1e3);I=setTimeout(()=>{z().catch(ee)},Math.max(F,p*(.8+Math.random()*.2))),sn(I)}async function z(){if(v)throw R("CONFIGURATION_DISPOSED","Configuration manager was destroyed");if(S)return S;let p=A,f=new AbortController;V=f;let C=(async()=>{if(!oe){oe=!0;try{let Re=await u.readManifest();if(Re&&!r){let W=Pe.parse(JSON.parse(Re));M(W.scope)===M(n)&&(r=W)}}catch{}}f.signal.throwIfAborted();let O=r,G=re(),x=await a(y,f.signal);x.status===304&&(!O||!x.headers.has("x-indiana-config-validated-at")||!x.headers.has("x-indiana-config-valid-until")||!x.headers.has("age"))&&(x=await a(y,f.signal));let q=x.status===304?O:Pe.parse(JSON.parse(await k(x,H.maxManifestBytes,f.signal))),{generation:Z,...ne}=q,ue=x.headers.get("etag");if(M(q.scope)!==M(n)||Be(ne)!==Z||ue!==`"${Z}"`&&ue!==`W/"${Z}"`)throw R("INVALID_RESPONSE","Configuration scope or content identity changed");if(O&&(q.revision<O.revision||q.revision===O.revision&&q.generation!==O.generation))throw R("INVALID_RESPONSE","Configuration revision moved backwards or changed identity");for(let[Re,W]of Object.entries(O?.funnels??{})){let le=q.funnels[Re];if(le&&(le.controlRevision<W.controlRevision||le.evaluationRevision<W.evaluationRevision||le.controlRevision===W.controlRevision&&le.state!==W.state||le.evaluationRevision===W.evaluationRevision&&le.evaluationMode!==W.evaluationMode))throw R("INVALID_RESPONSE","Funnel control revision changed identity")}let Te=B(x,G,q.policy);if(f.signal.throwIfAborted(),p!==A)throw R("CONFIGURATION_DISPOSED","Configuration scope changed");return r=q,s=Te,g=Date.now()+Math.max(0,Te-re()),w=!1,E=0,F=0,u.writeManifest(M(q)),X(),structuredClone(q)})(),h=setTimeout(()=>f.abort(R("CONFIGURATION_UNAVAILABLE","Configuration initialization timed out")),H.initializationMs),b=new Promise((O,G)=>f.signal.addEventListener("abort",()=>G(f.signal.reason),{once:!0})),L=Promise.race([C,b]).catch(O=>{throw E++,(O instanceof gn.ZodError||O instanceof SyntaxError||O instanceof d&&["CONFIGURATION_HTTP_404","CONFIGURATION_HTTP_410","INVALID_RESPONSE"].includes(O.code))&&(s=0,w=!0,X()),O}).finally(()=>{clearTimeout(h),S===L&&(S=void 0),K()});return S=L,L}async function me(p){let f=p.sha256,C=Z=>new TextEncoder().encode(Z).byteLength===p.byteLength&&Je(Z)===f;Y(p.url);let h=_.get(f);if(h&&C(h))return _.delete(f),_.set(f,h),h;if(U.has(f))return U.get(f);let b=new AbortController;T.add(b);let L=A,O=(async()=>{try{let ue=await u.readArtifact(f);if(ue&&C(ue))return N(f,ue),ue}catch{}b.signal.throwIfAborted();let Z=await a(p.url,b.signal,!0),ne=await k(Z,p.byteLength,b.signal);if(!C(ne))throw R("INVALID_RESPONSE","Configuration artifact digest or size mismatch");if(v||L!==A)throw R("CONFIGURATION_DISPOSED","Configuration scope changed");return N(f,ne),u.writeArtifact(f,ne),ne})(),G=setTimeout(()=>b.abort(R("CONFIGURATION_UNAVAILABLE","Configuration artifact timed out")),H.initializationMs),x=new Promise((Z,ne)=>b.signal.addEventListener("abort",()=>ne(b.signal.reason),{once:!0})),q=Promise.race([O,x]).finally(()=>{clearTimeout(G),T.delete(b),U.delete(f)});return U.set(f,q),q}async function pe(){return l()||await z(),c(),r}async function ie(p){let f,C=new Promise((h,b)=>{f=setTimeout(()=>b(R("CONFIGURATION_UNAVAILABLE","Configuration initialization timed out")),H.initializationMs)});try{return await Promise.race([p(),C])}finally{clearTimeout(f)}}function ae(p,f){if(c(),r?.generation!==p.generation)throw R("CONFIGURATION_CHANGED","Configuration changed while preparing a snapshot");if(f&&r.funnels[f]?.state!=="active")throw R("FUNNEL_STOPPED","Funnel is paused or unavailable")}async function Ie(p){let f=p.gb.features;if(!f)throw R("CONFIGURATION_UNAVAILABLE","Public Feature delivery is disabled");let C=p.artifacts[f];if(C.formatVersion!==1)throw R("UNSUPPORTED_SCHEMA","Unsupported public GB configuration format");let h=Me.parse(JSON.parse(await me(C)));if(M(h.scope)!==M({projectId:n.projectId,environment:n.environment})||h.generation!==C.generation||h.remoteFeatures.some(b=>Object.hasOwn(h.features,b)))throw R("INVALID_RESPONSE","Public GB configuration scope or generation is invalid");return ae(p),{...h,evaluatedAt:new Date().toISOString(),expiresAt:new Date(Date.now()+Math.max(0,s-re())).toISOString()}}async function se(p,f){let C=await pe();ae(C,p);let h=C.funnels[p];if(h.evaluationMode!=="local")throw R("EVALUATION_MODE","This Funnel executes at Indiana; public graph loading is disabled");let b=f??h.currentVersionId,L=h.versions[b];if(!L)throw R("CONFIGURATION_UNAVAILABLE","Pinned Funnel Version is unavailable");if(C.artifacts[L.artifact].formatVersion!==3)throw R("UNSUPPORTED_SCHEMA","Unsupported public Funnel format");let[O,G]=await Promise.all([me(C.artifacts[L.artifact]).then(x=>He(JSON.parse(x))),h.evaluationMode==="local"?Ie(C):void 0]);if(G&&M(ze(O,G))!==M(L.dependencies))throw R("INVALID_RESPONSE","Funnel and GB dependency contract do not match");return ae(C,p),{document:O,growth:G,versionId:b,control:structuredClone(h),manifest:structuredClone(C)}}function he(){w=!0,X(),z().catch(ee)}let $=()=>{(typeof document>"u"||document.visibilityState==="visible")&&he()};function Ce(p){if(v)throw R("CONFIGURATION_DISPOSED","Configuration manager was destroyed");return D.add(p),D.size===1&&(typeof window<"u"&&(window.addEventListener("online",he),window.addEventListener("focus",$),document.addEventListener("visibilitychange",$)),K()),()=>{D.delete(p),D.size||(clearTimeout(I),clearTimeout(P),Oe())}}function Oe(){typeof window<"u"&&(window.removeEventListener("online",he),window.removeEventListener("focus",$),document.removeEventListener("visibilitychange",$))}return{scope:Object.freeze({...n}),refresh:z,subscribe:Ce,assertFresh:c,assertFeatures(p){c();let f=r.gb.features;if(!f)throw R("CONFIGURATION_UNAVAILABLE","Public Feature delivery is disabled");if(p!==void 0&&r.artifacts[f].generation!==p)throw R("CONFIGURATION_CHANGED","Refresh changed Feature configuration before evaluation")},get fresh(){return l()},get snapshot(){return r?structuredClone(r):null},get remainingMs(){return l()?Math.max(0,s-re()):0},async features(){return ie(async()=>Ie(await pe()))},pageExperiments:()=>ie(async()=>{let p=await pe(),f=p.gb.pageExperiments;if(!f)throw R("CONFIGURATION_UNAVAILABLE","Public page experiments are disabled");let C=p.artifacts[f];if(C.formatVersion!==1)throw R("UNSUPPORTED_SCHEMA","Unsupported page experiment format");let h=Ge.parse(JSON.parse(await me(C)));if(h.environmentId!==n.environmentId||h.generation!==C.generation)throw R("INVALID_RESPONSE","Page experiment scope or generation changed");return ae(p),h}),funnel:(p,f)=>ie(()=>se(p,f)),async localFunnel(p,f){let C=await ie(()=>se(p,f));if(!C.growth)throw R("EVALUATION_MODE","This Funnel requires remote execution");let{analyticsConfig:h,remoteFeatures:b,...L}=C.growth;return qe({scope:{projectId:n.projectId,environment:n.environment},funnelId:p,versionId:C.versionId,evaluationMode:"local",evaluationRevision:C.control.evaluationRevision,document:C.document,payload:L})},assertFunnel(p,f,C){c();let h=r.funnels[p];if(!h||h.state!=="active")throw R("FUNNEL_STOPPED","Funnel is paused or unavailable");if(h.evaluationMode!=="local")throw R("EVALUATION_MODE","This Funnel now executes at Indiana");if(f!==void 0&&h.controlRevision!==f)throw R("RUN_RECONCILIATION_REQUIRED","Reconcile the original Run after a control change");if(C!==void 0&&!h.versions[C])throw R("CONFIGURATION_UNAVAILABLE","Pinned Funnel Version is unavailable")},destroy(){if(!v){v=!0,A++,s=0,V?.abort(R("CONFIGURATION_DISPOSED","Configuration manager was destroyed")),clearTimeout(I),clearTimeout(P),Oe(),X(),D.clear();for(let p of T)p.abort(R("CONFIGURATION_DISPOSED","Configuration manager was destroyed"));_.clear(),j=0}}}}function dt(e,n,i){return $e(e,n,i,de)}function un(e){let n=/^gg_ct_[A-Za-z0-9_-]{32,128}$/.test(e.apiKey);if(typeof window<"u"&&!n)throw new d("SERVER_ONLY","Funnel starts are issued by your backend");if(!n&&!/^gg_sk_[A-Za-z0-9_-]{32,128}$/.test(e.apiKey))throw new d("INVALID_TOKEN","A customer credential or server API key is required");let i=we({...e,timeoutMs:e.timeoutMs??35e3});return i.identify(e.apiKey),{async start(t){let m=te.safeParse({...t,operation:"start"});if(!m.success||m.data.operation!=="start"||(n?m.data.customer!==void 0:m.data.customer===void 0))throw new d("INVALID_REQUEST","Invalid current Funnel start");let y=m.data,o=Ee.safeParse(await i.request("funnels",y));if(!o.success||!o.data.runToken)throw new d("INVALID_RESPONSE","Funnel start credentials are missing");let u=o.data;if(u.run.source.id!==y.funnelId||u.run.locale!==(y.locale??"en")||!ye(u.run.parameters,y.parameters??{})||(y.customer?!u.customerId||y.customer.type==="id"&&u.customerId!==y.customer.value:u.customerId!==void 0))throw new d("INVALID_RESPONSE","Funnel start contract changed");return{...u,runToken:u.runToken}}}}async function Ct(e){e={...e};let n=e.configuration;if(!n)throw new d("CONFIGURATION_UNAVAILABLE","Local conditions require public configuration");let i={projectId:n.scope.projectId,environment:n.scope.environment};if(e.scope&&M(i)!==M(e.scope))throw new d("SCOPE_MISMATCH","Configuration and transport scopes differ");if((await n.funnel(e.funnelId)).control.evaluationMode!=="local")throw new d("EVALUATION_MODE","This Funnel uses Remote evaluation");let m=/^gg_sk_[A-Za-z0-9_-]{32,128}$/.test(e.credential);if(m?!e.customerId:e.customerId!==void 0)throw new d("INVALID_REQUEST","Only Server-Key starts name their Customer");let y=un({...e,scope:i,apiKey:e.credential}),o=u=>{let r=rn({...e,scope:i,runToken:u,...m?{serverKey:e.credential}:{}});return m||r.identify(e.credential),r};return{async start(u){let r=await y.start({...u,funnelId:e.funnelId,...m?{customer:{type:"id",value:e.customerId}}:{}}),s=o(r.runToken),g=await s.get();return{...r,...g,controller:s}},async restore(u){let r=o(u),s=await r.get();if(s.run.source.id!==e.funnelId)throw r.reset(),new d("SCOPE_MISMATCH","Run belongs to another Funnel");return{...s,runToken:u,controller:r}}}}export{yn as a,Rn as b,ye as c,Fn as d,ln as e,cn as f,Ze as g,rn as h,Zn as i,st as j,dt as k,un as l,Ct as m};
|
|
1
|
+
import{a as we}from"./chunk-QG3WUJG5.js";import{$k as Ke,Bf as Ue,Ei as Ee,Ek as H,Fi as ke,Fk as je,Gd as Le,Jk as Pe,Kk as M,Lk as Je,Mk as Be,Nk as ze,Oi as Se,Ok as He,Pi as qe,Rh as be,Vf as ce,al as $e,bl as Qe,cl as Ye,hk as Ge,ui as te,xf as Ve,yf as Me}from"./chunk-HTRQPMJO.js";import{a as Ae}from"./chunk-S5TVMQRC.js";import{b as _e,h as ge}from"./chunk-ISUXYPYL.js";import{a as d}from"./chunk-5TEZEOHX.js";import{f as De,j as xe,m as Ne}from"./chunk-S2MSIA57.js";function yn(e){let n=null,i=null,t=0,m=0,y=new Set,o=null,u=null,r=new Set,s=()=>{for(let I of r)try{I()}catch{}},g={attributes:Ne.parse(e.attributes??{}),onFeatureUsage:e.onFeatureUsage?(I,P)=>{!y.has(I)&&(!n||!("analyticsConfig"in n)||n.analyticsConfig.featureUsageEnabled)&&e.onFeatureUsage(I,structuredClone(P))}:void 0,onExperimentViewed:e.onExperimentViewed?(I,P)=>(!n||!("analyticsConfig"in n)||n.analyticsConfig.experimentViewsEnabled)&&e.onExperimentViewed(structuredClone(I),structuredClone(P)):void 0,stickyBucketAssignmentDocs:structuredClone(e.stickyBucketAssignmentDocs),saveStickyBucketAssignmentDoc:e.saveStickyBucketAssignmentDoc?I=>e.saveStickyBucketAssignmentDoc(structuredClone(I)):void 0,trackedFeatureUsage:{},trackedExperiments:new Set},w=()=>({value:null,source:"unknownFeature",on:!1,off:!0,ruleId:""});function v(I,P=new Set){return y.has(I)?!o||!o.features[I]||["unknownFeature","cyclicPrerequisite"].includes(o.features[I].source):P.has(I)?!1:(P.add(I),(n?.features[I]?.rules??[]).some(F=>[...F.parentConditions??[],...(F.tracks??[]).flatMap(D=>D.experiment.parentConditions??[])].some(D=>v(D.id,P))))}let A=I=>{if(e.assertUsable?.(n?.generation),!n)throw new Error("Initialize the Feature client before evaluation");if(n.expiresAt&&Date.parse(n.expiresAt)<=Date.now())throw new Error("Feature configuration expired; refresh before evaluation");return o?.expiresAt&&Date.parse(o.expiresAt)<=Date.now()&&(o=null,g.features=n.features),y.has(I)?!o||o.expiresAt&&Date.parse(o.expiresAt)<=Date.now()?w():structuredClone(o.features[I]??w()):v(I)?w():structuredClone(xe(I,g))};async function E(){if(!n||!y.size)return;if(!e.evaluateRemote)throw new Error("Remote Feature evaluation requires a server loader");let I=m;if(u?.revision===I)return u.loading;let P=t,F=n,D=[...y],T=(async()=>{let _=Ue.parse(await e.evaluateRemote({attributes:structuredClone(g.attributes),features:D}));if(!(P!==t||I!==m||F!==n)){if(e.assertUsable?.(F.generation),_.generation!==F.generation)throw new Error("Feature configuration changed; refresh before evaluation");if(D.some(U=>!Object.hasOwn(_.features,U))||Object.keys(_.features).some(U=>!y.has(U)))throw new Error("Invalid remote Feature results");o=structuredClone(_),g.features={...F.features,...Object.fromEntries(Object.entries(o.features).map(([U,j])=>[U,{defaultValue:j.value}]))},s()}})();u={revision:I,loading:T};try{await T}finally{u?.loading===T&&(u=null)}}function S(){E().catch(I=>{try{e.onError?.(I)}catch{}})}async function V(){if(i)return i;let I=t,P=(async()=>{let F=await e.load(),D="remoteFeatures"in F?Ve.parse(F):null,T=D??ge.parse(F);if(T.scope.projectId!==e.scope.projectId||T.scope.environment!==e.scope.environment)throw new Error("Feature payload scope changed");if(I!==t)throw new Error("Feature client was reset");if(e.assertUsable&&n?.generation===T.generation){let{evaluatedAt:U,expiresAt:j,...oe}=n,{evaluatedAt:X,expiresAt:ee,...l}=T;if(M(oe)!==M(l))throw new Error("Immutable Feature generation changed content");return n.evaluatedAt=T.evaluatedAt,n.expiresAt=T.expiresAt,s(),(!o||o.expiresAt&&Date.parse(o.expiresAt)<=Date.now())&&S(),structuredClone(n)}let _=new Set(D?.remoteFeatures??[]);if([..._].some(U=>Object.hasOwn(T.features,U)))throw new Error("Remote Feature definitions must not be delivered locally");return n&&"analyticsConfig"in n&&"analyticsConfig"in T&&!n.analyticsConfig.experimentViewsEnabled&&D?.analyticsConfig.experimentViewsEnabled&&g.trackedExperiments?.clear(),n=structuredClone(T),y=_,o=null,u=null,m++,g.features=n.features,g.savedGroups=De(n.savedGroups),g.trackedFeatureUsage={},s(),S(),structuredClone(n)})();i=P;try{return await P}finally{i===P&&(i=null)}}return{init:V,refresh:V,refreshRemote:E,get generation(){return n?.generation??null},get expiresAt(){return n?.expiresAt??null},subscribe(I){return r.add(I),()=>{r.delete(I)}},setAttributes(I){g.attributes=Ne.parse(I),m++,o=null,u=null,g.features=n?.features??{},g.trackedFeatureUsage={},s(),S()},evalFeature:A,isOn(I){return A(I).on},isOff(I){return A(I).off},getFeatureValue(I,P){let F=A(I).value;return structuredClone(F===null?P:F)},reset(){t++,m++,i=null,u=null,n=null,o=null,y.clear(),g.features={},g.savedGroups={},g.stickyBucketAssignmentDocs={},g.attributes={},g.trackedFeatureUsage={},g.trackedExperiments?.clear(),s()}}}function Ze(e){let n,i,t=()=>new d("COMMAND_STORAGE_INVALID","Durable command storage is unavailable"),m=Promise.resolve().then(async()=>{if(n=e.storage??globalThis.localStorage,i=e.locks??globalThis.navigator?.locks,!n||!i||!globalThis.crypto?.subtle)throw t();let u=new TextEncoder().encode(JSON.stringify([new URL(e.baseUrl??Ae).href,e.runToken])),r=new Uint8Array(await crypto.subtle.digest("SHA-256",u));return"indiana.funnel.commands.v1."+Array.from(r,s=>s.toString(16).padStart(2,"0")).join("")});m.catch(()=>{});async function y(u){try{let r=await m;return await i.request(r,{mode:"exclusive"},()=>u(r))}catch(r){throw r instanceof d?r:t()}}function o(u){let r=n.getItem(u);if(r===null)return{revision:0,entry:null};if(r.length>1048576)throw t();let s=JSON.parse(r);if(!s||typeof s!="object"||!("revision"in s)||!("entry"in s)||!Number.isSafeInteger(s.revision)||Number(s.revision)<0)throw t();return{revision:Number(s.revision),entry:s.entry}}return{read:()=>y(o),write:(u,r)=>y(s=>{if(o(s).revision!==u)return null;if(!Number.isSafeInteger(u+1))throw t();return n.setItem(s,JSON.stringify({revision:u+1,entry:r})),u+1})}}function Rn(e,n){return n.type==="id"?e.customerId===n.value:e.externalUserId===n.value}function ye(e,n){if(e===n)return!0;if(Array.isArray(e)||Array.isArray(n))return Array.isArray(e)&&Array.isArray(n)&&e.length===n.length&&e.every((m,y)=>ye(m,n[y]));if(!e||!n||typeof e!="object"||typeof n!="object")return!1;let i=Object.entries(e),t=Object.entries(n);return i.length===t.length&&i.every(([m,y])=>Object.hasOwn(n,m)&&ye(y,Reflect.get(n,m)))}var de=(e,n)=>new d(e,n);function Fn(e){return Ke(e,de)}function ln(e,n,i){return Qe(e,n,i,de)}async function We(e,n){let i=n.instruction;if(i?.type!=="evaluate")throw new Error("Evaluation instruction required");if(!e)throw new d("CONFIGURATION_UNAVAILABLE","Local conditions require the shared public configuration manager");let t=await e.funnel(n.source.id,n.source.versionId);if(!t.growth||t.control.evaluationMode!=="local"||t.control.evaluationRevision!==i.policyRevision)throw new d("EVALUATION_MODE","Refresh the original Funnel evaluation policy");let{analyticsConfig:m,remoteFeatures:y,...o}=t.growth,u=Se({scope:{projectId:e.scope.projectId,environment:e.scope.environment},funnelId:n.source.id,versionId:n.source.versionId,evaluationMode:"local",evaluationRevision:i.policyRevision,document:t.document,payload:ge.parse(o)});if(e.scope.environmentId!==i.environmentId)throw new d("SCOPE_MISMATCH","Evaluation environment changed");let r=ln(u,n.nodeId,i);return e.assertFunnel(n.source.id,void 0,n.source.versionId),{generation:t.manifest.generation,result:r}}async function Xe(e,n){let i=n.instruction;if(i?.type!=="evaluate_segment")throw new Error("Local segment instruction required");if(!e)throw new d("CONFIGURATION_UNAVAILABLE","Local execution requires public configuration");let t=await e.funnel(n.source.id,n.source.versionId);if(!t.growth||t.control.evaluationMode!=="local"||t.control.evaluationRevision!==i.policyRevision)throw new d("EVALUATION_MODE","Refresh the original Funnel evaluation policy");if(e.scope.environmentId!==i.environmentId)throw new d("SCOPE_MISMATCH","Evaluation environment changed");let{analyticsConfig:m,remoteFeatures:y,...o}=t.growth,u=Se({scope:{projectId:e.scope.projectId,environment:e.scope.environment},funnelId:n.source.id,versionId:n.source.versionId,evaluationMode:"local",evaluationRevision:i.policyRevision,document:t.document,payload:ge.parse(o)}),r=cn(u,t.document,{...n,...i});return e.assertFunnel(n.source.id,void 0,n.source.versionId),{...r,generation:t.manifest.generation,policyRevision:i.policyRevision}}function cn(e,n,i){return Ye(e,n,i,de)}import{z as Q}from"zod";var en=te.refine(e=>!["start","get","review"].includes(e.operation)&&!("customerToken"in e),"Persist only the original mutation, without credentials").transform(e=>{if(e.operation==="start"||e.operation==="get"||e.operation==="review")throw new d("COMMAND_STORAGE_INVALID","Stored mutation required");return e}),nn=Q.strictObject({schemaVersion:Q.literal(1),scope:_e,runId:Q.uuid(),funnelId:Q.uuid(),versionId:Q.uuid(),command:en.optional(),closeCommand:en.refine(e=>e.operation==="close").optional(),purchase:Q.strictObject({receiptId:Q.uuid(),operationId:Q.uuid(),generation:Q.number().int().nonnegative()}).optional(),closed:Q.literal(!0).optional()}).refine(e=>!e.closeCommand||e.command&&e.command.operation!=="close"&&e.command.requestId!==e.closeCommand.requestId,"Close requires a separate request identity").refine(e=>e.command!==void 0||e.purchase!==void 0,"A recovery record requires an original obligation"),J=()=>new d("COMMAND_STORAGE_CONFLICT","Another host changed this Run's pending command"),Fe=(e,n)=>JSON.stringify(e)===JSON.stringify(n);function tn(e){let n=0,i=null,t=r=>JSON.stringify([r.scope,r.runId,r.funnelId,r.versionId]),m=Promise.resolve();async function y(){let r=await e.read();if(!Number.isSafeInteger(r.revision)||r.revision<0)throw new d("COMMAND_STORAGE_INVALID","Invalid command storage revision");return{revision:r.revision,entry:r.entry===null?null:nn.parse(r.entry)}}function o(r){let s=m.then(r);return m=s.catch(()=>{}),s}async function u(r){for(let s=0;s<4;s++){let g=await y();if(g.entry&&i!==null&&t(g.entry)!==i)throw J();let w=r(g.entry,g.revision);if(Fe(g.entry,w)){n=g.revision;return}let v=await e.write(g.revision,w);if(v!==null){if(!Number.isSafeInteger(v)||v<=g.revision)throw J();n=v;return}}throw J()}return{bind(r){let s=JSON.stringify([r.scope,r.runId,r.funnelId,r.versionId]);if(i!==null&&i!==s)throw J();i=s},async load(){let r=await y();return n=r.revision,i=r.entry?t(r.entry):null,r.entry},retain(r){let s=nn.parse(r),g=s.command;return!g||i!==null&&t(s)!==i?Promise.reject(J()):(i??=t(s),o(()=>u((w,v)=>{if(w&&!Fe(t(w),t(s)))throw J();if(!w){if(v!==n&&g.operation!=="close")throw J();return s}if(!w.command)return{...w,command:g,...g.operation==="close"?{closed:!0}:{}};if(g.operation==="close"&&w.command.operation!=="close"){if(w.command.requestId===g.requestId||w.closeCommand&&!Fe(w.closeCommand,g))throw J();return{...w,closeCommand:g,closed:!0}}if(!Fe(w.command,g))throw J();return w})))},observePurchase(r,s,g){return o(()=>u((w,v)=>{if(!w&&v!==n||w&&t(w)!==t({...r,schemaVersion:1}))throw J();if(w?.purchase&&w.purchase.generation>s.generation)return w;if(w?.purchase&&w.purchase.generation===s.generation&&w.purchase.operationId!==s.operationId)throw J();return g?!w?.purchase||w.purchase.operationId!==s.operationId?w:w.command?{...w,purchase:void 0}:null:{schemaVersion:1,...r,...w,purchase:s}}))},settle(r){return o(()=>u(s=>s?s.command&&"requestId"in s.command&&s.command.requestId===r?s.closeCommand?{...s,command:s.closeCommand,closeCommand:void 0}:s.purchase?{...s,command:void 0}:null:s.closeCommand&&"requestId"in s.closeCommand&&s.closeCommand.requestId===r?{...s,closeCommand:void 0}:s:null))}}}function fe(e){let{customerToken:n,...i}=e;return i}var dn=e=>!(e instanceof d)||e.status===void 0||e.status>=500||[401,425].includes(e.status);function rn(e){if(e={...e},typeof e.runToken!="string"||!/^gg_fr_[A-Za-z0-9_-]{43}$/.test(e.runToken))throw new d("INVALID_TOKEN","Run credential required");if(e.serverKey&&(typeof window<"u"||!/^gg_sk_[A-Za-z0-9_-]{32,128}$/.test(e.serverKey)))throw new d("SERVER_ONLY","Run Server-Key proof belongs to the merchant backend");let n=we({...e,...e.serverKey?{fetch:(l,c)=>{let N=new Headers(c?.headers);return N.set(ke,e.serverKey),(e.fetch??globalThis.fetch)(l,{...c,headers:N})}}:{},timeoutMs:e.timeoutMs??35e3});n.identify(e.runToken);let i,t=null,m=0,y=0,o=null,u=null,r=!1,s=null,g=!1,w=null,v=new Set,A=e.funnelCommandStorage??(typeof window<"u"&&window.isSecureContext?Ze(e):void 0),E=A&&tn(A),S,V=null,I=!1,P=E?E.load().then(l=>{if(I)throw new d("IDENTITY_CHANGED","Controller was reset during command restoration");if(V=l,!l)return;if(e.scope&&(l.scope.projectId!==e.scope.projectId||l.scope.environment!==e.scope.environment))throw new d("SCOPE_MISMATCH","Pending command belongs to another scope");if(S=l.purchase,r=l.closed===!0,!l.command)return;let c=te.parse(l.command);if(c.operation==="start"||c.operation==="get"||c.operation==="review")throw new d("COMMAND_STORAGE_INVALID","Stored mutation required");o=c,l.closeCommand&&(u=l.closeCommand,r=!0),c.operation==="close"&&(r=!0),g=!0}):Promise.resolve();P.catch(()=>{});async function F(l,c,N){E&&await P;let k=m,Y=t,a=Ee.parse(await n.request("funnels",te.parse(l)));if(l.operation==="review"&&!a.review)throw new d("INVALID_RESPONSE","Historical projection is missing");if(k!==m)throw new d("IDENTITY_CHANGED","Run identity changed during the request");if(a.runToken&&a.runToken!==e.runToken)throw new d("INVALID_RESPONSE","Run credential changed");let B=l.operation==="get"?l.settlementRequestId:"requestId"in l&&l.operation!=="start"?l.requestId:void 0;if(B&&a.settlement?.requestId!==B)throw new d("INVALID_RESPONSE","Exact command settlement is missing or belongs to another command");if(V&&(a.run.id!==V.runId||a.run.source.id!==V.funnelId||a.run.source.versionId!==V.versionId))throw new d("SCOPE_MISMATCH","Stored command belongs to another Run or Version");if(t&&(a.run.id!==t.id||a.run.source.type!==t.source.type||a.run.source.id!==t.source.id||a.run.source.versionId!==t.source.versionId||a.run.locale!==t.locale||!ye(a.run.parameters,t.parameters)))throw new d("INVALID_RESPONSE","Run version changed");if(e.funnelId&&a.run.source.id!==e.funnelId)throw new d("INVALID_RESPONSE","Run belongs to another Funnel");E?.bind({scope:a.scope,runId:a.run.id,funnelId:a.run.source.id,versionId:a.run.source.versionId}),A&&!e.scope&&(e.scope=a.scope);let K=a.run.paywall,z=K??a.purchase,me=z?.operation,pe=a.settlement&&(!K||K.purchaseRequestId===a.settlement.requestId)&&(!S||S.operationId===a.settlement.operationId)?a.settlement:void 0,ie=me?.operationId??z?.quote?.operationId??pe?.operationId,ae=z?.receiptId??pe?.receiptId,Ie=K?.selectionGeneration??S?.generation??0;if(E&&ie&&ae&&l.operation!=="review"&&(!t||a.run.revision>=t.revision)&&(N===void 0||N>=y)&&(!S||Ie>=S.generation)){let $={receiptId:ae,operationId:ie,generation:Ie},Ce=me?.status==="complete"||z?.canReselect===!0;await E.observePurchase({scope:a.scope,runId:a.run.id,funnelId:a.run.source.id,versionId:a.run.source.versionId},$,Ce),Ce?S?.operationId===$.operationId&&(S=void 0):S=$}if(!a.run.stopped&&["running","waiting"].includes(a.run.status)&&l.operation==="get"&&l.settlementRequestId)return a;let se=c?.(a),he=typeof se=="boolean"?se:se?await se:!1;if(["running","waiting"].includes(a.run.status)||(r=!0),l.operation==="review"&&t&&t!==Y&&a.run.revision<=t.revision||t&&a.run.revision===t.revision&&N!==void 0&&N<y||(l.operation==="review"&&!a.run.stopped&&["running","waiting"].includes(a.run.status)&&t&&a.run.nodeId===t.nodeId&&a.run.visit===t.visit&&a.run.revision===t.revision&&(a.run.screen=t.screen,(t.paywall?.quote?.operationId===a.review?.activeOperationId||!t.paywall?.quote&&a.review?.activeOperationId===null)&&(a.run.paywall=t.paywall)),t?.paywall&&a.run.paywall&&t.paywall.receiptId===a.run.paywall.receiptId&&(a.run.paywall.selectionGeneration??0)<(t.paywall.selectionGeneration??0)))return a;if(!t||a.run.revision>=t.revision)t=a.run;else if(!he)return a;if(t)for(let $ of v)try{$(structuredClone(t))}catch{}return a}async function D(l=o){if(E&&await P,!l)throw new d("INVALID_REQUEST","No command is pending");let c=l,N=m;if(E){if(!t||!e.scope)throw new d("COMMAND_STORAGE_INVALID","Read the original scoped Run before persisting a mutation");await E.retain({schemaVersion:1,scope:e.scope,runId:t.id,funnelId:t.source.id,versionId:t.source.versionId,command:fe(c)})}if(N!==m||o!==c&&u!==c)throw new d("IDENTITY_CHANGED","Run changed before command dispatch");let k={...c,...i?{customerToken:i}:{}},Y=g;g=!0;try{return await F(k,a=>{if(!a.settlement)throw new d("INVALID_RESPONSE","Exact command settlement is missing");if(a.settlement.requestId!==c.requestId)throw new d("INVALID_RESPONSE","Command settlement identity changed");if(N===m&&(o===c||u===c)&&a.run.pendingRequest?.requestId!==c.requestId&&a.settlement.state==="settled"&&(!r||c.operation==="close"||a.settlement?.state==="settled"&&!["running","waiting"].includes(a.run.status))){let B=()=>N!==m||o!==c&&u!==c?!1:(o===c&&(o=null),u===c&&(u=null),g=o!==null,V=null,!0);return E?E.settle(c.requestId).then(B):B()}return!1})}catch(a){throw N===m&&o===c&&!Y&&!dn(a)&&(E&&await E.settle(c.requestId),N===m&&o===c&&(o=null,g=!1,V=null)),a}}function T(l){let c=te.parse(l);if(c.operation==="start"||c.operation==="get"||c.operation==="review")throw new d("INVALID_REQUEST","Mutation required");if(t?.recoveryRestricted&&c.operation!=="close"&&c.operation!=="resume"&&o?.requestId!==c.requestId)throw new d("PRECONDITION_FAILED","Original Run requires restricted recovery");if(r&&c.operation!=="close"){if(o?.requestId===c.requestId)return ee.settle(c.requestId);throw new d("COMMAND_PENDING","Close preserves the original recovery record; settle it by identity")}if(c.operation==="close"&&o?.operation!=="close"){if(r=!0,u&&JSON.stringify(fe(u))!==JSON.stringify(fe(c)))throw new d("COMMAND_PENDING","Retry the original Close");if(u??=c,s)return s;let k=D(u);return s=k,k.then(()=>{s===k&&(s=null)},()=>{s===k&&(s=null)}),k}if(o){if(JSON.stringify(fe(o))!==JSON.stringify(fe(c)))throw new d("COMMAND_PENDING","Retry the original command before sending another");if(w)return w}else o=c,g=!1;let N=D();return w=N,N.then(()=>{w===N&&(w=null)},()=>{w===N&&(w=null)}),N}let _=null,U=new WeakMap;function j(l){let c=U.get(l);if(c)return c;let N=X(l);return U.set(l,N),N}let oe=!1;async function X(l){let c=await l;if(c.run.recoveryRestricted||!["evaluate","evaluate_segment"].includes(c.run.instruction?.type??""))return c;if(_)return _;oe=!0;let N=m,k=(async()=>{for(let Y=0;Y<32&&["evaluate","evaluate_segment"].includes(c.run.instruction?.type??"");Y++){if(o||r)return c;let a=c.run,B=c.run.instruction;if(B?.type==="evaluate_segment"){let z=await Xe(e.configuration,a);if(N!==m)throw new d("IDENTITY_CHANGED","Run identity changed during segment calculation");if(o||r)return c;if(t&&(t.revision!==a.revision||t.visit!==a.visit||t.nodeId!==a.nodeId))return F({operation:"get",...i?{customerToken:i}:{}});c=await T({operation:"commit_segment",requestId:be(a.id,a.visit,`segment:${a.revision}`),nodeId:a.nodeId,visit:a.visit,revision:a.revision,...z});continue}if(B?.type!=="evaluate")return c;let K=await We(e.configuration,a);if(N!==m)throw new d("IDENTITY_CHANGED","Run identity changed during evaluation");if(o||r)return c;if(t&&(t.revision!==a.revision||t.visit!==a.visit||t.nodeId!==a.nodeId))return F({operation:"get",...i?{customerToken:i}:{}});c=await T({operation:"evaluate",requestId:be(a.id,a.visit,"evaluation"),nodeId:a.nodeId,visit:a.visit,revision:a.revision,receiptId:B.receiptId,policyRevision:B.policyRevision,...K})}return c})();_=k;try{return await k}finally{_===k&&(_=null)}}let ee={get configuration(){return oe?e.configuration:void 0},get configurationReady(){return!0},get view(){return t?structuredClone(t):null},get pendingCommand(){let l=u??o;return l?structuredClone(fe(l)):null},get pendingCommands(){return[o,u].filter(l=>l!==null).map(l=>structuredClone(fe(l)))},get pendingPurchase(){return S?structuredClone(S):null},async settle(l){let c=await F({operation:"get",settlementRequestId:l,...i?{customerToken:i}:{}});if(c.settlement?.requestId!==l)throw new d("INVALID_RESPONSE","Exact command settlement is missing");return c.settlement.state==="settled"&&(E&&await E.settle(l),o?.requestId===l&&(o=null,g=!1),u?.requestId===l&&(u=null)),c},get webViewUrl(){return n.webViewUrl()},review(l){return F({operation:"review",...l?{receiptId:l}:{},...i?{customerToken:i}:{}},void 0,++y)},async get(l,c){E&&await P,c??=S&&{receiptId:S.receiptId,operationId:S.operationId};let N=++y;return j(F({operation:"get",...l?{data:l}:{},...c?{purchase:c}:{},...i?{customerToken:i}:{}},void 0,N))},resume(l=t?.pendingRequest?.requestId){return l?r?ee.settle(l):o?.requestId===l?j(T(o)):j(T({operation:"resume",requestId:l})):Promise.reject(new d("INVALID_REQUEST","No interrupted command is available"))},submit(l){return j(T(l))},retry(){return s||(u?D(u):r&&o?ee.settle(o.requestId):w?j(w):o?j(T(o)):Promise.reject(new d("INVALID_REQUEST","No command is pending")))},identify(l){if(!/^gg_ct_[A-Za-z0-9_-]{43}$/.test(l))throw new d("INVALID_TOKEN","Customer credential required");m++,i=l,n.identify(e.runToken)},subscribe(l){return v.add(l),()=>v.delete(l)},reset(){I=!0,m++,i=void 0,t=null,o=null,u=null,s=null,g=!1,w=null,n.reset(),v.clear()}};return ee}async function Zn(e,n){if(!/^gg_ct_[A-Za-z0-9_-]{43}$/.test(n.customerToken))throw new d("INVALID_TOKEN","A verified Customer credential is required");let i=we(e);i.identify(n.customerToken);let t=ce.resolvePaywall.request.parse({funnelId:n.funnelId,funnelVersionId:n.funnelVersionId,selector:n.paywallVersionId?{type:"version",versionId:n.paywallVersionId}:{type:"paywall",paywallId:n.paywallId},commerce:n.commerce,locale:n.locale,...n.requirement?{requirement:n.requirement}:{}}),m=null,y=null,o=null,u=null,r=null;async function s(){let v=ce.resolvePaywall,A=v.response.parse(await i.request(v.path,v.request.parse({...t,selector:m?{type:"version",versionId:m.id}:t.selector})));if(n.paywallVersionId?A.paywall.id!==n.paywallVersionId:A.paywall.paywallId!==n.paywallId)throw new d("INVALID_RESPONSE","The requested Paywall changed");if(m&&(A.paywall.id!==m.id||A.paywall.paywallId!==m.paywallId||A.paywall.offering.id!==m.offering.id))throw new d("INVALID_RESPONSE","The pinned Paywall or Offering Version changed");return m=A.paywall,structuredClone(m)}async function g(v){if(!y)throw new d("INVALID_REQUEST","A quoted purchase is required");let A=v==="read"?ce.readSubscriptionOperation:ce.attach,E=A.response.parse(await i.request(A.path,A.request.parse({operationId:y.operationId,...v==="read"?{}:{intent:v}})));if(E.operation.operationId!==y.operationId||E.operation.currency!==t.commerce.currency)throw new d("INVALID_RESPONSE","The purchase operation changed");return o?.status==="complete"&&E.operation.status!=="complete"||o&&o.status!=="pending"&&E.operation.status==="pending"||(o=E.operation),structuredClone(o)}let w={get view(){return m?structuredClone(m):null},get quote(){return y?structuredClone(y):null},get operation(){return o?structuredClone(o):null},get webViewUrl(){return i.webViewUrl()},refresh:s,async preview(v){if(!m)throw new d("INVALID_REQUEST","Load the Paywall first");let A=m.document.buttons[v.actionId];if(A?.type!=="checkout")throw new d("INVALID_REQUEST","Choose an authored purchase action");let E=Le(A.product,v.selection,m.capabilities);if(!E)throw new d("PRODUCT_UNAVAILABLE","Choose an available Product");let S=ce.previewAttach.request.parse({funnelId:t.funnelId,funnelVersionId:t.funnelVersionId,requestId:v.requestId,plans:[{productVersionId:E}],provider:t.commerce.provider,currency:t.commerce.currency,...v.offerId?{offerId:v.offerId}:{},...v.nativeOffer?{nativeOffer:v.nativeOffer}:{}}),V=JSON.stringify(S);if(u&&u!==V&&(!o||o.status==="pending"))throw new d("COMMAND_PENDING","Finish or cancel the original purchase before changing it");if(u===V){if(r)return r;if(y)return structuredClone(y)}u=V;let I=(async()=>{let P=ce.previewAttach,F=P.response.parse(await i.request(P.path,S));if(F.quote.currency!==t.commerce.currency||F.quote.provider!==t.commerce.provider||F.quote.lines.length!==1||F.quote.lines[0].productVersionId!==E)throw new d("INVALID_RESPONSE","The purchase quote changed its selected Product or presentment");return y=F.quote,o=null,structuredClone(y)})();r=I;try{return await I}finally{r===I&&(r=null)}},confirm:()=>g("confirm"),cancel:()=>g("cancel"),read:()=>g("read"),destroy(){i.reset(),m=null,y=null,o=null,u=null}};return await s(),w}import{z as gn}from"zod";import{z as ve}from"zod";var fn=ve.record(ve.string().regex(/^[a-f0-9]{64}$/),ve.strictObject({at:ve.number(),text:ve.string()})),on=2*1048576,mn=100;function pn(){try{return typeof window>"u"?void 0:window.localStorage}catch{return}}function an(e,n){let i=n===void 0?pn():n,t=Promise.resolve();async function m(o){if(!i)return null;let u;try{return await Promise.race([Promise.resolve().then(()=>i.getItem(o)),new Promise(r=>{u=setTimeout(()=>r(null),mn)})])}catch{return null}finally{clearTimeout(u)}}async function y(){try{let o=await m(`${e}:artifacts`);if(o&&o.length<=on)return fn.parse(JSON.parse(o))}catch{}return{}}return{async readManifest(){return m(e)},writeManifest(o){Promise.resolve().then(()=>i?.setItem(e,o)).catch(()=>{})},async readArtifact(o){let u=(await y())[o];return u&&Date.now()>=u.at&&Date.now()-u.at<=H.retentionMs?u.text:void 0},writeArtifact(o,u){i&&(t=t.catch(()=>{}).then(async()=>{let r=await y(),s=Date.now();r[o]={at:s,text:u};let g={},w=2,v=0;for(let[A,E]of Object.entries(r).sort(([,S],[,V])=>V.at-S.at)){if(E.at>s||s-E.at>H.retentionMs)continue;let S=new TextEncoder().encode(JSON.stringify({[A]:E})).byteLength;w+S>on||v>=128||(g[A]=E,w+=S,v++)}await i.setItem(`${e}:artifacts`,JSON.stringify(g))}).catch(()=>{}))}}}var R=(e,n)=>new d(e,n),re=()=>performance.now(),sn=e=>{typeof e=="object"&&"unref"in e&&e.unref()};function st(e){let n=je.parse(e.scope),i=new URL(e.origin??Ae);if(i.username||i.password||i.search||i.hash||i.pathname!=="/"||i.protocol!=="https:"&&!(i.protocol==="http:"&&["localhost","127.0.0.1","[::1]"].includes(i.hostname)))throw R("INVALID_URL","Configuration requires a trusted HTTPS origin");let t=new Set([i.origin,...(e.assetOrigins??[]).map(p=>{let f=new URL(p);if(f.protocol!=="https:"||f.username||f.password||f.search||f.hash||f.pathname!=="/")throw R("INVALID_URL","Invalid configuration asset origin");return f.origin})]),m=e.fetch??globalThis.fetch.bind(globalThis),y=`/api/v1/configuration/${n.environmentId}`,o=`indiana:configuration:1:${i.origin}:${M(n)}`,u=an(o,e.storage),r,s=0,g=0,w=!1,v=!1,A=0,E=0,S,V,I,P,F=0,D=new Set,T=new Set,_=new Map,U=new Map,j=0,oe=!1;function X(){for(let p of D)try{p()}catch{}}function ee(p){try{e.onError?.(p)}catch{}}let l=()=>!v&&!w&&!!r&&re()<s&&Date.now()<g;function c(){if(!l())throw R("CONFIGURATION_EXPIRED","Refresh configuration before using it")}function N(p,f){let C=new TextEncoder().encode(f).byteLength;if(!_.has(p)){for(;_.size&&(_.size>=128||j+C>H.maxCacheBytes);){let h=_.entries().next().value;j-=new TextEncoder().encode(h[1]).byteLength,_.delete(h[0])}_.set(p,f),j+=C}}async function k(p,f,C){if(Number(p.headers.get("content-length"))>f)throw R("INVALID_RESPONSE","Configuration exceeds its byte limit");let h=p.body?.getReader();if(!h)throw R("INVALID_RESPONSE","Configuration body is missing");let b=[],L=0;try{for(;;){C.throwIfAborted();let x=await h.read();if(x.done)break;if(L+=x.value.length,L>f)throw R("INVALID_RESPONSE","Configuration exceeds its byte limit");b.push(x.value)}}finally{await h.cancel().catch(()=>{})}C.throwIfAborted();let O=new Uint8Array(L),G=0;for(let x of b)O.set(x,G),G+=x.length;return new TextDecoder("utf-8",{fatal:!0}).decode(O)}function Y(p){let f=new URL(p,i);if(!t.has(f.origin)||f.username||f.password||f.hash||f.search)throw R("INVALID_URL","Configuration artifact origin is not trusted");return f.href}async function a(p,f,C=!1){let h=await m(Y(p),{method:"GET",credentials:"omit",redirect:"error",cache:C?"default":"no-cache",signal:f,headers:{}});if(h.status===429){let b=h.headers.get("retry-after")??"";F=/^\d+$/.test(b)?Number(b)*1e3:Math.max(0,Date.parse(b)-Date.now())||15e3}if(!h.ok&&h.status!==304)throw R(`CONFIGURATION_HTTP_${h.status}`,"Configuration synchronization failed");return h}function B(p,f,C){let h=Date.parse(p.headers.get("x-indiana-config-validated-at")??""),b=Date.parse(p.headers.get("x-indiana-config-valid-until")??""),L=Date.parse(p.headers.get("date")??""),O=p.headers.get("age"),G=O!==null&&/^\d+(\.\d+)?$/.test(O)?Number(O)*1e3:NaN;if(![h,b,L,G].every(Number.isFinite)||b<=h||b-h>H.maxControlAgeMs||h>L+1e3)throw R("INVALID_RESPONSE","Configuration freshness evidence is invalid");let q=Math.min(b-h,C.maxControlAgeSeconds*1e3,H.maxControlAgeMs)-Math.max(G,L-h,0)-(re()-f);if(q<=0)throw R("CONFIGURATION_EXPIRED","Configuration validation expired in transit");return re()+q}function K(){if(clearTimeout(I),clearTimeout(P),v||!D.size)return;l()&&(P=setTimeout(()=>{l()?K():X()},Math.max(1,s-re())),sn(P));let p=E?Math.min(15e3,1e3*2**Math.min(E-1,4)):Math.min(15e3,(r?.policy.refreshIntervalSeconds??15)*1e3);I=setTimeout(()=>{z().catch(ee)},Math.max(F,p*(.8+Math.random()*.2))),sn(I)}async function z(){if(v)throw R("CONFIGURATION_DISPOSED","Configuration manager was destroyed");if(S)return S;let p=A,f=new AbortController;V=f;let C=(async()=>{if(!oe){oe=!0;try{let Re=await u.readManifest();if(Re&&!r){let W=Pe.parse(JSON.parse(Re));M(W.scope)===M(n)&&(r=W)}}catch{}}f.signal.throwIfAborted();let O=r,G=re(),x=await a(y,f.signal);x.status===304&&(!O||!x.headers.has("x-indiana-config-validated-at")||!x.headers.has("x-indiana-config-valid-until")||!x.headers.has("age"))&&(x=await a(y,f.signal));let q=x.status===304?O:Pe.parse(JSON.parse(await k(x,H.maxManifestBytes,f.signal))),{generation:Z,...ne}=q,ue=x.headers.get("etag");if(M(q.scope)!==M(n)||Be(ne)!==Z||ue!==`"${Z}"`&&ue!==`W/"${Z}"`)throw R("INVALID_RESPONSE","Configuration scope or content identity changed");if(O&&(q.revision<O.revision||q.revision===O.revision&&q.generation!==O.generation))throw R("INVALID_RESPONSE","Configuration revision moved backwards or changed identity");for(let[Re,W]of Object.entries(O?.funnels??{})){let le=q.funnels[Re];if(le&&(le.controlRevision<W.controlRevision||le.evaluationRevision<W.evaluationRevision||le.controlRevision===W.controlRevision&&le.state!==W.state||le.evaluationRevision===W.evaluationRevision&&le.evaluationMode!==W.evaluationMode))throw R("INVALID_RESPONSE","Funnel control revision changed identity")}let Te=B(x,G,q.policy);if(f.signal.throwIfAborted(),p!==A)throw R("CONFIGURATION_DISPOSED","Configuration scope changed");return r=q,s=Te,g=Date.now()+Math.max(0,Te-re()),w=!1,E=0,F=0,u.writeManifest(M(q)),X(),structuredClone(q)})(),h=setTimeout(()=>f.abort(R("CONFIGURATION_UNAVAILABLE","Configuration initialization timed out")),H.initializationMs),b=new Promise((O,G)=>f.signal.addEventListener("abort",()=>G(f.signal.reason),{once:!0})),L=Promise.race([C,b]).catch(O=>{throw E++,(O instanceof gn.ZodError||O instanceof SyntaxError||O instanceof d&&["CONFIGURATION_HTTP_404","CONFIGURATION_HTTP_410","INVALID_RESPONSE"].includes(O.code))&&(s=0,w=!0,X()),O}).finally(()=>{clearTimeout(h),S===L&&(S=void 0),K()});return S=L,L}async function me(p){let f=p.sha256,C=Z=>new TextEncoder().encode(Z).byteLength===p.byteLength&&Je(Z)===f;Y(p.url);let h=_.get(f);if(h&&C(h))return _.delete(f),_.set(f,h),h;if(U.has(f))return U.get(f);let b=new AbortController;T.add(b);let L=A,O=(async()=>{try{let ue=await u.readArtifact(f);if(ue&&C(ue))return N(f,ue),ue}catch{}b.signal.throwIfAborted();let Z=await a(p.url,b.signal,!0),ne=await k(Z,p.byteLength,b.signal);if(!C(ne))throw R("INVALID_RESPONSE","Configuration artifact digest or size mismatch");if(v||L!==A)throw R("CONFIGURATION_DISPOSED","Configuration scope changed");return N(f,ne),u.writeArtifact(f,ne),ne})(),G=setTimeout(()=>b.abort(R("CONFIGURATION_UNAVAILABLE","Configuration artifact timed out")),H.initializationMs),x=new Promise((Z,ne)=>b.signal.addEventListener("abort",()=>ne(b.signal.reason),{once:!0})),q=Promise.race([O,x]).finally(()=>{clearTimeout(G),T.delete(b),U.delete(f)});return U.set(f,q),q}async function pe(){return l()||await z(),c(),r}async function ie(p){let f,C=new Promise((h,b)=>{f=setTimeout(()=>b(R("CONFIGURATION_UNAVAILABLE","Configuration initialization timed out")),H.initializationMs)});try{return await Promise.race([p(),C])}finally{clearTimeout(f)}}function ae(p,f){if(c(),r?.generation!==p.generation)throw R("CONFIGURATION_CHANGED","Configuration changed while preparing a snapshot");if(f&&r.funnels[f]?.state!=="active")throw R("FUNNEL_STOPPED","Funnel is paused or unavailable")}async function Ie(p){let f=p.gb.features;if(!f)throw R("CONFIGURATION_UNAVAILABLE","Public Feature delivery is disabled");let C=p.artifacts[f];if(C.formatVersion!==1)throw R("UNSUPPORTED_SCHEMA","Unsupported public GB configuration format");let h=Me.parse(JSON.parse(await me(C)));if(M(h.scope)!==M({projectId:n.projectId,environment:n.environment})||h.generation!==C.generation||h.remoteFeatures.some(b=>Object.hasOwn(h.features,b)))throw R("INVALID_RESPONSE","Public GB configuration scope or generation is invalid");return ae(p),{...h,evaluatedAt:new Date().toISOString(),expiresAt:new Date(Date.now()+Math.max(0,s-re())).toISOString()}}async function se(p,f){let C=await pe();ae(C,p);let h=C.funnels[p];if(h.evaluationMode!=="local")throw R("EVALUATION_MODE","This Funnel executes at Indiana; public graph loading is disabled");let b=f??h.currentVersionId,L=h.versions[b];if(!L)throw R("CONFIGURATION_UNAVAILABLE","Pinned Funnel Version is unavailable");if(C.artifacts[L.artifact].formatVersion!==3)throw R("UNSUPPORTED_SCHEMA","Unsupported public Funnel format");let[O,G]=await Promise.all([me(C.artifacts[L.artifact]).then(x=>He(JSON.parse(x))),h.evaluationMode==="local"?Ie(C):void 0]);if(G&&M(ze(O,G))!==M(L.dependencies))throw R("INVALID_RESPONSE","Funnel and GB dependency contract do not match");return ae(C,p),{document:O,growth:G,versionId:b,control:structuredClone(h),manifest:structuredClone(C)}}function he(){w=!0,X(),z().catch(ee)}let $=()=>{(typeof document>"u"||document.visibilityState==="visible")&&he()};function Ce(p){if(v)throw R("CONFIGURATION_DISPOSED","Configuration manager was destroyed");return D.add(p),D.size===1&&(typeof window<"u"&&(window.addEventListener("online",he),window.addEventListener("focus",$),document.addEventListener("visibilitychange",$)),K()),()=>{D.delete(p),D.size||(clearTimeout(I),clearTimeout(P),Oe())}}function Oe(){typeof window<"u"&&(window.removeEventListener("online",he),window.removeEventListener("focus",$),document.removeEventListener("visibilitychange",$))}return{scope:Object.freeze({...n}),refresh:z,subscribe:Ce,assertFresh:c,assertFeatures(p){c();let f=r.gb.features;if(!f)throw R("CONFIGURATION_UNAVAILABLE","Public Feature delivery is disabled");if(p!==void 0&&r.artifacts[f].generation!==p)throw R("CONFIGURATION_CHANGED","Refresh changed Feature configuration before evaluation")},get fresh(){return l()},get snapshot(){return r?structuredClone(r):null},get remainingMs(){return l()?Math.max(0,s-re()):0},async features(){return ie(async()=>Ie(await pe()))},pageExperiments:()=>ie(async()=>{let p=await pe(),f=p.gb.pageExperiments;if(!f)throw R("CONFIGURATION_UNAVAILABLE","Public page experiments are disabled");let C=p.artifacts[f];if(C.formatVersion!==1)throw R("UNSUPPORTED_SCHEMA","Unsupported page experiment format");let h=Ge.parse(JSON.parse(await me(C)));if(h.environmentId!==n.environmentId||h.generation!==C.generation)throw R("INVALID_RESPONSE","Page experiment scope or generation changed");return ae(p),h}),funnel:(p,f)=>ie(()=>se(p,f)),async localFunnel(p,f){let C=await ie(()=>se(p,f));if(!C.growth)throw R("EVALUATION_MODE","This Funnel requires remote execution");let{analyticsConfig:h,remoteFeatures:b,...L}=C.growth;return qe({scope:{projectId:n.projectId,environment:n.environment},funnelId:p,versionId:C.versionId,evaluationMode:"local",evaluationRevision:C.control.evaluationRevision,document:C.document,payload:L})},assertFunnel(p,f,C){c();let h=r.funnels[p];if(!h||h.state!=="active")throw R("FUNNEL_STOPPED","Funnel is paused or unavailable");if(h.evaluationMode!=="local")throw R("EVALUATION_MODE","This Funnel now executes at Indiana");if(f!==void 0&&h.controlRevision!==f)throw R("RUN_RECONCILIATION_REQUIRED","Reconcile the original Run after a control change");if(C!==void 0&&!h.versions[C])throw R("CONFIGURATION_UNAVAILABLE","Pinned Funnel Version is unavailable")},destroy(){if(!v){v=!0,A++,s=0,V?.abort(R("CONFIGURATION_DISPOSED","Configuration manager was destroyed")),clearTimeout(I),clearTimeout(P),Oe(),X(),D.clear();for(let p of T)p.abort(R("CONFIGURATION_DISPOSED","Configuration manager was destroyed"));_.clear(),j=0}}}}function dt(e,n,i){return $e(e,n,i,de)}function un(e){let n=/^gg_ct_[A-Za-z0-9_-]{32,128}$/.test(e.apiKey);if(typeof window<"u"&&!n)throw new d("SERVER_ONLY","Funnel starts are issued by your backend");if(!n&&!/^gg_sk_[A-Za-z0-9_-]{32,128}$/.test(e.apiKey))throw new d("INVALID_TOKEN","A customer credential or server API key is required");let i=we({...e,timeoutMs:e.timeoutMs??35e3});return i.identify(e.apiKey),{async start(t){let m=te.safeParse({...t,operation:"start"});if(!m.success||m.data.operation!=="start"||(n?m.data.customer!==void 0:m.data.customer===void 0))throw new d("INVALID_REQUEST","Invalid current Funnel start");let y=m.data,o=Ee.safeParse(await i.request("funnels",y));if(!o.success||!o.data.runToken)throw new d("INVALID_RESPONSE","Funnel start credentials are missing");let u=o.data;if(u.run.source.id!==y.funnelId||u.run.locale!==(y.locale??"en")||!ye(u.run.parameters,y.parameters??{})||(y.customer?!u.customerId||y.customer.type==="id"&&u.customerId!==y.customer.value:u.customerId!==void 0))throw new d("INVALID_RESPONSE","Funnel start contract changed");return{...u,runToken:u.runToken}}}}async function Ct(e){e={...e};let n=e.configuration;if(!n)throw new d("CONFIGURATION_UNAVAILABLE","Local conditions require public configuration");let i={projectId:n.scope.projectId,environment:n.scope.environment};if(e.scope&&M(i)!==M(e.scope))throw new d("SCOPE_MISMATCH","Configuration and transport scopes differ");if((await n.funnel(e.funnelId)).control.evaluationMode!=="local")throw new d("EVALUATION_MODE","This Funnel uses Remote evaluation");let m=/^gg_sk_[A-Za-z0-9_-]{32,128}$/.test(e.credential);if(m?!e.customerId:e.customerId!==void 0)throw new d("INVALID_REQUEST","Only Server-Key starts name their Customer");let y=un({...e,scope:i,apiKey:e.credential}),o=u=>{let r=rn({...e,scope:i,runToken:u,...m?{serverKey:e.credential}:{}});return m||r.identify(e.credential),r};return{async start(u){let r=await y.start({...u,funnelId:e.funnelId,...m?{customer:{type:"id",value:e.customerId}}:{}}),s=o(r.runToken),g=await s.get();return{...r,...g,controller:s}},async restore(u){let r=o(u),s=await r.get();if(s.run.source.id!==e.funnelId)throw r.reset(),new d("SCOPE_MISMATCH","Run belongs to another Funnel");return{...s,runToken:u,controller:r}}}}export{yn as a,Rn as b,ye as c,Fn as d,ln as e,cn as f,Ze as g,rn as h,Zn as i,st as j,dt as k,un as l,Ct as m};
|