@bigmi/react 0.0.0-preview-aab0339

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.
Files changed (103) hide show
  1. package/CHANGELOG.md +207 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +471 -0
  4. package/dist/cjs/context.d.ts +15 -0
  5. package/dist/cjs/context.js +16 -0
  6. package/dist/cjs/context.js.map +1 -0
  7. package/dist/cjs/errors/context.d.ts +13 -0
  8. package/dist/cjs/errors/context.js +13 -0
  9. package/dist/cjs/errors/context.js.map +1 -0
  10. package/dist/cjs/hooks/useAccount.d.ts +11 -0
  11. package/dist/cjs/hooks/useAccount.js +26 -0
  12. package/dist/cjs/hooks/useAccount.js.map +1 -0
  13. package/dist/cjs/hooks/useConfig.d.ts +13 -0
  14. package/dist/cjs/hooks/useConfig.js +15 -0
  15. package/dist/cjs/hooks/useConfig.js.map +1 -0
  16. package/dist/cjs/hooks/useConnect.d.ts +20 -0
  17. package/dist/cjs/hooks/useConnect.js +32 -0
  18. package/dist/cjs/hooks/useConnect.js.map +1 -0
  19. package/dist/cjs/hooks/useConnectors.d.ts +11 -0
  20. package/dist/cjs/hooks/useConnectors.js +15 -0
  21. package/dist/cjs/hooks/useConnectors.js.map +1 -0
  22. package/dist/cjs/hooks/useReconnect.d.ts +7 -0
  23. package/dist/cjs/hooks/useReconnect.js +14 -0
  24. package/dist/cjs/hooks/useReconnect.js.map +1 -0
  25. package/dist/cjs/hooks/useSyncExternalStoreWithTracked.d.ts +5 -0
  26. package/dist/cjs/hooks/useSyncExternalStoreWithTracked.js +41 -0
  27. package/dist/cjs/hooks/useSyncExternalStoreWithTracked.js.map +1 -0
  28. package/dist/cjs/hydrate.d.ts +21 -0
  29. package/dist/cjs/hydrate.js +45 -0
  30. package/dist/cjs/hydrate.js.map +1 -0
  31. package/dist/cjs/index.d.ts +6 -0
  32. package/dist/cjs/index.js +12 -0
  33. package/dist/cjs/package.json +1 -0
  34. package/dist/cjs/types.d.ts +12 -0
  35. package/dist/cjs/types.js +0 -0
  36. package/dist/cjs/utils/query.d.ts +9 -0
  37. package/dist/cjs/utils/query.js +1 -0
  38. package/dist/cjs/version.d.ts +6 -0
  39. package/dist/cjs/version.js +9 -0
  40. package/dist/cjs/version.js.map +1 -0
  41. package/dist/esm/context.d.ts +15 -0
  42. package/dist/esm/context.d.ts.map +1 -0
  43. package/dist/esm/context.js +14 -0
  44. package/dist/esm/context.js.map +1 -0
  45. package/dist/esm/errors/context.d.ts +13 -0
  46. package/dist/esm/errors/context.d.ts.map +1 -0
  47. package/dist/esm/errors/context.js +12 -0
  48. package/dist/esm/errors/context.js.map +1 -0
  49. package/dist/esm/hooks/useAccount.d.ts +11 -0
  50. package/dist/esm/hooks/useAccount.d.ts.map +1 -0
  51. package/dist/esm/hooks/useAccount.js +25 -0
  52. package/dist/esm/hooks/useAccount.js.map +1 -0
  53. package/dist/esm/hooks/useConfig.d.ts +13 -0
  54. package/dist/esm/hooks/useConfig.d.ts.map +1 -0
  55. package/dist/esm/hooks/useConfig.js +14 -0
  56. package/dist/esm/hooks/useConfig.js.map +1 -0
  57. package/dist/esm/hooks/useConnect.d.ts +20 -0
  58. package/dist/esm/hooks/useConnect.d.ts.map +1 -0
  59. package/dist/esm/hooks/useConnect.js +31 -0
  60. package/dist/esm/hooks/useConnect.js.map +1 -0
  61. package/dist/esm/hooks/useConnectors.d.ts +11 -0
  62. package/dist/esm/hooks/useConnectors.d.ts.map +1 -0
  63. package/dist/esm/hooks/useConnectors.js +14 -0
  64. package/dist/esm/hooks/useConnectors.js.map +1 -0
  65. package/dist/esm/hooks/useReconnect.d.ts +7 -0
  66. package/dist/esm/hooks/useReconnect.d.ts.map +1 -0
  67. package/dist/esm/hooks/useReconnect.js +13 -0
  68. package/dist/esm/hooks/useReconnect.js.map +1 -0
  69. package/dist/esm/hooks/useSyncExternalStoreWithTracked.d.ts +5 -0
  70. package/dist/esm/hooks/useSyncExternalStoreWithTracked.d.ts.map +1 -0
  71. package/dist/esm/hooks/useSyncExternalStoreWithTracked.js +40 -0
  72. package/dist/esm/hooks/useSyncExternalStoreWithTracked.js.map +1 -0
  73. package/dist/esm/hydrate.d.ts +21 -0
  74. package/dist/esm/hydrate.d.ts.map +1 -0
  75. package/dist/esm/hydrate.js +43 -0
  76. package/dist/esm/hydrate.js.map +1 -0
  77. package/dist/esm/index.d.ts +6 -0
  78. package/dist/esm/index.js +6 -0
  79. package/dist/esm/package.json +1 -0
  80. package/dist/esm/types.d.ts +12 -0
  81. package/dist/esm/types.d.ts.map +1 -0
  82. package/dist/esm/types.js +1 -0
  83. package/dist/esm/utils/query.d.ts +9 -0
  84. package/dist/esm/utils/query.d.ts.map +1 -0
  85. package/dist/esm/utils/query.js +2 -0
  86. package/dist/esm/version.d.ts +6 -0
  87. package/dist/esm/version.d.ts.map +1 -0
  88. package/dist/esm/version.js +7 -0
  89. package/dist/esm/version.js.map +1 -0
  90. package/package.json +58 -0
  91. package/src/context.ts +33 -0
  92. package/src/errors/context.ts +11 -0
  93. package/src/hooks/useAccount.ts +43 -0
  94. package/src/hooks/useConfig.ts +27 -0
  95. package/src/hooks/useConnect.ts +90 -0
  96. package/src/hooks/useConnectors.ts +33 -0
  97. package/src/hooks/useReconnect.ts +11 -0
  98. package/src/hooks/useSyncExternalStoreWithTracked.ts +76 -0
  99. package/src/hydrate.ts +86 -0
  100. package/src/index.ts +6 -0
  101. package/src/types.ts +9 -0
  102. package/src/utils/query.ts +31 -0
  103. package/src/version.ts +2 -0
