@squadbase/vite-server 0.1.3-dev.9 → 0.1.4-dev.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/cli/index.js +14539 -29447
- package/dist/connectors/airtable-oauth.js +43 -6
- package/dist/connectors/airtable.js +43 -6
- package/dist/connectors/amplitude.js +43 -6
- package/dist/connectors/anthropic.js +43 -6
- package/dist/connectors/asana.js +43 -6
- package/dist/connectors/attio.js +522 -118
- package/dist/connectors/{google-ads-oauth.d.ts → backlog-api-key.d.ts} +1 -1
- package/dist/connectors/backlog-api-key.js +629 -0
- package/dist/connectors/customerio.js +43 -6
- package/dist/connectors/dbt.js +43 -6
- package/dist/connectors/{google-sheets-oauth.d.ts → gamma.d.ts} +1 -1
- package/dist/connectors/gamma.js +866 -0
- package/dist/connectors/gemini.js +43 -6
- package/dist/connectors/gmail-oauth.js +65 -8
- package/dist/connectors/gmail.js +104 -44
- package/dist/connectors/google-ads.d.ts +1 -1
- package/dist/connectors/google-ads.js +410 -332
- package/dist/connectors/google-analytics-oauth.js +61 -8
- package/dist/connectors/google-analytics.js +107 -292
- package/dist/connectors/google-calendar-oauth.js +61 -8
- package/dist/connectors/google-calendar.js +111 -58
- package/dist/connectors/{linkedin-ads-oauth.d.ts → google-docs.d.ts} +1 -1
- package/dist/connectors/google-docs.js +631 -0
- package/dist/connectors/google-drive.d.ts +5 -0
- package/dist/connectors/google-drive.js +875 -0
- package/dist/connectors/google-sheets.d.ts +1 -1
- package/dist/connectors/google-sheets.js +267 -285
- package/dist/connectors/google-slides.d.ts +5 -0
- package/dist/connectors/google-slides.js +663 -0
- package/dist/connectors/grafana.js +43 -6
- package/dist/connectors/hubspot-oauth.js +43 -6
- package/dist/connectors/hubspot.js +43 -6
- package/dist/connectors/intercom-oauth.js +43 -6
- package/dist/connectors/intercom.js +43 -6
- package/dist/connectors/jira-api-key.js +43 -6
- package/dist/connectors/kintone-api-token.js +256 -82
- package/dist/connectors/kintone.js +43 -6
- package/dist/connectors/linkedin-ads.js +188 -168
- package/dist/connectors/mailchimp-oauth.js +43 -6
- package/dist/connectors/mailchimp.js +43 -6
- package/dist/connectors/mixpanel.d.ts +5 -0
- package/dist/connectors/mixpanel.js +779 -0
- package/dist/connectors/notion-oauth.js +43 -6
- package/dist/connectors/notion.js +43 -6
- package/dist/connectors/openai.js +43 -6
- package/dist/connectors/sentry.d.ts +5 -0
- package/dist/connectors/sentry.js +761 -0
- package/dist/connectors/shopify-oauth.js +43 -6
- package/dist/connectors/shopify.js +43 -6
- package/dist/connectors/stripe-api-key.js +46 -7
- package/dist/connectors/stripe-oauth.js +43 -6
- package/dist/connectors/wix-store.js +43 -6
- package/dist/connectors/zendesk-oauth.js +43 -6
- package/dist/connectors/zendesk.js +43 -6
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4574 -3863
- package/dist/main.js +4572 -3862
- package/dist/vite-plugin.js +4572 -3862
- package/package.json +30 -12
- package/dist/connectors/google-ads-oauth.js +0 -890
- package/dist/connectors/google-sheets-oauth.js +0 -718
- package/dist/connectors/linkedin-ads-oauth.js +0 -848
package/dist/connectors/attio.js
CHANGED
|
@@ -78,72 +78,255 @@ function createClient(params) {
|
|
|
78
78
|
);
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
+
function buildQuery(params2) {
|
|
82
|
+
if (!params2) return "";
|
|
83
|
+
const entries = Object.entries(params2).filter(
|
|
84
|
+
([, v]) => v !== void 0 && v !== null
|
|
85
|
+
);
|
|
86
|
+
if (entries.length === 0) return "";
|
|
87
|
+
const usp = new URLSearchParams();
|
|
88
|
+
for (const [k, v] of entries) usp.set(k, String(v));
|
|
89
|
+
return `?${usp.toString()}`;
|
|
90
|
+
}
|
|
91
|
+
async function httpJson(method, path2, label, body) {
|
|
92
|
+
const res = await fetch(`${BASE_URL}${path2}`, {
|
|
93
|
+
method,
|
|
94
|
+
headers: authHeaders(),
|
|
95
|
+
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
96
|
+
});
|
|
97
|
+
await assertOk(res, label);
|
|
98
|
+
return await res.json();
|
|
99
|
+
}
|
|
100
|
+
async function httpVoid(method, path2, label) {
|
|
101
|
+
const res = await fetch(`${BASE_URL}${path2}`, {
|
|
102
|
+
method,
|
|
103
|
+
headers: authHeaders()
|
|
104
|
+
});
|
|
105
|
+
await assertOk(res, label);
|
|
106
|
+
}
|
|
107
|
+
function queryBody(options) {
|
|
108
|
+
const body = {};
|
|
109
|
+
if (options?.filter) body.filter = options.filter;
|
|
110
|
+
if (options?.sorts) body.sorts = options.sorts;
|
|
111
|
+
if (options?.limit) body.limit = options.limit;
|
|
112
|
+
if (options?.offset) body.offset = options.offset;
|
|
113
|
+
return body;
|
|
114
|
+
}
|
|
115
|
+
const enc = encodeURIComponent;
|
|
81
116
|
return {
|
|
82
117
|
request(path2, init) {
|
|
83
118
|
const url = `${BASE_URL}${path2}`;
|
|
84
119
|
const headers = new Headers(init?.headers);
|
|
85
120
|
headers.set("Authorization", `Bearer ${apiKey}`);
|
|
86
|
-
headers.
|
|
121
|
+
if (!headers.has("Content-Type"))
|
|
122
|
+
headers.set("Content-Type", "application/json");
|
|
87
123
|
return fetch(url, { ...init, headers });
|
|
88
124
|
},
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
125
|
+
// ---- Meta ----
|
|
126
|
+
self: () => httpJson("GET", "/self", "self"),
|
|
127
|
+
// ---- Objects ----
|
|
128
|
+
listObjects: () => httpJson("GET", "/objects", "listObjects"),
|
|
129
|
+
getObject: (object) => httpJson("GET", `/objects/${enc(object)}`, "getObject"),
|
|
130
|
+
listObjectViews: (object) => httpJson(
|
|
131
|
+
"GET",
|
|
132
|
+
`/objects/${enc(object)}/views`,
|
|
133
|
+
"listObjectViews"
|
|
134
|
+
),
|
|
135
|
+
// ---- Attributes ----
|
|
136
|
+
listAttributes: (object) => httpJson(
|
|
137
|
+
"GET",
|
|
138
|
+
`/objects/${enc(object)}/attributes`,
|
|
139
|
+
"listAttributes"
|
|
140
|
+
),
|
|
141
|
+
getAttribute: (object, attribute) => httpJson(
|
|
142
|
+
"GET",
|
|
143
|
+
`/objects/${enc(object)}/attributes/${enc(attribute)}`,
|
|
144
|
+
"getAttribute"
|
|
145
|
+
),
|
|
146
|
+
listSelectOptions: (object, attribute) => httpJson(
|
|
147
|
+
"GET",
|
|
148
|
+
`/objects/${enc(object)}/attributes/${enc(attribute)}/options`,
|
|
149
|
+
"listSelectOptions"
|
|
150
|
+
),
|
|
151
|
+
listStatuses: (object, attribute) => httpJson(
|
|
152
|
+
"GET",
|
|
153
|
+
`/objects/${enc(object)}/attributes/${enc(attribute)}/statuses`,
|
|
154
|
+
"listStatuses"
|
|
155
|
+
),
|
|
156
|
+
// ---- Records ----
|
|
157
|
+
queryRecords: (object, options) => httpJson(
|
|
158
|
+
"POST",
|
|
159
|
+
`/objects/${enc(object)}/records/query`,
|
|
160
|
+
"queryRecords",
|
|
161
|
+
queryBody(options)
|
|
162
|
+
),
|
|
163
|
+
getRecord: (object, recordId) => httpJson(
|
|
164
|
+
"GET",
|
|
165
|
+
`/objects/${enc(object)}/records/${enc(recordId)}`,
|
|
166
|
+
"getRecord"
|
|
167
|
+
),
|
|
168
|
+
createRecord: (object, data) => httpJson(
|
|
169
|
+
"POST",
|
|
170
|
+
`/objects/${enc(object)}/records`,
|
|
171
|
+
"createRecord",
|
|
172
|
+
{ data }
|
|
173
|
+
),
|
|
174
|
+
updateRecord: (object, recordId, data) => httpJson(
|
|
175
|
+
"PATCH",
|
|
176
|
+
`/objects/${enc(object)}/records/${enc(recordId)}`,
|
|
177
|
+
"updateRecord",
|
|
178
|
+
{ data }
|
|
179
|
+
),
|
|
180
|
+
overwriteRecord: (object, recordId, data) => httpJson(
|
|
181
|
+
"PUT",
|
|
182
|
+
`/objects/${enc(object)}/records/${enc(recordId)}`,
|
|
183
|
+
"overwriteRecord",
|
|
184
|
+
{ data }
|
|
185
|
+
),
|
|
186
|
+
deleteRecord: (object, recordId) => httpVoid(
|
|
187
|
+
"DELETE",
|
|
188
|
+
`/objects/${enc(object)}/records/${enc(recordId)}`,
|
|
189
|
+
"deleteRecord"
|
|
190
|
+
),
|
|
191
|
+
assertRecord: (object, data) => httpJson(
|
|
192
|
+
"PUT",
|
|
193
|
+
`/objects/${enc(object)}/records`,
|
|
194
|
+
"assertRecord",
|
|
195
|
+
{ data }
|
|
196
|
+
),
|
|
197
|
+
listRecordEntries: (object, recordId) => httpJson(
|
|
198
|
+
"GET",
|
|
199
|
+
`/objects/${enc(object)}/records/${enc(recordId)}/entries`,
|
|
200
|
+
"listRecordEntries"
|
|
201
|
+
),
|
|
202
|
+
// ---- Lists ----
|
|
203
|
+
listLists: () => httpJson("GET", "/lists", "listLists"),
|
|
204
|
+
getList: (listId) => httpJson("GET", `/lists/${enc(listId)}`, "getList"),
|
|
205
|
+
listListViews: (listId) => httpJson(
|
|
206
|
+
"GET",
|
|
207
|
+
`/lists/${enc(listId)}/views`,
|
|
208
|
+
"listListViews"
|
|
209
|
+
),
|
|
210
|
+
queryListEntries: (listId, options) => httpJson(
|
|
211
|
+
"POST",
|
|
212
|
+
`/lists/${enc(listId)}/entries/query`,
|
|
213
|
+
"queryListEntries",
|
|
214
|
+
queryBody(options)
|
|
215
|
+
),
|
|
216
|
+
getListEntry: (listId, entryId) => httpJson(
|
|
217
|
+
"GET",
|
|
218
|
+
`/lists/${enc(listId)}/entries/${enc(entryId)}`,
|
|
219
|
+
"getListEntry"
|
|
220
|
+
),
|
|
221
|
+
createListEntry: (listId, data) => httpJson(
|
|
222
|
+
"POST",
|
|
223
|
+
`/lists/${enc(listId)}/entries`,
|
|
224
|
+
"createListEntry",
|
|
225
|
+
{ data }
|
|
226
|
+
),
|
|
227
|
+
updateListEntry: (listId, entryId, data) => httpJson(
|
|
228
|
+
"PATCH",
|
|
229
|
+
`/lists/${enc(listId)}/entries/${enc(entryId)}`,
|
|
230
|
+
"updateListEntry",
|
|
231
|
+
{ data }
|
|
232
|
+
),
|
|
233
|
+
overwriteListEntry: (listId, entryId, data) => httpJson(
|
|
234
|
+
"PUT",
|
|
235
|
+
`/lists/${enc(listId)}/entries/${enc(entryId)}`,
|
|
236
|
+
"overwriteListEntry",
|
|
237
|
+
{ data }
|
|
238
|
+
),
|
|
239
|
+
deleteListEntry: (listId, entryId) => httpVoid(
|
|
240
|
+
"DELETE",
|
|
241
|
+
`/lists/${enc(listId)}/entries/${enc(entryId)}`,
|
|
242
|
+
"deleteListEntry"
|
|
243
|
+
),
|
|
244
|
+
assertListEntry: (listId, data) => httpJson(
|
|
245
|
+
"PUT",
|
|
246
|
+
`/lists/${enc(listId)}/entries`,
|
|
247
|
+
"assertListEntry",
|
|
248
|
+
{ data }
|
|
249
|
+
),
|
|
250
|
+
// ---- Workspace Members ----
|
|
251
|
+
listWorkspaceMembers: () => httpJson("GET", "/workspace_members", "listWorkspaceMembers"),
|
|
252
|
+
getWorkspaceMember: (workspaceMemberId) => httpJson(
|
|
253
|
+
"GET",
|
|
254
|
+
`/workspace_members/${enc(workspaceMemberId)}`,
|
|
255
|
+
"getWorkspaceMember"
|
|
256
|
+
),
|
|
257
|
+
async getWorkspaceMemberMap() {
|
|
258
|
+
const { data } = await httpJson(
|
|
259
|
+
"GET",
|
|
260
|
+
"/workspace_members",
|
|
261
|
+
"getWorkspaceMemberMap"
|
|
118
262
|
);
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
await assertOk(res, "getRecord");
|
|
128
|
-
return await res.json();
|
|
263
|
+
const map = /* @__PURE__ */ new Map();
|
|
264
|
+
for (const m of data) {
|
|
265
|
+
const id = m?.id?.workspace_member_id;
|
|
266
|
+
if (!id) continue;
|
|
267
|
+
const name = [m.first_name, m.last_name].filter(Boolean).join(" ").trim() || m.email_address || id;
|
|
268
|
+
map.set(id, { id, name, email: m.email_address });
|
|
269
|
+
}
|
|
270
|
+
return map;
|
|
129
271
|
},
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
272
|
+
// ---- Notes ----
|
|
273
|
+
listNotes: (options) => httpJson("GET", `/notes${buildQuery(options)}`, "listNotes"),
|
|
274
|
+
getNote: (noteId) => httpJson("GET", `/notes/${enc(noteId)}`, "getNote"),
|
|
275
|
+
createNote: (data) => httpJson("POST", "/notes", "createNote", { data }),
|
|
276
|
+
updateNote: (noteId, data) => httpJson("PATCH", `/notes/${enc(noteId)}`, "updateNote", {
|
|
277
|
+
data
|
|
278
|
+
}),
|
|
279
|
+
deleteNote: (noteId) => httpVoid("DELETE", `/notes/${enc(noteId)}`, "deleteNote"),
|
|
280
|
+
// ---- Tasks ----
|
|
281
|
+
listTasks: (options) => httpJson("GET", `/tasks${buildQuery(options)}`, "listTasks"),
|
|
282
|
+
getTask: (taskId) => httpJson("GET", `/tasks/${enc(taskId)}`, "getTask"),
|
|
283
|
+
createTask: (data) => httpJson("POST", "/tasks", "createTask", { data }),
|
|
284
|
+
updateTask: (taskId, data) => httpJson("PATCH", `/tasks/${enc(taskId)}`, "updateTask", {
|
|
285
|
+
data
|
|
286
|
+
}),
|
|
287
|
+
deleteTask: (taskId) => httpVoid("DELETE", `/tasks/${enc(taskId)}`, "deleteTask"),
|
|
288
|
+
// ---- Threads & Comments ----
|
|
289
|
+
listThreads: (options) => httpJson(
|
|
290
|
+
"GET",
|
|
291
|
+
`/threads${buildQuery(options)}`,
|
|
292
|
+
"listThreads"
|
|
293
|
+
),
|
|
294
|
+
getThread: (threadId) => httpJson("GET", `/threads/${enc(threadId)}`, "getThread"),
|
|
295
|
+
createComment: (data) => httpJson("POST", "/comments", "createComment", { data }),
|
|
296
|
+
getComment: (commentId) => httpJson("GET", `/comments/${enc(commentId)}`, "getComment"),
|
|
297
|
+
updateComment: (commentId, data) => httpJson(
|
|
298
|
+
"PATCH",
|
|
299
|
+
`/comments/${enc(commentId)}`,
|
|
300
|
+
"updateComment",
|
|
301
|
+
{ data }
|
|
302
|
+
),
|
|
303
|
+
deleteComment: (commentId) => httpVoid(
|
|
304
|
+
"DELETE",
|
|
305
|
+
`/comments/${enc(commentId)}`,
|
|
306
|
+
"deleteComment"
|
|
307
|
+
),
|
|
308
|
+
// ---- Webhooks ----
|
|
309
|
+
listWebhooks: () => httpJson("GET", "/webhooks", "listWebhooks"),
|
|
310
|
+
getWebhook: (webhookId) => httpJson("GET", `/webhooks/${enc(webhookId)}`, "getWebhook"),
|
|
311
|
+
createWebhook: (data) => httpJson("POST", "/webhooks", "createWebhook", { data }),
|
|
312
|
+
updateWebhook: (webhookId, data) => httpJson(
|
|
313
|
+
"PATCH",
|
|
314
|
+
`/webhooks/${enc(webhookId)}`,
|
|
315
|
+
"updateWebhook",
|
|
316
|
+
{ data }
|
|
317
|
+
),
|
|
318
|
+
deleteWebhook: (webhookId) => httpVoid(
|
|
319
|
+
"DELETE",
|
|
320
|
+
`/webhooks/${enc(webhookId)}`,
|
|
321
|
+
"deleteWebhook"
|
|
322
|
+
),
|
|
323
|
+
// ---- Meetings ----
|
|
324
|
+
listMeetings: (options) => httpJson(
|
|
325
|
+
"GET",
|
|
326
|
+
`/meetings${buildQuery(options)}`,
|
|
327
|
+
"listMeetings"
|
|
328
|
+
),
|
|
329
|
+
getMeeting: (meetingId) => httpJson("GET", `/meetings/${enc(meetingId)}`, "getMeeting")
|
|
147
330
|
};
|
|
148
331
|
}
|
|
149
332
|
|
|
@@ -229,21 +412,58 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
229
412
|
* Filters connections by connectorKey internally.
|
|
230
413
|
* Returns tools keyed as `${connectorKey}_${toolName}`.
|
|
231
414
|
*/
|
|
232
|
-
createTools(connections, config) {
|
|
415
|
+
createTools(connections, config, opts) {
|
|
233
416
|
const myConnections = connections.filter(
|
|
234
417
|
(c) => _ConnectorPlugin.deriveKey(c.connector.slug, c.connector.authType) === this.connectorKey
|
|
235
418
|
);
|
|
236
419
|
const result = {};
|
|
237
420
|
for (const t of Object.values(this.tools)) {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
421
|
+
const tool = t.createTool(myConnections, config);
|
|
422
|
+
const originalToModelOutput = tool.toModelOutput;
|
|
423
|
+
result[`${this.connectorKey}_${t.name}`] = {
|
|
424
|
+
...tool,
|
|
425
|
+
toModelOutput: async (options) => {
|
|
426
|
+
if (!originalToModelOutput) {
|
|
427
|
+
return opts.truncateOutput(options.output);
|
|
428
|
+
}
|
|
429
|
+
const modelOutput = await originalToModelOutput(options);
|
|
430
|
+
if (modelOutput.type === "text" || modelOutput.type === "json") {
|
|
431
|
+
return opts.truncateOutput(modelOutput.value);
|
|
432
|
+
}
|
|
433
|
+
return modelOutput;
|
|
434
|
+
}
|
|
435
|
+
};
|
|
242
436
|
}
|
|
243
437
|
return result;
|
|
244
438
|
}
|
|
245
439
|
static deriveKey(slug, authType) {
|
|
246
|
-
|
|
440
|
+
if (authType) return `${slug}-${authType}`;
|
|
441
|
+
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
442
|
+
// user-password
|
|
443
|
+
"postgresql": "user-password",
|
|
444
|
+
"mysql": "user-password",
|
|
445
|
+
"clickhouse": "user-password",
|
|
446
|
+
"kintone": "user-password",
|
|
447
|
+
"squadbase-db": "user-password",
|
|
448
|
+
// service-account
|
|
449
|
+
"snowflake": "service-account",
|
|
450
|
+
"bigquery": "service-account",
|
|
451
|
+
"google-analytics": "service-account",
|
|
452
|
+
"google-calendar": "service-account",
|
|
453
|
+
"aws-athena": "service-account",
|
|
454
|
+
"redshift": "service-account",
|
|
455
|
+
// api-key
|
|
456
|
+
"databricks": "api-key",
|
|
457
|
+
"dbt": "api-key",
|
|
458
|
+
"airtable": "api-key",
|
|
459
|
+
"openai": "api-key",
|
|
460
|
+
"gemini": "api-key",
|
|
461
|
+
"anthropic": "api-key",
|
|
462
|
+
"wix-store": "api-key"
|
|
463
|
+
};
|
|
464
|
+
const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
|
|
465
|
+
if (fallbackAuthType) return `${slug}-${fallbackAuthType}`;
|
|
466
|
+
return slug;
|
|
247
467
|
}
|
|
248
468
|
};
|
|
249
469
|
|
|
@@ -260,14 +480,18 @@ var AUTH_TYPES = {
|
|
|
260
480
|
// ../connectors/src/connectors/attio/setup.ts
|
|
261
481
|
var attioOnboarding = new ConnectorOnboarding({
|
|
262
482
|
dataOverviewInstructions: {
|
|
263
|
-
en: `1. Call attio_request with GET /objects to
|
|
264
|
-
2.
|
|
265
|
-
3. Call attio_request with POST /objects/
|
|
266
|
-
4.
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
483
|
+
en: `1. Call attio_request with GET /objects to discover the object slugs actually configured in this workspace (typically people, companies, deals, plus any custom objects).
|
|
484
|
+
2. For each object you plan to use, call attio_request with GET /objects/{slug}/attributes to explore its attributes
|
|
485
|
+
3. Call attio_request with POST /objects/{slug}/records/query with { "limit": 5 } to sample records
|
|
486
|
+
4. Call attio_request with GET /workspace_members (top-level, snake_case) to list team members. The response shape is \`{ data: [{ id: { workspace_member_id }, first_name, last_name, email_address, ... }] }\`. You need this mapping in dashboard handlers to resolve \`owner\` and other actor-reference fields (which return \`referenced_actor_id\`, not a name). Sample one record that has an \`owner\` and confirm the shape \`{ referenced_actor_type, referenced_actor_id }\`, then use \`client.getWorkspaceMemberMap()\` in handlers to resolve IDs to names.
|
|
487
|
+
5. If an endpoint later returns 403 (tasks / threads / webhooks / meetings require specific scopes), call GET /self to inspect the token's active scopes.
|
|
488
|
+
6. Explore lists via GET /lists as needed, and use /notes, /tasks, /threads, /comments, /webhooks, /meetings when the question requires them.`,
|
|
489
|
+
ja: `1. attio_request \u3067 GET /objects \u3092\u547C\u3073\u51FA\u3057\u3001\u3053\u306E\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306B\u5B9F\u5728\u3059\u308B\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8slug\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u901A\u5E38\u306F people / companies / deals\u3001\u52A0\u3048\u3066\u8A2D\u5B9A\u6E08\u307F\u306E\u30AB\u30B9\u30BF\u30E0\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\uFF09
|
|
490
|
+
2. \u4F7F\u3046\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3054\u3068\u306B attio_request \u3067 GET /objects/{slug}/attributes \u3092\u547C\u3073\u51FA\u3057\u3001\u5C5E\u6027\u3092\u78BA\u8A8D
|
|
491
|
+
3. attio_request \u3067 POST /objects/{slug}/records/query \u3092 { "limit": 5 } \u3067\u547C\u3073\u51FA\u3057\u3001\u30EC\u30B3\u30FC\u30C9\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0
|
|
492
|
+
4. attio_request \u3067 GET /workspace_members\uFF08\u30C8\u30C3\u30D7\u30EC\u30D9\u30EB\u3001\u30B9\u30CD\u30FC\u30AF\u30B1\u30FC\u30B9\uFF09\u3092\u547C\u3073\u51FA\u3057\u3001\u30C1\u30FC\u30E0\u30E1\u30F3\u30D0\u30FC\u4E00\u89A7\u3092\u53D6\u5F97\u3002\u30EC\u30B9\u30DD\u30F3\u30B9\u306F \`{ data: [{ id: { workspace_member_id }, first_name, last_name, email_address, ... }] }\` \u306E\u5F62\u5F0F\u3067\u3059\u3002\u3053\u306E\u30DE\u30C3\u30D4\u30F3\u30B0\u306F\u3001\`owner\` \u306A\u3069\u306E actor-reference \u30D5\u30A3\u30FC\u30EB\u30C9\uFF08\`referenced_actor_id\` \u3092\u8FD4\u3059\uFF09\u3092\u540D\u524D\u306B\u89E3\u6C7A\u3059\u308B\u305F\u3081\u306B\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9\u30CF\u30F3\u30C9\u30E9\u3067\u5FC5\u9808\u3067\u3059\u3002\`owner\` \u3092\u6301\u3064\u30EC\u30B3\u30FC\u30C9\u30921\u4EF6\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0\u3057\u3001\`{ referenced_actor_type, referenced_actor_id }\` \u306E\u5F62\u3092\u78BA\u8A8D\u3057\u305F\u4E0A\u3067\u3001\u30CF\u30F3\u30C9\u30E9\u3067\u306F \`client.getWorkspaceMemberMap()\` \u3092\u4F7F\u3063\u3066 ID \u2192 \u540D\u524D \u306B\u89E3\u6C7A\u3057\u3066\u304F\u3060\u3055\u3044
|
|
493
|
+
5. \u5F8C\u6BB5\u3067 403 \u304C\u51FA\u305F\u5834\u5408\uFF08tasks / threads / webhooks / meetings \u306A\u3069\u306F\u500B\u5225\u306E scope \u304C\u5FC5\u8981\uFF09\u306F\u3001GET /self \u3092\u547C\u3073\u51FA\u3057\u3066API\u30C8\u30FC\u30AF\u30F3\u306E\u6709\u52B9 scope \u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044
|
|
494
|
+
6. \u5FC5\u8981\u306B\u5FDC\u3058\u3066 GET /lists \u3067\u30EA\u30B9\u30C8\u3092\u63A2\u7D22\u3057\u3001/notes\u3001/tasks\u3001/threads\u3001/comments\u3001/webhooks\u3001/meetings \u3082\u6D3B\u7528\u3057\u3066\u304F\u3060\u3055\u3044`
|
|
271
495
|
}
|
|
272
496
|
});
|
|
273
497
|
|
|
@@ -280,11 +504,11 @@ var inputSchema = z.object({
|
|
|
280
504
|
"Brief description of what you intend to accomplish with this tool call"
|
|
281
505
|
),
|
|
282
506
|
connectionId: z.string().describe("ID of the Attio connection to use"),
|
|
283
|
-
method: z.enum(["GET", "POST", "PATCH", "DELETE"]).describe(
|
|
284
|
-
"HTTP method. GET for reading resources, POST for creating
|
|
507
|
+
method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).describe(
|
|
508
|
+
"HTTP method. GET for reading resources and list endpoints, POST for creating records/querying/asserting, PATCH for partial updates (append multiselect), PUT for full updates (overwrite multiselect), DELETE for removing."
|
|
285
509
|
),
|
|
286
510
|
path: z.string().describe(
|
|
287
|
-
"API path (
|
|
511
|
+
"Attio REST API path relative to https://api.attio.com/v2 (include the leading slash). Examples: '/self', '/objects', '/objects/people/attributes', '/objects/people/records/query', '/objects/companies/records/{record_id}', '/workspace_members', '/workspace_members/{workspace_member_id}', '/lists', '/lists/{list_id}/entries/query', '/notes', '/tasks', '/threads', '/comments', '/webhooks', '/meetings'."
|
|
288
512
|
),
|
|
289
513
|
body: z.record(z.string(), z.unknown()).optional().describe("Request body (JSON) for POST/PATCH requests")
|
|
290
514
|
});
|
|
@@ -301,10 +525,10 @@ var outputSchema = z.discriminatedUnion("success", [
|
|
|
301
525
|
]);
|
|
302
526
|
var requestTool = new ConnectorTool({
|
|
303
527
|
name: "request",
|
|
304
|
-
description: `Send authenticated requests to the Attio REST API.
|
|
528
|
+
description: `Send authenticated requests to the Attio REST API (base URL: https://api.attio.com/v2).
|
|
305
529
|
Authentication is handled automatically using the API Key (Bearer token).
|
|
306
|
-
Use this tool for
|
|
307
|
-
|
|
530
|
+
Use this tool for every Attio API interaction, including: querying records (people, companies, deals, and any custom objects configured in the workspace) and their attributes, listing/getting/creating/updating/deleting records and list entries, reading workspace members, and working with notes, tasks, threads, comments, webhooks, and meetings. Call GET /self to introspect the current API token.
|
|
531
|
+
Record queries use POST /objects/{object}/records/query with a JSON body containing \`filter\`, \`sorts\`, \`limit\`, and \`offset\`. Record updates use PATCH (append multiselect) or PUT (overwrite multiselect). Workspace members, tasks, webhooks, notes, threads, comments, and meetings live at top-level paths \u2014 the workspace-members path uses a snake_case underscore: /workspace_members.`,
|
|
308
532
|
inputSchema,
|
|
309
533
|
outputSchema,
|
|
310
534
|
async execute({ connectionId, method, path: path2, body }, connections) {
|
|
@@ -363,19 +587,69 @@ var attioConnector = new ConnectorPlugin({
|
|
|
363
587
|
systemPrompt: {
|
|
364
588
|
en: `### Tools
|
|
365
589
|
|
|
366
|
-
- \`attio_request\`: The only way to call the Attio REST API. Use it
|
|
590
|
+
- \`attio_request\`: The only way to call the Attio REST API. Use it for every Attio resource \u2014 records (people, companies, deals, and any custom objects configured in the workspace), their attributes, lists and entries, workspace members, notes, tasks, threads, comments, webhooks, and meetings. Authentication (Bearer token) is configured automatically. Querying records uses POST \`/objects/{object}/records/query\` with a JSON body. Use PATCH for partial updates (append multiselect) and PUT for full updates (overwrite multiselect). Always call GET \`/objects\` first to discover the actual object slugs in this workspace.
|
|
367
591
|
|
|
368
592
|
### Business Logic
|
|
369
593
|
|
|
370
|
-
The business logic type for this connector is "typescript". Use the connector SDK in your handler
|
|
594
|
+
The business logic type for this connector is "typescript". Use the connector SDK in your handler; authentication is handled by the SDK client.
|
|
371
595
|
|
|
372
596
|
SDK methods (client created via \`connection(connectionId)\`):
|
|
373
597
|
- \`client.request(path, init?)\` \u2014 low-level authenticated fetch
|
|
374
|
-
- \`client.
|
|
375
|
-
- \`client.
|
|
376
|
-
- \`client.
|
|
377
|
-
- \`client.getRecord(object, recordId)\`
|
|
378
|
-
- \`client.queryListEntries(listId, options?)\`
|
|
598
|
+
- \`client.self()\` \u2014 current API token introspection (GET /self) \u2014 returns workspace id, scopes, token status
|
|
599
|
+
- Objects: \`client.listObjects()\`, \`client.getObject(object)\`, \`client.listObjectViews(object)\`
|
|
600
|
+
- Attributes: \`client.listAttributes(object)\`, \`client.getAttribute(object, attribute)\`, \`client.listSelectOptions(object, attribute)\`, \`client.listStatuses(object, attribute)\`
|
|
601
|
+
- Records: \`client.queryRecords(object, options?)\`, \`client.getRecord(object, recordId)\`, \`client.createRecord(object, data)\`, \`client.updateRecord(object, recordId, data)\` (PATCH), \`client.overwriteRecord(object, recordId, data)\` (PUT), \`client.deleteRecord(object, recordId)\`, \`client.assertRecord(object, data)\`, \`client.listRecordEntries(object, recordId)\`
|
|
602
|
+
- Lists & entries: \`client.listLists()\`, \`client.getList(listId)\`, \`client.listListViews(listId)\`, \`client.queryListEntries(listId, options?)\`, \`client.getListEntry(listId, entryId)\`, \`client.createListEntry(listId, data)\`, \`client.updateListEntry(listId, entryId, data)\`, \`client.overwriteListEntry(listId, entryId, data)\`, \`client.deleteListEntry(listId, entryId)\`, \`client.assertListEntry(listId, data)\`
|
|
603
|
+
- Workspace members: \`client.listWorkspaceMembers()\`, \`client.getWorkspaceMember(workspaceMemberId)\`, \`client.getWorkspaceMemberMap()\` (returns \`Map<workspace_member_id, { id, name, email }>\` \u2014 use to resolve \`owner\` / actor-reference fields to names)
|
|
604
|
+
- Notes: \`client.listNotes(options?)\`, \`client.getNote(noteId)\`, \`client.createNote(data)\`, \`client.updateNote(noteId, data)\`, \`client.deleteNote(noteId)\`
|
|
605
|
+
- Tasks: \`client.listTasks(options?)\`, \`client.getTask(taskId)\`, \`client.createTask(data)\`, \`client.updateTask(taskId, data)\`, \`client.deleteTask(taskId)\`
|
|
606
|
+
- Threads & comments: \`client.listThreads(options?)\`, \`client.getThread(threadId)\`, \`client.createComment(data)\`, \`client.getComment(commentId)\`, \`client.updateComment(commentId, data)\`, \`client.deleteComment(commentId)\`
|
|
607
|
+
- Webhooks: \`client.listWebhooks()\`, \`client.getWebhook(webhookId)\`, \`client.createWebhook(data)\`, \`client.updateWebhook(webhookId, data)\`, \`client.deleteWebhook(webhookId)\`
|
|
608
|
+
- Meetings: \`client.listMeetings(options?)\`, \`client.getMeeting(meetingId)\`
|
|
609
|
+
|
|
610
|
+
### CRITICAL: Owner / Actor reference resolution
|
|
611
|
+
|
|
612
|
+
Fields like \`owner\` \u2014 and any \`actor-reference\` attribute \u2014 in Attio record \`values\` do **not** contain names. They carry actor IDs shaped like:
|
|
613
|
+
\`\`\`json
|
|
614
|
+
{ "referenced_actor_type": "workspace-member", "referenced_actor_id": "<workspace_member_id>" }
|
|
615
|
+
\`\`\`
|
|
616
|
+
Rendering that raw leaves opaque IDs in the UI (e.g. \`owner_name\` stays as a UUID). **Always** resolve these IDs to names before returning them. Do this by fetching workspace members once and joining on \`workspace_member_id\`.
|
|
617
|
+
|
|
618
|
+
- Use \`client.getWorkspaceMemberMap()\` \u2014 it returns a typed \`Map<workspace_member_id, { id, name, email }>\` ready to join with actor references.
|
|
619
|
+
- The workspace-member endpoint is top-level: \`GET /workspace_members\`.
|
|
620
|
+
- Fetch \`client.getWorkspaceMemberMap()\` in parallel with \`queryRecords\` via \`Promise.all\` (single fetch, joined in-memory).
|
|
621
|
+
|
|
622
|
+
Example \u2014 owner-based performance with names resolved:
|
|
623
|
+
\`\`\`ts
|
|
624
|
+
import type { Context } from "hono";
|
|
625
|
+
import { connection } from "@squadbase/vite-server/connectors/attio";
|
|
626
|
+
|
|
627
|
+
const attio = connection("<connectionId>");
|
|
628
|
+
|
|
629
|
+
export default async function handler(c: Context) {
|
|
630
|
+
const [{ data: deals }, memberMap] = await Promise.all([
|
|
631
|
+
attio.queryRecords("deals", { limit: 500 }),
|
|
632
|
+
attio.getWorkspaceMemberMap(),
|
|
633
|
+
]);
|
|
634
|
+
|
|
635
|
+
const byOwner = new Map<string, { owner_name: string; count: number }>();
|
|
636
|
+
for (const deal of deals) {
|
|
637
|
+
const values = (deal as { values?: Record<string, unknown[]> }).values ?? {};
|
|
638
|
+
const ownerCell = (values.owner ?? [])[0] as
|
|
639
|
+
| { referenced_actor_id?: string }
|
|
640
|
+
| undefined;
|
|
641
|
+
const ownerId = ownerCell?.referenced_actor_id ?? "unassigned";
|
|
642
|
+
const ownerName = memberMap.get(ownerId)?.name ?? "Unassigned";
|
|
643
|
+
const prev = byOwner.get(ownerId) ?? { owner_name: ownerName, count: 0 };
|
|
644
|
+
prev.count += 1;
|
|
645
|
+
byOwner.set(ownerId, prev);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
return c.json({ rows: Array.from(byOwner.values()) });
|
|
649
|
+
}
|
|
650
|
+
\`\`\`
|
|
651
|
+
|
|
652
|
+
### Minimal example
|
|
379
653
|
|
|
380
654
|
\`\`\`ts
|
|
381
655
|
import type { Context } from "hono";
|
|
@@ -400,39 +674,129 @@ export default async function handler(c: Context) {
|
|
|
400
674
|
- Base URL: \`https://api.attio.com/v2\`
|
|
401
675
|
- Authentication: Bearer token (handled automatically)
|
|
402
676
|
- Querying records uses POST with JSON body (not GET with query params)
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
-
|
|
411
|
-
-
|
|
412
|
-
-
|
|
413
|
-
-
|
|
414
|
-
- GET \`/
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
- \`
|
|
420
|
-
- \`
|
|
677
|
+
- Update semantics: PATCH appends multiselect values, PUT overwrites them
|
|
678
|
+
- Many list endpoints support \`limit\` and \`offset\` for pagination
|
|
679
|
+
|
|
680
|
+
#### Meta
|
|
681
|
+
- GET \`/self\` \u2014 current API token introspection (workspace id, scopes, token status)
|
|
682
|
+
|
|
683
|
+
#### Objects & Attributes
|
|
684
|
+
- GET \`/objects\` \u2014 list all objects in the workspace (default: people, companies, deals; plus any custom objects configured)
|
|
685
|
+
- GET \`/objects/{object}\` \u2014 get a single object
|
|
686
|
+
- GET \`/objects/{object}/views\` \u2014 list views for an object
|
|
687
|
+
- GET \`/objects/{object}/attributes\` \u2014 list attributes for an object
|
|
688
|
+
- GET \`/objects/{object}/attributes/{attribute}\` \u2014 get an attribute
|
|
689
|
+
- GET \`/objects/{object}/attributes/{attribute}/options\` \u2014 list select options
|
|
690
|
+
- GET \`/objects/{object}/attributes/{attribute}/statuses\` \u2014 list statuses
|
|
691
|
+
|
|
692
|
+
#### Records
|
|
693
|
+
- POST \`/objects/{object}/records/query\` \u2014 query records (filter / sorts / limit / offset)
|
|
694
|
+
- GET \`/objects/{object}/records/{record_id}\` \u2014 get a record
|
|
695
|
+
- POST \`/objects/{object}/records\` \u2014 create a record (body: \`{ "data": { ... } }\`)
|
|
696
|
+
- PATCH \`/objects/{object}/records/{record_id}\` \u2014 update (append multiselect)
|
|
697
|
+
- PUT \`/objects/{object}/records/{record_id}\` \u2014 update (overwrite multiselect)
|
|
698
|
+
- DELETE \`/objects/{object}/records/{record_id}\` \u2014 delete a record
|
|
699
|
+
- PUT \`/objects/{object}/records\` \u2014 assert (upsert) by matching attribute
|
|
700
|
+
- GET \`/objects/{object}/records/{record_id}/entries\` \u2014 list list entries that reference the record
|
|
701
|
+
|
|
702
|
+
#### Lists & Entries
|
|
703
|
+
- GET \`/lists\` \u2014 list all lists
|
|
704
|
+
- GET \`/lists/{list_id}\` \u2014 get a list
|
|
705
|
+
- GET \`/lists/{list_id}/views\` \u2014 list views for a list
|
|
706
|
+
- POST \`/lists/{list_id}/entries/query\` \u2014 query list entries
|
|
707
|
+
- GET \`/lists/{list_id}/entries/{entry_id}\` \u2014 get a list entry
|
|
708
|
+
- POST \`/lists/{list_id}/entries\` \u2014 create an entry
|
|
709
|
+
- PATCH \`/lists/{list_id}/entries/{entry_id}\` \u2014 update (append multiselect)
|
|
710
|
+
- PUT \`/lists/{list_id}/entries/{entry_id}\` \u2014 update (overwrite multiselect)
|
|
711
|
+
- DELETE \`/lists/{list_id}/entries/{entry_id}\` \u2014 delete an entry
|
|
712
|
+
- PUT \`/lists/{list_id}/entries\` \u2014 assert (upsert) a list entry by parent
|
|
713
|
+
|
|
714
|
+
#### Workspace Members
|
|
715
|
+
- GET \`/workspace_members\` \u2014 list every member of the workspace (team members, their roles, and access levels)
|
|
716
|
+
- GET \`/workspace_members/{workspace_member_id}\` \u2014 get a single workspace member
|
|
717
|
+
|
|
718
|
+
#### Notes, Tasks, Threads & Comments
|
|
719
|
+
- \`/notes\` (GET list, POST create) and \`/notes/{note_id}\` (GET / PATCH / DELETE). Filter list notes with \`?parent_object={object}&parent_record_id={id}\`.
|
|
720
|
+
- \`/tasks\` (GET list, POST create) and \`/tasks/{task_id}\` (GET / PATCH / DELETE)
|
|
721
|
+
- \`/threads\` (GET list) and \`/threads/{thread_id}\` (GET)
|
|
722
|
+
- \`/comments\` (POST create) and \`/comments/{comment_id}\` (GET / PATCH / DELETE)
|
|
723
|
+
|
|
724
|
+
#### Webhooks
|
|
725
|
+
- GET \`/webhooks\`, POST \`/webhooks\`, GET/PATCH/DELETE \`/webhooks/{webhook_id}\`
|
|
726
|
+
|
|
727
|
+
#### Meetings
|
|
728
|
+
- GET \`/meetings\`, GET \`/meetings/{meeting_id}\`
|
|
729
|
+
|
|
730
|
+
#### Query Body (for POST /objects/{object}/records/query and /lists/{list_id}/entries/query)
|
|
731
|
+
- \`filter\` \u2014 filter conditions
|
|
732
|
+
- \`sorts\` \u2014 array of sort specifications
|
|
733
|
+
- \`limit\` \u2014 max records per page (default 25)
|
|
734
|
+
- \`offset\` \u2014 pagination offset`,
|
|
421
735
|
ja: `### \u30C4\u30FC\u30EB
|
|
422
736
|
|
|
423
|
-
- \`attio_request\`: Attio REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30EC\u30B3\u30FC\u30C9\uFF08people\u3001companies\u3001deals\
|
|
737
|
+
- \`attio_request\`: Attio REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30EC\u30B3\u30FC\u30C9\uFF08people\u3001companies\u3001deals\u3001\u304A\u3088\u3073\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306B\u8A2D\u5B9A\u3055\u308C\u305F\u30AB\u30B9\u30BF\u30E0\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\uFF09\u3068\u305D\u306E\u5C5E\u6027\u3001\u30EA\u30B9\u30C8\u3068\u30A8\u30F3\u30C8\u30EA\u3001\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u30E1\u30F3\u30D0\u30FC\u3001\u30CE\u30FC\u30C8\u3001\u30BF\u30B9\u30AF\u3001\u30B9\u30EC\u30C3\u30C9\u3001\u30B3\u30E1\u30F3\u30C8\u3001Webhook\u3001\u30DF\u30FC\u30C6\u30A3\u30F3\u30B0\u306A\u3069\u3001\u3059\u3079\u3066\u306EAttio\u30EA\u30BD\u30FC\u30B9\u306E\u64CD\u4F5C\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08Bearer\u30C8\u30FC\u30AF\u30F3\uFF09\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002\u30EC\u30B3\u30FC\u30C9\u306E\u30AF\u30A8\u30EA\u306B\u306F POST \`/objects/{object}/records/query\` \u3092\u30D5\u30A3\u30EB\u30BF\u4ED8\u304D\u306EJSON\u30DC\u30C7\u30A3\u3067\u4F7F\u7528\u3057\u307E\u3059\u3002\u90E8\u5206\u66F4\u65B0\uFF08multiselect\u306E\u8FFD\u52A0\uFF09\u306B\u306FPATCH\u3001\u5168\u7F6E\u63DB\uFF08multiselect\u306E\u4E0A\u66F8\u304D\uFF09\u306B\u306FPUT\u3092\u4F7F\u3044\u307E\u3059\u3002**\u5FC5\u305A** \u6700\u521D\u306B GET \`/objects\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u3053\u306E\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306B\u5B9F\u5728\u3059\u308B\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8slug\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
|
424
738
|
|
|
425
739
|
### Business Logic
|
|
426
740
|
|
|
427
|
-
\u3053\u306E\u30B3\u30CD\u30AF\u30BF\u306E\u30D3\u30B8\u30CD\u30B9\u30ED\u30B8\u30C3\u30AF\u30BF\u30A4\u30D7\u306F "typescript" \u3067\u3059\u3002\u30CF\u30F3\u30C9\u30E9\u5185\u3067\u306F\u30B3\u30CD\u30AF\u30BFSDK\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002\
|
|
741
|
+
\u3053\u306E\u30B3\u30CD\u30AF\u30BF\u306E\u30D3\u30B8\u30CD\u30B9\u30ED\u30B8\u30C3\u30AF\u30BF\u30A4\u30D7\u306F "typescript" \u3067\u3059\u3002\u30CF\u30F3\u30C9\u30E9\u5185\u3067\u306F\u30B3\u30CD\u30AF\u30BFSDK\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u8A8D\u8A3C\u306FSDK\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u5074\u3067\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002
|
|
428
742
|
|
|
429
743
|
SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8):
|
|
430
744
|
- \`client.request(path, init?)\` \u2014 \u4F4E\u30EC\u30D9\u30EB\u306E\u8A8D\u8A3C\u4ED8\u304Dfetch
|
|
431
|
-
- \`client.
|
|
432
|
-
- \`client.
|
|
433
|
-
- \`client.
|
|
434
|
-
- \`client.getRecord(object, recordId)\`
|
|
435
|
-
- \`client.queryListEntries(listId, options?)\`
|
|
745
|
+
- \`client.identify()\` \u2014 \u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9/\u30C8\u30FC\u30AF\u30F3\u60C5\u5831\uFF08GET /meta/identify\uFF09
|
|
746
|
+
- Objects: \`client.listObjects()\`, \`client.getObject(object)\`, \`client.listObjectViews(object)\`
|
|
747
|
+
- Attributes: \`client.listAttributes(object)\`, \`client.getAttribute(object, attribute)\`, \`client.listSelectOptions(object, attribute)\`, \`client.listStatuses(object, attribute)\`
|
|
748
|
+
- Records: \`client.queryRecords(object, options?)\`, \`client.getRecord(object, recordId)\`, \`client.createRecord(object, data)\`, \`client.updateRecord(object, recordId, data)\` (PATCH), \`client.overwriteRecord(object, recordId, data)\` (PUT), \`client.deleteRecord(object, recordId)\`, \`client.assertRecord(object, data)\`, \`client.listRecordEntries(object, recordId)\`
|
|
749
|
+
- Lists & entries: \`client.listLists()\`, \`client.getList(listId)\`, \`client.listListViews(listId)\`, \`client.queryListEntries(listId, options?)\`, \`client.getListEntry(listId, entryId)\`, \`client.createListEntry(listId, data)\`, \`client.updateListEntry(listId, entryId, data)\`, \`client.overwriteListEntry(listId, entryId, data)\`, \`client.deleteListEntry(listId, entryId)\`, \`client.assertListEntry(listId, data)\`
|
|
750
|
+
- Workspace members: \`client.listWorkspaceMembers()\`, \`client.getWorkspaceMember(workspaceMemberId)\`, \`client.getWorkspaceMemberMap()\` (returns \`Map<workspace_member_id, { id, name, email }>\` \u2014 use to resolve \`owner\` / actor-reference fields to names)
|
|
751
|
+
- Notes: \`client.listNotes(options?)\`, \`client.getNote(noteId)\`, \`client.createNote(data)\`, \`client.updateNote(noteId, data)\`, \`client.deleteNote(noteId)\`
|
|
752
|
+
- Tasks: \`client.listTasks(options?)\`, \`client.getTask(taskId)\`, \`client.createTask(data)\`, \`client.updateTask(taskId, data)\`, \`client.deleteTask(taskId)\`
|
|
753
|
+
- Threads & comments: \`client.listThreads(options?)\`, \`client.getThread(threadId)\`, \`client.createComment(data)\`, \`client.getComment(commentId)\`, \`client.updateComment(commentId, data)\`, \`client.deleteComment(commentId)\`
|
|
754
|
+
- Webhooks: \`client.listWebhooks()\`, \`client.getWebhook(webhookId)\`, \`client.createWebhook(data)\`, \`client.updateWebhook(webhookId, data)\`, \`client.deleteWebhook(webhookId)\`
|
|
755
|
+
- Meetings: \`client.listMeetings(options?)\`, \`client.getMeeting(meetingId)\`
|
|
756
|
+
|
|
757
|
+
### \u91CD\u8981: Owner / Actor reference \u306E\u540D\u524D\u89E3\u6C7A
|
|
758
|
+
|
|
759
|
+
\u30EC\u30B3\u30FC\u30C9\u5024\u306E \`owner\`\uFF08\u304A\u3088\u3073 \`actor-reference\` \u578B\u306E\u5C5E\u6027\uFF09\u306F\u540D\u524D\u3067\u306F\u306A\u304F\u3001\u6B21\u306E\u3088\u3046\u306Aactor ID\u3092\u542B\u307F\u307E\u3059\uFF1A
|
|
760
|
+
\`\`\`json
|
|
761
|
+
{ "referenced_actor_type": "workspace-member", "referenced_actor_id": "<workspace_member_id>" }
|
|
762
|
+
\`\`\`
|
|
763
|
+
\u3053\u308C\u3092\u305D\u306E\u307E\u307E\u8FD4\u3059\u3068UI\u306B\u4E0D\u900F\u660E\u306AID\uFF08\`owner_name\` \u304CUUID\u306E\u307E\u307E\u7B49\uFF09\u304C\u8868\u793A\u3055\u308C\u307E\u3059\u3002**\u5FC5\u305A** \u30CF\u30F3\u30C9\u30E9\u5185\u3067 \`workspace_member_id\` \u2192 \u540D\u524D\u3078\u89E3\u6C7A\u3057\u3066\u304B\u3089\u8FD4\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
|
764
|
+
|
|
765
|
+
- \u89E3\u6C7A\u306B\u306F \`client.getWorkspaceMemberMap()\` \u3092\u4F7F\u3063\u3066\u304F\u3060\u3055\u3044\u3002\u3053\u308C\u306F \`Map<workspace_member_id, { id, name, email }>\` \u3092\u8FD4\u3057\u3001\u305D\u306E\u307E\u307Eactor reference\u3068\u7D50\u5408\u3067\u304D\u307E\u3059\u3002
|
|
766
|
+
- \u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u30E1\u30F3\u30D0\u30FC\u306E\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306F\u30C8\u30C3\u30D7\u30EC\u30D9\u30EB\u306E \`GET /workspace_members\` \u3067\u3059\u3002
|
|
767
|
+
- \`queryRecords\` \u3068 \`getWorkspaceMemberMap\` \u306F \`Promise.all\` \u3067\u4E26\u5217\u53D6\u5F97\u3057\u3001\u30E1\u30E2\u30EA\u4E0A\u3067\u7D50\u5408\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u90FD\u5EA6\u53D6\u5F97\u305B\u305A\u4E00\u62EC\u53D6\u5F97\uFF09\u3002
|
|
768
|
+
|
|
769
|
+
\u4F8B \u2014 owner\u3054\u3068\u306E\u30D1\u30D5\u30A9\u30FC\u30DE\u30F3\u30B9\uFF08\u540D\u524D\u89E3\u6C7A\u8FBC\u307F\uFF09:
|
|
770
|
+
\`\`\`ts
|
|
771
|
+
import type { Context } from "hono";
|
|
772
|
+
import { connection } from "@squadbase/vite-server/connectors/attio";
|
|
773
|
+
|
|
774
|
+
const attio = connection("<connectionId>");
|
|
775
|
+
|
|
776
|
+
export default async function handler(c: Context) {
|
|
777
|
+
const [{ data: deals }, memberMap] = await Promise.all([
|
|
778
|
+
attio.queryRecords("deals", { limit: 500 }),
|
|
779
|
+
attio.getWorkspaceMemberMap(),
|
|
780
|
+
]);
|
|
781
|
+
|
|
782
|
+
const byOwner = new Map<string, { owner_name: string; count: number }>();
|
|
783
|
+
for (const deal of deals) {
|
|
784
|
+
const values = (deal as { values?: Record<string, unknown[]> }).values ?? {};
|
|
785
|
+
const ownerCell = (values.owner ?? [])[0] as
|
|
786
|
+
| { referenced_actor_id?: string }
|
|
787
|
+
| undefined;
|
|
788
|
+
const ownerId = ownerCell?.referenced_actor_id ?? "unassigned";
|
|
789
|
+
const ownerName = memberMap.get(ownerId)?.name ?? "\u672A\u5272\u5F53";
|
|
790
|
+
const prev = byOwner.get(ownerId) ?? { owner_name: ownerName, count: 0 };
|
|
791
|
+
prev.count += 1;
|
|
792
|
+
byOwner.set(ownerId, prev);
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
return c.json({ rows: Array.from(byOwner.values()) });
|
|
796
|
+
}
|
|
797
|
+
\`\`\`
|
|
798
|
+
|
|
799
|
+
### \u6700\u5C0F\u30B5\u30F3\u30D7\u30EB
|
|
436
800
|
|
|
437
801
|
\`\`\`ts
|
|
438
802
|
import type { Context } from "hono";
|
|
@@ -457,20 +821,60 @@ export default async function handler(c: Context) {
|
|
|
457
821
|
- \u30D9\u30FC\u30B9URL: \`https://api.attio.com/v2\`
|
|
458
822
|
- \u8A8D\u8A3C: Bearer\u30C8\u30FC\u30AF\u30F3\uFF08\u81EA\u52D5\u8A2D\u5B9A\uFF09
|
|
459
823
|
- \u30EC\u30B3\u30FC\u30C9\u306E\u30AF\u30A8\u30EA\u306B\u306FGET\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF\u3067\u306F\u306A\u304FPOST\u3067JSON\u30DC\u30C7\u30A3\u3092\u4F7F\u7528\u3057\u307E\u3059
|
|
824
|
+
- \u66F4\u65B0\u30BB\u30DE\u30F3\u30C6\u30A3\u30AF\u30B9: PATCH\u306Fmultiselect\u5024\u3092\u8FFD\u52A0\u3001PUT\u306F\u4E0A\u66F8\u304D
|
|
825
|
+
- \u591A\u304F\u306E\u4E00\u89A7\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306F \`limit\` \u3068 \`offset\` \u306B\u3088\u308B\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u3092\u30B5\u30DD\u30FC\u30C8
|
|
826
|
+
|
|
827
|
+
#### Meta
|
|
828
|
+
- GET \`/self\` \u2014 \u73FE\u5728\u306EAPI\u30C8\u30FC\u30AF\u30F3\u306E\u60C5\u5831\uFF08workspace id / scopes / \u6709\u52B9\u72B6\u614B\uFF09
|
|
460
829
|
|
|
461
|
-
####
|
|
462
|
-
- GET \`/objects\` \u2014 \u5168\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\
|
|
830
|
+
#### Objects & Attributes
|
|
831
|
+
- GET \`/objects\` \u2014 \u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306E\u5168\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\uFF08\u30C7\u30D5\u30A9\u30EB\u30C8\u306F people / companies / deals\u3001\u52A0\u3048\u3066\u8A2D\u5B9A\u6E08\u307F\u306E\u30AB\u30B9\u30BF\u30E0\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\uFF09
|
|
832
|
+
- GET \`/objects/{object}\` \u2014 \u5358\u4E00\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u53D6\u5F97
|
|
833
|
+
- GET \`/objects/{object}/views\` \u2014 \u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u30D3\u30E5\u30FC\u4E00\u89A7
|
|
463
834
|
- GET \`/objects/{object}/attributes\` \u2014 \u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u5C5E\u6027\u4E00\u89A7
|
|
464
|
-
-
|
|
835
|
+
- GET \`/objects/{object}/attributes/{attribute}\` \u2014 \u5C5E\u6027\u306E\u53D6\u5F97
|
|
836
|
+
- GET \`/objects/{object}/attributes/{attribute}/options\` \u2014 \u30BB\u30EC\u30AF\u30C8\u9078\u629E\u80A2\u306E\u4E00\u89A7
|
|
837
|
+
- GET \`/objects/{object}/attributes/{attribute}/statuses\` \u2014 \u30B9\u30C6\u30FC\u30BF\u30B9\u4E00\u89A7
|
|
838
|
+
|
|
839
|
+
#### Records
|
|
840
|
+
- POST \`/objects/{object}/records/query\` \u2014 \u30EC\u30B3\u30FC\u30C9\u306E\u691C\u7D22\uFF08filter / sorts / limit / offset\uFF09
|
|
465
841
|
- GET \`/objects/{object}/records/{record_id}\` \u2014 \u30EC\u30B3\u30FC\u30C9\u306E\u53D6\u5F97
|
|
466
|
-
- POST \`/objects/{object}/records\` \u2014 \u30EC\u30B3\u30FC\u30C9\u306E\u4F5C\u6210
|
|
467
|
-
- PATCH \`/objects/{object}/records/{record_id}\` \u2014 \
|
|
842
|
+
- POST \`/objects/{object}/records\` \u2014 \u30EC\u30B3\u30FC\u30C9\u306E\u4F5C\u6210\uFF08body: \`{ "data": { ... } }\`\uFF09
|
|
843
|
+
- PATCH \`/objects/{object}/records/{record_id}\` \u2014 \u66F4\u65B0\uFF08multiselect\u8FFD\u52A0\uFF09
|
|
844
|
+
- PUT \`/objects/{object}/records/{record_id}\` \u2014 \u66F4\u65B0\uFF08multiselect\u4E0A\u66F8\u304D\uFF09
|
|
468
845
|
- DELETE \`/objects/{object}/records/{record_id}\` \u2014 \u30EC\u30B3\u30FC\u30C9\u306E\u524A\u9664
|
|
469
|
-
-
|
|
470
|
-
-
|
|
471
|
-
- GET \`/notes?parent_object={object}&parent_record_id={id}\` \u2014 \u30EC\u30B3\u30FC\u30C9\u306E\u30CE\u30FC\u30C8\u3092\u53D6\u5F97
|
|
846
|
+
- PUT \`/objects/{object}/records\` \u2014 \u4E00\u81F4\u5C5E\u6027\u306B\u3088\u308B\u30A2\u30B5\u30FC\u30C8\uFF08upsert\uFF09
|
|
847
|
+
- GET \`/objects/{object}/records/{record_id}/entries\` \u2014 \u30EC\u30B3\u30FC\u30C9\u3092\u53C2\u7167\u3059\u308B\u30EA\u30B9\u30C8\u30A8\u30F3\u30C8\u30EA\u4E00\u89A7
|
|
472
848
|
|
|
473
|
-
####
|
|
849
|
+
#### Lists & Entries
|
|
850
|
+
- GET \`/lists\` \u2014 \u30EA\u30B9\u30C8\u4E00\u89A7
|
|
851
|
+
- GET \`/lists/{list_id}\` \u2014 \u30EA\u30B9\u30C8\u306E\u53D6\u5F97
|
|
852
|
+
- GET \`/lists/{list_id}/views\` \u2014 \u30EA\u30B9\u30C8\u306E\u30D3\u30E5\u30FC\u4E00\u89A7
|
|
853
|
+
- POST \`/lists/{list_id}/entries/query\` \u2014 \u30EA\u30B9\u30C8\u30A8\u30F3\u30C8\u30EA\u306E\u691C\u7D22
|
|
854
|
+
- GET \`/lists/{list_id}/entries/{entry_id}\` \u2014 \u30EA\u30B9\u30C8\u30A8\u30F3\u30C8\u30EA\u306E\u53D6\u5F97
|
|
855
|
+
- POST \`/lists/{list_id}/entries\` \u2014 \u30A8\u30F3\u30C8\u30EA\u4F5C\u6210
|
|
856
|
+
- PATCH \`/lists/{list_id}/entries/{entry_id}\` \u2014 \u66F4\u65B0\uFF08multiselect\u8FFD\u52A0\uFF09
|
|
857
|
+
- PUT \`/lists/{list_id}/entries/{entry_id}\` \u2014 \u66F4\u65B0\uFF08multiselect\u4E0A\u66F8\u304D\uFF09
|
|
858
|
+
- DELETE \`/lists/{list_id}/entries/{entry_id}\` \u2014 \u30A8\u30F3\u30C8\u30EA\u524A\u9664
|
|
859
|
+
- PUT \`/lists/{list_id}/entries\` \u2014 \u89AA\u30EC\u30B3\u30FC\u30C9\u306B\u3088\u308B\u30A2\u30B5\u30FC\u30C8\uFF08upsert\uFF09
|
|
860
|
+
|
|
861
|
+
#### Workspace Members\uFF08\u30C1\u30FC\u30E0\u30E1\u30F3\u30D0\u30FC\uFF09
|
|
862
|
+
- GET \`/workspace_members\` \u2014 \u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306E\u5168\u30E1\u30F3\u30D0\u30FC\u4E00\u89A7\uFF08\u30ED\u30FC\u30EB\u3084\u30A2\u30AF\u30BB\u30B9\u30EC\u30D9\u30EB\u3092\u542B\u3080\uFF09
|
|
863
|
+
- GET \`/workspace_members/{workspace_member_id}\` \u2014 \u5358\u4E00\u30E1\u30F3\u30D0\u30FC\u306E\u53D6\u5F97
|
|
864
|
+
|
|
865
|
+
#### Notes, Tasks, Threads & Comments
|
|
866
|
+
- \`/notes\`\uFF08GET \u4E00\u89A7 / POST \u4F5C\u6210\uFF09\u3001\`/notes/{note_id}\`\uFF08GET / PATCH / DELETE\uFF09\u3002\u4E00\u89A7\u306F \`?parent_object={object}&parent_record_id={id}\` \u3067\u7D5E\u308A\u8FBC\u307F\u53EF\u80FD
|
|
867
|
+
- \`/tasks\`\uFF08GET \u4E00\u89A7 / POST \u4F5C\u6210\uFF09\u3001\`/tasks/{task_id}\`\uFF08GET / PATCH / DELETE\uFF09
|
|
868
|
+
- \`/threads\`\uFF08GET \u4E00\u89A7\uFF09\u3001\`/threads/{thread_id}\`\uFF08GET\uFF09
|
|
869
|
+
- \`/comments\`\uFF08POST \u4F5C\u6210\uFF09\u3001\`/comments/{comment_id}\`\uFF08GET / PATCH / DELETE\uFF09
|
|
870
|
+
|
|
871
|
+
#### Webhooks
|
|
872
|
+
- GET \`/webhooks\`\u3001POST \`/webhooks\`\u3001GET/PATCH/DELETE \`/webhooks/{webhook_id}\`
|
|
873
|
+
|
|
874
|
+
#### Meetings
|
|
875
|
+
- GET \`/meetings\`\u3001GET \`/meetings/{meeting_id}\`
|
|
876
|
+
|
|
877
|
+
#### \u30AF\u30A8\u30EA\u30DC\u30C7\u30A3 (POST /objects/{object}/records/query \u304A\u3088\u3073 /lists/{list_id}/entries/query)
|
|
474
878
|
- \`filter\` \u2014 \u30D5\u30A3\u30EB\u30BF\u6761\u4EF6
|
|
475
879
|
- \`sorts\` \u2014 \u30BD\u30FC\u30C8\u6307\u5B9A\u306E\u914D\u5217
|
|
476
880
|
- \`limit\` \u2014 \u30DA\u30FC\u30B8\u3042\u305F\u308A\u306E\u6700\u5927\u30EC\u30B3\u30FC\u30C9\u6570\uFF08\u30C7\u30D5\u30A9\u30EB\u30C825\uFF09
|