@alien_org/react 0.2.0 → 0.2.2

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/index.cjs CHANGED
@@ -4,6 +4,7 @@ let react = require("react");
4
4
  let react_jsx_runtime = require("react/jsx-runtime");
5
5
 
6
6
  //#region src/context.tsx
7
+ const useIsomorphicLayoutEffect$1 = typeof window !== "undefined" ? react.useLayoutEffect : react.useEffect;
7
8
  const AlienContext = (0, react.createContext)(null);
8
9
  /**
9
10
  * Provider component that initializes the Alien miniapp context.
@@ -22,21 +23,33 @@ const AlienContext = (0, react.createContext)(null);
22
23
  * }
23
24
  * ```
24
25
  */
25
- function AlienProvider({ children }) {
26
- const value = (0, react.useMemo)(() => {
26
+ function AlienProvider({ children, autoReady = true }) {
27
+ const readySent = (0, react.useRef)(false);
28
+ const ready = (0, react.useCallback)(() => {
29
+ if (readySent.current) return;
30
+ readySent.current = true;
31
+ if ((0, _alien_org_bridge.isBridgeAvailable)()) (0, _alien_org_bridge.send)("app:ready", {});
32
+ }, []);
33
+ const [value, setValue] = (0, react.useState)(() => ({
34
+ authToken: void 0,
35
+ contractVersion: void 0,
36
+ isBridgeAvailable: false,
37
+ ready
38
+ }));
39
+ useIsomorphicLayoutEffect$1(() => {
27
40
  const launchParams = (0, _alien_org_bridge.getLaunchParams)();
28
- return {
41
+ const bridgeAvailable = (0, _alien_org_bridge.isBridgeAvailable)();
42
+ setValue({
29
43
  authToken: launchParams?.authToken,
30
44
  contractVersion: launchParams?.contractVersion,
31
- isBridgeAvailable: (0, _alien_org_bridge.isBridgeAvailable)()
32
- };
33
- }, []);
34
- (0, react.useEffect)(() => {
35
- if (!value.isBridgeAvailable) console.warn("[@alien_org/react] Bridge is not available. Running in dev mode? The SDK will handle errors gracefully, but bridge communication will not work.");
36
- }, [value.isBridgeAvailable]);
45
+ isBridgeAvailable: bridgeAvailable,
46
+ ready
47
+ });
48
+ if (!bridgeAvailable) console.warn("[@alien_org/react] Bridge is not available. Running in dev mode? The SDK will handle errors gracefully, but bridge communication will not work.");
49
+ }, [ready]);
37
50
  (0, react.useEffect)(() => {
38
- if (value.isBridgeAvailable) (0, _alien_org_bridge.send)("app:ready", {});
39
- }, [value.isBridgeAvailable]);
51
+ if (autoReady) ready();
52
+ }, [autoReady, ready]);
40
53
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AlienContext.Provider, {
41
54
  value,
42
55
  children
@@ -252,6 +265,7 @@ function useIsMethodSupported(method) {
252
265
 
253
266
  //#endregion
254
267
  //#region src/hooks/useLaunchParams.ts
268
+ const useIsomorphicLayoutEffect = typeof window !== "undefined" ? react.useLayoutEffect : react.useEffect;
255
269
  /**
256
270
  * Hook to get launch params.
257
271
  * Returns undefined if params unavailable (use mockLaunchParamsForDev in dev).
@@ -272,7 +286,11 @@ function useIsMethodSupported(method) {
272
286
  * ```
273
287
  */
274
288
  function useLaunchParams() {
275
- return (0, react.useMemo)(() => (0, _alien_org_bridge.getLaunchParams)(), []);
289
+ const [params, setParams] = (0, react.useState)(void 0);
290
+ useIsomorphicLayoutEffect(() => {
291
+ setParams((0, _alien_org_bridge.getLaunchParams)());
292
+ }, []);
293
+ return params;
276
294
  }
277
295
 
278
296
  //#endregion
package/dist/index.d.cts CHANGED
@@ -250,8 +250,9 @@ interface Methods {
250
250
  * Optional display fields (`title`, `caption`, `iconUrl`, `quantity`)
251
251
  * are shown on the payment approval screen.
252
252
  *
253
- * Set `test: true` for test mode - no real payment is made, but webhooks
254
- * are fired with `test: true` flag. Use for development and testing.
253
+ * Set `test` to a scenario string (e.g. `'paid'`, `'error:insufficient_balance'`)
254
+ * for test mode - no real payment is made, but the specified scenario is
255
+ * simulated. Use for development and testing.
255
256
  *
256
257
  * @since 0.1.1
257
258
  * @schema
@@ -317,7 +318,7 @@ interface Methods {
317
318
  *
318
319
  * | Scenario | Client | Webhook |
319
320
  * |----------|--------|---------|
320
- * | `true` / `'paid'` | `paid` | `finalized` |
321
+ * | `'paid'` | `paid` | `finalized` |
321
322
  * | `'paid:failed'` | `paid` | `failed` |
322
323
  * | `'cancelled'` | `cancelled` | none |
323
324
  * | `'error:*'` | `failed` | none |
@@ -343,7 +344,7 @@ interface Methods {
343
344
  * @since 0.1.1
344
345
  * @schema
345
346
  */
346
- test?: boolean | PaymentTestScenario;
347
+ test?: PaymentTestScenario;
347
348
  }>>;
348
349
  /**
349
350
  * Write text to the system clipboard.
@@ -525,9 +526,45 @@ interface AlienContextValue {
525
526
  * Whether the bridge is available (running inside Alien App).
526
527
  */
527
528
  isBridgeAvailable: boolean;
529
+ /**
530
+ * Manually signal to the host app that the miniapp is ready.
531
+ * Only needed when `autoReady` is set to `false`.
532
+ * Safe to call multiple times — only the first call sends the signal.
533
+ */
534
+ ready: () => void;
528
535
  }
529
536
  interface AlienProviderProps {
530
537
  children: ReactNode;
538
+ /**
539
+ * Whether to automatically send `app:ready` when the provider mounts.
540
+ * Defaults to `true`.
541
+ *
542
+ * Set to `false` if you need to defer the ready signal (e.g., after
543
+ * fetching initial data), then call `ready()` from `useAlien()` when done.
544
+ *
545
+ * @default true
546
+ *
547
+ * @example
548
+ * ```tsx
549
+ * // Auto (default) — fires immediately on mount
550
+ * <AlienProvider>
551
+ * <App />
552
+ * </AlienProvider>
553
+ *
554
+ * // Manual — fire when you're ready
555
+ * <AlienProvider autoReady={false}>
556
+ * <App />
557
+ * </AlienProvider>
558
+ *
559
+ * function App() {
560
+ * const { ready } = useAlien();
561
+ * useEffect(() => {
562
+ * fetchData().then(() => ready());
563
+ * }, []);
564
+ * }
565
+ * ```
566
+ */
567
+ autoReady?: boolean;
531
568
  }
532
569
  /**
533
570
  * Provider component that initializes the Alien miniapp context.
@@ -547,7 +584,8 @@ interface AlienProviderProps {
547
584
  * ```
548
585
  */
549
586
  declare function AlienProvider({
550
- children
587
+ children,
588
+ autoReady
551
589
  }: AlienProviderProps): ReactNode;
552
590
  //#endregion
553
591
  //#region src/errors.d.ts
package/dist/index.d.mts CHANGED
@@ -250,8 +250,9 @@ interface Methods {
250
250
  * Optional display fields (`title`, `caption`, `iconUrl`, `quantity`)
251
251
  * are shown on the payment approval screen.
252
252
  *
253
- * Set `test: true` for test mode - no real payment is made, but webhooks
254
- * are fired with `test: true` flag. Use for development and testing.
253
+ * Set `test` to a scenario string (e.g. `'paid'`, `'error:insufficient_balance'`)
254
+ * for test mode - no real payment is made, but the specified scenario is
255
+ * simulated. Use for development and testing.
255
256
  *
256
257
  * @since 0.1.1
257
258
  * @schema
@@ -317,7 +318,7 @@ interface Methods {
317
318
  *
318
319
  * | Scenario | Client | Webhook |
319
320
  * |----------|--------|---------|
320
- * | `true` / `'paid'` | `paid` | `finalized` |
321
+ * | `'paid'` | `paid` | `finalized` |
321
322
  * | `'paid:failed'` | `paid` | `failed` |
322
323
  * | `'cancelled'` | `cancelled` | none |
323
324
  * | `'error:*'` | `failed` | none |
@@ -343,7 +344,7 @@ interface Methods {
343
344
  * @since 0.1.1
344
345
  * @schema
345
346
  */
346
- test?: boolean | PaymentTestScenario;
347
+ test?: PaymentTestScenario;
347
348
  }>>;
348
349
  /**
349
350
  * Write text to the system clipboard.
@@ -525,9 +526,45 @@ interface AlienContextValue {
525
526
  * Whether the bridge is available (running inside Alien App).
526
527
  */
527
528
  isBridgeAvailable: boolean;
529
+ /**
530
+ * Manually signal to the host app that the miniapp is ready.
531
+ * Only needed when `autoReady` is set to `false`.
532
+ * Safe to call multiple times — only the first call sends the signal.
533
+ */
534
+ ready: () => void;
528
535
  }
529
536
  interface AlienProviderProps {
530
537
  children: ReactNode;
538
+ /**
539
+ * Whether to automatically send `app:ready` when the provider mounts.
540
+ * Defaults to `true`.
541
+ *
542
+ * Set to `false` if you need to defer the ready signal (e.g., after
543
+ * fetching initial data), then call `ready()` from `useAlien()` when done.
544
+ *
545
+ * @default true
546
+ *
547
+ * @example
548
+ * ```tsx
549
+ * // Auto (default) — fires immediately on mount
550
+ * <AlienProvider>
551
+ * <App />
552
+ * </AlienProvider>
553
+ *
554
+ * // Manual — fire when you're ready
555
+ * <AlienProvider autoReady={false}>
556
+ * <App />
557
+ * </AlienProvider>
558
+ *
559
+ * function App() {
560
+ * const { ready } = useAlien();
561
+ * useEffect(() => {
562
+ * fetchData().then(() => ready());
563
+ * }, []);
564
+ * }
565
+ * ```
566
+ */
567
+ autoReady?: boolean;
531
568
  }
532
569
  /**
533
570
  * Provider component that initializes the Alien miniapp context.
@@ -547,7 +584,8 @@ interface AlienProviderProps {
547
584
  * ```
548
585
  */
549
586
  declare function AlienProvider({
550
- children
587
+ children,
588
+ autoReady
551
589
  }: AlienProviderProps): ReactNode;
552
590
  //#endregion
553
591
  //#region src/errors.d.ts
package/dist/index.mjs CHANGED
@@ -1,9 +1,10 @@
1
1
  import { BridgeError, BridgeTimeoutError, BridgeUnavailableError, BridgeWindowUnavailableError, getLaunchParams, isBridgeAvailable, on, request, send, send as send$1 } from "@alien_org/bridge";
2
2
  import { getMethodMinVersion, getMethodMinVersion as getMethodMinVersion$1, isMethodSupported, isMethodSupported as isMethodSupported$1 } from "@alien_org/contract";
3
- import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
3
+ import { createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
 
6
6
  //#region src/context.tsx
7
+ const useIsomorphicLayoutEffect$1 = typeof window !== "undefined" ? useLayoutEffect : useEffect;
7
8
  const AlienContext = createContext(null);
8
9
  /**
9
10
  * Provider component that initializes the Alien miniapp context.
@@ -22,21 +23,33 @@ const AlienContext = createContext(null);
22
23
  * }
23
24
  * ```
24
25
  */
25
- function AlienProvider({ children }) {
26
- const value = useMemo(() => {
26
+ function AlienProvider({ children, autoReady = true }) {
27
+ const readySent = useRef(false);
28
+ const ready = useCallback(() => {
29
+ if (readySent.current) return;
30
+ readySent.current = true;
31
+ if (isBridgeAvailable()) send$1("app:ready", {});
32
+ }, []);
33
+ const [value, setValue] = useState(() => ({
34
+ authToken: void 0,
35
+ contractVersion: void 0,
36
+ isBridgeAvailable: false,
37
+ ready
38
+ }));
39
+ useIsomorphicLayoutEffect$1(() => {
27
40
  const launchParams = getLaunchParams();
28
- return {
41
+ const bridgeAvailable = isBridgeAvailable();
42
+ setValue({
29
43
  authToken: launchParams?.authToken,
30
44
  contractVersion: launchParams?.contractVersion,
31
- isBridgeAvailable: isBridgeAvailable()
32
- };
33
- }, []);
34
- useEffect(() => {
35
- if (!value.isBridgeAvailable) console.warn("[@alien_org/react] Bridge is not available. Running in dev mode? The SDK will handle errors gracefully, but bridge communication will not work.");
36
- }, [value.isBridgeAvailable]);
45
+ isBridgeAvailable: bridgeAvailable,
46
+ ready
47
+ });
48
+ if (!bridgeAvailable) console.warn("[@alien_org/react] Bridge is not available. Running in dev mode? The SDK will handle errors gracefully, but bridge communication will not work.");
49
+ }, [ready]);
37
50
  useEffect(() => {
38
- if (value.isBridgeAvailable) send$1("app:ready", {});
39
- }, [value.isBridgeAvailable]);
51
+ if (autoReady) ready();
52
+ }, [autoReady, ready]);
40
53
  return /* @__PURE__ */ jsx(AlienContext.Provider, {
41
54
  value,
42
55
  children
@@ -252,6 +265,7 @@ function useIsMethodSupported(method) {
252
265
 
253
266
  //#endregion
254
267
  //#region src/hooks/useLaunchParams.ts
268
+ const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
255
269
  /**
256
270
  * Hook to get launch params.
257
271
  * Returns undefined if params unavailable (use mockLaunchParamsForDev in dev).
@@ -272,7 +286,11 @@ function useIsMethodSupported(method) {
272
286
  * ```
273
287
  */
274
288
  function useLaunchParams() {
275
- return useMemo(() => getLaunchParams(), []);
289
+ const [params, setParams] = useState(void 0);
290
+ useIsomorphicLayoutEffect(() => {
291
+ setParams(getLaunchParams());
292
+ }, []);
293
+ return params;
276
294
  }
277
295
 
278
296
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alien_org/react",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -34,8 +34,8 @@
34
34
  "prepublishOnly": "bun run build"
35
35
  },
36
36
  "dependencies": {
37
- "@alien_org/bridge": "0.2.0",
38
- "@alien_org/contract": "0.2.0"
37
+ "@alien_org/bridge": "0.2.1",
38
+ "@alien_org/contract": "0.2.1"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "react": "^18 || ^19",