@oxy.so/protocol 1.1.0 → 1.1.1
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/platform/crypto.js +6 -10
- package/dist/cjs/platform/crypto.native.js +14 -46
- package/dist/cjs/platform/optionalPeer.js +22 -0
- package/dist/cjs/platform/random.js +18 -0
- package/dist/cjs/platform/random.native.js +52 -0
- package/dist/cjs/random.js +25 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/platform/crypto.js +4 -9
- package/dist/esm/platform/crypto.native.js +10 -43
- package/dist/esm/platform/optionalPeer.js +19 -0
- package/dist/esm/platform/random.js +15 -0
- package/dist/esm/platform/random.native.js +48 -0
- package/dist/esm/random.js +19 -0
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/platform/crypto.d.ts +1 -7
- package/dist/types/platform/crypto.native.d.ts +2 -10
- package/dist/types/platform/optionalPeer.d.ts +9 -0
- package/dist/types/platform/random.d.ts +13 -0
- package/dist/types/platform/random.native.d.ts +33 -0
- package/dist/types/random.d.ts +19 -0
- package/package.json +20 -3
- package/src/__tests__/randomEntry.test.ts +107 -0
- package/src/platform/crypto.native.ts +10 -48
- package/src/platform/crypto.ts +4 -9
- package/src/platform/optionalPeer.ts +23 -0
- package/src/platform/random.native.ts +56 -0
- package/src/platform/random.ts +18 -0
- package/src/random.ts +20 -0
|
@@ -106,11 +106,11 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
106
106
|
};
|
|
107
107
|
})();
|
|
108
108
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
109
|
+
exports.getRandomBytesRN = void 0;
|
|
109
110
|
exports.loadNodeCrypto = loadNodeCrypto;
|
|
110
111
|
exports.loadExpoCrypto = loadExpoCrypto;
|
|
111
112
|
exports.loadSecureStore = loadSecureStore;
|
|
112
113
|
exports.loadAsyncStorage = loadAsyncStorage;
|
|
113
|
-
exports.getRandomBytesRN = getRandomBytesRN;
|
|
114
114
|
exports.loadSharedIdentityBridge = loadSharedIdentityBridge;
|
|
115
115
|
const platform_1 = require("./platform");
|
|
116
116
|
// ---------------------------------------------------------------------------
|
|
@@ -164,15 +164,11 @@ async function loadSecureStore() {
|
|
|
164
164
|
async function loadAsyncStorage() {
|
|
165
165
|
throw notReactNativeError('@react-native-async-storage/async-storage');
|
|
166
166
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
*/
|
|
173
|
-
function getRandomBytesRN(_byteCount) {
|
|
174
|
-
throw notReactNativeError('expo-crypto.getRandomBytes (sync)');
|
|
175
|
-
}
|
|
167
|
+
// Synchronous random bytes live in the dependency-free `./random` module so
|
|
168
|
+
// `@oxy.so/core`'s crypto polyfill can load them through the
|
|
169
|
+
// `@oxy.so/protocol/random` entry without evaluating any crypto library first.
|
|
170
|
+
var random_1 = require("./random");
|
|
171
|
+
Object.defineProperty(exports, "getRandomBytesRN", { enumerable: true, get: function () { return random_1.getRandomBytesRN; } });
|
|
176
172
|
// ---------------------------------------------------------------------------
|
|
177
173
|
// Shared identity bridge — `@oxy.so/expo-oxy-identity` (native-only).
|
|
178
174
|
//
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* Those three RN modules are declared OPTIONAL peer dependencies in
|
|
26
26
|
* `package.json`. A static `import` contradicts that: an optional peer that is
|
|
27
27
|
* omitted does not degrade, it fails to RESOLVE, and Metro aborts the whole
|
|
28
|
-
* bundle. Because `@oxy.so/core`
|
|
28
|
+
* bundle. Because `@oxy.so/core` imports `@oxy.so/protocol`
|
|
29
29
|
* from its root entry, this file is in the eager graph of EVERY React Native
|
|
30
30
|
* app on `@oxy.so/core` — so a single undeclared optional peer broke the native
|
|
31
31
|
* bundle of every app that did not happen to install it, with a resolution
|
|
@@ -53,21 +53,15 @@
|
|
|
53
53
|
* so it stays a plain static import.
|
|
54
54
|
*/
|
|
55
55
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
56
|
+
exports.getRandomBytesRN = void 0;
|
|
56
57
|
exports.loadNodeCrypto = loadNodeCrypto;
|
|
57
58
|
exports.loadExpoCrypto = loadExpoCrypto;
|
|
58
59
|
exports.loadSecureStore = loadSecureStore;
|
|
59
60
|
exports.loadAsyncStorage = loadAsyncStorage;
|
|
60
|
-
exports.getRandomBytesRN = getRandomBytesRN;
|
|
61
61
|
exports.loadSharedIdentityBridge = loadSharedIdentityBridge;
|
|
62
62
|
const expo_modules_core_1 = require("expo-modules-core");
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
expoCryptoModule = require('expo-crypto');
|
|
67
|
-
}
|
|
68
|
-
catch (error) {
|
|
69
|
-
expoCryptoError = error;
|
|
70
|
-
}
|
|
63
|
+
const optionalPeer_1 = require("./optionalPeer");
|
|
64
|
+
const random_native_1 = require("./random.native");
|
|
71
65
|
let secureStoreModule = null;
|
|
72
66
|
let secureStoreError;
|
|
73
67
|
try {
|
|
@@ -88,22 +82,6 @@ try {
|
|
|
88
82
|
catch (error) {
|
|
89
83
|
asyncStorageError = error;
|
|
90
84
|
}
|
|
91
|
-
/**
|
|
92
|
-
* Actionable error for a missing optional peer. Carries the underlying Metro
|
|
93
|
-
* resolution message so the failure is never silent — the `catch` above only
|
|
94
|
-
* defers the report to the point where the capability is actually needed.
|
|
95
|
-
*/
|
|
96
|
-
function missingOptionalPeerError(packageName, capability, cause) {
|
|
97
|
-
const sentences = [
|
|
98
|
-
`[oxy.protocol.crypto] '${packageName}' is not installed, so ${capability} is unavailable in this app.`,
|
|
99
|
-
'It is an optional peer dependency of @oxy.so/protocol that the React Native runtime needs —',
|
|
100
|
-
`install it with \`npx expo install ${packageName}\`.`,
|
|
101
|
-
];
|
|
102
|
-
if (cause instanceof Error) {
|
|
103
|
-
sentences.push(`Underlying error: ${cause.message}`);
|
|
104
|
-
}
|
|
105
|
-
return new Error(sentences.join(' '));
|
|
106
|
-
}
|
|
107
85
|
// ---------------------------------------------------------------------------
|
|
108
86
|
// Node `crypto` — never available in RN.
|
|
109
87
|
// ---------------------------------------------------------------------------
|
|
@@ -124,17 +102,14 @@ async function loadNodeCrypto() {
|
|
|
124
102
|
// their compilation (see expoTypes.ts).
|
|
125
103
|
// ---------------------------------------------------------------------------
|
|
126
104
|
async function loadExpoCrypto() {
|
|
127
|
-
|
|
128
|
-
throw missingOptionalPeerError('expo-crypto', 'React Native cryptography', expoCryptoError);
|
|
129
|
-
}
|
|
130
|
-
return expoCryptoModule;
|
|
105
|
+
return (0, random_native_1.requireExpoCrypto)('React Native cryptography');
|
|
131
106
|
}
|
|
132
107
|
// ---------------------------------------------------------------------------
|
|
133
108
|
// expo-secure-store — RN keychain / keystore.
|
|
134
109
|
// ---------------------------------------------------------------------------
|
|
135
110
|
async function loadSecureStore() {
|
|
136
111
|
if (!secureStoreModule) {
|
|
137
|
-
throw missingOptionalPeerError('expo-secure-store', 'on-device identity storage', secureStoreError);
|
|
112
|
+
throw (0, optionalPeer_1.missingOptionalPeerError)('expo-secure-store', 'on-device identity storage', secureStoreError);
|
|
138
113
|
}
|
|
139
114
|
return secureStoreModule;
|
|
140
115
|
}
|
|
@@ -143,27 +118,20 @@ async function loadSecureStore() {
|
|
|
143
118
|
// ---------------------------------------------------------------------------
|
|
144
119
|
async function loadAsyncStorage() {
|
|
145
120
|
if (!asyncStorageModule) {
|
|
146
|
-
throw missingOptionalPeerError('@react-native-async-storage/async-storage', 'device/session persistence', asyncStorageError);
|
|
121
|
+
throw (0, optionalPeer_1.missingOptionalPeerError)('@react-native-async-storage/async-storage', 'device/session persistence', asyncStorageError);
|
|
147
122
|
}
|
|
148
123
|
// Mirror the shape callers historically used (`module.default.<method>`)
|
|
149
124
|
// so the call sites don't have to know whether the underlying module
|
|
150
125
|
// ships ESM or CJS-with-default.
|
|
151
126
|
return { default: asyncStorageModule };
|
|
152
127
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
*/
|
|
161
|
-
function getRandomBytesRN(byteCount) {
|
|
162
|
-
if (!expoCryptoModule) {
|
|
163
|
-
throw missingOptionalPeerError('expo-crypto', 'the React Native CSPRNG (crypto.getRandomValues)', expoCryptoError);
|
|
164
|
-
}
|
|
165
|
-
return expoCryptoModule.getRandomBytes(byteCount);
|
|
166
|
-
}
|
|
128
|
+
// Synchronous random bytes (and the single `expo-crypto` resolution) live in
|
|
129
|
+
// the dependency-free `./random.native` module, so `@oxy.so/core`'s crypto
|
|
130
|
+
// polyfill can load them through `@oxy.so/protocol/random` without evaluating
|
|
131
|
+
// any crypto library first. The explicit `.native` specifier keeps tsc and
|
|
132
|
+
// Metro pointed at the same file.
|
|
133
|
+
var random_native_2 = require("./random.native");
|
|
134
|
+
Object.defineProperty(exports, "getRandomBytesRN", { enumerable: true, get: function () { return random_native_2.getRandomBytesRN; } });
|
|
167
135
|
// ---------------------------------------------------------------------------
|
|
168
136
|
// Shared identity bridge — `@oxy.so/expo-oxy-identity` (native-only, OPTIONAL).
|
|
169
137
|
//
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.missingOptionalPeerError = missingOptionalPeerError;
|
|
4
|
+
/**
|
|
5
|
+
* Actionable error for a missing optional React Native peer.
|
|
6
|
+
*
|
|
7
|
+
* Shared by the React Native platform variants (`crypto.native.ts`,
|
|
8
|
+
* `random.native.ts`). It carries the underlying Metro resolution message so
|
|
9
|
+
* the failure is never silent: the variants' `try { require(...) } catch` only
|
|
10
|
+
* defers the report to the point where the capability is actually used.
|
|
11
|
+
*/
|
|
12
|
+
function missingOptionalPeerError(packageName, capability, cause) {
|
|
13
|
+
const sentences = [
|
|
14
|
+
`[oxy.protocol.crypto] '${packageName}' is not installed, so ${capability} is unavailable in this app.`,
|
|
15
|
+
'It is an optional peer dependency of @oxy.so/protocol that the React Native runtime needs —',
|
|
16
|
+
`install it with \`npx expo install ${packageName}\`.`,
|
|
17
|
+
];
|
|
18
|
+
if (cause instanceof Error) {
|
|
19
|
+
sentences.push(`Underlying error: ${cause.message}`);
|
|
20
|
+
}
|
|
21
|
+
return new Error(sentences.join(' '));
|
|
22
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Synchronous CSPRNG source — default variant (Node.js, browsers, bundlers).
|
|
4
|
+
*
|
|
5
|
+
* Companion to `./random.native.ts`, which Metro substitutes on iOS / Android.
|
|
6
|
+
* Node and browsers own a native CSPRNG (`node:crypto`, `globalThis.crypto`),
|
|
7
|
+
* so `getRandomBytesRN` only exists here to keep both variants' surfaces
|
|
8
|
+
* identical, and throws if anything reaches it outside React Native.
|
|
9
|
+
*
|
|
10
|
+
* Like its sibling, this module imports nothing: it is part of the
|
|
11
|
+
* `@oxy.so/protocol/random` entry that `@oxy.so/core`'s crypto polyfill loads
|
|
12
|
+
* BEFORE any crypto library is evaluated.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.getRandomBytesRN = getRandomBytesRN;
|
|
16
|
+
function getRandomBytesRN(_byteCount) {
|
|
17
|
+
throw new Error("[oxy.protocol.crypto] Tried to load 'expo-crypto.getRandomBytes (sync)' outside React Native. This module is only available in a React Native runtime; bundling routed this consumer to the default (Node/web) variant. This indicates a missing platform gate (`isReactNative()`) in the calling code.");
|
|
18
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Synchronous CSPRNG source — React Native variant.
|
|
4
|
+
*
|
|
5
|
+
* Companion to `./random.ts`; Metro substitutes this file on iOS / Android
|
|
6
|
+
* (see `./crypto.ts` for how the `.native` split works).
|
|
7
|
+
*
|
|
8
|
+
* This module is deliberately tiny and imports NOTHING but `expo-crypto`: it
|
|
9
|
+
* backs `@oxy.so/core`'s `globalThis.crypto.getRandomValues` polyfill, which
|
|
10
|
+
* must be fully installed before any module that captures `globalThis.crypto`
|
|
11
|
+
* at evaluation time (`@noble/hashes` 1.x's `crypto.js` does exactly that) is
|
|
12
|
+
* evaluated. Reaching a crypto library from here would let that library
|
|
13
|
+
* capture the missing global first and throw
|
|
14
|
+
* `crypto.getRandomValues must be defined` for the lifetime of the app.
|
|
15
|
+
*
|
|
16
|
+
* `expo-crypto` is an OPTIONAL peer, so it is resolved with a string-literal
|
|
17
|
+
* `require` inside a `try` (Metro's optional-dependency form; see
|
|
18
|
+
* `./crypto.native.ts`), and the load stays synchronous because
|
|
19
|
+
* `getRandomValues` cannot await.
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.requireExpoCrypto = requireExpoCrypto;
|
|
23
|
+
exports.getRandomBytesRN = getRandomBytesRN;
|
|
24
|
+
const optionalPeer_1 = require("./optionalPeer");
|
|
25
|
+
let expoCryptoModule = null;
|
|
26
|
+
let expoCryptoError;
|
|
27
|
+
try {
|
|
28
|
+
expoCryptoModule = require('expo-crypto');
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
expoCryptoError = error;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The resolved `expo-crypto` module, or an actionable error naming the missing
|
|
35
|
+
* peer and the capability that needed it. Shared with `./crypto.native.ts` so
|
|
36
|
+
* the optional peer is resolved in exactly one place.
|
|
37
|
+
*/
|
|
38
|
+
function requireExpoCrypto(capability) {
|
|
39
|
+
if (!expoCryptoModule) {
|
|
40
|
+
throw (0, optionalPeer_1.missingOptionalPeerError)('expo-crypto', capability, expoCryptoError);
|
|
41
|
+
}
|
|
42
|
+
return expoCryptoModule;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Synchronous random bytes via `expo-crypto.getRandomBytes`.
|
|
46
|
+
*
|
|
47
|
+
* Synchronous by contract: `@oxy.so/core`'s crypto polyfill uses this to back
|
|
48
|
+
* `globalThis.crypto.getRandomValues`, which cannot await.
|
|
49
|
+
*/
|
|
50
|
+
function getRandomBytesRN(byteCount) {
|
|
51
|
+
return requireExpoCrypto('the React Native CSPRNG (crypto.getRandomValues)').getRandomBytes(byteCount);
|
|
52
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `@oxy.so/protocol/random` — the platform randomness source, and nothing else.
|
|
4
|
+
*
|
|
5
|
+
* `@oxy.so/core`'s crypto polyfill installs `globalThis.crypto.getRandomValues`
|
|
6
|
+
* on hosts that lack it (React Native / Hermes). `@noble/hashes` 1.x captures
|
|
7
|
+
* `globalThis.crypto` ONCE, when its `crypto.js` is evaluated, so the polyfill
|
|
8
|
+
* has to be installed before any `@noble/*` module is evaluated. ES imports are
|
|
9
|
+
* evaluated before the importing module's body, so whatever the polyfill
|
|
10
|
+
* imports is evaluated first: importing the ROOT entry (which reaches
|
|
11
|
+
* `@noble/curves` through the envelope signer) let noble capture `undefined`
|
|
12
|
+
* and broke identity creation on Android.
|
|
13
|
+
*
|
|
14
|
+
* This entry therefore reaches no crypto library, no `@oxy.so/*` package and no
|
|
15
|
+
* third-party module other than the optional `expo-crypto` peer (RN variant
|
|
16
|
+
* only). `src/__tests__/randomEntry.test.ts` walks its module graph to keep it
|
|
17
|
+
* that way.
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.getRandomBytesRN = exports.isReactNative = exports.isNodeJS = void 0;
|
|
21
|
+
var platform_1 = require("./platform/platform");
|
|
22
|
+
Object.defineProperty(exports, "isNodeJS", { enumerable: true, get: function () { return platform_1.isNodeJS; } });
|
|
23
|
+
Object.defineProperty(exports, "isReactNative", { enumerable: true, get: function () { return platform_1.isReactNative; } });
|
|
24
|
+
var random_1 = require("./platform/random");
|
|
25
|
+
Object.defineProperty(exports, "getRandomBytesRN", { enumerable: true, get: function () { return random_1.getRandomBytesRN; } });
|