@marktiderman/genesis-native 0.0.0-stage → 0.2.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/LICENSE +21 -0
- package/README.md +267 -2
- package/dist/block-Dh5ny06W.d.ts +535 -0
- package/dist/chunk-MMTPWUWI.js +36 -0
- package/dist/chunk-MMTPWUWI.js.map +1 -0
- package/dist/index.d.ts +412 -0
- package/dist/index.js +600 -0
- package/dist/index.js.map +1 -0
- package/dist/persist.d.ts +44 -0
- package/dist/persist.js +42 -0
- package/dist/persist.js.map +1 -0
- package/dist/query-DhH3lLFa.d.ts +65 -0
- package/dist/updates.d.ts +20 -0
- package/dist/updates.js +813 -0
- package/dist/updates.js.map +1 -0
- package/package.json +84 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/boot.tsx","../src/errors.tsx","../src/auth.tsx","../src/held-link.ts","../src/app.tsx","../src/hydration-gate.ts","../src/links.ts"],"names":["jsx","createContext","useContext","useSyncExternalStore","View","Text","Fragment","useRef","client","persistence","session","boot","FatalFallback","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Boot: the async work an app must finish before its first screen (wipe a\n * session left by a reinstall, hydrate stores, load fonts, restore the query\n * cache, read the session).\n *\n * Steps run once each, in order. A step that finished is never run again, so\n * \"try again\" after a failure resumes at the step that failed. Each step has a\n * timeout (10 seconds by default), so a hung step ends in the fatal screen with\n * retry instead of trapping the splash. A minimum keeps a fast boot from\n * flashing the splash.\n *\n * `createBoot` is the controller (no React); `BootProvider` + `useBoot()` read\n * it from components.\n */\nimport { createContext, useContext, useSyncExternalStore, type ReactNode } from \"react\";\n\nexport interface BootStepContext {\n /**\n * Aborted when the step times out. Stop work when it fires: a retry waits\n * for a timed-out run to settle before running the step again.\n */\n signal: AbortSignal;\n}\n\nexport interface BootStep {\n /** Unique within the list; names the step in errors. */\n id: string;\n run: (context: BootStepContext) => Promise<unknown> | unknown;\n /** Overrides the boot's `timeoutMs` for this step. */\n timeoutMs?: number;\n}\n\nexport type BootStatus = \"idle\" | \"booting\" | \"ready\" | \"failed\";\n\nexport interface BootState {\n status: BootStatus;\n /** Set when `status` is `\"failed\"`. */\n error: Error | null;\n /** The id of the step that failed. */\n failedStep: string | null;\n /** Ids of the steps that have finished, in order. */\n completed: readonly string[];\n}\n\nexport interface BootOptions {\n /** Shortest time the boot takes, so the splash doesn't flash. Default 0. */\n minimumMs?: number;\n /** Longest time one step may take. Default 10 000. */\n timeoutMs?: number;\n}\n\nexport interface BootController {\n getState(): BootState;\n subscribe(listener: () => void): () => void;\n /** Run the steps not yet finished. Calling it while a run is in flight returns that run. */\n start(): Promise<void>;\n /** After a failure: run again from the step that failed. */\n retry(): Promise<void>;\n}\n\n/** Thrown when a step takes longer than its timeout. */\nexport class BootTimeoutError extends Error {\n readonly step: string;\n constructor(step: string, ms: number, reason = \"did not finish\") {\n super(`Boot step \"${step}\" ${reason} within ${ms} ms.`);\n this.name = \"BootTimeoutError\";\n this.step = step;\n }\n}\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\nexport function toError(value: unknown): Error {\n if (value instanceof Error) return value;\n return new Error(typeof value === \"string\" ? value : \"Unknown error\", { cause: value });\n}\n\n/** Resolves \"settled\" when `promise` settles, \"pending\" after `ms`. */\nfunction settledWithin(promise: Promise<unknown>, ms: number): Promise<\"settled\" | \"pending\"> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n return Promise.race([\n promise.then(\n () => \"settled\" as const,\n () => \"settled\" as const,\n ),\n new Promise<\"pending\">((resolve) => {\n timer = setTimeout(() => resolve(\"pending\"), ms);\n }),\n ]).finally(() => clearTimeout(timer));\n}\n\n/** The boot controller: runs `steps` once each, in order, with a timeout per step. */\nexport function createBoot(steps: readonly BootStep[], options: BootOptions = {}): BootController {\n const seen = new Set<string>();\n for (const step of steps) {\n if (seen.has(step.id)) throw new Error(`Boot step \"${step.id}\" is listed twice.`);\n seen.add(step.id);\n }\n const { minimumMs = 0, timeoutMs = DEFAULT_TIMEOUT_MS } = options;\n const listeners = new Set<() => void>();\n let state: BootState = { status: \"idle\", error: null, failedStep: null, completed: [] };\n let inFlight: Promise<void> | null = null;\n // A step that timed out keeps running (JavaScript can't stop it; `signal`\n // asks it to). A retry waits for it rather than running it twice at once.\n const abandoned = new Map<string, Promise<\"ok\" | \"failed\">>();\n\n const runStep = async (step: BootStep, ms: number): Promise<void> => {\n const previous = abandoned.get(step.id);\n if (previous) {\n if ((await settledWithin(previous, ms)) === \"pending\") {\n throw new BootTimeoutError(step.id, ms, \"is still running from the last attempt\");\n }\n abandoned.delete(step.id);\n // The abandoned run finished after all: it counts.\n if ((await previous) === \"ok\") return;\n }\n const controller = new AbortController();\n const running = Promise.resolve().then(() => step.run({ signal: controller.signal }));\n if ((await settledWithin(running, ms)) === \"pending\") {\n controller.abort();\n abandoned.set(step.id, running.then(() => \"ok\" as const, () => \"failed\" as const));\n throw new BootTimeoutError(step.id, ms);\n }\n await running;\n };\n\n const set = (next: Partial<BootState>) => {\n state = { ...state, ...next };\n for (const listener of listeners) listener();\n };\n\n const run = async () => {\n const started = Date.now();\n set({ status: \"booting\", error: null, failedStep: null });\n for (const step of steps) {\n if (state.completed.includes(step.id)) continue;\n try {\n await runStep(step, step.timeoutMs ?? timeoutMs);\n } catch (error) {\n set({ status: \"failed\", error: toError(error), failedStep: step.id });\n return;\n }\n set({ completed: [...state.completed, step.id] });\n }\n const wait = minimumMs - (Date.now() - started);\n if (wait > 0) await new Promise((resolve) => setTimeout(resolve, wait));\n set({ status: \"ready\" });\n };\n\n const start = () => {\n if (state.status === \"ready\") return Promise.resolve();\n if (!inFlight) {\n inFlight = run().finally(() => {\n inFlight = null;\n });\n }\n return inFlight;\n };\n\n return {\n getState: () => state,\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n start,\n retry: start,\n };\n}\n\nconst BootContext = createContext<BootController | null>(null);\n\n/** Makes a boot readable with `useBoot()`. */\nexport function BootProvider({ boot, children }: { boot: BootController; children: ReactNode }) {\n return <BootContext.Provider value={boot}>{children}</BootContext.Provider>;\n}\n\nexport interface UseBootReturn extends BootState {\n retry: () => void;\n}\n\n/** The boot's status, and `retry` after a failure. Inside `GenesisNativeApp` or a `BootProvider`. */\nexport function useBoot(): UseBootReturn {\n const boot = useContext(BootContext);\n if (!boot) throw new Error(\"useBoot must be used inside <GenesisNativeApp> or <BootProvider>.\");\n const state = useSyncExternalStore(boot.subscribe, boot.getState, boot.getState);\n return { ...state, retry: () => void boot.retry() };\n}\n","/**\n * Errors: a boundary per screen tree, and handlers for errors React never sees\n * (a fatal global error from `ErrorUtils`, an unhandled promise rejection).\n * All of them report through one `onError` (wire Sentry there) and show the\n * fatal screen instead of letting the app die; its \"Try again\" remounts the\n * tree with fresh state.\n */\nimport { Component, type ComponentType, type ErrorInfo, type ReactNode } from \"react\";\nimport { Pressable, Text, View } from \"react-native\";\nimport { NativeButton, NativeEmptyState } from \"@marktiderman/genesis-ui-native/components\";\nimport { toError } from \"./boot\";\n\nexport interface FatalScreenProps {\n error: Error;\n /** Clears the error and remounts the app below the shell (and re-runs a failed boot). */\n retry: () => void;\n}\n\n/** The default fatal screen: what went wrong and \"Try again\". */\nexport function FatalScreen({ error, retry }: FatalScreenProps) {\n return (\n <NativeEmptyState\n variant=\"error\"\n title=\"Something went wrong\"\n body=\"The app hit a problem. Try again, and if it keeps happening, close and reopen the app.\"\n details={error.message}\n primaryAction={\n <NativeButton onPress={retry} testID=\"genesis-fatal-retry\">\n Try again\n </NativeButton>\n }\n testID=\"genesis-fatal\"\n />\n );\n}\n\n/**\n * The last-resort fatal screen: React Native primitives only, no theme, no\n * context, nothing that can itself fail. Shown when the providers could not\n * start, or when the `fatal` slot threw.\n */\nexport function PlainFatalScreen({ error, retry }: FatalScreenProps) {\n return (\n <View testID=\"genesis-fatal-plain\" style={{ flex: 1, justifyContent: \"center\", alignItems: \"center\", padding: 24, gap: 12 }}>\n <Text accessibilityRole=\"header\" style={{ fontSize: 17, fontWeight: \"600\" }}>\n Something went wrong\n </Text>\n <Text style={{ textAlign: \"center\" }}>{error.message}</Text>\n <Pressable accessibilityRole=\"button\" onPress={retry} testID=\"genesis-fatal-plain-retry\" style={{ padding: 12 }}>\n <Text style={{ fontSize: 17 }}>Try again</Text>\n </Pressable>\n </View>\n );\n}\n\nexport interface ErrorReport {\n /** True when the app could not go on (a render error, a failed boot, a fatal global error). */\n fatal: boolean;\n source: \"boundary\" | \"global\" | \"boot\" | \"rejection\";\n componentStack?: string;\n}\n\nexport type OnError = (error: Error, report: ErrorReport) => void;\n\nexport interface GenesisErrorBoundaryProps {\n children?: ReactNode;\n /** What to render instead of the tree that threw. */\n fallback: ComponentType<FatalScreenProps>;\n onError?: OnError;\n /** Change it to clear a caught error (the tree remounts). */\n resetKey?: unknown;\n /** Called by the fallback's retry, after the error is cleared. */\n onRetry?: () => void;\n}\n\ninterface BoundaryState {\n error: Error | null;\n}\n\n/** An error boundary whose fallback gets `{ error, retry }`. */\nexport class GenesisErrorBoundary extends Component<GenesisErrorBoundaryProps, BoundaryState> {\n override state: BoundaryState = { error: null };\n\n static getDerivedStateFromError(error: unknown): BoundaryState {\n return { error: toError(error) };\n }\n\n override componentDidCatch(error: unknown, info: ErrorInfo) {\n this.props.onError?.(toError(error), { fatal: true, source: \"boundary\", componentStack: info.componentStack ?? undefined });\n }\n\n override componentDidUpdate(previous: GenesisErrorBoundaryProps) {\n if (this.state.error && previous.resetKey !== this.props.resetKey) this.setState({ error: null });\n }\n\n retry = () => {\n this.setState({ error: null });\n this.props.onRetry?.();\n };\n\n override render() {\n const { error } = this.state;\n if (!error) return this.props.children ?? null;\n const Fallback = this.props.fallback;\n return <Fallback error={error} retry={this.retry} />;\n }\n}\n\n/** React Native's `ErrorUtils` (a global in every RN app), or a stand-in. */\nexport interface ErrorUtilsLike {\n getGlobalHandler(): ((error: unknown, isFatal?: boolean) => void) | undefined;\n setGlobalHandler(handler: (error: unknown, isFatal?: boolean) => void): void;\n}\n\nexport interface GlobalErrorHandlerOptions {\n errorUtils: ErrorUtilsLike;\n onError?: OnError;\n /** A fatal error: show the fatal screen. The previous handler (which would end the app) is not called. */\n onFatal: (error: Error) => void;\n /**\n * True while a fatal screen is already up. Another fatal error then goes to\n * the previous handler, which ends the app (it restarts clean) rather than\n * leaving it stuck behind a screen that may itself be broken.\n */\n alreadyFatal?: () => boolean;\n}\n\n/**\n * Route global errors to `onError`. A fatal one goes to `onFatal` instead of\n * React Native's default handler, which would close the app; a non-fatal one\n * still reaches the previous handler (LogBox in development). Returns a\n * function that puts the previous handler back.\n */\nexport function installGlobalErrorHandler({ errorUtils, onError, onFatal, alreadyFatal }: GlobalErrorHandlerOptions): () => void {\n const previous = errorUtils.getGlobalHandler();\n errorUtils.setGlobalHandler((raw, isFatal) => {\n const error = toError(raw);\n try {\n onError?.(error, { fatal: Boolean(isFatal), source: \"global\" });\n } catch {\n // A failing reporter must not take the handler down with it.\n }\n if (isFatal && !alreadyFatal?.()) onFatal(error);\n else previous?.(raw, isFatal);\n });\n return () => {\n // With no previous handler, leave one that only logs, never ours (it would call an unmounted app).\n errorUtils.setGlobalHandler(previous ?? ((error) => console.error(error)));\n };\n}\n\n/** `globalThis.ErrorUtils` in a React Native runtime, undefined elsewhere. */\nexport function defaultErrorUtils(): ErrorUtilsLike | undefined {\n const candidate = (globalThis as { ErrorUtils?: ErrorUtilsLike }).ErrorUtils;\n return candidate && typeof candidate.setGlobalHandler === \"function\" ? candidate : undefined;\n}\n\n/** Hermes's `HermesInternal.enablePromiseRejectionTracker`, or a stand-in. */\nexport type EnableRejectionTracker = (options: {\n allRejections: boolean;\n onUnhandled: (id: number, rejection: unknown) => void;\n onHandled: (id: number) => void;\n}) => void;\n\n/**\n * Hermes's rejection tracker, when the app runs on Hermes. React Native sends\n * unhandled rejections to `ExceptionsManager` (LogBox in development), never\n * to `ErrorUtils`' global handler, so without this they never reach `onError`.\n */\nexport function defaultRejectionTracker(): EnableRejectionTracker | undefined {\n const hermes = (globalThis as { HermesInternal?: { enablePromiseRejectionTracker?: EnableRejectionTracker } }).HermesInternal;\n const enable = hermes?.enablePromiseRejectionTracker;\n return typeof enable === \"function\" ? enable.bind(hermes) : undefined;\n}\n\n/**\n * Report unhandled promise rejections to `onError` (non-fatal). This replaces\n * React Native's own tracker, so each rejection is also written with\n * `console.warn`, which LogBox shows in development as before.\n */\nexport function installRejectionTracker({ enable, onError }: { enable: EnableRejectionTracker; onError: OnError }): void {\n enable({\n allRejections: true,\n onUnhandled: (id, rejection) => {\n const error = toError(rejection);\n console.warn(`Uncaught (in promise, id: ${id}): ${error.message}`);\n try {\n onError(error, { fatal: false, source: \"rejection\" });\n } catch {\n // A failing reporter must not throw inside the promise machinery.\n }\n },\n onHandled: () => {},\n });\n}\n","/**\n * Auth gate: the Supabase session as app state.\n *\n * `createSessionStore(supabase)` reads the session once (`load`, a boot step,\n * so the splash stays up until it is known) and follows `onAuthStateChange`.\n * `useSession()` reads it; `AuthGate` renders `signedIn` or `signedOut`.\n *\n * Offline, `getSession()` can wait about 30 seconds on a token refresh that\n * can't succeed and then fail with a retryable error, although the session is\n * still on the phone. So `load` waits at most `waitMs` (5 s) and, on a timeout\n * or a network error, uses the stored session: the user stays signed in and\n * sees their cached data, and Supabase's own events correct it once online.\n *\n * With expo-router, gate in a layout instead and let the router render:\n *\n * const { status } = useSession();\n * if (status === \"signedOut\") return <Redirect href=\"/sign-in\" />;\n * return <Stack />;\n */\nimport { createContext, useContext, useSyncExternalStore, type ReactNode } from \"react\";\n\n/** The parts of a Supabase client the gate uses; a `SupabaseClient` fits. */\nexport interface AuthClientLike<S = unknown> {\n auth: {\n getSession(): Promise<{ data: { session: S | null }; error?: unknown }>;\n onAuthStateChange(callback: (event: string, session: S | null) => void): {\n data: { subscription: { unsubscribe(): void } };\n };\n };\n}\n\nexport type SessionStatus = \"loading\" | \"signedIn\" | \"signedOut\";\n\nexport interface SessionState<S = unknown> {\n status: SessionStatus;\n session: S | null;\n /** The signed-in user's id, or null. */\n userId: string | null;\n /** True when the session came from the phone because Supabase couldn't be reached. */\n offline: boolean;\n}\n\nexport interface SessionStore<S = unknown> {\n getState(): SessionState<S>;\n subscribe(listener: () => void): () => void;\n /** Read the current session (the boot step). Throws only on a non-network error. */\n load(): Promise<void>;\n /** Follow sign-in and sign-out; returns the unsubscribe. */\n start(): () => void;\n}\n\nexport interface SessionStoreOptions<S = unknown> {\n /**\n * The signed-in user changed after the session was first known: signed\n * out, signed in, or switched account. `previous` and `next` are user ids\n * (null when nobody). Clear caches here.\n */\n onUserChange?: (previous: string | null, next: string | null) => void;\n /** Longest wait for `getSession()` before using the stored session. Default 5000 ms. */\n waitMs?: number;\n /**\n * Read the session saved on the phone without refreshing it. Default: from\n * the Supabase client's own storage (`auth.storage` under `auth.storageKey`).\n */\n readStoredSession?: () => Promise<S | null>;\n /** The user id in a session. Default `session.user.id`. */\n userIdOf?: (session: S) => string | null;\n}\n\nconst DEFAULT_WAIT_MS = 5000;\n\nfunction defaultUserId(session: unknown): string | null {\n const id = (session as { user?: { id?: unknown } } | null)?.user?.id;\n return typeof id === \"string\" ? id : null;\n}\n\n/** A network failure (supabase-js `AuthRetryableFetchError`, status 0), as opposed to a real refusal. */\nfunction isNetworkError(error: unknown): boolean {\n const e = error as { name?: unknown; status?: unknown } | null;\n return e?.name === \"AuthRetryableFetchError\" || e?.status === 0;\n}\n\n/** The session supabase-js keeps under `auth.storageKey`, read without a refresh. */\nfunction storedSessionReader<S>(client: AuthClientLike<S>): () => Promise<S | null> {\n return async () => {\n const auth = client.auth as { storage?: { getItem(key: string): unknown }; storageKey?: unknown };\n if (!auth.storage || typeof auth.storageKey !== \"string\") return null;\n const raw = await auth.storage.getItem(auth.storageKey);\n if (typeof raw !== \"string\") return (raw as S | null) ?? null;\n try {\n return JSON.parse(raw) as S;\n } catch {\n return null;\n }\n };\n}\n\n/** The Supabase session as a store: `load` reads it once, `start` follows auth events. */\nexport function createSessionStore<S = unknown>(client: AuthClientLike<S>, options: SessionStoreOptions<S> = {}): SessionStore<S> {\n const { onUserChange, waitMs = DEFAULT_WAIT_MS, userIdOf = defaultUserId } = options;\n const readStored = options.readStoredSession ?? storedSessionReader(client);\n const listeners = new Set<() => void>();\n let state: SessionState<S> = { status: \"loading\", session: null, userId: null, offline: false };\n // Bumped by every auth event, so a slow `getSession()` can't overwrite a newer one.\n let version = 0;\n\n const set = (session: S | null, offline = false) => {\n const userId = session ? userIdOf(session) : null;\n const previous = state;\n if (previous.status !== \"loading\" && previous.session === session && previous.offline === offline) return;\n state = { status: session ? \"signedIn\" : \"signedOut\", session, userId, offline };\n for (const listener of listeners) listener();\n if (previous.status !== \"loading\" && previous.userId !== userId) onUserChange?.(previous.userId, userId);\n };\n\n return {\n getState: () => state,\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n async load() {\n const startedAt = version;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timedOut = new Promise<\"timeout\">((resolve) => {\n timer = setTimeout(() => resolve(\"timeout\"), waitMs);\n });\n const result = await Promise.race([client.auth.getSession(), timedOut]).finally(() => clearTimeout(timer));\n if (version !== startedAt) return; // an auth event already told us\n if (result !== \"timeout\" && !result.error) return set(result.data.session);\n if (result !== \"timeout\" && !isNetworkError(result.error)) {\n const error = result.error;\n throw error instanceof Error ? error : new Error(\"Could not read the session.\", { cause: error });\n }\n // Offline (or Supabase is slow): carry on with what the phone has.\n const stored = await readStored().catch(() => null);\n if (version !== startedAt) return;\n set(stored, stored !== null);\n },\n start() {\n const { data } = client.auth.onAuthStateChange((_event, session) => {\n version++;\n set(session);\n });\n return () => data.subscription.unsubscribe();\n },\n };\n}\n\nconst SessionContext = createContext<SessionStore | null>(null);\n\n/** Makes a session store readable with `useSession()`. */\nexport function SessionProvider({ store, children }: { store: SessionStore; children: ReactNode }) {\n return <SessionContext.Provider value={store}>{children}</SessionContext.Provider>;\n}\n\n/** The session and whether it is known yet. Inside `GenesisNativeApp` or a `SessionProvider`. */\nexport function useSession<S = unknown>(): SessionState<S> {\n const store = useContext(SessionContext);\n if (!store) throw new Error(\"useSession must be used inside <GenesisNativeApp> or <SessionProvider>.\");\n return useSyncExternalStore(store.subscribe, store.getState, store.getState) as SessionState<S>;\n}\n\nexport interface AuthGateProps {\n signedIn: ReactNode;\n signedOut: ReactNode;\n /** While the session is still being read. Default nothing (the splash is up). */\n loading?: ReactNode;\n}\n\n/** Render one tree for a signed-in user and another for everyone else. */\nexport function AuthGate({ signedIn, signedOut, loading = null }: AuthGateProps) {\n const { status } = useSession();\n if (status === \"loading\") return <>{loading}</>;\n return <>{status === \"signedIn\" ? signedIn : signedOut}</>;\n}\n","/**\n * Hold a deep link until sign-in completes.\n *\n * expo-router opens every incoming link itself. For a signed-in user that is\n * all that should happen. For a signed-out user, the auth layout redirects to\n * sign-in and the link is lost; holding it lets the app go there once the user\n * has signed in. The hold lives outside React, because expo-router's\n * `+native-intent` runs before any component:\n *\n * // lib/links.ts\n * export const linkHold = createLinkHold();\n * // app/+native-intent.ts\n * export function redirectSystemPath({ path }) {\n * const to = normalizeLink(path, links);\n * if (to && to !== \"/\") linkHold.hold(to);\n * return to;\n * }\n *\n * `useHeldLink` follows a held link only if the user was seen signed out\n * while it was held. A link that arrives while signed in, or at a cold start\n * that turns out signed in, is dropped, since the router already opened it.\n * `GenesisNativeApp` runs it for you (`links.onRelease`).\n */\nimport { useEffect, useRef, useSyncExternalStore } from \"react\";\n\nexport interface LinkHold {\n /** Hold `path`, replacing any held one. */\n hold(path: string): void;\n peek(): string | null;\n /** Return the held path and forget it. */\n take(): string | null;\n clear(): void;\n subscribe(listener: () => void): () => void;\n}\n\n/** A place to hold one deep link until sign-in completes; lives outside React. */\nexport function createLinkHold(): LinkHold {\n let held: string | null = null;\n const listeners = new Set<() => void>();\n const set = (next: string | null) => {\n if (held === next) return;\n held = next;\n for (const listener of listeners) listener();\n };\n return {\n hold: (path) => set(path),\n peek: () => held,\n take() {\n const path = held;\n set(null);\n return path;\n },\n clear: () => set(null),\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n };\n}\n\n/** `\"pending\"` while booting or reading the session. */\nexport type HeldLinkAuth = \"pending\" | \"signedOut\" | \"signedIn\";\n\nexport interface UseHeldLinkOptions {\n auth: HeldLinkAuth;\n /** Go there, e.g. `(path) => router.replace(path)`. Called once per link held across a sign-in. */\n onRelease: (path: string) => void;\n}\n\n/** Follow the held link after a sign-in, drop it otherwise; returns the link still held. */\nexport function useHeldLink(hold: LinkHold, { auth, onRelease }: UseHeldLinkOptions): string | null {\n const held = useSyncExternalStore(hold.subscribe, hold.peek, hold.peek);\n const release = useRef(onRelease);\n release.current = onRelease;\n // Was the user signed out while this link was held?\n const waitedForSignIn = useRef(false);\n useEffect(() => {\n if (held === null) {\n waitedForSignIn.current = false;\n return;\n }\n if (auth === \"signedOut\") waitedForSignIn.current = true;\n if (auth !== \"signedIn\") return;\n const path = hold.take();\n const follow = waitedForSignIn.current;\n waitedForSignIn.current = false;\n if (path !== null && follow) release.current(path);\n }, [auth, held, hold]);\n return held;\n}\n","/**\n * `<GenesisNativeApp>`: everything above an Expo app's screens, so the root\n * `_layout.tsx` is a few lines.\n *\n * last-resort boundary (React Native primitives only)\n * └ theme (GenesisThemeProvider, owning the platform color scheme)\n * └ keyboard-aware scrolling (when `keyboardScroll` is given)\n * └ data (GenesisProvider over the Supabase client, the QueryClient)\n * └ session + boot (splash held until both are known)\n * └ updates (with `updates`: force upgrade, maintenance, banner, what's new)\n * └ errorBoundary → your screens (or `signedOut`)\n *\n * Global errors, render errors and a failed boot show the `fatal` slot with\n * \"Try again\". Every part is a slot (`slots` / `slotProps`, `null` drops it)\n * and is also exported on its own.\n */\nimport { useEffect, useRef, useState, useSyncExternalStore, type ComponentType, type ReactNode } from \"react\";\nimport { Text, View } from \"react-native\";\nimport type { QueryClient, QueryClientConfig } from \"@tanstack/react-query\";\nimport { GenesisThemeProvider } from \"@marktiderman/genesis-design-system/theme\";\nimport type { CanonicalBrand } from \"@marktiderman/genesis-design-system\";\nimport { GenesisProvider, createSupabaseProvider, type DataProvider, type SupabaseClientInput } from \"@marktiderman/genesis-core/provider\";\nimport { renderSlot, type SlotPropsFor, type Slots } from \"@marktiderman/genesis-core/slots\";\nimport { KeyboardScrollProvider, type KeyboardScrollProps } from \"@marktiderman/genesis-ui-native/layouts\";\nimport { BootProvider, createBoot, type BootOptions, type BootStatus, type BootStep } from \"./boot\";\nimport {\n FatalScreen,\n GenesisErrorBoundary,\n PlainFatalScreen,\n defaultErrorUtils,\n defaultRejectionTracker,\n installGlobalErrorHandler,\n installRejectionTracker,\n type EnableRejectionTracker,\n type ErrorUtilsLike,\n type FatalScreenProps,\n type GenesisErrorBoundaryProps,\n type OnError,\n} from \"./errors\";\nimport { SessionProvider, createSessionStore, type AuthClientLike } from \"./auth\";\nimport { useHeldLink, type HeldLinkAuth, type LinkHold } from \"./held-link\";\nimport { connectQueryLifecycle, createNativeQueryClient, type QueryLifecycleOptions, type QueryPersistence } from \"./query\";\n// Types only: the block's code is in the `/updates` entry and arrives with the `updates` prop.\nimport type { UpdatesBlock, UpdatesSlots } from \"./updates/block\";\n\n/** `expo-splash-screen`, or a stand-in. Call `preventAutoHideAsync()` at module scope yourself too. */\nexport interface SplashModule {\n preventAutoHideAsync?: () => Promise<unknown>;\n hideAsync: () => Promise<unknown>;\n}\n\nexport interface BootScreenProps {\n status: BootStatus;\n}\n\nexport interface SignedOutProps {\n /** Your screens. The default renders them, for an expo-router layout that redirects. */\n children: ReactNode;\n}\n\n// A type, not an interface, so it fits the slots contract's Record constraint.\n// The updates block's slots (`forceUpgrade`, `maintenance`, `updateBanner`,\n// `whatsNew`) render only when the `updates` prop is given.\nexport type NativeAppSlots = UpdatesSlots & {\n /** Shown while booting: under the splash at launch, on its own after \"Try again\". Default `BootScreen`. */\n boot: BootScreenProps;\n /** A failed boot, a fatal global error or a render error. Default `FatalScreen`. */\n fatal: FatalScreenProps;\n /** The boundary around your screens. Default `GenesisErrorBoundary`. */\n errorBoundary: GenesisErrorBoundaryProps;\n /** What a signed-out user sees. Default your screens (gate them with `useSession`). */\n signedOut: SignedOutProps;\n};\n\nexport interface NativeQueryClientOptions {\n /** Your own client. Default `createNativeQueryClient(config)`. */\n client?: QueryClient;\n config?: QueryClientConfig;\n}\n\nexport interface GenesisNativeAppProps {\n brand: CanonicalBrand;\n /** A Supabase client (from `createGenesisSupabase` in `@marktiderman/genesis-supabase`). */\n supabase: AuthClientLike & SupabaseClientInput;\n /** The data provider. Default `createSupabaseProvider(supabase)`. */\n provider?: DataProvider;\n queryClient?: NativeQueryClientOptions;\n /**\n * Save queries to the phone: `persistQueries({ storage, keys, buster })`\n * from `@marktiderman/genesis-native/persist`. The saved cache belongs to\n * one user: it is restored only for that user and cleared when the user\n * changes (sign-out, a session that ended while the app was closed, an\n * account switch).\n */\n persist?: (client: QueryClient) => QueryPersistence;\n /** `expo-splash-screen`: hidden once boot has finished and the session is known. */\n splash?: SplashModule;\n /** `KeyboardAwareScrollView` from react-native-keyboard-controller, for form screens. */\n keyboardScroll?: ComponentType<KeyboardScrollProps>;\n /** Follow a link held while signed out, once the user signs in. */\n links?: { hold: LinkHold; onRelease: (path: string) => void };\n /** Run before first render, in order (wipe-on-reinstall, hydrate stores, fonts). Read once. */\n steps?: readonly BootStep[];\n bootOptions?: BootOptions;\n /** Longest wait for Supabase's `getSession()` before using the stored session (offline). Default 5000 ms. */\n sessionWaitMs?: number;\n /** Default `globalThis.ErrorUtils`. */\n errorUtils?: ErrorUtilsLike;\n /** Report unhandled promise rejections to `onError`. Default Hermes's tracker; `null` turns it off. */\n rejectionTracker?: EnableRejectionTracker | null;\n /** `AppState` and NetInfo, so queries refetch on focus and know the network. */\n lifecycle?: QueryLifecycleOptions;\n /** Every caught error, for reporting (Sentry). */\n onError?: OnError;\n /** After a signed-in user signs out, once the query cache is cleared. */\n onSignedOut?: () => void;\n /**\n * The updates block: `createUpdates(…)` from `@marktiderman/genesis-native/updates`\n * (force upgrade, maintenance, the update banner, what's new). Its policy\n * loads behind the splash for at most `policyTimeoutMs` and never fails the\n * boot. Read once; leave it out to turn the block off.\n */\n updates?: UpdatesBlock;\n slots?: Slots<NativeAppSlots>;\n slotProps?: SlotPropsFor<NativeAppSlots>;\n children?: ReactNode;\n}\n\n/** The default boot slot: a plain loading view (the splash covers it at launch). */\nexport function BootScreen(_props: BootScreenProps) {\n return (\n <View testID=\"genesis-boot\" accessibilityRole=\"progressbar\" style={{ flex: 1, justifyContent: \"center\", alignItems: \"center\" }}>\n <Text>Loading…</Text>\n </View>\n );\n}\n\nconst PassThrough: ComponentType<SignedOutProps> = ({ children }) => <>{children}</>;\n\n// The web provider's types don't list the native-only prop; Metro resolves the native provider.\nconst ThemeProvider = GenesisThemeProvider as ComponentType<{\n brand: CanonicalBrand;\n syncNativeAppearance?: boolean;\n children: ReactNode;\n}>;\n\n/**\n * The root of an Expo app: theme, keyboard scrolling, data, boot behind the splash, errors, session and held links.\n *\n * @stability Beta\n */\nexport function GenesisNativeApp(props: GenesisNativeAppProps) {\n // Above every provider: if one of them (or the shell's own set-up) throws,\n // this shows a screen made of nothing that can fail, and retry starts over.\n const [rootKey, setRootKey] = useState(0);\n const onErrorRef = useRef(props.onError);\n onErrorRef.current = props.onError;\n return (\n <GenesisErrorBoundary\n key={rootKey}\n fallback={PlainFatalScreen}\n onError={(e, r) => onErrorRef.current?.(e, r)}\n onRetry={() => setRootKey((key) => key + 1)}\n >\n <ThemedShell {...props} />\n </GenesisErrorBoundary>\n );\n}\n\nfunction ThemedShell(props: GenesisNativeAppProps) {\n const { brand, keyboardScroll } = props;\n const body = <Shell {...props} />;\n return (\n <ThemeProvider brand={brand} syncNativeAppearance>\n {keyboardScroll ? <KeyboardScrollProvider component={keyboardScroll}>{body}</KeyboardScrollProvider> : body}\n </ThemeProvider>\n );\n}\n\nconst SESSION_STEP_MARGIN_MS = 15_000;\n\nfunction Shell(props: GenesisNativeAppProps) {\n const { supabase, provider, queryClient: queryOptions, persist, splash, links, steps = [], bootOptions, sessionWaitMs = 5000 } = props;\n const { errorUtils, rejectionTracker, lifecycle, slots, slotProps, children } = props;\n const latest = useRef(props);\n latest.current = props;\n const onError: OnError = (error, report) => latest.current.onError?.(error, report);\n // How many fatal screens are up (the global handler lets a second fatal error end the app).\n const fatalShown = useRef(0);\n\n // Created once: the shell's parts live as long as the app.\n const [parts] = useState(() => {\n const client = queryOptions?.client ?? createNativeQueryClient(queryOptions?.config);\n const persistence = persist ? persist(client) : null;\n const session = createSessionStore(supabase, {\n waitMs: sessionWaitMs,\n // Another user (or nobody) now: nothing of the last user's may show or stay on disk.\n onUserChange: (previous, next) => {\n client.clear();\n void persistence?.clear();\n if (previous !== null && next === null) latest.current.onSignedOut?.();\n },\n });\n const boot = createBoot(\n [\n ...steps,\n // Settles within its own timeout and never throws: a policy that can't load never blocks the app.\n ...(props.updates ? [props.updates.bootStep] : []),\n { id: \"genesis:session\", run: () => session.load(), timeoutMs: sessionWaitMs + SESSION_STEP_MARGIN_MS },\n // After the session, so only the cache saved for this user is restored.\n ...(persistence ? [{ id: \"genesis:query-cache\", run: () => persistence.restore(session.getState().userId ?? \"\") }] : []),\n ],\n bootOptions,\n );\n // One component type for the life of the app, so a re-render never remounts a visible fatal screen.\n function FatalFallback(fallbackProps: FatalScreenProps) {\n useEffect(() => {\n fatalShown.current++;\n return () => {\n fatalShown.current--;\n };\n }, []);\n const { slots: s, slotProps: sp } = latest.current;\n return (\n // A `fatal` slot that throws falls back to the plain screen.\n <GenesisErrorBoundary fallback={PlainFatalScreen} onError={onError} onRetry={fallbackProps.retry}>\n {renderSlot(FatalScreen, s?.fatal, fallbackProps, sp?.fatal)}\n </GenesisErrorBoundary>\n );\n }\n return { client, persistence, session, boot, FatalFallback, updates: props.updates, provider: provider ?? createSupabaseProvider(supabase) };\n });\n const { boot, session, persistence, client, FatalFallback } = parts;\n const bootState = useSyncExternalStore(boot.subscribe, boot.getState, boot.getState);\n const sessionState = useSyncExternalStore(session.subscribe, session.getState, session.getState);\n const [fatal, setFatal] = useState<Error | null>(null);\n const [resetKey, setResetKey] = useState(0);\n\n useEffect(() => session.start(), [session]);\n useEffect(() => {\n void boot.start();\n }, [boot]);\n useEffect(() => {\n if (bootState.status === \"failed\" && bootState.error) onError(bootState.error, { fatal: true, source: \"boot\" });\n }, [bootState.status, bootState.error]);\n useEffect(() => {\n if (bootState.status === \"ready\" && persistence) return persistence.subscribe(sessionState.userId ?? \"\");\n }, [bootState.status, persistence, sessionState.userId]);\n useEffect(() => {\n const utils = errorUtils ?? defaultErrorUtils();\n if (!utils) return;\n return installGlobalErrorHandler({ errorUtils: utils, onError, onFatal: setFatal, alreadyFatal: () => fatalShown.current > 0 });\n }, [errorUtils]);\n useEffect(() => {\n const enable = rejectionTracker === null ? undefined : (rejectionTracker ?? defaultRejectionTracker());\n if (enable) installRejectionTracker({ enable, onError });\n }, [rejectionTracker]);\n useEffect(() => (lifecycle ? connectQueryLifecycle(lifecycle) : undefined), [lifecycle]);\n\n // Splash: up until boot has finished (the session step included), or failed.\n const settled = bootState.status === \"ready\" || bootState.status === \"failed\" || fatal !== null;\n const splashHidden = useRef(false);\n useEffect(() => {\n if (!settled || !splash || splashHidden.current) return;\n splashHidden.current = true;\n splash.hideAsync().catch(() => {});\n }, [settled, splash]);\n\n const auth: HeldLinkAuth = bootState.status !== \"ready\" || sessionState.status === \"loading\" ? \"pending\" : sessionState.status;\n useHeldLink(links?.hold ?? NO_HOLD, { auth: links ? auth : \"pending\", onRelease: (path) => links?.onRelease(path) });\n\n const retry = () => {\n setFatal(null);\n setResetKey((key) => key + 1);\n if (boot.getState().status === \"failed\") void boot.retry();\n };\n\n let content: ReactNode;\n if (fatal) {\n content = <FatalFallback error={fatal} retry={retry} />;\n } else if (bootState.status === \"failed\" && bootState.error) {\n content = <FatalFallback error={bootState.error} retry={retry} />;\n } else if (bootState.status !== \"ready\") {\n content = renderSlot(BootScreen, slots?.boot, { status: bootState.status }, slotProps?.boot);\n } else {\n const screens =\n sessionState.status === \"signedOut\" ? renderSlot(PassThrough, slots?.signedOut, { children }, slotProps?.signedOut) : children;\n const guarded = renderSlot(\n GenesisErrorBoundary,\n slots?.errorBoundary,\n { fallback: FatalFallback, onError, resetKey, onRetry: retry, children: screens },\n slotProps?.errorBoundary,\n );\n const Updates = parts.updates?.Root;\n content = Updates ? (\n <Updates slots={slots} slotProps={slotProps}>\n {guarded}\n </Updates>\n ) : (\n guarded\n );\n }\n\n return (\n <GenesisProvider provider={parts.provider} queryClient={client}>\n <SessionProvider store={session}>\n <BootProvider boot={boot}>\n <GenesisErrorBoundary key={resetKey} fallback={FatalFallback} onError={onError} onRetry={retry}>\n {content}\n </GenesisErrorBoundary>\n </BootProvider>\n </SessionProvider>\n </GenesisProvider>\n );\n}\n\nconst NO_HOLD: LinkHold = {\n hold: () => {},\n peek: () => null,\n take: () => null,\n clear: () => {},\n subscribe: () => () => {},\n};\n","/**\n * A hydration gate holds writes until a persisted store has loaded from disk.\n *\n * The bug it prevents: a persisted store (zustand `persist`, say) is created\n * with defaults, something sets a value before the saved state has been read,\n * and that write lands on disk first, replacing what the user had. With the\n * gate, a write made before hydration never reaches disk (`storage()`), or\n * waits for it (`run()`).\n *\n * const gate = createHydrationGate();\n * persist(store, {\n * storage: createJSONStorage(() => gate.storage(AsyncStorage)),\n * // Open only after a good read: after a failed one, writes would replace what's on disk.\n * onRehydrateStorage: () => (_state, error) => {\n * if (!error) gate.markHydrated();\n * },\n * });\n */\nimport type { AsyncStorageLike } from \"./query\";\n\nexport interface HydrationGate {\n readonly hydrated: boolean;\n /** Call once the store has read its saved state. Idempotent. */\n markHydrated(): void;\n /** Resolves once hydrated. */\n whenHydrated(): Promise<void>;\n /** Run a write now if hydrated, otherwise once hydrated. */\n run<T>(write: () => T | Promise<T>): Promise<T>;\n /**\n * The storage, with writes made before hydration dropped (reads pass\n * through, since hydration is a read). After hydration the store writes\n * its merged state on its next change, so nothing is lost but the stale\n * write. (A zustand migration's own write during hydration is dropped too;\n * the old version stays on disk and is migrated again until then.)\n */\n storage<S extends AsyncStorageLike>(storage: S): S;\n}\n\nexport interface HydrationGateOptions {\n /** Told about each write `storage()` dropped (to log it in development). */\n onDroppedWrite?: (key: string) => void;\n}\n\n/** A gate that holds writes until a persisted store has hydrated. */\nexport function createHydrationGate({ onDroppedWrite }: HydrationGateOptions = {}): HydrationGate {\n let hydrated = false;\n let open!: () => void;\n const opened = new Promise<void>((resolve) => {\n open = resolve;\n });\n\n const gate: HydrationGate = {\n get hydrated() {\n return hydrated;\n },\n markHydrated() {\n if (hydrated) return;\n hydrated = true;\n open();\n },\n whenHydrated: () => opened,\n async run(write) {\n if (!hydrated) await opened;\n return write();\n },\n storage(storage) {\n const setItem = async (key: string, value: string) => {\n if (!hydrated) return onDroppedWrite?.(key);\n return storage.setItem(key, value);\n };\n const removeItem = async (key: string) => {\n if (!hydrated) return onDroppedWrite?.(key);\n return storage.removeItem(key);\n };\n // A proxy, not a spread: a storage class's prototype methods (and its\n // private fields, through `this`) keep working.\n return new Proxy(storage, {\n get(target, property) {\n if (property === \"setItem\") return setItem;\n if (property === \"removeItem\") return removeItem;\n const value = Reflect.get(target, property, target) as unknown;\n return typeof value === \"function\" ? value.bind(target) : value;\n },\n });\n },\n };\n return gate;\n}\n","/**\n * Deep links: turn an incoming universal link or app link into an app path.\n *\n * Meant for expo-router's `app/+native-intent.ts`:\n *\n * export function redirectSystemPath({ path }: { path: string }) {\n * return normalizeLink(path, links);\n * }\n *\n * A link to a path the map doesn't know goes to `\"/\"` (and `onUnknown`), so a\n * stale or mistyped link opens the app instead of a \"not found\" screen. It\n * never throws: anything it can't read is unknown.\n */\n\n/** A target path (`\"/clients/:id\"`, params filled in) or a function of the params. */\nexport type LinkTarget = string | ((params: Record<string, string>) => string);\n\nexport interface LinkOptions {\n /** App schemes, without `://` (`[\"myapp\"]`). `myapp://clients/1` is the path `/clients/1`. */\n schemes?: readonly string[];\n /** Hosts of universal / app links (`[\"example.com\"]`). Other hosts are unknown. */\n hosts?: readonly string[];\n /**\n * Incoming path pattern → app path. A segment `:name` captures one\n * segment, a final `*` captures the rest (as `params[\"*\"]`). The first\n * match wins; `\"/\"` is always known.\n */\n map: Readonly<Record<string, LinkTarget>>;\n /** Patterns to ignore (return `null`, so expo-router doesn't navigate), e.g. an auth callback. */\n ignore?: readonly string[];\n /** Told about each link that went to `\"/\"` because nothing matched. */\n onUnknown?: (url: string) => void;\n}\n\nconst URL_PATTERN = /^([a-z][a-z0-9+.-]*):\\/\\/([^/?#]*)([^?#]*)(\\?[^#]*)?(#.*)?$/i;\n\ninterface Parsed {\n path: string;\n query: string;\n}\n\nfunction parse(url: string, schemes: readonly string[], hosts: readonly string[]): Parsed | null {\n const trimmed = url.trim();\n const match = URL_PATTERN.exec(trimmed);\n if (!match) {\n // Already a path (expo-router passes paths as well as URLs).\n if (/^[a-z][a-z0-9+.-]*:/i.test(trimmed)) return null;\n const noHash = trimmed.split(\"#\")[0] ?? \"\";\n const at = noHash.indexOf(\"?\");\n return at < 0 ? { path: noHash, query: \"\" } : { path: noHash.slice(0, at), query: noHash.slice(at) };\n }\n const [, scheme = \"\", host = \"\", path = \"\", query = \"\"] = match;\n const lowerScheme = scheme.toLowerCase();\n if (lowerScheme === \"http\" || lowerScheme === \"https\") {\n const bareHost = host.toLowerCase().replace(/:\\d+$/, \"\");\n if (!hosts.some((h) => h.toLowerCase() === bareHost)) return null;\n return { path, query };\n }\n if (!schemes.some((s) => s.toLowerCase() === lowerScheme)) return null;\n // In `myapp://clients/1`, \"clients\" sits where a host would.\n return { path: `/${host}${path}`, query };\n}\n\nfunction clean(path: string): string {\n const joined = `/${path}`.replace(/\\/{2,}/g, \"/\");\n return joined.length > 1 ? joined.replace(/\\/$/, \"\") : joined;\n}\n\nfunction matchPattern(pattern: string, path: string): Record<string, string> | null {\n const want = clean(pattern).split(\"/\").slice(1);\n const have = path.split(\"/\").slice(1);\n const params: Record<string, string> = {};\n for (let i = 0; i < want.length; i++) {\n const segment = want[i]!;\n if (segment === \"*\" && i === want.length - 1) {\n params[\"*\"] = have.slice(i).join(\"/\");\n return params;\n }\n const value = have[i];\n if (value === undefined) return null;\n if (segment.startsWith(\":\")) params[segment.slice(1)] = value;\n else if (segment !== value) return null;\n }\n return want.length === have.length ? params : null;\n}\n\nfunction fill(target: LinkTarget, params: Record<string, string>): string {\n if (typeof target === \"function\") return target(params);\n return target.replace(/:([A-Za-z_][A-Za-z0-9_]*)|\\*$/g, (token, name: string | undefined) =>\n name === undefined ? (params[\"*\"] ?? \"\") : (params[name] ?? token),\n );\n}\n\nfunction isDotSegment(segment: string): boolean {\n let decoded = segment;\n try {\n decoded = decodeURIComponent(segment);\n } catch {\n // Malformed escapes stay as they are.\n }\n return decoded === \".\" || decoded === \"..\";\n}\n\nfunction withQuery(path: string, query: string): string {\n if (!query || query === \"?\") return path;\n return path.includes(\"?\") ? `${path}&${query.slice(1)}` : `${path}${query}`;\n}\n\n/** The app path for `url`, `\"/\"` when it is unknown, or `null` when it is ignored. */\nexport function normalizeLink(url: string, options: LinkOptions): string | null {\n const { schemes = [], hosts = [], map, ignore = [], onUnknown } = options;\n const unknown = () => {\n onUnknown?.(url);\n return \"/\";\n };\n let parsed: Parsed | null;\n try {\n parsed = parse(url, schemes, hosts);\n } catch {\n parsed = null;\n }\n if (!parsed) return unknown();\n const path = clean(parsed.path);\n // \".\" and \"..\" would let a link climb out of the path it matched (a `*` capture included).\n if (path.split(\"/\").some(isDotSegment)) {\n return unknown();\n }\n if (ignore.some((pattern) => matchPattern(pattern, path))) return null;\n if (path === \"/\") return withQuery(\"/\", parsed.query);\n for (const [pattern, target] of Object.entries(map)) {\n const params = matchPattern(pattern, path);\n if (!params) continue;\n try {\n return withQuery(fill(target, params), parsed.query);\n } catch {\n return unknown();\n }\n }\n return unknown();\n}\n"]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { QueryClient } from '@tanstack/react-query';
|
|
2
|
+
import { A as AsyncStorageLike, Q as QueryPersistence } from './query-DhH3lLFa.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `@marktiderman/genesis-native/persist`: save chosen queries to async storage
|
|
6
|
+
* (AsyncStorage, MMKV, …) with TanStack's own persister, so restore,
|
|
7
|
+
* throttling and max age are theirs.
|
|
8
|
+
*
|
|
9
|
+
* Install `@tanstack/query-persist-client-core` and
|
|
10
|
+
* `@tanstack/query-async-storage-persister` at the same version as your
|
|
11
|
+
* `@tanstack/react-query`: they pin `@tanstack/query-core` exactly, and two
|
|
12
|
+
* copies of it would not share a cache.
|
|
13
|
+
*
|
|
14
|
+
* <GenesisNativeApp persist={persistQueries({ storage: AsyncStorage, keys: ["clients"], buster: version })} … />
|
|
15
|
+
*
|
|
16
|
+
* @stability Beta
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
interface PersistQueriesOptions {
|
|
20
|
+
storage: AsyncStorageLike;
|
|
21
|
+
/**
|
|
22
|
+
* The query-key roots to persist: a query is saved when its key's first
|
|
23
|
+
* element is listed (`["clients", id]` is saved under `"clients"`). Nothing
|
|
24
|
+
* else is written to the phone.
|
|
25
|
+
*/
|
|
26
|
+
keys: readonly string[];
|
|
27
|
+
/** Your app's version: a different value discards the saved cache. */
|
|
28
|
+
buster: string;
|
|
29
|
+
/** How old a saved cache may be when restored. Default 24 hours. */
|
|
30
|
+
maxAge?: number;
|
|
31
|
+
/** Storage key. Default `"genesis-query-cache"`. */
|
|
32
|
+
storageKey?: string;
|
|
33
|
+
/** Write at most this often. Default 1000 ms. */
|
|
34
|
+
throttleMs?: number;
|
|
35
|
+
}
|
|
36
|
+
interface QueryPersistenceOptions extends PersistQueriesOptions {
|
|
37
|
+
queryClient: QueryClient;
|
|
38
|
+
}
|
|
39
|
+
/** Save the allowlisted queries to async storage and restore them, with a max age, an app-version buster and a user scope. */
|
|
40
|
+
declare function createQueryPersistence({ queryClient, storage, keys, buster, maxAge, storageKey, throttleMs, }: QueryPersistenceOptions): QueryPersistence;
|
|
41
|
+
/** `createQueryPersistence` for `GenesisNativeApp`'s `persist` prop, which supplies the client. */
|
|
42
|
+
declare function persistQueries(options: PersistQueriesOptions): (queryClient: QueryClient) => QueryPersistence;
|
|
43
|
+
|
|
44
|
+
export { type PersistQueriesOptions, QueryPersistence, type QueryPersistenceOptions, createQueryPersistence, persistQueries };
|
package/dist/persist.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { DAY_MS } from './chunk-MMTPWUWI.js';
|
|
2
|
+
import { defaultShouldDehydrateQuery } from '@tanstack/react-query';
|
|
3
|
+
import { persistQueryClientSubscribe, persistQueryClientRestore } from '@tanstack/query-persist-client-core';
|
|
4
|
+
import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister';
|
|
5
|
+
|
|
6
|
+
function createQueryPersistence({
|
|
7
|
+
queryClient,
|
|
8
|
+
storage,
|
|
9
|
+
keys,
|
|
10
|
+
buster,
|
|
11
|
+
maxAge = DAY_MS,
|
|
12
|
+
storageKey = "genesis-query-cache",
|
|
13
|
+
throttleMs = 1e3
|
|
14
|
+
}) {
|
|
15
|
+
const persister = createAsyncStoragePersister({ storage, key: storageKey, throttleTime: throttleMs });
|
|
16
|
+
const allowed = new Set(keys);
|
|
17
|
+
const dehydrateOptions = {
|
|
18
|
+
shouldDehydrateQuery: (query) => allowed.has(String(query.queryKey[0])) && defaultShouldDehydrateQuery(query),
|
|
19
|
+
// Mutations stay in memory: replaying a saved write is an outbox's job.
|
|
20
|
+
shouldDehydrateMutation: () => false
|
|
21
|
+
};
|
|
22
|
+
const scoped = (scope) => `${buster}|user:${scope}`;
|
|
23
|
+
return {
|
|
24
|
+
restore: async (scope) => {
|
|
25
|
+
try {
|
|
26
|
+
await persistQueryClientRestore({ queryClient, persister, buster: scoped(scope), maxAge });
|
|
27
|
+
} catch {
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
subscribe: (scope) => persistQueryClientSubscribe({ queryClient, persister, buster: scoped(scope), dehydrateOptions }),
|
|
31
|
+
clear: async () => {
|
|
32
|
+
await persister.removeClient();
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function persistQueries(options) {
|
|
37
|
+
return (queryClient) => createQueryPersistence({ ...options, queryClient });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export { createQueryPersistence, persistQueries };
|
|
41
|
+
//# sourceMappingURL=persist.js.map
|
|
42
|
+
//# sourceMappingURL=persist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/persist.ts"],"names":[],"mappings":";;;;;AA0CO,SAAS,sBAAA,CAAuB;AAAA,EACrC,WAAA;AAAA,EACA,OAAA;AAAA,EACA,IAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA,GAAS,MAAA;AAAA,EACT,UAAA,GAAa,qBAAA;AAAA,EACb,UAAA,GAAa;AACf,CAAA,EAA8C;AAC5C,EAAA,MAAM,SAAA,GAAY,4BAA4B,EAAE,OAAA,EAAS,KAAK,UAAA,EAAY,YAAA,EAAc,YAAY,CAAA;AACpG,EAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,IAAI,CAAA;AAC5B,EAAA,MAAM,gBAAA,GAAmB;AAAA,IACvB,oBAAA,EAAsB,CAAC,KAAA,KACrB,OAAA,CAAQ,GAAA,CAAI,MAAA,CAAO,KAAA,CAAM,QAAA,CAAS,CAAC,CAAC,CAAC,CAAA,IAAK,4BAA4B,KAAK,CAAA;AAAA;AAAA,IAE7E,yBAAyB,MAAM;AAAA,GACjC;AAGA,EAAA,MAAM,SAAS,CAAC,KAAA,KAAkB,CAAA,EAAG,MAAM,SAAS,KAAK,CAAA,CAAA;AACzD,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,OAAO,KAAA,KAAU;AACxB,MAAA,IAAI;AACF,QAAA,MAAM,yBAAA,CAA0B,EAAE,WAAA,EAAa,SAAA,EAAW,QAAQ,MAAA,CAAO,KAAK,CAAA,EAAG,MAAA,EAAQ,CAAA;AAAA,MAC3F,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF,CAAA;AAAA,IACA,SAAA,EAAW,CAAC,KAAA,KAAU,2BAAA,CAA4B,EAAE,WAAA,EAAa,SAAA,EAAW,MAAA,EAAQ,MAAA,CAAO,KAAK,CAAA,EAAG,gBAAA,EAAkB,CAAA;AAAA,IACrH,OAAO,YAAY;AACjB,MAAA,MAAM,UAAU,YAAA,EAAa;AAAA,IAC/B;AAAA,GACF;AACF;AAGO,SAAS,eAAe,OAAA,EAAgF;AAC7G,EAAA,OAAO,CAAC,WAAA,KAAgB,sBAAA,CAAuB,EAAE,GAAG,OAAA,EAAS,aAAa,CAAA;AAC5E","file":"persist.js","sourcesContent":["/**\n * `@marktiderman/genesis-native/persist`: save chosen queries to async storage\n * (AsyncStorage, MMKV, …) with TanStack's own persister, so restore,\n * throttling and max age are theirs.\n *\n * Install `@tanstack/query-persist-client-core` and\n * `@tanstack/query-async-storage-persister` at the same version as your\n * `@tanstack/react-query`: they pin `@tanstack/query-core` exactly, and two\n * copies of it would not share a cache.\n *\n * <GenesisNativeApp persist={persistQueries({ storage: AsyncStorage, keys: [\"clients\"], buster: version })} … />\n *\n * @stability Beta\n */\nimport { defaultShouldDehydrateQuery, type QueryClient } from \"@tanstack/react-query\";\nimport { persistQueryClientRestore, persistQueryClientSubscribe } from \"@tanstack/query-persist-client-core\";\nimport { createAsyncStoragePersister } from \"@tanstack/query-async-storage-persister\";\nimport { DAY_MS, type AsyncStorageLike, type QueryPersistence } from \"./query\";\n\nexport interface PersistQueriesOptions {\n storage: AsyncStorageLike;\n /**\n * The query-key roots to persist: a query is saved when its key's first\n * element is listed (`[\"clients\", id]` is saved under `\"clients\"`). Nothing\n * else is written to the phone.\n */\n keys: readonly string[];\n /** Your app's version: a different value discards the saved cache. */\n buster: string;\n /** How old a saved cache may be when restored. Default 24 hours. */\n maxAge?: number;\n /** Storage key. Default `\"genesis-query-cache\"`. */\n storageKey?: string;\n /** Write at most this often. Default 1000 ms. */\n throttleMs?: number;\n}\n\nexport interface QueryPersistenceOptions extends PersistQueriesOptions {\n queryClient: QueryClient;\n}\n\n/** Save the allowlisted queries to async storage and restore them, with a max age, an app-version buster and a user scope. */\nexport function createQueryPersistence({\n queryClient,\n storage,\n keys,\n buster,\n maxAge = DAY_MS,\n storageKey = \"genesis-query-cache\",\n throttleMs = 1000,\n}: QueryPersistenceOptions): QueryPersistence {\n const persister = createAsyncStoragePersister({ storage, key: storageKey, throttleTime: throttleMs });\n const allowed = new Set(keys);\n const dehydrateOptions = {\n shouldDehydrateQuery: (query: Parameters<typeof defaultShouldDehydrateQuery>[0]) =>\n allowed.has(String(query.queryKey[0])) && defaultShouldDehydrateQuery(query),\n // Mutations stay in memory: replaying a saved write is an outbox's job.\n shouldDehydrateMutation: () => false,\n };\n // The scope rides in the buster: TanStack discards (and deletes) a saved\n // cache whose buster differs, so another user's cache is never restored.\n const scoped = (scope: string) => `${buster}|user:${scope}`;\n return {\n restore: async (scope) => {\n try {\n await persistQueryClientRestore({ queryClient, persister, buster: scoped(scope), maxAge });\n } catch {\n // An unreadable cache has already been deleted; start without it rather than fail the boot.\n }\n },\n subscribe: (scope) => persistQueryClientSubscribe({ queryClient, persister, buster: scoped(scope), dehydrateOptions }),\n clear: async () => {\n await persister.removeClient();\n },\n };\n}\n\n/** `createQueryPersistence` for `GenesisNativeApp`'s `persist` prop, which supplies the client. */\nexport function persistQueries(options: PersistQueriesOptions): (queryClient: QueryClient) => QueryPersistence {\n return (queryClient) => createQueryPersistence({ ...options, queryClient });\n}\n\nexport type { QueryPersistence } from \"./query\";\n"]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { QueryClientConfig, QueryClient } from '@tanstack/react-query';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Query: a TanStack Query client with offline-safe defaults, and the contract
|
|
5
|
+
* for saving it to the phone. The persister itself is in
|
|
6
|
+
* `@marktiderman/genesis-native/persist`, so an app that saves nothing doesn't
|
|
7
|
+
* install TanStack's persister packages.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** The part of AsyncStorage (or any async key-value store) Genesis uses. */
|
|
11
|
+
interface AsyncStorageLike {
|
|
12
|
+
getItem(key: string): Promise<string | null>;
|
|
13
|
+
setItem(key: string, value: string): Promise<void>;
|
|
14
|
+
removeItem(key: string): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
/** One day in milliseconds: the default max age of the saved query cache. */
|
|
17
|
+
declare const DAY_MS: number;
|
|
18
|
+
/**
|
|
19
|
+
* A QueryClient for a phone. `networkMode: "always"` runs a query or mutation
|
|
20
|
+
* even when the device reports offline, so it fails (and shows its error or
|
|
21
|
+
* cached data) instead of waiting forever for a network that may never come
|
|
22
|
+
* back. `gcTime` matches the persisted max age, or restored queries would be
|
|
23
|
+
* collected before they are used. Your `config` wins.
|
|
24
|
+
*/
|
|
25
|
+
declare function createNativeQueryClient(config?: QueryClientConfig): QueryClient;
|
|
26
|
+
/**
|
|
27
|
+
* The saved query cache. A `scope` (the signed-in user's id, `""` for nobody)
|
|
28
|
+
* is part of what is saved: a cache saved for one user is discarded, on disk
|
|
29
|
+
* too, when another scope restores it.
|
|
30
|
+
*/
|
|
31
|
+
interface QueryPersistence {
|
|
32
|
+
/** Load the saved cache into the client, if it was saved for `scope`. */
|
|
33
|
+
restore(scope: string): Promise<void>;
|
|
34
|
+
/** Save on every cache change, for `scope`; returns the unsubscribe. */
|
|
35
|
+
subscribe(scope: string): () => void;
|
|
36
|
+
/**
|
|
37
|
+
* Delete the saved cache. Clear the QueryClient first: the subscription
|
|
38
|
+
* then saves the empty cache, so a save already in flight can't leave the
|
|
39
|
+
* old queries on disk.
|
|
40
|
+
*/
|
|
41
|
+
clear(): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
/** React Native's `AppState`, or a stand-in. */
|
|
44
|
+
interface AppStateLike {
|
|
45
|
+
addEventListener(type: "change", listener: (state: string) => void): {
|
|
46
|
+
remove(): void;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** `@react-native-community/netinfo`'s default export, or a stand-in. */
|
|
50
|
+
interface NetInfoLike {
|
|
51
|
+
addEventListener(listener: (state: {
|
|
52
|
+
isConnected: boolean | null;
|
|
53
|
+
}) => void): () => void;
|
|
54
|
+
}
|
|
55
|
+
interface QueryLifecycleOptions {
|
|
56
|
+
appState?: AppStateLike;
|
|
57
|
+
netInfo?: NetInfoLike;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Tell TanStack Query when the app comes to the front (refetch stale
|
|
61
|
+
* queries) and when the network comes and goes. Returns the cleanup.
|
|
62
|
+
*/
|
|
63
|
+
declare function connectQueryLifecycle({ appState, netInfo }: QueryLifecycleOptions): () => void;
|
|
64
|
+
|
|
65
|
+
export { type AsyncStorageLike as A, DAY_MS as D, type NetInfoLike as N, type QueryPersistence as Q, type QueryLifecycleOptions as a, type AppStateLike as b, connectQueryLifecycle as c, createNativeQueryClient as d };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export { A as ApplicationLike, C as CLOCK_SKEW_MS, b as ChannelSwitchResult, c as ChannelSwitcher, d as ChannelSwitcherOptions, E as EvaluatePolicyOptions, F as ForceUpgradeProps, e as ForceUpgradeScreen, M as MaintenanceProps, f as MaintenanceScreen, P as PolicyClientLike, g as PolicyOrigin, h as PolicyState, i as PolicyStore, j as PolicyStoreOptions, R as ReleaseNote, k as ReloadGuard, S as SupabasePolicySourceOptions, l as UpdateBanner, m as UpdateBannerProps, n as UpdateCheckState, o as UpdateCheckStatus, p as UpdateChecker, q as UpdateCheckerOptions, r as UpdatePlatform, s as UpdatePolicy, t as UpdatePolicySource, u as UpdateVerdict, v as UpdatesAppStateLike, U as UpdatesBlock, w as UpdatesErrorSource, x as UpdatesModuleLike, y as UpdatesOnError, z as UpdatesOptions, B as UpdatesProvider, D as UpdatesRoot, G as UpdatesRootProps, a as UpdatesSlots, H as UpdatesStorageLike, V as VersionSignature, I as VersionSignatureInput, W as WEEK_MS, J as WhatsNewOptions, K as WhatsNewProps, L as WhatsNewSheet, N as WhatsNewState, O as WhatsNewStore, Q as createChannelSwitcher, T as createPolicyStore, X as createReloadGuard, Y as createUpdateChecker, Z as createUpdates, _ as createWhatsNewStore, $ as evaluatePolicy, a0 as notesSince, a1 as sanitizePolicy, a2 as staticPolicySource, a3 as supabasePolicySource, a4 as useBlockReload, a5 as useCanReload, a6 as useForceUpgrade, a7 as useMaintenance, a8 as useUpdateBanner, a9 as useUpdateCheck, aa as useUpdatePolicy, ab as useUpdateVerdict, ac as useUpdates, ad as useVersionSignature, ae as useWhatsNew, af as versionSignature } from './block-Dh5ny06W.js';
|
|
2
|
+
import 'react';
|
|
3
|
+
import '@marktiderman/genesis-core/slots';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Version numbers: the store version an app reports (`1.4.0`, `1.10`) and
|
|
7
|
+
* the minimum a policy sets. Only plain dotted numbers count (one to four
|
|
8
|
+
* parts, as App Store Connect and Play accept). Anything else (`1.2-beta`,
|
|
9
|
+
* `latest`, an empty string, a number too large to compare exactly) does not
|
|
10
|
+
* parse, and a comparison with it has no answer (`null`), so a malformed
|
|
11
|
+
* minimum can never block anyone.
|
|
12
|
+
*/
|
|
13
|
+
/** `"1.10"` → `[1, 10, 0, 0]`; `null` when it isn't a plain dotted version. */
|
|
14
|
+
declare function parseVersion(value: unknown): number[] | null;
|
|
15
|
+
/** -1, 0 or 1 as `a` is older than, the same as or newer than `b`; `null` when either doesn't parse. */
|
|
16
|
+
declare function compareVersions(a: unknown, b: unknown): -1 | 0 | 1 | null;
|
|
17
|
+
/** True only when both parse and `installed` is older than `minimum`. Fails open. */
|
|
18
|
+
declare function isBelowMinimum(installed: unknown, minimum: unknown): boolean;
|
|
19
|
+
|
|
20
|
+
export { compareVersions, isBelowMinimum, parseVersion };
|