@weave-apps/sdk 0.1.5 → 0.1.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.
Files changed (2) hide show
  1. package/README.md +327 -52
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -10,6 +10,10 @@ Official SDK for building third-party applications for the Weave Platform.
10
10
  - ✅ **Project Scaffolding** - Quick start with `weave-init`
11
11
  - ✅ **DOM API** - Secure parent page DOM manipulation
12
12
  - ✅ **Shadow DOM Isolation** - Scoped styles and encapsulation
13
+ - ✅ **Background Services** - Run code without user interaction
14
+ - ✅ **Form Integration** - Auto-fill forms with extracted data
15
+ - ✅ **AI Integration** - Leverage AI for smart form filling
16
+ - ✅ **Data Persistence** - Store app data with the Weave API
13
17
 
14
18
  ## Quick Start
15
19
 
@@ -19,6 +23,7 @@ Official SDK for building third-party applications for the Weave Platform.
19
23
  npx weave-init my-custom-app
20
24
  cd my-custom-app
21
25
  npm install
26
+ npm run build
22
27
  ```
23
28
 
24
29
  ### 2. Develop Your App
@@ -26,7 +31,7 @@ npm install
26
31
  Edit `src/app.ts`:
27
32
 
28
33
  ```typescript
29
- import { WeaveBaseApp } from '@weave/app-sdk';
34
+ import { WeaveBaseApp } from '@weave-apps/sdk';
30
35
 
31
36
  class MyCustomApp extends WeaveBaseApp {
32
37
  constructor() {
@@ -39,24 +44,43 @@ class MyCustomApp extends WeaveBaseApp {
39
44
  author: 'Your Name',
40
45
  tags: ['custom']
41
46
  });
47
+
48
+ this.state = {
49
+ count: 0
50
+ };
42
51
  }
43
52
 
44
53
  protected render(): void {
45
54
  this.renderHTML(`
46
55
  <style>
47
- .container { padding: 20px; }
48
- button { padding: 10px 20px; }
56
+ .container {
57
+ padding: 20px;
58
+ font-family: system-ui, sans-serif;
59
+ }
60
+ button {
61
+ padding: 10px 20px;
62
+ background: #3b82f6;
63
+ color: white;
64
+ border: none;
65
+ border-radius: 6px;
66
+ cursor: pointer;
67
+ }
68
+ button:hover {
69
+ background: #2563eb;
70
+ }
49
71
  </style>
50
72
  <div class="container">
51
- <h1>Hello Weave!</h1>
52
- <button id="myBtn">Click Me</button>
73
+ <h1>Counter App</h1>
74
+ <p>Count: <span id="count">${this.state.count}</span></p>
75
+ <button id="incrementBtn">Increment</button>
53
76
  </div>
54
77
  `);
55
78
  }
56
79
 
