@spooky-sync/client-solid 0.0.1-canary.113 → 0.0.1-canary.117

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.
@@ -0,0 +1,111 @@
1
+ import type {
2
+ ColumnSchema,
3
+ FinalQuery,
4
+ SchemaStructure,
5
+ TableNames,
6
+ } from '@spooky-sync/query-builder';
7
+ import { createEffect, useContext } from 'solid-js';
8
+ import { SyncedDb } from '..';
9
+ import type { Sp00kyQueryResultPromise, PreloadOptions as CorePreloadOptions } from '@spooky-sync/core';
10
+ import { Sp00kyContext } from './context';
11
+
12
+ type PreloadArg<
13
+ S extends SchemaStructure,
14
+ TableName extends TableNames<S>,
15
+ T extends { columns: Record<string, ColumnSchema> },
16
+ RelatedFields extends Record<string, any>,
17
+ IsOne extends boolean,
18
+ > =
19
+ | FinalQuery<S, TableName, T, RelatedFields, IsOne, Sp00kyQueryResultPromise>
20
+ | (() =>
21
+ | FinalQuery<S, TableName, T, RelatedFields, IsOne, Sp00kyQueryResultPromise>
22
+ | null
23
+ | undefined);
24
+
25
+ type PreloadOptions = CorePreloadOptions & {
26
+ /** Only preload while this returns true (defaults to always). */
27
+ enabled?: () => boolean;
28
+ };
29
+
30
+ // Overload: context-based (no explicit db)
31
+ export function createPreload<
32
+ S extends SchemaStructure,
33
+ TableName extends TableNames<S>,
34
+ T extends { columns: Record<string, ColumnSchema> },
35
+ RelatedFields extends Record<string, any>,
36
+ IsOne extends boolean,
37
+ >(
38
+ finalQuery: PreloadArg<S, TableName, T, RelatedFields, IsOne>,
39
+ options?: PreloadOptions,
40
+ ): void;
41
+
42
+ // Overload: explicit db
43
+ export function createPreload<
44
+ S extends SchemaStructure,
45
+ TableName extends TableNames<S>,
46
+ T extends { columns: Record<string, ColumnSchema> },
47
+ RelatedFields extends Record<string, any>,
48
+ IsOne extends boolean,
49
+ >(
50
+ db: SyncedDb<S>,
51
+ finalQuery: PreloadArg<S, TableName, T, RelatedFields, IsOne>,
52
+ options?: PreloadOptions,
53
+ ): void;
54
+
55
+ /**
56
+ * Reactive, fire-and-forget prewarm. Resolves the query (calling it if it's a
57
+ * function so it tracks reactive deps), dedupes on the query's stable identity
58
+ * hash, and warms it into the local cache via `db.preload`. No subscription and
59
+ * no cleanup: preload registers nothing that needs tearing down.
60
+ *
61
+ * Typical use: inside a list row, preload the detail query the user is likely
62
+ * to open next, so navigation paints from cache instead of the network.
63
+ */
64
+ export function createPreload<
65
+ S extends SchemaStructure,
66
+ TableName extends TableNames<S>,
67
+ T extends { columns: Record<string, ColumnSchema> },
68
+ RelatedFields extends Record<string, any>,
69
+ IsOne extends boolean,
70
+ >(
71
+ dbOrQuery: SyncedDb<S> | PreloadArg<S, TableName, T, RelatedFields, IsOne>,
72
+ queryOrOptions?: PreloadArg<S, TableName, T, RelatedFields, IsOne> | PreloadOptions,
73
+ maybeOptions?: PreloadOptions,
74
+ ): void {
75
+ let db: SyncedDb<S>;
76
+ let finalQuery: PreloadArg<S, TableName, T, RelatedFields, IsOne>;
77
+ let options: PreloadOptions | undefined;
78
+
79
+ if (dbOrQuery instanceof SyncedDb) {
80
+ db = dbOrQuery;
81
+ finalQuery = queryOrOptions as PreloadArg<S, TableName, T, RelatedFields, IsOne>;
82
+ options = maybeOptions;
83
+ } else {
84
+ const contextDb = useContext(Sp00kyContext);
85
+ if (!contextDb) {
86
+ throw new Error(
87
+ 'createPreload: No db argument provided and no Sp00kyContext found. ' +
88
+ 'Either pass a SyncedDb instance or wrap your app in <Sp00kyProvider>.',
89
+ );
90
+ }
91
+ db = contextDb as SyncedDb<S>;
92
+ finalQuery = dbOrQuery;
93
+ options = queryOrOptions as PreloadOptions | undefined;
94
+ }
95
+
96
+ let prevHash: number | undefined;
97
+
98
+ createEffect(() => {
99
+ if (!(options?.enabled?.() ?? true)) return;
100
+
101
+ const query = typeof finalQuery === 'function' ? finalQuery() : finalQuery;
102
+ if (!query) return;
103
+
104
+ // Dedupe on the query's stable identity hash so a reactive re-run with an
105
+ // unchanged query doesn't refetch (the core also dedupes per session).
106
+ if (query.hash === prevHash) return;
107
+ prevHash = query.hash;
108
+
109
+ void db.getSp00ky().preload(query, { refresh: options?.refresh, staleTime: options?.staleTime });
110
+ });
111
+ }