@feltdb/core 0.4.3 → 0.4.5
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 +13 -0
- package/dist/migrate/analyzer/index.d.ts +2 -0
- package/dist/migrate/analyzer/index.js +34 -0
- package/dist/migrate/benchmark/index.d.ts +13 -0
- package/dist/migrate/benchmark/index.js +8 -0
- package/dist/migrate/capability-gate/index.d.ts +3 -0
- package/dist/migrate/capability-gate/index.js +3 -0
- package/dist/migrate/classifier/index.d.ts +3 -0
- package/dist/migrate/classifier/index.js +53 -0
- package/dist/migrate/cli/index.d.ts +2 -0
- package/dist/migrate/cli/index.js +201 -0
- package/dist/migrate/domain-model/index.d.ts +2 -0
- package/dist/migrate/domain-model/index.js +4 -0
- package/dist/migrate/generator/index.d.ts +2 -0
- package/dist/migrate/generator/index.js +21 -0
- package/dist/migrate/index.d.ts +16 -0
- package/dist/migrate/index.js +16 -0
- package/dist/migrate/measurement/index.d.ts +7 -0
- package/dist/migrate/measurement/index.js +1 -0
- package/dist/migrate/migrator/index.d.ts +2 -0
- package/dist/migrate/migrator/index.js +35 -0
- package/dist/migrate/planner/index.d.ts +2 -0
- package/dist/migrate/planner/index.js +12 -0
- package/dist/migrate/prover/index.d.ts +9 -0
- package/dist/migrate/prover/index.js +3 -0
- package/dist/migrate/reporter/index.d.ts +4 -0
- package/dist/migrate/reporter/index.js +1 -0
- package/dist/migrate/runtime-dependencies/index.d.ts +13 -0
- package/dist/migrate/runtime-dependencies/index.js +112 -0
- package/dist/migrate/state-contract/index.d.ts +13 -0
- package/dist/migrate/state-contract/index.js +49 -0
- package/dist/migrate/types/index.d.ts +228 -0
- package/dist/migrate/types/index.js +1 -0
- package/dist/migrate/ui-wiring/index.d.ts +18 -0
- package/dist/migrate/ui-wiring/index.js +2 -0
- package/dist/migrate/util.d.ts +5 -0
- package/dist/migrate/util.js +10 -0
- package/dist/react/index.d.ts +7 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +6 -0
- package/dist/react/useCapability.d.ts +11 -0
- package/dist/react/useCapability.d.ts.map +1 -0
- package/dist/react/useCapability.js +30 -0
- package/dist/react/useCollection.d.ts +17 -0
- package/dist/react/useCollection.d.ts.map +1 -0
- package/dist/react/useCollection.js +69 -0
- package/dist/react/useFeltDB.d.ts +136 -0
- package/dist/react/useFeltDB.d.ts.map +1 -0
- package/dist/react/useFeltDB.js +350 -0
- package/dist/studio/.gitkeep +1 -0
- package/dist/studio/KeyManagementPanel-BOvWTRyH.js +246 -0
- package/dist/studio/app.d.ts +10 -0
- package/dist/studio/app.d.ts.map +1 -0
- package/dist/studio/components/AgentExplorer.d.ts +9 -0
- package/dist/studio/components/AgentExplorer.d.ts.map +1 -0
- package/dist/studio/components/ApplicationDesigner.d.ts +11 -0
- package/dist/studio/components/ApplicationDesigner.d.ts.map +1 -0
- package/dist/studio/components/CapabilityExplorer.d.ts +9 -0
- package/dist/studio/components/CapabilityExplorer.d.ts.map +1 -0
- package/dist/studio/components/ConflictExplorer.d.ts +9 -0
- package/dist/studio/components/ConflictExplorer.d.ts.map +1 -0
- package/dist/studio/components/ExecutionViewer.d.ts +9 -0
- package/dist/studio/components/ExecutionViewer.d.ts.map +1 -0
- package/dist/studio/components/GlobalSearch.d.ts +10 -0
- package/dist/studio/components/GlobalSearch.d.ts.map +1 -0
- package/dist/studio/components/HealthCenter.d.ts +9 -0
- package/dist/studio/components/HealthCenter.d.ts.map +1 -0
- package/dist/studio/components/KeyManagementPanel.d.ts +9 -0
- package/dist/studio/components/KeyManagementPanel.d.ts.map +1 -0
- package/dist/studio/components/KeyManagementPanel.js +2 -0
- package/dist/studio/components/ManagedInstancePanel.d.ts +4 -0
- package/dist/studio/components/ManagedInstancePanel.d.ts.map +1 -0
- package/dist/studio/components/ManagedInstancePanel.js +281 -0
- package/dist/studio/components/OperationsExplorer.d.ts +10 -0
- package/dist/studio/components/OperationsExplorer.d.ts.map +1 -0
- package/dist/studio/components/OverviewDashboard.d.ts +8 -0
- package/dist/studio/components/OverviewDashboard.d.ts.map +1 -0
- package/dist/studio/components/PeerMap.d.ts +8 -0
- package/dist/studio/components/PeerMap.d.ts.map +1 -0
- package/dist/studio/components/ProvenanceViewer.d.ts +11 -0
- package/dist/studio/components/ProvenanceViewer.d.ts.map +1 -0
- package/dist/studio/components/ReferenceExplorer.d.ts +10 -0
- package/dist/studio/components/ReferenceExplorer.d.ts.map +1 -0
- package/dist/studio/components/SettingsPanel.d.ts +7 -0
- package/dist/studio/components/SettingsPanel.d.ts.map +1 -0
- package/dist/studio/components/StateExplorer.d.ts +10 -0
- package/dist/studio/components/StateExplorer.d.ts.map +1 -0
- package/dist/studio/components/WorkflowVisualizer.d.ts +9 -0
- package/dist/studio/components/WorkflowVisualizer.d.ts.map +1 -0
- package/dist/studio/components/index.d.ts +24 -0
- package/dist/studio/components/index.d.ts.map +1 -0
- package/dist/studio/components/index.js +4 -0
- package/dist/studio/components-BRYUceo9.js +1711 -0
- package/dist/studio/hooks/index.d.ts +37 -0
- package/dist/studio/hooks/index.d.ts.map +1 -0
- package/dist/studio/index.d.ts +27 -0
- package/dist/studio/index.d.ts.map +1 -0
- package/dist/studio/index.html +30 -0
- package/dist/studio/index.js +236 -0
- package/dist/studio/main.d.ts +1 -0
- package/dist/studio/main.d.ts.map +1 -0
- package/dist/studio/studio.css +2 -0
- package/dist/studio/types/index.d.ts +133 -0
- package/dist/studio/types/index.d.ts.map +1 -0
- package/dist/studio/utils/api.d.ts +27 -0
- package/dist/studio/utils/api.d.ts.map +1 -0
- package/dist/studio/utils/format.d.ts +24 -0
- package/dist/studio/utils/format.d.ts.map +1 -0
- package/dist/studio/utils/index.d.ts +7 -0
- package/dist/studio/utils/index.d.ts.map +1 -0
- package/dist/studio/utils/index.js +75 -0
- package/dist/studio/utils/managed-instance.d.ts +40 -0
- package/dist/studio/utils/managed-instance.d.ts.map +1 -0
- package/dist/studio/utils/managed-instance.js +51 -0
- package/dist/studio-app/.gitkeep +1 -0
- package/dist/studio-app/assets/feltdb_wasm-BXMn9UxO.js +1 -0
- package/dist/studio-app/assets/feltdb_wasm_bg-bYYbZeRM.wasm +0 -0
- package/dist/studio-app/assets/index-B-lZjdtI.js +28 -0
- package/dist/studio-app/assets/index-CB-Eed9V.css +1 -0
- package/dist/studio-app/index.html +3 -0
- package/package.json +33 -4
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useFeltDB - React hook for FeltDB integration
|
|
3
|
+
*
|
|
4
|
+
* This module provides React hooks for easily integrating FeltDB
|
|
5
|
+
* into React applications with automatic state management.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```jsx
|
|
9
|
+
* import { useFeltDB } from './hooks/useFeltDB';
|
|
10
|
+
*
|
|
11
|
+
* function UserList() {
|
|
12
|
+
* const users = useFeltDB("users");
|
|
13
|
+
*
|
|
14
|
+
* const addUser = (name, email) => {
|
|
15
|
+
* users.insert(name, email);
|
|
16
|
+
* };
|
|
17
|
+
*
|
|
18
|
+
* return (
|
|
19
|
+
* <div>
|
|
20
|
+
* {users.records.map(user => (
|
|
21
|
+
* <div key={user.id}>{user.name}</div>
|
|
22
|
+
* ))}
|
|
23
|
+
* </div>
|
|
24
|
+
* );
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
import type { JsDb } from '@feltdb/wasm';
|
|
29
|
+
import type { Collection } from '@feltdb/core';
|
|
30
|
+
interface UseFeltDBOptions {
|
|
31
|
+
/** Auto-refresh interval in milliseconds (0 to disable) */
|
|
32
|
+
refreshInterval?: number;
|
|
33
|
+
/** Callback when data updates */
|
|
34
|
+
onUpdate?: (records: any[]) => void;
|
|
35
|
+
/** Callback when error occurs */
|
|
36
|
+
onError?: (error: string) => void;
|
|
37
|
+
}
|
|
38
|
+
interface UseFeltDBResult<T = any> {
|
|
39
|
+
/** Array of records from the database */
|
|
40
|
+
records: T[];
|
|
41
|
+
/** Whether data is loading */
|
|
42
|
+
loading: boolean;
|
|
43
|
+
/** Error message if any */
|
|
44
|
+
error: string | null;
|
|
45
|
+
/** Insert a new record */
|
|
46
|
+
insert: (key: string, data: Record<string, any>) => boolean;
|
|
47
|
+
/** Get a single record by key */
|
|
48
|
+
get: (key: string) => any | null;
|
|
49
|
+
/** Refresh data manually */
|
|
50
|
+
refresh: () => void;
|
|
51
|
+
/** Update a record */
|
|
52
|
+
update: (id: string | number, changes: Partial<T>) => Promise<void>;
|
|
53
|
+
/** Delete a record */
|
|
54
|
+
delete: (id: string | number) => Promise<void>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* React hook for FeltDB state-first collections
|
|
58
|
+
*
|
|
59
|
+
* This is a thin adapter that bridges React state management with FeltDB's
|
|
60
|
+
* unified state model. All applications (React, Vue, Svelte) use the same
|
|
61
|
+
* underlying Collection semantics.
|
|
62
|
+
*
|
|
63
|
+
* @param collection A FeltDB Collection (live application state)
|
|
64
|
+
* @param options Configuration options
|
|
65
|
+
* @returns UseFeltDBResult with records and helper methods
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```jsx
|
|
69
|
+
* import { useFeltDB } from 'feltdb/useFeltDB';
|
|
70
|
+
*
|
|
71
|
+
* function UserList({ collection }) {
|
|
72
|
+
* const { records, loading, error, insert, update } = useFeltDB(collection);
|
|
73
|
+
*
|
|
74
|
+
* if (loading) return <div>Loading...</div>;
|
|
75
|
+
* if (error) return <div>Error: {error}</div>;
|
|
76
|
+
*
|
|
77
|
+
* return (
|
|
78
|
+
* <div>
|
|
79
|
+
* {records.map((user) => (
|
|
80
|
+
* <div key={user.id}>{user.name}</div>
|
|
81
|
+
* ))}
|
|
82
|
+
* </div>
|
|
83
|
+
* );
|
|
84
|
+
* }
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export declare function useFeltDB<T = any>(collection: Collection<T> | null, options?: UseFeltDBOptions): UseFeltDBResult<T>;
|
|
88
|
+
/**
|
|
89
|
+
* Legacy compatibility: React hook for FeltDB capability queries
|
|
90
|
+
* Uses the low-level JsDb API for backward compatibility.
|
|
91
|
+
*
|
|
92
|
+
* New code should use useFeltDB with Collections instead.
|
|
93
|
+
*/
|
|
94
|
+
export declare function useLegacyFeltDB(db: JsDb | null, capability: string, options?: UseFeltDBOptions): UseFeltDBResult;
|
|
95
|
+
/**
|
|
96
|
+
* Higher-order component for wrapping components with FeltDB
|
|
97
|
+
*
|
|
98
|
+
* @param Component React component that receives db and useFeltDB hook
|
|
99
|
+
* @param dbPath Path to the database file
|
|
100
|
+
* @returns Wrapped component
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```jsx
|
|
104
|
+
* const UserListWithDb = withFeltDB(UserList, "app.db");
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
export declare function withFeltDB<P extends object>(Component: React.ComponentType<P & {
|
|
108
|
+
db: JsDb;
|
|
109
|
+
}>, dbPath: string): React.FC<P>;
|
|
110
|
+
/**
|
|
111
|
+
* Example component using useFeltDB
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```jsx
|
|
115
|
+
* import { useFeltDB } from './hooks/useFeltDB';
|
|
116
|
+
*
|
|
117
|
+
* function UserList({ db }) {
|
|
118
|
+
* const { records, loading, error, insert } = useFeltDB(db, "users", {
|
|
119
|
+
* refreshInterval: 5000, // Refresh every 5 seconds
|
|
120
|
+
* });
|
|
121
|
+
*
|
|
122
|
+
* if (loading) return <div>Loading...</div>;
|
|
123
|
+
* if (error) return <div>Error: {error}</div>;
|
|
124
|
+
*
|
|
125
|
+
* return (
|
|
126
|
+
* <div>
|
|
127
|
+
* {records.map((user: any) => (
|
|
128
|
+
* <div key={user.id}>{user.name} ({user.email})</div>
|
|
129
|
+
* ))}
|
|
130
|
+
* </div>
|
|
131
|
+
* );
|
|
132
|
+
* }
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
export default useFeltDB;
|
|
136
|
+
//# sourceMappingURL=useFeltDB.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFeltDB.d.ts","sourceRoot":"","sources":["../src/useFeltDB.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,UAAU,gBAAgB;IACxB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iCAAiC;IACjC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IACpC,iCAAiC;IACjC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,UAAU,eAAe,CAAC,CAAC,GAAG,GAAG;IAC/B,yCAAyC;IACzC,OAAO,EAAE,CAAC,EAAE,CAAC;IACb,8BAA8B;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,2BAA2B;IAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,0BAA0B;IAC1B,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC;IAC5D,iCAAiC;IACjC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,GAAG,GAAG,IAAI,CAAC;IACjC,4BAA4B;IAC5B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,sBAAsB;IACtB,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,sBAAsB;IACtB,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,SAAS,CAAC,CAAC,GAAG,GAAG,EAC/B,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,EAChC,OAAO,GAAE,gBAAqB,GAC7B,eAAe,CAAC,CAAC,CAAC,CAiJpB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,IAAI,GAAG,IAAI,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,gBAAqB,GAC7B,eAAe,CA8GjB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EACzC,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,CAAC,EAChD,MAAM,EAAE,MAAM,GACb,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CA4Bb;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAe,SAAS,CAAC"}
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* useFeltDB - React hook for FeltDB integration
|
|
4
|
+
*
|
|
5
|
+
* This module provides React hooks for easily integrating FeltDB
|
|
6
|
+
* into React applications with automatic state management.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* ```jsx
|
|
10
|
+
* import { useFeltDB } from './hooks/useFeltDB';
|
|
11
|
+
*
|
|
12
|
+
* function UserList() {
|
|
13
|
+
* const users = useFeltDB("users");
|
|
14
|
+
*
|
|
15
|
+
* const addUser = (name, email) => {
|
|
16
|
+
* users.insert(name, email);
|
|
17
|
+
* };
|
|
18
|
+
*
|
|
19
|
+
* return (
|
|
20
|
+
* <div>
|
|
21
|
+
* {users.records.map(user => (
|
|
22
|
+
* <div key={user.id}>{user.name}</div>
|
|
23
|
+
* ))}
|
|
24
|
+
* </div>
|
|
25
|
+
* );
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
30
|
+
/**
|
|
31
|
+
* React hook for FeltDB state-first collections
|
|
32
|
+
*
|
|
33
|
+
* This is a thin adapter that bridges React state management with FeltDB's
|
|
34
|
+
* unified state model. All applications (React, Vue, Svelte) use the same
|
|
35
|
+
* underlying Collection semantics.
|
|
36
|
+
*
|
|
37
|
+
* @param collection A FeltDB Collection (live application state)
|
|
38
|
+
* @param options Configuration options
|
|
39
|
+
* @returns UseFeltDBResult with records and helper methods
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```jsx
|
|
43
|
+
* import { useFeltDB } from 'feltdb/useFeltDB';
|
|
44
|
+
*
|
|
45
|
+
* function UserList({ collection }) {
|
|
46
|
+
* const { records, loading, error, insert, update } = useFeltDB(collection);
|
|
47
|
+
*
|
|
48
|
+
* if (loading) return <div>Loading...</div>;
|
|
49
|
+
* if (error) return <div>Error: {error}</div>;
|
|
50
|
+
*
|
|
51
|
+
* return (
|
|
52
|
+
* <div>
|
|
53
|
+
* {records.map((user) => (
|
|
54
|
+
* <div key={user.id}>{user.name}</div>
|
|
55
|
+
* ))}
|
|
56
|
+
* </div>
|
|
57
|
+
* );
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export function useFeltDB(collection, options = {}) {
|
|
62
|
+
const [records, setRecords] = useState([]);
|
|
63
|
+
const [loading, setLoading] = useState(true);
|
|
64
|
+
const [error, setError] = useState(null);
|
|
65
|
+
const unsubscribeRef = useRef(null);
|
|
66
|
+
// Subscribe to collection updates
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
if (!collection) {
|
|
69
|
+
setLoading(false);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
let isMounted = true;
|
|
73
|
+
const subscribe = async () => {
|
|
74
|
+
try {
|
|
75
|
+
setLoading(true);
|
|
76
|
+
// Initial load
|
|
77
|
+
const data = await collection.all();
|
|
78
|
+
if (isMounted) {
|
|
79
|
+
setRecords(data);
|
|
80
|
+
setError(null);
|
|
81
|
+
options.onUpdate?.(data);
|
|
82
|
+
}
|
|
83
|
+
// Subscribe to live updates
|
|
84
|
+
const unsubscribe = collection.subscribe((updatedData) => {
|
|
85
|
+
if (isMounted) {
|
|
86
|
+
setRecords(updatedData);
|
|
87
|
+
setError(null);
|
|
88
|
+
options.onUpdate?.(updatedData);
|
|
89
|
+
}
|
|
90
|
+
}, options.refreshInterval);
|
|
91
|
+
unsubscribeRef.current = unsubscribe;
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
const errorMsg = err instanceof Error ? err.message : "Failed to load collection";
|
|
95
|
+
if (isMounted) {
|
|
96
|
+
setError(errorMsg);
|
|
97
|
+
options.onError?.(errorMsg);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
if (isMounted) {
|
|
102
|
+
setLoading(false);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
subscribe();
|
|
107
|
+
// Cleanup
|
|
108
|
+
return () => {
|
|
109
|
+
isMounted = false;
|
|
110
|
+
if (unsubscribeRef.current) {
|
|
111
|
+
unsubscribeRef.current();
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}, [collection, options]);
|
|
115
|
+
// Insert a new record
|
|
116
|
+
const insert = useCallback((key, data) => {
|
|
117
|
+
if (!collection) {
|
|
118
|
+
setError("Collection not initialized");
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
const [, id] = key.split(':');
|
|
123
|
+
collection.insert(data, id);
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
const errorMsg = err instanceof Error ? err.message : "Insert failed";
|
|
128
|
+
setError(errorMsg);
|
|
129
|
+
options.onError?.(errorMsg);
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
}, [collection, options]);
|
|
133
|
+
// Get a single record
|
|
134
|
+
const get = useCallback((key) => {
|
|
135
|
+
if (!collection) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
const [, id] = key.split(':');
|
|
140
|
+
// This would need to be async in a real implementation
|
|
141
|
+
// For now, return null since we can't await in a sync callback
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
}, [collection]);
|
|
148
|
+
// Update a record
|
|
149
|
+
const update = useCallback(async (id, changes) => {
|
|
150
|
+
if (!collection) {
|
|
151
|
+
throw new Error("Collection not initialized");
|
|
152
|
+
}
|
|
153
|
+
await collection.update(id, changes);
|
|
154
|
+
}, [collection]);
|
|
155
|
+
// Delete a record
|
|
156
|
+
const deleteRecord = useCallback(async (id) => {
|
|
157
|
+
if (!collection) {
|
|
158
|
+
throw new Error("Collection not initialized");
|
|
159
|
+
}
|
|
160
|
+
await collection.delete(id);
|
|
161
|
+
}, [collection]);
|
|
162
|
+
// Manual refresh
|
|
163
|
+
const refresh = useCallback(async () => {
|
|
164
|
+
if (!collection) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
await collection.refresh();
|
|
168
|
+
}, [collection]);
|
|
169
|
+
return {
|
|
170
|
+
records,
|
|
171
|
+
loading,
|
|
172
|
+
error,
|
|
173
|
+
insert,
|
|
174
|
+
get,
|
|
175
|
+
refresh,
|
|
176
|
+
update,
|
|
177
|
+
delete: deleteRecord,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Legacy compatibility: React hook for FeltDB capability queries
|
|
182
|
+
* Uses the low-level JsDb API for backward compatibility.
|
|
183
|
+
*
|
|
184
|
+
* New code should use useFeltDB with Collections instead.
|
|
185
|
+
*/
|
|
186
|
+
export function useLegacyFeltDB(db, capability, options = {}) {
|
|
187
|
+
const [records, setRecords] = useState([]);
|
|
188
|
+
const [loading, setLoading] = useState(true);
|
|
189
|
+
const [error, setError] = useState(null);
|
|
190
|
+
const refreshIntervalRef = useRef(null);
|
|
191
|
+
// Fetch records from database
|
|
192
|
+
const fetchRecords = useCallback(() => {
|
|
193
|
+
if (!db) {
|
|
194
|
+
setLoading(false);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
try {
|
|
198
|
+
setLoading(true);
|
|
199
|
+
const result = db.query(capability);
|
|
200
|
+
if (result.success && result.data) {
|
|
201
|
+
const parsedRecords = JSON.parse(result.data);
|
|
202
|
+
setRecords(parsedRecords);
|
|
203
|
+
setError(null);
|
|
204
|
+
options.onUpdate?.(parsedRecords);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
setError(result.error || "Unknown error");
|
|
208
|
+
options.onError?.(result.error || "Unknown error");
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
catch (err) {
|
|
212
|
+
const errorMsg = err instanceof Error ? err.message : "Failed to fetch records";
|
|
213
|
+
setError(errorMsg);
|
|
214
|
+
options.onError?.(errorMsg);
|
|
215
|
+
}
|
|
216
|
+
finally {
|
|
217
|
+
setLoading(false);
|
|
218
|
+
}
|
|
219
|
+
}, [db, capability, options]);
|
|
220
|
+
// Initial fetch
|
|
221
|
+
useEffect(() => {
|
|
222
|
+
fetchRecords();
|
|
223
|
+
}, [fetchRecords]);
|
|
224
|
+
// Setup auto-refresh interval
|
|
225
|
+
useEffect(() => {
|
|
226
|
+
if (options.refreshInterval && options.refreshInterval > 0) {
|
|
227
|
+
refreshIntervalRef.current = setInterval(fetchRecords, options.refreshInterval);
|
|
228
|
+
return () => {
|
|
229
|
+
if (refreshIntervalRef.current) {
|
|
230
|
+
clearInterval(refreshIntervalRef.current);
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
}, [fetchRecords, options.refreshInterval]);
|
|
235
|
+
// Insert a new record
|
|
236
|
+
const insert = useCallback((key, data) => {
|
|
237
|
+
if (!db) {
|
|
238
|
+
setError("Database not initialized");
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
try {
|
|
242
|
+
const result = db.insert(key, JSON.stringify(data));
|
|
243
|
+
if (result.success) {
|
|
244
|
+
fetchRecords(); // Refresh after insert
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
setError(result.error || "Insert failed");
|
|
249
|
+
options.onError?.(result.error || "Insert failed");
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
const errorMsg = err instanceof Error ? err.message : "Insert failed";
|
|
255
|
+
setError(errorMsg);
|
|
256
|
+
options.onError?.(errorMsg);
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
}, [db, fetchRecords, options]);
|
|
260
|
+
// Get a single record
|
|
261
|
+
const get = useCallback((key) => {
|
|
262
|
+
if (!db) {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
try {
|
|
266
|
+
const result = db.get(key);
|
|
267
|
+
if (result.success && result.data) {
|
|
268
|
+
return JSON.parse(result.data);
|
|
269
|
+
}
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
}, [db]);
|
|
276
|
+
return {
|
|
277
|
+
records,
|
|
278
|
+
loading,
|
|
279
|
+
error,
|
|
280
|
+
insert,
|
|
281
|
+
get,
|
|
282
|
+
refresh: fetchRecords,
|
|
283
|
+
update: async () => { },
|
|
284
|
+
delete: async () => { },
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Higher-order component for wrapping components with FeltDB
|
|
289
|
+
*
|
|
290
|
+
* @param Component React component that receives db and useFeltDB hook
|
|
291
|
+
* @param dbPath Path to the database file
|
|
292
|
+
* @returns Wrapped component
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* ```jsx
|
|
296
|
+
* const UserListWithDb = withFeltDB(UserList, "app.db");
|
|
297
|
+
* ```
|
|
298
|
+
*/
|
|
299
|
+
export function withFeltDB(Component, dbPath) {
|
|
300
|
+
return (props) => {
|
|
301
|
+
const [db, setDb] = useState(null);
|
|
302
|
+
const [dbError, setDbError] = useState(null);
|
|
303
|
+
useEffect(() => {
|
|
304
|
+
try {
|
|
305
|
+
// Dynamically import feltdb module (WASM module)
|
|
306
|
+
import('@feltdb/wasm').then((feltdb) => {
|
|
307
|
+
setDb(feltdb.open(dbPath));
|
|
308
|
+
}).catch((err) => {
|
|
309
|
+
setDbError(`Failed to load FeltDB: ${err.message}`);
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
catch (err) {
|
|
313
|
+
setDbError(err instanceof Error ? err.message : "Unknown error");
|
|
314
|
+
}
|
|
315
|
+
}, []);
|
|
316
|
+
if (dbError) {
|
|
317
|
+
return _jsxs("div", { className: "error", children: ["Database Error: ", dbError] });
|
|
318
|
+
}
|
|
319
|
+
if (!db) {
|
|
320
|
+
return _jsx("div", { className: "loading", children: "Loading database..." });
|
|
321
|
+
}
|
|
322
|
+
return _jsx(Component, { ...props, db: db });
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Example component using useFeltDB
|
|
327
|
+
*
|
|
328
|
+
* @example
|
|
329
|
+
* ```jsx
|
|
330
|
+
* import { useFeltDB } from './hooks/useFeltDB';
|
|
331
|
+
*
|
|
332
|
+
* function UserList({ db }) {
|
|
333
|
+
* const { records, loading, error, insert } = useFeltDB(db, "users", {
|
|
334
|
+
* refreshInterval: 5000, // Refresh every 5 seconds
|
|
335
|
+
* });
|
|
336
|
+
*
|
|
337
|
+
* if (loading) return <div>Loading...</div>;
|
|
338
|
+
* if (error) return <div>Error: {error}</div>;
|
|
339
|
+
*
|
|
340
|
+
* return (
|
|
341
|
+
* <div>
|
|
342
|
+
* {records.map((user: any) => (
|
|
343
|
+
* <div key={user.id}>{user.name} ({user.email})</div>
|
|
344
|
+
* ))}
|
|
345
|
+
* </div>
|
|
346
|
+
* );
|
|
347
|
+
* }
|
|
348
|
+
* ```
|
|
349
|
+
*/
|
|
350
|
+
export default useFeltDB;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Public assets for FeltDB Studio
|