@ait-kit/sdk 0.2.0 → 0.3.0

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/README.md CHANGED
@@ -99,7 +99,7 @@ SDK initialization never grants or completes pending orders by itself.
99
99
  | Grant completion notify | ✅ | ✅ | sent only after server grant confirms |
100
100
  | Full-screen ads | ✅ | ➖ | ads are RN-only today |
101
101
  | Notification agreement | ✅ | ✅ | event-based, one template per request |
102
- | Share link / share sheet | ✅ | ✅ | `intoss://` paths; `closed` ≠ shared |
102
+ | Share link / share sheet | ✅ | ✅ | `intoss://` paths; `completed` ≠ shared |
103
103
  | Unsupported app version | `SdkError("UNSUPPORTED")` | same | per-function `isSupported` gates |
104
104
 
105
105
  Notification and sharing adapters ship in both entries (see below).
@@ -136,8 +136,13 @@ Contracts:
136
136
  reject with `SdkError("INVALID_LOGIN_RESULT")`; unsupported environments
137
137
  with `UNSUPPORTED`; SDK rejections propagate unchanged.
138
138
  - **Anonymous key** results must be the documented `{ type: "HASH", hash }`
139
- shape. Anything else (including sentinel values) rejects with
140
- `SdkError("INVALID_ANONYMOUS_KEY")` — the adapter never invents a key.
139
+ shape. Anything else (including the official SDK's `"ERROR"` sentinel)
140
+ rejects with `SdkError("INVALID_ANONYMOUS_KEY")` — the adapter never
141
+ invents a key. One exception: on React Native the official
142
+ `getAnonymousKey()` resolves `undefined` when the installed app is below
143
+ the feature's minimum version, which rejects with
144
+ `SdkError("UNSUPPORTED")` instead — an unsupported environment, not a
145
+ malformed key.
141
146
  - **Storage** keys and string values pass through byte-for-byte: no
142
147
  namespace prefixing, no key transformation. Compose namespaced keys
143
148
  yourself (e.g. `cart:items`). `get` resolves `null` for missing keys;
@@ -171,10 +176,10 @@ const result = await notification.requestAgreement("TEMPLATE_CODE");
171
176
  const share = createReactNativeShare();
172
177
  const link = await share.createLink("intoss://my-app/about", "https://cdn/og.png");
173
178
 
174
- // 3. Share sheet: "closed" means the sheet flow ended — nothing more.
179
+ // 3. Share sheet: "completed" means the SDK share call finished — nothing more.
175
180
  const uiResult = await share.sendMessage(`check this out ${link}`);
176
- // uiResult.status: "closed" | "failed" — closed does NOT prove the user
177
- // shared and never grants share-reward eligibility.
181
+ // uiResult.status: "completed" | "failed" — completed does NOT prove the
182
+ // user shared and never grants share-reward eligibility.
178
183
  ```
179
184
 
180
185
  Contracts:
@@ -186,8 +191,10 @@ Contracts:
186
191
  - **Share links** validate the documented `intoss://` path contract
187
192
  (`INVALID_SHARE_PATH` otherwise) and pass the resolved link through
188
193
  verbatim. OG image generation is the consumer's concern.
189
- - **Share sheet** resolution is `closed`, not "completed" — reward grants
190
- and completion tracking stay with the consumer.
194
+ - **Share sheet** resolution is `completed`, meaning ONLY that the SDK share
195
+ call finished — the underlying SDKs do not report whether the sheet opened,
196
+ closed, or the user actually shared. Reward grants and completion tracking
197
+ stay with the consumer. (Renamed from `closed` in 0.3.0; see Migrating.)
191
198
  - Unsupported surfaces/app versions reject with `SdkError("UNSUPPORTED")`.
192
199
 
193
200
  ## React Native full-screen ads
@@ -216,7 +223,16 @@ Behavior:
216
223
  are single-use: after a show flow ends (rewarded, dismissed, failed,
217
224
  timeout), a fresh load is required.
218
225
  - The whole show flow has one deadline (`showTimeoutMs`, default 60s);
219
- `loadTimeoutMs` (default 30s) bounds loads.
226
+ `loadTimeoutMs` (default 30s) bounds loads. The deadline is a single
227
+ budget covering SDK loading AND the provider event flow: a loader that
228
+ consumes most of it leaves only the remainder for the event wait, and a
229
+ fully consumed budget never registers with the provider. Timeout results
230
+ come from the event flow's own deadline, so the subscription is cleaned
231
+ up before the timeout settles — no orphaned listener outlives the call.
232
+ - Slot updates land inside the returned promise's settlement: a failed
233
+ load frees its slot before the caller's `catch` resumes (an immediate
234
+ retry starts a fresh registration), and a successful load is promoted
235
+ before the caller's `await` resumes (an immediate show works).
220
236
  - Missing or failed-to-import framework → `SdkError("SDK_UNAVAILABLE")`;
221
237
  unsupported app versions → `SdkError("UNSUPPORTED")`. Load failures are
222
238
  never permanently cached — a later call retries the import.
@@ -234,3 +250,46 @@ notification and sharing.)
234
250
 
235
251
  `@ait-kit/sdk` is versioned independently from the server API packages
236
252
  (`@ait-kit/api-*`), which release in lockstep with each other.
