@ait-kit/sdk 0.2.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.
Files changed (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +236 -0
  3. package/dist/event-flow.d.ts +36 -0
  4. package/dist/event-flow.d.ts.map +1 -0
  5. package/dist/event-flow.js +101 -0
  6. package/dist/iap/adapter.d.ts +47 -0
  7. package/dist/iap/adapter.d.ts.map +1 -0
  8. package/dist/iap/adapter.js +175 -0
  9. package/dist/iap/grant-coordinator.d.ts +36 -0
  10. package/dist/iap/grant-coordinator.d.ts.map +1 -0
  11. package/dist/iap/grant-coordinator.js +69 -0
  12. package/dist/iap/platform-contract.d.ts +55 -0
  13. package/dist/iap/platform-contract.d.ts.map +1 -0
  14. package/dist/iap/platform-contract.js +26 -0
  15. package/dist/iap/purchase-flow.d.ts +34 -0
  16. package/dist/iap/purchase-flow.d.ts.map +1 -0
  17. package/dist/iap/purchase-flow.js +167 -0
  18. package/dist/identity/platform-contract.d.ts +44 -0
  19. package/dist/identity/platform-contract.d.ts.map +1 -0
  20. package/dist/identity/platform-contract.js +71 -0
  21. package/dist/index.d.ts +215 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +16 -0
  24. package/dist/notification/platform-contract.d.ts +43 -0
  25. package/dist/notification/platform-contract.d.ts.map +1 -0
  26. package/dist/notification/platform-contract.js +89 -0
  27. package/dist/rn/ads.d.ts +39 -0
  28. package/dist/rn/ads.d.ts.map +1 -0
  29. package/dist/rn/ads.js +226 -0
  30. package/dist/rn/framework-contract.d.ts +45 -0
  31. package/dist/rn/framework-contract.d.ts.map +1 -0
  32. package/dist/rn/framework-contract.js +7 -0
  33. package/dist/rn/framework-loader.d.ts +22 -0
  34. package/dist/rn/framework-loader.d.ts.map +1 -0
  35. package/dist/rn/framework-loader.js +26 -0
  36. package/dist/rn/iap.d.ts +19 -0
  37. package/dist/rn/iap.d.ts.map +1 -0
  38. package/dist/rn/iap.js +35 -0
  39. package/dist/rn/identity.d.ts +20 -0
  40. package/dist/rn/identity.d.ts.map +1 -0
  41. package/dist/rn/identity.js +42 -0
  42. package/dist/rn/index.d.ts +27 -0
  43. package/dist/rn/index.d.ts.map +1 -0
  44. package/dist/rn/index.js +24 -0
  45. package/dist/rn/notify-share.d.ts +42 -0
  46. package/dist/rn/notify-share.d.ts.map +1 -0
  47. package/dist/rn/notify-share.js +159 -0
  48. package/dist/rn/storage.d.ts +18 -0
  49. package/dist/rn/storage.d.ts.map +1 -0
  50. package/dist/rn/storage.js +64 -0
  51. package/dist/share/platform-contract.d.ts +41 -0
  52. package/dist/share/platform-contract.d.ts.map +1 -0
  53. package/dist/share/platform-contract.js +34 -0
  54. package/dist/storage/platform-contract.d.ts +26 -0
  55. package/dist/storage/platform-contract.d.ts.map +1 -0
  56. package/dist/storage/platform-contract.js +16 -0
  57. package/dist/web/framework-loader.d.ts +9 -0
  58. package/dist/web/framework-loader.d.ts.map +1 -0
  59. package/dist/web/framework-loader.js +32 -0
  60. package/dist/web/iap-contract.d.ts +13 -0
  61. package/dist/web/iap-contract.d.ts.map +1 -0
  62. package/dist/web/iap-contract.js +1 -0
  63. package/dist/web/identity.d.ts +30 -0
  64. package/dist/web/identity.d.ts.map +1 -0
  65. package/dist/web/identity.js +87 -0
  66. package/dist/web/index.d.ts +47 -0
  67. package/dist/web/index.d.ts.map +1 -0
  68. package/dist/web/index.js +43 -0
  69. package/dist/web/notify-share.d.ts +37 -0
  70. package/dist/web/notify-share.d.ts.map +1 -0
  71. package/dist/web/notify-share.js +154 -0
  72. package/package.json +66 -0
@@ -0,0 +1,34 @@
1
+ import { SdkError } from "../index.js";
2
+ import { readErrorCode, readErrorMessage } from "../notification/platform-contract.js";
3
+ /**
4
+ * Validates the documented input contract (an `intoss://` deeplink path)
5
+ * before dispatching; the resolved share link passes through verbatim.
6
+ */
7
+ export function validateSharePath(path) {
8
+ // The path is dispatched verbatim, so surrounding whitespace must be
9
+ // rejected rather than silently trimmed away.
10
+ if (typeof path !== "string" || !/^intoss:\/\/[^\s/?#][^\s]*$/.test(path)) {
11
+ throw new SdkError("INVALID_SHARE_PATH", `share link path must be an intoss:// deeplink, received: ${String(path)}`);
12
+ }
13
+ return path;
14
+ }
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.
20
+ */
21
+ export async function runShareUi(platform, message) {
22
+ try {
23
+ await platform.Share.sendMessage({ message });
24
+ return { status: "closed" };
25
+ }
26
+ catch (error) {
27
+ const code = readErrorCode(error);
28
+ return {
29
+ status: "failed",
30
+ ...(code !== undefined ? { code } : {}),
31
+ reason: readErrorMessage(error)
32
+ };
33
+ }
34
+ }
@@ -0,0 +1,26 @@
1
+ import { type SdkStorage } from "../index.js";
2
+ /**
3
+ * Internal platform contract for the storage adapters, shared by /rn and
4
+ * /web. Keys and string values pass through verbatim — the adapter adds no
5
+ * namespace prefix and performs no key transformation; consumers that want
6
+ * namespacing compose their own keys. Rejections from the underlying SDK
7
+ * propagate to the caller so storage failures stay observable.
8
+ */
9
+ export interface StorageLike {
10
+ getItem: ((key: string) => Promise<string | null>) | undefined;
11
+ setItem: ((key: string, value: string) => Promise<void>) | undefined;
12
+ removeItem: ((key: string) => Promise<void>) | undefined;
13
+ }
14
+ export interface StoragePlatformSdk {
15
+ Storage?: StorageLike;
16
+ }
17
+ export type StoragePlatformLoader = () => Promise<{
18
+ available: true;
19
+ module: StoragePlatformSdk;
20
+ } | {
21
+ available: false;
22
+ reason: string;
23
+ }>;
24
+ /** Requires the full get/set/remove surface up front: storage is all-or-nothing. */
25
+ export declare function createSdkStorageFromPlatform(platform: StoragePlatformSdk): SdkStorage;
26
+ //# sourceMappingURL=platform-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-contract.d.ts","sourceRoot":"","sources":["../../src/storage/platform-contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAExD;;;;;;GAMG;AAEH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IAC/D,OAAO,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IACrE,UAAU,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;CAC1D;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAED,MAAM,MAAM,qBAAqB,GAAG,MAAM,OAAO,CAC/C;IAAE,SAAS,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,GAAG;IAAE,SAAS,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CACvF,CAAC;AAEF,oFAAoF;AACpF,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,kBAAkB,GAAG,UAAU,CAerF"}
@@ -0,0 +1,16 @@
1
+ import { SdkError } from "../index.js";
2
+ /** Requires the full get/set/remove surface up front: storage is all-or-nothing. */
3
+ export function createSdkStorageFromPlatform(platform) {
4
+ const storage = platform.Storage;
5
+ if (!storage ||
6
+ typeof storage.getItem !== "function" ||
7
+ typeof storage.setItem !== "function" ||
8
+ typeof storage.removeItem !== "function") {
9
+ throw new SdkError("UNSUPPORTED", "the installed SDK does not expose the Storage get/set/remove APIs");
10
+ }
11
+ return {
12
+ get: (key) => platform.Storage.getItem(key),
13
+ set: (key, value) => platform.Storage.setItem(key, value),
14
+ remove: (key) => platform.Storage.removeItem(key)
15
+ };
16
+ }
@@ -0,0 +1,9 @@
1
+ import type { IapPlatformLoader } from "../iap/platform-contract.js";
2
+ /**
3
+ * Default lazy loader for the official web SDK: imports
4
+ * `@apps-in-toss/web-framework` (an optional peer) only when an IAP
5
+ * operation needs it. Failed imports are never cached, so a later call
6
+ * retries; successful loads are cached.
7
+ */
8
+ export declare function createDefaultWebFrameworkLoader(): IapPlatformLoader;
9
+ //# sourceMappingURL=framework-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framework-loader.d.ts","sourceRoot":"","sources":["../../src/web/framework-loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAGrE;;;;;GAKG;AACH,wBAAgB,+BAA+B,IAAI,iBAAiB,CAwBnE"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Default lazy loader for the official web SDK: imports
3
+ * `@apps-in-toss/web-framework` (an optional peer) only when an IAP
4
+ * operation needs it. Failed imports are never cached, so a later call
5
+ * retries; successful loads are cached.
6
+ */
7
+ export function createDefaultWebFrameworkLoader() {
8
+ let cached;
9
+ return async () => {
10
+ if (cached) {
11
+ return { available: true, module: cached };
12
+ }
13
+ try {
14
+ const framework = (await import("@apps-in-toss/web-framework"));
15
+ const iap = framework.IAP;
16
+ if (typeof iap !== "object" || iap === null) {
17
+ return {
18
+ available: false,
19
+ reason: "@apps-in-toss/web-framework does not expose an IAP domain"
20
+ };
21
+ }
22
+ // Per-operation capability is validated at each call site: an
23
+ // installed version may expose some IAP functions but not others.
24
+ cached = iap;
25
+ return { available: true, module: cached };
26
+ }
27
+ catch (error) {
28
+ const message = error instanceof Error ? error.message : String(error);
29
+ return { available: false, reason: `failed to import @apps-in-toss/web-framework: ${message}` };
30
+ }
31
+ };
32
+ }
@@ -0,0 +1,13 @@
1
+ import type { IapPlatformSdk } from "../iap/platform-contract.js";
2
+ /**
3
+ * Structural contract for the official `@apps-in-toss/web-framework` IAP
4
+ * domain, declared from the published documentation so /web consumers
5
+ * type-check without the official web SDK installed. It is intentionally
6
+ * independent of the /rn contract — neither entry requires the other
7
+ * platform's package, in JavaScript or in generated declarations.
8
+ */
9
+ export type WebIapModule = IapPlatformSdk;
10
+ export type WebIapFramework = {
11
+ IAP: WebIapModule;
12
+ };
13
+ //# sourceMappingURL=iap-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iap-contract.d.ts","sourceRoot":"","sources":["../../src/web/iap-contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GAAG,cAAc,CAAC;AAE1C,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,EAAE,YAAY,CAAC;CACnB,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,30 @@
1
+ import { type SdkAnonymousKey, type SdkLoginResult, type SdkStorage } from "../index.js";
2
+ import { type IdentityPlatformLoader, type IdentityPlatformSdk } from "../identity/platform-contract.js";
3
+ import { type StoragePlatformLoader, type StoragePlatformSdk } from "../storage/platform-contract.js";
4
+ export interface WebIdentityOptions {
5
+ /**
6
+ * Web framework injection: pass a module exposing TossAuth/User or a
7
+ * custom loader (tests, dev replacements). Defaults to the lazy
8
+ * `import("@apps-in-toss/web-framework")` loader. The default never
9
+ * guesses the environment or substitutes a fake login.
10
+ */
11
+ framework?: IdentityPlatformSdk | IdentityPlatformLoader;
12
+ }
13
+ export interface WebIdentity {
14
+ /** Starts the platform login and validates/preserves the result. */
15
+ login(): Promise<SdkLoginResult>;
16
+ /** Looks up the SDK-issued anonymous key; never fabricates one. */
17
+ getAnonymousKey(): Promise<SdkAnonymousKey>;
18
+ }
19
+ export declare function createWebIdentity(options?: WebIdentityOptions): WebIdentity;
20
+ export interface WebStorageOptions {
21
+ /**
22
+ * Web framework injection: pass a module exposing Storage or a custom
23
+ * loader. Defaults to the lazy `import("@apps-in-toss/web-framework")`
24
+ * loader.
25
+ */
26
+ framework?: StoragePlatformSdk | StoragePlatformLoader;
27
+ }
28
+ /** SDK-backed storage for web with the same verbatim-key contract as /rn. */
29
+ export declare function createWebStorage(options?: WebStorageOptions): SdkStorage;
30
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/web/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AACnG,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EAGzB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACxB,MAAM,iCAAiC,CAAC;AAEzC,MAAM,WAAW,kBAAkB;IACjC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,mBAAmB,GAAG,sBAAsB,CAAC;CAC1D;AAED,MAAM,WAAW,WAAW;IAC1B,oEAAoE;IACpE,KAAK,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC;IACjC,mEAAmE;IACnE,eAAe,IAAI,OAAO,CAAC,eAAe,CAAC,CAAC;CAC7C;AAED,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,kBAAuB,GAAG,WAAW,CAa/E;AAED,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,SAAS,CAAC,EAAE,kBAAkB,GAAG,qBAAqB,CAAC;CACxD;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,UAAU,CA8B5E"}
@@ -0,0 +1,87 @@
1
+ import { SdkError } from "../index.js";
2
+ import { runSdkGetAnonymousKey, runSdkLogin } from "../identity/platform-contract.js";
3
+ import { createSdkStorageFromPlatform } from "../storage/platform-contract.js";
4
+ export function createWebIdentity(options = {}) {
5
+ const loader = normalizeWebIdentityLoader(options.framework);
6
+ const load = async () => {
7
+ const result = await loader();
8
+ if (!result.available) {
9
+ throw new SdkError("SDK_UNAVAILABLE", result.reason);
10
+ }
11
+ return result.module;
12
+ };
13
+ return {
14
+ login: async () => runSdkLogin(await load()),
15
+ getAnonymousKey: async () => runSdkGetAnonymousKey(await load())
16
+ };
17
+ }
18
+ /** SDK-backed storage for web with the same verbatim-key contract as /rn. */
19
+ export function createWebStorage(options = {}) {
20
+ const loader = normalizeWebStorageLoader(options.framework);
21
+ let cached;
22
+ let resolving;
23
+ const resolve = () => {
24
+ if (cached) {
25
+ return Promise.resolve(cached);
26
+ }
27
+ // Concurrent initial calls share one loader invocation so custom
28
+ // loaders cannot hand out independent stores.
29
+ if (!resolving) {
30
+ resolving = (async () => {
31
+ const result = await loader();
32
+ if (!result.available) {
33
+ throw new SdkError("SDK_UNAVAILABLE", result.reason);
34
+ }
35
+ cached = createSdkStorageFromPlatform(result.module);
36
+ return cached;
37
+ })();
38
+ resolving.catch(() => {
39
+ resolving = undefined;
40
+ });
41
+ }
42
+ return resolving;
43
+ };
44
+ return {
45
+ get: async (key) => (await resolve()).get(key),
46
+ set: async (key, value) => (await resolve()).set(key, value),
47
+ remove: async (key) => (await resolve()).remove(key)
48
+ };
49
+ }
50
+ function normalizeWebIdentityLoader(framework) {
51
+ if (!framework) {
52
+ return createDefaultWebLoader();
53
+ }
54
+ if (typeof framework === "function") {
55
+ return framework;
56
+ }
57
+ return async () => ({ available: true, module: framework });
58
+ }
59
+ function normalizeWebStorageLoader(framework) {
60
+ if (!framework) {
61
+ return createDefaultWebLoader();
62
+ }
63
+ if (typeof framework === "function") {
64
+ return framework;
65
+ }
66
+ return async () => ({ available: true, module: framework });
67
+ }
68
+ function createDefaultWebLoader() {
69
+ let cached;
70
+ return async () => {
71
+ if (cached) {
72
+ return { available: true, module: cached };
73
+ }
74
+ try {
75
+ const framework = (await import("@apps-in-toss/web-framework"));
76
+ cached = framework;
77
+ return { available: true, module: cached };
78
+ }
79
+ catch (error) {
80
+ const message = error instanceof Error ? error.message : String(error);
81
+ return {
82
+ available: false,
83
+ reason: `failed to import @apps-in-toss/web-framework: ${message}`
84
+ };
85
+ }
86
+ };
87
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Web adapters for `@ait-kit/sdk`.
3
+ *
4
+ * Requires the official `@apps-in-toss/web-framework` package (declared as
5
+ * an optional peer): it is imported lazily at first use, so this entry
6
+ * never requires the React Native SDK, and the React Native entry never
7
+ * requires this one.
8
+ *
9
+ * ```ts
10
+ * import { createWebIap } from "@ait-kit/sdk/web";
11
+ *
12
+ * const iap = createWebIap({
13
+ * // Resolve only after YOUR server verified the order and persisted the
14
+ * // grant (see the ait-kit server packages for verification flows).
15
+ * grant: async ({ orderId, sku }) => {
16
+ * const response = await fetch("/api/iap/grant", {
17
+ * method: "POST",
18
+ * body: JSON.stringify({ orderId, sku })
19
+ * });
20
+ * if (!response.ok) {
21
+ * // Resolve-only-on-success is part of the contract: never report a
22
+ * // grant your server did not verify and persist.
23
+ * throw new Error(`grant request failed: HTTP ${response.status}`);
24
+ * }
25
+ * }
26
+ * });
27
+ * const result = await iap.purchaseOneTime("SKU_100_COINS");
28
+ * ```
29
+ */
30
+ import { type IapAdapterOptions, type IapRecoveryResult } from "../iap/adapter.js";
31
+ import type { IapPlatformLoader, PartialIapPlatformSdk } from "../iap/platform-contract.js";
32
+ import type { WebIapFramework } from "./iap-contract.js";
33
+ export interface WebIapOptions extends Omit<IapAdapterOptions, "loader"> {
34
+ /**
35
+ * Web framework injection: pass an `IAP` module instance or a custom
36
+ * loader (tests/consumers). Defaults to the lazy
37
+ * `import("@apps-in-toss/web-framework")` loader.
38
+ */
39
+ framework?: WebIapFramework["IAP"] | PartialIapPlatformSdk | IapPlatformLoader;
40
+ }
41
+ export type WebIap = ReturnType<typeof createWebIap>;
42
+ export type { IapRecoveryResult };
43
+ export { createWebIdentity, type WebIdentity, type WebIdentityOptions } from "./identity.js";
44
+ export { createWebStorage, type WebStorageOptions } from "./identity.js";
45
+ export { createWebNotification, createWebShare, type WebNotification, type WebNotificationOptions, type WebShare, type WebShareOptions } from "./notify-share.js";
46
+ export declare function createWebIap(options: WebIapOptions): import("../iap/adapter.js").IapAdapter;
47
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/web/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EAAoB,KAAK,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACrG,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAE5F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IACtE;;;;OAIG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC,KAAK,CAAC,GAAG,qBAAqB,GAAG,iBAAiB,CAAC;CAChF;AAED,MAAM,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACrD,YAAY,EAAE,iBAAiB,EAAE,CAAC;AAElC,OAAO,EACL,iBAAiB,EACjB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACxB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGzE,OAAO,EACL,qBAAqB,EACrB,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,QAAQ,EACb,KAAK,eAAe,EACrB,MAAM,mBAAmB,CAAC;AAE3B,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,0CAOlD"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Web adapters for `@ait-kit/sdk`.
3
+ *
4
+ * Requires the official `@apps-in-toss/web-framework` package (declared as
5
+ * an optional peer): it is imported lazily at first use, so this entry
6
+ * never requires the React Native SDK, and the React Native entry never
7
+ * requires this one.
8
+ *
9
+ * ```ts
10
+ * import { createWebIap } from "@ait-kit/sdk/web";
11
+ *
12
+ * const iap = createWebIap({
13
+ * // Resolve only after YOUR server verified the order and persisted the
14
+ * // grant (see the ait-kit server packages for verification flows).
15
+ * grant: async ({ orderId, sku }) => {
16
+ * const response = await fetch("/api/iap/grant", {
17
+ * method: "POST",
18
+ * body: JSON.stringify({ orderId, sku })
19
+ * });
20
+ * if (!response.ok) {
21
+ * // Resolve-only-on-success is part of the contract: never report a
22
+ * // grant your server did not verify and persist.
23
+ * throw new Error(`grant request failed: HTTP ${response.status}`);
24
+ * }
25
+ * }
26
+ * });
27
+ * const result = await iap.purchaseOneTime("SKU_100_COINS");
28
+ * ```
29
+ */
30
+ import { createIapAdapter } from "../iap/adapter.js";
31
+ import { createDefaultWebFrameworkLoader } from "./framework-loader.js";
32
+ export { createWebIdentity } from "./identity.js";
33
+ export { createWebStorage } from "./identity.js";
34
+ // createWebStorage lives in identity.ts alongside the shared web loader helpers.
35
+ export { createWebNotification, createWebShare } from "./notify-share.js";
36
+ export function createWebIap(options) {
37
+ const loader = !options.framework
38
+ ? createDefaultWebFrameworkLoader()
39
+ : typeof options.framework === "function"
40
+ ? options.framework
41
+ : async () => ({ available: true, module: options.framework });
42
+ return createIapAdapter({ ...options, loader });
43
+ }
@@ -0,0 +1,37 @@
1
+ import { type SdkNotificationAgreementResult, type SdkShareUiResult } from "../index.js";
2
+ import { type NotificationPlatformLoader, type NotificationPlatformSdk } from "../notification/platform-contract.js";
3
+ import { type SharePlatformLoader, type SharePlatformSdk } from "../share/platform-contract.js";
4
+ export interface WebNotificationOptions {
5
+ /**
6
+ * Web framework injection: pass a module exposing Notification or a
7
+ * custom loader. Defaults to the lazy `import("@apps-in-toss/web-framework")`
8
+ * loader.
9
+ */
10
+ framework?: NotificationPlatformSdk | NotificationPlatformLoader;
11
+ /** Overall deadline per agreement request (default 60000ms; 0 disables). */
12
+ timeoutMs?: number;
13
+ }
14
+ export interface WebNotification {
15
+ /** See ReactNativeNotification.requestAgreement for the contract. */
16
+ requestAgreement(templateCode: string): Promise<SdkNotificationAgreementResult>;
17
+ }
18
+ export declare function createWebNotification(options?: WebNotificationOptions): WebNotification;
19
+ export interface WebShareOptions {
20
+ /**
21
+ * Web framework injection: pass a module exposing Share or a custom
22
+ * loader. Defaults to the lazy `import("@apps-in-toss/web-framework")`
23
+ * loader.
24
+ */
25
+ framework?: SharePlatformSdk | SharePlatformLoader;
26
+ }
27
+ export interface WebShare {
28
+ /** Creates a share link for an `intoss://` deeplink path. */
29
+ createLink(path: string, ogImageUrl?: string): Promise<string>;
30
+ /**
31
+ * Opens the native share sheet; `closed` never proves the user shared and
32
+ * never grants reward eligibility.
33
+ */
34
+ sendMessage(message: string): Promise<SdkShareUiResult>;
35
+ }
36
+ export declare function createWebShare(options?: WebShareOptions): WebShare;
37
+ //# sourceMappingURL=notify-share.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,154 @@
1
+ import { SdkError } from "../index.js";
2
+ import { runRequestAgreement } from "../notification/platform-contract.js";
3
+ import { runShareUi, validateSharePath } from "../share/platform-contract.js";
4
+ const DEFAULT_AGREEMENT_TIMEOUT_MS = 60_000;
5
+ export function createWebNotification(options = {}) {
6
+ const loader = normalizeWebNotificationLoader(options.framework);
7
+ const timeoutMs = options.timeoutMs ?? DEFAULT_AGREEMENT_TIMEOUT_MS;
8
+ return {
9
+ requestAgreement(templateCode) {
10
+ if (typeof templateCode !== "string" || !templateCode.trim()) {
11
+ return Promise.reject(new SdkError("UNSUPPORTED", "templateCode must be a non-empty string"));
12
+ }
13
+ return agreementWithLoaderDeadline(loader, templateCode, timeoutMs);
14
+ }
15
+ };
16
+ }
17
+ export function createWebShare(options = {}) {
18
+ const loader = normalizeWebShareLoader(options.framework);
19
+ const load = async () => {
20
+ const result = await loader();
21
+ if (!result.available) {
22
+ throw new SdkError("SDK_UNAVAILABLE", result.reason);
23
+ }
24
+ return result.module;
25
+ };
26
+ return {
27
+ async createLink(path, ogImageUrl) {
28
+ const validated = validateSharePath(path);
29
+ const platform = await load();
30
+ const createLink = platform.Share?.createLink;
31
+ if (typeof createLink !== "function") {
32
+ throw new SdkError("UNSUPPORTED", "the installed SDK does not expose Share.createLink");
33
+ }
34
+ if (typeof createLink.isSupported === "function" && !createLink.isSupported()) {
35
+ throw new SdkError("UNSUPPORTED", "share links are not supported on this app version");
36
+ }
37
+ return platform.Share.createLink(ogImageUrl !== undefined ? { path: validated, ogImageUrl } : { path: validated });
38
+ },
39
+ async sendMessage(message) {
40
+ if (typeof message !== "string" || !message) {
41
+ throw new SdkError("UNSUPPORTED", "message must be a non-empty string");
42
+ }
43
+ const platform = await load();
44
+ const sendMessage = platform.Share?.sendMessage;
45
+ if (typeof sendMessage !== "function") {
46
+ throw new SdkError("UNSUPPORTED", "the installed SDK does not expose Share.sendMessage");
47
+ }
48
+ if (typeof sendMessage.isSupported === "function" && !sendMessage.isSupported()) {
49
+ throw new SdkError("UNSUPPORTED", "the share sheet is not supported on this app version");
50
+ }
51
+ return runShareUi(platform, message);
52
+ }
53
+ };
54
+ }
55
+ function normalizeWebNotificationLoader(framework) {
56
+ if (!framework) {
57
+ return createDefaultWebModuleLoader();
58
+ }
59
+ if (typeof framework === "function") {
60
+ return framework;
61
+ }
62
+ return async () => ({ available: true, module: framework });
63
+ }
64
+ function normalizeWebShareLoader(framework) {
65
+ if (!framework) {
66
+ return createDefaultWebModuleLoader();
67
+ }
68
+ if (typeof framework === "function") {
69
+ return framework;
70
+ }
71
+ return async () => ({ available: true, module: framework });
72
+ }
73
+ function createDefaultWebModuleLoader() {
74
+ let cached;
75
+ return async () => {
76
+ if (cached) {
77
+ return { available: true, module: cached };
78
+ }
79
+ try {
80
+ const framework = (await import("@apps-in-toss/web-framework"));
81
+ cached = framework;
82
+ return { available: true, module: cached };
83
+ }
84
+ catch (error) {
85
+ const message = error instanceof Error ? error.message : String(error);
86
+ return {
87
+ available: false,
88
+ reason: `failed to import @apps-in-toss/web-framework: ${message}`
89
+ };
90
+ }
91
+ };
92
+ }
93
+ /**
94
+ * Same loader-covering deadline as the React Native adapter; see
95
+ * agreementWithLoaderDeadline there for the contract.
96
+ */
97
+ async function agreementWithLoaderDeadline(loader, templateCode, timeoutMs) {
98
+ const timedOut = () => ({
99
+ status: "timeout",
100
+ templateCode,
101
+ reason: `agreement request timed out after ${timeoutMs}ms; the user may still act — resolve the state server-side before retrying`
102
+ });
103
+ if (!(timeoutMs > 0)) {
104
+ return runRequestAgreement(await loadNotificationPlatform(loader), templateCode, 0);
105
+ }
106
+ const startedAt = Date.now();
107
+ let cancelled = false;
108
+ let timer;
109
+ const loadDeadline = new Promise((resolve) => {
110
+ timer = setTimeout(() => {
111
+ cancelled = true;
112
+ resolve(null);
113
+ }, timeoutMs);
114
+ });
115
+ let platform;
116
+ try {
117
+ platform = await Promise.race([
118
+ loadNotificationPlatform(loader).then((loaded) => (cancelled ? null : loaded)),
119
+ loadDeadline
120
+ ]);
121
+ }
122
+ finally {
123
+ if (timer !== undefined)
124
+ clearTimeout(timer);
125
+ }
126
+ if (!platform || cancelled || Date.now() - startedAt >= timeoutMs) {
127
+ return timedOut();
128
+ }
129
+ const remainingMs = Math.max(1, timeoutMs - (Date.now() - startedAt));
130
+ // The public reason reports the CONFIGURED deadline, not the remainder
131
+ // left after loading; the remainder still bounds the actual flow.
132
+ const flow = runRequestAgreement(platform, templateCode, remainingMs);
133
+ const configured = timeoutMs;
134
+ return flow.then((result) => result.status === "timeout"
135
+ ? {
136
+ ...result,
137
+ reason: `agreement request timed out after ${configured}ms; the user may still act — resolve the state server-side before retrying`
138
+ }
139
+ : result);
140
+ }
141
+ async function loadNotificationPlatform(loader) {
142
+ const result = await loader();
143
+ if (!result.available) {
144
+ throw new SdkError("SDK_UNAVAILABLE", result.reason);
145
+ }
146
+ const request = result.module.Notification?.requestAgreement;
147
+ if (typeof request !== "function") {
148
+ throw new SdkError("UNSUPPORTED", "the installed SDK does not expose Notification.requestAgreement");
149
+ }
150
+ if (typeof request.isSupported === "function" && !request.isSupported()) {
151
+ throw new SdkError("UNSUPPORTED", "notification agreements are not supported on this app version");
152
+ }
153
+ return result.module;
154
+ }
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@ait-kit/sdk",
3
+ "version": "0.2.0",
4
+ "description": "Frontend SDK adapters for Apps in Toss mini apps: shared contracts plus per-runtime entry points.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/imjlk/ait-kit.git",
10
+ "directory": "packages/sdk"
11
+ },
12
+ "homepage": "https://github.com/imjlk/ait-kit#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/imjlk/ait-kit/issues"
15
+ },
16
+ "keywords": [
17
+ "apps-in-toss",
18
+ "toss",
19
+ "sdk",
20
+ "react-native",
21
+ "ads",
22
+ "iap"
23
+ ],
24
+ "sideEffects": [
25
+ "./src/rn/**"
26
+ ],
27
+ "types": "./dist/index.d.ts",
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/index.d.ts",
31
+ "import": "./dist/index.js"
32
+ },
33
+ "./rn": {
34
+ "types": "./dist/rn/index.d.ts",
35
+ "import": "./dist/rn/index.js"
36
+ },
37
+ "./web": {
38
+ "types": "./dist/web/index.d.ts",
39
+ "import": "./dist/web/index.js"
40
+ }
41
+ },
42
+ "files": [
43
+ "dist"
44
+ ],
45
+ "scripts": {
46
+ "typecheck": "tsc -p tsconfig.json",
47
+ "build": "rm -rf dist && tsc -p tsconfig.build.json",
48
+ "test": "bun test test",
49
+ "prepack": "bun run build"
50
+ },
51
+ "peerDependencies": {
52
+ "@apps-in-toss/framework": "*",
53
+ "@apps-in-toss/web-framework": "*"
54
+ },
55
+ "peerDependenciesMeta": {
56
+ "@apps-in-toss/framework": {
57
+ "optional": true
58
+ },
59
+ "@apps-in-toss/web-framework": {
60
+ "optional": true
61
+ }
62
+ },
63
+ "publishConfig": {
64
+ "access": "public"
65
+ }
66
+ }