57
80
  protected setupEventListeners(): void {
58
- this.query('#myBtn')?.addEventListener('click', () => {
59
- alert('Button clicked!');
81
+ this.query('#incrementBtn')?.addEventListener('click', () => {
82
+ this.setState({ count: this.state.count + 1 });
83
+ this.render();
60
84
  });
61
85
  }
62
86
  }
@@ -72,19 +96,19 @@ npm run build
72
96
 
73
97
  This runs:
74
98
  1. `tsc` - Compiles TypeScript to JavaScript
75
- 2. `weave-build` - Transpiles to clean, platform-ready JavaScript
99
+ 2. `weave-compile` - Transpiles to clean, platform-ready JavaScript
76
100
 
77
- Output: `dist/app.js` - ready for upload to Weave Platform.
101
+ Output: `dist/my-custom-app.js` - ready for upload to Weave Platform.
78
102
 
79
103
  ### 4. Upload to Weave
80
104
 
81
- Upload the generated `dist/app.js` file to the Weave Platform via the Enterprise Management Console.
105
+ Upload the generated `dist/my-custom-app.js` file to the Weave Platform via the Enterprise Management Console.
82
106
 
83
107
  ## API Reference
84
108
 
85
109
  ### WeaveBaseApp
86
110
 
87
- Base class for all Weave apps.
111
+ Base class for all Weave apps. Handles state management, rendering, and lifecycle hooks.
88
112
 
89
113
  #### Constructor
90
114
 
@@ -99,53 +123,153 @@ constructor(appInfo: WeaveAppInfo)
99
123
  - `category` (string) - App category
100
124
  - `description` (string) - Detailed description
101
125
  - `author` (string) - Author name
102
- - `tags` (string[]) - Optional tags
126
+ - `tags` (string[])` - Optional tags
127
+
128
+ #### Settings & State
129
+
130
+ Define typed settings and state:
131
+
132
+ ```typescript
133
+ interface MyAppSettings {
134
+ apiEndpoint?: string;
135
+ debugMode?: boolean;
136
+ }
137
+
138
+ interface MyAppState {
139
+ isLoading: boolean;
140
+ data: any;
141
+ }
142
+
143
+ class MyApp extends WeaveBaseApp<MyAppSettings, MyAppState> {
144
+ constructor() {
145
+ super({ /* ... */ });
146
+
147
+ this.state = {
148
+ isLoading: false,
149
+ data: null
150
+ };
151
+
152
+ // Access settings (injected from Enterprise Console)
153
+ console.log(this.appSettings?.apiEndpoint);
154
+ }
155
+ }
156
+ ```
103
157
 
104
158
  #### Methods to Implement
105
159
 
106
- ##### `render(): void`
160
+ ##### `render(): void | Promise<void>`
107
161
  Render your app's UI. Use `this.renderHTML()` to inject HTML.
108
162
 
163
+ ```typescript
164
+ protected async render(): Promise<void> {
165
+ this.renderHTML(`
166
+ <div>Content here</div>
167
+ `);
168
+ }
169
+ ```
170
+
109
171
  ##### `setupEventListeners(): void` (Optional)
110
172
  Setup event listeners for your app's elements.
111
173
 
174
+ ```typescript
175
+ protected setupEventListeners(): void {
176
+ this.query('#myBtn')?.addEventListener('click', () => {
177
+ // Handle click
178
+ });
179
+ }
180
+ ```
181
+
182
+ ##### `onBackgroundService(): void` (Optional)
183
+ Background service that runs when sidebar loads, even if app drawer isn't open.
184
+
185
+ ```typescript
186
+ async onBackgroundService(): Promise<void> {
187
+ const url = await window.weaveDOM.getPageUrl();
188
+ if (url.includes('mypage.com')) {
189
+ // Do something on background
190
+ }
191
+ }
192
+ ```
193
+
194
+ ##### `onUrlChange(newUrl: string): void` (Optional)
195
+ Called when the page URL changes (SPA navigation).
196
+
197
+ ```typescript
198
+ async onUrlChange(newUrl: string): Promise<void> {
199
+ if (newUrl.includes('form')) {
200
+ await this.checkAndInjectButton();
201
+ }
202
+ }
203
+ ```
204
+
112
205
  ##### `cleanup(): void` (Optional)
113
- Cleanup when app is removed from DOM.
206
+ Cleanup when app is removed from DOM. Clear intervals, listeners, watchers.
207
+
208
+ ```typescript
209
+ protected cleanup(): void {
210
+ if (this.myInterval) {
211
+ clearInterval(this.myInterval);
212
+ }
213
+ }
214
+ ```
114
215
 
115
216
  #### Helper Methods
116
217
 
117
218
  ##### `renderHTML(html: string): void`
118
219
  Renders HTML into the shadow root.
119
220
 
221
+ ```typescript
222
+ this.renderHTML('<h1>Hello</h1>');
223
+ ```
224
+
225
+ ##### `setState(updates: object): void`
226
+ Update app state (shallow merge).
227
+
228
+ ```typescript
229
+ this.setState({ isLoading: true, count: 5 });
230
+ ```
231
+
120
232
  ##### `query<T>(selector: string): T | null`
121
233
  Query a single element in shadow root.
122
234
 
235
+ ```typescript
236
+ const btn = this.query<HTMLButtonElement>('#myBtn');
237
+ ```
238
+
123
239
  ##### `queryAll<T>(selector: string): NodeListOf<T>`
124
240
  Query all matching elements in shadow root.
125
241
 
126
- ##### `setState(updates: object): void`
127
- Update app state.
242
+ ```typescript
243
+ const buttons = this.queryAll<HTMLButtonElement>('button');
244
+ ```
128
245
 
129
246
  ### WeaveDOMAPI
130
247
 
131
- API for interacting with the parent page DOM.
248
+ API for securely interacting with the parent page DOM. Available globally as `window.weaveDOM`.
132
249
 
133
- **Available globally as `window.weaveDOM`**
250
+ #### URL & Navigation
251
+
252
+ ```typescript
253
+ // Get current page URL
254
+ const url = await window.weaveDOM.getPageUrl();
255
+
256
+ // Open new tab
257
+ window.open(url, '_blank');
258
+ ```
134
259
 
135
260
  #### Read Operations
136
261
 
137
262
  ```typescript
138
263
  // Query element
139
264
  const element = await window.weaveDOM.query('h1');
265
+ // Returns: { exists: boolean, value?: string, outerHTML?: string }
140
266
 
141
267
  // Get text content
142
268
  const text = await window.weaveDOM.getText('h1');
143
269
 
144
- // Get attribute
145
- const href = await window.weaveDOM.getAttribute('a', 'href');
146
-
147
- // Check if element has class
148
- const hasClass = await window.weaveDOM.hasClass('.btn', 'active');
270
+ // Get form data
271
+ const formData = await window.weaveDOM.getFormData('form');
272
+ // Returns: { formId, formName, fields: [...] }
149
273
  ```
150
274
 
151
275
  #### Write Operations
@@ -154,70 +278,221 @@ const hasClass = await window.weaveDOM.hasClass('.btn', 'active');
154
278
  // Set text
155
279
  await window.weaveDOM.setText('h1', 'New Title');
156
280
 
157
- // Add class
158
- await window.weaveDOM.addClass('.btn', 'active');
281
+ // Set form field value
282
+ await window.weaveDOM.setFormFieldValue('#email', 'user@example.com', true);
159
283
 
160
- // Set style
161
- await window.weaveDOM.setStyle('h1', 'color', 'red');
284
+ // Click element
285
+ await window.weaveDOM.clickElement('.submit-btn');
162
286
 
163
- // Set attribute
164
- await window.weaveDOM.setAttribute('input', 'placeholder', 'Enter text');
287
+ // Remove element
288
+ await window.weaveDOM.removeElement('.old-element');
165
289
  ```
166
290
 
167
- #### DOM Manipulation
291
+ #### DOM Injection
168
292
 
169
293
  ```typescript
170
- // Insert HTML
171
- await window.weaveDOM.insertHTML('.container', '<p>New content</p>', 'beforeend');
294
+ // Inject HTML element
295
+ const elementId = await window.weaveDOM.injectElement(
296
+ '.target-container',
297
+ 'beforeend',
298
+ '<button id="my-btn">Click Me</button>',
299
+ {
300
+ onClick: async () => {
301
+ console.log('Button clicked!');
302
+ }
303
+ }
304
+ );
172
305
 
173
- // Remove element
174
- await window.weaveDOM.removeElement('.old-element');
306
+ // Remove injected element
307
+ await window.weaveDOM.removeInjectedElement(elementId);
308
+ ```
309
+
310
+ #### Event Listeners
311
+
312
+ ```typescript
313
+ // Start form click listener
314
+ await window.weaveDOM.startFormClickListener(async (data) => {
315
+ console.log('Form detected:', data.formData);
316
+ await window.weaveDOM.stopFormClickListener();
317
+ });
318
+
319
+ // Watch element for changes
320
+ const watcherId = await window.weaveDOM.watchElement(
321
+ '.target',
322
+ (data) => {
323
+ console.log('Element changed:', data.changeType);
324
+ },
325
+ { watchChildren: true, watchAttributes: true }
326
+ );
327
+
328
+ // Stop watching
329
+ await window.weaveDOM.unwatchElement(watcherId);
175
330
  ```
176
331
 
332
+ ### WeaveAPIClient
333
+
334
+ API for accessing backend services. Available as `this.weaveAPI` or `window.weaveAPI`.
335
+
336
+ #### App Data Management
337
+
338
+ ```typescript
339
+ // Create app data
340
+ await this.weaveAPI.appData.create({
341
+ dataKey: 'my-key',
342
+ data: { content: '...', timestamp: new Date() }
343
+ });
344
+
345
+ // Get all app data
346
+ const response = await this.weaveAPI.appData.getAll();
347
+ const allData = response.data || [];
348
+
349
+ // Update existing data
350
+ await this.weaveAPI.appData.update(dataId, {
351
+ dataKey: 'my-key',
352
+ data: { content: '...', timestamp: new Date() }
353
+ });
354
+ ```
355
+
356
+ #### AI Integration
357
+
358
+ ```typescript
359
+ // Call AI for text analysis
360
+ const response = await this.weaveAPI.ai.chat({
361
+ prompt: 'Extract patient name from this text: ...',
362
+ context: 'Medical form filling',
363
+ disableJsonExtraction: false
364
+ });
365
+
366
+ console.log(response.response);
367
+ ```
368
+
369
+ #### Utilities
370
+
371
+ ```typescript
372
+ // Convert HTML to Markdown
373
+ const markdown = window.weaveAPI.utils.htmlToMarkdown(htmlString);
374
+
375
+ // Convert Markdown to HTML
376
+ const html = window.weaveAPI.utils.markdownToHtml(markdownString);
377
+ ```
378
+
379
+ ## Real-World Example: Heidi to DCP
380
+
381
+ The included `DemoWeaveHeidiDcp` app demonstrates advanced features:
382
+
383
+ - **Background Services** - Injects button on Heidi scribe pages
384
+ - **URL Monitoring** - Reacts to SPA navigation
385
+ - **DOM Injection** - Adds UI elements to parent page
386
+ - **Form Detection** - Captures form structure and data
387
+ - **Data Persistence** - Stores consultation notes
388
+ - **AI Integration** - Auto-fills forms using AI
389
+ - **State Management** - Multi-stage workflow (idle → select-form → confirm → filling → success)
390
+
391
+ Check `src/app.ts` for the complete implementation.
392
+
393
+ ## Advanced Topics
394
+
395
+ ### Settings & Configuration
396
+
397
+ Settings are injected from the Enterprise Console and displayed as auto-extracted form fields:
398
+
399
+ ```typescript
400
+ interface MyAppSettings {
401
+ /**
402
+ * @description API endpoint for the service
403
+ * @default "https://api.example.com"
404
+ */
405
+ apiEndpoint?: string;
406
+
407
+ /**
408
+ * @description Enable debug logging
409
+ * @default false
410
+ */
411
+ debugMode?: boolean;
412
+ }
413
+
414
+ class MyApp extends WeaveBaseApp<MyAppSettings, MyAppState> {
415
+ constructor() {
416
+ super({ /* ... */ });
417
+
418
+ const endpoint = this.appSettings?.apiEndpoint || 'https://api.example.com';
419
+ const debug = this.appSettings?.debugMode || false;
420
+ }
421
+ }
422
+ ```
423
+
424
+ ### Error Handling
425
+
426
+ ```typescript
427
+ try {
428
+ const data = await this.weaveAPI.appData.getAll();
429
+ } catch (error) {
430
+ console.error('Failed to fetch data:', error);
431
+ this.setState({ error: error.message });
432
+ this.render();
433
+ }
434
+ ```
435
+
436
+ ### Performance Tips
437
+
438
+ - Use `async/await` for API calls to avoid blocking UI
439
+ - Debounce rapid state changes with timers
440
+ - Clear intervals and listeners in `cleanup()`
441
+ - Use `isCheckingContainer` flags to prevent overlapping async callbacks
442
+ - Minimize re-renders by updating state only when needed
443
+
177
444
  ## Build Process
178
445
 
179
- The build uses two commands:
446
+ The build pipeline has two steps:
447
+
448
+ 1. **TypeScript Compilation** (`tsc`)
449
+ - Compiles TypeScript to ES2020 JavaScript
450
+ - Outputs to `dist/`
180
451
 
181
- 1. **`tsc`** - TypeScript compiler (ES2020 target)
182
- 2. **`weave-build`** - SDK's build tool that:
183
- - Removes import statements (SDK is global)
184
- - Replaces SDK references with `window.*`
185
- - Adds header comment
186
- - Generates clean, readable JavaScript
452
+ 2. **SDK Build** (`weave-compile`)
453
+ - Removes SDK imports (SDK is global)
454
+ - Replaces SDK references with `window.*`
455
+ - Generates final output ready for deployment
187
456
 
188
- You can also run `weave-build` manually after compiling:
457
+ You can also run manually:
189
458
  ```bash
190
459
  tsc
191
- weave-build
460
+ weave-compile
192
461
  ```
193
462
 
194
463
  ## Security
195
464
 
196
465
  - ✅ **Selector Validation** - Prevents dangerous selectors
197
- - ✅ **HTML Sanitization** - Removes scripts and event handlers
466
+ - ✅ **HTML Sanitization** - Removes scripts and dangerous content
198
467
  - ✅ **Attribute Whitelist** - Blocks dangerous attributes
199
468
  - ✅ **Shadow DOM Isolation** - Scoped styles and encapsulation
200
- - ✅ **No Direct DOM Access** - All operations go through secure bridge
469
+ - ✅ **Secure Bridge** - All DOM operations go through security validation
201
470
 
202
471
  ## Project Structure
203
472
 
204
473
  ```
205
474
  my-app/
206
475
  ├── src/
207
- │ └── app.ts # Your TypeScript source
476
+ │ └── app.ts # Your TypeScript app
208
477
  ├── dist/
209
- │ └── app.js # Compiled JavaScript (upload this)
478
+ │ └── my-app.js # Compiled output (upload this)
210
479
  ├── package.json
211
480
  ├── tsconfig.json
481
+ ├── SIDEKICK_SPEC.md # AI assistant guide
212
482
  └── README.md
213
483
  ```
214
484
 
215
- **Note:** The build script (`weave-build`) is part of the SDK, not copied to your app.
485
+ ## Troubleshooting
486
+
487
+ ### "TypeScript not found in SDK"
488
+ Make sure to run `npm install` in your app directory after initialization.
216
489
 
217
- ## Examples
490
+ ### Form not filling
491
+ Check that selectors match the actual form structure. Use browser DevTools to inspect the form.
218
492
 
219
- See the [examples directory](./examples) for complete app examples.
493
+ ### Button not injecting
494
+ Verify the target selector exists before injection attempt. Check browser console for errors.
220
495
 
221
- ## License
496
+ ### State not persisting
497
+ Use `this.weaveAPI.appData.*` methods to persist data to backend. In-memory state is lost on refresh.
222
498
 
223
- MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weave-apps/sdk",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "SDK for building Weave Micro Apps",
5
5
  "publishConfig": {
6
6
  "access": "public"