@feltdb/core 0.4.4 → 0.4.6
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 +22 -0
- package/bin/create-feltdb.js +3 -0
- package/bin/feltdb.js +3 -0
- package/dist/analytics-backend.js +1 -1
- package/dist/cli/api-client.js +236 -0
- package/dist/cli/cli.js +18 -0
- package/dist/cli/commands.js +795 -0
- package/dist/cli/config.js +66 -0
- package/dist/cli/index.js +399 -0
- package/dist/create/application-identity.js +132 -0
- package/dist/create/cli-scripts-generator.js +211 -0
- package/dist/create/cli.js +202 -0
- package/dist/create/create.js +638 -0
- package/dist/create/docker-compose-generator.js +258 -0
- package/dist/create/index.js +4 -0
- package/dist/create/package-versions.js +4 -0
- package/dist/create/runtime-templates.js +272 -0
- package/dist/index-backend.js +1 -1
- 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/dist/wasm/feltdb_wasm.d.ts +461 -0
- package/dist/wasm/feltdb_wasm.js +1690 -0
- package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
- package/dist/wasm/feltdb_wasm_bg.wasm.d.ts +84 -0
- package/dist/wasm/package.json +16 -0
- package/package.json +40 -5
|
@@ -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/core/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
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { useEffect as e, useState as t } from "react";
|
|
2
|
+
import { jsx as n, jsxs as r } from "react/jsx-runtime";
|
|
3
|
+
var i = {
|
|
4
|
+
panel: "_panel_1cbba_1",
|
|
5
|
+
header: "_header_1cbba_8",
|
|
6
|
+
createButton: "_createButton_1cbba_23",
|
|
7
|
+
error: "_error_1cbba_38",
|
|
8
|
+
createForm: "_createForm_1cbba_47",
|
|
9
|
+
formGroup: "_formGroup_1cbba_55",
|
|
10
|
+
scopeList: "_scopeList_1cbba_76",
|
|
11
|
+
scopeCheckbox: "_scopeCheckbox_1cbba_82",
|
|
12
|
+
submitButton: "_submitButton_1cbba_94",
|
|
13
|
+
empty: "_empty_1cbba_109",
|
|
14
|
+
keysList: "_keysList_1cbba_117",
|
|
15
|
+
keyCard: "_keyCard_1cbba_123",
|
|
16
|
+
keyHeader: "_keyHeader_1cbba_135",
|
|
17
|
+
namespace: "_namespace_1cbba_150",
|
|
18
|
+
status: "_status_1cbba_156",
|
|
19
|
+
active: "_active_1cbba_163",
|
|
20
|
+
expired: "_expired_1cbba_168",
|
|
21
|
+
keyDetails: "_keyDetails_1cbba_173",
|
|
22
|
+
detail: "_detail_1cbba_179",
|
|
23
|
+
copyBtn: "_copyBtn_1cbba_203",
|
|
24
|
+
daysLeft: "_daysLeft_1cbba_217",
|
|
25
|
+
scopes: "_scopes_1cbba_223",
|
|
26
|
+
scopeTags: "_scopeTags_1cbba_227",
|
|
27
|
+
scopeTag: "_scopeTag_1cbba_227",
|
|
28
|
+
keyActions: "_keyActions_1cbba_243",
|
|
29
|
+
revokeBtn: "_revokeBtn_1cbba_250",
|
|
30
|
+
info: "_info_1cbba_265"
|
|
31
|
+
}, a = ({ apiUrl: a, token: o, namespace: s = "app-store-sherpa" }) => {
|
|
32
|
+
let [c, l] = t([]), [u, d] = t(!0), [f, p] = t(null), [m, h] = t(!1), [g, _] = t(null), [v, y] = t(""), [b, x] = t([
|
|
33
|
+
"state:read",
|
|
34
|
+
"state:write",
|
|
35
|
+
"events:read"
|
|
36
|
+
]), S = [
|
|
37
|
+
"state:read",
|
|
38
|
+
"state:write",
|
|
39
|
+
"events:read",
|
|
40
|
+
"backup:create",
|
|
41
|
+
"backup:restore",
|
|
42
|
+
"admin:logs",
|
|
43
|
+
"admin:restart"
|
|
44
|
+
], C = [
|
|
45
|
+
"state:read",
|
|
46
|
+
"state:write",
|
|
47
|
+
"events:read",
|
|
48
|
+
"backup:create",
|
|
49
|
+
"backup:restore",
|
|
50
|
+
"admin:logs",
|
|
51
|
+
"admin:restart"
|
|
52
|
+
];
|
|
53
|
+
e(() => {
|
|
54
|
+
w();
|
|
55
|
+
}, []);
|
|
56
|
+
let w = async () => {
|
|
57
|
+
try {
|
|
58
|
+
d(!0), p(null);
|
|
59
|
+
let e = await fetch(`${a}/api/keys`, { headers: { Authorization: `Bearer ${o}` } });
|
|
60
|
+
if (!e.ok) throw Error(`Failed to fetch keys: ${e.statusText}`);
|
|
61
|
+
let t = await e.json();
|
|
62
|
+
l(t.tokens || []);
|
|
63
|
+
} catch (e) {
|
|
64
|
+
p(e instanceof Error ? e.message : "Failed to fetch keys");
|
|
65
|
+
} finally {
|
|
66
|
+
d(!1);
|
|
67
|
+
}
|
|
68
|
+
}, T = async (e) => {
|
|
69
|
+
e.preventDefault();
|
|
70
|
+
try {
|
|
71
|
+
let e = await fetch(`${a}/api/keys`, {
|
|
72
|
+
method: "POST",
|
|
73
|
+
headers: {
|
|
74
|
+
Authorization: `Bearer ${o}`,
|
|
75
|
+
"Content-Type": "application/json"
|
|
76
|
+
},
|
|
77
|
+
body: JSON.stringify({
|
|
78
|
+
id: v || `key-${Date.now()}`,
|
|
79
|
+
namespace: s,
|
|
80
|
+
scopes: b.length > 0 ? b : C,
|
|
81
|
+
expiresIn: 90
|
|
82
|
+
})
|
|
83
|
+
});
|
|
84
|
+
if (!e.ok) throw Error(`Failed to create key: ${e.statusText}`);
|
|
85
|
+
y(""), x(C), h(!1), await w();
|
|
86
|
+
} catch (e) {
|
|
87
|
+
p(e instanceof Error ? e.message : "Failed to create key");
|
|
88
|
+
}
|
|
89
|
+
}, E = async (e) => {
|
|
90
|
+
if (confirm(`Revoke key "${e}"? This cannot be undone.`)) try {
|
|
91
|
+
let t = await fetch(`${a}/api/keys/${e}`, {
|
|
92
|
+
method: "DELETE",
|
|
93
|
+
headers: { Authorization: `Bearer ${o}` }
|
|
94
|
+
});
|
|
95
|
+
if (!t.ok) throw Error(`Failed to revoke key: ${t.statusText}`);
|
|
96
|
+
await w();
|
|
97
|
+
} catch (e) {
|
|
98
|
+
p(e instanceof Error ? e.message : "Failed to revoke key");
|
|
99
|
+
}
|
|
100
|
+
}, D = (e, t) => {
|
|
101
|
+
navigator.clipboard.writeText(e), _(t), setTimeout(() => _(null), 2e3);
|
|
102
|
+
}, O = (e) => new Date(e).toLocaleDateString("en-US", {
|
|
103
|
+
year: "numeric",
|
|
104
|
+
month: "short",
|
|
105
|
+
day: "numeric",
|
|
106
|
+
hour: "2-digit",
|
|
107
|
+
minute: "2-digit"
|
|
108
|
+
}), k = (e) => new Date(e) < /* @__PURE__ */ new Date(), A = (e) => Math.ceil((new Date(e).getTime() - (/* @__PURE__ */ new Date()).getTime()) / 864e5);
|
|
109
|
+
return u ? /* @__PURE__ */ n("div", {
|
|
110
|
+
className: i.panel,
|
|
111
|
+
children: "Loading keys..."
|
|
112
|
+
}) : /* @__PURE__ */ r("div", {
|
|
113
|
+
className: i.panel,
|
|
114
|
+
children: [
|
|
115
|
+
/* @__PURE__ */ r("div", {
|
|
116
|
+
className: i.header,
|
|
117
|
+
children: [/* @__PURE__ */ n("h2", { children: "API Key Management" }), /* @__PURE__ */ n("button", {
|
|
118
|
+
className: i.createButton,
|
|
119
|
+
onClick: () => h(!m),
|
|
120
|
+
children: m ? "✕ Cancel" : "+ New Key"
|
|
121
|
+
})]
|
|
122
|
+
}),
|
|
123
|
+
f && /* @__PURE__ */ r("div", {
|
|
124
|
+
className: i.error,
|
|
125
|
+
children: ["⚠ ", f]
|
|
126
|
+
}),
|
|
127
|
+
m && /* @__PURE__ */ r("form", {
|
|
128
|
+
onSubmit: T,
|
|
129
|
+
className: i.createForm,
|
|
130
|
+
children: [
|
|
131
|
+
/* @__PURE__ */ r("div", {
|
|
132
|
+
className: i.formGroup,
|
|
133
|
+
children: [/* @__PURE__ */ n("label", { children: "Key Name (optional)" }), /* @__PURE__ */ n("input", {
|
|
134
|
+
type: "text",
|
|
135
|
+
value: v,
|
|
136
|
+
onChange: (e) => y(e.target.value),
|
|
137
|
+
placeholder: "e.g., staging-key-001"
|
|
138
|
+
})]
|
|
139
|
+
}),
|
|
140
|
+
/* @__PURE__ */ r("div", {
|
|
141
|
+
className: i.formGroup,
|
|
142
|
+
children: [/* @__PURE__ */ n("label", { children: "Scopes" }), /* @__PURE__ */ n("div", {
|
|
143
|
+
className: i.scopeList,
|
|
144
|
+
children: S.map((e) => /* @__PURE__ */ r("label", {
|
|
145
|
+
className: i.scopeCheckbox,
|
|
146
|
+
children: [/* @__PURE__ */ n("input", {
|
|
147
|
+
type: "checkbox",
|
|
148
|
+
checked: b.includes(e),
|
|
149
|
+
onChange: (t) => {
|
|
150
|
+
t.target.checked ? x([...b, e]) : x(b.filter((t) => t !== e));
|
|
151
|
+
}
|
|
152
|
+
}), e]
|
|
153
|
+
}, e))
|
|
154
|
+
})]
|
|
155
|
+
}),
|
|
156
|
+
/* @__PURE__ */ n("button", {
|
|
157
|
+
type: "submit",
|
|
158
|
+
className: i.submitButton,
|
|
159
|
+
children: "Create Key"
|
|
160
|
+
})
|
|
161
|
+
]
|
|
162
|
+
}),
|
|
163
|
+
c.length === 0 ? /* @__PURE__ */ n("div", {
|
|
164
|
+
className: i.empty,
|
|
165
|
+
children: "No API keys configured. Create one to get started."
|
|
166
|
+
}) : /* @__PURE__ */ n("div", {
|
|
167
|
+
className: i.keysList,
|
|
168
|
+
children: c.map((e) => /* @__PURE__ */ r("div", {
|
|
169
|
+
className: i.keyCard,
|
|
170
|
+
children: [
|
|
171
|
+
/* @__PURE__ */ r("div", {
|
|
172
|
+
className: i.keyHeader,
|
|
173
|
+
children: [/* @__PURE__ */ r("div", { children: [/* @__PURE__ */ n("h3", { children: e.id }), /* @__PURE__ */ r("p", {
|
|
174
|
+
className: i.namespace,
|
|
175
|
+
children: ["Namespace: ", e.namespace]
|
|
176
|
+
})] }), /* @__PURE__ */ n("span", {
|
|
177
|
+
className: `${i.status} ${k(e.expires_at) ? i.expired : i.active}`,
|
|
178
|
+
children: k(e.expires_at) ? "Expired" : "Active"
|
|
179
|
+
})]
|
|
180
|
+
}),
|
|
181
|
+
/* @__PURE__ */ r("div", {
|
|
182
|
+
className: i.keyDetails,
|
|
183
|
+
children: [
|
|
184
|
+
/* @__PURE__ */ r("div", {
|
|
185
|
+
className: i.detail,
|
|
186
|
+
children: [
|
|
187
|
+
/* @__PURE__ */ n("strong", { children: "Secret:" }),
|
|
188
|
+
/* @__PURE__ */ r("code", { children: [e.secret.substring(0, 20), "..."] }),
|
|
189
|
+
/* @__PURE__ */ n("button", {
|
|
190
|
+
className: i.copyBtn,
|
|
191
|
+
onClick: () => D(e.secret, e.id),
|
|
192
|
+
children: g === e.id ? "✓ Copied" : "Copy"
|
|
193
|
+
})
|
|
194
|
+
]
|
|
195
|
+
}),
|
|
196
|
+
/* @__PURE__ */ r("div", {
|
|
197
|
+
className: i.detail,
|
|
198
|
+
children: [/* @__PURE__ */ n("strong", { children: "Created:" }), /* @__PURE__ */ n("span", { children: O(e.created_at) })]
|
|
199
|
+
}),
|
|
200
|
+
/* @__PURE__ */ r("div", {
|
|
201
|
+
className: i.detail,
|
|
202
|
+
children: [/* @__PURE__ */ n("strong", { children: "Expires:" }), /* @__PURE__ */ r("span", { children: [O(e.expires_at), !k(e.expires_at) && /* @__PURE__ */ r("span", {
|
|
203
|
+
className: i.daysLeft,
|
|
204
|
+
children: [
|
|
205
|
+
"(",
|
|
206
|
+
A(e.expires_at),
|
|
207
|
+
" days)"
|
|
208
|
+
]
|
|
209
|
+
})] })]
|
|
210
|
+
}),
|
|
211
|
+
e.last_used && /* @__PURE__ */ r("div", {
|
|
212
|
+
className: i.detail,
|
|
213
|
+
children: [/* @__PURE__ */ n("strong", { children: "Last Used:" }), /* @__PURE__ */ n("span", { children: O(e.last_used) })]
|
|
214
|
+
}),
|
|
215
|
+
/* @__PURE__ */ r("div", {
|
|
216
|
+
className: i.scopes,
|
|
217
|
+
children: [/* @__PURE__ */ n("strong", { children: "Scopes:" }), /* @__PURE__ */ n("div", {
|
|
218
|
+
className: i.scopeTags,
|
|
219
|
+
children: e.scopes.map((e) => /* @__PURE__ */ n("span", {
|
|
220
|
+
className: i.scopeTag,
|
|
221
|
+
children: e
|
|
222
|
+
}, e))
|
|
223
|
+
})]
|
|
224
|
+
})
|
|
225
|
+
]
|
|
226
|
+
}),
|
|
227
|
+
/* @__PURE__ */ n("div", {
|
|
228
|
+
className: i.keyActions,
|
|
229
|
+
children: /* @__PURE__ */ n("button", {
|
|
230
|
+
className: i.revokeBtn,
|
|
231
|
+
onClick: () => E(e.id),
|
|
232
|
+
children: "Revoke"
|
|
233
|
+
})
|
|
234
|
+
})
|
|
235
|
+
]
|
|
236
|
+
}, e.id))
|
|
237
|
+
}),
|
|
238
|
+
/* @__PURE__ */ n("div", {
|
|
239
|
+
className: i.info,
|
|
240
|
+
children: /* @__PURE__ */ r("p", { children: [/* @__PURE__ */ n("strong", { children: "Security:" }), " Store tokens securely. Never commit to version control. Tokens expire after 90 days."] })
|
|
241
|
+
})
|
|
242
|
+
]
|
|
243
|
+
});
|
|
244
|
+
};
|
|
245
|
+
//#endregion
|
|
246
|
+
export { a as t };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { StateFirstDB } from '@feltdb/core';
|
|
3
|
+
export interface StudioAppProps {
|
|
4
|
+
db?: StateFirstDB;
|
|
5
|
+
remoteUrl?: string;
|
|
6
|
+
namespace?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function StudioApp({ db, remoteUrl, namespace }: StudioAppProps): React.JSX.Element;
|
|
9
|
+
export default StudioApp;
|
|
10
|
+
//# sourceMappingURL=app.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAmBnD,OAAO,EAAgC,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAC/E,OAAO,WAAW,CAAC;AAEnB,MAAM,WAAW,cAAc;IAC7B,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,SAAqB,EAAE,EAAE,cAAc,qBA2GjF;AAED,eAAe,SAAS,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { FlowSpec, StateFirstDB } from '@feltdb/core';
|
|
3
|
+
export interface AgentExplorerProps {
|
|
4
|
+
db?: StateFirstDB;
|
|
5
|
+
model?: FlowSpec | null;
|
|
6
|
+
}
|
|
7
|
+
export declare function AgentExplorer({ model }: AgentExplorerProps): React.JSX.Element;
|
|
8
|
+
export default AgentExplorer;
|
|
9
|
+
//# sourceMappingURL=AgentExplorer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentExplorer.d.ts","sourceRoot":"","sources":["../../src/components/AgentExplorer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AACxC,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,WAAW,kBAAkB;IAAG,EAAE,CAAC,EAAE,YAAY,CAAC;IAAC,KAAK,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;CAAE;AAElF,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,EAAE,kBAAkB,qBAK1D;AACD,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { StateFirstDB, FlowSpec } from '@feltdb/core';
|
|
3
|
+
export interface ApplicationDesignerProps {
|
|
4
|
+
db?: StateFirstDB;
|
|
5
|
+
namespace?: string;
|
|
6
|
+
projectSpec?: FlowSpec | null;
|
|
7
|
+
onSpecChange?: (spec: FlowSpec) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare function ApplicationDesigner({ db, namespace, projectSpec, onSpecChange }: ApplicationDesignerProps): React.JSX.Element;
|
|
10
|
+
export default ApplicationDesigner;
|
|
11
|
+
//# sourceMappingURL=ApplicationDesigner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApplicationDesigner.d.ts","sourceRoot":"","sources":["../../src/components/ApplicationDesigner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+C,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAkB,MAAM,cAAc,CAAC;AAU3E,MAAM,WAAW,wBAAwB;IAAG,EAAE,CAAC,EAAE,YAAY,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IAAC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAA;CAAE;AAE3J,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,EAAE,SAAqB,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE,wBAAwB,qBAsGrH;AACD,eAAe,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { FlowSpec, StateFirstDB } from '@feltdb/core';
|
|
3
|
+
export interface CapabilityExplorerProps {
|
|
4
|
+
db?: StateFirstDB;
|
|
5
|
+
model?: FlowSpec | null;
|
|
6
|
+
}
|
|
7
|
+
export declare function CapabilityExplorer({ model }: CapabilityExplorerProps): React.JSX.Element;
|
|
8
|
+
export default CapabilityExplorer;
|
|
9
|
+
//# sourceMappingURL=CapabilityExplorer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CapabilityExplorer.d.ts","sourceRoot":"","sources":["../../src/components/CapabilityExplorer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,WAAW,uBAAuB;IAAG,EAAE,CAAC,EAAE,YAAY,CAAC;IAAC,KAAK,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;CAAE;AAEvF,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,EAAE,uBAAuB,qBAMpE;AACD,eAAe,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { RuntimeDiagnostics, StateFirstDB } from '@feltdb/core';
|
|
3
|
+
export interface ConflictExplorerProps {
|
|
4
|
+
db?: StateFirstDB;
|
|
5
|
+
diagnostics?: RuntimeDiagnostics | null;
|
|
6
|
+
}
|
|
7
|
+
export declare function ConflictExplorer({ db, diagnostics }: ConflictExplorerProps): React.JSX.Element;
|
|
8
|
+
export default ConflictExplorer;
|
|
9
|
+
//# sourceMappingURL=ConflictExplorer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConflictExplorer.d.ts","sourceRoot":"","sources":["../../src/components/ConflictExplorer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACrE,MAAM,WAAW,qBAAqB;IAAG,EAAE,CAAC,EAAE,YAAY,CAAC;IAAC,WAAW,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAA;CAAE;AACrG,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,qBAAqB,qBAG1E;AACD,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { FlowSpec, StateFirstDB } from '@feltdb/core';
|
|
3
|
+
export interface ExecutionViewerProps {
|
|
4
|
+
db?: StateFirstDB;
|
|
5
|
+
model?: FlowSpec | null;
|
|
6
|
+
}
|
|
7
|
+
export declare function ExecutionViewer({ db, model }: ExecutionViewerProps): React.JSX.Element;
|
|
8
|
+
export default ExecutionViewer;
|
|
9
|
+
//# sourceMappingURL=ExecutionViewer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExecutionViewer.d.ts","sourceRoot":"","sources":["../../src/components/ExecutionViewer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG3D,MAAM,WAAW,oBAAoB;IAAG,EAAE,CAAC,EAAE,YAAY,CAAC;IAAC,KAAK,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;CAAE;AAQpF,wBAAgB,eAAe,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,oBAAoB,qBAOlE;AACD,eAAe,eAAe,CAAC"}
|