@oxyhq/core 1.11.12 → 1.11.14
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/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/CrossDomainAuth.js +3 -1
- package/dist/cjs/HttpService.js +214 -33
- package/dist/cjs/OxyServices.base.js +9 -0
- package/dist/cjs/OxyServices.js +8 -3
- package/dist/cjs/crypto/index.js +3 -1
- package/dist/cjs/crypto/keyManager.js +476 -172
- package/dist/cjs/crypto/polyfill.js +14 -65
- package/dist/cjs/crypto/recoveryPhrase.js +30 -11
- package/dist/cjs/crypto/signatureService.js +25 -60
- package/dist/cjs/i18n/locales/en-US.json +46 -1
- package/dist/cjs/i18n/locales/es-ES.json +46 -1
- package/dist/cjs/i18n/locales/locales/en-US.json +46 -1
- package/dist/cjs/i18n/locales/locales/es-ES.json +46 -1
- package/dist/cjs/index.js +10 -2
- package/dist/cjs/mixins/OxyServices.assets.js +9 -4
- package/dist/cjs/mixins/OxyServices.auth.js +147 -14
- package/dist/cjs/mixins/OxyServices.contacts.js +50 -0
- package/dist/cjs/mixins/OxyServices.features.js +0 -11
- package/dist/cjs/mixins/OxyServices.fedcm.js +4 -3
- package/dist/cjs/mixins/OxyServices.language.js +5 -36
- package/dist/cjs/mixins/OxyServices.redirect.js +6 -2
- package/dist/cjs/mixins/OxyServices.security.js +13 -2
- package/dist/cjs/mixins/OxyServices.user.js +59 -38
- package/dist/cjs/mixins/OxyServices.utility.js +416 -110
- package/dist/cjs/mixins/index.js +11 -3
- package/dist/cjs/utils/accountUtils.js +71 -2
- package/dist/cjs/utils/deviceManager.js +5 -36
- package/dist/cjs/utils/languageUtils.js +22 -0
- package/dist/cjs/utils/platformCrypto.js +165 -0
- package/dist/cjs/utils/platformCrypto.native.js +123 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/CrossDomainAuth.js +3 -1
- package/dist/esm/HttpService.js +215 -34
- package/dist/esm/OxyServices.base.js +9 -0
- package/dist/esm/OxyServices.js +8 -3
- package/dist/esm/crypto/index.js +1 -1
- package/dist/esm/crypto/keyManager.js +473 -138
- package/dist/esm/crypto/polyfill.js +14 -32
- package/dist/esm/crypto/recoveryPhrase.js +30 -11
- package/dist/esm/crypto/signatureService.js +25 -27
- package/dist/esm/i18n/locales/en-US.json +46 -1
- package/dist/esm/i18n/locales/es-ES.json +46 -1
- package/dist/esm/i18n/locales/locales/en-US.json +46 -1
- package/dist/esm/i18n/locales/locales/es-ES.json +46 -1
- package/dist/esm/index.js +4 -3
- package/dist/esm/mixins/OxyServices.assets.js +9 -4
- package/dist/esm/mixins/OxyServices.auth.js +145 -14
- package/dist/esm/mixins/OxyServices.contacts.js +47 -0
- package/dist/esm/mixins/OxyServices.features.js +0 -11
- package/dist/esm/mixins/OxyServices.fedcm.js +4 -3
- package/dist/esm/mixins/OxyServices.language.js +5 -3
- package/dist/esm/mixins/OxyServices.redirect.js +6 -2
- package/dist/esm/mixins/OxyServices.security.js +13 -2
- package/dist/esm/mixins/OxyServices.user.js +59 -38
- package/dist/esm/mixins/OxyServices.utility.js +416 -77
- package/dist/esm/mixins/index.js +11 -3
- package/dist/esm/utils/accountUtils.js +67 -1
- package/dist/esm/utils/deviceManager.js +5 -3
- package/dist/esm/utils/languageUtils.js +21 -0
- package/dist/esm/utils/platformCrypto.js +125 -0
- package/dist/esm/utils/platformCrypto.native.js +80 -0
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/HttpService.d.ts +47 -3
- package/dist/types/OxyServices.base.d.ts +7 -0
- package/dist/types/OxyServices.d.ts +50 -7
- package/dist/types/crypto/index.d.ts +1 -1
- package/dist/types/crypto/keyManager.d.ts +110 -9
- package/dist/types/crypto/polyfill.d.ts +3 -1
- package/dist/types/crypto/recoveryPhrase.d.ts +31 -7
- package/dist/types/crypto/signatureService.d.ts +4 -0
- package/dist/types/index.d.ts +7 -5
- package/dist/types/mixins/OxyServices.analytics.d.ts +1 -0
- package/dist/types/mixins/OxyServices.assets.d.ts +6 -10
- package/dist/types/mixins/OxyServices.auth.d.ts +82 -5
- package/dist/types/mixins/OxyServices.contacts.d.ts +99 -0
- package/dist/types/mixins/OxyServices.developer.d.ts +1 -0
- package/dist/types/mixins/OxyServices.devices.d.ts +1 -0
- package/dist/types/mixins/OxyServices.features.d.ts +2 -7
- package/dist/types/mixins/OxyServices.fedcm.d.ts +1 -0
- package/dist/types/mixins/OxyServices.karma.d.ts +1 -0
- package/dist/types/mixins/OxyServices.language.d.ts +1 -0
- package/dist/types/mixins/OxyServices.location.d.ts +1 -0
- package/dist/types/mixins/OxyServices.managedAccounts.d.ts +1 -0
- package/dist/types/mixins/OxyServices.payment.d.ts +1 -0
- package/dist/types/mixins/OxyServices.popup.d.ts +1 -0
- package/dist/types/mixins/OxyServices.privacy.d.ts +1 -0
- package/dist/types/mixins/OxyServices.redirect.d.ts +1 -0
- package/dist/types/mixins/OxyServices.security.d.ts +1 -0
- package/dist/types/mixins/OxyServices.topics.d.ts +1 -0
- package/dist/types/mixins/OxyServices.user.d.ts +28 -11
- package/dist/types/mixins/OxyServices.utility.d.ts +145 -10
- package/dist/types/mixins/index.d.ts +52 -4
- package/dist/types/models/interfaces.d.ts +62 -3
- package/dist/types/utils/accountUtils.d.ts +41 -1
- package/dist/types/utils/languageUtils.d.ts +1 -0
- package/dist/types/utils/platformCrypto.d.ts +87 -0
- package/dist/types/utils/platformCrypto.native.d.ts +54 -0
- package/package.json +45 -2
- package/src/CrossDomainAuth.ts +12 -10
- package/src/HttpService.ts +251 -40
- package/src/OxyServices.base.ts +10 -0
- package/src/OxyServices.ts +26 -7
- package/src/crypto/__tests__/keyManager.test.ts +336 -0
- package/src/crypto/index.ts +6 -1
- package/src/crypto/keyManager.ts +529 -151
- package/src/crypto/polyfill.ts +14 -34
- package/src/crypto/recoveryPhrase.ts +56 -17
- package/src/crypto/signatureService.ts +25 -30
- package/src/i18n/locales/en-US.json +46 -1
- package/src/i18n/locales/es-ES.json +46 -1
- package/src/index.ts +19 -4
- package/src/mixins/OxyServices.assets.ts +15 -11
- package/src/mixins/OxyServices.auth.ts +175 -15
- package/src/mixins/OxyServices.contacts.ts +73 -0
- package/src/mixins/OxyServices.features.ts +2 -12
- package/src/mixins/OxyServices.fedcm.ts +4 -3
- package/src/mixins/OxyServices.language.ts +6 -4
- package/src/mixins/OxyServices.redirect.ts +6 -2
- package/src/mixins/OxyServices.security.ts +18 -8
- package/src/mixins/OxyServices.user.ts +72 -49
- package/src/mixins/OxyServices.utility.ts +562 -89
- package/src/mixins/__tests__/serviceAuth.test.ts +623 -0
- package/src/mixins/index.ts +58 -7
- package/src/models/interfaces.ts +65 -3
- package/src/utils/accountUtils.ts +82 -2
- package/src/utils/deviceManager.ts +7 -4
- package/src/utils/languageUtils.ts +23 -2
- package/src/utils/platformCrypto.native.ts +101 -0
- package/src/utils/platformCrypto.ts +145 -0
|
@@ -18,6 +18,40 @@ export interface OxyConfig {
|
|
|
18
18
|
onRequestEnd?: (url: string, method: string, duration: number, success: boolean) => void;
|
|
19
19
|
onRequestError?: (url: string, method: string, error: Error) => void;
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Privacy settings for a user account.
|
|
23
|
+
*
|
|
24
|
+
* All fields are optional because:
|
|
25
|
+
* - Updates are dot-path partial PATCHes — clients send only changed keys.
|
|
26
|
+
* - The server may return a partial subdocument depending on the API
|
|
27
|
+
* build (older builds returned only the field that changed).
|
|
28
|
+
* - User accounts created before a new toggle was introduced won't
|
|
29
|
+
* have that key persisted yet.
|
|
30
|
+
*
|
|
31
|
+
* Mirrors `IPrivacySettings` from `packages/api/src/types/privacy.types.ts`,
|
|
32
|
+
* but with every field marked optional.
|
|
33
|
+
*/
|
|
34
|
+
export interface PrivacySettings {
|
|
35
|
+
isPrivateAccount?: boolean;
|
|
36
|
+
hideOnlineStatus?: boolean;
|
|
37
|
+
hideLastSeen?: boolean;
|
|
38
|
+
profileVisibility?: boolean;
|
|
39
|
+
loginAlerts?: boolean;
|
|
40
|
+
blockScreenshots?: boolean;
|
|
41
|
+
login?: boolean;
|
|
42
|
+
biometricLogin?: boolean;
|
|
43
|
+
showActivity?: boolean;
|
|
44
|
+
allowTagging?: boolean;
|
|
45
|
+
allowMentions?: boolean;
|
|
46
|
+
hideReadReceipts?: boolean;
|
|
47
|
+
allowDirectMessages?: boolean;
|
|
48
|
+
dataSharing?: boolean;
|
|
49
|
+
locationSharing?: boolean;
|
|
50
|
+
analyticsSharing?: boolean;
|
|
51
|
+
sensitiveContent?: boolean;
|
|
52
|
+
autoFilter?: boolean;
|
|
53
|
+
muteKeywords?: boolean;
|
|
54
|
+
}
|
|
21
55
|
export interface User {
|
|
22
56
|
id: string;
|
|
23
57
|
publicKey: string;
|
|
@@ -25,9 +59,7 @@ export interface User {
|
|
|
25
59
|
email?: string;
|
|
26
60
|
avatar?: string;
|
|
27
61
|
color?: string;
|
|
28
|
-
privacySettings?:
|
|
29
|
-
[key: string]: unknown;
|
|
30
|
-
};
|
|
62
|
+
privacySettings?: PrivacySettings;
|
|
31
63
|
name?: {
|
|
32
64
|
first?: string;
|
|
33
65
|
last?: string;
|
|
@@ -240,6 +272,33 @@ export interface FileDeleteResponse {
|
|
|
240
272
|
message: string;
|
|
241
273
|
fileId: string;
|
|
242
274
|
}
|
|
275
|
+
/**
|
|
276
|
+
* React Native file descriptor accepted by FormData.
|
|
277
|
+
*
|
|
278
|
+
* On React Native, the multipart upload reads the file from disk via the URI
|
|
279
|
+
* during the network request — no in-JS Blob construction is required (and
|
|
280
|
+
* doing so would fail on Hermes since RN's BlobManager cannot wrap an
|
|
281
|
+
* ArrayBuffer/ArrayBufferView).
|
|
282
|
+
*
|
|
283
|
+
* This shape matches what `expo-document-picker` and `expo-image-picker`
|
|
284
|
+
* return for selected assets, and is what `OxyServices.assetUpload` accepts
|
|
285
|
+
* on native platforms.
|
|
286
|
+
*/
|
|
287
|
+
export interface RNFileDescriptor {
|
|
288
|
+
uri: string;
|
|
289
|
+
type?: string;
|
|
290
|
+
name?: string;
|
|
291
|
+
size?: number;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Asset upload input — accepted by `OxyServices.assetUpload` and `uploadRawFile`.
|
|
295
|
+
*
|
|
296
|
+
* - `File` / `Blob`: standard web browser path. `assetUpload` appends the
|
|
297
|
+
* Blob to FormData directly.
|
|
298
|
+
* - {@link RNFileDescriptor}: React Native path. FormData reads the file from
|
|
299
|
+
* disk via the URI during the multipart request.
|
|
300
|
+
*/
|
|
301
|
+
export type AssetUploadInput = File | Blob | RNFileDescriptor;
|
|
243
302
|
/**
|
|
244
303
|
* Central Asset Service interfaces
|
|
245
304
|
*/
|
|
@@ -10,6 +10,44 @@ export interface QuickAccount {
|
|
|
10
10
|
avatar?: string;
|
|
11
11
|
avatarUrl?: string;
|
|
12
12
|
}
|
|
13
|
+
/** Minimal user shape accepted by display-name helpers. Avoids importing the full User type. */
|
|
14
|
+
export interface DisplayNameUserShape {
|
|
15
|
+
name?: string | {
|
|
16
|
+
first?: string;
|
|
17
|
+
last?: string;
|
|
18
|
+
full?: string;
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
};
|
|
21
|
+
username?: string;
|
|
22
|
+
publicKey?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Truncate a long public key for display, e.g. `0x12345678…`.
|
|
26
|
+
* Falls back to the raw key if it's too short to truncate.
|
|
27
|
+
*/
|
|
28
|
+
export declare const formatPublicKeyHandle: (publicKey: string) => string;
|
|
29
|
+
/**
|
|
30
|
+
* Resolve a friendly display name for a user.
|
|
31
|
+
*
|
|
32
|
+
* Order of preference:
|
|
33
|
+
* 1. `name.full`, or composed `name.first name.last`
|
|
34
|
+
* 2. `name` (when stored as a plain string)
|
|
35
|
+
* 3. `username`
|
|
36
|
+
* 4. `Account 0x12345678…` (derived from publicKey, when present)
|
|
37
|
+
* 5. Translated fallback (e.g. "Unnamed")
|
|
38
|
+
*
|
|
39
|
+
* The translation key `common.unnamed` is used for the final fallback. If the
|
|
40
|
+
* caller does not pass a locale, the default English translation is used.
|
|
41
|
+
*/
|
|
42
|
+
export declare const getAccountDisplayName: (user: DisplayNameUserShape | null | undefined, locale?: string) => string;
|
|
43
|
+
/**
|
|
44
|
+
* Resolve a `@handle` style identifier for a user.
|
|
45
|
+
*
|
|
46
|
+
* Returns the bare username when present (without the `@`), otherwise a
|
|
47
|
+
* truncated public-key handle (`0x12345678…`), or `undefined` when neither is
|
|
48
|
+
* available — callers can decide whether to hide the line entirely.
|
|
49
|
+
*/
|
|
50
|
+
export declare const getAccountFallbackHandle: (user: DisplayNameUserShape | null | undefined) => string | undefined;
|
|
13
51
|
/**
|
|
14
52
|
* Build an ordered array of QuickAccounts from a map and order list.
|
|
15
53
|
*/
|
|
@@ -23,11 +61,13 @@ export declare const buildAccountsArray: (accounts: Record<string, QuickAccount>
|
|
|
23
61
|
* @param getFileDownloadUrl - Function to generate avatar download URL from file ID
|
|
24
62
|
*/
|
|
25
63
|
export declare const createQuickAccount: (sessionId: string, userData: {
|
|
26
|
-
name?: {
|
|
64
|
+
name?: string | {
|
|
27
65
|
full?: string;
|
|
28
66
|
first?: string;
|
|
67
|
+
last?: string;
|
|
29
68
|
};
|
|
30
69
|
username?: string;
|
|
70
|
+
publicKey?: string;
|
|
31
71
|
id?: string;
|
|
32
72
|
_id?: {
|
|
33
73
|
toString(): string;
|
|
@@ -35,3 +35,4 @@ export declare function getNativeLanguageName(languageCode: string | null | unde
|
|
|
35
35
|
* @returns Normalized BCP-47 language code
|
|
36
36
|
*/
|
|
37
37
|
export declare function normalizeLanguageCode(lang?: string | null): string;
|
|
38
|
+
export declare function isRTLLocale(locale?: string | null): boolean;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform Crypto / Storage — Default Variant (Node.js, Browser, generic bundlers)
|
|
3
|
+
*
|
|
4
|
+
* Provides lazy access to platform-specific crypto and storage modules.
|
|
5
|
+
*
|
|
6
|
+
* # Variants
|
|
7
|
+
*
|
|
8
|
+
* This module ships in two physical variants on disk, selected per consumer
|
|
9
|
+
* by the bundler / runtime:
|
|
10
|
+
*
|
|
11
|
+
* - `platformCrypto.js` — this file. Used by Node.js, Vite, webpack,
|
|
12
|
+
* Rollup, esbuild, and anything that does
|
|
13
|
+
* not match Metro's `*.native.js`
|
|
14
|
+
* source-extension preference.
|
|
15
|
+
* - `platformCrypto.native.js` — sibling file. Picked up automatically by
|
|
16
|
+
* Metro's resolver (which prefers
|
|
17
|
+
* `*.<platform>.js` and `*.native.js` over
|
|
18
|
+
* plain `*.js` when `preferNativePlatform`
|
|
19
|
+
* is true — Expo sets this for all non-web
|
|
20
|
+
* builds).
|
|
21
|
+
*
|
|
22
|
+
* The `package.json#exports` map also declares a `"react-native"` condition
|
|
23
|
+
* pointing at the same `dist/esm/index.js` entry — that entry transitively
|
|
24
|
+
* imports `./platformCrypto`, and Metro's per-file source-extension lookup
|
|
25
|
+
* substitutes the `.native.js` sibling automatically inside `dist/`. This
|
|
26
|
+
* means consumers never have to add resolver shims; Metro Just Works.
|
|
27
|
+
*
|
|
28
|
+
* Both variants expose the EXACT same public API; importers don't need to know
|
|
29
|
+
* which one they got. The variant difference is purely about which underlying
|
|
30
|
+
* native modules each one references:
|
|
31
|
+
*
|
|
32
|
+
* ┌──────────────────┬───────────────────────┬───────────────────────────────┐
|
|
33
|
+
* │ Function │ Default variant │ React Native variant │
|
|
34
|
+
* ├──────────────────┼───────────────────────┼───────────────────────────────┤
|
|
35
|
+
* │ loadNodeCrypto │ `await import('crypto')` (Node built-in) │
|
|
36
|
+
* │ │ │ throws — Node crypto is not │
|
|
37
|
+
* │ │ │ available on Hermes/RN │
|
|
38
|
+
* ├──────────────────┼───────────────────────┼───────────────────────────────┤
|
|
39
|
+
* │ loadExpoCrypto │ throws — expo-crypto │ static `import 'expo-crypto'` │
|
|
40
|
+
* │ │ is not part of a │ │
|
|
41
|
+
* │ │ Node/Vite bundle │ │
|
|
42
|
+
* ├──────────────────┼───────────────────────┼───────────────────────────────┤
|
|
43
|
+
* │ loadSecureStore │ throws (web/Node have │ static `import 'expo-secure-` │
|
|
44
|
+
* │ │ their own storage) │ store' │
|
|
45
|
+
* ├──────────────────┼───────────────────────┼───────────────────────────────┤
|
|
46
|
+
* │ loadAsyncStorage │ throws (web/Node have │ static `import '@react- │
|
|
47
|
+
* │ │ their own storage) │ native-async-storage/...' │
|
|
48
|
+
* ├──────────────────┼───────────────────────┼───────────────────────────────┤
|
|
49
|
+
* │ getRandomBytesRN │ throws (RN-only) │ direct call into expo-crypto │
|
|
50
|
+
* └──────────────────┴───────────────────────┴───────────────────────────────┘
|
|
51
|
+
*
|
|
52
|
+
* Crucially, the default variant references ONLY Node's `'crypto'`. It never
|
|
53
|
+
* mentions `expo-*` or `@react-native-async-storage/*` — so Vite, webpack,
|
|
54
|
+
* esbuild, Rollup, and Node itself can bundle / require it without ever
|
|
55
|
+
* attempting to resolve those RN-only packages.
|
|
56
|
+
*
|
|
57
|
+
* The React Native variant references ONLY the RN packages. It never
|
|
58
|
+
* mentions `'crypto'` — so Metro and Hermes have nothing to choke on.
|
|
59
|
+
*
|
|
60
|
+
* # Why not a single file with dynamic import?
|
|
61
|
+
*
|
|
62
|
+
* A previous iteration used a "bundler-opaque" `new Function('s', 'return
|
|
63
|
+
* import(s)')` trick so a single file could service every platform. It
|
|
64
|
+
* bundled cleanly on Metro but Hermes refused to PARSE the resulting
|
|
65
|
+
* `import()` expression inside a Function-constructor body
|
|
66
|
+
* (`SyntaxError: Invalid expression encountered` at the `(` of `import(`).
|
|
67
|
+
* The platform-extension split is the only approach that lets each runtime
|
|
68
|
+
* see a file containing only specifiers it can understand — no tricks, no
|
|
69
|
+
* runtime parsing risks.
|
|
70
|
+
*/
|
|
71
|
+
export declare function loadNodeCrypto(): Promise<typeof import('crypto')>;
|
|
72
|
+
export declare function loadExpoCrypto(): Promise<typeof import('expo-crypto')>;
|
|
73
|
+
export declare function loadSecureStore(): Promise<typeof import('expo-secure-store')>;
|
|
74
|
+
export declare function loadAsyncStorage(): Promise<{
|
|
75
|
+
default: {
|
|
76
|
+
getItem: (key: string) => Promise<string | null>;
|
|
77
|
+
setItem: (key: string, value: string) => Promise<void>;
|
|
78
|
+
removeItem: (key: string) => Promise<void>;
|
|
79
|
+
};
|
|
80
|
+
}>;
|
|
81
|
+
/**
|
|
82
|
+
* Synchronous random-bytes via `expo-crypto.getRandomBytes`. Only available
|
|
83
|
+
* in the React Native variant. The default variant throws because Node and
|
|
84
|
+
* browsers have their own native CSPRNGs (`crypto.randomBytes` and
|
|
85
|
+
* `crypto.getRandomValues` respectively) — callers should use those.
|
|
86
|
+
*/
|
|
87
|
+
export declare function getRandomBytesRN(_byteCount: number): Uint8Array;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform Crypto / Storage — React Native Variant
|
|
3
|
+
*
|
|
4
|
+
* Companion to `./platformCrypto.ts`. See the doc-comment at the top of that
|
|
5
|
+
* file for the full design.
|
|
6
|
+
*
|
|
7
|
+
* Metro auto-selects this file in any non-web build (`preferNativePlatform`
|
|
8
|
+
* is `true` for iOS / Android, so `*.native.js` shadows `*.js` during
|
|
9
|
+
* source-extension resolution inside `node_modules/@oxyhq/core/dist/`). On
|
|
10
|
+
* iOS / Android `<base>.ios.js` / `<base>.android.js` would shadow this file
|
|
11
|
+
* if they existed, but they don't — `.native.js` is the shared RN variant.
|
|
12
|
+
*
|
|
13
|
+
* - The default variant references Node's `'crypto'` and would crash Metro
|
|
14
|
+
* if bundled into an RN app.
|
|
15
|
+
* - This variant references the RN-only modules (`expo-crypto`,
|
|
16
|
+
* `expo-secure-store`, `@react-native-async-storage/async-storage`)
|
|
17
|
+
* as static imports, so Metro and Hermes both resolve and parse them
|
|
18
|
+
* cleanly.
|
|
19
|
+
*
|
|
20
|
+
* Both variants expose the same surface; importers don't care which one
|
|
21
|
+
* they got.
|
|
22
|
+
*
|
|
23
|
+
* # Why static imports?
|
|
24
|
+
*
|
|
25
|
+
* Every RN consumer of `@oxyhq/core` already lists or transitively pulls
|
|
26
|
+
* in `expo-crypto`, `expo-secure-store`, and
|
|
27
|
+
* `@react-native-async-storage/async-storage` (they're stable Expo modules
|
|
28
|
+
* present in `services`, `accounts`, `inbox`, and `test-app`). A static
|
|
29
|
+
* import is what Metro wants to see anyway, and Hermes parses it like any
|
|
30
|
+
* other ES module — no `Function`-constructor parser exotic-mode involved.
|
|
31
|
+
*
|
|
32
|
+
* This is also clearer to debug: Metro fails up-front with a normal
|
|
33
|
+
* unresolved-module error if a consumer is missing a peer dep, instead of
|
|
34
|
+
* a confusing runtime throw the first time a code path that needs the
|
|
35
|
+
* module is exercised.
|
|
36
|
+
*/
|
|
37
|
+
export declare function loadNodeCrypto(): Promise<typeof import('crypto')>;
|
|
38
|
+
export declare function loadExpoCrypto(): Promise<typeof import('expo-crypto')>;
|
|
39
|
+
export declare function loadSecureStore(): Promise<typeof import('expo-secure-store')>;
|
|
40
|
+
type AsyncStorageLike = {
|
|
41
|
+
getItem: (key: string) => Promise<string | null>;
|
|
42
|
+
setItem: (key: string, value: string) => Promise<void>;
|
|
43
|
+
removeItem: (key: string) => Promise<void>;
|
|
44
|
+
};
|
|
45
|
+
export declare function loadAsyncStorage(): Promise<{
|
|
46
|
+
default: AsyncStorageLike;
|
|
47
|
+
}>;
|
|
48
|
+
/**
|
|
49
|
+
* Synchronous random-bytes via `expo-crypto.getRandomBytes`. Available
|
|
50
|
+
* synchronously because `expo-crypto` is statically imported by this file
|
|
51
|
+
* — no async initialization race.
|
|
52
|
+
*/
|
|
53
|
+
export declare function getRandomBytesRN(byteCount: number): Uint8Array;
|
|
54
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxyhq/core",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.14",
|
|
4
4
|
"description": "OxyHQ SDK Foundation — API client, authentication, cryptographic identity, and shared utilities",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -13,24 +13,31 @@
|
|
|
13
13
|
"exports": {
|
|
14
14
|
".": {
|
|
15
15
|
"types": "./dist/types/index.d.ts",
|
|
16
|
+
"react-native": "./dist/esm/index.js",
|
|
16
17
|
"import": "./dist/esm/index.js",
|
|
17
18
|
"require": "./dist/cjs/index.js",
|
|
18
19
|
"default": "./dist/esm/index.js"
|
|
19
20
|
},
|
|
20
21
|
"./crypto": {
|
|
21
22
|
"types": "./dist/types/crypto/index.d.ts",
|
|
23
|
+
"react-native": "./dist/esm/crypto/index.js",
|
|
22
24
|
"import": "./dist/esm/crypto/index.js",
|
|
23
25
|
"require": "./dist/cjs/crypto/index.js",
|
|
24
26
|
"default": "./dist/esm/crypto/index.js"
|
|
25
27
|
},
|
|
26
28
|
"./shared": {
|
|
27
29
|
"types": "./dist/types/shared/index.d.ts",
|
|
30
|
+
"react-native": "./dist/esm/shared/index.js",
|
|
28
31
|
"import": "./dist/esm/shared/index.js",
|
|
29
32
|
"require": "./dist/cjs/shared/index.js",
|
|
30
33
|
"default": "./dist/esm/shared/index.js"
|
|
31
34
|
},
|
|
32
35
|
"./package.json": "./package.json"
|
|
33
36
|
},
|
|
37
|
+
"react-native": {
|
|
38
|
+
"./dist/esm/utils/platformCrypto.js": "./dist/esm/utils/platformCrypto.native.js",
|
|
39
|
+
"./dist/cjs/utils/platformCrypto.js": "./dist/cjs/utils/platformCrypto.native.js"
|
|
40
|
+
},
|
|
34
41
|
"files": [
|
|
35
42
|
"dist",
|
|
36
43
|
"src"
|
|
@@ -62,7 +69,23 @@
|
|
|
62
69
|
"build:types": "tsc -p tsconfig.types.json",
|
|
63
70
|
"clean": "rm -rf dist",
|
|
64
71
|
"typescript": "tsc --noEmit",
|
|
65
|
-
"
|
|
72
|
+
"test": "jest --passWithNoTests",
|
|
73
|
+
"lint": "biome lint --error-on-warnings ./src",
|
|
74
|
+
"release": "rm -rf dist && bun run build && release-it"
|
|
75
|
+
},
|
|
76
|
+
"release-it": {
|
|
77
|
+
"git": {
|
|
78
|
+
"tagName": "@oxyhq/core@${version}",
|
|
79
|
+
"tagAnnotation": "Release @oxyhq/core@${version}",
|
|
80
|
+
"commitMessage": "chore(core): release @oxyhq/core@${version}"
|
|
81
|
+
},
|
|
82
|
+
"github": {
|
|
83
|
+
"release": true,
|
|
84
|
+
"releaseName": "@oxyhq/core@${version}"
|
|
85
|
+
},
|
|
86
|
+
"npm": {
|
|
87
|
+
"publish": true
|
|
88
|
+
}
|
|
66
89
|
},
|
|
67
90
|
"dependencies": {
|
|
68
91
|
"bip39": "^3.1.0",
|
|
@@ -73,11 +96,31 @@
|
|
|
73
96
|
"socket.io-client": "^4.8.1",
|
|
74
97
|
"zod": "^3.25.64"
|
|
75
98
|
},
|
|
99
|
+
"peerDependencies": {
|
|
100
|
+
"@react-native-async-storage/async-storage": "*",
|
|
101
|
+
"expo-crypto": "*",
|
|
102
|
+
"expo-secure-store": "*"
|
|
103
|
+
},
|
|
104
|
+
"peerDependenciesMeta": {
|
|
105
|
+
"@react-native-async-storage/async-storage": {
|
|
106
|
+
"optional": true
|
|
107
|
+
},
|
|
108
|
+
"expo-crypto": {
|
|
109
|
+
"optional": true
|
|
110
|
+
},
|
|
111
|
+
"expo-secure-store": {
|
|
112
|
+
"optional": true
|
|
113
|
+
}
|
|
114
|
+
},
|
|
76
115
|
"devDependencies": {
|
|
77
116
|
"@biomejs/biome": "^1.9.4",
|
|
117
|
+
"@react-native-async-storage/async-storage": "^2.2.0",
|
|
78
118
|
"@types/elliptic": "^6.4.18",
|
|
79
119
|
"@types/invariant": "^2.2.34",
|
|
80
120
|
"@types/node": "^20.19.9",
|
|
121
|
+
"expo-crypto": "~56.0.3",
|
|
122
|
+
"expo-secure-store": "~56.0.4",
|
|
123
|
+
"release-it": "^19.0.6",
|
|
81
124
|
"typescript": "^5.9.2"
|
|
82
125
|
}
|
|
83
126
|
}
|
package/src/CrossDomainAuth.ts
CHANGED
|
@@ -130,7 +130,7 @@ export class CrossDomainAuth {
|
|
|
130
130
|
* Best method - browser-native, no popups, Google-like experience
|
|
131
131
|
*/
|
|
132
132
|
async signInWithFedCM(options: CrossDomainAuthOptions = {}): Promise<SessionLoginResponse> {
|
|
133
|
-
return
|
|
133
|
+
return this.oxyServices.signInWithFedCM({
|
|
134
134
|
context: options.isSignup ? 'signup' : 'signin',
|
|
135
135
|
});
|
|
136
136
|
}
|
|
@@ -141,7 +141,7 @@ export class CrossDomainAuth {
|
|
|
141
141
|
* Good method - preserves app state, no full page reload
|
|
142
142
|
*/
|
|
143
143
|
async signInWithPopup(options: CrossDomainAuthOptions = {}): Promise<SessionLoginResponse> {
|
|
144
|
-
return
|
|
144
|
+
return this.oxyServices.signInWithPopup({
|
|
145
145
|
mode: options.isSignup ? 'signup' : 'login',
|
|
146
146
|
width: options.popupDimensions?.width,
|
|
147
147
|
height: options.popupDimensions?.height,
|
|
@@ -154,7 +154,7 @@ export class CrossDomainAuth {
|
|
|
154
154
|
* Fallback method - works everywhere but loses app state
|
|
155
155
|
*/
|
|
156
156
|
signInWithRedirect(options: CrossDomainAuthOptions = {}): void {
|
|
157
|
-
|
|
157
|
+
this.oxyServices.signInWithRedirect({
|
|
158
158
|
redirectUri: options.redirectUri,
|
|
159
159
|
mode: options.isSignup ? 'signup' : 'login',
|
|
160
160
|
});
|
|
@@ -166,7 +166,7 @@ export class CrossDomainAuth {
|
|
|
166
166
|
* Call this on app startup to check if we're returning from auth redirect
|
|
167
167
|
*/
|
|
168
168
|
handleRedirectCallback(): SessionLoginResponse | null {
|
|
169
|
-
return
|
|
169
|
+
return this.oxyServices.handleAuthCallback();
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
/**
|
|
@@ -181,7 +181,7 @@ export class CrossDomainAuth {
|
|
|
181
181
|
// Try FedCM silent sign-in first (if supported)
|
|
182
182
|
if (this.isFedCMSupported()) {
|
|
183
183
|
try {
|
|
184
|
-
const session = await
|
|
184
|
+
const session = await this.oxyServices.silentSignInWithFedCM();
|
|
185
185
|
if (session) {
|
|
186
186
|
return session;
|
|
187
187
|
}
|
|
@@ -192,7 +192,7 @@ export class CrossDomainAuth {
|
|
|
192
192
|
|
|
193
193
|
// Fallback to iframe-based silent auth
|
|
194
194
|
try {
|
|
195
|
-
return await
|
|
195
|
+
return await this.oxyServices.silentSignIn();
|
|
196
196
|
} catch (error) {
|
|
197
197
|
console.warn('[CrossDomainAuth] Silent sign-in failed:', error);
|
|
198
198
|
return null;
|
|
@@ -205,14 +205,16 @@ export class CrossDomainAuth {
|
|
|
205
205
|
* For redirect method - restores previously authenticated session from localStorage
|
|
206
206
|
*/
|
|
207
207
|
restoreSession(): boolean {
|
|
208
|
-
return
|
|
208
|
+
return this.oxyServices.restoreSession?.() || false;
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
/**
|
|
212
212
|
* Check if FedCM is supported in current browser
|
|
213
213
|
*/
|
|
214
214
|
isFedCMSupported(): boolean {
|
|
215
|
-
|
|
215
|
+
// FedCM support is exposed both as a static and an instance method on
|
|
216
|
+
// OxyServices; the instance method is reliable across mixin composition.
|
|
217
|
+
return this.oxyServices.isFedCMSupported?.() || false;
|
|
216
218
|
}
|
|
217
219
|
|
|
218
220
|
/**
|
|
@@ -263,10 +265,10 @@ export class CrossDomainAuth {
|
|
|
263
265
|
if (restored) {
|
|
264
266
|
// Verify session is still valid by fetching user
|
|
265
267
|
try {
|
|
266
|
-
const user = await
|
|
268
|
+
const user = await this.oxyServices.getCurrentUser();
|
|
267
269
|
if (user) {
|
|
268
270
|
return {
|
|
269
|
-
sessionId:
|
|
271
|
+
sessionId: this.oxyServices.getStoredSessionId?.() || '',
|
|
270
272
|
deviceId: '',
|
|
271
273
|
expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
|
|
272
274
|
user,
|