@spooky-sync/client-solid 0.0.1-canary.16 → 0.0.1-canary.160
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/AGENTS.md +68 -0
- package/README.md +20 -0
- package/dist/index.cjs +385 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +216 -21
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +216 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +380 -66
- package/dist/index.js.map +1 -1
- package/package.json +9 -7
- package/skills/sp00ky-solid/SKILL.md +335 -0
- package/skills/sp00ky-solid/references/file-hooks.md +112 -0
- package/src/cache/index.ts +1 -1
- package/src/cache/surrealdb-wasm-factory.ts +4 -1
- package/src/index.ts +164 -61
- package/src/lib/Sp00kyProvider.ts +102 -0
- package/src/lib/context.ts +3 -3
- package/src/lib/create-preload.ts +111 -0
- package/src/lib/models.ts +1 -1
- package/src/lib/use-app-release.ts +89 -0
- package/src/lib/use-crdt-field.ts +68 -0
- package/src/lib/use-download-file.ts +2 -2
- package/src/lib/use-feature-flag.ts +50 -0
- package/src/lib/use-file-upload.ts +2 -1
- package/src/lib/use-query.ts +143 -28
- package/src/lib/use-storage-status.ts +44 -0
- package/src/lib/use-sync-status.ts +50 -0
- package/src/types/index.ts +3 -4
- package/src/lib/SpookyProvider.ts +0 -55
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createSignal, onCleanup, type Accessor } from 'solid-js';
|
|
2
|
+
import { useDb } from './context';
|
|
3
|
+
import type { SyncHealth, SyncHealthStatus } from '@spooky-sync/core';
|
|
4
|
+
|
|
5
|
+
export interface UseSyncStatus {
|
|
6
|
+
/** Full health snapshot; updates reactively on every transition. */
|
|
7
|
+
health: Accessor<SyncHealth>;
|
|
8
|
+
/** `'healthy'` | `'degraded'`. */
|
|
9
|
+
status: Accessor<SyncHealthStatus>;
|
|
10
|
+
isHealthy: Accessor<boolean>;
|
|
11
|
+
/** `true` once sync has failed for a sustained run — drive a banner off this. */
|
|
12
|
+
isDegraded: Accessor<boolean>;
|
|
13
|
+
/** `true` once at least one sync round has succeeded this session. */
|
|
14
|
+
everConnected: Accessor<boolean>;
|
|
15
|
+
/**
|
|
16
|
+
* `true` only for a real lost connection: degraded AFTER a first successful
|
|
17
|
+
* sync. Stays `false` during the initial "connecting" phase (degraded but
|
|
18
|
+
* never reached the server yet), so an indicator can show nothing until the
|
|
19
|
+
* app has actually connected once.
|
|
20
|
+
*/
|
|
21
|
+
isOffline: Accessor<boolean>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Observe sync health for a "can't reach the server" banner / indicator.
|
|
26
|
+
*
|
|
27
|
+
* Backed by `db.subscribeToSyncHealth`. Individual sync failures (a transient
|
|
28
|
+
* remote 500 on query registration, a dropped socket) are absorbed by the
|
|
29
|
+
* retry and never flip this; `isDegraded()` only goes true once failures
|
|
30
|
+
* persist for the configured number of consecutive rounds (sp00ky core config
|
|
31
|
+
* `syncHealth.degradeAfterConsecutiveFailures`, default 3), and flips back on
|
|
32
|
+
* the next successful round. Must be used within a `<Sp00kyProvider>`.
|
|
33
|
+
*/
|
|
34
|
+
export function useSyncStatus(): UseSyncStatus {
|
|
35
|
+
const db = useDb();
|
|
36
|
+
// subscribeToSyncHealth fires synchronously with the current status, so the
|
|
37
|
+
// signal is correct from first read; the initial value just avoids a flash.
|
|
38
|
+
const [health, setHealth] = createSignal<SyncHealth>(db.syncHealth);
|
|
39
|
+
const unsub = db.subscribeToSyncHealth(setHealth);
|
|
40
|
+
onCleanup(unsub);
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
health,
|
|
44
|
+
status: () => health().status,
|
|
45
|
+
isHealthy: () => health().status === 'healthy',
|
|
46
|
+
isDegraded: () => health().status === 'degraded',
|
|
47
|
+
everConnected: () => health().everConnected,
|
|
48
|
+
isOffline: () => health().status === 'degraded' && health().everConnected,
|
|
49
|
+
};
|
|
50
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type { Surreal } from 'surrealdb';
|
|
2
1
|
import type { SyncedDb } from '../index';
|
|
3
|
-
import { GenericSchema } from '../lib/models';
|
|
4
|
-
import type {
|
|
2
|
+
import type { GenericSchema } from '../lib/models';
|
|
3
|
+
import type { Sp00kyConfig } from '@spooky-sync/core';
|
|
5
4
|
import type { SchemaStructure, TableNames, GetTable, TableModel } from '@spooky-sync/query-builder';
|
|
6
5
|
|
|
7
6
|
/**
|
|
@@ -44,7 +43,7 @@ export type InferRelationshipsFromConst<S extends SchemaStructure, Schema extend
|
|
|
44
43
|
// Prettify helper expands types for better intellisense
|
|
45
44
|
type Prettify<T> = { [K in keyof T]: T[K] } & {};
|
|
46
45
|
|
|
47
|
-
export type SyncedDbConfig<S extends SchemaStructure> = Prettify<
|
|
46
|
+
export type SyncedDbConfig<S extends SchemaStructure> = Prettify<Sp00kyConfig<S>>;
|
|
48
47
|
|
|
49
48
|
// export interface LocalDbConfig {
|
|
50
49
|
// name: string;
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { createSignal, onMount, createComponent, createMemo, JSX, mergeProps } from 'solid-js';
|
|
2
|
-
import type { SchemaStructure } from '@spooky/query-builder';
|
|
3
|
-
import type { SyncedDbConfig } from '../types';
|
|
4
|
-
import { SyncedDb } from '../index';
|
|
5
|
-
import { SpookyContext } from './context';
|
|
6
|
-
|
|
7
|
-
export interface SpookyProviderProps<S extends SchemaStructure> {
|
|
8
|
-
config: SyncedDbConfig<S>;
|
|
9
|
-
fallback?: JSX.Element;
|
|
10
|
-
onError?: (error: Error) => void;
|
|
11
|
-
onReady?: (db: SyncedDb<S>) => void;
|
|
12
|
-
children: JSX.Element;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function SpookyProvider<S extends SchemaStructure>(
|
|
16
|
-
props: SpookyProviderProps<S>
|
|
17
|
-
): JSX.Element {
|
|
18
|
-
const merged = mergeProps(
|
|
19
|
-
{
|
|
20
|
-
fallback: undefined as JSX.Element | undefined,
|
|
21
|
-
},
|
|
22
|
-
props
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
const [db, setDb] = createSignal<SyncedDb<S> | undefined>(undefined);
|
|
26
|
-
|
|
27
|
-
onMount(async () => {
|
|
28
|
-
try {
|
|
29
|
-
const instance = new SyncedDb<S>(merged.config);
|
|
30
|
-
await instance.init();
|
|
31
|
-
setDb(() => instance);
|
|
32
|
-
merged.onReady?.(instance);
|
|
33
|
-
} catch (e) {
|
|
34
|
-
const error = e instanceof Error ? e : new Error(String(e));
|
|
35
|
-
if (merged.onError) {
|
|
36
|
-
merged.onError(error);
|
|
37
|
-
} else {
|
|
38
|
-
console.error('SpookyProvider: Failed to initialize database', error);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
const content = createMemo(() => {
|
|
44
|
-
const instance = db();
|
|
45
|
-
if (!instance) return merged.fallback;
|
|
46
|
-
return createComponent(SpookyContext.Provider, {
|
|
47
|
-
value: instance,
|
|
48
|
-
get children() {
|
|
49
|
-
return merged.children;
|
|
50
|
-
},
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
return content as unknown as JSX.Element;
|
|
55
|
-
}
|