@multiplatform.one/core 6.0.4 → 6.1.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,45 @@
1
1
  # @multiplatform.one/core
2
2
 
3
+ ## 6.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Point apps at the `make localnet` dev chains by default: Web3Config gains
8
+ `localnet` (prepends the hardhat 31337 dev chain as wagmi's default chain on
9
+ web AND native via a shared `resolveChains`), `localnetRpcUrl` (emulator host
10
+ addresses), and `suiRpcUrl` alongside the existing `solanaRpcUrl`. createApp
11
+ reads WEB3_LOCALNET_ENABLED / WEB3_EVM_RPC / WEB3_SOLANA_RPC / WEB3_SUI_RPC
12
+ from env config.
13
+ - Native auth + authenticated Frappe data end-to-end:
14
+ - keycloak: native Keycloak login via a hand-rolled Better Auth expo flow
15
+ (fetch + expo-web-browser + SecureStore cookie jar — no @better-auth/expo
16
+ client, whose zod import graph dies on Hermes). Real native dist
17
+ (dist/esm/index.native.js) + react-native export condition; new
18
+ getKeycloakBearerToken() for Frappe Bearer auth; native useSession backed
19
+ by a real store; Loading/Authenticated use RN primitives (they mount above
20
+ TamaguiProvider); KeycloakProvider gains betterAuthBaseUrl/expoScheme.
21
+ - frappe: isBrowser() now means "client runtime" (isNative ||
22
+ isWindowDefined) — the tamagui native dist hardcodes isWindowDefined=false,
23
+ which silently disabled the entire sync pipeline (collections never
24
+ fetched) on iOS/Android. Token type widened to string | fn through the
25
+ React layer.
26
+ - core: createApp wires native Frappe requests with Authorization: Bearer
27
+ from better-auth /get-access-token (web stays same-origin cookie mode);
28
+ keycloak config plumbs betterAuthBaseUrl (BETTER_AUTH_BASE_URL, falls back
29
+ to BASE_URL) and expoScheme.
30
+ - (repo auth service, unpublished: exp:// trusted origin in development for
31
+ Expo Go OAuth returns.)
32
+
33
+ ### Patch Changes
34
+
35
+ - Updated dependencies
36
+ - @multiplatform.one/web3@6.1.0
37
+ - @multiplatform.one/i18n@6.1.0
38
+ - @multiplatform.one/logger@6.1.0
39
+ - @multiplatform.one/platform@6.1.0
40
+ - @multiplatform.one/store@6.1.0
41
+ - @multiplatform.one/theme@6.1.0
42
+
3
43
  ## 6.0.4
4
44
 
5
45
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@multiplatform.one/core",
3
- "version": "6.0.4",
3
+ "version": "6.1.0",
4
4
  "description": "Core framework shell, provider composition, and layout factories for multiplatform.one",
5
5
  "keywords": [
6
6
  "app",
@@ -36,12 +36,12 @@
36
36
  "@tanstack/react-form-devtools": "0.2.22",
37
37
  "@tanstack/react-pacer-devtools": "^0.7.0",
38
38
  "react-cookie": "^8.1.2",
39
- "@multiplatform.one/i18n": "6.0.4",
40
- "@multiplatform.one/logger": "6.0.4",
41
- "@multiplatform.one/platform": "6.0.4",
42
- "@multiplatform.one/theme": "6.0.4",
43
- "@multiplatform.one/store": "6.0.4",
44
- "@multiplatform.one/web3": "6.0.4"
39
+ "@multiplatform.one/i18n": "6.1.0",
40
+ "@multiplatform.one/store": "6.1.0",
41
+ "@multiplatform.one/platform": "6.1.0",
42
+ "@multiplatform.one/logger": "6.1.0",
43
+ "@multiplatform.one/theme": "6.1.0",
44
+ "@multiplatform.one/web3": "6.1.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@sentry/react": "^10.51.0",
@@ -57,8 +57,8 @@
57
57
  "react-native-safe-area-context": "~5.7.0",
58
58
  "tamagui": "2.0.0-rc.41",
59
59
  "typescript": "~5.9.3",
60
- "@multiplatform.one/frappe": "6.0.4",
61
- "@multiplatform.one/web3": "6.0.4"
60
+ "@multiplatform.one/web3": "6.1.0",
61
+ "@multiplatform.one/frappe": "6.1.0"
62
62
  },
63
63
  "peerDependencies": {
64
64
  "@sentry/react": "^9.0.0",
@@ -74,10 +74,10 @@
74
74
  "react-native-gesture-handler": ">=2.0.0",
75
75
  "react-native-safe-area-context": ">=4.0.0",
76
76
  "tamagui": "^2.0.0-rc",
77
- "@multiplatform.one/frappe": "6.0.4",
78
- "@multiplatform.one/keycloak": "6.0.4",
79
- "@multiplatform.one/frappe-ui": "6.0.4",
80
- "@multiplatform.one/web3": "6.0.4"
77
+ "@multiplatform.one/frappe": "^6.1.0",
78
+ "@multiplatform.one/keycloak": "^6.1.0",
79
+ "@multiplatform.one/web3": "^6.1.0",
80
+ "@multiplatform.one/frappe-ui": "^6.1.0"
81
81
  },
