@weave-apps/sdk 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/WeaveAPIClient.d.ts
CHANGED
|
@@ -81,6 +81,32 @@ export interface PaginatedResponse<T> {
|
|
|
81
81
|
/** Pagination metadata */
|
|
82
82
|
meta: PaginationMeta;
|
|
83
83
|
}
|
|
84
|
+
export interface FormDataScopeOptions {
|
|
85
|
+
/**
|
|
86
|
+
* Number of levels to traverse up from the current location before scoping results.
|
|
87
|
+
* 0 = current location, 1 = parent, 2 = grandparent, etc.
|
|
88
|
+
*/
|
|
89
|
+
locationLevelsUp?: number;
|
|
90
|
+
/**
|
|
91
|
+
* If true, ignores locationLevelsUp and scopes from the root location.
|
|
92
|
+
*/
|
|
93
|
+
locationIncludeToRoot?: boolean;
|
|
94
|
+
}
|
|
95
|
+
export interface CompanyMembersQueryOptions extends FormDataScopeOptions {
|
|
96
|
+
/**
|
|
97
|
+
* Optional target type. Defaults to app context when omitted.
|
|
98
|
+
*/
|
|
99
|
+
targetType?: 'app' | 'form' | 'workflow' | 'trigger' | 'startupUrlGroup';
|
|
100
|
+
/**
|
|
101
|
+
* Optional target identifier. Defaults to current app ID when omitted.
|
|
102
|
+
*/
|
|
103
|
+
targetId?: string;
|
|
104
|
+
offset?: number;
|
|
105
|
+
limit?: number;
|
|
106
|
+
search?: string;
|
|
107
|
+
role?: string;
|
|
108
|
+
status?: 'active' | 'inactive';
|
|
109
|
+
}
|
|
84
110
|
/**
|
|
85
111
|
* Weave API Client
|
|
86
112
|
* Provides methods for iframe apps to interact with Weave backend
|
|
@@ -197,6 +223,17 @@ export declare class WeaveAPIClient {
|
|
|
197
223
|
*/
|
|
198
224
|
delete: (appDataId: string) => Promise<void>;
|
|
199
225
|
};
|
|
226
|
+
/**
|
|
227
|
+
* Company member operations for app/user discovery scenarios.
|
|
228
|
+
*/
|
|
229
|
+
companyMembers: {
|
|
230
|
+
/**
|
|
231
|
+
* Get company members scoped by current user's location (supports ancestor traversal).
|
|
232
|
+
*
|
|
233
|
+
* Defaults to current app context (`targetType: 'app'`, `targetId` from app ID).
|
|
234
|
+
*/
|
|
235
|
+
getAll: (options?: CompanyMembersQueryOptions) => Promise<PaginatedResponse<any>>;
|
|
236
|
+
};
|
|
200
237
|
/**
|
|
201
238
|
* Forms API
|
|
202
239
|
*
|
|
@@ -232,7 +269,7 @@ export declare class WeaveAPIClient {
|
|
|
232
269
|
* console.log(response.data); // Array of form submissions
|
|
233
270
|
* ```
|
|
234
271
|
*/
|
|
235
|
-
getFormData: (formId: string) => Promise<PaginatedResponse<AppData>>;
|
|
272
|
+
getFormData: (formId: string, scopeOptions?: FormDataScopeOptions) => Promise<PaginatedResponse<AppData>>;
|
|
236
273
|
/**
|
|
237
274
|
* Submit form data
|
|
238
275
|
* Creates app data with targetType: 'form' and targetId: formId
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WeaveAPIClient.d.ts","sourceRoot":"","sources":["../src/WeaveAPIClient.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,0BAA0B;IAC1B,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,0BAA0B;IAC1B,IAAI,EAAE,cAAc,CAAC;CACtB;
|
|
1
|
+
{"version":3,"file":"WeaveAPIClient.d.ts","sourceRoot":"","sources":["../src/WeaveAPIClient.ts"],"names":[],"mappings":"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"}
|
package/dist/WeaveAPIClient.js
CHANGED
|
@@ -13,6 +13,8 @@ var APIOperation;
|
|
|
13
13
|
(function (APIOperation) {
|
|
14
14
|
// AI Service
|
|
15
15
|
APIOperation["AI_CHAT"] = "AI_CHAT";
|
|
16
|
+
// Company Members Service
|
|
17
|
+
APIOperation["COMPANY_MEMBERS_GET"] = "COMPANY_MEMBERS_GET";
|
|
16
18
|
// App Data Service
|
|
17
19
|
APIOperation["APP_DATA_GET_ALL"] = "APP_DATA_GET_ALL";
|
|
18
20
|
APIOperation["APP_DATA_CREATE"] = "APP_DATA_CREATE";
|
|
@@ -58,9 +60,9 @@ export class WeaveAPIClient {
|
|
|
58
60
|
return this.sendRequest(APIOperation.AI_CHAT, request);
|
|
59
61
|
}
|
|
60
62
|
};
|
|
61
|
-
//
|
|
63
|
+
// =========================================================================
|
|
62
64
|
// App Data Service
|
|
63
|
-
//
|
|
65
|
+
// =========================================================================
|
|
64
66
|
/**
|
|
65
67
|
* App Data operations - CRUD for app-specific data storage
|
|
66
68
|
*/
|
|
@@ -141,6 +143,22 @@ export class WeaveAPIClient {
|
|
|
141
143
|
return this.sendRequest(APIOperation.APP_DATA_DELETE, { appDataId });
|
|
142
144
|
}
|
|
143
145
|
};
|
|
146
|
+
// =========================================================================
|
|
147
|
+
// Company Members Service
|
|
148
|
+
// =========================================================================
|
|
149
|
+
/**
|
|
150
|
+
* Company member operations for app/user discovery scenarios.
|
|
151
|
+
*/
|
|
152
|
+
this.companyMembers = {
|
|
153
|
+
/**
|
|
154
|
+
* Get company members scoped by current user's location (supports ancestor traversal).
|
|
155
|
+
*
|
|
156
|
+
* Defaults to current app context (`targetType: 'app'`, `targetId` from app ID).
|
|
157
|
+
*/
|
|
158
|
+
getAll: async (options = {}) => {
|
|
159
|
+
return this.sendRequest(APIOperation.COMPANY_MEMBERS_GET, options);
|
|
160
|
+
},
|
|
161
|
+
};
|
|
144
162
|
/**
|
|
145
163
|
* Forms API
|
|
146
164
|
*
|
|
@@ -180,8 +198,11 @@ export class WeaveAPIClient {
|
|
|
180
198
|
* console.log(response.data); // Array of form submissions
|
|
181
199
|
* ```
|
|
182
200
|
*/
|
|
183
|
-
getFormData: async (formId) => {
|
|
184
|
-
return this.sendRequest(APIOperation.FORMS_GET_DATA, {
|
|
201
|
+
getFormData: async (formId, scopeOptions = {}) => {
|
|
202
|
+
return this.sendRequest(APIOperation.FORMS_GET_DATA, {
|
|
203
|
+
formId,
|
|
204
|
+
...scopeOptions,
|
|
205
|
+
});
|
|
185
206
|
},
|
|
186
207
|
/**
|
|
187
208
|
* Submit form data
|
package/package.json
CHANGED
package/templates/WEAVE_SPEC.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
Weave apps are **Web Components** that run in an **iframe** inside a browser extension sidebar. They interact with two secure APIs:
|
|
11
11
|
|
|
12
|
-
1. **Weave Backend API** - AI services
|
|
12
|
+
1. **Weave Backend API** - AI services, app data, forms, and company member discovery
|
|
13
13
|
2. **DOM Bridge API** - Parent page DOM manipulation
|
|
14
14
|
|
|
15
15
|
```
|
|
@@ -1808,8 +1808,9 @@ await axios.get('https://some-api.com');
|
|
|
1808
1808
|
✅ **ALLOWED:**
|
|
1809
1809
|
```typescript
|
|
1810
1810
|
// ✅ CORRECT - Use Weave API
|
|
1811
|
-
await weaveAPI.ai.chat({
|
|
1812
|
-
await weaveAPI.appData.create({
|
|
1811
|
+
await this.weaveAPI.ai.chat({ prompt: 'Summarize this page' });
|
|
1812
|
+
await this.weaveAPI.appData.create({ dataKey: 'key', data: {} });
|
|
1813
|
+
await this.weaveAPI.forms.getFormData('form-id-123', { locationLevelsUp: 1 });
|
|
1813
1814
|
|
|
1814
1815
|
// ✅ CORRECT - Use DOM Bridge
|
|
1815
1816
|
await weaveDOM.getText('h1');
|
|
@@ -2120,14 +2121,82 @@ interface AppData {
|
|
|
2120
2121
|
}
|
|
2121
2122
|
```
|
|
2122
2123
|
|
|
2124
|
+
### Forms Service
|
|
2125
|
+
|
|
2126
|
+
Use the Forms service for reading form definitions and working with form submissions.
|
|
2127
|
+
|
|
2128
|
+
```typescript
|
|
2129
|
+
class MyApp extends WeaveBaseApp {
|
|
2130
|
+
async loadFormsAndSubmissions(formId: string) {
|
|
2131
|
+
const apiClient = this.weaveAPI;
|
|
2132
|
+
|
|
2133
|
+
// List available forms for the current company
|
|
2134
|
+
const forms = await apiClient.forms.getAll();
|
|
2135
|
+
|
|
2136
|
+
// Fetch a single form definition
|
|
2137
|
+
const form = await apiClient.forms.get(formId);
|
|
2138
|
+
|
|
2139
|
+
// Fetch form submissions with location-aware scoping
|
|
2140
|
+
const submissions = await apiClient.forms.getFormData(formId, {
|
|
2141
|
+
locationLevelsUp: 1, // 0=current location, 1=parent, etc.
|
|
2142
|
+
locationIncludeToRoot: false // true = scope from root location
|
|
2143
|
+
});
|
|
2144
|
+
|
|
2145
|
+
return { forms: forms.data, form, submissions: submissions.data };
|
|
2146
|
+
}
|
|
2147
|
+
|
|
2148
|
+
async submitForm(formId: string, payload: Record<string, any>) {
|
|
2149
|
+
return this.weaveAPI.forms.submitFormData(formId, {
|
|
2150
|
+
dataKey: 'form_submission',
|
|
2151
|
+
data: payload,
|
|
2152
|
+
});
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
```
|
|
2156
|
+
|
|
2157
|
+
### Company Members Service
|
|
2158
|
+
|
|
2159
|
+
Use this service to fetch company members with optional location-based scope filters.
|
|
2160
|
+
|
|
2161
|
+
```typescript
|
|
2162
|
+
class MyApp extends WeaveBaseApp {
|
|
2163
|
+
async getVisiblePeopleForAppContext() {
|
|
2164
|
+
return this.weaveAPI.companyMembers.getAll({
|
|
2165
|
+
locationLevelsUp: 0,
|
|
2166
|
+
locationIncludeToRoot: false,
|
|
2167
|
+
offset: 0,
|
|
2168
|
+
limit: 100,
|
|
2169
|
+
});
|
|
2170
|
+
}
|
|
2171
|
+
|
|
2172
|
+
async getVisiblePeopleForForm(formId: string) {
|
|
2173
|
+
// Optional advanced scoping to a specific target type/id
|
|
2174
|
+
return this.weaveAPI.companyMembers.getAll({
|
|
2175
|
+
targetType: 'form',
|
|
2176
|
+
targetId: formId,
|
|
2177
|
+
locationLevelsUp: 2,
|
|
2178
|
+
locationIncludeToRoot: true,
|
|
2179
|
+
status: 'active',
|
|
2180
|
+
search: 'nurse',
|
|
2181
|
+
});
|
|
2182
|
+
}
|
|
2183
|
+
}
|
|
2184
|
+
```
|
|
2185
|
+
|
|
2186
|
+
`companyMembers.getAll(options)` supports:
|
|
2187
|
+
- `targetType?: 'app' | 'form' | 'workflow' | 'trigger' | 'startupUrlGroup'`
|
|
2188
|
+
- `targetId?: string`
|
|
2189
|
+
- `locationLevelsUp?: number`
|
|
2190
|
+
- `locationIncludeToRoot?: boolean`
|
|
2191
|
+
- `offset?: number`, `limit?: number`, `search?: string`, `role?: string`, `status?: 'active' | 'inactive'`
|
|
2192
|
+
|
|
2123
2193
|
### API Error Handling
|
|
2124
2194
|
|
|
2125
2195
|
All API methods return promises. Always use try-catch:
|
|
2126
2196
|
|
|
2127
2197
|
```typescript
|
|
2128
2198
|
try {
|
|
2129
|
-
const response = await weaveAPI.ai.chat({
|
|
2130
|
-
appName: 'my-app',
|
|
2199
|
+
const response = await this.weaveAPI.ai.chat({
|
|
2131
2200
|
prompt: 'Hello'
|
|
2132
2201
|
});
|
|
2133
2202
|
console.log(response.response);
|
|
@@ -2139,7 +2208,7 @@ try {
|
|
|
2139
2208
|
|
|
2140
2209
|
### API Timeouts
|
|
2141
2210
|
|
|
2142
|
-
- All API requests timeout after **
|
|
2211
|
+
- All API requests timeout after **3 minutes**
|
|
2143
2212
|
- Requests will reject with timeout error if exceeded
|
|
2144
2213
|
|
|
2145
2214
|
### Security & Scoping
|
|
@@ -4330,6 +4399,16 @@ customElements.define('page-title-editor', PageTitleEditor);
|
|
|
4330
4399
|
- `this.weaveAPI.appData.get(id)` - Get specific data
|
|
4331
4400
|
- `this.weaveAPI.appData.update(id, request)` - Update data
|
|
4332
4401
|
- `this.weaveAPI.appData.delete(id)` - Delete data
|
|
4402
|
+
- **Forms Service:**
|
|
4403
|
+
- `this.weaveAPI.forms.getAll()` - List forms
|
|
4404
|
+
- `this.weaveAPI.forms.get(formId)` - Get single form
|
|
4405
|
+
- `this.weaveAPI.forms.getFormData(formId, scopeOptions)` - Get submissions with optional location scope
|
|
4406
|
+
- `this.weaveAPI.forms.submitFormData(formId, payload)` - Submit form data
|
|
4407
|
+
- **Company Members Service:**
|
|
4408
|
+
- `this.weaveAPI.companyMembers.getAll(options)` - Get company members with optional location and target scoping
|
|
4409
|
+
- **Utilities:**
|
|
4410
|
+
- `this.weaveAPI.utils.htmlToMarkdown(html)`
|
|
4411
|
+
- `this.weaveAPI.utils.markdownToHtml(markdown)`
|
|
4333
4412
|
|
|
4334
4413
|
### DOM API Methods (`weaveDOM`)
|
|
4335
4414
|
- **Read:** `query`, `queryAll`, `getText`, `getAttribute`, `getValue`, `hasClass`, `getPageUrl`
|