@atlasauth/expo 0.1.1 → 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/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @atlasauth/expo changelog
2
2
 
3
+ ## 0.2.0
4
+ - **Signing out clears the stored session token.** `createCacheFetch()` now clears the token in the
5
+ `TokenCache` when `POST /v1/client/sessions/:id/revoke` succeeds (2xx, or 404 — already gone) for the
6
+ session the token belongs to (its `sid`), before the response is returned. Previously a sign-out left
7
+ the token in the cache. A failed revoke keeps the token, so the background re-try can still
8
+ authenticate; a `jwt` a revoke response carries is still persisted.
9
+ - **A failed sign-out survives an app restart.** `<AtlasProvider>` passes `@atlasauth/react` a
10
+ `tombstoneStore` backed by the same `TokenCache`, so the ids of sessions the app signed out of persist
11
+ (React Native has no `localStorage`; they were memory-only). After a restart a session whose revoke
12
+ failed is refused — and its revoke re-tried — instead of re-adopted from the token.
13
+ - **Added `tombstoneStoreFor(cache: TokenCache): TombstoneStore`** — the adapter (`getItem` →
14
+ `cache.getToken`, `setItem` → `cache.saveToken`; the key is rewritten to `[A-Za-z0-9._-]` for
15
+ `expo-secure-store`).
16
+ - **Added `tombstoneStore?: TombstoneStore` to `AtlasProviderProps`** (inherited from `@atlasauth/react`
17
+ 0.7.0); defaults to `tombstoneStoreFor(tokenCache)`.
18
+
19
+ ## 0.1.2
20
+ - Picks up `@atlasauth/react` 0.6.0 / `@atlasauth/js` 0.7.0: popup sign-in completes when the opener page
21
+ sends `Cross-Origin-Opener-Policy: same-origin`; a tab opened after a failed sign-out stays signed out
22
+ (sign-out tombstones shared across tabs); the default focus ring keeps 3:1 contrast. No API changes.
23
+
3
24
  ## 0.1.1
4
25
  - **`frontendApi` is validated at mount (via `@atlasauth/react`) and in `createNativeSessionManager()`.** A missing, empty or malformed value now throws an
5
26
  `AtlasConfigError` (from `@atlasauth/js`; `code: 'FRONTEND_API_REQUIRED'` or `'FRONTEND_API_INVALID'`)
@@ -11,6 +11,12 @@ import { type TokenCache } from './token-cache';
11
11
  * {@link createCacheFetch} that bearer-authenticates from, and persists rotated
12
12
  * tokens into, an `expo-secure-store`-backed {@link TokenCache}.
13
13
  *
14
+ * Sign-out: a confirmed revoke clears the stored token (see
15
+ * {@link createCacheFetch}), and the sessions this app signed out of are kept in
16
+ * the same token cache (`tombstoneStore`), so after an app restart a session
17
+ * whose revoke failed is still refused — and its revoke re-tried — rather than
18
+ * re-adopted from the token the failed revoke left behind.
19
+ *
14
20
  * Expo Router friendly: mount it once at the app root (e.g. in `app/_layout.tsx`)
15
21
  * and read auth anywhere with `useAuth()` / `useUser()` / `<SignedIn>` — the
16
22
  * token cache, not a cookie, is what carries the session across a cold start.
@@ -18,6 +24,8 @@ import { type TokenCache } from './token-cache';
18
24
  /**
19
25
  * Props mirror `@atlasauth/react`'s provider (publishableKey, frontendApi,
20
26
  * appearance, localization, oauthMode, onSignedIn) and add the two Expo knobs.
27
+ * `tombstoneStore` defaults to the token cache; pass one to keep sign-out
28
+ * tombstones elsewhere.
21
29
  * `fetchImpl` is replaced by the cache-backed fetch, so it is not forwardable.
22
30
  */