82
82
  "peerDependenciesMeta": {
83
83
  "@multiplatform.one/frappe": {
@@ -58,6 +58,12 @@ export interface KeycloakConfig {
58
58
  iframeSso?: boolean;
59
59
  loginRedirectUri?: string;
60
60
  messageHandlerKeys?: string[];
61
+ /** Better Auth server base URL (native sign-in). When omitted, reads
62
+ * BETTER_AUTH_BASE_URL, then falls back to BASE_URL (the app server proxies
63
+ * /api/auth). */
64
+ betterAuthBaseUrl?: string;
65
+ /** App scheme for the Expo auth-session redirect (native). */
66
+ expoScheme?: string;
61
67
  }
62
68
 
63
69
  export interface FrappeConfig {
@@ -71,7 +77,7 @@ export interface FrappeConfig {
71
77
  socketPort?: number;
72
78
  auth?: {
73
79
  useToken?: boolean;
74
- token?: string;
80
+ token?: string | (() => string | Promise<string>);
75
81
  type?: string;
76
82
  };
77
83
  }
@@ -85,9 +91,17 @@ export interface Web3AppConfig {
85
91
  appUrl?: string;
86
92
  appIcon?: string;
87
93
  enableTestnets?: boolean;
88
- /** Native: URL serving the wallet WebView HTML (preferred over the inline string). */
94
+ /** Add the local dev chain (`make localnet`). When omitted, reads WEB3_LOCALNET_ENABLED. */
95
+ localnet?: boolean;
96
+ /** Local EVM JSON-RPC endpoint for localnet. When omitted, reads WEB3_EVM_RPC. */
97
+ localnetRpcUrl?: string;
98
+ /** Solana JSON-RPC endpoint. When omitted, reads WEB3_SOLANA_RPC. */
99
+ solanaRpcUrl?: string;
100
+ /** Sui JSON-RPC endpoint. When omitted, reads WEB3_SUI_RPC. */
101
+ suiRpcUrl?: string;
102
+ /** Native: URL serving the wallet WebView HTML. When omitted, reads WEB3_WEBVIEW_URL. */
89
103
  webViewUrl?: string;
90
- /** E2E only (native): route connect through the in-WebView mock wallet. */
104
+ /** E2E only (native): route connect through the in-WebView mock wallet. When omitted, reads WEB3_MOCK_WALLET. */
91
105
  mockWallet?: boolean;
92
106
  }
93
107
 
@@ -186,8 +200,12 @@ export function createApp(appConfig: CreateAppConfig) {
186
200
  (isWeb && typeof window !== "undefined" ? window.location.origin : ""),
187
201
  appIcon: cfg.appIcon,
188
202
  enableTestnets: testnetsEnabled,
189
- webViewUrl: cfg.webViewUrl,
190
- mockWallet: cfg.mockWallet,
203
+ localnet: cfg.localnet ?? config.get("WEB3_LOCALNET_ENABLED") === "1",
204
+ localnetRpcUrl: cfg.localnetRpcUrl || config.get("WEB3_EVM_RPC") || undefined,
205
+ solanaRpcUrl: cfg.solanaRpcUrl || config.get("WEB3_SOLANA_RPC") || undefined,
206
+ suiRpcUrl: cfg.suiRpcUrl || config.get("WEB3_SUI_RPC") || undefined,
207
+ webViewUrl: cfg.webViewUrl || config.get("WEB3_WEBVIEW_URL") || undefined,
208
+ mockWallet: cfg.mockWallet ?? config.get("WEB3_MOCK_WALLET") === "1",
191
209
  }}
192
210
  >
193
211
  {children}
@@ -216,6 +234,8 @@ export function createApp(appConfig: CreateAppConfig) {
216
234
  iframeSso?: boolean;
217
235
  loginRedirectUri?: string;
218
236
  messageHandlerKeys?: string[];
237
+ betterAuthBaseUrl?: string;
238
+ expoScheme?: string;
219
239
  }>
220
240
  >,
221
241
  };
@@ -237,6 +257,13 @@ export function createApp(appConfig: CreateAppConfig) {
237
257
  iframeSso={cfg.iframeSso}
238
258
  loginRedirectUri={cfg.loginRedirectUri}
239
259
  messageHandlerKeys={cfg.messageHandlerKeys || []}
260
+ betterAuthBaseUrl={
261
+ cfg.betterAuthBaseUrl ||
262
+ config.get("BETTER_AUTH_BASE_URL") ||
263
+ config.get("BASE_URL") ||
264
+ undefined
265
+ }
266
+ expoScheme={cfg.expoScheme}
240
267
  >
241
268
  {children}
242
269
  </LazyKeycloakProvider>
@@ -264,8 +291,29 @@ export function createApp(appConfig: CreateAppConfig) {
264
291
  const socketPort =
265
292
  cfg.socketPort ?? (Number(config.get("FRAPPE_SOCKETIO_PORT")) || undefined);
266
293
 
294
+ // Auth transport differs by platform. Web is same-origin with the bench
295
+ // (:8000 proxy), so the better-auth account cookie authenticates Frappe
296
+ // requests automatically (the bench's frappe_keycloak hook decrypts it).
297
+ // Native requests can't carry those cookies (they live in the SecureStore
298
+ // jar), so the HttpClient sends `Authorization: Bearer <keycloak access
299
+ // token>` instead, fetched lazily from better-auth's /get-access-token
300
+ // (which also refreshes server-side). When signed out the getter resolves
301
+ // undefined and requests fall back to guest.
302
+ const auth =
303
+ cfg.auth ??
304
+ (!isWeb && appConfig.keycloak
305
+ ? {
306
+ useToken: true,
307
+ type: "Bearer",
308
+ token: async () => {
309
+ const mod = await import("@multiplatform.one/keycloak");
310
+ return (await mod.getKeycloakBearerToken()) || "";
311
+ },
312
+ }
313
+ : undefined);
314
+
267
315
  return (
268
- <FrappeProvider baseURL={baseURL} socketPort={socketPort} auth={cfg.auth}>
316
+ <FrappeProvider baseURL={baseURL} socketPort={socketPort} auth={auth}>
269
317
  {children}
270
318
  </FrappeProvider>
271
319
  );