@ticketlayer/live 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.
- package/LICENSE +21 -0
- package/README.md +198 -0
- package/dist/auto.d.ts +31 -0
- package/dist/auto.d.ts.map +1 -0
- package/dist/auto.js +78 -0
- package/dist/auto.js.map +1 -0
- package/dist/client.d.ts +538 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +495 -0
- package/dist/client.js.map +1 -0
- package/dist/clientHeader.d.ts +4 -0
- package/dist/clientHeader.d.ts.map +1 -0
- package/dist/clientHeader.js +25 -0
- package/dist/clientHeader.js.map +1 -0
- package/dist/core/liveClient.d.ts +176 -0
- package/dist/core/liveClient.d.ts.map +1 -0
- package/dist/core/liveClient.js +372 -0
- package/dist/core/liveClient.js.map +1 -0
- package/dist/createLiveClient.d.ts +49 -0
- package/dist/createLiveClient.d.ts.map +1 -0
- package/dist/createLiveClient.js +91 -0
- package/dist/createLiveClient.js.map +1 -0
- package/dist/elements.d.ts +88 -0
- package/dist/elements.d.ts.map +1 -0
- package/dist/elements.js +165 -0
- package/dist/elements.js.map +1 -0
- package/dist/generated/types.d.ts +6110 -0
- package/dist/generated/types.d.ts.map +1 -0
- package/dist/generated/types.js +6 -0
- package/dist/generated/types.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/native/asyncStorageStorage.d.ts +24 -0
- package/dist/native/asyncStorageStorage.d.ts.map +1 -0
- package/dist/native/asyncStorageStorage.js +24 -0
- package/dist/native/asyncStorageStorage.js.map +1 -0
- package/dist/native/checkoutUrl.d.ts +85 -0
- package/dist/native/checkoutUrl.d.ts.map +1 -0
- package/dist/native/checkoutUrl.js +147 -0
- package/dist/native/checkoutUrl.js.map +1 -0
- package/dist/native/index.d.ts +119 -0
- package/dist/native/index.d.ts.map +1 -0
- package/dist/native/index.js +145 -0
- package/dist/native/index.js.map +1 -0
- package/dist/native/secureStoreStorage.d.ts +33 -0
- package/dist/native/secureStoreStorage.d.ts.map +1 -0
- package/dist/native/secureStoreStorage.js +39 -0
- package/dist/native/secureStoreStorage.js.map +1 -0
- package/dist/native/storage.d.ts +29 -0
- package/dist/native/storage.d.ts.map +1 -0
- package/dist/native/storage.js +24 -0
- package/dist/native/storage.js.map +1 -0
- package/dist/server.d.ts +95 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +188 -0
- package/dist/server.js.map +1 -0
- package/dist/state/buyModal.d.ts +24 -0
- package/dist/state/buyModal.d.ts.map +1 -0
- package/dist/state/buyModal.js +56 -0
- package/dist/state/buyModal.js.map +1 -0
- package/dist/state/checkoutModal.d.ts +26 -0
- package/dist/state/checkoutModal.d.ts.map +1 -0
- package/dist/state/checkoutModal.js +126 -0
- package/dist/state/checkoutModal.js.map +1 -0
- package/dist/state/emitter.d.ts +21 -0
- package/dist/state/emitter.d.ts.map +1 -0
- package/dist/state/emitter.js +26 -0
- package/dist/state/emitter.js.map +1 -0
- package/dist/state/loadElements.d.ts +8 -0
- package/dist/state/loadElements.d.ts.map +1 -0
- package/dist/state/loadElements.js +39 -0
- package/dist/state/loadElements.js.map +1 -0
- package/dist/state/registry.d.ts +39 -0
- package/dist/state/registry.d.ts.map +1 -0
- package/dist/state/registry.js +65 -0
- package/dist/state/registry.js.map +1 -0
- package/dist/state/theme.d.ts +20 -0
- package/dist/state/theme.d.ts.map +1 -0
- package/dist/state/theme.js +47 -0
- package/dist/state/theme.js.map +1 -0
- package/dist/ticketlayer.js +5 -0
- package/dist/ticketlayer.js.map +7 -0
- package/dist/version.d.ts +7 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +7 -0
- package/dist/version.js.map +1 -0
- package/package.json +80 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hosted checkout for a WebView - the pure parts.
|
|
3
|
+
*
|
|
4
|
+
* A native app cannot take card details itself; it opens the hosted checkout
|
|
5
|
+
* (`/embed/checkout` on the checkout host) in a WebView, handing over the Live
|
|
6
|
+
* session token so the page sees the same cart, and gets the result back two
|
|
7
|
+
* ways: `tl:*` messages through `window.ReactNativeWebView.postMessage`, and a
|
|
8
|
+
* `return_url` deep link the page navigates to on success with `order` and
|
|
9
|
+
* `reference` appended. Both are specified in
|
|
10
|
+
* live-hostedboxoffice/docs/embed-checkout-contract.md (protocol version 1).
|
|
11
|
+
* Nothing here touches the network or the DOM.
|
|
12
|
+
*/
|
|
13
|
+
export const CHECKOUT_PROTOCOL_VERSION = 1;
|
|
14
|
+
/**
|
|
15
|
+
* The URL to load in the WebView:
|
|
16
|
+
* `${checkoutBaseUrl}/embed/checkout?session=...&return_url=...`.
|
|
17
|
+
* No `parent_origin`: the page detects the native bridge and ignores it.
|
|
18
|
+
*/
|
|
19
|
+
export function buildCheckoutUrl(input) {
|
|
20
|
+
const base = input.checkoutBaseUrl.replace(/\/+$/, '');
|
|
21
|
+
if (!/^https?:\/\//i.test(base)) {
|
|
22
|
+
throw new Error(`buildCheckoutUrl: checkoutBaseUrl must be an http(s) URL, got "${input.checkoutBaseUrl}"`);
|
|
23
|
+
}
|
|
24
|
+
if (!input.sessionToken) {
|
|
25
|
+
throw new Error('buildCheckoutUrl: sessionToken is required');
|
|
26
|
+
}
|
|
27
|
+
let query = `session=${encodeURIComponent(input.sessionToken)}`;
|
|
28
|
+
if (input.returnUrl) {
|
|
29
|
+
validateReturnUrl(input.returnUrl);
|
|
30
|
+
query += `&return_url=${encodeURIComponent(input.returnUrl)}`;
|
|
31
|
+
}
|
|
32
|
+
return `${base}/embed/checkout?${query}`;
|
|
33
|
+
}
|
|
34
|
+
const BLOCKED_SCHEMES = /^(javascript|data|vbscript|file|blob|about):/i;
|
|
35
|
+
function validateReturnUrl(url) {
|
|
36
|
+
if (!/^[a-z][a-z0-9+.-]*:/i.test(url)) {
|
|
37
|
+
throw new Error(`buildCheckoutUrl: returnUrl must be absolute (a scheme or https origin), got "${url}"`);
|
|
38
|
+
}
|
|
39
|
+
if (BLOCKED_SCHEMES.test(url)) {
|
|
40
|
+
throw new Error(`buildCheckoutUrl: returnUrl scheme is not allowed: "${url}"`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Strip query and fragment. */
|
|
44
|
+
function withoutQuery(url) {
|
|
45
|
+
return url.split('#')[0].split('?')[0];
|
|
46
|
+
}
|
|
47
|
+
/** Parse the query string by hand: React Native's URL is not WHATWG complete. */
|
|
48
|
+
function queryOf(url) {
|
|
49
|
+
const hashless = url.split('#')[0];
|
|
50
|
+
const q = hashless.indexOf('?');
|
|
51
|
+
const out = {};
|
|
52
|
+
if (q === -1)
|
|
53
|
+
return out;
|
|
54
|
+
for (const pair of hashless.slice(q + 1).split('&')) {
|
|
55
|
+
if (!pair)
|
|
56
|
+
continue;
|
|
57
|
+
const eq = pair.indexOf('=');
|
|
58
|
+
const rawKey = eq === -1 ? pair : pair.slice(0, eq);
|
|
59
|
+
const rawValue = eq === -1 ? '' : pair.slice(eq + 1);
|
|
60
|
+
try {
|
|
61
|
+
out[decodeURIComponent(rawKey.replace(/\+/g, ' '))] = decodeURIComponent(rawValue.replace(/\+/g, ' '));
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// Malformed percent-encoding: skip the pair rather than throw in a deep-link handler.
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Read the completed order off a `return_url` deep link
|
|
71
|
+
* (`rowbot://tickets/complete?order=ord_123&reference=TL-1001`). Returns null
|
|
72
|
+
* for anything that is not a checkout return (no `order` parameter, or a
|
|
73
|
+
* different path than `opts.returnUrl`). The order access token is never on
|
|
74
|
+
* the URL; it only arrives in the `tl:complete` message.
|
|
75
|
+
*/
|
|
76
|
+
export function parseCheckoutReturn(url, opts = {}) {
|
|
77
|
+
if (typeof url !== 'string' || url.length === 0)
|
|
78
|
+
return null;
|
|
79
|
+
if (opts.returnUrl) {
|
|
80
|
+
const expected = withoutQuery(opts.returnUrl).replace(/\/+$/, '');
|
|
81
|
+
const actual = withoutQuery(url).replace(/\/+$/, '');
|
|
82
|
+
if (actual !== expected)
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
const params = queryOf(url);
|
|
86
|
+
const orderId = params.order;
|
|
87
|
+
if (!orderId)
|
|
88
|
+
return null;
|
|
89
|
+
return { orderId, orderReference: params.reference || null };
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Parse `event.nativeEvent.data` from react-native-webview's `onMessage`.
|
|
93
|
+
* Returns null for anything that is not a v1 checkout message so the handler
|
|
94
|
+
* can share the WebView with other pages.
|
|
95
|
+
*/
|
|
96
|
+
export function parseCheckoutMessage(data) {
|
|
97
|
+
let value = data;
|
|
98
|
+
if (typeof value === 'string') {
|
|
99
|
+
try {
|
|
100
|
+
value = JSON.parse(value);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (!value || typeof value !== 'object')
|
|
107
|
+
return null;
|
|
108
|
+
const m = value;
|
|
109
|
+
if (m.version !== CHECKOUT_PROTOCOL_VERSION || typeof m.type !== 'string')
|
|
110
|
+
return null;
|
|
111
|
+
switch (m.type) {
|
|
112
|
+
case 'tl:ready':
|
|
113
|
+
return { type: 'tl:ready', version: 1 };
|
|
114
|
+
case 'tl:close':
|
|
115
|
+
case 'tl:cancel':
|
|
116
|
+
return { type: 'tl:close', version: 1 };
|
|
117
|
+
case 'tl:height':
|
|
118
|
+
return typeof m.height === 'number' && Number.isFinite(m.height)
|
|
119
|
+
? { type: 'tl:height', version: 1, height: m.height }
|
|
120
|
+
: null;
|
|
121
|
+
case 'tl:complete': {
|
|
122
|
+
const order = (m.order ?? null);
|
|
123
|
+
const orderId = typeof m.orderId === 'string' ? m.orderId : typeof order?.id === 'string' ? order.id : null;
|
|
124
|
+
if (!orderId)
|
|
125
|
+
return null;
|
|
126
|
+
const orderReference = typeof m.orderReference === 'string'
|
|
127
|
+
? m.orderReference
|
|
128
|
+
: typeof order?.orderNumber === 'string'
|
|
129
|
+
? order.orderNumber
|
|
130
|
+
: '';
|
|
131
|
+
return {
|
|
132
|
+
type: 'tl:complete',
|
|
133
|
+
version: 1,
|
|
134
|
+
orderId,
|
|
135
|
+
orderReference,
|
|
136
|
+
...(typeof m.accessToken === 'string' ? { accessToken: m.accessToken } : {}),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
case 'tl:error':
|
|
140
|
+
return typeof m.code === 'string' && typeof m.message === 'string'
|
|
141
|
+
? { type: 'tl:error', version: 1, code: m.code, message: m.message }
|
|
142
|
+
: null;
|
|
143
|
+
default:
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=checkoutUrl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkoutUrl.js","sourceRoot":"","sources":["../../src/native/checkoutUrl.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ticketlayer/live/native - the buyer-facing client for React Native.
|
|
3
|
+
*
|
|
4
|
+
* The browser entry (`@ticketlayer/live`) resolves the channel from
|
|
5
|
+
* `window.location`, publishes itself on `window.Ticketlayer`, injects the
|
|
6
|
+
* theme into the document and mounts iframe modals. None of that exists in a
|
|
7
|
+
* native app, so this entry builds the same stateful facade
|
|
8
|
+
* ({@link TicketlayerLive}: events, cart, auth, orders, presale, queue, the
|
|
9
|
+
* event bus) with:
|
|
10
|
+
*
|
|
11
|
+
* - no DOM defaults: `apiUrl` and `checkoutBaseUrl` are required;
|
|
12
|
+
* - token transport only: the Live session id travels in the
|
|
13
|
+
* `X-Live-Session` header (the browser embed does the same) and is kept in
|
|
14
|
+
* an injectable async {@link NativeTokenStorage} (expo-secure-store or
|
|
15
|
+
* AsyncStorage adapters ship next to this file);
|
|
16
|
+
* - a resumed session on start when the storage already holds a token, so a
|
|
17
|
+
* cart or a magic-link sign-in survives an app restart;
|
|
18
|
+
* - hosted checkout helpers for a WebView: `buildCheckoutUrl({ returnUrl })`
|
|
19
|
+
* and `parseCheckoutReturn(url)` per
|
|
20
|
+
* live-hostedboxoffice/docs/embed-checkout-contract.md.
|
|
21
|
+
*
|
|
22
|
+
* Nothing here is imported by the browser entry or the CDN build.
|
|
23
|
+
*/
|
|
24
|
+
import { LiveClient, LiveAPIError, API_DATED_VERSION } from '../client.js';
|
|
25
|
+
import { TicketlayerLive } from '../core/liveClient.js';
|
|
26
|
+
import { type NativeTokenStorage } from './storage.js';
|
|
27
|
+
import { type CheckoutReturn, type ParseCheckoutReturnOptions } from './checkoutUrl.js';
|
|
28
|
+
export { LiveAPIError, API_DATED_VERSION };
|
|
29
|
+
export type { LiveEvent } from '../state/emitter.js';
|
|
30
|
+
export type { PresaleRedemption } from '../core/liveClient.js';
|
|
31
|
+
export { TicketlayerLive };
|
|
32
|
+
export { DEFAULT_TOKEN_KEY, memoryStorage, toLiveTokenStorage, type NativeTokenStorage, } from './storage.js';
|
|
33
|
+
export { secureStoreStorage, type SecureStoreLike, type SecureStoreStorageOptions } from './secureStoreStorage.js';
|
|
34
|
+
export { asyncStorageStorage, type AsyncStorageLike, type AsyncStorageStorageOptions } from './asyncStorageStorage.js';
|
|
35
|
+
export { CHECKOUT_PROTOCOL_VERSION, buildCheckoutUrl, parseCheckoutReturn, parseCheckoutMessage, type BuildCheckoutUrlInput, type CheckoutMessage, type CheckoutReturn, type ParseCheckoutReturnOptions, } from './checkoutUrl.js';
|
|
36
|
+
export interface NativeLiveClientOptions {
|
|
37
|
+
/** Base URL of the Live API, e.g. https://live-api.ticketlayer.com. Required: there is no page to default from. */
|
|
38
|
+
apiUrl: string;
|
|
39
|
+
/** The channel's publishable key (tlpk_...). Identifies the channel and authorises catalogue reads. */
|
|
40
|
+
publishableKey: string;
|
|
41
|
+
/** Origin of the hosted checkout (the HBO deployment serving /embed/checkout). Required. */
|
|
42
|
+
checkoutBaseUrl: string;
|
|
43
|
+
/**
|
|
44
|
+
* Where the Live session token lives between app launches. Use
|
|
45
|
+
* `secureStoreStorage(SecureStore)` on Expo or `asyncStorageStorage(AsyncStorage)`.
|
|
46
|
+
* Defaults to in-memory storage, which forgets the session on restart.
|
|
47
|
+
*/
|
|
48
|
+
tokenStorage?: NativeTokenStorage;
|
|
49
|
+
/**
|
|
50
|
+
* Resume the stored session on start (default true): `GET /session` with
|
|
51
|
+
* the stored token rehydrates the cart and sign-in state. A token the API
|
|
52
|
+
* rejects is removed from storage and the client starts lazily instead.
|
|
53
|
+
*/
|
|
54
|
+
resume?: boolean;
|
|
55
|
+
/** Override the dated API version sent as TL-Version. */
|
|
56
|
+
apiVersion?: string;
|
|
57
|
+
}
|
|
58
|
+
export interface NativeCheckoutUrlOptions {
|
|
59
|
+
/**
|
|
60
|
+
* Deep link the checkout navigates to on success, e.g. `rowbot://tickets/complete`.
|
|
61
|
+
* The checkout host must list its scheme on RETURN_URL_ALLOWLIST.
|
|
62
|
+
*/
|
|
63
|
+
returnUrl?: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The stateful Live facade plus what a native app needs around the hosted
|
|
67
|
+
* checkout and the persisted session. Everything on {@link TicketlayerLive}
|
|
68
|
+
* (`events`, `cart`, `auth`, `orders`, `presale`, `queue`, `on`/`off`/`emit`)
|
|
69
|
+
* works unchanged.
|
|
70
|
+
*/
|
|
71
|
+
export declare class NativeTicketlayerLive extends TicketlayerLive {
|
|
72
|
+
private readonly nativeStorage;
|
|
73
|
+
private readonly checkoutBaseUrl;
|
|
74
|
+
constructor(client: LiveClient, opts: {
|
|
75
|
+
publishableKey: string;
|
|
76
|
+
baseUrl: string;
|
|
77
|
+
}, native: {
|
|
78
|
+
storage: NativeTokenStorage;
|
|
79
|
+
checkoutBaseUrl: string;
|
|
80
|
+
});
|
|
81
|
+
/**
|
|
82
|
+
* The URL to open in a WebView to pay for the current cart. Creates the
|
|
83
|
+
* Live session if none exists yet (the cart already implies one) and hands
|
|
84
|
+
* its token to the hosted checkout, which resumes it and sees the same cart.
|
|
85
|
+
* Throws when there is no cart to pay for.
|
|
86
|
+
*/
|
|
87
|
+
buildCheckoutUrl(opts?: NativeCheckoutUrlOptions): Promise<string>;
|
|
88
|
+
/** Read the completed order off a `return_url` deep link; see {@link parseCheckoutReturn}. */
|
|
89
|
+
parseCheckoutReturn(url: string, opts?: ParseCheckoutReturnOptions): CheckoutReturn | null;
|
|
90
|
+
/**
|
|
91
|
+
* Tell the client the hosted checkout finished (from `tl:complete` or the
|
|
92
|
+
* return deep link): emits `checkout:completed` and re-reads the cart, which
|
|
93
|
+
* the checkout consumed, so `cart.current` and `cart:updated` subscribers
|
|
94
|
+
* see it empty.
|
|
95
|
+
*/
|
|
96
|
+
completeCheckout(order: CheckoutReturn | {
|
|
97
|
+
orderId: string;
|
|
98
|
+
orderReference?: string | null;
|
|
99
|
+
accessToken?: string;
|
|
100
|
+
}): Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* End the session and forget its token: the server session is ended, the
|
|
103
|
+
* stored token removed, and local cart and sign-in state cleared. The next
|
|
104
|
+
* cart mutation or sign-in mints a fresh session.
|
|
105
|
+
*/
|
|
106
|
+
signOut(): Promise<void>;
|
|
107
|
+
/** Forget a stored token the API rejected and go back to starting lazily. */
|
|
108
|
+
forgetSession(): Promise<void>;
|
|
109
|
+
/** The storage the session token is kept in (to clear it on app reset, for example). */
|
|
110
|
+
get tokenStorage(): NativeTokenStorage;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Create the Live client for a React Native app. Resolves once the stored
|
|
114
|
+
* session (if any) has been resumed; the returned client is ready to browse
|
|
115
|
+
* immediately and creates a session lazily on the first cart mutation or
|
|
116
|
+
* sign-in.
|
|
117
|
+
*/
|
|
118
|
+
export declare function createNativeLiveClient(options: NativeLiveClientOptions): Promise<NativeTicketlayerLive>;
|
|
119
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/native/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ticketlayer/live/native - the buyer-facing client for React Native.
|
|
3
|
+
*
|
|
4
|
+
* The browser entry (`@ticketlayer/live`) resolves the channel from
|
|
5
|
+
* `window.location`, publishes itself on `window.Ticketlayer`, injects the
|
|
6
|
+
* theme into the document and mounts iframe modals. None of that exists in a
|
|
7
|
+
* native app, so this entry builds the same stateful facade
|
|
8
|
+
* ({@link TicketlayerLive}: events, cart, auth, orders, presale, queue, the
|
|
9
|
+
* event bus) with:
|
|
10
|
+
*
|
|
11
|
+
* - no DOM defaults: `apiUrl` and `checkoutBaseUrl` are required;
|
|
12
|
+
* - token transport only: the Live session id travels in the
|
|
13
|
+
* `X-Live-Session` header (the browser embed does the same) and is kept in
|
|
14
|
+
* an injectable async {@link NativeTokenStorage} (expo-secure-store or
|
|
15
|
+
* AsyncStorage adapters ship next to this file);
|
|
16
|
+
* - a resumed session on start when the storage already holds a token, so a
|
|
17
|
+
* cart or a magic-link sign-in survives an app restart;
|
|
18
|
+
* - hosted checkout helpers for a WebView: `buildCheckoutUrl({ returnUrl })`
|
|
19
|
+
* and `parseCheckoutReturn(url)` per
|
|
20
|
+
* live-hostedboxoffice/docs/embed-checkout-contract.md.
|
|
21
|
+
*
|
|
22
|
+
* Nothing here is imported by the browser entry or the CDN build.
|
|
23
|
+
*/
|
|
24
|
+
import { LiveClient, LiveAPIError, API_DATED_VERSION } from '../client.js';
|
|
25
|
+
import { TicketlayerLive } from '../core/liveClient.js';
|
|
26
|
+
import { memoryStorage, toLiveTokenStorage } from './storage.js';
|
|
27
|
+
import { buildCheckoutUrl as buildCheckoutUrlPure, parseCheckoutReturn as parseCheckoutReturnPure, } from './checkoutUrl.js';
|
|
28
|
+
export { LiveAPIError, API_DATED_VERSION };
|
|
29
|
+
export { TicketlayerLive };
|
|
30
|
+
export { DEFAULT_TOKEN_KEY, memoryStorage, toLiveTokenStorage, } from './storage.js';
|
|
31
|
+
export { secureStoreStorage } from './secureStoreStorage.js';
|
|
32
|
+
export { asyncStorageStorage } from './asyncStorageStorage.js';
|
|
33
|
+
export { CHECKOUT_PROTOCOL_VERSION, buildCheckoutUrl, parseCheckoutReturn, parseCheckoutMessage, } from './checkoutUrl.js';
|
|
34
|
+
/**
|
|
35
|
+
* The stateful Live facade plus what a native app needs around the hosted
|
|
36
|
+
* checkout and the persisted session. Everything on {@link TicketlayerLive}
|
|
37
|
+
* (`events`, `cart`, `auth`, `orders`, `presale`, `queue`, `on`/`off`/`emit`)
|
|
38
|
+
* works unchanged.
|
|
39
|
+
*/
|
|
40
|
+
export class NativeTicketlayerLive extends TicketlayerLive {
|
|
41
|
+
constructor(client, opts, native) {
|
|
42
|
+
super(client, { sessionMode: 'token', publishableKey: opts.publishableKey, baseUrl: opts.baseUrl });
|
|
43
|
+
this.nativeStorage = native.storage;
|
|
44
|
+
this.checkoutBaseUrl = native.checkoutBaseUrl;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The URL to open in a WebView to pay for the current cart. Creates the
|
|
48
|
+
* Live session if none exists yet (the cart already implies one) and hands
|
|
49
|
+
* its token to the hosted checkout, which resumes it and sees the same cart.
|
|
50
|
+
* Throws when there is no cart to pay for.
|
|
51
|
+
*/
|
|
52
|
+
async buildCheckoutUrl(opts = {}) {
|
|
53
|
+
if (!this.cart.id) {
|
|
54
|
+
throw new LiveAPIError('No cart to check out. Add tickets first.', 'CART_EMPTY', 0);
|
|
55
|
+
}
|
|
56
|
+
await this.ensureSession();
|
|
57
|
+
const token = await this.getSessionToken();
|
|
58
|
+
if (!token) {
|
|
59
|
+
throw new LiveAPIError('No Live session token to hand to the checkout.', 'NO_SESSION', 0);
|
|
60
|
+
}
|
|
61
|
+
return buildCheckoutUrlPure({
|
|
62
|
+
checkoutBaseUrl: this.checkoutBaseUrl,
|
|
63
|
+
sessionToken: token,
|
|
64
|
+
...(opts.returnUrl ? { returnUrl: opts.returnUrl } : {}),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/** Read the completed order off a `return_url` deep link; see {@link parseCheckoutReturn}. */
|
|
68
|
+
parseCheckoutReturn(url, opts = {}) {
|
|
69
|
+
return parseCheckoutReturnPure(url, opts);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Tell the client the hosted checkout finished (from `tl:complete` or the
|
|
73
|
+
* return deep link): emits `checkout:completed` and re-reads the cart, which
|
|
74
|
+
* the checkout consumed, so `cart.current` and `cart:updated` subscribers
|
|
75
|
+
* see it empty.
|
|
76
|
+
*/
|
|
77
|
+
async completeCheckout(order) {
|
|
78
|
+
this.emit('checkout:completed', order);
|
|
79
|
+
await this.cart.refresh().catch(() => undefined);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* End the session and forget its token: the server session is ended, the
|
|
83
|
+
* stored token removed, and local cart and sign-in state cleared. The next
|
|
84
|
+
* cart mutation or sign-in mints a fresh session.
|
|
85
|
+
*/
|
|
86
|
+
async signOut() {
|
|
87
|
+
await this.auth.logout();
|
|
88
|
+
await this.nativeStorage.remove().catch(() => undefined);
|
|
89
|
+
this._resetSessionStarted();
|
|
90
|
+
}
|
|
91
|
+
/** Forget a stored token the API rejected and go back to starting lazily. */
|
|
92
|
+
async forgetSession() {
|
|
93
|
+
await this.nativeStorage.remove().catch(() => undefined);
|
|
94
|
+
this._resetSessionStarted();
|
|
95
|
+
}
|
|
96
|
+
/** The storage the session token is kept in (to clear it on app reset, for example). */
|
|
97
|
+
get tokenStorage() {
|
|
98
|
+
return this.nativeStorage;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function requireHttpUrl(name, value) {
|
|
102
|
+
if (typeof value !== 'string' || !/^https?:\/\/[^/\s]+/i.test(value)) {
|
|
103
|
+
throw new Error(`createNativeLiveClient: ${name} must be an absolute http(s) URL (there is no window.location to default from)`);
|
|
104
|
+
}
|
|
105
|
+
return value.replace(/\/+$/, '');
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Create the Live client for a React Native app. Resolves once the stored
|
|
109
|
+
* session (if any) has been resumed; the returned client is ready to browse
|
|
110
|
+
* immediately and creates a session lazily on the first cart mutation or
|
|
111
|
+
* sign-in.
|
|
112
|
+
*/
|
|
113
|
+
export async function createNativeLiveClient(options) {
|
|
114
|
+
const apiUrl = requireHttpUrl('apiUrl', options.apiUrl);
|
|
115
|
+
const checkoutBaseUrl = requireHttpUrl('checkoutBaseUrl', options.checkoutBaseUrl);
|
|
116
|
+
if (typeof options.publishableKey !== 'string' || options.publishableKey.length === 0) {
|
|
117
|
+
throw new Error('createNativeLiveClient: publishableKey is required');
|
|
118
|
+
}
|
|
119
|
+
const storage = options.tokenStorage ?? memoryStorage();
|
|
120
|
+
const client = new LiveClient({
|
|
121
|
+
baseUrl: apiUrl,
|
|
122
|
+
sessionMode: 'token',
|
|
123
|
+
publishableKey: options.publishableKey,
|
|
124
|
+
tokenStorage: toLiveTokenStorage(storage),
|
|
125
|
+
...(options.apiVersion ? { apiVersion: options.apiVersion } : {}),
|
|
126
|
+
});
|
|
127
|
+
const tl = new NativeTicketlayerLive(client, { publishableKey: options.publishableKey, baseUrl: apiUrl }, { storage, checkoutBaseUrl });
|
|
128
|
+
if (options.resume !== false) {
|
|
129
|
+
const token = await storage.get().catch(() => null);
|
|
130
|
+
if (token) {
|
|
131
|
+
try {
|
|
132
|
+
await tl.resume(token);
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
if (err instanceof LiveAPIError && (err.status === 401 || err.status === 404)) {
|
|
136
|
+
// The session is gone (expired, ended). Drop the dead token and
|
|
137
|
+
// start lazily; a transient failure keeps the token for next time.
|
|
138
|
+
await tl.forgetSession();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return tl;
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/native/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAA2B,MAAM,cAAc,CAAC;AAC1F,OAAO,EACL,gBAAgB,IAAI,oBAAoB,EACxC,mBAAmB,IAAI,uBAAuB,GAG/C,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,CAAC;AAG3C,OAAO,EAAE,eAAe,EAAE,CAAC;AAE3B,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,kBAAkB,GAEnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAwD,MAAM,yBAAyB,CAAC;AACnH,OAAO,EAAE,mBAAmB,EAA0D,MAAM,0BAA0B,CAAC;AACvH,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,GAKrB,MAAM,kBAAkB,CAAC;AAiC1B;;;;;GAKG;AACH,MAAM,OAAO,qBAAsB,SAAQ,eAAe;IAIxD,YACE,MAAkB,EAClB,IAAiD,EACjD,MAAgE;QAEhE,KAAK,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACpG,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC;QACpC,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;IAChD,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,gBAAgB,CAAC,OAAiC,EAAE;QACxD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YAClB,MAAM,IAAI,YAAY,CAAC,0CAA0C,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;QACtF,CAAC;QACD,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,YAAY,CAAC,gDAAgD,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;QAC5F,CAAC;QACD,OAAO,oBAAoB,CAAC;YAC1B,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,YAAY,EAAE,KAAK;YACnB,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzD,CAAC,CAAC;IACL,CAAC;IAED,8FAA8F;IAC9F,mBAAmB,CAAC,GAAW,EAAE,OAAmC,EAAE;QACpE,OAAO,uBAAuB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC5C,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,gBAAgB,CAAC,KAAiG;QACtH,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;QACvC,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACnD,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACzB,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACzD,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC9B,CAAC;IAED,6EAA6E;IAC7E,KAAK,CAAC,aAAa;QACjB,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACzD,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC9B,CAAC;IAED,wFAAwF;IACxF,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,SAAS,cAAc,CAAC,IAAY,EAAE,KAAc;IAClD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CACb,2BAA2B,IAAI,gFAAgF,CAChH,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACnC,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,OAAgC;IAC3E,MAAM,MAAM,GAAG,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACxD,MAAM,eAAe,GAAG,cAAc,CAAC,iBAAiB,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IACnF,IAAI,OAAO,OAAO,CAAC,cAAc,KAAK,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtF,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,IAAI,aAAa,EAAE,CAAC;IAExD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC;QAC5B,OAAO,EAAE,MAAM;QACf,WAAW,EAAE,OAAO;QACpB,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,YAAY,EAAE,kBAAkB,CAAC,OAAO,CAAC;QACzC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAClE,CAAC,CAAC;IACH,MAAM,EAAE,GAAG,IAAI,qBAAqB,CAClC,MAAM,EACN,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,EAC3D,EAAE,OAAO,EAAE,eAAe,EAAE,CAC7B,CAAC;IAEF,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QACpD,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACzB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,GAAG,YAAY,YAAY,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,EAAE,CAAC;oBAC9E,gEAAgE;oBAChE,mEAAmE;oBACnE,MAAM,EAAE,CAAC,aAAa,EAAE,CAAC;gBAC3B,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* expo-secure-store adapter.
|
|
3
|
+
*
|
|
4
|
+
* Pass the module in so the SDK has no dependency on expo-secure-store:
|
|
5
|
+
*
|
|
6
|
+
* import * as SecureStore from 'expo-secure-store';
|
|
7
|
+
* import { secureStoreStorage } from '@ticketlayer/live/native';
|
|
8
|
+
* const tokenStorage = secureStoreStorage(SecureStore);
|
|
9
|
+
*
|
|
10
|
+
* The keychain/keystore is the right home for the session token: it is the
|
|
11
|
+
* credential that owns the buyer's cart and, after a magic-link sign-in,
|
|
12
|
+
* their orders. SecureStore keys may only contain letters, digits, '.', '-'
|
|
13
|
+
* and '_'; the default key satisfies that.
|
|
14
|
+
*/
|
|
15
|
+
import { type NativeTokenStorage } from './storage.js';
|
|
16
|
+
/** The subset of expo-secure-store this adapter uses. */
|
|
17
|
+
export interface SecureStoreLike {
|
|
18
|
+
getItemAsync(key: string, options?: unknown): Promise<string | null>;
|
|
19
|
+
setItemAsync(key: string, value: string, options?: unknown): Promise<void>;
|
|
20
|
+
deleteItemAsync(key: string, options?: unknown): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
export interface SecureStoreStorageOptions {
|
|
23
|
+
/** Storage key. Default `ticketlayer.live.session`. */
|
|
24
|
+
key?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Options forwarded to every SecureStore call, for example
|
|
27
|
+
* `{ keychainAccessible: SecureStore.AFTER_FIRST_UNLOCK }` so the token is
|
|
28
|
+
* readable while the app refreshes a cart in the background.
|
|
29
|
+
*/
|
|
30
|
+
options?: unknown;
|
|
31
|
+
}
|
|
32
|
+
export declare function secureStoreStorage(secureStore: SecureStoreLike, opts?: SecureStoreStorageOptions): NativeTokenStorage;
|
|
33
|
+
//# sourceMappingURL=secureStoreStorage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secureStoreStorage.d.ts","sourceRoot":"","sources":["../../src/native/secureStoreStorage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAE1E,yDAAyD;AACzD,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACrE,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,yBAAyB;IACxC,uDAAuD;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAID,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,eAAe,EAC5B,IAAI,GAAE,yBAA8B,GACnC,kBAAkB,CAsBpB"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* expo-secure-store adapter.
|
|
3
|
+
*
|
|
4
|
+
* Pass the module in so the SDK has no dependency on expo-secure-store:
|
|
5
|
+
*
|
|
6
|
+
* import * as SecureStore from 'expo-secure-store';
|
|
7
|
+
* import { secureStoreStorage } from '@ticketlayer/live/native';
|
|
8
|
+
* const tokenStorage = secureStoreStorage(SecureStore);
|
|
9
|
+
*
|
|
10
|
+
* The keychain/keystore is the right home for the session token: it is the
|
|
11
|
+
* credential that owns the buyer's cart and, after a magic-link sign-in,
|
|
12
|
+
* their orders. SecureStore keys may only contain letters, digits, '.', '-'
|
|
13
|
+
* and '_'; the default key satisfies that.
|
|
14
|
+
*/
|
|
15
|
+
import { DEFAULT_TOKEN_KEY } from './storage.js';
|
|
16
|
+
const KEY_PATTERN = /^[A-Za-z0-9._-]+$/;
|
|
17
|
+
export function secureStoreStorage(secureStore, opts = {}) {
|
|
18
|
+
const key = opts.key ?? DEFAULT_TOKEN_KEY;
|
|
19
|
+
if (!KEY_PATTERN.test(key)) {
|
|
20
|
+
throw new Error(`secureStoreStorage: key "${key}" is not a valid SecureStore key (letters, digits, '.', '-' and '_' only)`);
|
|
21
|
+
}
|
|
22
|
+
const options = opts.options;
|
|
23
|
+
return {
|
|
24
|
+
get: async () => {
|
|
25
|
+
const value = await secureStore.getItemAsync(key, options);
|
|
26
|
+
return typeof value === 'string' && value.length > 0 ? value : null;
|
|
27
|
+
},
|
|
28
|
+
set: (token) => secureStore.setItemAsync(key, token, options),
|
|
29
|
+
remove: async () => {
|
|
30
|
+
try {
|
|
31
|
+
await secureStore.deleteItemAsync(key, options);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Nothing stored under the key: nothing to remove.
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=secureStoreStorage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secureStoreStorage.js","sourceRoot":"","sources":["../../src/native/secureStoreStorage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,iBAAiB,EAA2B,MAAM,cAAc,CAAC;AAoB1E,MAAM,WAAW,GAAG,mBAAmB,CAAC;AAExC,MAAM,UAAU,kBAAkB,CAChC,WAA4B,EAC5B,OAAkC,EAAE;IAEpC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,iBAAiB,CAAC;IAC1C,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CACb,4BAA4B,GAAG,2EAA2E,CAC3G,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAC7B,OAAO;QACL,GAAG,EAAE,KAAK,IAAI,EAAE;YACd,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAC3D,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;QACtE,CAAC;QACD,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC;QAC7D,MAAM,EAAE,KAAK,IAAI,EAAE;YACjB,IAAI,CAAC;gBACH,MAAM,WAAW,CAAC,eAAe,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAClD,CAAC;YAAC,MAAM,CAAC;gBACP,mDAAmD;YACrD,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token storage for React Native.
|
|
3
|
+
*
|
|
4
|
+
* The generated client's {@link LiveTokenStorage} is `{ get, set, clear }` and
|
|
5
|
+
* allows synchronous implementations (the browser default is in-memory). A
|
|
6
|
+
* native app persists the Live session token in the OS keychain or app
|
|
7
|
+
* storage, which is always asynchronous and is exposed by the platform
|
|
8
|
+
* modules as get/set/remove. `NativeTokenStorage` is that shape; the two
|
|
9
|
+
* adapters shipped next to this file (`secureStoreStorage`,
|
|
10
|
+
* `asyncStorageStorage`) produce it from the corresponding module without
|
|
11
|
+
* the SDK depending on either package.
|
|
12
|
+
*/
|
|
13
|
+
import type { LiveTokenStorage } from '../client.js';
|
|
14
|
+
/** Async key/value holder for the Live session token. */
|
|
15
|
+
export interface NativeTokenStorage {
|
|
16
|
+
/** The stored token, or null when none is stored. */
|
|
17
|
+
get(): Promise<string | null>;
|
|
18
|
+
/** Persist the token. */
|
|
19
|
+
set(token: string): Promise<void>;
|
|
20
|
+
/** Forget the token. Must not throw when nothing is stored. */
|
|
21
|
+
remove(): Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
/** Default storage key used by the shipped adapters. */
|
|
24
|
+
export declare const DEFAULT_TOKEN_KEY = "ticketlayer.live.session";
|
|
25
|
+
/** In-memory storage: lost when the app restarts. Useful for tests and previews. */
|
|
26
|
+
export declare function memoryStorage(): NativeTokenStorage;
|
|
27
|
+
/** Adapt a {@link NativeTokenStorage} to the generated client's storage interface. */
|
|
28
|
+
export declare function toLiveTokenStorage(storage: NativeTokenStorage): LiveTokenStorage;
|
|
29
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/native/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,yDAAyD;AACzD,MAAM,WAAW,kBAAkB;IACjC,qDAAqD;IACrD,GAAG,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC9B,yBAAyB;IACzB,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,+DAA+D;IAC/D,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAED,wDAAwD;AACxD,eAAO,MAAM,iBAAiB,6BAA6B,CAAC;AAE5D,oFAAoF;AACpF,wBAAgB,aAAa,IAAI,kBAAkB,CAWlD;AAED,sFAAsF;AACtF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,GAAG,gBAAgB,CAMhF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Default storage key used by the shipped adapters. */
|
|
2
|
+
export const DEFAULT_TOKEN_KEY = 'ticketlayer.live.session';
|
|
3
|
+
/** In-memory storage: lost when the app restarts. Useful for tests and previews. */
|
|
4
|
+
export function memoryStorage() {
|
|
5
|
+
let token = null;
|
|
6
|
+
return {
|
|
7
|
+
get: async () => token,
|
|
8
|
+
set: async (t) => {
|
|
9
|
+
token = t;
|
|
10
|
+
},
|
|
11
|
+
remove: async () => {
|
|
12
|
+
token = null;
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/** Adapt a {@link NativeTokenStorage} to the generated client's storage interface. */
|
|
17
|
+
export function toLiveTokenStorage(storage) {
|
|
18
|
+
return {
|
|
19
|
+
get: () => storage.get(),
|
|
20
|
+
set: (token) => storage.set(token),
|
|
21
|
+
clear: () => storage.remove(),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/native/storage.ts"],"names":[],"mappings":"AAwBA,wDAAwD;AACxD,MAAM,CAAC,MAAM,iBAAiB,GAAG,0BAA0B,CAAC;AAE5D,oFAAoF;AACpF,MAAM,UAAU,aAAa;IAC3B,IAAI,KAAK,GAAkB,IAAI,CAAC;IAChC,OAAO;QACL,GAAG,EAAE,KAAK,IAAI,EAAE,CAAC,KAAK;QACtB,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;YACf,KAAK,GAAG,CAAC,CAAC;QACZ,CAAC;QACD,MAAM,EAAE,KAAK,IAAI,EAAE;YACjB,KAAK,GAAG,IAAI,CAAC;QACf,CAAC;KACF,CAAC;AACJ,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,kBAAkB,CAAC,OAA2B;IAC5D,OAAO;QACL,GAAG,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;QACxB,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;QAClC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE;KAC9B,CAAC;AACJ,CAAC"}
|