253
+
254
+ ## Verified official SDK versions
255
+
256
+ The adapters are developed and continuously checked against these exact
257
+ official releases (see `scripts/test-package-tarballs.mjs`):
258
+
259
+ | Official package | Verified version | Peer range |
260
+ |---|---|---|
261
+ | `@apps-in-toss/framework` (RN) | 2.10.10 | `>=2.10.10` |
262
+ | `@apps-in-toss/web-framework` (Web) | 3.4.0 | `>=3.4.0` |
263
+
264
+ Older versions may work where the runtime surfaces match (every capability
265
+ is checked per function and missing ones reject with `UNSUPPORTED`), but
266
+ only the versions above are verified. Newer versions are expected to work
267
+ via the same structural checks; if an official export shape changes, the
268
+ per-operation errors surface it instead of silent misbehavior.
269
+
270
+ ## Migrating
271
+
272
+ ### 0.3.0 — share sheet result `closed` → `completed`
273
+
274
+ `sendMessage` now resolves `{ status: "completed" }` instead of
275
+ `{ status: "closed" }`. The meaning also got precise: `completed` states
276
+ only that the SDK share **call** finished. It does not prove the share
277
+ sheet opened or closed, that the user shared, or that any reward
278
+ eligibility was earned. Update any `status === "closed"` checks; failure
279
+ results (`status: "failed"` with `code`/`reason`) are unchanged.
280
+
281
+ ### 0.3.0 — RN adapters call the official export shapes
282
+
283
+ The React Native default loaders now convert the official flat exports
284
+ (`appLogin`, `getAnonymousKey`, `requestNotificationAgreement`,
285
+ `getTossShareLink`, `share`) into the shared adapter contracts. Previously
286
+ a correctly installed official RN SDK still produced
287
+ `SdkError("UNSUPPORTED")` for these five capabilities because the loaders
288
+ looked for the web SDK's namespaced shapes. Custom `framework` injections
289
+ using the internal namespaced contract or a loader keep working unchanged.
290
+
291
+ One error-mapping change rides along: the official RN `getAnonymousKey()`
292
+ resolving `undefined` (installed app below the feature's minimum version)
293
+ now rejects with `SdkError("UNSUPPORTED")` instead of
294
+ `INVALID_ANONYMOUS_KEY`; the `"ERROR"` sentinel still rejects with
295
+ `INVALID_ANONYMOUS_KEY`.
package/dist/index.d.ts CHANGED
@@ -62,12 +62,14 @@ export type SdkNotificationAgreementResult = {
62
62
  reason?: string;
63
63
  };
64
64
  /**
65
- * Result of opening the share UI. `closed` means the native share sheet
66
- * flow ended normally — it does NOT prove the user actually shared, and it
67
- * never grants share-reward eligibility on its own.
65
+ * Result of opening the share UI. `completed` means ONLY that the SDK share
66
+ * call finished — it does NOT prove the share sheet opened or closed, that
67
+ * the user actually shared, and it never grants share-reward eligibility.
68
+ * (Renamed from `closed` in 0.3.0: the underlying SDKs guarantee the call
69
+ * completing, not the sheet's lifecycle.)
68
70
  */
69
71
  export type SdkShareUiResult = {
70
- status: "closed";
72
+ status: "completed";
71
73
  } | {
72
74
  status: "failed";
73
75
  code?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,oDAAoD;AACpD,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,GACpB;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,QAAQ,CAAA;CAAE,GACxC;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,GACvB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1C,mDAAmD;AACnD,MAAM,MAAM,YAAY,GACpB,iBAAiB,GACjB,aAAa,GACb,eAAe,GACf,oBAAoB,GACpB,gBAAgB,GAChB,iBAAiB,GACjB,sBAAsB,GACtB,uBAAuB,GACvB,oBAAoB,CAAC;AAMzB,mEAAmE;AACnE,MAAM,MAAM,4BAA4B,GAAG,cAAc,GAAG,eAAe,GAAG,mBAAmB,CAAC;AAElG;;;;;;GAMG;AACH,MAAM,MAAM,8BAA8B,GACtC;IACE,MAAM,EAAE,QAAQ,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC,4BAA4B,EAAE,mBAAmB,CAAC,CAAC;IACtE,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/B,GACD;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAC3E;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1E;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjE;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,GACpB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAMzD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,SAAS,CAAC;AAErD;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,gBAAgB,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,oEAAoE;AACpE,MAAM,WAAW,UAAU;IACzB,qEAAqE;IACrE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzC,6DAA6D;IAC7D,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,uEAAuE;IACvE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC;AAMD,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,gBAAgB,GAAG,cAAc,CAAC;AAC9E,MAAM,MAAM,2BAA2B,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE1E,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,YAAY,GAAG,kBAAkB,GAAG,WAAW,CAAC;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,cAAc,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,YAAY,CAAC,EAAE,2BAA2B,CAAC;IAC3C,MAAM,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,0EAA0E;AAC1E,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEpB;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,sBAAsB,CAAA;CAAE,GAClG;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,GACtB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACpD;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAKtF,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE;QACP,GAAG,EAAE,MAAM,CAAC;QACZ,mBAAmB,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;KAClF,CAAC;IACF,OAAO,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,sBAAsB,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5F,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE;QACP,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,mBAAmB,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;KAClF,CAAC;IACF,OAAO,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,sBAAsB,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5F,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED,gDAAgD;AAChD,qBAAa,QAAS,SAAQ,KAAK;IACjC,IAAI,EAAE,YAAY,CAAC;IAEnB,YAAY,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAI7E;CACF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ads.d.ts","sourceRoot":"","sources":["../../src/rn/ads.ts"],"names":[],"mappings":"AAGA,OAAO,EAA2B,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAEzE,OAAO,KAAK,EAAyB,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC1F,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,uBAAuB,CAAC;AAE/B,wEAAwE;AACxE,MAAM,MAAM,SAAS,GAAG,YAAY,CAAC;AAErC,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,SAAS,CAAC,EAAE,eAAe,GAAG,mBAAmB,CAAC;IAClD,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,8EAA8E;IAC9E,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD;;;;OAIG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC5D;AAWD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,qBAA0B,GAAG,cAAc,CAuLxF"}
1
+ {"version":3,"file":"ads.d.ts","sourceRoot":"","sources":["../../src/rn/ads.ts"],"names":[],"mappings":"AAGA,OAAO,EAA2B,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAEzE,OAAO,KAAK,EAAyB,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC1F,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,uBAAuB,CAAC;AAE/B,wEAAwE;AACxE,MAAM,MAAM,SAAS,GAAG,YAAY,CAAC;AAErC,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,SAAS,CAAC,EAAE,eAAe,GAAG,mBAAmB,CAAC;IAClD,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,8EAA8E;IAC9E,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD;;;;OAIG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC5D;AAmED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,qBAA0B,GAAG,cAAc,CAqKxF"}
package/dist/rn/ads.js CHANGED
@@ -6,6 +6,37 @@ import { runEventFlow } from "../event-flow.js";
6
6
  import { createDefaultFrameworkLoader } from "./framework-loader.js";
7
7
  const DEFAULT_SHOW_TIMEOUT_MS = 60_000;
8
8
  const DEFAULT_LOAD_TIMEOUT_MS = 30_000;
9
+ function createAdDeadline(timeoutMs, now = monotonicNow) {
10
+ if (!(timeoutMs > 0)) {
11
+ return { remainingMs: () => undefined, race: (promise) => promise };
12
+ }
13
+ const startedAt = now();
14
+ return {
15
+ remainingMs: () => timeoutMs - (now() - startedAt),
16
+ race: (promise) => new Promise((resolve, reject) => {
17
+ const timer = setTimeout(() => resolve(undefined), timeoutMs);
18
+ // Attaching handlers also sinks a settlement that happens after the
19
+ // deadline already won; the no-op reject/resolve after settling is
20
+ // ignored by promise semantics.
21
+ promise.then((value) => {
22
+ clearTimeout(timer);
23
+ resolve(value);
24
+ }, (error) => {
25
+ clearTimeout(timer);
26
+ reject(error);
27
+ });
28
+ })
29
+ };
30
+ }
31
+ /**
32
+ * Monotonic elapsed time: a system wall-clock correction while the loader
33
+ * is pending must not shrink or stretch the remaining budget.
34
+ */
35
+ function monotonicNow() {
36
+ return typeof performance !== "undefined" && typeof performance.now === "function"
37
+ ? performance.now()
38
+ : Date.now();
39
+ }
9
40
  /**
10
41
  * React Native ad adapter over `@apps-in-toss/framework`. Load state is
11
42
  * tracked per ad type + ad unit, in-flight duplicate loads share one
@@ -28,73 +59,28 @@ export function createReactNativeAds(options = {}) {
28
59
  if (existing) {
29
60
  return existing.kind === "loaded" ? Promise.resolve() : existing.promise;
30
61
  }
31
- const request = (async () => {
32
- // The deadline covers framework acquisition as well as the provider
33
- // load flow, and a timed-out task must not register with the provider
34
- // afterwards: a retried load would otherwise race a late registration.
35
- let cancelled = false;
36
- const task = (async () => {
37
- const framework = await loadFramework();
38
- if (cancelled) {
39
- throw new SdkError("AD_LOAD_TIMEOUT", "full-screen ad load timed out");
62
+ // Slot updates run inside this promise's settlement — before the
63
+ // caller's await/catch continuation — so a caller that immediately
64
+ // retries after a failure starts a fresh registration, and a caller
65
+ // that immediately shows after a success finds the slot loaded. The
66
+ // identity check keeps a stale task from touching a newer task's slot.
67
+ const promise = new Promise((resolve, reject) => {
68
+ runLoad(adGroupId).then(() => {
69
+ const current = slots.get(id);
70
+ if (current?.kind === "loading" && current.promise === promise) {
71
+ slots.set(id, { kind: "loaded" });
40
72
  }
41
- if (typeof framework.loadFullScreenAd.isSupported === "function" &&
42
- !framework.loadFullScreenAd.isSupported()) {
43
- throw new SdkError("UNSUPPORTED", "full-screen ads are not supported on this app version");
44
- }
45
- const outcome = await runEventFlow({
46
- register: (emit) => framework.loadFullScreenAd({
47
- options: { adGroupId },
48
- onEvent: emit,
49
- onError: (error) => emit({ type: "sdkError", error })
50
- }),
51
- reduce: (event) => event.type === "loaded"
52
- ? { done: true, result: undefined }
53
- : { done: true, result: loadFailure(event.error) },
54
- onTimeout: () => new SdkError("AD_LOAD_TIMEOUT", "full-screen ad load timed out"),
55
- timeoutMs: loadTimeoutMs
56
- });
57
- if (outcome instanceof SdkError) {
58
- throw outcome;
59
- }
60
- })();
61
- // If the deadline wins, the orphaned task rejects into this sink.
62
- task.catch(() => { });
63
- let timer;
64
- const deadline = new Promise((_, reject) => {
65
- if (loadTimeoutMs > 0) {
66
- timer = setTimeout(() => {
67
- cancelled = true;
68
- reject(new SdkError("AD_LOAD_TIMEOUT", "full-screen ad load timed out"));
69
- }, loadTimeoutMs);
73
+ resolve();
74
+ }, (error) => {
75
+ const current = slots.get(id);
76
+ if (current?.kind === "loading" && current.promise === promise) {
77
+ slots.delete(id);
70
78
  }
79
+ reject(error);
71
80
  });
72
- try {
73
- return await Promise.race([task, deadline]);
74
- }
75
- finally {
76
- if (timer !== undefined)
77
- clearTimeout(timer);
78
- }
79
- })();
80
- slots.set(id, { kind: "loading", promise: request });
81
- request
82
- .then(() => {
83
- // Promote only when this exact request still owns the slot: a
84
- // timed-out task resolving late must not mark a newer retry loaded.
85
- const current = slots.get(id);
86
- if (current?.kind === "loading" && current.promise === request) {
87
- slots.set(id, { kind: "loaded" });
88
- }
89
- })
90
- .catch(() => {
91
- // A failed load frees the slot so the next attempt retries.
92
- const current = slots.get(id);
93
- if (current?.kind === "loading" && current.promise === request) {
94
- slots.delete(id);
95
- }
96
81
  });
97
- return request;
82
+ slots.set(id, { kind: "loading", promise });
83
+ return promise;
98
84
  };
99
85
  const show = (adGroupId) => {
100
86
  const id = adKey("fullscreen", adGroupId);
@@ -111,65 +97,85 @@ export function createReactNativeAds(options = {}) {
111
97
  slots.delete(id);
112
98
  showing.add(id);
113
99
  return (async () => {
114
- // The deadline covers framework acquisition as well as the show flow:
115
- // a stalled loader must release the showing slot instead of wedging
116
- // the ad group forever, and a late-resolving loader must not register
117
- // a show the deadline already ended.
118
- let reward;
119
- let cancelled = false;
120
100
  const timedOut = () => ({ status: "failed", reason: "ad show flow timed out" });
121
101
  try {
122
- let timer;
123
- const deadline = new Promise((resolve) => {
124
- if (showTimeoutMs > 0) {
125
- timer = setTimeout(() => {
126
- cancelled = true;
127
- resolve(timedOut());
128
- }, showTimeoutMs);
129
- }
130
- });
131
- const task = (async () => {
132
- const framework = await loadFramework();
133
- if (cancelled) {
134
- return timedOut();
135
- }
136
- if (typeof framework.showFullScreenAd.isSupported === "function" &&
137
- !framework.showFullScreenAd.isSupported()) {
138
- throw new SdkError("UNSUPPORTED", "full-screen ads are not supported on this app version");
139
- }
140
- return await runEventFlow({
141
- register: (emit) => framework.showFullScreenAd({
142
- options: { adGroupId },
143
- onEvent: emit,
144
- onError: (error) => emit({ type: "sdkError", error })
145
- }),
146
- reduce: (event) => {
147
- if (event.type === "sdkError") {
148
- const message = errorMessage(event.error);
149
- return {
150
- done: true,
151
- result: { status: "failed", reason: `full-screen ad show failed: ${message}` }
152
- };
153
- }
154
- return reduceShowEvent(event, () => reward, (value) => (reward = value));
155
- },
156
- onTimeout: timedOut,
157
- timeoutMs: showTimeoutMs
158
- });
159
- })();
160
- try {
161
- return await Promise.race([task, deadline]);
102
+ // The whole show shares one budget: the loader races it, the event
103
+ // flow gets what remains, and the flow's own deadline produces the
104
+ // timeout result — its subscription cleanup completes before this
105
+ // promise settles, so `showing` is only released after the
106
+ // subscription is gone.
107
+ const deadline = createAdDeadline(showTimeoutMs);
108
+ const framework = await deadline.race(loadFramework());
109
+ if (!framework) {
110
+ return timedOut();
111
+ }
112
+ if (typeof framework.showFullScreenAd.isSupported === "function" &&
113
+ !framework.showFullScreenAd.isSupported()) {
114
+ throw new SdkError("UNSUPPORTED", "full-screen ads are not supported on this app version");
162
115
  }
163
- finally {
164
- if (timer !== undefined)
165
- clearTimeout(timer);
116
+ const remaining = deadline.remainingMs();
117
+ if (remaining !== undefined && remaining <= 0) {
118
+ return timedOut();
166
119
  }
120
+ let reward;
121
+ return await runEventFlow({
122
+ register: (emit) => framework.showFullScreenAd({
123
+ options: { adGroupId },
124
+ onEvent: emit,
125
+ onError: (error) => emit({ type: "sdkError", error })
126
+ }),
127
+ reduce: (event) => {
128
+ if (event.type === "sdkError") {
129
+ const message = errorMessage(event.error);
130
+ return {
131
+ done: true,
132
+ result: { status: "failed", reason: `full-screen ad show failed: ${message}` }
133
+ };
134
+ }
135
+ return reduceShowEvent(event, () => reward, (value) => (reward = value));
136
+ },
137
+ onTimeout: timedOut,
138
+ timeoutMs: remaining ?? 0
139
+ });
167
140
  }
168
141
  finally {
169
142
  showing.delete(id);
170
143
  }
171
144
  })();
172
145
  };
146
+ async function runLoad(adGroupId) {
147
+ // One deadline covers framework acquisition AND the provider flow. A
148
+ // loader that wins the race only just — or too late — leaves no budget
149
+ // for the provider registration, which is then skipped entirely.
150
+ const deadline = createAdDeadline(loadTimeoutMs);
151
+ const framework = await deadline.race(loadFramework());
152
+ if (!framework) {
153
+ throw new SdkError("AD_LOAD_TIMEOUT", "full-screen ad load timed out");
154
+ }
155
+ if (typeof framework.loadFullScreenAd.isSupported === "function" &&
156
+ !framework.loadFullScreenAd.isSupported()) {
157
+ throw new SdkError("UNSUPPORTED", "full-screen ads are not supported on this app version");
158
+ }
159
+ const remaining = deadline.remainingMs();
160
+ if (remaining !== undefined && remaining <= 0) {
161
+ throw new SdkError("AD_LOAD_TIMEOUT", "full-screen ad load timed out");
162
+ }
163
+ const outcome = await runEventFlow({
164
+ register: (emit) => framework.loadFullScreenAd({
165
+ options: { adGroupId },
166
+ onEvent: emit,
167
+ onError: (error) => emit({ type: "sdkError", error })
168
+ }),
169
+ reduce: (event) => event.type === "loaded"
170
+ ? { done: true, result: undefined }
171
+ : { done: true, result: loadFailure(event.error) },
172
+ onTimeout: () => new SdkError("AD_LOAD_TIMEOUT", "full-screen ad load timed out"),
173
+ timeoutMs: remaining ?? 0
174
+ });
175
+ if (outcome instanceof SdkError) {
176
+ throw outcome;
177
+ }
178
+ }
173
179
  async function loadFramework() {
174
180
  const result = await loader();
175
181
  if (!result.available) {
@@ -1 +1 @@
1
- {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/rn/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAClF,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EAGzB,MAAM,kCAAkC,CAAC;AAE1C,MAAM,WAAW,0BAA0B;IACzC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,mBAAmB,GAAG,sBAAsB,CAAC;CAC1D;AAED,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,KAAK,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC;IACjC,mEAAmE;IACnE,eAAe,IAAI,OAAO,CAAC,eAAe,CAAC,CAAC;CAC7C;AAED,wBAAgB,yBAAyB,CAAC,OAAO,GAAE,0BAA+B,GAAG,mBAAmB,CAavG;AAED,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,0BAA0B,CAAC,WAAW,CAAC,GACjD,sBAAsB,CAQxB"}
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/rn/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAClF,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EAGzB,MAAM,kCAAkC,CAAC;AAG1C,MAAM,WAAW,0BAA0B;IACzC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,mBAAmB,GAAG,sBAAsB,CAAC;CAC1D;AAED,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,KAAK,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC;IACjC,mEAAmE;IACnE,eAAe,IAAI,OAAO,CAAC,eAAe,CAAC,CAAC;CAC7C;AAED,wBAAgB,yBAAyB,CAAC,OAAO,GAAE,0BAA+B,GAAG,mBAAmB,CAavG;AAED,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,0BAA0B,CAAC,WAAW,CAAC,GACjD,sBAAsB,CAQxB"}
@@ -1,5 +1,6 @@
1
1
  import { SdkError } from "../index.js";
2
2
  import { runSdkGetAnonymousKey, runSdkLogin } from "../identity/platform-contract.js";
3
+ import { adaptOfficialRnIdentity } from "./official-module.js";
3
4
  export function createReactNativeIdentity(options = {}) {
4
5
  const loader = normalizeIdentityLoader(options.framework);
5
6
  const load = async () => {
@@ -23,6 +24,12 @@ export function normalizeIdentityLoader(framework) {
23
24
  }
24
25
  return async () => ({ available: true, module: framework });
25
26
  }
27
+ /**
28
+ * Default loader: imports the official `@apps-in-toss/framework` lazily and
29
+ * converts its flat export surface (`appLogin`, `getAnonymousKey`) to the
30
+ * shared identity contract. A failed import is never cached (a later call
31
+ * retries); successful loads cache the converted module.
32
+ */
26
33
  function createDefaultRnIdentityLoader() {
27
34
  let cached;
28
35
  return async () => {
@@ -30,8 +37,7 @@ function createDefaultRnIdentityLoader() {
30
37
  return { available: true, module: cached };
31
38
  }
32
39
  try {
33
- const framework = (await import("@apps-in-toss/framework"));
34
- cached = framework;
40
+ cached = adaptOfficialRnIdentity(await import("@apps-in-toss/framework"));
35
41
  return { available: true, module: cached };
36
42
  }
37
43
  catch (error) {
@@ -30,9 +30,9 @@ export interface ReactNativeShare {
30
30
  /** Creates a share link for an `intoss://` deeplink path. */
31
31
  createLink(path: string, ogImageUrl?: string): Promise<string>;
32
32
  /**
33
- * Opens the native share sheet. Resolving `closed` means the sheet flow
34
- * ended — it does not prove the user shared and never grants reward
35
- * eligibility.
33
+ * Opens the native share sheet. Resolving `completed` means the SDK share
34
+ * call finished — it does not prove the user shared (or even saw the
35
+ * sheet) and never grants reward eligibility.
36
36
  */
37
37
  sendMessage(message: string): Promise<SdkShareUiResult>;
38
38
  }
@@ -1 +1 @@
1
- {"version":3,"file":"notify-share.d.ts","sourceRoot":"","sources":["../../src/rn/notify-share.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,8BAA8B,EACnC,KAAK,gBAAgB,EACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,uBAAuB,EAE7B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EAGtB,MAAM,+BAA+B,CAAC;AAQvC,MAAM,WAAW,8BAA8B;IAC7C;;;OAGG;IACH,SAAS,CAAC,EAAE,uBAAuB,GAAG,0BAA0B,CAAC;IACjE,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAAC;CACjF;AAED,wBAAgB,6BAA6B,CAC3C,OAAO,GAAE,8BAAmC,GAC3C,uBAAuB,CAazB;AAMD,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,SAAS,CAAC,EAAE,gBAAgB,GAAG,mBAAmB,CAAC;CACpD;AAED,MAAM,WAAW,gBAAgB;IAC/B,6DAA6D;IAC7D,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D;;;;OAIG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACzD;AAED,wBAAgB,sBAAsB,CACpC,OAAO,GAAE,uBAA4B,GACpC,gBAAgB,CAyClB;AAMD,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,8BAA8B,CAAC,WAAW,CAAC,GACrD,0BAA0B,CAQ5B;AAED,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,uBAAuB,CAAC,WAAW,CAAC,GAC9C,mBAAmB,CAQrB"}
1
+ {"version":3,"file":"notify-share.d.ts","sourceRoot":"","sources":["../../src/rn/notify-share.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,8BAA8B,EACnC,KAAK,gBAAgB,EACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,uBAAuB,EAE7B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EAGtB,MAAM,+BAA+B,CAAC;AASvC,MAAM,WAAW,8BAA8B;IAC7C;;;OAGG;IACH,SAAS,CAAC,EAAE,uBAAuB,GAAG,0BAA0B,CAAC;IACjE,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAAC;CACjF;AAED,wBAAgB,6BAA6B,CAC3C,OAAO,GAAE,8BAAmC,GAC3C,uBAAuB,CAazB;AAMD,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,SAAS,CAAC,EAAE,gBAAgB,GAAG,mBAAmB,CAAC;CACpD;AAED,MAAM,WAAW,gBAAgB;IAC/B,6DAA6D;IAC7D,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D;;;;OAIG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACzD;AAED,wBAAgB,sBAAsB,CACpC,OAAO,GAAE,uBAA4B,GACpC,gBAAgB,CAyClB;AAMD,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,8BAA8B,CAAC,WAAW,CAAC,GACrD,0BAA0B,CAQ5B;AAED,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,uBAAuB,CAAC,WAAW,CAAC,GAC9C,mBAAmB,CAQrB"}
@@ -1,6 +1,7 @@
1
1
  import { SdkError } from "../index.js";
2
2
  import { runRequestAgreement } from "../notification/platform-contract.js";
3
3
  import { runShareUi, validateSharePath } from "../share/platform-contract.js";
4
+ import { adaptOfficialRnNotification, adaptOfficialRnShare } from "./official-module.js";
4
5
  const DEFAULT_AGREEMENT_TIMEOUT_MS = 60_000;
5
6
  export function createReactNativeNotification(options = {}) {
6
7
  const loader = normalizeNotificationLoader(options.framework);
@@ -58,7 +59,7 @@ export function createReactNativeShare(options = {}) {
58
59
  // ---------------------------------------------------------------------------
59
60
  export function normalizeNotificationLoader(framework) {
60
61
  if (!framework) {
61
- return createDefaultRnModuleLoader();
62
+ return createDefaultRnNotificationLoader();
62
63
  }
63
64
  if (typeof framework === "function") {
64
65
  return framework;
@@ -67,22 +68,46 @@ export function normalizeNotificationLoader(framework) {
67
68
  }
68
69
  export function normalizeShareLoader(framework) {
69
70
  if (!framework) {
70
- return createDefaultRnModuleLoader();
71
+ return createDefaultRnShareLoader();
71
72
  }
72
73
  if (typeof framework === "function") {
73
74
  return framework;
74
75
  }
75
76
  return async () => ({ available: true, module: framework });
76
77
  }
77
- function createDefaultRnModuleLoader() {
78
+ /**
79
+ * Default loaders: import the official `@apps-in-toss/framework` lazily and
80
+ * convert its flat export surface (`requestNotificationAgreement`,
81
+ * `getTossShareLink`, `share`) to the shared contracts. Failed imports are
82
+ * never cached; successful loads cache the converted module.
83
+ */
84
+ function createDefaultRnNotificationLoader() {
85
+ let cached;
86
+ return async () => {
87
+ if (cached) {
88
+ return { available: true, module: cached };
89
+ }
90
+ try {
91
+ cached = adaptOfficialRnNotification(await import("@apps-in-toss/framework"));
92
+ return { available: true, module: cached };
93
+ }
94
+ catch (error) {
95
+ const message = error instanceof Error ? error.message : String(error);
96
+ return {
97
+ available: false,
98
+ reason: `failed to import @apps-in-toss/framework: ${message}`
99
+ };
100
+ }
101
+ };
102
+ }
103
+ function createDefaultRnShareLoader() {
78
104
  let cached;
79
105
  return async () => {
80
106
  if (cached) {
81
107
  return { available: true, module: cached };
82
108
  }
83
109
  try {
84
- const framework = (await import("@apps-in-toss/framework"));
85
- cached = framework;
110
+ cached = adaptOfficialRnShare(await import("@apps-in-toss/framework"));
86
111
  return { available: true, module: cached };
87
112
  }
88
113
  catch (error) {
@@ -0,0 +1,67 @@
1
+ import type { IdentityPlatformSdk } from "../identity/platform-contract.js";
2
+ import type { NotificationAgreementParams, NotificationPlatformSdk } from "../notification/platform-contract.js";
3
+ import type { SharePlatformSdk } from "../share/platform-contract.js";
4
+ /**
5
+ * Internal conversion layer between the official `@apps-in-toss/framework`
6
+ * exports and the shared platform contracts. The official React Native SDK
7
+ * (verified against 2.10.10, re-exported from @apps-in-toss/native-modules)
8
+ * exposes these capabilities as flat module functions, while the shared
9
+ * contracts (which match the web SDK's namespaced API) group them under
10
+ * TossAuth/User/Notification/Share. This module performs that translation;
11
+ * it is never exported from a public subpath.
12
+ *
13
+ * Every member of {@link OfficialRnFrameworkModule} is optional: older
14
+ * app/SDK versions may omit any of them, and each adapter surfaces a
15
+ * missing capability as a clear UNSUPPORTED error for that operation
16
+ * instead of guessing a call shape.
17
+ */
18
+ /** Official `appLogin()` result, preserved verbatim by the identity engine. */
19
+ export interface OfficialAppLoginResult {
20
+ authorizationCode: string;
21
+ referrer: "DEFAULT" | "SANDBOX";
22
+ }
23
+ /**
24
+ * Official `getAnonymousKey()` success shape. The official function may
25
+ * also resolve the `"ERROR"` sentinel (unknown failure) or `undefined`
26
+ * (app below the feature's minimum version); both are handled by the
27
+ * adapter below.
28
+ */
29
+ export interface OfficialAnonymousKeyResult {
30
+ type: "HASH";
31
+ hash: string;
32
+ }
33
+ type OfficialFunction<F> = F & {
34
+ isSupported?: () => boolean;
35
+ };
36
+ /** Structural subset of the official React Native framework module. */
37
+ export interface OfficialRnFrameworkModule {
38
+ appLogin?: OfficialFunction<() => Promise<OfficialAppLoginResult>>;
39
+ getAnonymousKey?: OfficialFunction<() => Promise<OfficialAnonymousKeyResult | "ERROR" | undefined>>;
40
+ requestNotificationAgreement?: OfficialFunction<(params: NotificationAgreementParams) => () => void>;
41
+ getTossShareLink?: OfficialFunction<(path: string, ogImageUrl?: string) => Promise<string>>;
42
+ share?: OfficialFunction<(message: {
43
+ message: string;
44
+ }) => Promise<void>>;
45
+ }
46
+ /**
47
+ * Converts the official identity exports (`appLogin`, `getAnonymousKey`) to
48
+ * the shared identity contract. Missing functions stay missing so the
49
+ * shared engine reports UNSUPPORTED per operation.
50
+ */
51
+ export declare function adaptOfficialRnIdentity(module: OfficialRnFrameworkModule): IdentityPlatformSdk;
52
+ /**
53
+ * Converts the official `requestNotificationAgreement` to the shared
54
+ * notification contract. The official params shape matches the internal
55
+ * one exactly, and the returned cleanup function passes through so the
56
+ * event flow owns and invokes it.
57
+ */
58
+ export declare function adaptOfficialRnNotification(module: OfficialRnFrameworkModule): NotificationPlatformSdk;
59
+ /**
60
+ * Converts the official share exports to the shared share contract:
61
+ * `getTossShareLink(path, ogImageUrl?)` takes positional arguments (the
62
+ * internal contract's object form is unpacked here) and `share` receives
63
+ * the `{ message }` object as-is.
64
+ */
65
+ export declare function adaptOfficialRnShare(module: OfficialRnFrameworkModule): SharePlatformSdk;
66
+ export {};
67
+ //# sourceMappingURL=official-module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"official-module.d.ts","sourceRoot":"","sources":["../../src/rn/official-module.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,KAAK,EACV,2BAA2B,EAC3B,uBAAuB,EACxB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAyB,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAE7F;;;;;;;;;;;;;GAaG;AAEH,+EAA+E;AAC/E,MAAM,WAAW,sBAAsB;IACrC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,SAAS,GAAG,SAAS,CAAC;CACjC;AAED;;;;;GAKG;AACH,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,KAAK,gBAAgB,CAAC,CAAC,IAAI,CAAC,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,OAAO,CAAA;CAAE,CAAC;AAE/D,uEAAuE;AACvE,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,EAAE,gBAAgB,CAAC,MAAM,OAAO,CAAC,sBAAsB,CAAC,CAAC,CAAC;IACnE,eAAe,CAAC,EAAE,gBAAgB,CAChC,MAAM,OAAO,CAAC,0BAA0B,GAAG,OAAO,GAAG,SAAS,CAAC,CAChE,CAAC;IACF,4BAA4B,CAAC,EAAE,gBAAgB,CAC7C,CAAC,MAAM,EAAE,2BAA2B,KAAK,MAAM,IAAI,CACpD,CAAC;IACF,gBAAgB,CAAC,EAAE,gBAAgB,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5F,KAAK,CAAC,EAAE,gBAAgB,CAAC,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;CAC3E;AAkBD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,yBAAyB,GAAG,mBAAmB,CA6B9F;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,yBAAyB,GAAG,uBAAuB,CAWtG;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,yBAAyB,GAAG,gBAAgB,CAsBxF"}
@@ -0,0 +1,86 @@
1
+ import { SdkError } from "../index.js";
2
+ /**
3
+ * Wraps an official function for the internal contract while preserving the
4
+ * original receiver (the official module object, in case the implementation
5
+ * relies on `this`) and an optional `isSupported` flag, so version-gate
6
+ * checks keep working whenever the official SDK exposes them.
7
+ */
8
+ function preserveSupport(original, wrapper) {
9
+ if (typeof original.isSupported === "function") {
10
+ return Object.assign(wrapper, { isSupported: () => original.isSupported() });
11
+ }
12
+ return wrapper;
13
+ }
14
+ /**
15
+ * Converts the official identity exports (`appLogin`, `getAnonymousKey`) to
16
+ * the shared identity contract. Missing functions stay missing so the
17
+ * shared engine reports UNSUPPORTED per operation.
18
+ */
19
+ export function adaptOfficialRnIdentity(module) {
20
+ const identity = {};
21
+ if (typeof module.appLogin === "function") {
22
+ const appLogin = module.appLogin;
23
+ identity.TossAuth = {
24
+ login: preserveSupport(appLogin, () => appLogin.call(module))
25
+ };
26
+ }
27
+ if (typeof module.getAnonymousKey === "function") {
28
+ const getAnonymousKey = module.getAnonymousKey;
29
+ identity.User = {
30
+ getAnonymousKey: preserveSupport(getAnonymousKey, async () => {
31
+ const result = await getAnonymousKey.call(module);
32
+ // The official SDK resolves undefined when the installed app is
33
+ // below the feature's minimum version: that is an unsupported
34
+ // environment, not a malformed result.
35
+ if (result === undefined) {
36
+ throw new SdkError("UNSUPPORTED", "the installed app version does not support getAnonymousKey");
37
+ }
38
+ // The "ERROR" sentinel and malformed shapes are rejected by the
39
+ // shared validator (runSdkGetAnonymousKey) like on any platform.
40
+ return result;
41
+ })
42
+ };
43
+ }
44
+ return identity;
45
+ }
46
+ /**
47
+ * Converts the official `requestNotificationAgreement` to the shared
48
+ * notification contract. The official params shape matches the internal
49
+ * one exactly, and the returned cleanup function passes through so the
50
+ * event flow owns and invokes it.
51
+ */
52
+ export function adaptOfficialRnNotification(module) {
53
+ const notification = {};
54
+ if (typeof module.requestNotificationAgreement === "function") {
55
+ const requestNotificationAgreement = module.requestNotificationAgreement;
56
+ notification.Notification = {
57
+ requestAgreement: preserveSupport(requestNotificationAgreement, (params) => requestNotificationAgreement.call(module, params))
58
+ };
59
+ }
60
+ return notification;
61
+ }
62
+ /**
63
+ * Converts the official share exports to the shared share contract:
64
+ * `getTossShareLink(path, ogImageUrl?)` takes positional arguments (the
65
+ * internal contract's object form is unpacked here) and `share` receives
66
+ * the `{ message }` object as-is.
67
+ */
68
+ export function adaptOfficialRnShare(module) {
69
+ const share = {};
70
+ if (typeof module.getTossShareLink === "function") {
71
+ const getTossShareLink = module.getTossShareLink;
72
+ share.Share = {
73
+ createLink: preserveSupport(getTossShareLink, ({ path, ogImageUrl }) => ogImageUrl !== undefined
74
+ ? getTossShareLink.call(module, path, ogImageUrl)
75
+ : getTossShareLink.call(module, path))
76
+ };
77
+ }
78
+ if (typeof module.share === "function") {
79
+ const officialShare = module.share;
80
+ share.Share = {
81
+ ...share.Share,
82
+ sendMessage: preserveSupport(officialShare, (message) => officialShare.call(module, message))
83
+ };
84
+ }
85
+ return share;
86
+ }
@@ -52,7 +52,9 @@ function createDefaultRnStorageLoader() {
52
52
  return { available: true, module: cached };
53
53
  }
54
54
  try {
55
- const framework = (await import("@apps-in-toss/framework"));
55
+ // The official RN SDK exposes Storage under the same namespaced shape
56
+ // as the shared contract, so no conversion is needed.
57
+ const framework = await import("@apps-in-toss/framework");
56
58
  cached = framework;
57
59
  return { available: true, module: cached };
58
60
  }
@@ -31,10 +31,10 @@ export type SharePlatformLoader = () => Promise<{
31
31
  */
32
32
  export declare function validateSharePath(path: string): string;
33
33
  /**
34
- * Wraps the share-UI call: a resolution means the native share sheet flow
35
- * ended normally ("closed") — it never proves the user actually shared and
36
- * never grants reward eligibility. Rejections surface as failed with the
37
- * platform's error code/message preserved.
34
+ * Wraps the share-UI call: a resolution means ONLY that the SDK share call
35
+ * completed ("completed") — it never proves the share sheet opened or that
36
+ * the user actually shared, and never grants reward eligibility. Rejections
37
+ * surface as failed with the platform's error code/message preserved.
38
38
  */
39
39
  export declare function runShareUi(platform: SharePlatformSdk, message: string): Promise<SdkShareUiResult>;
40
40
  export {};
@@ -13,15 +13,15 @@ export function validateSharePath(path) {
13
13
  return path;
14
14
  }
15
15
  /**
16
- * Wraps the share-UI call: a resolution means the native share sheet flow
17
- * ended normally ("closed") — it never proves the user actually shared and
18
- * never grants reward eligibility. Rejections surface as failed with the
19
- * platform's error code/message preserved.
16
+ * Wraps the share-UI call: a resolution means ONLY that the SDK share call
17
+ * completed ("completed") — it never proves the share sheet opened or that
18
+ * the user actually shared, and never grants reward eligibility. Rejections
19
+ * surface as failed with the platform's error code/message preserved.
20
20
  */
21
21
  export async function runShareUi(platform, message) {
22
22
  try {
23
23
  await platform.Share.sendMessage({ message });
24
- return { status: "closed" };
24
+ return { status: "completed" };
25
25
  }
26
26
  catch (error) {
27
27
  const code = readErrorCode(error);
@@ -49,7 +49,7 @@ export function createWebStorage(options = {}) {
49
49
  }
50
50
  function normalizeWebIdentityLoader(framework) {
51
51
  if (!framework) {
52
- return createDefaultWebLoader();
52
+ return createDefaultWebIdentityLoader();
53
53
  }
54
54
  if (typeof framework === "function") {
55
55
  return framework;
@@ -58,21 +58,44 @@ function normalizeWebIdentityLoader(framework) {
58
58
  }
59
59
  function normalizeWebStorageLoader(framework) {
60
60
  if (!framework) {
61
- return createDefaultWebLoader();
61
+ return createDefaultWebStorageLoader();
62
62
  }
63
63
  if (typeof framework === "function") {
64
64
  return framework;
65
65
  }
66
66
  return async () => ({ available: true, module: framework });
67
67
  }
68
- function createDefaultWebLoader() {
68
+ // The web SDK exposes the shared namespaced contract shapes directly, so
69
+ // the default loaders consume the official module without any conversion
70
+ // or type assertion; a failed import is never cached, successful loads are.
71
+ function createDefaultWebIdentityLoader() {
69
72
  let cached;
70
73
  return async () => {
71
74
  if (cached) {
72
75
  return { available: true, module: cached };
73
76
  }
74
77
  try {
75
- const framework = (await import("@apps-in-toss/web-framework"));
78
+ const framework = await import("@apps-in-toss/web-framework");
79
+ cached = framework;
80
+ return { available: true, module: cached };
81
+ }
82
+ catch (error) {
83
+ const message = error instanceof Error ? error.message : String(error);
84
+ return {
85
+ available: false,
86
+ reason: `failed to import @apps-in-toss/web-framework: ${message}`
87
+ };
88
+ }
89
+ };
90
+ }
91
+ function createDefaultWebStorageLoader() {
92
+ let cached;
93
+ return async () => {
94
+ if (cached) {
95
+ return { available: true, module: cached };
96
+ }
97
+ try {
98
+ const framework = await import("@apps-in-toss/web-framework");
76
99
  cached = framework;
77
100
  return { available: true, module: cached };
78
101
  }
@@ -28,8 +28,9 @@ export interface WebShare {
28
28
  /** Creates a share link for an `intoss://` deeplink path. */
29
29
  createLink(path: string, ogImageUrl?: string): Promise<string>;
30
30
  /**
31
- * Opens the native share sheet; `closed` never proves the user shared and
32
- * never grants reward eligibility.
31
+ * Opens the native share sheet; `completed` means only that the SDK share
32
+ * call finished — it never proves the user shared and never grants reward
33
+ * eligibility.
33
34
  */
34
35
  sendMessage(message: string): Promise<SdkShareUiResult>;
35
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"notify-share.d.ts","sourceRoot":"","sources":["../../src/web/notify-share.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,8BAA8B,EACnC,KAAK,gBAAgB,EACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,uBAAuB,EAE7B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EAGtB,MAAM,+BAA+B,CAAC;AAIvC,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,SAAS,CAAC,EAAE,uBAAuB,GAAG,0BAA0B,CAAC;IACjE,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,qEAAqE;IACrE,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAAC;CACjF;AAED,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,sBAA2B,GAAG,eAAe,CAa3F;AAED,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,SAAS,CAAC,EAAE,gBAAgB,GAAG,mBAAmB,CAAC;CACpD;AAED,MAAM,WAAW,QAAQ;IACvB,6DAA6D;IAC7D,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D;;;OAGG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACzD;AAED,wBAAgB,cAAc,CAAC,OAAO,GAAE,eAAoB,GAAG,QAAQ,CAwCtE"}
1
+ {"version":3,"file":"notify-share.d.ts","sourceRoot":"","sources":["../../src/web/notify-share.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,8BAA8B,EACnC,KAAK,gBAAgB,EACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,uBAAuB,EAE7B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EAGtB,MAAM,+BAA+B,CAAC;AAIvC,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,SAAS,CAAC,EAAE,uBAAuB,GAAG,0BAA0B,CAAC;IACjE,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,qEAAqE;IACrE,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAAC;CACjF;AAED,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,sBAA2B,GAAG,eAAe,CAa3F;AAED,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,SAAS,CAAC,EAAE,gBAAgB,GAAG,mBAAmB,CAAC;CACpD;AAED,MAAM,WAAW,QAAQ;IACvB,6DAA6D;IAC7D,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D;;;;OAIG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACzD;AAED,wBAAgB,cAAc,CAAC,OAAO,GAAE,eAAoB,GAAG,QAAQ,CAwCtE"}
@@ -54,7 +54,7 @@ export function createWebShare(options = {}) {
54
54
  }
55
55
  function normalizeWebNotificationLoader(framework) {
56
56
  if (!framework) {
57
- return createDefaultWebModuleLoader();
57
+ return createDefaultWebNotificationLoader();
58
58
  }
59
59
  if (typeof framework === "function") {
60
60
  return framework;
@@ -63,21 +63,43 @@ function normalizeWebNotificationLoader(framework) {
63
63
  }
64
64
  function normalizeWebShareLoader(framework) {
65
65
  if (!framework) {
66
- return createDefaultWebModuleLoader();
66
+ return createDefaultWebShareLoader();
67
67
  }
68
68
  if (typeof framework === "function") {
69
69
  return framework;
70
70
  }
71
71
  return async () => ({ available: true, module: framework });
72
72
  }
73
- function createDefaultWebModuleLoader() {
73
+ // See createDefaultWebIdentityLoader in ./identity.ts: the web SDK already
74
+ // matches the shared contract shapes, so no conversion or assertion is used.
75
+ function createDefaultWebNotificationLoader() {
74
76
  let cached;
75
77
  return async () => {
76
78
  if (cached) {
77
79
  return { available: true, module: cached };
78
80
  }
79
81
  try {
80
- const framework = (await import("@apps-in-toss/web-framework"));
82
+ const framework = await import("@apps-in-toss/web-framework");
83
+ cached = framework;
84
+ return { available: true, module: cached };
85
+ }
86
+ catch (error) {
87
+ const message = error instanceof Error ? error.message : String(error);
88
+ return {
89
+ available: false,
90
+ reason: `failed to import @apps-in-toss/web-framework: ${message}`
91
+ };
92
+ }
93
+ };
94
+ }
95
+ function createDefaultWebShareLoader() {
96
+ let cached;
97
+ return async () => {
98
+ if (cached) {
99
+ return { available: true, module: cached };
100
+ }
101
+ try {
102
+ const framework = await import("@apps-in-toss/web-framework");
81
103
  cached = framework;
82
104
  return { available: true, module: cached };
83
105
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ait-kit/sdk",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Frontend SDK adapters for Apps in Toss mini apps: shared contracts plus per-runtime entry points.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -49,8 +49,8 @@
49
49
  "prepack": "bun run build"
50
50
  },
51
51
  "peerDependencies": {
52
- "@apps-in-toss/framework": "*",
53
- "@apps-in-toss/web-framework": "*"
52
+ "@apps-in-toss/framework": ">=2.10.10",
53
+ "@apps-in-toss/web-framework": ">=3.4.0"
54
54
  },
55
55
  "peerDependenciesMeta": {
56
56
  "@apps-in-toss/framework": {