@xnetjs/react 0.0.2 → 0.1.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/README.md +206 -2
- package/dist/chunk-6VOICQZ3.js +760 -0
- package/dist/chunk-7OQXRHEQ.js +4649 -0
- package/dist/chunk-EJ5RW5GI.js +93 -0
- package/dist/chunk-IHTMVTTE.js +1108 -0
- package/dist/chunk-JCOFKBOB.js +11 -0
- package/dist/chunk-KSHTDZ2V.js +893 -0
- package/dist/chunk-QHNYQVUM.js +989 -0
- package/dist/context-CFu9i136.d.ts +392 -0
- package/dist/core.d.ts +372 -0
- package/dist/core.js +29 -0
- package/dist/database.d.ts +383 -0
- package/dist/database.js +19 -0
- package/dist/experimental-B2FrBnkV.d.ts +1584 -0
- package/dist/experimental.d.ts +15 -0
- package/dist/experimental.js +248 -0
- package/dist/index.d.ts +601 -2700
- package/dist/index.js +4782 -4427
- package/dist/{instrumentation-Cn94kn8-.d.ts → instrumentation-CpIuG2y5.d.ts} +32 -1
- package/dist/internal.d.ts +32 -22
- package/dist/internal.js +16 -4
- package/dist/telemetry-context-B7r6H1KW.d.ts +35 -0
- package/dist/useNodeStore-DTCSBF51.d.ts +28 -0
- package/dist/useQuery-D7ajycrc.d.ts +302 -0
- package/package.json +28 -10
- package/dist/chunk-CWHCGYDW.js +0 -2238
package/dist/index.d.ts
CHANGED
|
@@ -1,2782 +1,683 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
* Properties from future schema versions that aren't known to the current schema.
|
|
49
|
-
* Preserved for forward compatibility - can be displayed in a "raw data" view.
|
|
50
|
-
*/
|
|
51
|
-
_unknown?: Record<string, unknown>;
|
|
52
|
-
/**
|
|
53
|
-
* The schema version that last wrote to this node.
|
|
54
|
-
* Useful for detecting when migrations might be needed.
|
|
55
|
-
*/
|
|
56
|
-
_schemaVersion?: string;
|
|
57
|
-
/**
|
|
58
|
-
* The original schema IRI this node was migrated from.
|
|
59
|
-
* Only present if the node was automatically migrated on read.
|
|
60
|
-
*/
|
|
61
|
-
_migratedFrom?: SchemaIRI;
|
|
62
|
-
/**
|
|
63
|
-
* Full migration info if the node was migrated.
|
|
64
|
-
* Includes lossless flag and any warnings about data loss.
|
|
65
|
-
*/
|
|
66
|
-
_migrationInfo?: MigrationInfo;
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* A flattened node with properties at the top level.
|
|
70
|
-
*
|
|
71
|
-
* Instead of `node.properties.title`, access `node.title` directly.
|
|
72
|
-
* All property types are correctly inferred from the schema.
|
|
73
|
-
*
|
|
74
|
-
* @example
|
|
75
|
-
* ```tsx
|
|
76
|
-
* const { data } = useQuery(TaskSchema, id)
|
|
77
|
-
* // data is FlatNode<typeof TaskSchema._properties>
|
|
78
|
-
*
|
|
79
|
-
* console.log(data.title) // string - correctly typed!
|
|
80
|
-
* console.log(data.status) // 'todo' | 'done' - union type!
|
|
81
|
-
* ```
|
|
82
|
-
*/
|
|
83
|
-
type FlatNode<P extends Record<string, PropertyBuilder>> = NodeBase & InferCreateProps<P>;
|
|
84
|
-
/**
|
|
85
|
-
* Options for flattenNode function
|
|
86
|
-
*/
|
|
87
|
-
interface FlattenNodeOptions {
|
|
88
|
-
/**
|
|
89
|
-
* Mark this node as having an unknown schema.
|
|
90
|
-
* This happens when the node's schemaId is not registered in the current app version.
|
|
91
|
-
*/
|
|
92
|
-
unknownSchema?: boolean;
|
|
93
|
-
/**
|
|
94
|
-
* Migration info if the node was migrated from a different schema version.
|
|
95
|
-
*/
|
|
96
|
-
migrationInfo?: MigrationInfo;
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Flatten a NodeState by spreading properties to top level.
|
|
100
|
-
*
|
|
101
|
-
* @param node - The NodeState with nested properties
|
|
102
|
-
* @param options - Optional settings for handling unknown schemas
|
|
103
|
-
* @returns A new object with properties flattened to top level
|
|
104
|
-
*
|
|
105
|
-
* @example
|
|
106
|
-
* ```ts
|
|
107
|
-
* const nodeState = {
|
|
108
|
-
* id: '123',
|
|
109
|
-
* schemaId: 'xnet://xnet.fyi/Task',
|
|
110
|
-
* properties: { title: 'My Task', status: 'todo' },
|
|
111
|
-
* // ...
|
|
112
|
-
* }
|
|
113
|
-
*
|
|
114
|
-
* const flat = flattenNode(nodeState)
|
|
115
|
-
* // { id: '123', schemaId: '...', title: 'My Task', status: 'todo', ... }
|
|
116
|
-
* ```
|
|
117
|
-
*/
|
|
118
|
-
declare function flattenNode<P extends Record<string, PropertyBuilder>>(node: NodeState | MigratedNodeState, options?: FlattenNodeOptions): FlatNode<P>;
|
|
119
|
-
/**
|
|
120
|
-
* Flatten an array of NodeState objects.
|
|
121
|
-
*/
|
|
122
|
-
declare function flattenNodes<P extends Record<string, PropertyBuilder>>(nodes: (NodeState | MigratedNodeState)[], options?: FlattenNodeOptions): FlatNode<P>[];
|
|
123
|
-
/**
|
|
124
|
-
* Create a FlatNode with unknown schema flag.
|
|
125
|
-
* Use this when displaying nodes whose schema is not registered.
|
|
126
|
-
*/
|
|
127
|
-
declare function flattenUnknownSchemaNode(node: NodeState): FlatNode<Record<string, PropertyBuilder>>;
|
|
128
|
-
/**
|
|
129
|
-
* Create FlatNodes from an array, marking those with unknown schemas.
|
|
130
|
-
*
|
|
131
|
-
* @param nodes - Array of NodeState objects
|
|
132
|
-
* @param isSchemaKnown - Function to check if a schema is registered
|
|
133
|
-
* @returns Array of FlatNodes with _unknownSchema set appropriately
|
|
134
|
-
*/
|
|
135
|
-
declare function flattenNodesWithSchemaCheck<P extends Record<string, PropertyBuilder>>(nodes: NodeState[], isSchemaKnown: (schemaId: string) => boolean): FlatNode<P>[];
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* useQuery - Unified read hook for Nodes via DataBridge
|
|
139
|
-
*
|
|
140
|
-
* A single hook for all read operations:
|
|
141
|
-
* - List all nodes of a schema
|
|
142
|
-
* - Get a single node by ID
|
|
143
|
-
* - Query with filters
|
|
144
|
-
*
|
|
145
|
-
* Returns FlatNode with properties at top level for ergonomic access.
|
|
146
|
-
*
|
|
147
|
-
* Uses DataBridge for off-main-thread data access. The bridge handles
|
|
148
|
-
* caching and provides useSyncExternalStore-compatible subscriptions.
|
|
149
|
-
*
|
|
150
|
-
* @example
|
|
151
|
-
* ```tsx
|
|
152
|
-
* // List all tasks
|
|
153
|
-
* const { data: tasks } = useQuery(TaskSchema)
|
|
154
|
-
* tasks.forEach(task => console.log(task.title)) // Direct access!
|
|
155
|
-
*
|
|
156
|
-
* // Get single task by ID
|
|
157
|
-
* const { data: task } = useQuery(TaskSchema, taskId)
|
|
158
|
-
* console.log(task?.status) // Typed correctly!
|
|
159
|
-
*
|
|
160
|
-
* // Query with filters
|
|
161
|
-
* const { data: urgent } = useQuery(TaskSchema, {
|
|
162
|
-
* where: { status: 'urgent' },
|
|
163
|
-
* orderBy: { createdAt: 'desc' }
|
|
164
|
-
* })
|
|
165
|
-
* ```
|
|
166
|
-
*/
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Sort direction
|
|
170
|
-
*/
|
|
171
|
-
type SortDirection = 'asc' | 'desc';
|
|
172
|
-
/**
|
|
173
|
-
* System fields that can be used for ordering
|
|
174
|
-
*/
|
|
175
|
-
type SystemOrderField = 'createdAt' | 'updatedAt';
|
|
176
|
-
/**
|
|
177
|
-
* Query filter options
|
|
178
|
-
*/
|
|
179
|
-
interface QueryFilter<P extends Record<string, PropertyBuilder> = Record<string, PropertyBuilder>> {
|
|
180
|
-
/** Filter conditions (property: value) */
|
|
181
|
-
where?: Partial<InferCreateProps<P>>;
|
|
182
|
-
/** Include soft-deleted nodes */
|
|
183
|
-
includeDeleted?: boolean;
|
|
184
|
-
/** Sort by property or system field (createdAt, updatedAt) */
|
|
185
|
-
orderBy?: {
|
|
186
|
-
[K in keyof InferCreateProps<P> | SystemOrderField]?: SortDirection;
|
|
187
|
-
};
|
|
188
|
-
/** Limit results */
|
|
189
|
-
limit?: number;
|
|
190
|
-
/** Offset for pagination */
|
|
191
|
-
offset?: number;
|
|
192
|
-
}
|
|
193
|
-
/**
|
|
194
|
-
* Migration warning info
|
|
195
|
-
*/
|
|
196
|
-
interface MigrationWarning {
|
|
197
|
-
/** The node ID that was migrated */
|
|
198
|
-
nodeId: string;
|
|
199
|
-
/** The original schema IRI */
|
|
200
|
-
from: string;
|
|
201
|
-
/** The target schema IRI */
|
|
202
|
-
to: string;
|
|
203
|
-
/** Warning messages about potential data loss */
|
|
204
|
-
warnings: string[];
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Result when querying a list of nodes
|
|
208
|
-
*/
|
|
209
|
-
interface QueryListResult<P extends Record<string, PropertyBuilder>> {
|
|
210
|
-
/** The queried nodes (flattened - access properties directly) */
|
|
211
|
-
data: FlatNode<P>[];
|
|
212
|
-
/** Whether currently loading */
|
|
213
|
-
loading: boolean;
|
|
214
|
-
/** Any error that occurred */
|
|
215
|
-
error: Error | null;
|
|
216
|
-
/** Reload the query */
|
|
217
|
-
reload: () => void;
|
|
218
|
-
/**
|
|
219
|
-
* Migration warnings for nodes that were migrated from different schema versions.
|
|
220
|
-
* Only populated if nodes required migration and the migration was lossy.
|
|
221
|
-
*/
|
|
222
|
-
migrationWarnings: MigrationWarning[];
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* Result when querying a single node
|
|
226
|
-
*/
|
|
227
|
-
interface QuerySingleResult<P extends Record<string, PropertyBuilder>> {
|
|
228
|
-
/** The queried node (flattened - access properties directly), null if not found */
|
|
229
|
-
data: FlatNode<P> | null;
|
|
230
|
-
/** Whether currently loading */
|
|
231
|
-
loading: boolean;
|
|
232
|
-
/** Any error that occurred */
|
|
233
|
-
error: Error | null;
|
|
234
|
-
/** Reload the query */
|
|
235
|
-
reload: () => void;
|
|
236
|
-
/**
|
|
237
|
-
* Migration warnings if the node was migrated from a different schema version.
|
|
238
|
-
* Only populated if the node required migration and the migration was lossy.
|
|
239
|
-
*/
|
|
240
|
-
migrationWarnings: MigrationWarning[];
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* Query all nodes of a schema
|
|
244
|
-
*/
|
|
245
|
-
declare function useQuery<P extends Record<string, PropertyBuilder>>(schema: DefinedSchema<P>): QueryListResult<P>;
|
|
246
|
-
/**
|
|
247
|
-
* Query a single node by ID
|
|
248
|
-
*/
|
|
249
|
-
declare function useQuery<P extends Record<string, PropertyBuilder>>(schema: DefinedSchema<P>, id: string): QuerySingleResult<P>;
|
|
250
|
-
/**
|
|
251
|
-
* Query nodes with filters
|
|
252
|
-
*/
|
|
253
|
-
declare function useQuery<P extends Record<string, PropertyBuilder>>(schema: DefinedSchema<P>, filter: QueryFilter<P>): QueryListResult<P>;
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* useMutate - Unified write hook for Nodes via DataBridge
|
|
257
|
-
*
|
|
258
|
-
* A single hook for all write operations:
|
|
259
|
-
* - Create nodes (requires schema)
|
|
260
|
-
* - Update nodes (requires schema for type safety)
|
|
261
|
-
* - Delete nodes (by ID)
|
|
262
|
-
* - Atomic transactions (multiple operations)
|
|
263
|
-
*
|
|
264
|
-
* Uses DataBridge for off-main-thread data access.
|
|
265
|
-
*
|
|
266
|
-
* Features:
|
|
267
|
-
* - Immediate local updates (bridge updates UI subscribers synchronously)
|
|
268
|
-
* - Type-safe schema-bound mutations
|
|
269
|
-
* - Transaction support for atomic multi-node operations
|
|
270
|
-
* - Pending state tracking
|
|
271
|
-
*
|
|
272
|
-
* @example
|
|
273
|
-
* ```tsx
|
|
274
|
-
* const { create, update, remove, mutate, isPending } = useMutate()
|
|
275
|
-
*
|
|
276
|
-
* // Simple operations
|
|
277
|
-
* await create(TaskSchema, { title: 'New Task', status: 'todo' })
|
|
278
|
-
* await update(TaskSchema, taskId, { status: 'done' }) // Type-safe!
|
|
279
|
-
* await remove(taskId)
|
|
280
|
-
*
|
|
281
|
-
* // Atomic transaction
|
|
282
|
-
* await mutate([
|
|
283
|
-
* { type: 'create', schema: TaskSchema, data: { title: 'Task 1' } },
|
|
284
|
-
* { type: 'update', id: taskId, data: { status: 'done' } },
|
|
285
|
-
* { type: 'delete', id: oldTaskId }
|
|
286
|
-
* ])
|
|
287
|
-
* ```
|
|
288
|
-
*/
|
|
289
|
-
|
|
290
|
-
/**
|
|
291
|
-
* Create operation for mutate
|
|
292
|
-
*/
|
|
293
|
-
interface MutateCreate<P extends Record<string, PropertyBuilder> = Record<string, PropertyBuilder>> {
|
|
294
|
-
type: 'create';
|
|
295
|
-
schema: DefinedSchema<P>;
|
|
296
|
-
data: InferCreateProps<P>;
|
|
297
|
-
id?: string;
|
|
298
|
-
}
|
|
299
|
-
/**
|
|
300
|
-
* Update operation for mutate
|
|
301
|
-
*/
|
|
302
|
-
interface MutateUpdate {
|
|
303
|
-
type: 'update';
|
|
304
|
-
id: string;
|
|
305
|
-
data: Record<string, unknown>;
|
|
306
|
-
}
|
|
307
|
-
/**
|
|
308
|
-
* Delete operation for mutate
|
|
309
|
-
*/
|
|
310
|
-
interface MutateDelete {
|
|
311
|
-
type: 'delete';
|
|
312
|
-
id: string;
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* Restore operation for mutate
|
|
316
|
-
*/
|
|
317
|
-
interface MutateRestore {
|
|
318
|
-
type: 'restore';
|
|
319
|
-
id: string;
|
|
320
|
-
}
|
|
321
|
-
/**
|
|
322
|
-
* All possible mutate operations
|
|
323
|
-
*/
|
|
324
|
-
type MutateOp = MutateCreate<Record<string, PropertyBuilder>> | MutateUpdate | MutateDelete | MutateRestore;
|
|
325
|
-
/**
|
|
326
|
-
* Result from a mutate transaction
|
|
327
|
-
*/
|
|
328
|
-
interface MutateResult {
|
|
329
|
-
/** Results for each operation (NodeState or null for delete) */
|
|
330
|
-
results: (NodeState | null)[];
|
|
331
|
-
/** Batch ID when transaction backend is available */
|
|
332
|
-
batchId?: string;
|
|
333
|
-
/** Temp ID mapping when transaction backend is available */
|
|
334
|
-
tempIds?: Record<string, string>;
|
|
335
|
-
}
|
|
336
|
-
/**
|
|
337
|
-
* Result from useMutate hook
|
|
338
|
-
*/
|
|
339
|
-
interface UseMutateResult {
|
|
340
|
-
/**
|
|
341
|
-
* Create a new node.
|
|
342
|
-
* Requires a schema to know what type to create.
|
|
343
|
-
* Optionally specify a custom ID (otherwise auto-generated).
|
|
344
|
-
*
|
|
345
|
-
* @returns The created node (flattened), or null if creation failed
|
|
346
|
-
*/
|
|
347
|
-
create: <P extends Record<string, PropertyBuilder>>(schema: DefinedSchema<P>, data: InferCreateProps<P>, id?: string) => Promise<FlatNode<P> | null>;
|
|
348
|
-
/**
|
|
349
|
-
* Update an existing node by ID.
|
|
350
|
-
* Requires schema for type-safe property checking.
|
|
351
|
-
*
|
|
352
|
-
* @example
|
|
353
|
-
* ```tsx
|
|
354
|
-
* await update(TaskSchema, taskId, { status: 'done' }) // OK
|
|
355
|
-
* await update(TaskSchema, taskId, { typo: 'x' }) // Type error!
|
|
356
|
-
* ```
|
|
357
|
-
*
|
|
358
|
-
* @returns The updated node (flattened), or null if update failed
|
|
359
|
-
*/
|
|
360
|
-
update: <P extends Record<string, PropertyBuilder>>(schema: DefinedSchema<P>, id: string, data: Partial<InferCreateProps<P>>) => Promise<FlatNode<P> | null>;
|
|
361
|
-
/**
|
|
362
|
-
* Delete a node by ID (soft delete).
|
|
363
|
-
*/
|
|
364
|
-
remove: (id: string) => Promise<void>;
|
|
365
|
-
/**
|
|
366
|
-
* Restore a deleted node by ID.
|
|
367
|
-
*
|
|
368
|
-
* @returns The restored node (flattened), or null if restore failed
|
|
369
|
-
*/
|
|
370
|
-
restore: (id: string) => Promise<FlatNode<Record<string, PropertyBuilder>> | null>;
|
|
371
|
-
/**
|
|
372
|
-
* Execute multiple operations atomically.
|
|
373
|
-
* All operations succeed or fail together.
|
|
374
|
-
*
|
|
375
|
-
* Note: Transaction support requires MainThreadBridge with direct NodeStore access.
|
|
376
|
-
* WorkerBridge executes operations sequentially (not truly atomic).
|
|
377
|
-
*/
|
|
378
|
-
mutate: (ops: MutateOp[]) => Promise<MutateResult | null>;
|
|
379
|
-
/**
|
|
380
|
-
* Whether any mutation is currently in progress.
|
|
381
|
-
*/
|
|
382
|
-
isPending: boolean;
|
|
383
|
-
/**
|
|
384
|
-
* Number of pending mutations.
|
|
385
|
-
*/
|
|
386
|
-
pendingCount: number;
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* Hook for all write operations on Nodes via DataBridge.
|
|
390
|
-
*
|
|
391
|
-
* Provides both convenience methods (create, update, remove) and
|
|
392
|
-
* a full transaction API (mutate) for atomic multi-node operations.
|
|
393
|
-
*
|
|
394
|
-
* All operations update the local cache immediately, and subscribers
|
|
395
|
-
* see changes synchronously. Background sync handles persistence.
|
|
396
|
-
*/
|
|
397
|
-
declare function useMutate(): UseMutateResult;
|
|
398
|
-
|
|
399
|
-
/**
|
|
400
|
-
* useNode - The unified hook for working with a single Node
|
|
401
|
-
*
|
|
402
|
-
* This is the primary hook for editing Nodes. It provides:
|
|
403
|
-
* - Node properties (flattened for ergonomic access)
|
|
404
|
-
* - Y.Doc for collaborative rich text (if schema specifies document: 'yjs')
|
|
405
|
-
* - Auto-sync via WebSocket
|
|
406
|
-
* - Type-safe mutations (update, remove)
|
|
407
|
-
* - Presence awareness (live + hub snapshot)
|
|
408
|
-
* - Auto-create with createIfMissing
|
|
409
|
-
*
|
|
410
|
-
* @example
|
|
411
|
-
* ```tsx
|
|
412
|
-
* const {
|
|
413
|
-
* data, // FlatNode - access data.title directly!
|
|
414
|
-
* doc, // Y.Doc for rich text
|
|
415
|
-
* update, // Type-safe update function
|
|
416
|
-
* remove, // Soft delete
|
|
417
|
-
* syncStatus, // 'offline' | 'connecting' | 'connected'
|
|
418
|
-
* peerCount, // Number of connected peers
|
|
419
|
-
* presence, // Presence list (live + hub snapshot)
|
|
420
|
-
* loading,
|
|
421
|
-
* error
|
|
422
|
-
* } = useNode(PageSchema, pageId, {
|
|
423
|
-
* createIfMissing: { title: 'Untitled' }
|
|
424
|
-
* })
|
|
425
|
-
*
|
|
426
|
-
* // Update is type-safe!
|
|
427
|
-
* update({ title: 'New Title' }) // OK
|
|
428
|
-
* update({ typo: 'x' }) // Type error!
|
|
429
|
-
* ```
|
|
430
|
-
*/
|
|
431
|
-
|
|
432
|
-
/**
|
|
433
|
-
* Sync connection status
|
|
434
|
-
*/
|
|
435
|
-
type SyncStatus$1 = 'offline' | 'connecting' | 'connected' | 'error';
|
|
436
|
-
interface PresenceUser {
|
|
437
|
-
did: string;
|
|
438
|
-
name?: string;
|
|
439
|
-
color?: string;
|
|
440
|
-
lastSeen?: number;
|
|
441
|
-
isStale?: boolean;
|
|
442
|
-
}
|
|
443
|
-
/**
|
|
444
|
-
* Options for useNode
|
|
445
|
-
*/
|
|
446
|
-
interface UseNodeOptions<P extends Record<string, PropertyBuilder>> {
|
|
447
|
-
/** Signaling servers for y-webrtc (default: localhost for dev) */
|
|
448
|
-
signalingServers?: string[];
|
|
449
|
-
/** Disable auto-sync (default: false) */
|
|
450
|
-
disableSync?: boolean;
|
|
451
|
-
/** Debounce persistence delay in ms (default: 1000) */
|
|
452
|
-
persistDebounce?: number;
|
|
453
|
-
/**
|
|
454
|
-
* Auto-create the node if it doesn't exist.
|
|
455
|
-
* Provide the default properties to use for creation.
|
|
456
|
-
*/
|
|
457
|
-
createIfMissing?: InferCreateProps<P>;
|
|
458
|
-
/**
|
|
459
|
-
* User's DID for presence/cursors. If provided, broadcasts awareness state.
|
|
460
|
-
*/
|
|
461
|
-
did?: string;
|
|
462
|
-
}
|
|
463
|
-
/**
|
|
464
|
-
* Result from useNode hook
|
|
465
|
-
*/
|
|
466
|
-
interface UseNodeResult<P extends Record<string, PropertyBuilder>> {
|
|
467
|
-
/** Node properties (flattened - access directly: data.title) */
|
|
468
|
-
data: FlatNode<P> | null;
|
|
469
|
-
/** Yjs document instance (null if schema has no document type) */
|
|
470
|
-
doc: Y.Doc | null;
|
|
471
|
-
/**
|
|
472
|
-
* Update node properties (type-safe).
|
|
473
|
-
* Only properties defined in the schema are allowed.
|
|
474
|
-
*/
|
|
475
|
-
update: (properties: Partial<InferCreateProps<P>>) => Promise<void>;
|
|
476
|
-
/**
|
|
477
|
-
* Soft-delete the node.
|
|
478
|
-
*/
|
|
479
|
-
remove: () => Promise<void>;
|
|
480
|
-
/** Whether currently loading */
|
|
481
|
-
loading: boolean;
|
|
482
|
-
/** Any error that occurred */
|
|
483
|
-
error: Error | null;
|
|
484
|
-
/** Whether document has unsaved changes */
|
|
485
|
-
isDirty: boolean;
|
|
486
|
-
/** Last persistence timestamp */
|
|
487
|
-
lastSavedAt: number | null;
|
|
488
|
-
/** Whether the node was auto-created (via createIfMissing) */
|
|
489
|
-
wasCreated: boolean;
|
|
490
|
-
/** Sync connection status */
|
|
491
|
-
syncStatus: SyncStatus$1;
|
|
492
|
-
/** Sync error message (if syncStatus is 'error') */
|
|
493
|
-
syncError: string | null;
|
|
494
|
-
/** Connected peer count */
|
|
495
|
-
peerCount: number;
|
|
496
|
-
/** Presence list (live awareness + hub snapshot) */
|
|
497
|
-
presence: PresenceUser[];
|
|
498
|
-
/** Yjs Awareness instance (for TipTap CollaborationCursor) */
|
|
499
|
-
awareness: Awareness | null;
|
|
500
|
-
/** Manually trigger save */
|
|
501
|
-
save: () => Promise<void>;
|
|
502
|
-
/** Reload from storage */
|
|
503
|
-
reload: () => Promise<void>;
|
|
504
|
-
}
|
|
505
|
-
/**
|
|
506
|
-
* Load a Node with its CRDT document.
|
|
507
|
-
*
|
|
508
|
-
* This is the primary hook for editing content. It combines:
|
|
509
|
-
* - Data loading (with FlatNode for ergonomic access)
|
|
510
|
-
* - Y.Doc for collaborative rich text
|
|
511
|
-
* - Type-safe mutations
|
|
512
|
-
* - Real-time sync and presence
|
|
513
|
-
*/
|
|
514
|
-
declare function useNode<P extends Record<string, PropertyBuilder>>(schema: DefinedSchema<P>, id: string | null, options?: UseNodeOptions<P>): UseNodeResult<P>;
|
|
515
|
-
|
|
516
|
-
/**
|
|
517
|
-
* useDatabaseDoc - Hook for database column and view operations
|
|
518
|
-
*
|
|
519
|
-
* Provides reactive access to the database's Y.Doc structure:
|
|
520
|
-
* - Column definitions (CRDT-ordered)
|
|
521
|
-
* - View configurations
|
|
522
|
-
* - Column and view CRUD operations
|
|
523
|
-
*
|
|
524
|
-
* @example
|
|
525
|
-
* ```tsx
|
|
526
|
-
* const {
|
|
527
|
-
* columns,
|
|
528
|
-
* views,
|
|
529
|
-
* createColumn,
|
|
530
|
-
* updateColumn,
|
|
531
|
-
* deleteColumn,
|
|
532
|
-
* reorderColumn,
|
|
533
|
-
* createView,
|
|
534
|
-
* updateView,
|
|
535
|
-
* deleteView
|
|
536
|
-
* } = useDatabaseDoc(databaseId)
|
|
537
|
-
* ```
|
|
538
|
-
*/
|
|
539
|
-
|
|
540
|
-
interface UseDatabaseDocResult {
|
|
541
|
-
/** All column definitions (CRDT-ordered) */
|
|
542
|
-
columns: ColumnDefinition[];
|
|
543
|
-
/** All view configurations */
|
|
544
|
-
views: ViewConfig[];
|
|
545
|
-
/** Y.Doc for direct access (if needed) */
|
|
546
|
-
doc: Y.Doc | null;
|
|
547
|
-
/** Whether the doc is loading */
|
|
548
|
-
loading: boolean;
|
|
549
|
-
/** Any error that occurred */
|
|
550
|
-
error: Error | null;
|
|
551
|
-
/** Create a new column */
|
|
552
|
-
createColumn: (definition: Omit<ColumnDefinition, 'id'>) => string | null;
|
|
553
|
-
/** Update a column's properties */
|
|
554
|
-
updateColumn: (columnId: string, updates: Partial<Omit<ColumnDefinition, 'id'>>) => void;
|
|
555
|
-
/** Delete a column */
|
|
556
|
-
deleteColumn: (columnId: string) => void;
|
|
557
|
-
/** Reorder a column to a new position */
|
|
558
|
-
reorderColumn: (columnId: string, newIndex: number) => void;
|
|
559
|
-
/** Duplicate a column */
|
|
560
|
-
duplicateColumn: (columnId: string, newName?: string) => string | null;
|
|
561
|
-
/** Get a single column by ID */
|
|
562
|
-
getColumn: (columnId: string) => ColumnDefinition | null;
|
|
563
|
-
/** Create a new view */
|
|
564
|
-
createView: (config: Omit<ViewConfig, 'id'>) => string | null;
|
|
565
|
-
/** Update a view's properties */
|
|
566
|
-
updateView: (viewId: string, updates: Partial<Omit<ViewConfig, 'id'>>) => void;
|
|
567
|
-
/** Delete a view */
|
|
568
|
-
deleteView: (viewId: string) => void;
|
|
569
|
-
/** Duplicate a view */
|
|
570
|
-
duplicateView: (viewId: string, newName?: string) => string | null;
|
|
571
|
-
/** Get a single view by ID */
|
|
572
|
-
getView: (viewId: string) => ViewConfig | null;
|
|
573
|
-
}
|
|
574
|
-
/**
|
|
575
|
-
* Hook for database column and view operations.
|
|
576
|
-
*
|
|
577
|
-
* Provides reactive access to the database's Y.Doc structure with
|
|
578
|
-
* CRDT-based column ordering and real-time schema sync.
|
|
579
|
-
*/
|
|
580
|
-
declare function useDatabaseDoc(databaseId: string): UseDatabaseDocResult;
|
|
581
|
-
|
|
582
|
-
/**
|
|
583
|
-
* useDatabase - Hook for database row operations with pagination
|
|
584
|
-
*
|
|
585
|
-
* Provides:
|
|
586
|
-
* - Paginated row queries
|
|
587
|
-
* - Row CRUD operations
|
|
588
|
-
* - Integration with useDatabaseDoc for columns/views
|
|
589
|
-
*
|
|
590
|
-
* @example
|
|
591
|
-
* ```tsx
|
|
592
|
-
* const {
|
|
593
|
-
* rows,
|
|
594
|
-
* columns,
|
|
595
|
-
* views,
|
|
596
|
-
* loading,
|
|
597
|
-
* hasMore,
|
|
598
|
-
* loadMore,
|
|
599
|
-
* createRow,
|
|
600
|
-
* updateRow,
|
|
601
|
-
* deleteRow
|
|
602
|
-
* } = useDatabase(databaseId)
|
|
603
|
-
* ```
|
|
604
|
-
*/
|
|
605
|
-
|
|
606
|
-
interface UseDatabaseOptions {
|
|
607
|
-
/** Active view ID (uses first view if not specified) */
|
|
608
|
-
view?: string;
|
|
609
|
-
/** Override view filters */
|
|
610
|
-
filters?: FilterGroup;
|
|
611
|
-
/** Override view sorts */
|
|
612
|
-
sorts?: SortConfig[];
|
|
613
|
-
/** Search query (full-text search) - not yet implemented */
|
|
614
|
-
search?: string;
|
|
615
|
-
/** Page size (default: 50) */
|
|
616
|
-
pageSize?: number;
|
|
617
|
-
}
|
|
618
|
-
interface DatabaseRow {
|
|
619
|
-
/** Row ID */
|
|
620
|
-
id: string;
|
|
621
|
-
/** Sort key for ordering */
|
|
622
|
-
sortKey: string;
|
|
623
|
-
/** Cell values keyed by column ID */
|
|
624
|
-
cells: Record<string, CellValue>;
|
|
625
|
-
/** Creation timestamp */
|
|
626
|
-
createdAt: number;
|
|
627
|
-
/** Creator DID */
|
|
628
|
-
createdBy: string;
|
|
629
|
-
}
|
|
630
|
-
interface UseDatabaseResult {
|
|
631
|
-
/** Column definitions */
|
|
632
|
-
columns: ColumnDefinition[];
|
|
633
|
-
/** View configurations */
|
|
634
|
-
views: ViewConfig[];
|
|
635
|
-
/** Loaded rows */
|
|
636
|
-
rows: DatabaseRow[];
|
|
637
|
-
/** Total row count */
|
|
638
|
-
total: number;
|
|
639
|
-
/** Whether more rows are available */
|
|
640
|
-
hasMore: boolean;
|
|
641
|
-
/** Load more rows */
|
|
642
|
-
loadMore: () => Promise<void>;
|
|
643
|
-
/** Active view configuration */
|
|
644
|
-
activeView: ViewConfig | null;
|
|
645
|
-
/** Set the active view */
|
|
646
|
-
setActiveView: (viewId: string) => void;
|
|
647
|
-
/** Create a new row */
|
|
648
|
-
createRow: (values?: Record<string, CellValue>) => Promise<string>;
|
|
649
|
-
/** Update a row's cell values */
|
|
650
|
-
updateRow: (rowId: string, values: Record<string, CellValue>) => Promise<void>;
|
|
651
|
-
/** Delete a row */
|
|
652
|
-
deleteRow: (rowId: string) => Promise<void>;
|
|
653
|
-
/** Reorder a row */
|
|
654
|
-
reorderRow: (rowId: string, before?: string, after?: string) => Promise<void>;
|
|
655
|
-
/** Delete multiple rows */
|
|
656
|
-
deleteRows: (rowIds: string[]) => Promise<void>;
|
|
657
|
-
/** Whether initially loading */
|
|
658
|
-
loading: boolean;
|
|
659
|
-
/** Whether loading more rows */
|
|
660
|
-
loadingMore: boolean;
|
|
661
|
-
/** Any error that occurred */
|
|
662
|
-
error: Error | null;
|
|
663
|
-
/** Refetch all rows */
|
|
664
|
-
refetch: () => Promise<void>;
|
|
665
|
-
}
|
|
666
|
-
/**
|
|
667
|
-
* Hook for database row operations with pagination.
|
|
668
|
-
*/
|
|
669
|
-
declare function useDatabase(databaseId: string, options?: UseDatabaseOptions): UseDatabaseResult;
|
|
670
|
-
|
|
671
|
-
/**
|
|
672
|
-
* useDatabaseRow - Hook for single row operations with optimistic updates
|
|
673
|
-
*
|
|
674
|
-
* Provides:
|
|
675
|
-
* - Row data with cell values
|
|
676
|
-
* - Y.Doc for rich text cells
|
|
677
|
-
* - Optimistic updates
|
|
678
|
-
* - Delete operation
|
|
679
|
-
*
|
|
680
|
-
* @example
|
|
681
|
-
* ```tsx
|
|
682
|
-
* const {
|
|
683
|
-
* row,
|
|
684
|
-
* doc,
|
|
685
|
-
* update,
|
|
686
|
-
* delete: deleteRow,
|
|
687
|
-
* loading
|
|
688
|
-
* } = useDatabaseRow(rowId)
|
|
689
|
-
* ```
|
|
690
|
-
*/
|
|
691
|
-
|
|
692
|
-
interface DatabaseRowData {
|
|
693
|
-
/** Row ID */
|
|
694
|
-
id: string;
|
|
695
|
-
/** Database ID this row belongs to */
|
|
696
|
-
databaseId: string;
|
|
697
|
-
/** Sort key for ordering */
|
|
698
|
-
sortKey: string;
|
|
699
|
-
/** Cell values keyed by column ID */
|
|
700
|
-
cells: Record<string, CellValue>;
|
|
701
|
-
/** Creation timestamp */
|
|
702
|
-
createdAt: number;
|
|
703
|
-
/** Creator DID */
|
|
704
|
-
createdBy: string;
|
|
705
|
-
}
|
|
706
|
-
interface UseDatabaseRowResult {
|
|
707
|
-
/** Row data */
|
|
708
|
-
row: DatabaseRowData | null;
|
|
709
|
-
/** Y.Doc for rich text cells (if any) */
|
|
710
|
-
doc: Y.Doc | null;
|
|
711
|
-
/** Update cell values (with optimistic UI) */
|
|
712
|
-
update: (values: Record<string, CellValue>) => Promise<void>;
|
|
713
|
-
/** Delete this row */
|
|
714
|
-
delete: () => Promise<void>;
|
|
715
|
-
/** Loading state */
|
|
716
|
-
loading: boolean;
|
|
717
|
-
/** Error state */
|
|
718
|
-
error: Error | null;
|
|
719
|
-
}
|
|
720
|
-
/**
|
|
721
|
-
* Hook for single row operations with optimistic updates.
|
|
722
|
-
*/
|
|
723
|
-
declare function useDatabaseRow(rowId: string): UseDatabaseRowResult;
|
|
724
|
-
|
|
725
|
-
/**
|
|
726
|
-
* useCell - Hook for individual cell editing with debounced saves
|
|
727
|
-
*
|
|
728
|
-
* Provides:
|
|
729
|
-
* - Cell value with optimistic updates
|
|
730
|
-
* - Debounced persistence
|
|
731
|
-
* - Clear operation
|
|
732
|
-
*
|
|
733
|
-
* @example
|
|
734
|
-
* ```tsx
|
|
735
|
-
* const { value, setValue, saving } = useCell<string>(rowId, 'title')
|
|
736
|
-
*
|
|
737
|
-
* return (
|
|
738
|
-
* <Input
|
|
739
|
-
* value={value ?? ''}
|
|
740
|
-
* onChange={(e) => setValue(e.target.value)}
|
|
741
|
-
* className={saving ? 'opacity-50' : ''}
|
|
742
|
-
* />
|
|
743
|
-
* )
|
|
744
|
-
* ```
|
|
745
|
-
*/
|
|
746
|
-
|
|
747
|
-
interface UseCellResult<T extends CellValue = CellValue> {
|
|
748
|
-
/** Cell value */
|
|
749
|
-
value: T | null;
|
|
750
|
-
/** Update cell value (debounced save) */
|
|
751
|
-
setValue: (value: T | null) => void;
|
|
752
|
-
/** Clear cell value */
|
|
753
|
-
clear: () => void;
|
|
754
|
-
/** Whether cell is being saved */
|
|
755
|
-
saving: boolean;
|
|
756
|
-
/** Error from last save */
|
|
757
|
-
error: Error | null;
|
|
758
|
-
}
|
|
759
|
-
interface UseCellOptions {
|
|
760
|
-
/** Debounce delay in ms (default: 300) */
|
|
761
|
-
debounce?: number;
|
|
762
|
-
}
|
|
763
|
-
/**
|
|
764
|
-
* Hook for individual cell editing with debounced saves.
|
|
765
|
-
*/
|
|
766
|
-
declare function useCell<T extends CellValue = CellValue>(rowId: string, columnId: string, options?: UseCellOptions): UseCellResult<T>;
|
|
767
|
-
|
|
768
|
-
/**
|
|
769
|
-
* useRelatedRows - Hook for loading related row data for relation columns
|
|
770
|
-
*
|
|
771
|
-
* Fetches the row data for a list of row IDs, typically from a relation column.
|
|
772
|
-
*
|
|
773
|
-
* @example
|
|
774
|
-
* ```tsx
|
|
775
|
-
* const { rows, loading, error } = useRelatedRows(['row1', 'row2'])
|
|
776
|
-
* // rows contains the full row data for display
|
|
777
|
-
* ```
|
|
778
|
-
*/
|
|
779
|
-
|
|
780
|
-
interface UseRelatedRowsResult {
|
|
781
|
-
/** Loaded row data */
|
|
782
|
-
rows: DatabaseRow[];
|
|
783
|
-
/** Whether rows are loading */
|
|
784
|
-
loading: boolean;
|
|
785
|
-
/** Any error that occurred */
|
|
786
|
-
error: Error | null;
|
|
787
|
-
}
|
|
788
|
-
/**
|
|
789
|
-
* Hook for loading related row data.
|
|
790
|
-
*
|
|
791
|
-
* @param rowIds - Array of row IDs to load
|
|
792
|
-
* @returns Object containing rows, loading state, and error
|
|
793
|
-
*/
|
|
794
|
-
declare function useRelatedRows(rowIds: string[]): UseRelatedRowsResult;
|
|
795
|
-
|
|
796
|
-
/**
|
|
797
|
-
* useReverseRelations - Hook for finding rows that link TO a given row
|
|
798
|
-
*
|
|
799
|
-
* Finds all rows in other databases that have relation columns pointing
|
|
800
|
-
* to the specified row. Useful for showing "backlinks" or "linked from" sections.
|
|
801
|
-
*
|
|
802
|
-
* @example
|
|
803
|
-
* ```tsx
|
|
804
|
-
* const { relations, loading, error } = useReverseRelations(taskId, tasksDatabaseId)
|
|
805
|
-
* // relations contains all rows that link to this task
|
|
806
|
-
* ```
|
|
807
|
-
*/
|
|
808
|
-
|
|
809
|
-
interface ReverseRelation {
|
|
810
|
-
/** The row that links to the target row */
|
|
811
|
-
row: DatabaseRow;
|
|
812
|
-
/** The relation column through which it links */
|
|
813
|
-
column: ColumnDefinition;
|
|
814
|
-
/** ID of the source database */
|
|
815
|
-
sourceDatabaseId: string;
|
|
816
|
-
/** Title of the source database */
|
|
817
|
-
sourceDatabaseTitle: string;
|
|
818
|
-
}
|
|
819
|
-
interface UseReverseRelationsResult {
|
|
820
|
-
/** Found reverse relations */
|
|
821
|
-
relations: ReverseRelation[];
|
|
822
|
-
/** Whether relations are loading */
|
|
823
|
-
loading: boolean;
|
|
824
|
-
/** Any error that occurred */
|
|
825
|
-
error: Error | null;
|
|
826
|
-
/** Refetch the relations */
|
|
827
|
-
refetch: () => void;
|
|
828
|
-
}
|
|
829
|
-
/**
|
|
830
|
-
* Hook for finding reverse relations (backlinks) to a row.
|
|
831
|
-
*
|
|
832
|
-
* @param rowId - The row ID to find links to
|
|
833
|
-
* @param databaseId - The database containing the row
|
|
834
|
-
* @returns Object containing relations, loading state, and error
|
|
835
|
-
*/
|
|
836
|
-
declare function useReverseRelations(rowId: string, databaseId: string): UseReverseRelationsResult;
|
|
837
|
-
|
|
838
|
-
/**
|
|
839
|
-
* useDatabaseSchema - Hook for database-defined schema access
|
|
840
|
-
*
|
|
841
|
-
* Provides reactive access to a database's schema metadata and properties.
|
|
842
|
-
* Works with the schema registry to resolve database-defined schemas.
|
|
843
|
-
*
|
|
844
|
-
* @example
|
|
845
|
-
* ```tsx
|
|
846
|
-
* const {
|
|
847
|
-
* schema,
|
|
848
|
-
* metadata,
|
|
849
|
-
* loading,
|
|
850
|
-
* error
|
|
851
|
-
* } = useDatabaseSchema(databaseId)
|
|
852
|
-
*
|
|
853
|
-
* // Access schema version
|
|
854
|
-
* console.log(metadata?.version) // "1.2.0"
|
|
855
|
-
*
|
|
856
|
-
* // Access schema properties
|
|
857
|
-
* schema?.properties.forEach(prop => console.log(prop.name))
|
|
858
|
-
* ```
|
|
859
|
-
*/
|
|
860
|
-
|
|
861
|
-
interface UseDatabaseSchemaResult {
|
|
862
|
-
/** The resolved Schema object, or null if not loaded */
|
|
863
|
-
schema: Schema | null;
|
|
864
|
-
/** The schema metadata from the database's Y.Doc */
|
|
865
|
-
metadata: DatabaseSchemaMetadata | null;
|
|
866
|
-
/** The schema IRI for this database */
|
|
867
|
-
schemaIRI: string | null;
|
|
868
|
-
/** Whether the schema is loading */
|
|
869
|
-
loading: boolean;
|
|
870
|
-
/** Any error that occurred */
|
|
871
|
-
error: Error | null;
|
|
872
|
-
/** Force refresh the schema */
|
|
873
|
-
refresh: () => void;
|
|
874
|
-
}
|
|
875
|
-
/**
|
|
876
|
-
* Hook for accessing a database's schema.
|
|
877
|
-
*
|
|
878
|
-
* Loads the database's Y.Doc, extracts schema metadata and columns,
|
|
879
|
-
* builds the Schema object, and registers it with the schema registry.
|
|
880
|
-
*
|
|
881
|
-
* @param databaseId - The database node ID
|
|
882
|
-
* @returns The schema, metadata, and loading state
|
|
883
|
-
*/
|
|
884
|
-
declare function useDatabaseSchema(databaseId: string | undefined): UseDatabaseSchemaResult;
|
|
885
|
-
|
|
886
|
-
interface UseCommentsOptions {
|
|
887
|
-
/** The Node ID to get comments for (any schema) */
|
|
888
|
-
nodeId: string;
|
|
889
|
-
/** Optional: filter to specific anchor type */
|
|
890
|
-
anchorType?: 'text' | 'cell' | 'row' | 'column' | 'canvas-position' | 'canvas-object' | 'node';
|
|
891
|
-
}
|
|
892
|
-
interface CommentThread {
|
|
893
|
-
/** The root comment (holds anchor data and resolved state) */
|
|
894
|
-
root: CommentNode;
|
|
895
|
-
/** Replies to this thread (sorted by Lamport time) */
|
|
896
|
-
replies: CommentNode[];
|
|
897
|
-
}
|
|
898
|
-
/** Flattened comment node for easier access */
|
|
899
|
-
interface CommentNode {
|
|
900
|
-
id: string;
|
|
901
|
-
schemaId: string;
|
|
902
|
-
createdAt: number;
|
|
903
|
-
lamportTime: number;
|
|
904
|
-
wallTime: number;
|
|
905
|
-
properties: {
|
|
906
|
-
target: string;
|
|
907
|
-
targetSchema?: string;
|
|
908
|
-
inReplyTo?: string;
|
|
909
|
-
anchorType: string;
|
|
910
|
-
anchorData: string;
|
|
911
|
-
content: string;
|
|
912
|
-
attachments?: string[];
|
|
913
|
-
replyToUser?: string;
|
|
914
|
-
replyToCommentId?: string;
|
|
915
|
-
resolved: boolean;
|
|
916
|
-
resolvedBy?: string;
|
|
917
|
-
resolvedAt?: number;
|
|
918
|
-
edited: boolean;
|
|
919
|
-
editedAt?: number;
|
|
920
|
-
createdBy: string;
|
|
921
|
-
};
|
|
922
|
-
}
|
|
923
|
-
interface AddCommentOptions {
|
|
924
|
-
/** Comment content (GitHub-flavored markdown) */
|
|
925
|
-
content: string;
|
|
926
|
-
/** Type of anchor */
|
|
927
|
-
anchorType: 'text' | 'cell' | 'row' | 'column' | 'canvas-position' | 'canvas-object' | 'node';
|
|
928
|
-
/** JSON-encoded anchor data */
|
|
929
|
-
anchorData: string;
|
|
930
|
-
/** Schema IRI of the target Node (optimization) */
|
|
931
|
-
targetSchema?: string;
|
|
932
|
-
}
|
|
933
|
-
interface ReplyContext {
|
|
934
|
-
/** DID of user being replied to (for "replying to @user" UI) */
|
|
935
|
-
replyToUser?: string;
|
|
936
|
-
/** Comment ID being referenced (for "in reply to X" display) */
|
|
937
|
-
replyToCommentId?: string;
|
|
938
|
-
}
|
|
939
|
-
interface UseCommentsResult {
|
|
940
|
-
/** All comments on the target node */
|
|
941
|
-
comments: CommentNode[];
|
|
942
|
-
/** Comments grouped into threads (root + replies) */
|
|
943
|
-
threads: CommentThread[];
|
|
944
|
-
/** Total comment count */
|
|
945
|
-
count: number;
|
|
946
|
-
/** Count of unresolved threads */
|
|
947
|
-
unresolvedCount: number;
|
|
948
|
-
/** Whether loading */
|
|
949
|
-
loading: boolean;
|
|
950
|
-
/** Any error */
|
|
951
|
-
error: Error | null;
|
|
952
|
-
/** Add a new root comment */
|
|
953
|
-
addComment: (options: AddCommentOptions) => Promise<string | null>;
|
|
954
|
-
/** Reply to a thread */
|
|
955
|
-
replyTo: (rootCommentId: string, content: string, context?: ReplyContext) => Promise<string | null>;
|
|
956
|
-
/** Resolve a thread */
|
|
957
|
-
resolveThread: (rootCommentId: string) => Promise<void>;
|
|
958
|
-
/** Reopen a resolved thread */
|
|
959
|
-
reopenThread: (rootCommentId: string) => Promise<void>;
|
|
960
|
-
/** Delete a comment (soft delete) */
|
|
961
|
-
deleteComment: (commentId: string) => Promise<void>;
|
|
962
|
-
/** Delete an entire thread (root + all replies) */
|
|
963
|
-
deleteThread: (rootCommentId: string) => Promise<void>;
|
|
964
|
-
/** Edit a comment */
|
|
965
|
-
editComment: (commentId: string, content: string) => Promise<void>;
|
|
966
|
-
/** Reload comments */
|
|
967
|
-
reload: () => Promise<void>;
|
|
968
|
-
}
|
|
969
|
-
/**
|
|
970
|
-
* Universal hook for comments on any Node.
|
|
971
|
-
*/
|
|
972
|
-
declare function useComments({ nodeId, anchorType }: UseCommentsOptions): UseCommentsResult;
|
|
973
|
-
|
|
974
|
-
/**
|
|
975
|
-
* Get the unresolved comment count for a Node.
|
|
976
|
-
*
|
|
977
|
-
* @param nodeId - The Node ID to get comment count for
|
|
978
|
-
* @returns The number of unresolved comment threads
|
|
979
|
-
*/
|
|
980
|
-
declare function useCommentCount(nodeId: string): number;
|
|
981
|
-
/**
|
|
982
|
-
* Get detailed comment counts for a Node.
|
|
983
|
-
*
|
|
984
|
-
* @param nodeId - The Node ID to get comment counts for
|
|
985
|
-
* @returns Object with total and unresolved counts
|
|
986
|
-
*/
|
|
987
|
-
declare function useCommentCounts(nodeId: string): {
|
|
988
|
-
total: number;
|
|
989
|
-
unresolved: number;
|
|
990
|
-
resolved: number;
|
|
991
|
-
};
|
|
992
|
-
|
|
993
|
-
/**
|
|
994
|
-
* useHistory - React hook for node history / time travel
|
|
995
|
-
*
|
|
996
|
-
* Provides point-in-time reconstruction, timeline browsing,
|
|
997
|
-
* and state materialization for a node.
|
|
998
|
-
*
|
|
999
|
-
* @example
|
|
1000
|
-
* ```tsx
|
|
1001
|
-
* const { timeline, materializeAt, diff, changeCount, loading } = useHistory(nodeId)
|
|
1002
|
-
*
|
|
1003
|
-
* // Get timeline
|
|
1004
|
-
* const entries = timeline
|
|
1005
|
-
*
|
|
1006
|
-
* // Materialize at a specific point
|
|
1007
|
-
* const historical = await materializeAt({ type: 'index', index: 5 })
|
|
1008
|
-
*
|
|
1009
|
-
* // Diff two points
|
|
1010
|
-
* const diffs = await diff({ type: 'index', index: 0 }, { type: 'latest' })
|
|
1011
|
-
* ```
|
|
1012
|
-
*/
|
|
1013
|
-
|
|
1014
|
-
interface UseHistoryResult {
|
|
1015
|
-
/** Full timeline of changes for the node */
|
|
1016
|
-
timeline: TimelineEntry[];
|
|
1017
|
-
/** Total number of changes */
|
|
1018
|
-
changeCount: number;
|
|
1019
|
-
/** Reconstruct node state at a target point */
|
|
1020
|
-
materializeAt: (target: HistoryTarget) => Promise<HistoricalState | null>;
|
|
1021
|
-
/** Diff between two points */
|
|
1022
|
-
diff: (from: HistoryTarget, to: HistoryTarget) => Promise<PropertyDiff[]>;
|
|
1023
|
-
/** Create a revert payload to restore to a historical point */
|
|
1024
|
-
createRevertPayload: (target: HistoryTarget) => Promise<Record<string, unknown> | null>;
|
|
1025
|
-
/** Whether the timeline is loading */
|
|
1026
|
-
loading: boolean;
|
|
1027
|
-
/** Any error */
|
|
1028
|
-
error: Error | null;
|
|
1029
|
-
/** Reload the timeline */
|
|
1030
|
-
reload: () => Promise<void>;
|
|
1031
|
-
}
|
|
1032
|
-
declare function useHistory(nodeId: NodeId | null): UseHistoryResult;
|
|
1033
|
-
|
|
1034
|
-
/**
|
|
1035
|
-
* useUndo - React hook for per-node undo/redo
|
|
1036
|
-
*
|
|
1037
|
-
* Wraps UndoManager to provide undo/redo actions, stack depth,
|
|
1038
|
-
* and canUndo/canRedo state for a given node.
|
|
1039
|
-
*
|
|
1040
|
-
* @example
|
|
1041
|
-
* ```tsx
|
|
1042
|
-
* const { undo, redo, canUndo, canRedo, undoCount, redoCount } = useUndo(nodeId)
|
|
1043
|
-
*
|
|
1044
|
-
* // Wire to keyboard shortcuts
|
|
1045
|
-
* <button onClick={undo} disabled={!canUndo}>Undo</button>
|
|
1046
|
-
* <button onClick={redo} disabled={!canRedo}>Redo</button>
|
|
1047
|
-
* ```
|
|
1048
|
-
*/
|
|
1049
|
-
|
|
1050
|
-
interface UseUndoOptions {
|
|
1051
|
-
/** The local user's DID (required for undo to work) */
|
|
1052
|
-
localDID: DID;
|
|
1053
|
-
/** UndoManager configuration overrides */
|
|
1054
|
-
options?: Partial<UndoManagerOptions>;
|
|
1055
|
-
}
|
|
1056
|
-
interface UseUndoResult {
|
|
1057
|
-
/** Undo the last change for this node */
|
|
1058
|
-
undo: () => Promise<boolean>;
|
|
1059
|
-
/** Redo the last undone change for this node */
|
|
1060
|
-
redo: () => Promise<boolean>;
|
|
1061
|
-
/** Undo all changes in a batch */
|
|
1062
|
-
undoBatch: (batchId: string) => Promise<boolean>;
|
|
1063
|
-
/** Whether undo is available */
|
|
1064
|
-
canUndo: boolean;
|
|
1065
|
-
/** Whether redo is available */
|
|
1066
|
-
canRedo: boolean;
|
|
1067
|
-
/** Number of undo entries */
|
|
1068
|
-
undoCount: number;
|
|
1069
|
-
/** Number of redo entries */
|
|
1070
|
-
redoCount: number;
|
|
1071
|
-
/** Clear undo/redo stacks for this node */
|
|
1072
|
-
clear: () => void;
|
|
1073
|
-
}
|
|
1074
|
-
declare function useUndo(nodeId: NodeId | null, opts: UseUndoOptions): UseUndoResult;
|
|
1075
|
-
|
|
1076
|
-
/**
|
|
1077
|
-
* useAudit - React hook for querying the audit log
|
|
1078
|
-
*
|
|
1079
|
-
* Provides paginated, filterable access to change audit entries
|
|
1080
|
-
* and activity summaries for nodes.
|
|
1081
|
-
*
|
|
1082
|
-
* @example
|
|
1083
|
-
* ```tsx
|
|
1084
|
-
* const { entries, activity, loading } = useAudit(nodeId)
|
|
1085
|
-
* const { entries: filtered } = useAudit(nodeId, { operations: ['create', 'delete'] })
|
|
1086
|
-
* ```
|
|
1087
|
-
*/
|
|
1088
|
-
|
|
1089
|
-
interface UseAuditOptions {
|
|
1090
|
-
/** Filter by operations */
|
|
1091
|
-
operations?: ('create' | 'update' | 'delete' | 'restore')[];
|
|
1092
|
-
/** Filter by author DID */
|
|
1093
|
-
author?: string;
|
|
1094
|
-
/** Time range filter [from, to] in wall clock ms */
|
|
1095
|
-
timeRange?: [number, number];
|
|
1096
|
-
/** Max entries to return */
|
|
1097
|
-
limit?: number;
|
|
1098
|
-
/** Sort order */
|
|
1099
|
-
order?: 'asc' | 'desc';
|
|
1100
|
-
}
|
|
1101
|
-
interface UseAuditResult {
|
|
1102
|
-
/** Audit entries matching the query */
|
|
1103
|
-
entries: AuditEntry[];
|
|
1104
|
-
/** Activity summary for the node */
|
|
1105
|
-
activity: ActivitySummary | null;
|
|
1106
|
-
/** Whether loading */
|
|
1107
|
-
loading: boolean;
|
|
1108
|
-
/** Any error */
|
|
1109
|
-
error: Error | null;
|
|
1110
|
-
/** Reload audit data */
|
|
1111
|
-
reload: () => Promise<void>;
|
|
1112
|
-
}
|
|
1113
|
-
declare function useAudit(nodeId: NodeId | null, options?: UseAuditOptions): UseAuditResult;
|
|
1114
|
-
|
|
1115
|
-
/**
|
|
1116
|
-
* useDiff - React hook for comparing node state between two points
|
|
1117
|
-
*
|
|
1118
|
-
* Wraps DiffEngine to provide on-demand diffs between any two
|
|
1119
|
-
* HistoryTarget points.
|
|
1120
|
-
*
|
|
1121
|
-
* @example
|
|
1122
|
-
* ```tsx
|
|
1123
|
-
* const { diff, result, loading } = useDiff(nodeId)
|
|
1124
|
-
*
|
|
1125
|
-
* // Compare creation to latest
|
|
1126
|
-
* await diff({ type: 'index', index: 0 }, { type: 'latest' })
|
|
1127
|
-
*
|
|
1128
|
-
* // Show result
|
|
1129
|
-
* result?.diffs.forEach(d => console.log(d.property, d.type))
|
|
1130
|
-
* ```
|
|
1131
|
-
*/
|
|
1132
|
-
|
|
1133
|
-
interface UseDiffResult {
|
|
1134
|
-
/** Compute diff between two points */
|
|
1135
|
-
diff: (from: HistoryTarget, to: HistoryTarget) => Promise<void>;
|
|
1136
|
-
/** Diff N changes back from current */
|
|
1137
|
-
diffFromCurrent: (changesAgo: number) => Promise<void>;
|
|
1138
|
-
/** Latest diff result */
|
|
1139
|
-
result: DiffResult | null;
|
|
1140
|
-
/** Whether diffing */
|
|
1141
|
-
loading: boolean;
|
|
1142
|
-
/** Any error */
|
|
1143
|
-
error: Error | null;
|
|
1144
|
-
}
|
|
1145
|
-
declare function useDiff(nodeId: NodeId | null): UseDiffResult;
|
|
1146
|
-
|
|
1147
|
-
/**
|
|
1148
|
-
* useBlame - React hook for per-property attribution
|
|
1149
|
-
*
|
|
1150
|
-
* Shows who last changed each property, how many times,
|
|
1151
|
-
* and the full edit history.
|
|
1152
|
-
*
|
|
1153
|
-
* @example
|
|
1154
|
-
* ```tsx
|
|
1155
|
-
* const { blame, loading, reload } = useBlame(nodeId)
|
|
1156
|
-
*
|
|
1157
|
-
* blame.forEach(b => {
|
|
1158
|
-
* console.log(`${b.property}: last changed by ${b.lastChangedBy}, ${b.totalEdits} edits`)
|
|
1159
|
-
* })
|
|
1160
|
-
* ```
|
|
1161
|
-
*/
|
|
1162
|
-
|
|
1163
|
-
interface UseBlameResult {
|
|
1164
|
-
/** Blame info for all properties */
|
|
1165
|
-
blame: BlameInfo[];
|
|
1166
|
-
/** Whether loading */
|
|
1167
|
-
loading: boolean;
|
|
1168
|
-
/** Any error */
|
|
1169
|
-
error: Error | null;
|
|
1170
|
-
/** Reload blame data */
|
|
1171
|
-
reload: () => Promise<void>;
|
|
1172
|
-
}
|
|
1173
|
-
declare function useBlame(nodeId: NodeId | null): UseBlameResult;
|
|
1174
|
-
|
|
1175
|
-
/**
|
|
1176
|
-
* useVerification - React hook for cryptographic chain verification
|
|
1177
|
-
*
|
|
1178
|
-
* Runs verification on a node's change history and reports
|
|
1179
|
-
* validity, errors, and statistics.
|
|
1180
|
-
*
|
|
1181
|
-
* @example
|
|
1182
|
-
* ```tsx
|
|
1183
|
-
* const { verify, result, loading } = useVerification(nodeId)
|
|
1184
|
-
*
|
|
1185
|
-
* await verify()
|
|
1186
|
-
* if (result?.valid) {
|
|
1187
|
-
* console.log('Chain is valid!', result.stats)
|
|
1188
|
-
* } else {
|
|
1189
|
-
* console.log('Errors:', result?.errors)
|
|
1190
|
-
* }
|
|
1191
|
-
* ```
|
|
1192
|
-
*/
|
|
1193
|
-
|
|
1194
|
-
interface UseVerificationResult {
|
|
1195
|
-
/** Run full verification */
|
|
1196
|
-
verify: (options?: VerificationOptions) => Promise<void>;
|
|
1197
|
-
/** Run quick check (hash + chain only) */
|
|
1198
|
-
quickCheck: () => Promise<{
|
|
1199
|
-
valid: boolean;
|
|
1200
|
-
errors: number;
|
|
1201
|
-
} | null>;
|
|
1202
|
-
/** Latest verification result */
|
|
1203
|
-
result: VerificationResult | null;
|
|
1204
|
-
/** Whether verification is running */
|
|
1205
|
-
loading: boolean;
|
|
1206
|
-
/** Verification progress (0-1) */
|
|
1207
|
-
progress: number;
|
|
1208
|
-
/** Any error */
|
|
1209
|
-
error: Error | null;
|
|
1210
|
-
}
|
|
1211
|
-
declare function useVerification(nodeId: NodeId | null): UseVerificationResult;
|
|
1212
|
-
|
|
1213
|
-
/**
|
|
1214
|
-
* Connection Manager - Multiplexed WebSocket connection for all tracked Nodes
|
|
1215
|
-
*
|
|
1216
|
-
* Instead of one WebSocket per Node (current WebSocketSyncProvider approach),
|
|
1217
|
-
* the Connection Manager maintains a single WebSocket subscribed to multiple
|
|
1218
|
-
* rooms. This reduces connection count from O(N) to O(1).
|
|
1219
|
-
*
|
|
1220
|
-
* The signaling protocol supports multi-room subscriptions:
|
|
1221
|
-
* { type: "subscribe", topics: ["xnet-doc-abc", "xnet-doc-def"] }
|
|
1222
|
-
*/
|
|
1223
|
-
type ConnectionStatus = 'disconnected' | 'connecting' | 'connected' | 'error';
|
|
1224
|
-
interface ConnectionManagerConfig {
|
|
1225
|
-
/** Signaling/hub WebSocket URL */
|
|
1226
|
-
url: string;
|
|
1227
|
-
/** Reconnect delay in ms (default: 2000) */
|
|
1228
|
-
reconnectDelay?: number;
|
|
1229
|
-
/** Max reconnect attempts (default: Infinity) */
|
|
1230
|
-
maxReconnects?: number;
|
|
1231
|
-
/** UCAN token for hub auth */
|
|
1232
|
-
ucanToken?: string;
|
|
1233
|
-
/** Async UCAN token provider (preferred for rotation) */
|
|
1234
|
-
getUCANToken?: () => Promise<string>;
|
|
1235
|
-
}
|
|
1236
|
-
type RoomHandler = (data: Record<string, unknown>) => void;
|
|
1237
|
-
type StatusHandler = (status: ConnectionStatus) => void;
|
|
1238
|
-
interface RoomJoinResult {
|
|
1239
|
-
/** Unsubscribe function */
|
|
1240
|
-
unsubscribe: () => void;
|
|
1241
|
-
/** Promise that resolves when server confirms subscription */
|
|
1242
|
-
ready: Promise<void>;
|
|
1243
|
-
}
|
|
1244
|
-
interface ConnectionManager {
|
|
1245
|
-
/** Current connection status */
|
|
1246
|
-
readonly status: ConnectionStatus;
|
|
1247
|
-
/** Connect to the signaling server */
|
|
1248
|
-
connect(): void;
|
|
1249
|
-
/** Disconnect and cleanup */
|
|
1250
|
-
disconnect(): void;
|
|
1251
|
-
/** Subscribe to a room (returns unsubscribe function) */
|
|
1252
|
-
joinRoom(room: string, handler: RoomHandler): () => void;
|
|
1253
|
-
/** Subscribe to a room with confirmation (returns cleanup and ready promise) */
|
|
1254
|
-
joinRoomAsync(room: string, handler: RoomHandler): RoomJoinResult;
|
|
1255
|
-
/** Leave a room */
|
|
1256
|
-
leaveRoom(room: string): void;
|
|
1257
|
-
/** Publish a message to a room */
|
|
1258
|
-
publish(room: string, data: object): void;
|
|
1259
|
-
/** Send a raw message on the WebSocket */
|
|
1260
|
-
sendRaw(message: object): void;
|
|
1261
|
-
/** Listen for non-room messages */
|
|
1262
|
-
onMessage(handler: (message: Record<string, unknown>) => void): () => void;
|
|
1263
|
-
/** Listen for status changes */
|
|
1264
|
-
onStatus(handler: StatusHandler): () => void;
|
|
1265
|
-
/** Number of active room subscriptions */
|
|
1266
|
-
readonly roomCount: number;
|
|
1267
|
-
}
|
|
1268
|
-
declare function createConnectionManager(config: ConnectionManagerConfig): ConnectionManager;
|
|
1269
|
-
|
|
1270
|
-
/**
|
|
1271
|
-
* Blob Sync Provider - Handles blob synchronization between peers.
|
|
1272
|
-
*
|
|
1273
|
-
* Integrates with the Background Sync Manager's ConnectionManager to send
|
|
1274
|
-
* blob have/want/data messages over the same multiplexed WebSocket connection
|
|
1275
|
-
* used for Y.Doc sync. Uses a dedicated room for blob sync messages.
|
|
1276
|
-
*
|
|
1277
|
-
* Protocol:
|
|
1278
|
-
* blob-have: Announce available CIDs to peers
|
|
1279
|
-
* blob-want: Request missing blobs by CID
|
|
1280
|
-
* blob-data: Transfer blob bytes (base64 encoded)
|
|
1281
|
-
* blob-not-found: Signal unavailability
|
|
1282
|
-
*/
|
|
1283
|
-
|
|
1284
|
-
/** Minimal blob store interface for sync (satisfied by BlobStore from @xnetjs/storage) */
|
|
1285
|
-
interface BlobStoreForSync {
|
|
1286
|
-
get(cid: ContentId): Promise<Uint8Array | null>;
|
|
1287
|
-
put(data: Uint8Array): Promise<ContentId>;
|
|
1288
|
-
has(cid: ContentId): Promise<boolean>;
|
|
1289
|
-
}
|
|
1290
|
-
|
|
1291
|
-
/**
|
|
1292
|
-
* Sync Manager - Top-level orchestrator for Background Sync
|
|
1293
|
-
*
|
|
1294
|
-
* Wires together Node Pool, Registry, and Connection Manager into a cohesive
|
|
1295
|
-
* sync service. Handles the Yjs sync protocol (state vectors, diffs, incremental
|
|
1296
|
-
* updates) for each tracked Node.
|
|
1297
|
-
*
|
|
1298
|
-
* Components acquire Y.Docs via the SyncManager (through useNode). When released,
|
|
1299
|
-
* docs stay alive in the pool and continue syncing in the background.
|
|
1300
|
-
*/
|
|
1301
|
-
|
|
1302
|
-
type SyncStatus = ConnectionStatus;
|
|
1303
|
-
interface SyncManagerConfig {
|
|
1304
|
-
/** NodeStore for meta bridge */
|
|
1305
|
-
nodeStore: NodeStore;
|
|
1306
|
-
/** Storage adapter for pool persistence (Y.Doc content) */
|
|
1307
|
-
storage: NodeStorageAdapter;
|
|
1308
|
-
/** Signaling/hub WebSocket URL */
|
|
1309
|
-
signalingUrl: string;
|
|
1310
|
-
/** Max Y.Docs in memory (default: 50) */
|
|
1311
|
-
poolSize?: number;
|
|
1312
|
-
/** TTL for tracked Nodes in ms (default: 7 days) */
|
|
1313
|
-
trackTTL?: number;
|
|
1314
|
-
/** Author DID for awareness */
|
|
1315
|
-
authorDID?: string;
|
|
1316
|
-
/** Blob store for P2P blob sync (optional — if omitted, blob sync is disabled) */
|
|
1317
|
-
blobStore?: BlobStoreForSync;
|
|
1318
|
-
/** Optional UCAN token for hub auth */
|
|
1319
|
-
ucanToken?: string;
|
|
1320
|
-
/** Optional UCAN token provider for hub auth */
|
|
1321
|
-
getUCANToken?: () => Promise<string>;
|
|
1322
|
-
/** Optional pool update callback */
|
|
1323
|
-
onDocUpdate?: (nodeId: string, doc: Y.Doc) => void;
|
|
1324
|
-
/** Optional pool eviction callback */
|
|
1325
|
-
onDocEvict?: (nodeId: string, doc: Y.Doc) => void;
|
|
1326
|
-
/** Optional room for node-change relay (enables NodeStore sync via hub) */
|
|
1327
|
-
nodeSyncRoom?: string;
|
|
1328
|
-
}
|
|
1329
|
-
interface SyncManager {
|
|
1330
|
-
/** Start the sync manager (connect, load registry, sync tracked Nodes) */
|
|
1331
|
-
start(): Promise<void>;
|
|
1332
|
-
/** Stop (disconnect, flush, save registry) */
|
|
1333
|
-
stop(): Promise<void>;
|
|
1334
|
-
/** Track a Node for background sync */
|
|
1335
|
-
track(nodeId: string, schemaId: string): void;
|
|
1336
|
-
/** Stop tracking a Node */
|
|
1337
|
-
untrack(nodeId: string): void;
|
|
1338
|
-
/** Acquire a Y.Doc (used by useNode) */
|
|
1339
|
-
acquire(nodeId: string): Promise<Y.Doc>;
|
|
1340
|
-
/** Release a Y.Doc (component unmounted) */
|
|
1341
|
-
release(nodeId: string): void;
|
|
1342
|
-
/** Get awareness for a Node (for cursor presence) */
|
|
1343
|
-
getAwareness(nodeId: string): Awareness | null;
|
|
1344
|
-
/** Listen for awareness snapshots from the hub */
|
|
1345
|
-
onAwarenessSnapshot(nodeId: string, handler: (users: AwarenessSnapshotUser[]) => void): () => void;
|
|
1346
|
-
/** Request blobs from peers by CID (no-op if blob sync is disabled) */
|
|
1347
|
-
requestBlobs(cids: string[]): Promise<void>;
|
|
1348
|
-
/** Announce blob CIDs to peers (no-op if blob sync is disabled) */
|
|
1349
|
-
announceBlobs(cids: string[]): void;
|
|
1350
|
-
/** Connection status */
|
|
1351
|
-
readonly status: SyncStatus;
|
|
1352
|
-
/** Pool stats */
|
|
1353
|
-
readonly poolSize: number;
|
|
1354
|
-
/** Tracked count */
|
|
1355
|
-
readonly trackedCount: number;
|
|
1356
|
-
/** Offline queue size */
|
|
1357
|
-
readonly queueSize: number;
|
|
1358
|
-
/** Pending blob requests */
|
|
1359
|
-
readonly pendingBlobCount: number;
|
|
1360
|
-
/** Listen for events */
|
|
1361
|
-
on(event: 'status', handler: (status: SyncStatus) => void): () => void;
|
|
1362
|
-
/** Underlying ConnectionManager (if available) */
|
|
1363
|
-
readonly connection?: ConnectionManager;
|
|
1364
|
-
}
|
|
1365
|
-
type AwarenessSnapshotUser = {
|
|
1366
|
-
did: string;
|
|
1367
|
-
state: {
|
|
1368
|
-
user?: {
|
|
1369
|
-
name?: string;
|
|
1370
|
-
color?: string;
|
|
1371
|
-
avatar?: string;
|
|
1372
|
-
did?: string;
|
|
1373
|
-
};
|
|
1374
|
-
cursor?: {
|
|
1375
|
-
anchor: number;
|
|
1376
|
-
head: number;
|
|
1377
|
-
};
|
|
1378
|
-
selection?: unknown;
|
|
1379
|
-
online?: boolean;
|
|
1380
|
-
[key: string]: unknown;
|
|
1381
|
-
};
|
|
1382
|
-
lastSeen: number;
|
|
1383
|
-
isStale: boolean;
|
|
1384
|
-
};
|
|
1385
|
-
declare function createSyncManager(config: SyncManagerConfig): SyncManager;
|
|
1386
|
-
|
|
1387
|
-
/**
|
|
1388
|
-
* useHubStatus - Access hub connection status from context.
|
|
1389
|
-
*/
|
|
1390
|
-
|
|
1391
|
-
declare function useHubStatus(): SyncStatus;
|
|
1392
|
-
|
|
1393
|
-
/**
|
|
1394
|
-
* useCan - Check current user's permissions for a node.
|
|
1395
|
-
*/
|
|
1396
|
-
interface UseCanResult {
|
|
1397
|
-
canRead: boolean;
|
|
1398
|
-
canWrite: boolean;
|
|
1399
|
-
canDelete: boolean;
|
|
1400
|
-
canShare: boolean;
|
|
1401
|
-
loading: boolean;
|
|
1402
|
-
error: Error | null;
|
|
1403
|
-
isFresh: boolean;
|
|
1404
|
-
evaluatedAt: number;
|
|
1405
|
-
}
|
|
1406
|
-
declare function useCan(nodeId: string): UseCanResult;
|
|
1407
|
-
|
|
1408
|
-
/**
|
|
1409
|
-
* useCanEdit - Resolve editor/viewer capabilities for a node.
|
|
1410
|
-
*/
|
|
1411
|
-
type UseCanEditResult = {
|
|
1412
|
-
canEdit: boolean;
|
|
1413
|
-
canView: boolean;
|
|
1414
|
-
loading: boolean;
|
|
1415
|
-
error: Error | null;
|
|
1416
|
-
roles: string[];
|
|
1417
|
-
};
|
|
1418
|
-
declare function useCanEdit(nodeId: string): UseCanEditResult;
|
|
1419
|
-
|
|
1420
|
-
/**
|
|
1421
|
-
* useGrants - Read and mutate grants for a node.
|
|
1422
|
-
*/
|
|
1423
|
-
|
|
1424
|
-
interface GrantInput {
|
|
1425
|
-
to: DID;
|
|
1426
|
-
actions: AuthAction[];
|
|
1427
|
-
resource?: string;
|
|
1428
|
-
expiresIn?: string | number;
|
|
1429
|
-
parentGrantId?: string;
|
|
1430
|
-
}
|
|
1431
|
-
interface UseGrantsResult {
|
|
1432
|
-
grants: AuthGrant[];
|
|
1433
|
-
loading: boolean;
|
|
1434
|
-
error: Error | null;
|
|
1435
|
-
grant: (input: GrantInput) => Promise<AuthGrant>;
|
|
1436
|
-
revoke: (grantId: string) => Promise<void>;
|
|
1437
|
-
}
|
|
1438
|
-
declare function useGrants(nodeId: string): UseGrantsResult;
|
|
1439
|
-
|
|
1440
|
-
interface UseBackupReturn {
|
|
1441
|
-
upload: (docId: string, plaintext: Uint8Array) => Promise<void>;
|
|
1442
|
-
download: (docId: string) => Promise<Uint8Array | null>;
|
|
1443
|
-
uploading: boolean;
|
|
1444
|
-
}
|
|
1445
|
-
declare function useBackup(): UseBackupReturn;
|
|
1446
|
-
|
|
1447
|
-
interface FileRef {
|
|
1448
|
-
cid: string;
|
|
1449
|
-
name: string;
|
|
1450
|
-
mimeType: string;
|
|
1451
|
-
size: number;
|
|
1452
|
-
}
|
|
1453
|
-
interface UseFileUploadReturn {
|
|
1454
|
-
upload: (file: File) => Promise<FileRef>;
|
|
1455
|
-
uploading: boolean;
|
|
1456
|
-
progress: number;
|
|
1457
|
-
}
|
|
1458
|
-
declare function useFileUpload(): UseFileUploadReturn;
|
|
1459
|
-
|
|
1460
|
-
interface HubSearchOptions {
|
|
1461
|
-
schemaIri?: string;
|
|
1462
|
-
limit?: number;
|
|
1463
|
-
offset?: number;
|
|
1464
|
-
}
|
|
1465
|
-
interface HubSearchResult {
|
|
1466
|
-
docId: string;
|
|
1467
|
-
title: string;
|
|
1468
|
-
schemaIri: string;
|
|
1469
|
-
snippet: string;
|
|
1470
|
-
rank: number;
|
|
1471
|
-
}
|
|
1472
|
-
interface HubSearchState {
|
|
1473
|
-
search: (query: string, options?: HubSearchOptions) => Promise<HubSearchResult[]>;
|
|
1474
|
-
results: HubSearchResult[];
|
|
1475
|
-
loading: boolean;
|
|
1476
|
-
error: Error | null;
|
|
1477
|
-
}
|
|
1478
|
-
declare function useHubSearch(): HubSearchState;
|
|
1479
|
-
|
|
1480
|
-
/**
|
|
1481
|
-
* useRemoteSchema - Hub schema registry fetch hook.
|
|
1482
|
-
*/
|
|
1483
|
-
interface RemoteSchemaDefinition {
|
|
1484
|
-
iri: string;
|
|
1485
|
-
version: number;
|
|
1486
|
-
name: string;
|
|
1487
|
-
description: string;
|
|
1488
|
-
definition: Record<string, unknown>;
|
|
1489
|
-
authorDid: string;
|
|
1490
|
-
propertiesCount: number;
|
|
1491
|
-
createdAt: number;
|
|
1492
|
-
}
|
|
1493
|
-
interface RemoteSchemaState {
|
|
1494
|
-
schema: RemoteSchemaDefinition | null;
|
|
1495
|
-
loading: boolean;
|
|
1496
|
-
error: Error | null;
|
|
1497
|
-
}
|
|
1498
|
-
declare const useRemoteSchema: (iri: string | undefined) => RemoteSchemaState;
|
|
1499
|
-
|
|
1500
|
-
/**
|
|
1501
|
-
* usePeerDiscovery - hub peer discovery hook.
|
|
1502
|
-
*/
|
|
1503
|
-
interface DiscoveredPeer {
|
|
1504
|
-
did: string;
|
|
1505
|
-
displayName?: string;
|
|
1506
|
-
endpoints: Array<{
|
|
1507
|
-
type: string;
|
|
1508
|
-
address: string;
|
|
1509
|
-
priority?: number;
|
|
1510
|
-
}>;
|
|
1511
|
-
lastSeen: number;
|
|
1512
|
-
isOnline: boolean;
|
|
1513
|
-
}
|
|
1514
|
-
declare const usePeerDiscovery: () => {
|
|
1515
|
-
peers: DiscoveredPeer[];
|
|
1516
|
-
resolve: (did: string) => Promise<DiscoveredPeer | null>;
|
|
1517
|
-
refresh: () => Promise<void>;
|
|
1518
|
-
loading: boolean;
|
|
1519
|
-
};
|
|
1520
|
-
|
|
1521
|
-
declare function HubStatusIndicator(): JSX.Element;
|
|
1522
|
-
|
|
1523
|
-
/**
|
|
1524
|
-
* Global error boundary for xNet React apps.
|
|
1525
|
-
*
|
|
1526
|
-
* Catches unhandled React render errors and displays a recovery UI
|
|
1527
|
-
* instead of crashing the entire app tree.
|
|
1528
|
-
*/
|
|
1529
|
-
|
|
1530
|
-
type ErrorBoundaryFallbackProps = {
|
|
1531
|
-
error: Error;
|
|
1532
|
-
reset: () => void;
|
|
1533
|
-
};
|
|
1534
|
-
type ErrorBoundaryProps = {
|
|
1535
|
-
children: ReactNode;
|
|
1536
|
-
/** Custom fallback UI. Receives error + reset function. If omitted, a default error screen is shown. */
|
|
1537
|
-
fallback?: ReactNode | ((props: ErrorBoundaryFallbackProps) => ReactNode);
|
|
1538
|
-
/** Callback fired when an error is caught. */
|
|
1539
|
-
onError?: (error: Error, errorInfo: ErrorInfo) => void;
|
|
1540
|
-
/** Change this value to force a reset (e.g. after navigation). */
|
|
1541
|
-
resetKey?: string | number;
|
|
1542
|
-
};
|
|
1543
|
-
type ErrorBoundaryState = {
|
|
1544
|
-
hasError: boolean;
|
|
1545
|
-
error: Error | null;
|
|
1546
|
-
};
|
|
1547
|
-
declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
|
1548
|
-
state: ErrorBoundaryState;
|
|
1549
|
-
static getDerivedStateFromError(error: Error): ErrorBoundaryState;
|
|
1550
|
-
componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
|
|
1551
|
-
private handleReset;
|
|
1552
|
-
componentDidUpdate(prevProps: ErrorBoundaryProps): void;
|
|
1553
|
-
render(): ReactNode;
|
|
1554
|
-
}
|
|
1555
|
-
|
|
1556
|
-
/**
|
|
1557
|
-
* Skeleton loading placeholder.
|
|
1558
|
-
*
|
|
1559
|
-
* Shows a pulsing placeholder while content is loading. Supports
|
|
1560
|
-
* different shapes (text lines, circles, rectangles).
|
|
1561
|
-
*/
|
|
1562
|
-
type SkeletonProps = {
|
|
1563
|
-
/** Width (CSS value). Default: '100%'. */
|
|
1564
|
-
width?: string | number;
|
|
1565
|
-
/** Height (CSS value). Default: '1em'. */
|
|
1566
|
-
height?: string | number;
|
|
1567
|
-
/** Border radius. Use '50%' for circles. Default: '4px'. */
|
|
1568
|
-
borderRadius?: string | number;
|
|
1569
|
-
/** Additional inline styles. */
|
|
1570
|
-
style?: React.CSSProperties;
|
|
1571
|
-
/** Number of lines to render. Default: 1. */
|
|
1572
|
-
lines?: number;
|
|
1573
|
-
/** Gap between lines. Default: '0.5rem'. */
|
|
1574
|
-
gap?: string;
|
|
1575
|
-
};
|
|
1576
|
-
declare function Skeleton({ width, height, borderRadius, style, lines, gap }: SkeletonProps): JSX.Element;
|
|
1577
|
-
/**
|
|
1578
|
-
* Inject the skeleton keyframes into the document head.
|
|
1579
|
-
* Call once at app startup, or include the CSS in your stylesheet:
|
|
1580
|
-
*
|
|
1581
|
-
* ```css
|
|
1582
|
-
* @keyframes xnet-skeleton-pulse {
|
|
1583
|
-
* 0% { background-position: 200% 0; }
|
|
1584
|
-
* 100% { background-position: -200% 0; }
|
|
1585
|
-
* }
|
|
1586
|
-
* ```
|
|
1587
|
-
*/
|
|
1588
|
-
declare function injectSkeletonStyles(): void;
|
|
1589
|
-
|
|
1590
|
-
interface DemoBannerProps {
|
|
1591
|
-
/** How many hours until demo data expires */
|
|
1592
|
-
evictionHours: number;
|
|
1593
|
-
/** Called when banner is dismissed */
|
|
1594
|
-
onDismiss?: () => void;
|
|
1595
|
-
}
|
|
1596
|
-
/**
|
|
1597
|
-
* DemoBanner component
|
|
1598
|
-
*
|
|
1599
|
-
* @example
|
|
1600
|
-
* ```tsx
|
|
1601
|
-
* <DemoBanner evictionHours={24} />
|
|
1602
|
-
* ```
|
|
1603
|
-
*/
|
|
1604
|
-
declare function DemoBanner({ evictionHours, onDismiss }: DemoBannerProps): react_jsx_runtime.JSX.Element | null;
|
|
1605
|
-
|
|
1606
|
-
/**
|
|
1607
|
-
* DemoQuotaIndicator - Shows storage quota usage for demo mode
|
|
1608
|
-
*
|
|
1609
|
-
* Displays a progress bar with bytes used / limit.
|
|
1610
|
-
* Colors change at warning (80%) and critical (95%) thresholds.
|
|
1611
|
-
*/
|
|
1612
|
-
interface DemoQuotaIndicatorProps {
|
|
1613
|
-
/** Bytes currently used */
|
|
1614
|
-
usedBytes: number;
|
|
1615
|
-
/** Total quota limit in bytes */
|
|
1616
|
-
limitBytes: number;
|
|
1617
|
-
}
|
|
1618
|
-
/**
|
|
1619
|
-
* DemoQuotaIndicator component
|
|
1620
|
-
*
|
|
1621
|
-
* @example
|
|
1622
|
-
* ```tsx
|
|
1623
|
-
* <DemoQuotaIndicator usedBytes={5242880} limitBytes={10485760} />
|
|
1624
|
-
* ```
|
|
1625
|
-
*/
|
|
1626
|
-
declare function DemoQuotaIndicator({ usedBytes, limitBytes }: DemoQuotaIndicatorProps): react_jsx_runtime.JSX.Element;
|
|
1627
|
-
|
|
1628
|
-
/**
|
|
1629
|
-
* DemoDataExpiredScreen - Full-screen message when demo data is evicted
|
|
1630
|
-
*
|
|
1631
|
-
* Shown when the user's demo data has been cleaned up after inactivity.
|
|
1632
|
-
* Provides options to start fresh or download the desktop app.
|
|
1633
|
-
*/
|
|
1634
|
-
/**
|
|
1635
|
-
* DemoDataExpiredScreen component
|
|
1636
|
-
*
|
|
1637
|
-
* @example
|
|
1638
|
-
* ```tsx
|
|
1639
|
-
* if (dataExpired) {
|
|
1640
|
-
* return <DemoDataExpiredScreen />
|
|
1641
|
-
* }
|
|
1642
|
-
* ```
|
|
1643
|
-
*/
|
|
1644
|
-
declare function DemoDataExpiredScreen(): react_jsx_runtime.JSX.Element;
|
|
1645
|
-
|
|
1646
|
-
/**
|
|
1647
|
-
* Demo mode limits (from hub handshake)
|
|
1648
|
-
*/
|
|
1649
|
-
interface DemoLimits {
|
|
1650
|
-
/** Storage quota in bytes */
|
|
1651
|
-
quotaBytes: number;
|
|
1652
|
-
/** Maximum number of documents */
|
|
1653
|
-
maxDocs: number;
|
|
1654
|
-
/** Eviction time in hours */
|
|
1655
|
-
evictionHours: number;
|
|
1656
|
-
}
|
|
1657
|
-
/**
|
|
1658
|
-
* Demo mode usage stats (future: populated from hub)
|
|
1659
|
-
*/
|
|
1660
|
-
interface DemoUsage {
|
|
1661
|
-
/** Bytes currently used */
|
|
1662
|
-
usedBytes: number;
|
|
1663
|
-
/** Number of documents */
|
|
1664
|
-
docCount: number;
|
|
1665
|
-
}
|
|
1666
|
-
/**
|
|
1667
|
-
* Demo mode state
|
|
1668
|
-
*/
|
|
1669
|
-
interface DemoModeState {
|
|
1670
|
-
/** Whether connected to a demo hub */
|
|
1671
|
-
isDemo: boolean;
|
|
1672
|
-
/** Demo mode limits (if in demo mode) */
|
|
1673
|
-
limits?: DemoLimits;
|
|
1674
|
-
/** Current usage (if in demo mode and available) */
|
|
1675
|
-
usage?: DemoUsage;
|
|
1676
|
-
}
|
|
1677
|
-
/**
|
|
1678
|
-
* Hook to detect and track demo mode from hub connection
|
|
1679
|
-
*
|
|
1680
|
-
* Listens for the handshake message from the hub which includes `isDemo`
|
|
1681
|
-
* and `demoLimits` fields when connected to a demo hub.
|
|
1682
|
-
*
|
|
1683
|
-
* @example
|
|
1684
|
-
* ```tsx
|
|
1685
|
-
* function App() {
|
|
1686
|
-
* const { isDemo, limits } = useDemoMode()
|
|
1687
|
-
*
|
|
1688
|
-
* return (
|
|
1689
|
-
* <div>
|
|
1690
|
-
* {isDemo && limits && (
|
|
1691
|
-
* <DemoBanner evictionHours={limits.evictionHours} />
|
|
1692
|
-
* )}
|
|
1693
|
-
* <MainContent />
|
|
1694
|
-
* </div>
|
|
1695
|
-
* )
|
|
1696
|
-
* }
|
|
1697
|
-
* ```
|
|
1698
|
-
*/
|
|
1699
|
-
declare function useDemoMode(): DemoModeState;
|
|
1700
|
-
|
|
1701
|
-
type OfflineIndicatorProps = {
|
|
1702
|
-
/** Custom message. Default: 'You are offline. Changes will sync when reconnected.' */
|
|
1703
|
-
message?: string;
|
|
1704
|
-
/** Additional CSS class. */
|
|
1705
|
-
className?: string;
|
|
1706
|
-
/** Position. Default: 'bottom'. */
|
|
1707
|
-
position?: 'top' | 'bottom';
|
|
1708
|
-
};
|
|
1709
|
-
/** Returns true when the browser is offline. */
|
|
1710
|
-
declare function useIsOffline(): boolean;
|
|
1711
|
-
declare function OfflineIndicator({ message, className, position }: OfflineIndicatorProps): JSX.Element | null;
|
|
1712
|
-
|
|
1713
|
-
/**
|
|
1714
|
-
* WebSocketSyncProvider - Syncs Y.Doc via WebSocket relay
|
|
1715
|
-
*
|
|
1716
|
-
* Unlike y-webrtc (which uses WebRTC DataChannels for P2P), this provider
|
|
1717
|
-
* relays all Yjs updates through the signaling server. This works in all
|
|
1718
|
-
* environments (same-machine, different networks, behind NATs) at the cost
|
|
1719
|
-
* of server-relayed traffic.
|
|
1720
|
-
*
|
|
1721
|
-
* Protocol (extends the y-webrtc signaling protocol):
|
|
1722
|
-
* - Uses the same subscribe/publish mechanism as y-webrtc signaling
|
|
1723
|
-
* - Sync messages are published as JSON with base64-encoded binary data
|
|
1724
|
-
* - Message types: 'sync-step1', 'sync-step2', 'sync-update', 'awareness'
|
|
1725
|
-
*
|
|
1726
|
-
* Sync flow:
|
|
1727
|
-
* 1. On connect: subscribe to room, broadcast sync-step1 (state vector)
|
|
1728
|
-
* 2. On receiving sync-step1: respond with sync-step2 (diff for their vector)
|
|
1729
|
-
* 3. On local update: broadcast sync-update to room
|
|
1730
|
-
* 4. On receiving sync-update: apply to local doc
|
|
1731
|
-
*
|
|
1732
|
-
* Awareness flow:
|
|
1733
|
-
* 1. On connect: broadcast local awareness state
|
|
1734
|
-
* 2. On awareness change: broadcast updated state
|
|
1735
|
-
* 3. On receiving awareness: apply to local awareness instance
|
|
1736
|
-
* 4. On disconnect: peers remove the disconnected client's state
|
|
1737
|
-
*/
|
|
1738
|
-
|
|
1739
|
-
interface WebSocketSyncProviderOptions {
|
|
1740
|
-
/** WebSocket URL of the signaling/relay server */
|
|
1741
|
-
url: string;
|
|
1742
|
-
/** Room name (peers in the same room sync together) */
|
|
1743
|
-
room: string;
|
|
1744
|
-
/** Reconnect delay in ms (default: 2000) */
|
|
1745
|
-
reconnectDelay?: number;
|
|
1746
|
-
/** Maximum reconnect attempts (default: Infinity) */
|
|
1747
|
-
maxReconnectAttempts?: number;
|
|
1748
|
-
}
|
|
1749
|
-
type SyncEventType = 'status' | 'synced' | 'peers' | 'awareness-snapshot';
|
|
1750
|
-
type SyncEventHandler = (event: unknown) => void;
|
|
1751
|
-
declare class WebSocketSyncProvider {
|
|
1752
|
-
readonly doc: Y.Doc;
|
|
1753
|
-
readonly room: string;
|
|
1754
|
-
readonly url: string;
|
|
1755
|
-
readonly awareness: Awareness;
|
|
1756
|
-
private ws;
|
|
1757
|
-
private reconnectDelay;
|
|
1758
|
-
private maxReconnectAttempts;
|
|
1759
|
-
private reconnectAttempts;
|
|
1760
|
-
private reconnectTimer;
|
|
1761
|
-
private destroyed;
|
|
1762
|
-
private connected;
|
|
1763
|
-
private synced;
|
|
1764
|
-
private peerId;
|
|
1765
|
-
private remotePeerIds;
|
|
1766
|
-
private eventHandlers;
|
|
1767
|
-
constructor(doc: Y.Doc, options: WebSocketSyncProviderOptions);
|
|
1768
|
-
get isConnected(): boolean;
|
|
1769
|
-
get isSynced(): boolean;
|
|
1770
|
-
/** Helper to get XML fragment length for debug logging */
|
|
1771
|
-
private _getFragmentLength;
|
|
1772
|
-
on(event: SyncEventType, handler: SyncEventHandler): void;
|
|
1773
|
-
off(event: SyncEventType, handler: SyncEventHandler): void;
|
|
1774
|
-
private emit;
|
|
1775
|
-
destroy(): void;
|
|
1776
|
-
private _connect;
|
|
1777
|
-
private _scheduleReconnect;
|
|
1778
|
-
private _send;
|
|
1779
|
-
private _publish;
|
|
1780
|
-
/** Handle incoming sync messages from other peers */
|
|
1781
|
-
private _handleSyncMessage;
|
|
1782
|
-
/** Broadcast local doc updates to peers */
|
|
1783
|
-
private _onDocUpdate;
|
|
1784
|
-
/** Broadcast local awareness changes to peers */
|
|
1785
|
-
private _onAwarenessUpdate;
|
|
1786
|
-
}
|
|
1787
|
-
|
|
1788
|
-
/**
|
|
1789
|
-
* useSyncManager - Access the Background Sync Manager from context
|
|
1790
|
-
*
|
|
1791
|
-
* Returns null if SyncManager is not available (disabled, not initialized,
|
|
1792
|
-
* or when running outside XNetProvider).
|
|
1793
|
-
*/
|
|
1794
|
-
|
|
1795
|
-
declare function useSyncManager(): SyncManager | null;
|
|
1796
|
-
|
|
1797
|
-
/**
|
|
1798
|
-
* Meta Bridge - Unidirectional sync from NodeStore → Y.Doc meta map
|
|
1799
|
-
*
|
|
1800
|
-
* SECURITY: This bridge is intentionally ONE-WAY. The Y.Doc meta map is a
|
|
1801
|
-
* read-only cache for the editor UI. Property changes MUST go through the
|
|
1802
|
-
* signed NodeChange pipeline (via mutate()), never through Yjs.
|
|
1803
|
-
*
|
|
1804
|
-
* Before (VULNERABLE):
|
|
1805
|
-
* NodeStore ↔ MetaBridge ↔ Y.Doc meta
|
|
1806
|
-
* (Malicious Yjs updates could poison NodeStore!)
|
|
1807
|
-
*
|
|
1808
|
-
* After (SECURE):
|
|
1809
|
-
* NodeStore → MetaBridge → Y.Doc meta (write)
|
|
1810
|
-
* Y.Doc meta → Editor UI (read-only display)
|
|
1811
|
-
* Editor UI → mutate() → NodeStore (signed writes)
|
|
1812
|
-
*
|
|
1813
|
-
* See: docs/plans/plan03_4_1YjsSecurity/04-metabridge-isolation.md
|
|
1814
|
-
*/
|
|
1815
|
-
|
|
1816
|
-
/** Transaction origin for MetaBridge writes (for debugging/monitoring) */
|
|
1817
|
-
declare const METABRIDGE_ORIGIN = "metabridge";
|
|
1818
|
-
declare const METABRIDGE_SEED_ORIGIN = "metabridge-seed";
|
|
1819
|
-
interface MetaBridge {
|
|
1820
|
-
/**
|
|
1821
|
-
* Start observing NodeStore changes for a Node and syncing to Y.Doc meta.
|
|
1822
|
-
* Direction: NodeStore → Y.Doc meta map (ONE-WAY)
|
|
1823
|
-
*
|
|
1824
|
-
* @returns Unsubscribe function
|
|
1825
|
-
*/
|
|
1826
|
-
observe(nodeId: string, doc: Y.Doc): () => void;
|
|
1827
|
-
/**
|
|
1828
|
-
* Seed the Y.Doc meta map with current NodeStore state.
|
|
1829
|
-
* Called on document open to populate editor UI.
|
|
1830
|
-
*/
|
|
1831
|
-
seed(nodeId: string, doc: Y.Doc): Promise<void>;
|
|
1832
|
-
/**
|
|
1833
|
-
* @deprecated Use seed() instead. applyNow() was the bidirectional API.
|
|
1834
|
-
* This is kept for backward compatibility but now just calls seed().
|
|
1835
|
-
*/
|
|
1836
|
-
applyNow(nodeId: string, doc: Y.Doc): Promise<void>;
|
|
1837
|
-
}
|
|
1838
|
-
/**
|
|
1839
|
-
* Create a unidirectional MetaBridge.
|
|
1840
|
-
*
|
|
1841
|
-
* @param store - NodeStore to observe
|
|
1842
|
-
* @param options - Configuration options
|
|
1843
|
-
*/
|
|
1844
|
-
declare function createMetaBridge(store: NodeStore, options?: {
|
|
1845
|
-
/** Log warnings for non-MetaBridge meta map changes (default: true) */
|
|
1846
|
-
warnOnExternalMetaChanges?: boolean;
|
|
1847
|
-
}): MetaBridge;
|
|
1848
|
-
|
|
1849
|
-
/**
|
|
1850
|
-
* Node Pool - LRU cache of Y.Doc instances with acquire/release semantics
|
|
1851
|
-
*
|
|
1852
|
-
* Components acquire a Y.Doc when they need it and release it when they unmount.
|
|
1853
|
-
* Released Y.Docs stay in the pool (warm state) and continue receiving sync
|
|
1854
|
-
* updates via the Connection Manager.
|
|
1855
|
-
*
|
|
1856
|
-
* States:
|
|
1857
|
-
* - Active: refCount > 0, never evicted
|
|
1858
|
-
* - Warm: refCount = 0, evictable (LRU)
|
|
1859
|
-
* - Cold: evicted, serialized to storage (load on demand)
|
|
1860
|
-
*/
|
|
1861
|
-
|
|
1862
|
-
type PoolEntryState = 'active' | 'warm' | 'cold';
|
|
1863
|
-
interface NodePoolConfig {
|
|
1864
|
-
/** Storage adapter for persisting Y.Doc state */
|
|
1865
|
-
storage: NodeStorageAdapter;
|
|
1866
|
-
/** Meta bridge for syncing properties to NodeStore */
|
|
1867
|
-
metaBridge: MetaBridge;
|
|
1868
|
-
/** Max warm entries before LRU eviction (default: 50) */
|
|
1869
|
-
maxWarm?: number;
|
|
1870
|
-
/** Debounce delay for persisting dirty docs (default: 2000ms) */
|
|
1871
|
-
persistDelay?: number;
|
|
1872
|
-
/** Optional callback when a doc is updated */
|
|
1873
|
-
onDocUpdate?: (nodeId: string, doc: Y.Doc) => void;
|
|
1874
|
-
/** Optional callback before a doc is evicted */
|
|
1875
|
-
onDocEvict?: (nodeId: string, doc: Y.Doc) => void;
|
|
1876
|
-
}
|
|
1877
|
-
interface NodePool {
|
|
1878
|
-
/** Acquire a Y.Doc for a Node (load from storage or create new) */
|
|
1879
|
-
acquire(nodeId: string): Promise<Y.Doc>;
|
|
1880
|
-
/** Release a Y.Doc (component unmounted, doc stays warm) */
|
|
1881
|
-
release(nodeId: string): void;
|
|
1882
|
-
/** Check if a Node is in the pool */
|
|
1883
|
-
has(nodeId: string): boolean;
|
|
1884
|
-
/** Get pool entry state */
|
|
1885
|
-
getState(nodeId: string): PoolEntryState | null;
|
|
1886
|
-
/** Number of entries currently in memory */
|
|
1887
|
-
readonly size: number;
|
|
1888
|
-
/** Force-persist all dirty docs */
|
|
1889
|
-
flushAll(): Promise<void>;
|
|
1890
|
-
/** Destroy pool, persist all docs, cleanup */
|
|
1891
|
-
destroy(): Promise<void>;
|
|
1892
|
-
}
|
|
1893
|
-
declare function createNodePool(config: NodePoolConfig): NodePool;
|
|
1894
|
-
|
|
1895
|
-
/**
|
|
1896
|
-
* NodeStoreSyncProvider - Sync NodeChange events via hub ConnectionManager.
|
|
1897
|
-
*/
|
|
1898
|
-
|
|
1899
|
-
type SerializedNodeChange = {
|
|
1900
|
-
id: string;
|
|
1901
|
-
type: string;
|
|
1902
|
-
hash: string;
|
|
1903
|
-
room: string;
|
|
1904
|
-
nodeId: string;
|
|
1905
|
-
schemaId?: string;
|
|
1906
|
-
lamportTime: number;
|
|
1907
|
-
lamportAuthor: string;
|
|
1908
|
-
authorDid: string;
|
|
1909
|
-
wallTime: number;
|
|
1910
|
-
parentHash: string | null;
|
|
1911
|
-
payload: NodePayload;
|
|
1912
|
-
signatureB64: string;
|
|
1913
|
-
batchId?: string;
|
|
1914
|
-
batchIndex?: number;
|
|
1915
|
-
batchSize?: number;
|
|
1916
|
-
};
|
|
1917
|
-
type NodeSyncResponse = {
|
|
1918
|
-
type: 'node-sync-response';
|
|
1919
|
-
room: string;
|
|
1920
|
-
changes: SerializedNodeChange[];
|
|
1921
|
-
highWaterMark: number;
|
|
1922
|
-
};
|
|
1923
|
-
/**
|
|
1924
|
-
* Listener for unknown change type events.
|
|
1925
|
-
*/
|
|
1926
|
-
type UnknownChangeTypeListener = (change: NodeChange, peerId: string) => void;
|
|
1927
|
-
declare class NodeStoreSyncProvider {
|
|
1928
|
-
private store;
|
|
1929
|
-
private room;
|
|
1930
|
-
private lastSyncedLamport;
|
|
1931
|
-
private connection;
|
|
1932
|
-
private roomCleanup;
|
|
1933
|
-
private statusCleanup;
|
|
1934
|
-
private messageCleanup;
|
|
1935
|
-
private storeCleanup;
|
|
1936
|
-
private unknownChangeTypeListeners;
|
|
1937
|
-
constructor(store: NodeStore, room: string);
|
|
1938
|
-
/**
|
|
1939
|
-
* Subscribe to unknown change type events.
|
|
1940
|
-
* These are changes received from peers with types this version doesn't know how to process.
|
|
1941
|
-
* The changes are still stored in the change log for forward compatibility.
|
|
1942
|
-
*
|
|
1943
|
-
* @param listener - Callback invoked when an unknown change type is received
|
|
1944
|
-
* @returns Unsubscribe function
|
|
1945
|
-
*/
|
|
1946
|
-
onUnknownChangeType(listener: UnknownChangeTypeListener): () => void;
|
|
1947
|
-
private emitUnknownChangeType;
|
|
1948
|
-
attach(connection: ConnectionManager): void;
|
|
1949
|
-
detach(): void;
|
|
1950
|
-
private handleRoomMessage;
|
|
1951
|
-
private handleDirectMessage;
|
|
1952
|
-
private requestSync;
|
|
1953
|
-
private syncLocalChanges;
|
|
1954
|
-
private broadcastChange;
|
|
1955
|
-
private handleRemoteChange;
|
|
1956
|
-
private handleSyncResponse;
|
|
1957
|
-
private serializeChange;
|
|
1958
|
-
private deserializeChange;
|
|
1959
|
-
}
|
|
1960
|
-
|
|
1961
|
-
/**
|
|
1962
|
-
* Registry - Persistent tracked-Node set that survives app restarts
|
|
1963
|
-
*
|
|
1964
|
-
* The Registry maintains the set of Nodes the BSM should keep synced.
|
|
1965
|
-
* Nodes are added automatically when opened and expire after a configurable TTL.
|
|
1966
|
-
* Pinned Nodes never expire.
|
|
1967
|
-
*/
|
|
1968
|
-
interface TrackedNode {
|
|
1969
|
-
nodeId: string;
|
|
1970
|
-
schemaId: string;
|
|
1971
|
-
/** When the user last opened this Node */
|
|
1972
|
-
lastOpened: number;
|
|
1973
|
-
/** When sync last completed for this Node */
|
|
1974
|
-
lastSynced: number;
|
|
1975
|
-
/** Whether explicitly pinned (never expires) */
|
|
1976
|
-
pinned: boolean;
|
|
1977
|
-
}
|
|
1978
|
-
interface RegistryStorage {
|
|
1979
|
-
get(key: string): Promise<TrackedNode[] | null>;
|
|
1980
|
-
set(key: string, entries: TrackedNode[]): Promise<void>;
|
|
1981
|
-
}
|
|
1982
|
-
interface RegistryConfig {
|
|
1983
|
-
/** Storage adapter for persistence */
|
|
1984
|
-
storage: RegistryStorage;
|
|
1985
|
-
/** TTL for tracked Nodes in ms (default: 7 days) */
|
|
1986
|
-
trackTTL?: number;
|
|
1987
|
-
/** Storage key for the tracked set */
|
|
1988
|
-
storageKey?: string;
|
|
1989
|
-
}
|
|
1990
|
-
interface Registry {
|
|
1991
|
-
/** Add a Node to the tracked set */
|
|
1992
|
-
track(nodeId: string, schemaId: string): void;
|
|
1993
|
-
/** Remove a Node from the tracked set */
|
|
1994
|
-
untrack(nodeId: string): void;
|
|
1995
|
-
/** Pin a Node (never expires) */
|
|
1996
|
-
pin(nodeId: string): void;
|
|
1997
|
-
/** Unpin a Node (subject to TTL expiry) */
|
|
1998
|
-
unpin(nodeId: string): void;
|
|
1999
|
-
/** Mark a Node as recently opened (refreshes TTL) */
|
|
2000
|
-
touch(nodeId: string): void;
|
|
2001
|
-
/** Mark a Node as synced */
|
|
2002
|
-
markSynced(nodeId: string): void;
|
|
2003
|
-
/** Get all tracked Nodes (excluding expired) */
|
|
2004
|
-
getTracked(): TrackedNode[];
|
|
2005
|
-
/** Check if a Node is tracked */
|
|
2006
|
-
isTracked(nodeId: string): boolean;
|
|
2007
|
-
/** Load from storage */
|
|
2008
|
-
load(): Promise<void>;
|
|
2009
|
-
/** Persist to storage */
|
|
2010
|
-
save(): Promise<void>;
|
|
2011
|
-
/** Remove expired entries */
|
|
2012
|
-
prune(): number;
|
|
2013
|
-
}
|
|
2014
|
-
declare function createRegistry(config: RegistryConfig): Registry;
|
|
2015
|
-
|
|
2016
|
-
/**
|
|
2017
|
-
* Offline Queue - Persistent queue for Y.Doc updates made while disconnected
|
|
2018
|
-
*
|
|
2019
|
-
* When the network is unavailable, local Y.Doc updates are queued in persistent
|
|
2020
|
-
* storage. On reconnect, the queue is drained (replayed in order). This ensures
|
|
2021
|
-
* no local changes are lost, even across app restarts.
|
|
2022
|
-
*/
|
|
2023
|
-
|
|
2024
|
-
interface QueueEntry {
|
|
2025
|
-
/** Node ID this update belongs to */
|
|
2026
|
-
nodeId: string;
|
|
2027
|
-
/** Serialized Y.Doc update (base64 encoded) */
|
|
2028
|
-
update: string;
|
|
2029
|
-
/** Timestamp when queued */
|
|
2030
|
-
queuedAt: number;
|
|
2031
|
-
}
|
|
2032
|
-
interface OfflineQueueConfig {
|
|
2033
|
-
/** Storage adapter for persistence */
|
|
2034
|
-
storage: NodeStorageAdapter;
|
|
2035
|
-
/** Storage key for the queue (default: '_xnet_offline_queue') */
|
|
2036
|
-
storageKey?: string;
|
|
2037
|
-
/** Max queue size before dropping oldest entries (default: 1000) */
|
|
2038
|
-
maxSize?: number;
|
|
2039
|
-
}
|
|
2040
|
-
interface OfflineQueue {
|
|
2041
|
-
/** Enqueue an update for later broadcast */
|
|
2042
|
-
enqueue(nodeId: string, update: Uint8Array): Promise<void>;
|
|
2043
|
-
/** Drain the queue, calling handler for each entry. Returns count drained. */
|
|
2044
|
-
drain(handler: (entry: QueueEntry) => Promise<void>): Promise<number>;
|
|
2045
|
-
/** Number of entries in the queue */
|
|
2046
|
-
readonly size: number;
|
|
2047
|
-
/** Load queue from storage */
|
|
2048
|
-
load(): Promise<void>;
|
|
2049
|
-
/** Persist queue to storage */
|
|
2050
|
-
save(): Promise<void>;
|
|
2051
|
-
/** Clear all entries */
|
|
2052
|
-
clear(): Promise<void>;
|
|
1
|
+
import { Q as QueryFilter, a as QueryStatus, F as FlatNode, b as QueryPlanSummary } from './useQuery-D7ajycrc.js';
|
|
2
|
+
export { i as FlattenNodeOptions, M as MigrationWarning, c as QueryListResult, d as QuerySingleResult, S as SortDirection, f as flattenNode, e as flattenNodes, h as flattenNodesWithSchemaCheck, g as flattenUnknownSchemaNode, u as useQuery } from './useQuery-D7ajycrc.js';
|
|
3
|
+
export { ErrorBoundary, ErrorBoundaryProps, InfiniteQueryFilter, InfiniteQueryPage, InfiniteQueryResult, MutateCreate, MutateDelete, MutateOp, MutateRestore, MutateUpdate, OfflineIndicator, OfflineIndicatorProps, PresenceUser, SyncStatus, UseIdentityResult, UseMutateResult, UseNodeOptions, UseNodeResult, useIdentity, useInfiniteQuery, useIsOffline, useMutate, useNode } from './core.js';
|
|
4
|
+
import { U as UseTaskProjectionSyncResult, T as TaskProjectionInput, a as TaskTreeItem } from './experimental-B2FrBnkV.js';
|
|
5
|
+
export { A as AddCommentOptions, a0 as AddReactionOptions, bm as AuthErrorScreen, aP as AuthTraceSummary, bl as AuthenticatingScreen, r as CommentNode, C as CommentThread, F as CommentVisibility, ad as CreateMessageRequestOptions, b7 as DemoBanner, b8 as DemoBannerProps, bb as DemoDataExpiredScreen, be as DemoLimits, bd as DemoModeState, b9 as DemoQuotaIndicator, ba as DemoQuotaIndicatorProps, bf as DemoUsage, b2 as DiscoveredPeer, aU as FileRef, ae as FirstContactAdmission, af as FirstContactDecision, ag as FirstContactDecisionInput, G as FirstContactMode, ah as FirstContactVisibility, aK as GrantConsentSummary, aL as GrantInput, bp as HubConnectScreen, aX as HubSearchOptions, aY as HubSearchResult, aZ as HubSearchState, b3 as HubStatusIndicator, bo as ImportIdentityScreen, I as InteractionPermission, ai as MessageRequestNode, aj as MessageRequestProperties, ak as MessageRequestStatus, M as ModeratedCommentNode, H as ModeratedCommentThread, J as ModerationFilterOptions, K as ModerationLabelSummary, bA as OnboardingContextValue, bD as OnboardingEvent, bj as OnboardingFlow, bB as OnboardingFlowProps, bE as OnboardingMachineContext, bh as OnboardingProvider, bz as OnboardingProviderProps, bF as OnboardingReducerState, bC as OnboardingState, P as PageTaskInput, e as PageTaskReferenceInput, bI as PageTasksPanel, bJ as PageTasksPanelProps, bW as PluginRegistryContext, L as PublicInteractionMode, N as PublicInteractionPolicySnapshot, O as PublicInteractionSurface, Q as PublicModerationMode, bv as QUICK_START_TEMPLATES, bG as QuickStartTemplate, a1 as ReactionCounterSnapshot, a2 as ReactionNode, a3 as ReactionType, bq as ReadyScreen, a$ as RemoteSchemaDefinition, b0 as RemoteSchemaState, R as ReplyContext, bQ as SecurityContextActions, bP as SecurityContextState, bR as SecurityContextValue, bM as SecurityProvider, bS as SecurityProviderProps, b4 as Skeleton, b6 as SkeletonProps, br as SmartWelcome, bs as SyncProgressOverlay, bH as SyncProgressOverlayProps, bK as TaskCollectionEmbed, bL as TaskCollectionEmbedProps, j as TaskProjectionHost, i as TaskProjectionReferenceInput, bn as UnsupportedBrowserScreen, aw as UseAuditOptions, av as UseAuditResult, aQ as UseAuthTraceResult, aS as UseBackupReturn, aA as UseBlameResult, aH as UseCanEditResult, aF as UseCanResult, p as UseCommentsOptions, q as UseCommentsResult, ay as UseDiffResult, aV as UseFileUploadReturn, b as UseFindOptions, c as UseFindResult, aM as UseGrantsResult, aq as UseHistoryResult, al as UseMessageRequestsOptions, am as UseMessageRequestsResult, S as UseModeratedThreadOptions, f as UsePageTaskSyncOptions, g as UsePageTaskSyncResult, a4 as UsePolicyFilteredReactionCountersOptions, a5 as UsePolicyFilteredReactionCountersResult, bU as UseSecurityOptions, bV as UseSecurityResult, k as UseTaskProjectionSyncOptions, m as UseTasksOptions, n as UseTasksResult, at as UseUndoOptions, as as UseUndoResult, aC as UseVerificationResult, V as UseVisibleCommentsOptions, W as UseVisibleCommentsResult, bk as WelcomeScreen, by as copyToClipboard, a7 as createConversationKey, bu as createInitialState, a8 as createMessageRequestProperties, v as createModerationLabelIndex, Y as createReactionCounterSnapshot, Z as dedupeReactions, aI as describeGrantConsent, w as evaluateCommentModeration, a9 as evaluateFirstContactDecision, x as evaluateInteractionPermission, aa as findLatestMessageRequest, bw as getPlatformAuthName, ab as hasAcceptedContact, b5 as injectSkeletonStyles, _ as isReactionVisible, y as moderateThread, bt as onboardingReducer, z as selectActiveInteractionPolicy, B as selectPublicInteractionMode, aN as summarizeAuthTrace, ac as summarizeMessageRequest, D as summarizeModerationLabel, E as summarizePublicInteractionPolicy, $ as summarizeReactionNode, bx as truncateDid, au as useAudit, aO as useAuthTrace, aR as useBackup, az as useBlame, aE as useCan, aG as useCanEdit, c7 as useCommand, c0 as useCommands, an as useCommentCount, ao as useCommentCounts, o as useComments, b_ as useContributions, bc as useDemoMode, ax as useDiff, c4 as useEditorExtensions, c5 as useEditorExtensionsSafe, aT as useFileUpload, u as useFind, aJ as useGrants, ap as useHistory, aW as useHubSearch, aD as useHubStatus, c3 as useImporters, a6 as useMessageRequests, t as useModeratedThread, bi as useOnboarding, d as usePageTaskSync, b1 as usePeerDiscovery, bX as usePluginRegistry, bY as usePluginRegistryOptional, bZ as usePlugins, X as usePolicyFilteredReactionCounters, a_ as useRemoteSchema, bT as useSecurity, bN as useSecurityContext, bO as useSecurityContextOptional, c2 as useSidebarItems, c1 as useSlashCommands, bg as useSyncManager, h as useTaskProjectionSync, l as useTasks, ar as useUndo, aB as useVerification, c6 as useView, b$ as useViews, s as useVisibleComments } from './experimental-B2FrBnkV.js';
|
|
6
|
+
import { SchemaIRI, Schema, SavedViewDescriptor, DefinedSchema, PropertyBuilder, QueryASTOrderBy, QueryASTPage, QueryASTValidationResult, QueryASTPlannerGate, QueryASTAggregateExecution, ExternalReferenceProvider, SavedViewFeedLayout, SavedViewFeedDensity, FieldType, FieldConfig, ViewType, FilterGroup, SortConfig, RowHeight, SummaryFunction, CellValue } from '@xnetjs/data';
|
|
7
|
+
export { ColumnConfig, ColumnDefinition, ColumnType, SavedViewFeedDensity, SavedViewFeedLayout, ViewConfig, ViewType } from '@xnetjs/data';
|
|
8
|
+
import { QueryExecutionMode, QuerySourcePreference, QuerySearchFilter, QueryPageInfo, QueryMetadata } from '@xnetjs/data-bridge';
|
|
9
|
+
import { LucideIcon } from 'lucide-react';
|
|
10
|
+
import { ReactNode, JSX } from 'react';
|
|
11
|
+
export { DatabaseRow, DatabaseRowData, ReverseRelation, UseCellOptions, UseCellResult, UseDatabaseDocResult, UseDatabaseOptions, UseDatabaseResult, UseDatabaseRowResult, UseDatabaseSchemaResult, UseRelatedRowsResult, UseReverseRelationsResult, useCell, useDatabase, useDatabaseDoc, useDatabaseRow, useDatabaseSchema, useRelatedRows, useReverseRelations } from './database.js';
|
|
12
|
+
export { u as useNodeStore } from './useNodeStore-DTCSBF51.js';
|
|
13
|
+
export { BlobStoreForSync, ConnectionManager, ConnectionManagerConfig, ConnectionStatus, InitialSyncManager, InitialSyncMessage, METABRIDGE_ORIGIN, METABRIDGE_SEED_ORIGIN, MetaBridge, MultiHubConnectionManagerConfig, NodePool, NodePoolConfig, NodeStoreSyncProvider, NodeSyncResponse, OfflineQueue, OfflineQueueConfig, PoolEntryState, ProgressListener, QueueEntry, Registry, RegistryConfig, RegistryStorage, SerializedNodeChange, SyncManager, SyncManagerConfig, SyncStatus as SyncManagerStatus, SyncPhase, SyncProgress, SyncReconciliationOptions, SyncReconciliationReport, TrackedNode, WebSocketSyncProvider, WebSocketSyncProviderOptions, createConnectionManager, createInitialSyncManager, createMetaBridge, createMultiHubConnectionManager, createNodePool, createOfflineQueue, createRegistry, createSyncManager } from '@xnetjs/runtime';
|
|
14
|
+
import { Subscription, Customer, Invoice, Payment } from '@xnetjs/billing';
|
|
15
|
+
export { n as TRACE_STAGES, s as TracingAttributes, T as TracingContext, p as TracingHandle, o as TracingReporter, r as TracingRootKind, q as TracingSpanInput, f as XNetConfig, X as XNetContextValue, e as XNetProvider, g as XNetProviderProps, h as XNetRuntimeConfig, i as XNetRuntimeFallback, j as XNetRuntimeMode, k as XNetRuntimePhase, d as XNetRuntimeStatus, l as XNetRuntimeWorkerConfig, u as useDataBridge, m as useTracingReporter, a as useXNet } from './context-CFu9i136.js';
|
|
16
|
+
export { I as InstrumentationContext, a as InstrumentationContextValue, Q as QueryTrackerLike, Y as YDocRegistryLike, u as useInstrumentation } from './instrumentation-CpIuG2y5.js';
|
|
17
|
+
export { a as TelemetryContext, T as TelemetryReporter, u as useTelemetryReporter } from './telemetry-context-B7r6H1KW.js';
|
|
18
|
+
import '@xnetjs/core';
|
|
19
|
+
import 'y-protocols/awareness';
|
|
20
|
+
import 'yjs';
|
|
21
|
+
import '@xnetjs/identity';
|
|
22
|
+
import '@xnetjs/history';
|
|
23
|
+
import 'react/jsx-runtime';
|
|
24
|
+
import '@xnetjs/crypto';
|
|
25
|
+
import '@xnetjs/plugins';
|
|
26
|
+
import '@xnetjs/sync';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* useEffectiveSchema — resolve a node type's *effective* schema reactively:
|
|
30
|
+
* the canonical core schema (from the registry) plus any registered extension
|
|
31
|
+
* fields, composed by `buildEffectiveSchema`.
|
|
32
|
+
*
|
|
33
|
+
* This is the keystone for the universal database view: given any schema IRI
|
|
34
|
+
* (a built-in like `Task`/`Contact`, or a database-derived schema), it yields
|
|
35
|
+
* the column set the grid should render — core columns marked `readonly`
|
|
36
|
+
* (structurally locked) and `ext:<authority>/<field>` columns editable.
|
|
37
|
+
*
|
|
38
|
+
* Composition happens at read time (not cached in the registry) because
|
|
39
|
+
* extensions are added/removed live; the two `useQuery` subscriptions keep the
|
|
40
|
+
* effective schema in sync as `SchemaExtension`/`ExtensionField` nodes change.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
interface UseEffectiveSchemaResult {
|
|
44
|
+
/** The composed effective schema, or null while the core schema loads / can't resolve. */
|
|
45
|
+
schema: Schema | null;
|
|
46
|
+
/** True while the core schema is being resolved. */
|
|
47
|
+
loading: boolean;
|
|
2053
48
|
}
|
|
2054
|
-
declare function
|
|
49
|
+
declare function useEffectiveSchema(schemaId: SchemaIRI | null | undefined): UseEffectiveSchemaResult;
|
|
2055
50
|
|
|
2056
51
|
/**
|
|
2057
|
-
*
|
|
52
|
+
* useSavedView - Execute persisted SavedView descriptors.
|
|
2058
53
|
*/
|
|
2059
54
|
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
55
|
+
type RegistrySchema = DefinedSchema<Record<string, PropertyBuilder>>;
|
|
56
|
+
type SavedViewSchemaRegistry = readonly RegistrySchema[];
|
|
57
|
+
type SavedViewPrivacySummary = {
|
|
58
|
+
counts: Record<string, number>;
|
|
59
|
+
sensitiveCount: number;
|
|
60
|
+
};
|
|
61
|
+
type SavedViewQueryOverride = {
|
|
62
|
+
search?: string | QuerySearchFilter;
|
|
63
|
+
orderBy?: QueryASTOrderBy[];
|
|
64
|
+
page?: QueryASTPage;
|
|
65
|
+
};
|
|
66
|
+
type UseSavedViewOptions = Pick<QueryFilter<Record<string, PropertyBuilder>>, 'includeDeleted' | 'materializedView'> & {
|
|
67
|
+
mode?: QueryExecutionMode;
|
|
68
|
+
source?: QuerySourcePreference;
|
|
69
|
+
search?: string | QuerySearchFilter;
|
|
70
|
+
includePolicy?: 'ignore' | 'block';
|
|
71
|
+
queryOverrides?: Record<string, SavedViewQueryOverride>;
|
|
72
|
+
};
|
|
73
|
+
type SavedViewQueryResult = {
|
|
74
|
+
queryId: string;
|
|
75
|
+
rowRole: string;
|
|
76
|
+
schemaId: string;
|
|
77
|
+
schemaName: string;
|
|
78
|
+
data: FlatNode<Record<string, PropertyBuilder>>[];
|
|
79
|
+
status: QueryStatus;
|
|
80
|
+
loading: boolean;
|
|
81
|
+
error: Error | null;
|
|
82
|
+
pageInfo: QueryPageInfo;
|
|
83
|
+
totalCount: number | null;
|
|
84
|
+
hasMore: boolean;
|
|
85
|
+
plan: QueryPlanSummary | null;
|
|
86
|
+
metadata: QueryMetadata | null;
|
|
87
|
+
plannerGate: QueryASTPlannerGate;
|
|
88
|
+
blockers: string[];
|
|
89
|
+
warnings: string[];
|
|
90
|
+
canExecute: boolean;
|
|
91
|
+
aggregates: QueryASTAggregateExecution | null;
|
|
92
|
+
privacy: SavedViewPrivacySummary;
|
|
93
|
+
};
|
|
94
|
+
type UseSavedViewResult = {
|
|
95
|
+
descriptor: SavedViewDescriptor | null;
|
|
96
|
+
validation: QueryASTValidationResult;
|
|
97
|
+
kind: 'node' | 'query-set' | 'invalid';
|
|
98
|
+
status: QueryStatus;
|
|
99
|
+
loading: boolean;
|
|
100
|
+
error: Error | null;
|
|
101
|
+
title: string | null;
|
|
102
|
+
description: string | null;
|
|
103
|
+
primaryQueryId: string | null;
|
|
104
|
+
queryIds: string[];
|
|
105
|
+
queries: Record<string, SavedViewQueryResult>;
|
|
106
|
+
primary: SavedViewQueryResult | null;
|
|
107
|
+
blockers: string[];
|
|
108
|
+
warnings: string[];
|
|
109
|
+
privacy: SavedViewPrivacySummary;
|
|
110
|
+
reload: () => void;
|
|
111
|
+
};
|
|
112
|
+
declare function useSavedView(input: SavedViewDescriptor | string | null | undefined, registry: SavedViewSchemaRegistry, options?: UseSavedViewOptions): UseSavedViewResult;
|
|
2072
113
|
|
|
2073
114
|
/**
|
|
2074
|
-
*
|
|
2075
|
-
*
|
|
2076
|
-
* States:
|
|
2077
|
-
* welcome → authenticating → connecting-hub → ready → complete
|
|
2078
|
-
* ↓ ↑
|
|
2079
|
-
* auth-error ──────── (retry) ────────┘
|
|
2080
|
-
* welcome → unsupported-browser (terminal)
|
|
2081
|
-
* welcome → import-identity → qr-scan/recovery-phrase → connecting-hub
|
|
115
|
+
* Shared visual-preview derivation for saved view rows.
|
|
2082
116
|
*/
|
|
2083
117
|
|
|
2084
|
-
type
|
|
2085
|
-
type
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
type: 'IMPORT_EXISTING';
|
|
2091
|
-
} | {
|
|
2092
|
-
type: 'PASSKEY_SUCCESS';
|
|
2093
|
-
identity: Identity;
|
|
2094
|
-
keyBundle: KeyBundle;
|
|
2095
|
-
} | {
|
|
2096
|
-
type: 'PASSKEY_FAILED';
|
|
2097
|
-
error: Error;
|
|
2098
|
-
} | {
|
|
2099
|
-
type: 'BROWSER_UNSUPPORTED';
|
|
2100
|
-
} | {
|
|
2101
|
-
type: 'RETRY_AUTH';
|
|
2102
|
-
} | {
|
|
2103
|
-
type: 'BACK_TO_WELCOME';
|
|
118
|
+
type SavedViewVisualPreviewKind = 'content' | 'actor' | 'interaction' | 'message' | 'collection' | 'reference' | 'record';
|
|
119
|
+
type SavedViewVisualPreviewPrivacy = 'private' | 'shared' | 'public' | 'unknown';
|
|
120
|
+
type SavedViewVisualWorkspaceLayout = {
|
|
121
|
+
kind: 'grid';
|
|
122
|
+
groupBy?: string;
|
|
123
|
+
sortBy?: string;
|
|
2104
124
|
} | {
|
|
2105
|
-
|
|
125
|
+
kind: 'timeline';
|
|
126
|
+
timeField: string;
|
|
127
|
+
laneBy?: string;
|
|
2106
128
|
} | {
|
|
2107
|
-
|
|
129
|
+
kind: 'cluster';
|
|
130
|
+
groupBy: string;
|
|
131
|
+
sizeBy?: string;
|
|
2108
132
|
} | {
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
133
|
+
kind: 'graph';
|
|
134
|
+
lensId?: string;
|
|
135
|
+
algorithm: 'layered' | 'radial' | 'force' | 'stress';
|
|
2112
136
|
} | {
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
type: 'HUB_FAILED';
|
|
2116
|
-
error: Error;
|
|
2117
|
-
} | {
|
|
2118
|
-
type: 'CREATE_FIRST_PAGE';
|
|
137
|
+
kind: 'collection-board';
|
|
138
|
+
collectionField: string;
|
|
2119
139
|
};
|
|
2120
|
-
type
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
error: Error | null;
|
|
2125
|
-
isDemo: boolean;
|
|
140
|
+
type SavedViewVisualPreviewCreator = {
|
|
141
|
+
id?: string;
|
|
142
|
+
label: string;
|
|
143
|
+
url?: string;
|
|
2126
144
|
};
|
|
2127
|
-
type
|
|
2128
|
-
|
|
2129
|
-
|
|
145
|
+
type SavedViewVisualPreviewRelationship = {
|
|
146
|
+
kind: string;
|
|
147
|
+
targetNodeId: string;
|
|
148
|
+
label?: string;
|
|
2130
149
|
};
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
150
|
+
type SavedViewVisualPreviewModel = {
|
|
151
|
+
id: string;
|
|
152
|
+
sourceNodeId: string;
|
|
153
|
+
sourceSchemaId: string;
|
|
154
|
+
kind: SavedViewVisualPreviewKind;
|
|
155
|
+
platform: string;
|
|
156
|
+
title: string;
|
|
157
|
+
subtitle?: string;
|
|
158
|
+
description?: string;
|
|
159
|
+
creator?: SavedViewVisualPreviewCreator;
|
|
160
|
+
timestamp?: string;
|
|
161
|
+
timestampMs?: number;
|
|
162
|
+
url?: string;
|
|
163
|
+
thumbnailUrl?: string;
|
|
164
|
+
embedUrl?: string;
|
|
165
|
+
provider?: ExternalReferenceProvider;
|
|
166
|
+
platformContentId?: string;
|
|
167
|
+
privacy: SavedViewVisualPreviewPrivacy;
|
|
168
|
+
metrics: Record<string, number>;
|
|
169
|
+
relationships: SavedViewVisualPreviewRelationship[];
|
|
170
|
+
source: {
|
|
171
|
+
queryId?: string;
|
|
172
|
+
rowRole?: string;
|
|
173
|
+
schemaName?: string;
|
|
174
|
+
sourceRecordId?: string;
|
|
175
|
+
importRunId?: string;
|
|
176
|
+
};
|
|
2142
177
|
};
|
|
2143
|
-
type
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
178
|
+
type SavedViewVisualTimelineBucket = {
|
|
179
|
+
key: string;
|
|
180
|
+
label: string;
|
|
181
|
+
startMs: number;
|
|
182
|
+
count: number;
|
|
183
|
+
previews: SavedViewVisualPreviewModel[];
|
|
2149
184
|
};
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
185
|
+
type SavedViewCanvasProjectionNode = {
|
|
186
|
+
id: string;
|
|
187
|
+
schemaId: string;
|
|
188
|
+
kind: 'actor' | 'content' | 'interaction' | 'conversation' | 'message' | 'collection' | 'collection-item' | 'source-record';
|
|
189
|
+
title: string;
|
|
190
|
+
subtitle?: string;
|
|
191
|
+
platform?: string;
|
|
192
|
+
privacyClass?: string;
|
|
193
|
+
groupKey?: string;
|
|
2159
194
|
};
|
|
2160
|
-
declare function
|
|
195
|
+
declare function deriveSavedViewVisualPreview(row: Readonly<Record<string, unknown>>, query?: Pick<SavedViewQueryResult, 'queryId' | 'rowRole' | 'schemaId' | 'schemaName'> | null): SavedViewVisualPreviewModel;
|
|
196
|
+
declare function deriveSavedViewVisualPreviews(rows: readonly Readonly<Record<string, unknown>>[], query?: Pick<SavedViewQueryResult, 'queryId' | 'rowRole' | 'schemaId' | 'schemaName'> | null): SavedViewVisualPreviewModel[];
|
|
197
|
+
declare function deriveCachedSavedViewVisualPreviews(input: {
|
|
198
|
+
descriptor?: SavedViewDescriptor | string | null;
|
|
199
|
+
query?: Pick<SavedViewQueryResult, 'queryId' | 'rowRole' | 'schemaId' | 'schemaName'> | null;
|
|
200
|
+
rows: readonly Readonly<Record<string, unknown>>[];
|
|
201
|
+
}): SavedViewVisualPreviewModel[];
|
|
202
|
+
declare function createSavedViewVisualPreviewFingerprint(input: {
|
|
203
|
+
descriptor?: SavedViewDescriptor | string | null;
|
|
204
|
+
query?: Pick<SavedViewQueryResult, 'queryId' | 'schemaId'> | null;
|
|
205
|
+
rows: readonly Readonly<Record<string, unknown>>[];
|
|
206
|
+
}): string;
|
|
207
|
+
declare function deriveSavedViewTimelineBuckets(previews: readonly SavedViewVisualPreviewModel[]): SavedViewVisualTimelineBucket[];
|
|
208
|
+
declare function createSavedViewCanvasProjectionNodes(previews: readonly SavedViewVisualPreviewModel[], options?: {
|
|
209
|
+
limit?: number;
|
|
210
|
+
groupBy?: 'platform' | 'kind' | 'creator' | 'privacy';
|
|
211
|
+
}): SavedViewCanvasProjectionNode[];
|
|
212
|
+
declare function isSavedViewVisualPreviewEmbeddable(preview: SavedViewVisualPreviewModel): boolean;
|
|
213
|
+
declare function hasSavedViewVisualPreviewSensitiveData(preview: SavedViewVisualPreviewModel): boolean;
|
|
214
|
+
declare function savedViewVisualPreviewIsSelfActor(row: Readonly<Record<string, unknown>>): boolean;
|
|
2161
215
|
|
|
2162
|
-
interface OnboardingFlowProps {
|
|
2163
|
-
/** Optional hub connection function */
|
|
2164
|
-
connectToHub?: HubConnectScreenProps['connectToHub'];
|
|
2165
|
-
/** Render prop for the completed state (app content) */
|
|
2166
|
-
children?: React.ReactNode;
|
|
2167
|
-
}
|
|
2168
216
|
/**
|
|
2169
|
-
*
|
|
217
|
+
* @xnetjs/react - Media feed presentation for saved view previews.
|
|
2170
218
|
*
|
|
2171
|
-
*
|
|
2172
|
-
*
|
|
2173
|
-
* <OnboardingFlow>
|
|
2174
|
-
* <App />
|
|
2175
|
-
* </OnboardingFlow>
|
|
2176
|
-
* </OnboardingProvider>
|
|
219
|
+
* Renders content-shaped rows (videos, posts, saves, playlists) as a
|
|
220
|
+
* thumbnail-forward feed with list/grid layouts and a density control.
|
|
2177
221
|
*/
|
|
2178
|
-
declare function OnboardingFlow({ connectToHub, children }: OnboardingFlowProps): JSX.Element;
|
|
2179
|
-
|
|
2180
|
-
declare function WelcomeScreen(): JSX.Element;
|
|
2181
|
-
|
|
2182
|
-
declare function AuthenticatingScreen(): JSX.Element;
|
|
2183
|
-
|
|
2184
|
-
declare function AuthErrorScreen(): JSX.Element;
|
|
2185
|
-
|
|
2186
|
-
declare function UnsupportedBrowserScreen(): JSX.Element;
|
|
2187
|
-
|
|
2188
|
-
declare function ImportIdentityScreen(): JSX.Element;
|
|
2189
|
-
|
|
2190
|
-
declare function ReadyScreen(): JSX.Element;
|
|
2191
|
-
|
|
2192
|
-
declare function SmartWelcome(): JSX.Element;
|
|
2193
222
|
|
|
223
|
+
type SavedViewFeedEnrichmentEntry = {
|
|
224
|
+
title?: string | null;
|
|
225
|
+
description?: string | null;
|
|
226
|
+
authorName?: string | null;
|
|
227
|
+
thumbnailUrl?: string | null;
|
|
228
|
+
};
|
|
2194
229
|
/**
|
|
2195
|
-
*
|
|
2196
|
-
*
|
|
2197
|
-
*
|
|
2198
|
-
* with an existing identity. Tracks progress and provides callbacks.
|
|
230
|
+
* Optional overlay that lets the host app merge locally cached metadata
|
|
231
|
+
* (titles, descriptions, thumbnails) over imported preview rows and request
|
|
232
|
+
* fetches for the previews currently on screen.
|
|
2199
233
|
*/
|
|
2200
|
-
type
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
234
|
+
type SavedViewFeedEnrichmentAdapter = {
|
|
235
|
+
lookup: (preview: SavedViewVisualPreviewModel) => SavedViewFeedEnrichmentEntry | null;
|
|
236
|
+
requestMany?: (previews: readonly SavedViewVisualPreviewModel[]) => void;
|
|
237
|
+
};
|
|
238
|
+
declare function mergeSavedViewFeedEnrichment(preview: SavedViewVisualPreviewModel, entry: SavedViewFeedEnrichmentEntry | null | undefined): SavedViewVisualPreviewModel;
|
|
239
|
+
declare function SavedViewVisualFeed({ previews, layout, density, onSelectLayout, onSelectDensity, selectedSourceNodeId, activeEmbedPreviewId, onSelectPreview, onToggleLiveEmbed, enrichment, wrapItem }: {
|
|
240
|
+
previews: SavedViewVisualPreviewModel[];
|
|
241
|
+
layout: SavedViewFeedLayout;
|
|
242
|
+
density: SavedViewFeedDensity;
|
|
243
|
+
onSelectLayout: (layout: SavedViewFeedLayout) => void;
|
|
244
|
+
onSelectDensity: (density: SavedViewFeedDensity) => void;
|
|
245
|
+
selectedSourceNodeId: string | null;
|
|
246
|
+
activeEmbedPreviewId: string | null;
|
|
247
|
+
onSelectPreview: (preview: SavedViewVisualPreviewModel) => void;
|
|
248
|
+
onToggleLiveEmbed: (preview: SavedViewVisualPreviewModel) => void;
|
|
249
|
+
enrichment?: SavedViewFeedEnrichmentAdapter;
|
|
250
|
+
wrapItem?: (nodeId: string, content: ReactNode) => ReactNode;
|
|
251
|
+
}): JSX.Element;
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* @xnetjs/react - Generic saved view execution surface.
|
|
255
|
+
*/
|
|
256
|
+
|
|
257
|
+
type SavedViewRunnerProps = {
|
|
258
|
+
descriptor?: SavedViewDescriptor | string | null;
|
|
259
|
+
registry: SavedViewSchemaRegistry;
|
|
260
|
+
title?: string | null;
|
|
261
|
+
description?: string | null;
|
|
262
|
+
fallbackId?: string | null;
|
|
263
|
+
resetKey?: string | null;
|
|
264
|
+
className?: string;
|
|
265
|
+
emptyLabel?: string;
|
|
266
|
+
pageSizes?: readonly number[];
|
|
267
|
+
initialPageSize?: number;
|
|
268
|
+
options?: Omit<UseSavedViewOptions, 'queryOverrides' | 'search'>;
|
|
269
|
+
onSaveLens?: (draft: SavedViewLensDraft) => void | Promise<void>;
|
|
270
|
+
saveLensLabel?: string;
|
|
271
|
+
onOpenVisualCanvasProjection?: (request: SavedViewVisualCanvasProjectionRequest) => void | Promise<void>;
|
|
272
|
+
feedEnrichment?: SavedViewFeedEnrichmentAdapter;
|
|
273
|
+
/**
|
|
274
|
+
* Optional per-item wrapper for the visual renderers (cards mode), keyed by a
|
|
275
|
+
* preview's source node id. The host uses it to route each item through its
|
|
276
|
+
* moderation render gate without this package depending on it. Default: no-op
|
|
277
|
+
* (content rendered unwrapped, exactly as before).
|
|
278
|
+
*/
|
|
279
|
+
wrapItem?: (nodeId: string, content: ReactNode) => ReactNode;
|
|
2212
280
|
};
|
|
2213
|
-
type
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
281
|
+
type SavedViewResultTableProps = {
|
|
282
|
+
query: SavedViewQueryResult | null;
|
|
283
|
+
columns: readonly string[];
|
|
284
|
+
expandedRowId: string | null;
|
|
285
|
+
onToggleRow: (rowId: string) => void;
|
|
286
|
+
loadingLabel?: string;
|
|
287
|
+
emptyLabel?: string;
|
|
288
|
+
formatValue?: (input: {
|
|
289
|
+
column: string;
|
|
290
|
+
value: unknown;
|
|
291
|
+
row: Record<string, unknown>;
|
|
292
|
+
}) => ReactNode;
|
|
2219
293
|
};
|
|
2220
|
-
type
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
* ```ts
|
|
2226
|
-
* const manager = createInitialSyncManager()
|
|
2227
|
-
* const unsub = manager.onProgress((p) => updateUI(p))
|
|
2228
|
-
*
|
|
2229
|
-
* // Feed messages from the hub WebSocket:
|
|
2230
|
-
* manager.handleMessage({ type: 'initial-sync', room: 'r1', update: ... })
|
|
2231
|
-
* manager.handleMessage({ type: 'initial-sync-complete', roomCount: 5 })
|
|
2232
|
-
*
|
|
2233
|
-
* unsub()
|
|
2234
|
-
* ```
|
|
2235
|
-
*/
|
|
2236
|
-
type InitialSyncManager = {
|
|
2237
|
-
/** Subscribe to progress updates */
|
|
2238
|
-
onProgress(listener: ProgressListener): () => void;
|
|
2239
|
-
/** Handle an incoming sync message from the hub */
|
|
2240
|
-
handleMessage(msg: InitialSyncMessage): void;
|
|
2241
|
-
/** Get current progress snapshot */
|
|
2242
|
-
getProgress(): SyncProgress;
|
|
2243
|
-
/** Mark sync as started (connecting phase) */
|
|
2244
|
-
start(): void;
|
|
2245
|
-
/** Mark sync as errored */
|
|
2246
|
-
setError(error: Error): void;
|
|
2247
|
-
/** Reset to initial state */
|
|
2248
|
-
reset(): void;
|
|
294
|
+
type SavedViewFacetSelection = Record<string, readonly string[]>;
|
|
295
|
+
type SavedViewFacetValueSummary = {
|
|
296
|
+
valueKey: string;
|
|
297
|
+
label: string;
|
|
298
|
+
count: number;
|
|
2249
299
|
};
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
300
|
+
type SavedViewFacetSummary = {
|
|
301
|
+
field: string;
|
|
302
|
+
values: SavedViewFacetValueSummary[];
|
|
303
|
+
totalValues: number;
|
|
304
|
+
};
|
|
305
|
+
type SavedViewDateBucketInterval = 'day' | 'month' | 'year';
|
|
306
|
+
type SavedViewDateBucketSummary = {
|
|
307
|
+
bucketKey: string;
|
|
308
|
+
label: string;
|
|
309
|
+
startMs: number;
|
|
310
|
+
endMs: number;
|
|
311
|
+
count: number;
|
|
312
|
+
};
|
|
313
|
+
type SavedViewDateBucketFieldSummary = {
|
|
314
|
+
field: string;
|
|
315
|
+
interval: SavedViewDateBucketInterval;
|
|
316
|
+
buckets: SavedViewDateBucketSummary[];
|
|
317
|
+
minMs: number;
|
|
318
|
+
maxMs: number;
|
|
319
|
+
totalRows: number;
|
|
320
|
+
};
|
|
321
|
+
type SavedViewDateBrushSelection = {
|
|
322
|
+
field: string | null;
|
|
323
|
+
bucketKeys: readonly string[];
|
|
324
|
+
};
|
|
325
|
+
type SavedViewInspectorItemKind = 'field' | 'relation' | 'source' | 'import';
|
|
326
|
+
type SavedViewInspectorItem = {
|
|
327
|
+
key: string;
|
|
328
|
+
label: string;
|
|
329
|
+
value: unknown;
|
|
330
|
+
formatted: string;
|
|
331
|
+
kind: SavedViewInspectorItemKind;
|
|
332
|
+
};
|
|
333
|
+
type SavedViewRowInspectorModel = {
|
|
334
|
+
rowId: string;
|
|
335
|
+
schemaId: string;
|
|
336
|
+
rowRole: string | null;
|
|
337
|
+
fields: SavedViewInspectorItem[];
|
|
338
|
+
relations: SavedViewInspectorItem[];
|
|
339
|
+
sourceRecords: SavedViewInspectorItem[];
|
|
340
|
+
importRuns: SavedViewInspectorItem[];
|
|
341
|
+
rawJson: string;
|
|
342
|
+
};
|
|
343
|
+
type SavedViewPrivacyChipTone = 'safe' | 'neutral' | 'warning';
|
|
344
|
+
type SavedViewPrivacyChip = {
|
|
345
|
+
privacyClass: string;
|
|
346
|
+
label: string;
|
|
347
|
+
count: number;
|
|
348
|
+
tone: SavedViewPrivacyChipTone;
|
|
349
|
+
};
|
|
350
|
+
type SavedViewSortDirection = 'asc' | 'desc';
|
|
351
|
+
type SavedViewLensDraft = {
|
|
352
|
+
title: string;
|
|
2268
353
|
description: string;
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
354
|
+
descriptor: SavedViewDescriptor;
|
|
355
|
+
queryId: string;
|
|
356
|
+
sourceTitle: string;
|
|
357
|
+
stateSummary: {
|
|
358
|
+
facetFields: string[];
|
|
359
|
+
dateField: string | null;
|
|
360
|
+
dateBucketCount: number;
|
|
361
|
+
sortField: string | null;
|
|
362
|
+
sortDirection: SavedViewSortDirection | null;
|
|
363
|
+
pageSize: number;
|
|
364
|
+
};
|
|
365
|
+
};
|
|
366
|
+
type SavedViewPresentationMode = 'table' | 'cards' | 'timeline' | 'canvas' | 'graph' | 'feed';
|
|
2272
367
|
|
|
368
|
+
type SavedViewVisualLayoutId = 'grid' | 'timeline' | 'creator-clusters' | 'platform-lanes' | 'content-type-lanes' | 'date-bands' | 'collection-board' | 'graph';
|
|
369
|
+
type SavedViewVisualLayoutOption = {
|
|
370
|
+
id: SavedViewVisualLayoutId;
|
|
371
|
+
label: string;
|
|
372
|
+
description: string;
|
|
373
|
+
icon: LucideIcon;
|
|
374
|
+
enabled: boolean;
|
|
375
|
+
workspaceLayout: SavedViewVisualWorkspaceLayout;
|
|
376
|
+
projectionGroupBy: 'platform' | 'kind' | 'creator' | 'privacy';
|
|
377
|
+
};
|
|
378
|
+
type SavedViewVisualCanvasProjectionRequest = {
|
|
379
|
+
id: string;
|
|
380
|
+
title: string;
|
|
381
|
+
description?: string | null;
|
|
382
|
+
descriptor?: SavedViewDescriptor | string | null;
|
|
383
|
+
sourceQueryId?: string | null;
|
|
384
|
+
sourceSchemaId?: string | null;
|
|
385
|
+
layout: {
|
|
386
|
+
id: SavedViewVisualLayoutId;
|
|
387
|
+
label: string;
|
|
388
|
+
workspaceLayout: SavedViewVisualWorkspaceLayout;
|
|
389
|
+
projectionGroupBy: SavedViewVisualLayoutOption['projectionGroupBy'];
|
|
390
|
+
};
|
|
391
|
+
nodes: SavedViewCanvasProjectionNode[];
|
|
392
|
+
sourceNodeIds: string[];
|
|
393
|
+
omittedNodeCount: number;
|
|
394
|
+
previewCount: number;
|
|
395
|
+
};
|
|
2273
396
|
/**
|
|
2274
|
-
*
|
|
2275
|
-
*/
|
|
2276
|
-
/**
|
|
2277
|
-
* Get a human-friendly name for the platform's biometric authenticator.
|
|
2278
|
-
*/
|
|
2279
|
-
declare function getPlatformAuthName(): string;
|
|
2280
|
-
/**
|
|
2281
|
-
* Truncate a DID for display, showing first and last segments.
|
|
2282
|
-
* e.g. "did:key:z6MkhaXg...yz" → "did:key:z6Mkha...xyz"
|
|
397
|
+
* Derive a stable display column list from flattened schema query rows.
|
|
2283
398
|
*/
|
|
2284
|
-
declare function
|
|
399
|
+
declare function deriveSavedViewColumns(rows: readonly Record<string, unknown>[]): string[];
|
|
2285
400
|
/**
|
|
2286
|
-
*
|
|
2287
|
-
* Returns false in SSR environments where navigator is unavailable.
|
|
401
|
+
* Format primitive and structured cell values for read-only schema query tables.
|
|
2288
402
|
*/
|
|
2289
|
-
declare function
|
|
2290
|
-
|
|
403
|
+
declare function formatSavedViewCellValue(column: string, value: unknown): string;
|
|
2291
404
|
/**
|
|
2292
|
-
*
|
|
2293
|
-
*
|
|
2294
|
-
* Provides an optional duck-typed TelemetryReporter to the React tree.
|
|
2295
|
-
* When present, hooks report performance timing, usage counts, and errors.
|
|
2296
|
-
*
|
|
2297
|
-
* Uses the same duck-typed interface pattern as other xNet packages to
|
|
2298
|
-
* avoid circular dependencies with @xnetjs/telemetry.
|
|
405
|
+
* Compute low-cardinality facets over loaded schema query rows.
|
|
2299
406
|
*/
|
|
407
|
+
declare function deriveSavedViewFacetSummaries(rows: readonly Record<string, unknown>[], columns: readonly string[]): SavedViewFacetSummary[];
|
|
2300
408
|
/**
|
|
2301
|
-
*
|
|
2302
|
-
* Satisfied by @xnetjs/telemetry's TelemetryCollector or any compatible object.
|
|
2303
|
-
*
|
|
2304
|
-
* @example
|
|
2305
|
-
* ```ts
|
|
2306
|
-
* import { TelemetryCollector } from '@xnetjs/telemetry'
|
|
2307
|
-
* const telemetry = new TelemetryCollector({ consent })
|
|
2308
|
-
* // Pass to XNetProvider via config.telemetry
|
|
2309
|
-
* ```
|
|
409
|
+
* Filter loaded schema query rows by facet value keys.
|
|
2310
410
|
*/
|
|
2311
|
-
|
|
2312
|
-
reportPerformance(metricName: string, durationMs: number): void;
|
|
2313
|
-
reportUsage(metricName: string, count: number): void;
|
|
2314
|
-
reportCrash(error: Error, context?: Record<string, unknown>): void;
|
|
2315
|
-
}
|
|
2316
|
-
declare const TelemetryContext: react.Context<TelemetryReporter | null>;
|
|
411
|
+
declare function filterSavedViewRowsByFacets<T extends Record<string, unknown>>(rows: readonly T[], selection: SavedViewFacetSelection): T[];
|
|
2317
412
|
/**
|
|
2318
|
-
*
|
|
2319
|
-
* @internal Used by useQuery/useMutate - not part of public API.
|
|
413
|
+
* Compute date buckets over loaded schema query rows.
|
|
2320
414
|
*/
|
|
2321
|
-
declare function
|
|
2322
|
-
|
|
415
|
+
declare function deriveSavedViewDateBucketSummaries(rows: readonly Record<string, unknown>[], columns: readonly string[]): SavedViewDateBucketFieldSummary[];
|
|
2323
416
|
/**
|
|
2324
|
-
*
|
|
2325
|
-
*
|
|
2326
|
-
* Provides NodeStore and optional identity to the React tree.
|
|
2327
|
-
* All data access happens through useQuery/useMutate/useNode hooks.
|
|
417
|
+
* Filter loaded schema query rows by a selected date bucket brush.
|
|
2328
418
|
*/
|
|
2329
|
-
|
|
419
|
+
declare function filterSavedViewRowsByDateBrush<T extends Record<string, unknown>>(rows: readonly T[], selection: SavedViewDateBrushSelection): T[];
|
|
2330
420
|
/**
|
|
2331
|
-
*
|
|
421
|
+
* Build a generic row inspector model from a flattened saved-view result row.
|
|
2332
422
|
*/
|
|
2333
|
-
|
|
2334
|
-
/** Node storage adapter for NodeStore (defaults to MemoryNodeStorageAdapter) */
|
|
2335
|
-
nodeStorage?: NodeStorageAdapter;
|
|
2336
|
-
/** Author's DID for signing changes */
|
|
2337
|
-
authorDID?: DID;
|
|
2338
|
-
/** Ed25519 signing key */
|
|
2339
|
-
signingKey?: Uint8Array;
|
|
2340
|
-
/** User identity */
|
|
2341
|
-
identity?: Identity;
|
|
2342
|
-
/** Signaling server URLs for sync (default: ['ws://localhost:4444']) */
|
|
2343
|
-
signalingServers?: string[];
|
|
2344
|
-
/** Hub WebSocket URL for always-on sync (overrides signalingServers[0]) */
|
|
2345
|
-
hubUrl?: string;
|
|
2346
|
-
/** Hub integration options */
|
|
2347
|
-
hubOptions?: {
|
|
2348
|
-
/** Auto-generate UCAN for hub auth (default: true) */
|
|
2349
|
-
autoAuth?: boolean;
|
|
2350
|
-
/** Static UCAN token override for pre-authorized share sessions */
|
|
2351
|
-
authToken?: string;
|
|
2352
|
-
/** Enable auto-backup on document updates (default: false) */
|
|
2353
|
-
autoBackup?: boolean;
|
|
2354
|
-
/** Backup debounce delay in ms (default: 5000) */
|
|
2355
|
-
backupDebounceMs?: number;
|
|
2356
|
-
/** Enable search indexing on NodeStore changes (default: false) */
|
|
2357
|
-
enableSearchIndex?: boolean;
|
|
2358
|
-
/** Room name for node-change relay (defaults to author DID) */
|
|
2359
|
-
nodeSyncRoom?: string;
|
|
2360
|
-
};
|
|
2361
|
-
/** Encryption key for hub backups (XChaCha20-Poly1305) */
|
|
2362
|
-
encryptionKey?: Uint8Array;
|
|
2363
|
-
/** Disable Background Sync Manager (default: false) */
|
|
2364
|
-
disableSyncManager?: boolean;
|
|
2365
|
-
/** Provide an external SyncManager (e.g., IPC-based for Electron desktop).
|
|
2366
|
-
* When provided, the internal SyncManager creation is skipped. */
|
|
2367
|
-
syncManager?: SyncManager;
|
|
2368
|
-
/** Blob store for P2P blob sync (images, files). If provided, the SyncManager
|
|
2369
|
-
* will sync blobs alongside Y.Doc state. Typically a BlobStore from @xnetjs/storage. */
|
|
2370
|
-
blobStore?: BlobStoreForSync;
|
|
2371
|
-
/** Platform for plugin compatibility ('web' | 'electron' | 'mobile'). Defaults to 'web'. */
|
|
2372
|
-
platform?: Platform;
|
|
2373
|
-
/** Disable plugin system (default: false) */
|
|
2374
|
-
disablePlugins?: boolean;
|
|
2375
|
-
/**
|
|
2376
|
-
* Custom DataBridge instance.
|
|
2377
|
-
*
|
|
2378
|
-
* When provided, this bridge is used for data access instead of creating
|
|
2379
|
-
* a MainThreadBridge. This allows using WorkerBridge or other off-main-thread
|
|
2380
|
-
* implementations.
|
|
2381
|
-
*
|
|
2382
|
-
* The bridge must already be initialized before passing to XNetProvider.
|
|
2383
|
-
*
|
|
2384
|
-
* Note: When using a custom bridge, NodeStore is still created on the main
|
|
2385
|
-
* thread for SyncManager and other integrations. The custom bridge is used
|
|
2386
|
-
* only for React hook data access (useQuery, useMutate).
|
|
2387
|
-
*
|
|
2388
|
-
* @example
|
|
2389
|
-
* ```tsx
|
|
2390
|
-
* // Using WorkerBridge
|
|
2391
|
-
* const bridge = new WorkerBridge(workerUrl)
|
|
2392
|
-
* await bridge.initialize({ authorDID, signingKey, dbName: 'xnet' })
|
|
2393
|
-
*
|
|
2394
|
-
* <XNetProvider config={{ dataBridge: bridge, ... }}>
|
|
2395
|
-
* <App />
|
|
2396
|
-
* </XNetProvider>
|
|
2397
|
-
* ```
|
|
2398
|
-
*/
|
|
2399
|
-
dataBridge?: DataBridge;
|
|
2400
|
-
/**
|
|
2401
|
-
* Security configuration for multi-level cryptography.
|
|
2402
|
-
*/
|
|
2403
|
-
security?: {
|
|
2404
|
-
/** Default security level for new signatures (default: 0 for Ed25519-only) */
|
|
2405
|
-
level?: SecurityLevel;
|
|
2406
|
-
/** Minimum acceptable level for verification (default: 0) */
|
|
2407
|
-
minVerificationLevel?: SecurityLevel;
|
|
2408
|
-
/** Verification policy (default: 'strict') */
|
|
2409
|
-
verificationPolicy?: 'strict' | 'permissive';
|
|
2410
|
-
/** Custom PQ key registry */
|
|
2411
|
-
registry?: PQKeyRegistry;
|
|
2412
|
-
};
|
|
2413
|
-
/**
|
|
2414
|
-
* Hybrid key bundle for multi-level cryptography.
|
|
2415
|
-
*
|
|
2416
|
-
* When provided, enables signing at higher security levels (1, 2).
|
|
2417
|
-
* The bundle includes Ed25519 keys and optionally ML-DSA (post-quantum) keys.
|
|
2418
|
-
*
|
|
2419
|
-
* @example
|
|
2420
|
-
* ```tsx
|
|
2421
|
-
* const bundle = createKeyBundle({ includePQ: true })
|
|
2422
|
-
*
|
|
2423
|
-
* <XNetProvider config={{ keyBundle: bundle, ... }}>
|
|
2424
|
-
* <App />
|
|
2425
|
-
* </XNetProvider>
|
|
2426
|
-
* ```
|
|
2427
|
-
*/
|
|
2428
|
-
keyBundle?: HybridKeyBundle;
|
|
2429
|
-
/**
|
|
2430
|
-
* Optional telemetry reporter for hook instrumentation.
|
|
2431
|
-
*
|
|
2432
|
-
* When provided, useQuery and useMutate hooks will report:
|
|
2433
|
-
* - Query timing (first-load latency)
|
|
2434
|
-
* - Cache hit/miss rates
|
|
2435
|
-
* - Mutation success/failure rates
|
|
2436
|
-
* - Subscription churn (mount/unmount frequency)
|
|
2437
|
-
*
|
|
2438
|
-
* Uses a duck-typed interface to avoid circular dependencies with @xnetjs/telemetry.
|
|
2439
|
-
*
|
|
2440
|
-
* @example
|
|
2441
|
-
* ```tsx
|
|
2442
|
-
* import { TelemetryCollector, ConsentManager } from '@xnetjs/telemetry'
|
|
2443
|
-
* const consent = new ConsentManager()
|
|
2444
|
-
* const telemetry = new TelemetryCollector({ consent })
|
|
2445
|
-
*
|
|
2446
|
-
* <XNetProvider config={{ telemetry, ... }}>
|
|
2447
|
-
* <App />
|
|
2448
|
-
* </XNetProvider>
|
|
2449
|
-
* ```
|
|
2450
|
-
*/
|
|
2451
|
-
telemetry?: TelemetryReporter;
|
|
2452
|
-
}
|
|
423
|
+
declare function deriveSavedViewRowInspector(row: Record<string, unknown>, query?: SavedViewQueryResult | null): SavedViewRowInspectorModel;
|
|
2453
424
|
/**
|
|
2454
|
-
*
|
|
425
|
+
* Derive privacy class chips for the active saved-view result.
|
|
2455
426
|
*/
|
|
2456
|
-
|
|
2457
|
-
/** NodeStore for Node operations */
|
|
2458
|
-
nodeStore: NodeStore | null;
|
|
2459
|
-
/** Whether NodeStore is initialized */
|
|
2460
|
-
nodeStoreReady: boolean;
|
|
2461
|
-
/** User identity (if provided) */
|
|
2462
|
-
identity?: Identity;
|
|
2463
|
-
/** Author DID (resolved from config.authorDID or config.identity.did) */
|
|
2464
|
-
authorDID: string | null;
|
|
2465
|
-
/** Background Sync Manager (null if disabled or not yet initialized) */
|
|
2466
|
-
syncManager: SyncManager | null;
|
|
2467
|
-
/** Hub URL (if configured) */
|
|
2468
|
-
hubUrl: string | null;
|
|
2469
|
-
/** Hub connection status */
|
|
2470
|
-
hubStatus: SyncStatus;
|
|
2471
|
-
/** Hub connection (shares SyncManager connection when available) */
|
|
2472
|
-
hubConnection: ConnectionManager | null;
|
|
2473
|
-
/** Hub auth token provider (for HTTP requests) */
|
|
2474
|
-
getHubAuthToken?: () => Promise<string>;
|
|
2475
|
-
/** Encryption key for hub backups */
|
|
2476
|
-
encryptionKey: Uint8Array | null;
|
|
2477
|
-
/** Blob store for content-addressed storage (null if not configured) */
|
|
2478
|
-
blobStore: BlobStoreForSync | null;
|
|
2479
|
-
/** Plugin Registry (null if disabled or not yet initialized) */
|
|
2480
|
-
pluginRegistry: PluginRegistry | null;
|
|
2481
|
-
}
|
|
427
|
+
declare function deriveSavedViewPrivacyChips(query: SavedViewQueryResult | null): SavedViewPrivacyChip[];
|
|
2482
428
|
/**
|
|
2483
|
-
*
|
|
429
|
+
* Return a user-facing warning when loaded rows contain non-public data.
|
|
2484
430
|
*/
|
|
2485
|
-
|
|
2486
|
-
config: XNetConfig;
|
|
2487
|
-
children: ReactNode;
|
|
2488
|
-
}
|
|
431
|
+
declare function getSavedViewSensitiveResultWarning(query: SavedViewQueryResult | null): string | null;
|
|
2489
432
|
/**
|
|
2490
|
-
*
|
|
2491
|
-
*
|
|
2492
|
-
* Initializes NodeStore and provides it to the React tree.
|
|
433
|
+
* Build a persisted saved-view descriptor from the current table control state.
|
|
2493
434
|
*/
|
|
2494
|
-
declare function
|
|
435
|
+
declare function createSavedViewLensDraft(input: {
|
|
436
|
+
descriptor: SavedViewDescriptor;
|
|
437
|
+
queryId: string;
|
|
438
|
+
query: SavedViewQueryResult;
|
|
439
|
+
facetSelection: SavedViewFacetSelection;
|
|
440
|
+
dateBrushSelection: SavedViewDateBrushSelection;
|
|
441
|
+
sortField: string;
|
|
442
|
+
sortDirection: SavedViewSortDirection;
|
|
443
|
+
pageSize: number;
|
|
444
|
+
title?: string | null;
|
|
445
|
+
description?: string | null;
|
|
446
|
+
}): SavedViewLensDraft | null;
|
|
447
|
+
declare function SavedViewRunner({ descriptor, registry, title, description, fallbackId, resetKey, className, emptyLabel, pageSizes, initialPageSize, options: baseOptions, onSaveLens, saveLensLabel, onOpenVisualCanvasProjection, feedEnrichment, wrapItem }: SavedViewRunnerProps): JSX.Element;
|
|
448
|
+
declare function createSavedViewVisualCanvasProjectionRequest(input: {
|
|
449
|
+
descriptor?: SavedViewDescriptor | string | null;
|
|
450
|
+
title: string;
|
|
451
|
+
description?: string | null;
|
|
452
|
+
sourceQueryId?: string | null;
|
|
453
|
+
sourceSchemaId?: string | null;
|
|
454
|
+
layout: SavedViewVisualLayoutOption;
|
|
455
|
+
previews: readonly SavedViewVisualPreviewModel[];
|
|
456
|
+
nodes: readonly SavedViewCanvasProjectionNode[];
|
|
457
|
+
}): SavedViewVisualCanvasProjectionRequest;
|
|
458
|
+
declare function SavedViewResultTable({ query, columns, expandedRowId, onToggleRow, loadingLabel, emptyLabel, formatValue }: SavedViewResultTableProps): JSX.Element;
|
|
459
|
+
|
|
2495
460
|
/**
|
|
2496
|
-
*
|
|
461
|
+
* useCanvasTaskSync - Reconcile canvas checklist items with Task nodes.
|
|
2497
462
|
*
|
|
2498
|
-
*
|
|
463
|
+
* Canvas checklist objects are an editing projection just like page
|
|
464
|
+
* checklists: every item is backed by a canonical Task node (source:
|
|
465
|
+
* 'canvas', `canvas` relation = hosting canvas, anchorBlockId = the
|
|
466
|
+
* checklist object id). Items removed from the canvas archive their nodes;
|
|
467
|
+
* items pasted from elsewhere claim them. Semantics in
|
|
468
|
+
* docs/specs/PAGE_TASK_RECONCILIATION.md.
|
|
2499
469
|
*/
|
|
2500
|
-
|
|
470
|
+
|
|
471
|
+
type CanvasTaskInput = TaskProjectionInput;
|
|
472
|
+
interface UseCanvasTaskSyncOptions {
|
|
473
|
+
canvasId: string | null;
|
|
474
|
+
debounceMs?: number;
|
|
475
|
+
}
|
|
476
|
+
type UseCanvasTaskSyncResult = UseTaskProjectionSyncResult;
|
|
477
|
+
declare function useCanvasTaskSync({ canvasId, debounceMs }: UseCanvasTaskSyncOptions): UseCanvasTaskSyncResult;
|
|
2501
478
|
|
|
2502
479
|
/**
|
|
2503
|
-
*
|
|
480
|
+
* useGridDatabase - The V2 database hook (exploration 0159).
|
|
481
|
+
*
|
|
482
|
+
* One subscription path: fields, views, select options, and rows are all
|
|
483
|
+
* nodes read through useQuery (DataBridge → SQLite, with materialized view
|
|
484
|
+
* caching and full-text search). View nodes are the single source of truth
|
|
485
|
+
* for sort/filter/layout — there is no mirrored React state to drift.
|
|
2504
486
|
*
|
|
2505
|
-
*
|
|
2506
|
-
* -
|
|
2507
|
-
* - Verification policy configuration
|
|
2508
|
-
* - PQ key registry access
|
|
2509
|
-
* - Key bundle management
|
|
487
|
+
* Replaces the legacy useDatabase/useDatabaseDoc pair (Y.Doc columns/views,
|
|
488
|
+
* 10× over-fetch, client-side pipeline over the whole table).
|
|
2510
489
|
*/
|
|
2511
490
|
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
/** PQ key registry */
|
|
2523
|
-
registry: PQKeyRegistry;
|
|
2524
|
-
/** Current key bundle (if available) */
|
|
2525
|
-
keyBundle?: HybridKeyBundle;
|
|
491
|
+
interface GridFieldModel {
|
|
492
|
+
id: string;
|
|
493
|
+
name: string;
|
|
494
|
+
type: FieldType;
|
|
495
|
+
config: FieldConfig;
|
|
496
|
+
sortKey: string;
|
|
497
|
+
width: number;
|
|
498
|
+
isTitle?: boolean;
|
|
499
|
+
hidden?: boolean;
|
|
500
|
+
options?: GridOptionModel[];
|
|
2526
501
|
}
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
/** Set the minimum verification level */
|
|
2534
|
-
setMinVerificationLevel: (level: SecurityLevel) => void;
|
|
2535
|
-
/** Set the verification policy */
|
|
2536
|
-
setVerificationPolicy: (policy: 'strict' | 'permissive') => void;
|
|
2537
|
-
/** Update the key bundle */
|
|
2538
|
-
setKeyBundle: (bundle: HybridKeyBundle | undefined) => void;
|
|
502
|
+
interface GridOptionModel {
|
|
503
|
+
id: string;
|
|
504
|
+
field: string;
|
|
505
|
+
name: string;
|
|
506
|
+
color?: string;
|
|
507
|
+
sortKey: string;
|
|
2539
508
|
}
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
type
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
509
|
+
interface GridViewModel {
|
|
510
|
+
id: string;
|
|
511
|
+
name: string;
|
|
512
|
+
type: ViewType;
|
|
513
|
+
filters: FilterGroup | null;
|
|
514
|
+
sorts: SortConfig[];
|
|
515
|
+
groupBy: string | null;
|
|
516
|
+
collapsedGroups: string[];
|
|
517
|
+
fieldOrder: Record<string, string>;
|
|
518
|
+
fieldWidths: Record<string, number>;
|
|
519
|
+
hiddenFields: string[];
|
|
520
|
+
rowHeight: RowHeight;
|
|
521
|
+
columnSummaries: Record<string, SummaryFunction>;
|
|
522
|
+
sortKey: string;
|
|
523
|
+
}
|
|
524
|
+
interface GridRowModel {
|
|
525
|
+
id: string;
|
|
526
|
+
sortKey: string;
|
|
527
|
+
cells: Record<string, CellValue>;
|
|
528
|
+
}
|
|
529
|
+
interface UseGridDatabaseOptions {
|
|
530
|
+
/** Active view ID (defaults to the first view) */
|
|
531
|
+
viewId?: string;
|
|
532
|
+
/** Quick-find text (full-text search via SQLite FTS) */
|
|
533
|
+
search?: string;
|
|
534
|
+
/** Row window size (default 500) */
|
|
535
|
+
pageSize?: number;
|
|
536
|
+
}
|
|
537
|
+
interface UseGridDatabaseResult {
|
|
538
|
+
/** Database node (flattened) */
|
|
539
|
+
database: {
|
|
540
|
+
id: string;
|
|
541
|
+
title?: string;
|
|
542
|
+
icon?: string;
|
|
543
|
+
} | null;
|
|
544
|
+
/** All fields, database order */
|
|
545
|
+
fields: GridFieldModel[];
|
|
546
|
+
/** Fields for the active view: order overrides applied, hidden removed */
|
|
547
|
+
visibleFields: GridFieldModel[];
|
|
548
|
+
/** All views, tab order */
|
|
549
|
+
views: GridViewModel[];
|
|
550
|
+
activeView: GridViewModel | null;
|
|
551
|
+
/** Rows: view filters + sorts applied to the fetched window */
|
|
552
|
+
rows: GridRowModel[];
|
|
553
|
+
loading: boolean;
|
|
554
|
+
updateCell: (rowId: string, fieldId: string, value: CellValue) => Promise<void>;
|
|
555
|
+
clearCells: (cells: Array<{
|
|
556
|
+
rowId: string;
|
|
557
|
+
fieldId: string;
|
|
558
|
+
}>) => Promise<void>;
|
|
559
|
+
addRow: (afterRowId?: string, cells?: Record<string, CellValue>) => Promise<string | null>;
|
|
560
|
+
deleteRows: (rowIds: string[]) => Promise<void>;
|
|
561
|
+
moveRowToIndex: (rowId: string, targetIndex: number) => Promise<void>;
|
|
562
|
+
addField: (name: string, type: FieldType, config?: FieldConfig, opts?: {
|
|
563
|
+
isTitle?: boolean;
|
|
564
|
+
width?: number;
|
|
565
|
+
}) => Promise<string | null>;
|
|
566
|
+
renameField: (fieldId: string, name: string) => Promise<void>;
|
|
567
|
+
updateFieldConfig: (fieldId: string, config: FieldConfig) => Promise<void>;
|
|
568
|
+
changeFieldType: (fieldId: string, type: FieldType) => Promise<void>;
|
|
569
|
+
removeField: (fieldId: string) => Promise<void>;
|
|
570
|
+
moveFieldToIndex: (fieldId: string, targetIndex: number) => Promise<void>;
|
|
571
|
+
resizeField: (fieldId: string, width: number) => Promise<void>;
|
|
572
|
+
setFieldHidden: (fieldId: string, hidden: boolean) => Promise<void>;
|
|
573
|
+
createOption: (fieldId: string, name: string) => Promise<string | null>;
|
|
574
|
+
toggleSort: (fieldId: string) => Promise<void>;
|
|
575
|
+
setFilters: (filters: FilterGroup | null) => Promise<void>;
|
|
576
|
+
setGroupBy: (fieldId: string | null) => Promise<void>;
|
|
577
|
+
setRowHeight: (rowHeight: RowHeight) => Promise<void>;
|
|
578
|
+
setColumnSummary: (fieldId: string, fn: SummaryFunction) => Promise<void>;
|
|
579
|
+
addView: (name: string, type: ViewType) => Promise<string | null>;
|
|
580
|
+
renameView: (viewId: string, name: string) => Promise<void>;
|
|
581
|
+
removeView: (viewId: string) => Promise<void>;
|
|
582
|
+
undo: () => Promise<boolean>;
|
|
583
|
+
redo: () => Promise<boolean>;
|
|
584
|
+
canUndo: boolean;
|
|
585
|
+
canRedo: boolean;
|
|
2559
586
|
}
|
|
587
|
+
declare function useGridDatabase(databaseId: string, options?: UseGridDatabaseOptions): UseGridDatabaseResult;
|
|
588
|
+
|
|
2560
589
|
/**
|
|
2561
|
-
*
|
|
2562
|
-
*
|
|
2563
|
-
* Wraps the application with security configuration and state.
|
|
590
|
+
* useGlobalUndo - app-wide Cmd+Z (exploration 0179)
|
|
2564
591
|
*
|
|
2565
|
-
*
|
|
2566
|
-
*
|
|
2567
|
-
*
|
|
2568
|
-
*
|
|
2569
|
-
*
|
|
2570
|
-
* ```
|
|
2571
|
-
*/
|
|
2572
|
-
declare function SecurityProvider({ children, level: initialLevel, minVerificationLevel: initialMinLevel, verificationPolicy: initialPolicy, registry: providedRegistry, keyBundle: initialBundle }: SecurityProviderProps): JSX.Element;
|
|
2573
|
-
/**
|
|
2574
|
-
* Hook to access security context.
|
|
592
|
+
* Reads the single app-level UndoManager from XNetProvider context and
|
|
593
|
+
* exposes undo/redo backed by undoLatest()/redoLatest(), so one keybinding
|
|
594
|
+
* reverses the most recent action across every node-backed surface —
|
|
595
|
+
* folders, tasks, databases, chat, settings — without the caller caring
|
|
596
|
+
* which surface produced it.
|
|
2575
597
|
*
|
|
2576
|
-
*
|
|
598
|
+
* Rich-text editing (TipTap) and the canvas keep their own document-scoped
|
|
599
|
+
* undo and claim Cmd+Z while focused via the command registry's scope
|
|
600
|
+
* stack; this hook is the fallthrough for everything else.
|
|
2577
601
|
*
|
|
2578
602
|
* @example
|
|
2579
603
|
* ```tsx
|
|
2580
|
-
*
|
|
2581
|
-
*
|
|
2582
|
-
* // ...
|
|
2583
|
-
* }
|
|
604
|
+
* const { undo, redo, canUndo, canRedo } = useGlobalUndo()
|
|
605
|
+
* registry.register({ id: 'edit.undo', key: 'Mod-Z', run: () => void undo() })
|
|
2584
606
|
* ```
|
|
2585
607
|
*/
|
|
2586
|
-
|
|
2587
|
-
/**
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
*/
|
|
2592
|
-
|
|
608
|
+
interface UseGlobalUndoResult {
|
|
609
|
+
/** Reverse the most recent local action across all node-backed surfaces */
|
|
610
|
+
undo: () => Promise<boolean>;
|
|
611
|
+
/** Re-apply the most recently undone action */
|
|
612
|
+
redo: () => Promise<boolean>;
|
|
613
|
+
/** Whether anything is undoable right now */
|
|
614
|
+
canUndo: boolean;
|
|
615
|
+
/** Whether anything is redoable right now */
|
|
616
|
+
canRedo: boolean;
|
|
617
|
+
}
|
|
618
|
+
declare function useGlobalUndo(): UseGlobalUndoResult;
|
|
2593
619
|
|
|
2594
620
|
/**
|
|
2595
|
-
*
|
|
621
|
+
* useBilling — reactive billing state + checkout, the same shape as `useIdentity`.
|
|
622
|
+
*
|
|
623
|
+
* Reads the caller's own DID-scoped billing from the hub (`GET /billing/me`) and
|
|
624
|
+
* exposes `openCheckout` / `openPortal`, which call the hub (secret key stays
|
|
625
|
+
* server-side) and redirect to the returned hosted URL. The client needs no
|
|
626
|
+
* Stripe secret — only the hub URL it already has. See exploration 0187.
|
|
2596
627
|
*
|
|
2597
|
-
*
|
|
2598
|
-
*
|
|
628
|
+
* Types come from `@xnetjs/billing` as a type-only import, so nothing pulls
|
|
629
|
+
* `node:crypto`/the provider adapters into the browser bundle.
|
|
2599
630
|
*/
|
|
2600
631
|
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
632
|
+
interface CheckoutOptions {
|
|
633
|
+
/** `subscription` (default) for recurring, `payment` for one-shot (e.g. Bitcoin). */
|
|
634
|
+
mode?: 'subscription' | 'payment';
|
|
635
|
+
successUrl?: string;
|
|
636
|
+
cancelUrl?: string;
|
|
637
|
+
customerEmail?: string;
|
|
2607
638
|
}
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
/**
|
|
2623
|
-
|
|
2624
|
-
/**
|
|
2625
|
-
|
|
2626
|
-
/**
|
|
2627
|
-
|
|
639
|
+
interface UseBillingResult {
|
|
640
|
+
/** The most relevant subscription (active/trialing first), or null. */
|
|
641
|
+
subscription: Subscription | null;
|
|
642
|
+
/** True when the subscription is active or trialing. */
|
|
643
|
+
isActive: boolean;
|
|
644
|
+
/** The active subscription's price/plan ref, or null. */
|
|
645
|
+
plan: string | null;
|
|
646
|
+
status: Subscription['status'] | null;
|
|
647
|
+
customer: Customer | null;
|
|
648
|
+
subscriptions: Subscription[];
|
|
649
|
+
invoices: Invoice[];
|
|
650
|
+
payments: Payment[];
|
|
651
|
+
loading: boolean;
|
|
652
|
+
error: Error | null;
|
|
653
|
+
/** Re-fetch billing state from the hub. */
|
|
654
|
+
reload: () => Promise<void>;
|
|
655
|
+
/** Start hosted checkout for a price/plan and redirect to it. */
|
|
656
|
+
openCheckout: (priceRef: string, options?: CheckoutOptions) => Promise<void>;
|
|
657
|
+
/** Open the provider's customer portal (Stripe) and redirect to it. */
|
|
658
|
+
openPortal: (returnUrl?: string) => Promise<void>;
|
|
659
|
+
/** Stripe publishable key, if configured (for future embedded checkout). */
|
|
660
|
+
publishableKey: string | null;
|
|
2628
661
|
}
|
|
2629
|
-
|
|
2630
|
-
* Hook for security-aware operations.
|
|
2631
|
-
*
|
|
2632
|
-
* Provides signing and verification functions that use the current
|
|
2633
|
-
* security level from the SecurityContext.
|
|
2634
|
-
*
|
|
2635
|
-
* @example
|
|
2636
|
-
* ```tsx
|
|
2637
|
-
* function SignedMessage() {
|
|
2638
|
-
* const { sign, verify, level, hasPQKeys } = useSecurity()
|
|
2639
|
-
*
|
|
2640
|
-
* const handleSign = async () => {
|
|
2641
|
-
* const data = new TextEncoder().encode('Hello')
|
|
2642
|
-
* const sig = sign(data)
|
|
2643
|
-
* console.log(`Signed at Level ${sig.level}`)
|
|
2644
|
-
* }
|
|
2645
|
-
*
|
|
2646
|
-
* return (
|
|
2647
|
-
* <div>
|
|
2648
|
-
* <p>Security Level: {level}</p>
|
|
2649
|
-
* <p>PQ Keys: {hasPQKeys ? 'Yes' : 'No'}</p>
|
|
2650
|
-
* <button onClick={handleSign}>Sign</button>
|
|
2651
|
-
* </div>
|
|
2652
|
-
* )
|
|
2653
|
-
* }
|
|
2654
|
-
* ```
|
|
2655
|
-
*
|
|
2656
|
-
* @example Per-operation level override
|
|
2657
|
-
* ```tsx
|
|
2658
|
-
* function HighSecurityOperation() {
|
|
2659
|
-
* const { sign } = useSecurity({ level: 2 }) // Force Level 2
|
|
2660
|
-
*
|
|
2661
|
-
* const handleCritical = () => {
|
|
2662
|
-
* const data = new TextEncoder().encode('Critical operation')
|
|
2663
|
-
* const sig = sign(data) // Signs at Level 2
|
|
2664
|
-
* console.log(sig.level) // 2
|
|
2665
|
-
* }
|
|
2666
|
-
*
|
|
2667
|
-
* return <button onClick={handleCritical}>Critical Action</button>
|
|
2668
|
-
* }
|
|
2669
|
-
* ```
|
|
2670
|
-
*
|
|
2671
|
-
* @example Fast mode for high-frequency operations
|
|
2672
|
-
* ```tsx
|
|
2673
|
-
* function CursorUpdates() {
|
|
2674
|
-
* const { sign } = useSecurity({ level: 0 }) // Fast Ed25519-only
|
|
2675
|
-
*
|
|
2676
|
-
* const handleCursor = (position: number) => {
|
|
2677
|
-
* const data = new TextEncoder().encode(JSON.stringify({ position }))
|
|
2678
|
-
* const sig = sign(data) // Fast signing
|
|
2679
|
-
* }
|
|
2680
|
-
*
|
|
2681
|
-
* return <canvas onMouseMove={(e) => handleCursor(e.clientX)} />
|
|
2682
|
-
* }
|
|
2683
|
-
* ```
|
|
2684
|
-
*/
|
|
2685
|
-
declare function useSecurity(options?: UseSecurityOptions): UseSecurityResult;
|
|
662
|
+
declare function useBilling(): UseBillingResult;
|
|
2686
663
|
|
|
2687
664
|
/**
|
|
2688
|
-
*
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
* Access the PluginRegistry instance
|
|
2693
|
-
*
|
|
2694
|
-
* @example
|
|
2695
|
-
* ```tsx
|
|
2696
|
-
* const registry = usePluginRegistry()
|
|
2697
|
-
* const plugins = registry.getAll()
|
|
2698
|
-
* ```
|
|
2699
|
-
*
|
|
2700
|
-
* @throws Error if used outside of XNetProvider with plugins enabled
|
|
2701
|
-
*/
|
|
2702
|
-
declare function usePluginRegistry(): PluginRegistry;
|
|
2703
|
-
/**
|
|
2704
|
-
* Safely access the PluginRegistry instance, returns null if not available
|
|
2705
|
-
*
|
|
2706
|
-
* Use this when you need to optionally access the plugin system without throwing.
|
|
2707
|
-
*/
|
|
2708
|
-
declare function usePluginRegistryOptional(): PluginRegistry | null;
|
|
2709
|
-
/**
|
|
2710
|
-
* Get all registered plugins with reactive updates
|
|
2711
|
-
*
|
|
2712
|
-
* @example
|
|
2713
|
-
* ```tsx
|
|
2714
|
-
* const plugins = usePlugins()
|
|
2715
|
-
* // Re-renders when plugins change
|
|
2716
|
-
* ```
|
|
2717
|
-
*/
|
|
2718
|
-
declare function usePlugins(): RegisteredPlugin[];
|
|
2719
|
-
/**
|
|
2720
|
-
* Contribution type to interface mapping
|
|
665
|
+
* @xnetjs/react - Pure helpers for rendering a page's task tree as a
|
|
666
|
+
* flat list of rows. Shared by the in-page task panel and host apps
|
|
667
|
+
* that render page tasks in their own chrome (e.g. the web context
|
|
668
|
+
* panel).
|
|
2721
669
|
*/
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
settings: SettingContribution;
|
|
670
|
+
|
|
671
|
+
type RenderableTaskRow = {
|
|
672
|
+
id: string;
|
|
673
|
+
title: string;
|
|
674
|
+
completed: boolean;
|
|
675
|
+
dueDate: number | undefined;
|
|
676
|
+
depth: number;
|
|
677
|
+
assigneeCount: number;
|
|
2731
678
|
};
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
* @example
|
|
2736
|
-
* ```tsx
|
|
2737
|
-
* // Get all registered views
|
|
2738
|
-
* const views = useContributions('views')
|
|
2739
|
-
*
|
|
2740
|
-
* // Get all commands
|
|
2741
|
-
* const commands = useContributions('commands')
|
|
2742
|
-
* ```
|
|
2743
|
-
*/
|
|
2744
|
-
declare function useContributions<K extends keyof ContributionTypeMap>(type: K): ContributionTypeMap[K][];
|
|
2745
|
-
/**
|
|
2746
|
-
* Get all registered views
|
|
2747
|
-
*/
|
|
2748
|
-
declare function useViews(): ViewContribution[];
|
|
2749
|
-
/**
|
|
2750
|
-
* Get all registered commands
|
|
2751
|
-
*/
|
|
2752
|
-
declare function useCommands(): CommandContribution[];
|
|
2753
|
-
/**
|
|
2754
|
-
* Get all registered slash commands
|
|
2755
|
-
*/
|
|
2756
|
-
declare function useSlashCommands(): SlashCommandContribution[];
|
|
2757
|
-
/**
|
|
2758
|
-
* Get all registered sidebar items
|
|
2759
|
-
*/
|
|
2760
|
-
declare function useSidebarItems(): SidebarContribution[];
|
|
2761
|
-
/**
|
|
2762
|
-
* Get all registered editor extensions
|
|
2763
|
-
*
|
|
2764
|
-
* @throws Error if plugin system is not enabled
|
|
2765
|
-
*/
|
|
2766
|
-
declare function useEditorExtensions(): EditorContribution[];
|
|
2767
|
-
/**
|
|
2768
|
-
* Get all registered editor extensions, returns empty array if plugin system is not available
|
|
2769
|
-
*
|
|
2770
|
-
* Safe version that doesn't throw if plugins aren't enabled.
|
|
2771
|
-
*/
|
|
2772
|
-
declare function useEditorExtensionsSafe(): EditorContribution[];
|
|
2773
|
-
/**
|
|
2774
|
-
* Get a specific view by type
|
|
2775
|
-
*/
|
|
2776
|
-
declare function useView(type: string): ViewContribution | undefined;
|
|
2777
|
-
/**
|
|
2778
|
-
* Get a specific command by ID
|
|
2779
|
-
*/
|
|
2780
|
-
declare function useCommand(id: string): CommandContribution | undefined;
|
|
679
|
+
declare function flattenTaskTree(items: TaskTreeItem[], depth?: number): RenderableTaskRow[];
|
|
680
|
+
declare function formatTaskDueDate(timestamp: number | undefined): string | null;
|
|
681
|
+
declare function isTaskOverdue(timestamp: number | undefined, completed: boolean): boolean;
|
|
2781
682
|
|
|
2782
|
-
export { type
|
|
683
|
+
export { type CanvasTaskInput, type CheckoutOptions, FlatNode, type GridFieldModel, type GridOptionModel, type GridRowModel, type GridViewModel, QueryFilter, type RenderableTaskRow, type SavedViewCanvasProjectionNode, type SavedViewDateBrushSelection, type SavedViewDateBucketFieldSummary, type SavedViewDateBucketInterval, type SavedViewDateBucketSummary, type SavedViewFacetSelection, type SavedViewFacetSummary, type SavedViewFacetValueSummary, type SavedViewFeedEnrichmentAdapter, type SavedViewFeedEnrichmentEntry, type SavedViewInspectorItem, type SavedViewInspectorItemKind, type SavedViewLensDraft, type SavedViewPresentationMode, type SavedViewPrivacyChip, type SavedViewPrivacyChipTone, type SavedViewPrivacySummary, type SavedViewQueryOverride, type SavedViewQueryResult, SavedViewResultTable, type SavedViewResultTableProps, type SavedViewRowInspectorModel, SavedViewRunner, type SavedViewRunnerProps, type SavedViewSchemaRegistry, type SavedViewSortDirection, type SavedViewVisualCanvasProjectionRequest, SavedViewVisualFeed, type SavedViewVisualLayoutId, type SavedViewVisualLayoutOption, type SavedViewVisualPreviewCreator, type SavedViewVisualPreviewKind, type SavedViewVisualPreviewModel, type SavedViewVisualPreviewPrivacy, type SavedViewVisualPreviewRelationship, type SavedViewVisualTimelineBucket, type SavedViewVisualWorkspaceLayout, TaskProjectionInput, TaskTreeItem, type UseBillingResult, type UseCanvasTaskSyncOptions, type UseCanvasTaskSyncResult, type UseEffectiveSchemaResult, type UseGlobalUndoResult, type UseGridDatabaseOptions, type UseGridDatabaseResult, type UseSavedViewOptions, type UseSavedViewResult, UseTaskProjectionSyncResult, createSavedViewCanvasProjectionNodes, createSavedViewLensDraft, createSavedViewVisualCanvasProjectionRequest, createSavedViewVisualPreviewFingerprint, deriveCachedSavedViewVisualPreviews, deriveSavedViewColumns, deriveSavedViewDateBucketSummaries, deriveSavedViewFacetSummaries, deriveSavedViewPrivacyChips, deriveSavedViewRowInspector, deriveSavedViewTimelineBuckets, deriveSavedViewVisualPreview, deriveSavedViewVisualPreviews, filterSavedViewRowsByDateBrush, filterSavedViewRowsByFacets, flattenTaskTree, formatSavedViewCellValue, formatTaskDueDate, getSavedViewSensitiveResultWarning, hasSavedViewVisualPreviewSensitiveData, isSavedViewVisualPreviewEmbeddable, isTaskOverdue, mergeSavedViewFeedEnrichment, savedViewVisualPreviewIsSelfActor, useBilling, useCanvasTaskSync, useEffectiveSchema, useGlobalUndo, useGridDatabase, useSavedView };
|