@xnetjs/react 0.0.2 → 0.0.3

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,392 @@
1
+ import { SyncManager, BlobStoreForSync, SyncStatus, ConnectionManager } from '@xnetjs/runtime';
2
+ import { DID } from '@xnetjs/core';
3
+ import { SecurityLevel } from '@xnetjs/crypto';
4
+ import { NodeStorageAdapter, NodeStore } from '@xnetjs/data';
5
+ import { Identity, PQKeyRegistry, HybridKeyBundle } from '@xnetjs/identity';
6
+ import { SyncReplicationConfig } from '@xnetjs/sync';
7
+ import * as react from 'react';
8
+ import { ReactNode } from 'react';
9
+ import { DataBridge, RemoteNodeQueryClient, NodeQueryRouterThresholds } from '@xnetjs/data-bridge';
10
+ import { UndoManager } from '@xnetjs/history';
11
+ import { Platform, PluginRegistry } from '@xnetjs/plugins';
12
+ import { T as TelemetryReporter } from './telemetry-context-B7r6H1KW.js';
13
+
14
+ /**
15
+ * Runtime configuration helpers for @xnetjs/react
16
+ */
17
+
18
+ type XNetRuntimeMode = 'main-thread' | 'worker' | 'ipc';
19
+ type XNetRuntimeFallback = 'main-thread' | 'error';
20
+ type XNetRuntimePhase = 'initializing' | 'ready' | 'error';
21
+ interface XNetRuntimeWorkerConfig {
22
+ /**
23
+ * Worker entry URL for the data runtime.
24
+ * When omitted, worker mode will fall back or error explicitly.
25
+ */
26
+ url?: string | URL;
27
+ /**
28
+ * Optional database name for worker-backed storage.
29
+ */
30
+ dbName?: string;
31
+ /**
32
+ * Optional signaling URL override for worker-backed sync.
33
+ */
34
+ signalingUrl?: string;
35
+ /**
36
+ * Optional MessagePort connected to the SQLite worker (from
37
+ * `WebSQLiteProxy.createMessagePort()`). Transferred to the data worker
38
+ * so its storage calls run worker-to-worker; without it the data worker
39
+ * uses in-memory storage.
40
+ */
41
+ storagePort?: MessagePort;
42
+ }
43
+ interface XNetRuntimeConfig {
44
+ /**
45
+ * Requested runtime mode for data and sync orchestration.
46
+ */
47
+ mode: XNetRuntimeMode;
48
+ /**
49
+ * Fallback behavior when the requested runtime cannot be activated.
50
+ */
51
+ fallback?: XNetRuntimeFallback;
52
+ /**
53
+ * Emit runtime diagnostics through console logging.
54
+ */
55
+ diagnostics?: boolean;
56
+ /**
57
+ * Worker-specific bootstrap options.
58
+ */
59
+ worker?: XNetRuntimeWorkerConfig;
60
+ }
61
+ interface XNetRuntimeStatus {
62
+ /**
63
+ * Runtime mode requested by app bootstrap.
64
+ */
65
+ requestedMode: XNetRuntimeMode;
66
+ /**
67
+ * Runtime mode currently active.
68
+ * Null while initializing or when runtime activation failed.
69
+ */
70
+ activeMode: XNetRuntimeMode | null;
71
+ /**
72
+ * Fallback mode that was used, if any.
73
+ */
74
+ fallbackMode: XNetRuntimeMode | null;
75
+ /**
76
+ * Whether the provider had to deviate from the requested runtime mode.
77
+ */
78
+ usedFallback: boolean;
79
+ /**
80
+ * Runtime initialization phase.
81
+ */
82
+ phase: XNetRuntimePhase;
83
+ /**
84
+ * Human-readable reason for fallback or failure.
85
+ */
86
+ reason: string | null;
87
+ }
88
+
89
+ /**
90
+ * Tracing context for @xnetjs/react (exploration 0190).
91
+ *
92
+ * Provides an optional duck-typed TracingReporter to the React tree. When
93
+ * present, useQuery/useMutate open a per-call trace and record main-thread
94
+ * stage spans. Mirrors the telemetry-context duck-typing so @xnetjs/react
95
+ * never has to depend on @xnetjs/telemetry (which would be circular).
96
+ *
97
+ * The reporter is satisfied by @xnetjs/telemetry's `TraceCollector`. When no
98
+ * reporter is supplied the hooks pay nothing — `tracing?.startTrace(...)` is a
99
+ * no-op and the optional chaining short-circuits.
100
+ */
101
+ declare const TRACE_STAGES: {
102
+ readonly queryDescriptor: "data.query.descriptor";
103
+ readonly queryBridge: "data.query.bridge";
104
+ readonly queryFlatten: "data.query.flatten";
105
+ readonly queryCommit: "data.query.commit";
106
+ readonly mutateBridge: "data.mutate.bridge";
107
+ };
108
+ type TracingRootKind = 'query' | 'mutate' | 'sync' | 'other';
109
+ type TracingAttributes = Record<string, string | number | boolean | undefined>;
110
+ interface TracingSpanInput {
111
+ name: string;
112
+ startOffsetMs: number;
113
+ durationMs: number;
114
+ parentSpanId?: string;
115
+ attributes?: TracingAttributes;
116
+ }
117
+ /** A handle to an in-progress trace. Inert when the trace is not being captured. */
118
+ interface TracingHandle {
119
+ readonly traceId: string;
120
+ readonly active: boolean;
121
+ /** Start timing a stage; the returned fn records the span when called. */
122
+ mark(name: string, parentSpanId?: string): (attributes?: TracingAttributes) => string;
123
+ addSpan(span: TracingSpanInput): string;
124
+ end(): unknown;
125
+ }
126
+ /**
127
+ * Duck-typed interface for opening traces. Satisfied by @xnetjs/telemetry's
128
+ * `TraceCollector` (structurally — `startTrace` returns a compatible handle).
129
+ */
130
+ interface TracingReporter {
131
+ startTrace(rootKind: TracingRootKind, rootName: string, traceId?: string): TracingHandle;
132
+ }
133
+ declare const TracingContext: react.Context<TracingReporter | null>;
134
+ /**
135
+ * Hook to access the tracing reporter (null if no tracing configured).
136
+ * @internal Used by useQuery/useMutate — not part of the public hook API.
137
+ */
138
+ declare function useTracingReporter(): TracingReporter | null;
139
+
140
+ /**
141
+ * XNet React context provider
142
+ *
143
+ * Provides NodeStore and optional identity to the React tree.
144
+ * All data access happens through useQuery/useMutate/useNode hooks.
145
+ */
146
+
147
+ /**
148
+ * XNet configuration
149
+ */
150
+ interface XNetConfig {
151
+ /** Node storage adapter for NodeStore (defaults to MemoryNodeStorageAdapter) */
152
+ nodeStorage?: NodeStorageAdapter;
153
+ /** Author's DID for signing changes */
154
+ authorDID?: DID;
155
+ /** Ed25519 signing key */
156
+ signingKey?: Uint8Array;
157
+ /** User identity */
158
+ identity?: Identity;
159
+ /** Signaling server URLs for sync (default: ['ws://localhost:4444']) */
160
+ signalingServers?: string[];
161
+ /** Hub WebSocket URL for always-on sync (overrides signalingServers[0]) */
162
+ hubUrl?: string;
163
+ /**
164
+ * Optional billing config (exploration 0187), surfaced to `useBilling`. The
165
+ * default redirect-checkout flow needs neither field — the hub creates checkout
166
+ * sessions server-side with the secret key. Use `apiBase` only to point billing
167
+ * at a different origin than the hub, and `publishableKey` only for future
168
+ * embedded (Stripe Elements) checkout.
169
+ */
170
+ billing?: {
171
+ /** Base URL for the hub billing routes. Defaults to the hub's HTTP URL. */
172
+ apiBase?: string;
173
+ /** Stripe publishable key (`pk_…`). The secret key NEVER goes on the client. */
174
+ publishableKey?: string;
175
+ };
176
+ /** Hub integration options */
177
+ hubOptions?: {
178
+ /** Auto-generate UCAN for hub auth (default: true) */
179
+ autoAuth?: boolean;
180
+ /** Static UCAN token override for pre-authorized share sessions */
181
+ authToken?: string;
182
+ /** Enable auto-backup on document updates (default: false) */
183
+ autoBackup?: boolean;
184
+ /** Backup debounce delay in ms (default: 5000) */
185
+ backupDebounceMs?: number;
186
+ /** Enable search indexing on NodeStore changes (default: false) */
187
+ enableSearchIndex?: boolean;
188
+ /** Room name for node-change relay (defaults to author DID) */
189
+ nodeSyncRoom?: string;
190
+ };
191
+ /** Encryption key for hub backups (XChaCha20-Poly1305) */
192
+ encryptionKey?: Uint8Array;
193
+ /** Disable Background Sync Manager (default: false) */
194
+ disableSyncManager?: boolean;
195
+ /** Provide an external SyncManager (e.g., IPC-based for Electron desktop).
196
+ * When provided, the internal SyncManager creation is skipped. */
197
+ syncManager?: SyncManager;
198
+ /** Blob store for P2P blob sync (images, files). If provided, the SyncManager
199
+ * will sync blobs alongside Y.Doc state. Typically a BlobStore from @xnetjs/storage. */
200
+ blobStore?: BlobStoreForSync;
201
+ /** Platform for plugin compatibility ('web' | 'electron' | 'mobile'). Defaults to 'web'. */
202
+ platform?: Platform;
203
+ /** Signed replication policy for document sync. */
204
+ sync?: SyncReplicationConfig;
205
+ /** Disable plugin system (default: false) */
206
+ disablePlugins?: boolean;
207
+ /**
208
+ * Explicit runtime selection for bridge and sync bootstrap.
209
+ */
210
+ runtime?: XNetRuntimeConfig;
211
+ /**
212
+ * Custom DataBridge instance.
213
+ *
214
+ * When provided, this bridge is used for data access instead of creating
215
+ * a MainThreadBridge. This allows using WorkerBridge or other off-main-thread
216
+ * implementations.
217
+ *
218
+ * The bridge must already be initialized before passing to XNetProvider.
219
+ *
220
+ * Note: When using a custom bridge, NodeStore is still created on the main
221
+ * thread for SyncManager and other integrations. The custom bridge is used
222
+ * only for React hook data access (useQuery, useMutate).
223
+ *
224
+ * @example
225
+ * ```tsx
226
+ * // Using WorkerBridge
227
+ * const bridge = new WorkerBridge(workerUrl)
228
+ * await bridge.initialize({ authorDID, signingKey, dbName: 'xnet' })
229
+ *
230
+ * <XNetProvider config={{ dataBridge: bridge, ... }}>
231
+ * <App />
232
+ * </XNetProvider>
233
+ * ```
234
+ */
235
+ dataBridge?: DataBridge;
236
+ /**
237
+ * Optional remote Node query client for progressive `useQuery` reads.
238
+ *
239
+ * When provided with the main-thread bridge, queries using
240
+ * `mode: 'local-then-remote'` render the local snapshot first and then merge
241
+ * hub/federated results. Queries using `mode: 'remote'` use this client as
242
+ * their primary source.
243
+ */
244
+ remoteNodeQueryClient?: RemoteNodeQueryClient;
245
+ /**
246
+ * Optional routing thresholds for `source: "auto"` Node descriptor reads.
247
+ *
248
+ * These thresholds are used by the main-thread bridge after the first local
249
+ * snapshot to decide whether a remote client should refresh the same query.
250
+ */
251
+ remoteNodeQueryRouting?: Partial<NodeQueryRouterThresholds>;
252
+ /**
253
+ * Security configuration for multi-level cryptography.
254
+ */
255
+ security?: {
256
+ /** Default security level for new signatures (default: 0 for Ed25519-only) */
257
+ level?: SecurityLevel;
258
+ /** Minimum acceptable level for verification (default: 0) */
259
+ minVerificationLevel?: SecurityLevel;
260
+ /** Verification policy (default: 'strict') */
261
+ verificationPolicy?: 'strict' | 'permissive';
262
+ /** Custom PQ key registry */
263
+ registry?: PQKeyRegistry;
264
+ };
265
+ /**
266
+ * Hybrid key bundle for multi-level cryptography.
267
+ *
268
+ * When provided, enables signing at higher security levels (1, 2).
269
+ * The bundle includes Ed25519 keys and optionally ML-DSA (post-quantum) keys.
270
+ *
271
+ * @example
272
+ * ```tsx
273
+ * const bundle = createKeyBundle({ includePQ: true })
274
+ *
275
+ * <XNetProvider config={{ keyBundle: bundle, ... }}>
276
+ * <App />
277
+ * </XNetProvider>
278
+ * ```
279
+ */
280
+ keyBundle?: HybridKeyBundle;
281
+ /**
282
+ * Optional telemetry reporter for hook instrumentation.
283
+ *
284
+ * When provided, useQuery and useMutate hooks will report:
285
+ * - Query timing (first-load latency)
286
+ * - Cache hit/miss rates
287
+ * - Mutation success/failure rates
288
+ * - Subscription churn (mount/unmount frequency)
289
+ *
290
+ * Uses a duck-typed interface to avoid circular dependencies with @xnetjs/telemetry.
291
+ *
292
+ * @example
293
+ * ```tsx
294
+ * import { TelemetryCollector, ConsentManager } from '@xnetjs/telemetry'
295
+ * const consent = new ConsentManager()
296
+ * const telemetry = new TelemetryCollector({ consent })
297
+ *
298
+ * <XNetProvider config={{ telemetry, ... }}>
299
+ * <App />
300
+ * </XNetProvider>
301
+ * ```
302
+ */
303
+ telemetry?: TelemetryReporter;
304
+ /**
305
+ * Optional full-stack tracing reporter (exploration 0190).
306
+ *
307
+ * When provided, useQuery/useMutate open a per-call trace and record
308
+ * main-thread stage spans, assembled into a local waterfall (devtools) and
309
+ * — when sampled — folded into bucketed performance metrics. Satisfied by
310
+ * @xnetjs/telemetry's `TraceCollector`. Duck-typed to avoid a circular dep.
311
+ */
312
+ tracing?: TracingReporter;
313
+ }
314
+ /**
315
+ * XNet context value
316
+ */
317
+ interface XNetContextValue {
318
+ /** NodeStore for Node operations */
319
+ nodeStore: NodeStore | null;
320
+ /** Whether NodeStore is initialized */
321
+ nodeStoreReady: boolean;
322
+ /** User identity (if provided) */
323
+ identity?: Identity;
324
+ /** Author DID (resolved from config.authorDID or config.identity.did) */
325
+ authorDID: string | null;
326
+ /** Background Sync Manager (null if disabled or not yet initialized) */
327
+ syncManager: SyncManager | null;
328
+ /** Hub URL (if configured) */
329
+ hubUrl: string | null;
330
+ /** Hub connection status */
331
+ hubStatus: SyncStatus;
332
+ /** Hub connection (shares SyncManager connection when available) */
333
+ hubConnection: ConnectionManager | null;
334
+ /** Hub auth token provider (for HTTP requests) */
335
+ getHubAuthToken?: () => Promise<string>;
336
+ /** Billing config (exploration 0187), surfaced to useBilling. */
337
+ billing?: {
338
+ apiBase?: string;
339
+ publishableKey?: string;
340
+ };
341
+ /** Encryption key for hub backups */
342
+ encryptionKey: Uint8Array | null;
343
+ /** Blob store for content-addressed storage (null if not configured) */
344
+ blobStore: BlobStoreForSync | null;
345
+ /** Plugin Registry (null if disabled or not yet initialized) */
346
+ pluginRegistry: PluginRegistry | null;
347
+ /** Runtime mode request, fallback behavior, and active runtime status */
348
+ runtimeStatus: XNetRuntimeStatus;
349
+ /**
350
+ * App-wide undo manager — one stack across every node-backed surface
351
+ * (folders, tasks, databases, chat, settings). Drives Cmd+Z via
352
+ * undoLatest/redoLatest. Null until the NodeStore is ready (0179).
353
+ */
354
+ undoManager: UndoManager | null;
355
+ }
356
+ type XNetInternalContextValue = {
357
+ authorDID: string | null;
358
+ signingKey: Uint8Array | null;
359
+ sync: SyncReplicationConfig | undefined;
360
+ };
361
+ /**
362
+ * Hook to access the DataBridge.
363
+ * Returns null while the bridge is initializing.
364
+ *
365
+ * @internal Used by useQuery/useMutate hooks - not part of public API yet.
366
+ */
367
+ declare function useDataBridge(): DataBridge | null;
368
+ /**
369
+ * XNet provider props
370
+ */
371
+ interface XNetProviderProps {
372
+ config: XNetConfig;
373
+ children: ReactNode;
374
+ }
375
+ /**
376
+ * XNet provider component
377
+ *
378
+ * Initializes NodeStore and provides it to the React tree.
379
+ */
380
+ declare function XNetProvider({ config, children }: XNetProviderProps): JSX.Element;
381
+ /**
382
+ * Hook to access XNet context
383
+ *
384
+ * @internal Used by useIdentity. Not part of public API.
385
+ */
386
+ declare function useXNet(): XNetContextValue;
387
+ /**
388
+ * @internal Internal access to sync credentials and replication policy.
389
+ */
390
+ declare function useXNetInternal(): XNetInternalContextValue;
391
+
392
+ export { TracingContext as T, type XNetContextValue as X, useXNet as a, useXNetInternal as b, type XNetInternalContextValue as c, type XNetRuntimeStatus as d, XNetProvider as e, type XNetConfig as f, type XNetProviderProps as g, type XNetRuntimeConfig as h, type XNetRuntimeFallback as i, type XNetRuntimeMode as j, type XNetRuntimePhase as k, type XNetRuntimeWorkerConfig as l, useTracingReporter as m, TRACE_STAGES as n, type TracingReporter as o, type TracingHandle as p, type TracingSpanInput as q, type TracingRootKind as r, type TracingAttributes as s, useDataBridge as u };