23
31
  export interface AtlasProviderProps extends Omit<ReactAtlasProviderProps, 'fetchImpl'> {
@@ -10,11 +10,18 @@ function AtlasProvider(props) {
10
10
  // Built exactly once — the initializer runs on first render only, so the cache
11
11
  // (and the default in-memory one, when no adapter is passed) survives
12
12
  // re-renders rather than being re-created and losing the session every render.
13
- const [cacheFetch] = (0, react_1.useState)(() => (0, cache_fetch_1.createCacheFetch)({
14
- cache: tokenCache ?? (0, token_cache_1.createInMemoryTokenCache)(),
15
- key: tokenKey,
16
- fetchImpl: fetchImpl ?? fetch,
17
- }));
18
- return (0, react_1.createElement)(react_2.AtlasProvider, { ...rest, fetchImpl: cacheFetch });
13
+ const [wiring] = (0, react_1.useState)(() => {
14
+ const cache = tokenCache ?? (0, token_cache_1.createInMemoryTokenCache)();
15
+ return {
16
+ cacheFetch: (0, cache_fetch_1.createCacheFetch)({ cache, key: tokenKey, fetchImpl: fetchImpl ?? fetch }),
17
+ // Sign-out tombstones persist beside the token (there is no localStorage).
18
+ tombstoneStore: (0, token_cache_1.tombstoneStoreFor)(cache),
19
+ };
20
+ });
21
+ return (0, react_1.createElement)(react_2.AtlasProvider, {
22
+ ...rest,
23
+ tombstoneStore: rest.tombstoneStore ?? wiring.tombstoneStore,
24
+ fetchImpl: wiring.cacheFetch,
25
+ });
19
26
  }
20
27
  //# sourceMappingURL=AtlasProvider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AtlasProvider.js","sourceRoot":"","sources":["../src/AtlasProvider.tsx"],"names":[],"mappings":";;AA6CA,sCAeC;AA5DD,iCAAmE;AACnE,4CAG0B;AAC1B,+CAAiD;AACjD,+CAIuB;AAmCvB,SAAgB,aAAa,CAAC,KAAyB;IACrD,MAAM,EAAE,UAAU,EAAE,QAAQ,GAAG,iCAAmB,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IAEjF,+EAA+E;IAC/E,sEAAsE;IACtE,+EAA+E;IAC/E,MAAM,CAAC,UAAU,CAAC,GAAG,IAAA,gBAAQ,EAAC,GAAG,EAAE,CACjC,IAAA,8BAAgB,EAAC;QACf,KAAK,EAAE,UAAU,IAAI,IAAA,sCAAwB,GAAE;QAC/C,GAAG,EAAE,QAAQ;QACb,SAAS,EAAE,SAAS,IAAI,KAAK;KAC9B,CAAC,CACH,CAAC;IAEF,OAAO,IAAA,qBAAa,EAAC,qBAAkB,EAAE,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;AAC/E,CAAC"}
1
+ {"version":3,"file":"AtlasProvider.js","sourceRoot":"","sources":["../src/AtlasProvider.tsx"],"names":[],"mappings":";;AAsDA,sCAoBC;AA1ED,iCAAmE;AACnE,4CAG0B;AAC1B,+CAAiD;AACjD,+CAKuB;AA2CvB,SAAgB,aAAa,CAAC,KAAyB;IACrD,MAAM,EAAE,UAAU,EAAE,QAAQ,GAAG,iCAAmB,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IAEjF,+EAA+E;IAC/E,sEAAsE;IACtE,+EAA+E;IAC/E,MAAM,CAAC,MAAM,CAAC,GAAG,IAAA,gBAAQ,EAAC,GAAG,EAAE;QAC7B,MAAM,KAAK,GAAG,UAAU,IAAI,IAAA,sCAAwB,GAAE,CAAC;QACvD,OAAO;YACL,UAAU,EAAE,IAAA,8BAAgB,EAAC,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,IAAI,KAAK,EAAE,CAAC;YACrF,2EAA2E;YAC3E,cAAc,EAAE,IAAA,+BAAiB,EAAC,KAAK,CAAC;SACzC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,IAAA,qBAAa,EAAC,qBAAkB,EAAE;QACvC,GAAG,IAAI;QACP,cAAc,EAAE,IAAI,CAAC,cAAc,IAAI,MAAM,CAAC,cAAc;QAC5D,SAAS,EAAE,MAAM,CAAC,UAAU;KAC7B,CAAC,CAAC;AACL,CAAC"}
@@ -17,6 +17,14 @@ import type { TokenCache } from './token-cache';
17
17
  * durable copy native needs. Reading the body is done on a `clone()` so the
18
18
  * provider still gets to consume the original.
19
19
  *
20
+ * 3. SIGN-OUT — a successful `POST /v1/client/sessions/:id/revoke` (2xx, or
21
+ * 404: already gone) of the session the stored token belongs to clears the
22
+ * token, so a sign-out actually drops the credential and a restart boots
23
+ * signed out. The clear is awaited before the response is handed back, so
24
+ * no later request can still carry the token. A FAILED revoke keeps it: the
25
+ * provider remembers the session as signed out (its tombstone) and re-tries
26
+ * the revoke in the background, which needs the token to authenticate.
27
+ *
20
28
  * The persist is fire-and-forget: a secure-store write failure must not break a
21
29
  * live, already-parsed response.
22
30
  */
@@ -19,6 +19,14 @@ exports.createCacheFetch = createCacheFetch;
19
19
  * durable copy native needs. Reading the body is done on a `clone()` so the
20
20
  * provider still gets to consume the original.
21
21
  *
22
+ * 3. SIGN-OUT — a successful `POST /v1/client/sessions/:id/revoke` (2xx, or
23
+ * 404: already gone) of the session the stored token belongs to clears the
24
+ * token, so a sign-out actually drops the credential and a restart boots
25
+ * signed out. The clear is awaited before the response is handed back, so
26
+ * no later request can still carry the token. A FAILED revoke keeps it: the
27
+ * provider remembers the session as signed out (its tombstone) and re-tries
28
+ * the revoke in the background, which needs the token to authenticate.
29
+ *
22
30
  * The persist is fire-and-forget: a secure-store write failure must not break a
23
31
  * live, already-parsed response.
24
32
  */
@@ -30,6 +38,15 @@ function createCacheFetch(opts) {
30
38
  if (token)
31
39
  headers.set('authorization', `Bearer ${token}`);
32
40
  const response = await fetchImpl(input, { ...init, headers });
41
+ const revoked = revokedSessionId(input, init);
42
+ if (revoked && token && (response.ok || response.status === 404) && tokenBelongsTo(token, revoked)) {
43
+ try {
44
+ await cache.clearToken(key);
45
+ }
46
+ catch {
47
+ // A secure-store failure must not break the sign-out response.
48
+ }
49
+ }
33
50
  // Capture a rotated session token for persistence, without consuming the
34
51
  // body the caller still needs.
35
52
  const contentType = response.headers.get('content-type') ?? '';
@@ -50,4 +67,40 @@ function createCacheFetch(opts) {
50
67
  return response;
51
68
  };
52
69
  }
70
+ const REVOKE_PATH = /\/v1\/client\/sessions\/([^/?#]+)\/revoke(?:[?#]|$)/;
71
+ /** The session id a `POST …/v1/client/sessions/:id/revoke` targets, else null. */
72
+ function revokedSessionId(input, init) {
73
+ const isRequest = typeof Request !== 'undefined' && input instanceof Request;
74
+ const method = (init?.method ?? (isRequest ? input.method : 'GET')).toUpperCase();
75
+ if (method !== 'POST')
76
+ return null;
77
+ const url = isRequest ? input.url : String(input);
78
+ const match = REVOKE_PATH.exec(url);
79
+ if (!match)
80
+ return null;
81
+ try {
82
+ return decodeURIComponent(match[1]);
83
+ }
84
+ catch {
85
+ return match[1];
86
+ }
87
+ }
88
+ /**
89
+ * Whether the stored token is the revoked session's: its `sid` claim matches.
90
+ * A token whose claims cannot be read is treated as the session's own (the
91
+ * provider only revokes the session it is signed in to, or one it refuses).
92
+ */
93
+ function tokenBelongsTo(token, sessionId) {
94
+ const payload = token.split('.')[1];
95
+ const decode = globalThis.atob;
96
+ if (!payload || !decode)
97
+ return true;
98
+ try {
99
+ const claims = JSON.parse(decode(payload.replace(/-/g, '+').replace(/_/g, '/')));
100
+ return typeof claims.sid !== 'string' || claims.sid === sessionId;
101
+ }
102
+ catch {
103
+ return true;
104
+ }
105
+ }
53
106
  //# sourceMappingURL=cache-fetch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cache-fetch.js","sourceRoot":"","sources":["../src/cache-fetch.ts"],"names":[],"mappings":";;AAuBA,4CAiCC;AAtDD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAgB,gBAAgB,CAAC,IAIhC;IACC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IAEvC,OAAO,KAAK,EAAE,KAAwB,EAAE,IAAkB,EAAqB,EAAE;QAC/E,MAAM,KAAK,GAAG,CAAC,MAAM,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC;QAClD,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3C,IAAI,KAAK;YAAE,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,KAAK,EAAE,CAAC,CAAC;QAE3D,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAE9D,yEAAyE;QACzE,+BAA+B;QAC/B,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QAC/D,IAAI,QAAQ,CAAC,EAAE,IAAI,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;YAC5D,KAAK,CAAC,KAAK,IAAI,EAAE;gBACf,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAsB,CAAC;oBAClE,IAAI,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;wBAC7C,MAAM,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;oBACvC,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,sEAAsE;oBACtE,0BAA0B;gBAC5B,CAAC;YACH,CAAC,CAAC,EAAE,CAAC;QACP,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"cache-fetch.js","sourceRoot":"","sources":["../src/cache-fetch.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,7 @@
14
14
  * structurally ({@link SecureStore}) and the app passes the real module in — the
15
15
  * package compiles, typechecks and tests without `expo-secure-store` installed.
16
16
  */
17
+ import type { TombstoneStore } from '@atlasauth/js';
17
18
  /**
18
19
  * A key→token cache, the shape `<AtlasProvider tokenCache>` and the native
19
20
  * session wiring both consume. Mirrors Clerk's Expo `tokenCache` contract
@@ -85,5 +86,16 @@ export interface TokenStorage {
85
86
  export declare function tokenStorageFor(cache: TokenCache, key: string): TokenStorage;
86
87
  /** A process-memory {@link TokenStorage}. Non-persistent — see note above. */
87
88
  export declare function createInMemoryStorage(): TokenStorage;
89
+ /**
90
+ * View a {@link TokenCache} as the `TombstoneStore` `@atlasauth/react` keeps its
91
+ * sign-out tombstones in (the ids of sessions this app signed out of — never a
92
+ * token). React Native has no `localStorage`, so without this the tombstones are
93
+ * memory-only and an app restart could re-adopt a session whose revoke failed.
94
+ *
95
+ * The tombstone key (`atlas:signed-out-sessions:<frontend api origin>`) is
96
+ * rewritten to the characters `expo-secure-store` accepts in a key
97
+ * (`A–Z a–z 0–9 . - _`), so the same adapter fits every cache.
98
+ */
99
+ export declare function tombstoneStoreFor(cache: TokenCache): TombstoneStore;
88
100
  /** The default cache key the `<AtlasProvider>` session is stored under. */
89
101
  export declare const DEFAULT_SESSION_KEY = "atlas.session";
@@ -21,6 +21,7 @@ exports.createSecureStoreTokenCache = createSecureStoreTokenCache;
21
21
  exports.createInMemoryTokenCache = createInMemoryTokenCache;
22
22
  exports.tokenStorageFor = tokenStorageFor;
23
23
  exports.createInMemoryStorage = createInMemoryStorage;
24
+ exports.tombstoneStoreFor = tombstoneStoreFor;
24
25
  /**
25
26
  * Build a {@link TokenCache} backed by `expo-secure-store` (hardware-backed
26
27
  * Keychain / Keystore). The app imports the module and passes it in — the SDK
@@ -79,6 +80,25 @@ function createInMemoryStorage() {
79
80
  },
80
81
  };
81
82
  }
83
+ /**
84
+ * View a {@link TokenCache} as the `TombstoneStore` `@atlasauth/react` keeps its
85
+ * sign-out tombstones in (the ids of sessions this app signed out of — never a
86
+ * token). React Native has no `localStorage`, so without this the tombstones are
87
+ * memory-only and an app restart could re-adopt a session whose revoke failed.
88
+ *
89
+ * The tombstone key (`atlas:signed-out-sessions:<frontend api origin>`) is
90
+ * rewritten to the characters `expo-secure-store` accepts in a key
91
+ * (`A–Z a–z 0–9 . - _`), so the same adapter fits every cache.
92
+ */
93
+ function tombstoneStoreFor(cache) {
94
+ return {
95
+ getItem: (key) => cache.getToken(storeKey(key)),
96
+ setItem: (key, value) => cache.saveToken(storeKey(key), value),
97
+ };
98
+ }
99
+ function storeKey(key) {
100
+ return key.replace(/[^A-Za-z0-9._-]/g, '_');
101
+ }
82
102
  /** The default cache key the `<AtlasProvider>` session is stored under. */
83
103
  exports.DEFAULT_SESSION_KEY = 'atlas.session';
84
104
  //# sourceMappingURL=token-cache.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"token-cache.js","sourceRoot":"","sources":["../src/token-cache.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;AAsDH,kEAUC;AAOD,4DAWC;AAeD,0CAMC;AAGD,sDAWC;AA3ED;;;;;;;;;;;GAWG;AACH,SAAgB,2BAA2B,CACzC,KAAkB,EAClB,UAAwC,EAAE;IAE1C,MAAM,IAAI,GAAG,OAAO,CAAC,kBAAkB,CAAC;IACxC,OAAO;QACL,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC;QAChD,SAAS,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC;QAC/D,UAAU,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC;KACtD,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,wBAAwB;IACtC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtC,OAAO;QACL,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI;QACvC,SAAS,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;YACxB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACtB,CAAC;QACD,UAAU,EAAE,CAAC,GAAG,EAAE,EAAE;YAClB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC;AAcD,iFAAiF;AACjF,SAAgB,eAAe,CAAC,KAAiB,EAAE,GAAW;IAC5D,OAAO;QACL,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI;QACzD,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC;QAChD,UAAU,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;KACxC,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,SAAgB,qBAAqB;IACnC,IAAI,KAAK,GAAkB,IAAI,CAAC;IAChC,OAAO;QACL,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK;QACrB,QAAQ,EAAE,CAAC,IAAY,EAAE,EAAE;YACzB,KAAK,GAAG,IAAI,CAAC;QACf,CAAC;QACD,UAAU,EAAE,GAAG,EAAE;YACf,KAAK,GAAG,IAAI,CAAC;QACf,CAAC;KACF,CAAC;AACJ,CAAC;AAED,2EAA2E;AAC9D,QAAA,mBAAmB,GAAG,eAAe,CAAC"}
1
+ {"version":3,"file":"token-cache.js","sourceRoot":"","sources":["../src/token-cache.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;AAwDH,kEAUC;AAOD,4DAWC;AAeD,0CAMC;AAGD,sDAWC;AAYD,8CAKC;AA5FD;;;;;;;;;;;GAWG;AACH,SAAgB,2BAA2B,CACzC,KAAkB,EAClB,UAAwC,EAAE;IAE1C,MAAM,IAAI,GAAG,OAAO,CAAC,kBAAkB,CAAC;IACxC,OAAO;QACL,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC;QAChD,SAAS,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC;QAC/D,UAAU,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC;KACtD,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,wBAAwB;IACtC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtC,OAAO;QACL,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI;QACvC,SAAS,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;YACxB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACtB,CAAC;QACD,UAAU,EAAE,CAAC,GAAG,EAAE,EAAE;YAClB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC;AAcD,iFAAiF;AACjF,SAAgB,eAAe,CAAC,KAAiB,EAAE,GAAW;IAC5D,OAAO;QACL,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI;QACzD,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC;QAChD,UAAU,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;KACxC,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,SAAgB,qBAAqB;IACnC,IAAI,KAAK,GAAkB,IAAI,CAAC;IAChC,OAAO;QACL,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK;QACrB,QAAQ,EAAE,CAAC,IAAY,EAAE,EAAE;YACzB,KAAK,GAAG,IAAI,CAAC;QACf,CAAC;QACD,UAAU,EAAE,GAAG,EAAE;YACf,KAAK,GAAG,IAAI,CAAC;QACf,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,iBAAiB,CAAC,KAAiB;IACjD,OAAO;QACL,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC/C,OAAO,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC;KAC/D,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW;IAC3B,OAAO,GAAG,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;AAC9C,CAAC;AAED,2EAA2E;AAC9D,QAAA,mBAAmB,GAAG,eAAe,CAAC"}
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@atlasauth/expo",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "dependencies": {
7
- "@atlasauth/react": "0.5.0",
8
- "@atlasauth/js": "0.6.0"
7
+ "@atlasauth/react": "0.7.0",
8
+ "@atlasauth/js": "0.8.0"
9
9
  },
10
10
  "peerDependencies": {
11
11
  "react": ">=18",