@@ -0,0 +1,90 @@
1
+ 'use client'
2
+
3
+ import {
4
+ type Config,
5
+ type ConnectData,
6
+ type ConnectErrorType,
7
+ type ConnectMutate,
8
+ type ConnectMutateAsync,
9
+ type ConnectVariables,
10
+ connectMutationOptions,
11
+ } from '@bigmi/client'
12
+ import type { Compute } from '@bigmi/core'
13
+ import { useMutation } from '@tanstack/react-query'
14
+ import { useEffect } from 'react'
15
+ import type { ResolvedRegister } from '../types.js'
16
+ import type {
17
+ UseMutationParameters,
18
+ UseMutationReturnType,
19
+ } from '../utils/query.js'
20
+ import { type ConfigParameter, useConfig } from './useConfig.js'
21
+ import { type UseConnectorsReturnType, useConnectors } from './useConnectors.js'
22
+
23
+ export type UseConnectParameters<
24
+ config extends Config = Config,
25
+ context = unknown,
26
+ > = Compute<
27
+ ConfigParameter<config> & {
28
+ mutation?:
29
+ | UseMutationParameters<
30
+ ConnectData<config>,
31
+ ConnectErrorType,
32
+ ConnectVariables<config, config['connectors'][number]>,
33
+ context
34
+ >
35
+ | undefined
36
+ }
37
+ >
38
+
39
+ export type UseConnectReturnType<
40
+ config extends Config = Config,
41
+ context = unknown,
42
+ > = Compute<
43
+ UseMutationReturnType<
44
+ ConnectData<config>,
45
+ ConnectErrorType,
46
+ ConnectVariables<config, config['connectors'][number]>,
47
+ context
48
+ > & {
49
+ connect: ConnectMutate<config, context>
50
+ connectAsync: ConnectMutateAsync<config, context>
51
+ connectors: Compute<UseConnectorsReturnType> | config['connectors']
52
+ }
53
+ >
54
+
55
+ export function useConnect<
56
+ config extends Config = ResolvedRegister['config'],
57
+ context = unknown,
58
+ >(
59
+ parameters: UseConnectParameters<config, context> = {}
60
+ ): UseConnectReturnType<config, context> {
61
+ const { mutation } = parameters
62
+
63
+ const config = useConfig(parameters)
64
+
65
+ const mutationOptions = connectMutationOptions(config)
66
+ const { mutate, mutateAsync, reset, ...result } = useMutation({
67
+ ...mutation,
68
+ ...mutationOptions,
69
+ })
70
+
71
+ // Reset mutation back to an idle state when the connector disconnects.
72
+ useEffect(() => {
73
+ return config.subscribe(
74
+ ({ status }) => status,
75
+ (status, previousStatus) => {
76
+ if (previousStatus === 'connected' && status === 'disconnected') {
77
+ reset()
78
+ }
79
+ }
80
+ )
81
+ }, [config, reset])
82
+
83
+ type Return = UseConnectReturnType<config, context>
84
+ return {
85
+ ...(result as Return),
86
+ connect: mutate as Return['connect'],
87
+ connectAsync: mutateAsync as Return['connectAsync'],
88
+ connectors: useConnectors({ config }),
89
+ }
90
+ }
@@ -0,0 +1,33 @@
1
+ 'use client'
2
+
3
+ import {
4
+ type Config,
5
+ type GetConnectorsReturnType,
6
+ getConnectors,
7
+ watchConnectors,
8
+ } from '@bigmi/client'
9
+ import { useSyncExternalStore } from 'react'
10
+ import type { ResolvedRegister } from '../types.js'
11
+ import { type ConfigParameter, useConfig } from './useConfig.js'
12
+
13
+ export type UseConnectorsParameters<config extends Config = Config> =
14
+ ConfigParameter<config>
15
+
16
+ export type UseConnectorsReturnType<config extends Config = Config> =
17
+ GetConnectorsReturnType<config>
18
+
19
+ const EMPTY_CONNECTORS: readonly [] = []
20
+
21
+ export function useConnectors<
22
+ config extends Config = ResolvedRegister['config'],
23
+ >(
24
+ parameters: UseConnectorsParameters<config> = {}
25
+ ): UseConnectorsReturnType<config> {
26
+ const config = useConfig(parameters)
27
+
28
+ return useSyncExternalStore(
29
+ (onChange) => watchConnectors(config, { onChange }),
30
+ () => getConnectors(config),
31
+ () => EMPTY_CONNECTORS as UseConnectorsReturnType<config>
32
+ )
33
+ }
@@ -0,0 +1,11 @@
1
+ 'use client'
2
+
3
+ import { type Config, reconnect } from '@bigmi/client'
4
+
5
+ import { useEffect } from 'react'
6
+
7
+ export const useReconnect = (config: Config): void => {
8
+ useEffect(() => {
9
+ reconnect(config)
10
+ }, [config])
11
+ }
@@ -0,0 +1,76 @@
1
+ 'use client'
2
+ import { deepEqual } from '@bigmi/core'
3
+ import { useMemo, useRef, useSyncExternalStore } from 'react'
4
+
5
+ const isPlainObject = (obj: unknown): obj is Record<string, any> =>
6
+ typeof obj === 'object' && !Array.isArray(obj)
7
+
8
+ export function useSyncExternalStoreWithTracked<
9
+ Snapshot extends Selection,
10
+ Selection = Snapshot,
11
+ >(
12
+ subscribe: (onStoreChange: () => void) => () => void,
13
+ getSnapshot: () => Snapshot,
14
+ getServerSnapshot: (() => Snapshot) | undefined = getSnapshot,
15
+ isEqual: (a: Selection, b: Selection) => boolean = deepEqual
16
+ ): Selection {
17
+ const trackedKeys = useRef<Set<string>>(new Set())
18
+ const previousResult = useRef<Selection | undefined>(undefined)
19
+ const snapshotCache = useRef(getSnapshot())
20
+
21
+ const snapshot = useSyncExternalStore(
22
+ (onChange) =>
23
+ subscribe(() => {
24
+ snapshotCache.current = getSnapshot()
25
+ onChange()
26
+ }),
27
+ () => snapshotCache.current!,
28
+ getServerSnapshot
29
+ )
30
+
31
+ const result = useMemo(() => {
32
+ if (!isPlainObject(snapshot)) {
33
+ return snapshot
34
+ }
35
+
36
+ const trackedResult = { ...snapshot }
37
+ Object.defineProperties(
38
+ trackedResult,
39
+ Object.fromEntries(
40
+ Object.entries(trackedResult).map(([key, value]) => [
41
+ key,
42
+ {
43
+ configurable: false,
44
+ enumerable: true,
45
+ get: () => {
46
+ trackedKeys.current.add(key)
47
+ return value
48
+ },
49
+ },
50
+ ])
51
+ )
52
+ )
53
+ return trackedResult
54
+ }, [snapshot])
55
+
56
+ return useMemo(() => {
57
+ if (!trackedKeys.current.size || !previousResult.current) {
58
+ previousResult.current = result
59
+ return result
60
+ }
61
+
62
+ const hasChanged = Array.from(trackedKeys.current).some(
63
+ (key) =>
64
+ !isEqual(
65
+ (result as Record<string, Selection>)[key],
66
+ (previousResult.current as Record<string, Selection>)[key]
67
+ )
68
+ )
69
+
70
+ if (!hasChanged) {
71
+ return previousResult.current
72
+ }
73
+ previousResult.current = result
74
+ return result
75
+ }, [result, isEqual])
76
+ }
package/src/hydrate.ts ADDED
@@ -0,0 +1,86 @@
1
+ 'use client'
2
+
3
+ import { type Config, reconnect, type State } from '@bigmi/client'
4
+
5
+ import { type ReactElement, useEffect, useRef } from 'react'
6
+
7
+ import type { ResolvedRegister } from './types.js'
8
+
9
+ export type HydrateProps = {
10
+ config: ResolvedRegister['config']
11
+ initialState?: State | undefined
12
+ reconnectOnMount?: boolean | undefined
13
+ }
14
+
15
+ type HydrateParameters = {
16
+ initialState?: State | undefined
17
+ reconnectOnMount?: boolean | undefined
18
+ }
19
+
20
+ export function hydrate(
21
+ config: Config,
22
+ parameters: HydrateParameters
23
+ ): { onMount(): Promise<void> } {
24
+ const { initialState, reconnectOnMount } = parameters
25
+
26
+ if (initialState && !config._internal.store.persist.hasHydrated()) {
27
+ config.setState({
28
+ ...initialState,
29
+ chainId: config.chains.some((x) => x.id === initialState.chainId)
30
+ ? initialState.chainId
31
+ : config.chains[0].id,
32
+ connections: reconnectOnMount ? initialState.connections : new Map(),
33
+ status: reconnectOnMount ? 'reconnecting' : 'disconnected',
34
+ })
35
+ }
36
+
37
+ return {
38
+ async onMount(): Promise<void> {
39
+ if (config._internal.ssr) {
40
+ await config._internal.store.persist.rehydrate()
41
+ }
42
+
43
+ if (reconnectOnMount) {
44
+ reconnect(config)
45
+ } else if (config.storage) {
46
+ // Reset connections that may have been hydrated from storage.
47
+ config.setState((x) => ({
48
+ ...x,
49
+ connections: new Map(),
50
+ }))
51
+ }
52
+ },
53
+ }
54
+ }
55
+
56
+ export function Hydrate(parameters: React.PropsWithChildren<HydrateProps>) {
57
+ const { children, config, initialState, reconnectOnMount = true } = parameters
58
+
59
+ const { onMount } = hydrate(config, {
60
+ initialState,
61
+ reconnectOnMount,
62
+ })
63
+
64
+ // Hydrate for non-SSR
65
+ if (!config._internal.ssr) {
66
+ onMount()
67
+ }
68
+
69
+ // Hydrate for SSR
70
+ const active = useRef(true)
71
+ // biome-ignore lint/correctness/useExhaustiveDependencies: `queryKey` not required
72
+ useEffect(() => {
73
+ if (!active.current) {
74
+ return
75
+ }
76
+ if (!config._internal.ssr) {
77
+ return
78
+ }
79
+ onMount()
80
+ return () => {
81
+ active.current = false
82
+ }
83
+ }, [])
84
+
85
+ return children as ReactElement
86
+ }
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export type { BigmiProviderProps } from './context.js'
2
+ export { BigmiContext, BigmiProvider } from './context.js'
3
+ export { useAccount } from './hooks/useAccount.js'
4
+ export { useConfig } from './hooks/useConfig.js'
5
+ export { useConnect } from './hooks/useConnect.js'
6
+ export { useReconnect } from './hooks/useReconnect.js'
package/src/types.ts ADDED
@@ -0,0 +1,9 @@
1
+ import type { Config } from '@bigmi/client'
2
+
3
+ // biome-ignore lint/complexity/noBannedTypes: part of the types
4
+ export type Register = {}
5
+ export type ResolvedRegister = {
6
+ config: Register extends { config: infer config extends Config }
7
+ ? config
8
+ : Config
9
+ }
@@ -0,0 +1,31 @@
1
+ 'use client'
2
+
3
+ import type { Compute, UnionStrictOmit } from '@bigmi/core'
4
+ import type {
5
+ UseMutationOptions,
6
+ UseMutationResult,
7
+ } from '@tanstack/react-query'
8
+
9
+ export type UseMutationParameters<
10
+ data = unknown,
11
+ error = Error,
12
+ variables = void,
13
+ context = unknown,
14
+ > = Compute<
15
+ Omit<
16
+ UseMutationOptions<data, error, Compute<variables>, context>,
17
+ 'mutationFn' | 'mutationKey' | 'throwOnError'
18
+ >
19
+ >
20
+
21
+ export type UseMutationReturnType<
22
+ data = unknown,
23
+ error = Error,
24
+ variables = void,
25
+ context = unknown,
26
+ > = Compute<
27
+ UnionStrictOmit<
28
+ UseMutationResult<data, error, variables, context>,
29
+ 'mutate' | 'mutateAsync'
30
+ >
31
+ >
package/src/version.ts ADDED
@@ -0,0 +1,2 @@
1
+ export const name = '@bigmi/react'
2
+ export const version = '0.0.0-preview-aab0339'