@qontinui/ui-bridge 0.2.0 → 0.3.1
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/dist/ai/index.d.mts +312 -155
- package/dist/ai/index.d.ts +312 -155
- package/dist/ai/index.js +2363 -67
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/index.mjs +2328 -68
- package/dist/ai/index.mjs.map +1 -1
- package/dist/annotations/index.d.mts +218 -0
- package/dist/annotations/index.d.ts +218 -0
- package/dist/annotations/index.js +246 -0
- package/dist/annotations/index.js.map +1 -0
- package/dist/annotations/index.mjs +241 -0
- package/dist/annotations/index.mjs.map +1 -0
- package/dist/assertions-BSR3afVr.d.ts +161 -0
- package/dist/assertions-CTw1hfOx.d.mts +161 -0
- package/dist/babel-plugin/index.js +504 -0
- package/dist/babel-plugin/index.js.map +1 -0
- package/dist/babel-plugin/index.mjs +488 -0
- package/dist/babel-plugin/index.mjs.map +1 -0
- package/dist/browser-capture-Bms60T6f.d.mts +47 -0
- package/dist/browser-capture-CsTU29mb.d.ts +47 -0
- package/dist/control/index.d.mts +26 -7
- package/dist/control/index.d.ts +26 -7
- package/dist/control/index.js +276 -48
- package/dist/control/index.js.map +1 -1
- package/dist/control/index.mjs +276 -48
- package/dist/control/index.mjs.map +1 -1
- package/dist/core/index.d.mts +115 -44
- package/dist/core/index.d.ts +115 -44
- package/dist/core/index.js +0 -1560
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +1 -1549
- package/dist/core/index.mjs.map +1 -1
- package/dist/debug/index.d.mts +5 -3
- package/dist/debug/index.d.ts +5 -3
- package/dist/debug/index.js +925 -1
- package/dist/debug/index.js.map +1 -1
- package/dist/debug/index.mjs +924 -2
- package/dist/debug/index.mjs.map +1 -1
- package/dist/index.d.mts +13 -9
- package/dist/index.d.ts +13 -9
- package/dist/index.js +8310 -3777
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +8246 -3766
- package/dist/index.mjs.map +1 -1
- package/dist/{metrics-NC3csD0R.d.mts → metrics-DuA2qIIz.d.mts} +2 -2
- package/dist/{metrics-C9XRi_mL.d.ts → metrics-KFAAKNEB.d.ts} +2 -2
- package/dist/native/control/index.js +448 -0
- package/dist/native/control/index.js.map +1 -0
- package/dist/native/control/index.mjs +445 -0
- package/dist/native/control/index.mjs.map +1 -0
- package/dist/native/core/index.js +486 -0
- package/dist/native/core/index.js.map +1 -0
- package/dist/native/core/index.mjs +475 -0
- package/dist/native/core/index.mjs.map +1 -0
- package/dist/native/debug/index.js +408 -0
- package/dist/native/debug/index.js.map +1 -0
- package/dist/native/debug/index.mjs +406 -0
- package/dist/native/debug/index.mjs.map +1 -0
- package/dist/native/index.js +2232 -0
- package/dist/native/index.js.map +1 -0
- package/dist/native/index.mjs +2204 -0
- package/dist/native/index.mjs.map +1 -0
- package/dist/native/react/index.js +1377 -0
- package/dist/native/react/index.js.map +1 -0
- package/dist/native/react/index.mjs +1365 -0
- package/dist/native/react/index.mjs.map +1 -0
- package/dist/native/server/index.js +440 -0
- package/dist/native/server/index.js.map +1 -0
- package/dist/native/server/index.mjs +435 -0
- package/dist/native/server/index.mjs.map +1 -0
- package/dist/react/index.d.mts +121 -9
- package/dist/react/index.d.ts +121 -9
- package/dist/react/index.js +2239 -91
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +2239 -92
- package/dist/react/index.mjs.map +1 -1
- package/dist/{registry-CIEDjbQ9.d.ts → registry-C6dDtn1v.d.ts} +34 -15
- package/dist/{registry-SsSDq46X.d.mts → registry-POtcxnal.d.mts} +34 -15
- package/dist/render-log/index.d.mts +1 -1
- package/dist/render-log/index.d.ts +1 -1
- package/dist/server/express.d.mts +37 -0
- package/dist/server/express.d.ts +37 -0
- package/dist/server/express.js +298 -0
- package/dist/server/express.js.map +1 -0
- package/dist/server/express.mjs +294 -0
- package/dist/server/express.mjs.map +1 -0
- package/dist/server/handlers.d.mts +124 -0
- package/dist/server/handlers.d.ts +124 -0
- package/dist/server/handlers.js +7183 -0
- package/dist/server/handlers.js.map +1 -0
- package/dist/server/handlers.mjs +7180 -0
- package/dist/server/handlers.mjs.map +1 -0
- package/dist/server/index.d.mts +12 -0
- package/dist/server/index.d.ts +12 -0
- package/dist/server/index.js +8384 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/index.mjs +8369 -0
- package/dist/server/index.mjs.map +1 -0
- package/dist/server/nextjs.d.mts +128 -0
- package/dist/server/nextjs.d.ts +128 -0
- package/dist/server/nextjs.js +390 -0
- package/dist/server/nextjs.js.map +1 -0
- package/dist/server/nextjs.mjs +385 -0
- package/dist/server/nextjs.mjs.map +1 -0
- package/dist/server/standalone.d.mts +7 -0
- package/dist/server/standalone.d.ts +7 -0
- package/dist/server/standalone.js +845 -0
- package/dist/server/standalone.js.map +1 -0
- package/dist/server/standalone.mjs +841 -0
- package/dist/server/standalone.mjs.map +1 -0
- package/dist/specs/index.d.mts +365 -0
- package/dist/specs/index.d.ts +365 -0
- package/dist/specs/index.js +2809 -0
- package/dist/specs/index.js.map +1 -0
- package/dist/specs/index.mjs +2786 -0
- package/dist/specs/index.mjs.map +1 -0
- package/dist/standalone-B6GLIEmR.d.ts +216 -0
- package/dist/standalone-CjdYqj3P.d.mts +216 -0
- package/dist/swc-plugin/index.d.mts +79 -0
- package/dist/swc-plugin/index.d.ts +79 -0
- package/dist/swc-plugin/index.js +15 -0
- package/dist/swc-plugin/index.js.map +1 -0
- package/dist/swc-plugin/index.mjs +9 -0
- package/dist/swc-plugin/index.mjs.map +1 -0
- package/dist/types-B2EfvEaq.d.ts +236 -0
- package/dist/{types-Dr6tH-bm.d.mts → types-C7gVYRnF.d.ts} +72 -2
- package/dist/{types-oCTrRxSw.d.ts → types-CJGrBEhC.d.mts} +72 -2
- package/dist/types-CebMQj76.d.ts +1275 -0
- package/dist/types-D_ypYl3T.d.mts +1275 -0
- package/dist/types-UBtp7R0u.d.mts +132 -0
- package/dist/types-UBtp7R0u.d.ts +132 -0
- package/dist/types-gO696T_t.d.mts +236 -0
- package/dist/{types-CPMbN_Iw.d.mts → types-suaYwWWg.d.mts} +519 -152
- package/dist/{types-CPMbN_Iw.d.ts → types-suaYwWWg.d.ts} +519 -152
- package/package.json +123 -4
- package/swc-plugin-wasm/ui_bridge_swc_plugin.wasm +0 -0
- package/dist/types-BvCfFuEV.d.ts +0 -534
- package/dist/types-CFT3Dnx4.d.mts +0 -534
- package/dist/websocket-client-CX4QJesI.d.ts +0 -124
- package/dist/websocket-client-C_Na0OSp.d.mts +0 -124
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { c as AnnotationEvent, E as ElementAnnotation, a as AnnotationConfig, b as AnnotationCoverage } from '../types-UBtp7R0u.mjs';
|
|
2
|
+
export { A as ANNOTATION_CONFIG_VERSION, d as AnnotationEventType } from '../types-UBtp7R0u.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Annotation Store
|
|
6
|
+
*
|
|
7
|
+
* In-memory store for element annotations with CRUD operations,
|
|
8
|
+
* import/export, coverage tracking, and event emission.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Listener function for annotation events.
|
|
13
|
+
*/
|
|
14
|
+
type AnnotationListener = (event: AnnotationEvent) => void;
|
|
15
|
+
/**
|
|
16
|
+
* Annotation Store
|
|
17
|
+
*
|
|
18
|
+
* Stores element annotations in memory with event-driven updates.
|
|
19
|
+
* Provides CRUD operations, import/export, coverage tracking, and
|
|
20
|
+
* an event system for reacting to annotation changes.
|
|
21
|
+
*
|
|
22
|
+
* @example Basic CRUD usage
|
|
23
|
+
* ```ts
|
|
24
|
+
* const store = new AnnotationStore();
|
|
25
|
+
*
|
|
26
|
+
* // Set an annotation
|
|
27
|
+
* store.set('login-btn', {
|
|
28
|
+
* description: 'Primary login button',
|
|
29
|
+
* purpose: 'Submits the login form',
|
|
30
|
+
* tags: ['auth', 'primary-action'],
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // Read it back
|
|
34
|
+
* const annotation = store.get('login-btn');
|
|
35
|
+
* console.log(annotation?.description); // 'Primary login button'
|
|
36
|
+
*
|
|
37
|
+
* // Check existence
|
|
38
|
+
* store.has('login-btn'); // true
|
|
39
|
+
*
|
|
40
|
+
* // Delete it
|
|
41
|
+
* store.delete('login-btn'); // true
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @example Import/export workflow
|
|
45
|
+
* ```ts
|
|
46
|
+
* const store = new AnnotationStore();
|
|
47
|
+
*
|
|
48
|
+
* // Import from a config file
|
|
49
|
+
* const config = JSON.parse(fs.readFileSync('annotations.json', 'utf-8'));
|
|
50
|
+
* const count = store.importConfig(config);
|
|
51
|
+
* console.log(`Imported ${count} annotations`);
|
|
52
|
+
*
|
|
53
|
+
* // Export current state
|
|
54
|
+
* const exported = store.exportConfig({ appName: 'MyApp' });
|
|
55
|
+
* fs.writeFileSync('annotations.json', JSON.stringify(exported, null, 2));
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* @example Listening for changes
|
|
59
|
+
* ```ts
|
|
60
|
+
* const store = new AnnotationStore();
|
|
61
|
+
*
|
|
62
|
+
* const unsubscribe = store.on((event) => {
|
|
63
|
+
* switch (event.type) {
|
|
64
|
+
* case 'annotation:set':
|
|
65
|
+
* console.log(`Updated: ${event.elementId}`);
|
|
66
|
+
* break;
|
|
67
|
+
* case 'annotation:deleted':
|
|
68
|
+
* console.log(`Deleted: ${event.elementId}`);
|
|
69
|
+
* break;
|
|
70
|
+
* case 'annotation:imported':
|
|
71
|
+
* console.log(`Imported ${event.count} annotations`);
|
|
72
|
+
* break;
|
|
73
|
+
* case 'annotation:cleared':
|
|
74
|
+
* console.log('All annotations cleared');
|
|
75
|
+
* break;
|
|
76
|
+
* }
|
|
77
|
+
* });
|
|
78
|
+
*
|
|
79
|
+
* // Later, stop listening
|
|
80
|
+
* unsubscribe();
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
declare class AnnotationStore {
|
|
84
|
+
private store;
|
|
85
|
+
private listeners;
|
|
86
|
+
/**
|
|
87
|
+
* Get an annotation by element ID.
|
|
88
|
+
*/
|
|
89
|
+
get(elementId: string): ElementAnnotation | undefined;
|
|
90
|
+
/**
|
|
91
|
+
* Get all annotations as a record.
|
|
92
|
+
*/
|
|
93
|
+
getAll(): Record<string, ElementAnnotation>;
|
|
94
|
+
/**
|
|
95
|
+
* Set an annotation for an element. Auto-sets `updatedAt`.
|
|
96
|
+
*/
|
|
97
|
+
set(elementId: string, annotation: ElementAnnotation): void;
|
|
98
|
+
/**
|
|
99
|
+
* Delete an annotation by element ID.
|
|
100
|
+
*
|
|
101
|
+
* @returns true if the annotation existed and was deleted
|
|
102
|
+
*/
|
|
103
|
+
delete(elementId: string): boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Check if an annotation exists for an element.
|
|
106
|
+
*/
|
|
107
|
+
has(elementId: string): boolean;
|
|
108
|
+
/**
|
|
109
|
+
* Get the number of stored annotations.
|
|
110
|
+
*/
|
|
111
|
+
get count(): number;
|
|
112
|
+
/**
|
|
113
|
+
* Clear all annotations.
|
|
114
|
+
*/
|
|
115
|
+
clear(): void;
|
|
116
|
+
/**
|
|
117
|
+
* Import annotations from a config object.
|
|
118
|
+
*
|
|
119
|
+
* Merges with existing annotations (new values overwrite per element ID).
|
|
120
|
+
*
|
|
121
|
+
* @returns Number of annotations imported
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```ts
|
|
125
|
+
* const config: AnnotationConfig = {
|
|
126
|
+
* version: '1.0.0',
|
|
127
|
+
* annotations: {
|
|
128
|
+
* 'btn-1': { description: 'Submit button', tags: ['form'] },
|
|
129
|
+
* 'input-1': { description: 'Name field' },
|
|
130
|
+
* },
|
|
131
|
+
* };
|
|
132
|
+
* const count = store.importConfig(config); // 2
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
importConfig(config: AnnotationConfig): number;
|
|
136
|
+
/**
|
|
137
|
+
* Export all annotations as a config object.
|
|
138
|
+
*
|
|
139
|
+
* The returned object can be serialized to JSON and saved to a file,
|
|
140
|
+
* then later re-imported with {@link importConfig}.
|
|
141
|
+
*
|
|
142
|
+
* @param metadata - Optional metadata to include (appName, description, etc.)
|
|
143
|
+
* @returns AnnotationConfig with all current annotations
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```ts
|
|
147
|
+
* const config = store.exportConfig({ appName: 'MyApp' });
|
|
148
|
+
* // config.version === '1.0.0'
|
|
149
|
+
* // config.annotations === { 'btn-1': { ... }, 'input-1': { ... } }
|
|
150
|
+
* // config.metadata === { appName: 'MyApp', exportedAt: 1706900000000 }
|
|
151
|
+
*
|
|
152
|
+
* // Save to file
|
|
153
|
+
* fs.writeFileSync('annotations.json', JSON.stringify(config, null, 2));
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
exportConfig(metadata?: AnnotationConfig['metadata']): AnnotationConfig;
|
|
157
|
+
/**
|
|
158
|
+
* Compute annotation coverage against a set of known element IDs.
|
|
159
|
+
*
|
|
160
|
+
* Compares the store's annotations against the provided list of element IDs
|
|
161
|
+
* to determine what percentage of elements have been annotated.
|
|
162
|
+
*
|
|
163
|
+
* @param allElementIds - Array of all known element IDs in the UI
|
|
164
|
+
* @returns Coverage statistics including percentages and lists of annotated/unannotated IDs
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```ts
|
|
168
|
+
* store.set('btn-1', { description: 'Submit' });
|
|
169
|
+
* store.set('input-1', { description: 'Name' });
|
|
170
|
+
*
|
|
171
|
+
* const coverage = store.getCoverage(['btn-1', 'input-1', 'input-2', 'link-1']);
|
|
172
|
+
* // coverage.totalElements === 4
|
|
173
|
+
* // coverage.annotatedElements === 2
|
|
174
|
+
* // coverage.coveragePercent === 50
|
|
175
|
+
* // coverage.annotatedIds === ['btn-1', 'input-1']
|
|
176
|
+
* // coverage.unannotatedIds === ['input-2', 'link-1']
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
getCoverage(allElementIds: string[]): AnnotationCoverage;
|
|
180
|
+
/**
|
|
181
|
+
* Subscribe to annotation events.
|
|
182
|
+
*
|
|
183
|
+
* The listener is called whenever annotations are set, deleted, imported,
|
|
184
|
+
* or cleared. Returns an unsubscribe function to stop listening.
|
|
185
|
+
*
|
|
186
|
+
* @param listener - Callback function receiving {@link AnnotationEvent} objects
|
|
187
|
+
* @returns Unsubscribe function - call it to remove the listener
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```ts
|
|
191
|
+
* const unsubscribe = store.on((event) => {
|
|
192
|
+
* if (event.type === 'annotation:set') {
|
|
193
|
+
* console.log(`Element ${event.elementId} annotated:`, event.annotation);
|
|
194
|
+
* }
|
|
195
|
+
* });
|
|
196
|
+
*
|
|
197
|
+
* store.set('btn-1', { description: 'Submit' });
|
|
198
|
+
* // Logs: "Element btn-1 annotated: { description: 'Submit', updatedAt: ... }"
|
|
199
|
+
*
|
|
200
|
+
* unsubscribe(); // Stop listening
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
on(listener: AnnotationListener): () => void;
|
|
204
|
+
/**
|
|
205
|
+
* Emit an event to all listeners.
|
|
206
|
+
*/
|
|
207
|
+
private emit;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Get the global annotation store singleton.
|
|
211
|
+
*/
|
|
212
|
+
declare function getGlobalAnnotationStore(): AnnotationStore;
|
|
213
|
+
/**
|
|
214
|
+
* Reset the global annotation store (primarily for testing).
|
|
215
|
+
*/
|
|
216
|
+
declare function resetGlobalAnnotationStore(): void;
|
|
217
|
+
|
|
218
|
+
export { AnnotationConfig, AnnotationCoverage, AnnotationEvent, type AnnotationListener, AnnotationStore, ElementAnnotation, getGlobalAnnotationStore, resetGlobalAnnotationStore };
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { c as AnnotationEvent, E as ElementAnnotation, a as AnnotationConfig, b as AnnotationCoverage } from '../types-UBtp7R0u.js';
|
|
2
|
+
export { A as ANNOTATION_CONFIG_VERSION, d as AnnotationEventType } from '../types-UBtp7R0u.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Annotation Store
|
|
6
|
+
*
|
|
7
|
+
* In-memory store for element annotations with CRUD operations,
|
|
8
|
+
* import/export, coverage tracking, and event emission.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Listener function for annotation events.
|
|
13
|
+
*/
|
|
14
|
+
type AnnotationListener = (event: AnnotationEvent) => void;
|
|
15
|
+
/**
|
|
16
|
+
* Annotation Store
|
|
17
|
+
*
|
|
18
|
+
* Stores element annotations in memory with event-driven updates.
|
|
19
|
+
* Provides CRUD operations, import/export, coverage tracking, and
|
|
20
|
+
* an event system for reacting to annotation changes.
|
|
21
|
+
*
|
|
22
|
+
* @example Basic CRUD usage
|
|
23
|
+
* ```ts
|
|
24
|
+
* const store = new AnnotationStore();
|
|
25
|
+
*
|
|
26
|
+
* // Set an annotation
|
|
27
|
+
* store.set('login-btn', {
|
|
28
|
+
* description: 'Primary login button',
|
|
29
|
+
* purpose: 'Submits the login form',
|
|
30
|
+
* tags: ['auth', 'primary-action'],
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // Read it back
|
|
34
|
+
* const annotation = store.get('login-btn');
|
|
35
|
+
* console.log(annotation?.description); // 'Primary login button'
|
|
36
|
+
*
|
|
37
|
+
* // Check existence
|
|
38
|
+
* store.has('login-btn'); // true
|
|
39
|
+
*
|
|
40
|
+
* // Delete it
|
|
41
|
+
* store.delete('login-btn'); // true
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @example Import/export workflow
|
|
45
|
+
* ```ts
|
|
46
|
+
* const store = new AnnotationStore();
|
|
47
|
+
*
|
|
48
|
+
* // Import from a config file
|
|
49
|
+
* const config = JSON.parse(fs.readFileSync('annotations.json', 'utf-8'));
|
|
50
|
+
* const count = store.importConfig(config);
|
|
51
|
+
* console.log(`Imported ${count} annotations`);
|
|
52
|
+
*
|
|
53
|
+
* // Export current state
|
|
54
|
+
* const exported = store.exportConfig({ appName: 'MyApp' });
|
|
55
|
+
* fs.writeFileSync('annotations.json', JSON.stringify(exported, null, 2));
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* @example Listening for changes
|
|
59
|
+
* ```ts
|
|
60
|
+
* const store = new AnnotationStore();
|
|
61
|
+
*
|
|
62
|
+
* const unsubscribe = store.on((event) => {
|
|
63
|
+
* switch (event.type) {
|
|
64
|
+
* case 'annotation:set':
|
|
65
|
+
* console.log(`Updated: ${event.elementId}`);
|
|
66
|
+
* break;
|
|
67
|
+
* case 'annotation:deleted':
|
|
68
|
+
* console.log(`Deleted: ${event.elementId}`);
|
|
69
|
+
* break;
|
|
70
|
+
* case 'annotation:imported':
|
|
71
|
+
* console.log(`Imported ${event.count} annotations`);
|
|
72
|
+
* break;
|
|
73
|
+
* case 'annotation:cleared':
|
|
74
|
+
* console.log('All annotations cleared');
|
|
75
|
+
* break;
|
|
76
|
+
* }
|
|
77
|
+
* });
|
|
78
|
+
*
|
|
79
|
+
* // Later, stop listening
|
|
80
|
+
* unsubscribe();
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
declare class AnnotationStore {
|
|
84
|
+
private store;
|
|
85
|
+
private listeners;
|
|
86
|
+
/**
|
|
87
|
+
* Get an annotation by element ID.
|
|
88
|
+
*/
|
|
89
|
+
get(elementId: string): ElementAnnotation | undefined;
|
|
90
|
+
/**
|
|
91
|
+
* Get all annotations as a record.
|
|
92
|
+
*/
|
|
93
|
+
getAll(): Record<string, ElementAnnotation>;
|
|
94
|
+
/**
|
|
95
|
+
* Set an annotation for an element. Auto-sets `updatedAt`.
|
|
96
|
+
*/
|
|
97
|
+
set(elementId: string, annotation: ElementAnnotation): void;
|
|
98
|
+
/**
|
|
99
|
+
* Delete an annotation by element ID.
|
|
100
|
+
*
|
|
101
|
+
* @returns true if the annotation existed and was deleted
|
|
102
|
+
*/
|
|
103
|
+
delete(elementId: string): boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Check if an annotation exists for an element.
|
|
106
|
+
*/
|
|
107
|
+
has(elementId: string): boolean;
|
|
108
|
+
/**
|
|
109
|
+
* Get the number of stored annotations.
|
|
110
|
+
*/
|
|
111
|
+
get count(): number;
|
|
112
|
+
/**
|
|
113
|
+
* Clear all annotations.
|
|
114
|
+
*/
|
|
115
|
+
clear(): void;
|
|
116
|
+
/**
|
|
117
|
+
* Import annotations from a config object.
|
|
118
|
+
*
|
|
119
|
+
* Merges with existing annotations (new values overwrite per element ID).
|
|
120
|
+
*
|
|
121
|
+
* @returns Number of annotations imported
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```ts
|
|
125
|
+
* const config: AnnotationConfig = {
|
|
126
|
+
* version: '1.0.0',
|
|
127
|
+
* annotations: {
|
|
128
|
+
* 'btn-1': { description: 'Submit button', tags: ['form'] },
|
|
129
|
+
* 'input-1': { description: 'Name field' },
|
|
130
|
+
* },
|
|
131
|
+
* };
|
|
132
|
+
* const count = store.importConfig(config); // 2
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
importConfig(config: AnnotationConfig): number;
|
|
136
|
+
/**
|
|
137
|
+
* Export all annotations as a config object.
|
|
138
|
+
*
|
|
139
|
+
* The returned object can be serialized to JSON and saved to a file,
|
|
140
|
+
* then later re-imported with {@link importConfig}.
|
|
141
|
+
*
|
|
142
|
+
* @param metadata - Optional metadata to include (appName, description, etc.)
|
|
143
|
+
* @returns AnnotationConfig with all current annotations
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```ts
|
|
147
|
+
* const config = store.exportConfig({ appName: 'MyApp' });
|
|
148
|
+
* // config.version === '1.0.0'
|
|
149
|
+
* // config.annotations === { 'btn-1': { ... }, 'input-1': { ... } }
|
|
150
|
+
* // config.metadata === { appName: 'MyApp', exportedAt: 1706900000000 }
|
|
151
|
+
*
|
|
152
|
+
* // Save to file
|
|
153
|
+
* fs.writeFileSync('annotations.json', JSON.stringify(config, null, 2));
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
exportConfig(metadata?: AnnotationConfig['metadata']): AnnotationConfig;
|
|
157
|
+
/**
|
|
158
|
+
* Compute annotation coverage against a set of known element IDs.
|
|
159
|
+
*
|
|
160
|
+
* Compares the store's annotations against the provided list of element IDs
|
|
161
|
+
* to determine what percentage of elements have been annotated.
|
|
162
|
+
*
|
|
163
|
+
* @param allElementIds - Array of all known element IDs in the UI
|
|
164
|
+
* @returns Coverage statistics including percentages and lists of annotated/unannotated IDs
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```ts
|
|
168
|
+
* store.set('btn-1', { description: 'Submit' });
|
|
169
|
+
* store.set('input-1', { description: 'Name' });
|
|
170
|
+
*
|
|
171
|
+
* const coverage = store.getCoverage(['btn-1', 'input-1', 'input-2', 'link-1']);
|
|
172
|
+
* // coverage.totalElements === 4
|
|
173
|
+
* // coverage.annotatedElements === 2
|
|
174
|
+
* // coverage.coveragePercent === 50
|
|
175
|
+
* // coverage.annotatedIds === ['btn-1', 'input-1']
|
|
176
|
+
* // coverage.unannotatedIds === ['input-2', 'link-1']
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
getCoverage(allElementIds: string[]): AnnotationCoverage;
|
|
180
|
+
/**
|
|
181
|
+
* Subscribe to annotation events.
|
|
182
|
+
*
|
|
183
|
+
* The listener is called whenever annotations are set, deleted, imported,
|
|
184
|
+
* or cleared. Returns an unsubscribe function to stop listening.
|
|
185
|
+
*
|
|
186
|
+
* @param listener - Callback function receiving {@link AnnotationEvent} objects
|
|
187
|
+
* @returns Unsubscribe function - call it to remove the listener
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```ts
|
|
191
|
+
* const unsubscribe = store.on((event) => {
|
|
192
|
+
* if (event.type === 'annotation:set') {
|
|
193
|
+
* console.log(`Element ${event.elementId} annotated:`, event.annotation);
|
|
194
|
+
* }
|
|
195
|
+
* });
|
|
196
|
+
*
|
|
197
|
+
* store.set('btn-1', { description: 'Submit' });
|
|
198
|
+
* // Logs: "Element btn-1 annotated: { description: 'Submit', updatedAt: ... }"
|
|
199
|
+
*
|
|
200
|
+
* unsubscribe(); // Stop listening
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
on(listener: AnnotationListener): () => void;
|
|
204
|
+
/**
|
|
205
|
+
* Emit an event to all listeners.
|
|
206
|
+
*/
|
|
207
|
+
private emit;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Get the global annotation store singleton.
|
|
211
|
+
*/
|
|
212
|
+
declare function getGlobalAnnotationStore(): AnnotationStore;
|
|
213
|
+
/**
|
|
214
|
+
* Reset the global annotation store (primarily for testing).
|
|
215
|
+
*/
|
|
216
|
+
declare function resetGlobalAnnotationStore(): void;
|
|
217
|
+
|
|
218
|
+
export { AnnotationConfig, AnnotationCoverage, AnnotationEvent, type AnnotationListener, AnnotationStore, ElementAnnotation, getGlobalAnnotationStore, resetGlobalAnnotationStore };
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/annotations/types.ts
|
|
4
|
+
var ANNOTATION_CONFIG_VERSION = "1.0.0";
|
|
5
|
+
|
|
6
|
+
// src/annotations/store.ts
|
|
7
|
+
var AnnotationStore = class {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.store = /* @__PURE__ */ new Map();
|
|
10
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Get an annotation by element ID.
|
|
14
|
+
*/
|
|
15
|
+
get(elementId) {
|
|
16
|
+
return this.store.get(elementId);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Get all annotations as a record.
|
|
20
|
+
*/
|
|
21
|
+
getAll() {
|
|
22
|
+
const result = {};
|
|
23
|
+
for (const [id, annotation] of this.store) {
|
|
24
|
+
result[id] = annotation;
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Set an annotation for an element. Auto-sets `updatedAt`.
|
|
30
|
+
*/
|
|
31
|
+
set(elementId, annotation) {
|
|
32
|
+
const updated = {
|
|
33
|
+
...annotation,
|
|
34
|
+
updatedAt: Date.now()
|
|
35
|
+
};
|
|
36
|
+
this.store.set(elementId, updated);
|
|
37
|
+
this.emit({
|
|
38
|
+
type: "annotation:set",
|
|
39
|
+
elementId,
|
|
40
|
+
annotation: updated,
|
|
41
|
+
timestamp: Date.now()
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Delete an annotation by element ID.
|
|
46
|
+
*
|
|
47
|
+
* @returns true if the annotation existed and was deleted
|
|
48
|
+
*/
|
|
49
|
+
delete(elementId) {
|
|
50
|
+
const existed = this.store.delete(elementId);
|
|
51
|
+
if (existed) {
|
|
52
|
+
this.emit({
|
|
53
|
+
type: "annotation:deleted",
|
|
54
|
+
elementId,
|
|
55
|
+
timestamp: Date.now()
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return existed;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Check if an annotation exists for an element.
|
|
62
|
+
*/
|
|
63
|
+
has(elementId) {
|
|
64
|
+
return this.store.has(elementId);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get the number of stored annotations.
|
|
68
|
+
*/
|
|
69
|
+
get count() {
|
|
70
|
+
return this.store.size;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Clear all annotations.
|
|
74
|
+
*/
|
|
75
|
+
clear() {
|
|
76
|
+
this.store.clear();
|
|
77
|
+
this.emit({
|
|
78
|
+
type: "annotation:cleared",
|
|
79
|
+
timestamp: Date.now()
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Import annotations from a config object.
|
|
84
|
+
*
|
|
85
|
+
* Merges with existing annotations (new values overwrite per element ID).
|
|
86
|
+
*
|
|
87
|
+
* @returns Number of annotations imported
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* const config: AnnotationConfig = {
|
|
92
|
+
* version: '1.0.0',
|
|
93
|
+
* annotations: {
|
|
94
|
+
* 'btn-1': { description: 'Submit button', tags: ['form'] },
|
|
95
|
+
* 'input-1': { description: 'Name field' },
|
|
96
|
+
* },
|
|
97
|
+
* };
|
|
98
|
+
* const count = store.importConfig(config); // 2
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
importConfig(config) {
|
|
102
|
+
let count = 0;
|
|
103
|
+
for (const [id, annotation] of Object.entries(config.annotations)) {
|
|
104
|
+
this.store.set(id, {
|
|
105
|
+
...annotation,
|
|
106
|
+
updatedAt: annotation.updatedAt ?? Date.now()
|
|
107
|
+
});
|
|
108
|
+
count++;
|
|
109
|
+
}
|
|
110
|
+
this.emit({
|
|
111
|
+
type: "annotation:imported",
|
|
112
|
+
count,
|
|
113
|
+
timestamp: Date.now()
|
|
114
|
+
});
|
|
115
|
+
return count;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Export all annotations as a config object.
|
|
119
|
+
*
|
|
120
|
+
* The returned object can be serialized to JSON and saved to a file,
|
|
121
|
+
* then later re-imported with {@link importConfig}.
|
|
122
|
+
*
|
|
123
|
+
* @param metadata - Optional metadata to include (appName, description, etc.)
|
|
124
|
+
* @returns AnnotationConfig with all current annotations
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```ts
|
|
128
|
+
* const config = store.exportConfig({ appName: 'MyApp' });
|
|
129
|
+
* // config.version === '1.0.0'
|
|
130
|
+
* // config.annotations === { 'btn-1': { ... }, 'input-1': { ... } }
|
|
131
|
+
* // config.metadata === { appName: 'MyApp', exportedAt: 1706900000000 }
|
|
132
|
+
*
|
|
133
|
+
* // Save to file
|
|
134
|
+
* fs.writeFileSync('annotations.json', JSON.stringify(config, null, 2));
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
exportConfig(metadata) {
|
|
138
|
+
return {
|
|
139
|
+
version: ANNOTATION_CONFIG_VERSION,
|
|
140
|
+
annotations: this.getAll(),
|
|
141
|
+
metadata: {
|
|
142
|
+
...metadata,
|
|
143
|
+
exportedAt: Date.now()
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Compute annotation coverage against a set of known element IDs.
|
|
149
|
+
*
|
|
150
|
+
* Compares the store's annotations against the provided list of element IDs
|
|
151
|
+
* to determine what percentage of elements have been annotated.
|
|
152
|
+
*
|
|
153
|
+
* @param allElementIds - Array of all known element IDs in the UI
|
|
154
|
+
* @returns Coverage statistics including percentages and lists of annotated/unannotated IDs
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* ```ts
|
|
158
|
+
* store.set('btn-1', { description: 'Submit' });
|
|
159
|
+
* store.set('input-1', { description: 'Name' });
|
|
160
|
+
*
|
|
161
|
+
* const coverage = store.getCoverage(['btn-1', 'input-1', 'input-2', 'link-1']);
|
|
162
|
+
* // coverage.totalElements === 4
|
|
163
|
+
* // coverage.annotatedElements === 2
|
|
164
|
+
* // coverage.coveragePercent === 50
|
|
165
|
+
* // coverage.annotatedIds === ['btn-1', 'input-1']
|
|
166
|
+
* // coverage.unannotatedIds === ['input-2', 'link-1']
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
getCoverage(allElementIds) {
|
|
170
|
+
const annotatedIds = [];
|
|
171
|
+
const unannotatedIds = [];
|
|
172
|
+
for (const id of allElementIds) {
|
|
173
|
+
if (this.store.has(id)) {
|
|
174
|
+
annotatedIds.push(id);
|
|
175
|
+
} else {
|
|
176
|
+
unannotatedIds.push(id);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
const total = allElementIds.length;
|
|
180
|
+
return {
|
|
181
|
+
totalElements: total,
|
|
182
|
+
annotatedElements: annotatedIds.length,
|
|
183
|
+
coveragePercent: total > 0 ? annotatedIds.length / total * 100 : 0,
|
|
184
|
+
annotatedIds,
|
|
185
|
+
unannotatedIds,
|
|
186
|
+
timestamp: Date.now()
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Subscribe to annotation events.
|
|
191
|
+
*
|
|
192
|
+
* The listener is called whenever annotations are set, deleted, imported,
|
|
193
|
+
* or cleared. Returns an unsubscribe function to stop listening.
|
|
194
|
+
*
|
|
195
|
+
* @param listener - Callback function receiving {@link AnnotationEvent} objects
|
|
196
|
+
* @returns Unsubscribe function - call it to remove the listener
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* ```ts
|
|
200
|
+
* const unsubscribe = store.on((event) => {
|
|
201
|
+
* if (event.type === 'annotation:set') {
|
|
202
|
+
* console.log(`Element ${event.elementId} annotated:`, event.annotation);
|
|
203
|
+
* }
|
|
204
|
+
* });
|
|
205
|
+
*
|
|
206
|
+
* store.set('btn-1', { description: 'Submit' });
|
|
207
|
+
* // Logs: "Element btn-1 annotated: { description: 'Submit', updatedAt: ... }"
|
|
208
|
+
*
|
|
209
|
+
* unsubscribe(); // Stop listening
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
on(listener) {
|
|
213
|
+
this.listeners.add(listener);
|
|
214
|
+
return () => {
|
|
215
|
+
this.listeners.delete(listener);
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Emit an event to all listeners.
|
|
220
|
+
*/
|
|
221
|
+
emit(event) {
|
|
222
|
+
for (const listener of this.listeners) {
|
|
223
|
+
try {
|
|
224
|
+
listener(event);
|
|
225
|
+
} catch {
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
var globalStore = null;
|
|
231
|
+
function getGlobalAnnotationStore() {
|
|
232
|
+
if (!globalStore) {
|
|
233
|
+
globalStore = new AnnotationStore();
|
|
234
|
+
}
|
|
235
|
+
return globalStore;
|
|
236
|
+
}
|
|
237
|
+
function resetGlobalAnnotationStore() {
|
|
238
|
+
globalStore = null;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
exports.ANNOTATION_CONFIG_VERSION = ANNOTATION_CONFIG_VERSION;
|
|
242
|
+
exports.AnnotationStore = AnnotationStore;
|
|
243
|
+
exports.getGlobalAnnotationStore = getGlobalAnnotationStore;
|
|
244
|
+
exports.resetGlobalAnnotationStore = resetGlobalAnnotationStore;
|
|
245
|
+
//# sourceMappingURL=index.js.map
|
|
246
|
+
//# sourceMappingURL=index.js.map
|