@squadbase/vite-server 0.1.9-dev.b193824 → 0.1.9-dev.e22f810
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 +4989 -433
- package/dist/connectors/asana.js +15 -2
- package/dist/connectors/aws-billing.js +1 -1
- package/dist/connectors/azure-sql.d.ts +5 -0
- package/dist/connectors/azure-sql.js +682 -0
- package/dist/connectors/clickup.d.ts +5 -0
- package/dist/connectors/clickup.js +850 -0
- package/dist/connectors/freshdesk.d.ts +5 -0
- package/dist/connectors/freshdesk.js +842 -0
- package/dist/connectors/freshsales.d.ts +5 -0
- package/dist/connectors/freshsales.js +867 -0
- package/dist/connectors/freshservice.d.ts +5 -0
- package/dist/connectors/freshservice.js +813 -0
- package/dist/connectors/github.d.ts +5 -0
- package/dist/connectors/github.js +963 -0
- package/dist/connectors/gmail-oauth.js +15 -2
- package/dist/connectors/gmail.js +23 -14
- package/dist/connectors/google-audit-log.js +25 -14
- package/dist/connectors/google-calendar-oauth.js +18 -2
- package/dist/connectors/google-calendar.js +40 -26
- package/dist/connectors/google-docs.js +18 -2
- package/dist/connectors/google-drive.js +15 -2
- package/dist/connectors/google-search-console-oauth.d.ts +5 -0
- package/dist/connectors/google-search-console-oauth.js +954 -0
- package/dist/connectors/google-sheets.js +18 -2
- package/dist/connectors/google-slides.js +18 -2
- package/dist/connectors/jdbc.d.ts +5 -0
- package/dist/connectors/jdbc.js +21521 -0
- package/dist/connectors/monday.d.ts +5 -0
- package/dist/connectors/monday.js +853 -0
- package/dist/connectors/oracle.d.ts +5 -0
- package/dist/connectors/oracle.js +689 -0
- package/dist/connectors/semrush.d.ts +5 -0
- package/dist/connectors/semrush.js +825 -0
- package/dist/connectors/sqlserver.d.ts +5 -0
- package/dist/connectors/sqlserver.js +679 -0
- package/dist/connectors/supabase.d.ts +5 -0
- package/dist/connectors/supabase.js +582 -0
- package/dist/connectors/tiktok-ads.js +15 -2
- package/dist/index.js +5066 -510
- package/dist/main.js +4975 -419
- package/dist/vite-plugin.js +4975 -419
- package/package.json +56 -2
|
@@ -0,0 +1,853 @@
|
|
|
1
|
+
// ../connectors/src/parameter-definition.ts
|
|
2
|
+
var ParameterDefinition = class {
|
|
3
|
+
slug;
|
|
4
|
+
name;
|
|
5
|
+
description;
|
|
6
|
+
envVarBaseKey;
|
|
7
|
+
type;
|
|
8
|
+
secret;
|
|
9
|
+
required;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.slug = config.slug;
|
|
12
|
+
this.name = config.name;
|
|
13
|
+
this.description = config.description;
|
|
14
|
+
this.envVarBaseKey = config.envVarBaseKey;
|
|
15
|
+
this.type = config.type;
|
|
16
|
+
this.secret = config.secret;
|
|
17
|
+
this.required = config.required;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get the parameter value from a ConnectorConnectionObject.
|
|
21
|
+
*/
|
|
22
|
+
getValue(connection2) {
|
|
23
|
+
const param = connection2.parameters.find(
|
|
24
|
+
(p) => p.parameterSlug === this.slug
|
|
25
|
+
);
|
|
26
|
+
if (!param || param.value == null) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`Parameter "${this.slug}" not found or has no value in connection "${connection2.id}"`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return param.value;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Try to get the parameter value. Returns undefined if not found (for optional params).
|
|
35
|
+
*/
|
|
36
|
+
tryGetValue(connection2) {
|
|
37
|
+
const param = connection2.parameters.find(
|
|
38
|
+
(p) => p.parameterSlug === this.slug
|
|
39
|
+
);
|
|
40
|
+
if (!param || param.value == null) return void 0;
|
|
41
|
+
return param.value;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// ../connectors/src/connectors/monday/parameters.ts
|
|
46
|
+
var parameters = {
|
|
47
|
+
apiToken: new ParameterDefinition({
|
|
48
|
+
slug: "api-token",
|
|
49
|
+
name: "monday.com API Token",
|
|
50
|
+
description: "Personal API token generated from monday.com Profile > Developers > My access tokens. Account-scoped tokens (Admin > API) are also supported.",
|
|
51
|
+
envVarBaseKey: "MONDAY_API_TOKEN",
|
|
52
|
+
type: "text",
|
|
53
|
+
secret: true,
|
|
54
|
+
required: true
|
|
55
|
+
})
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// ../connectors/src/connectors/monday/sdk/index.ts
|
|
59
|
+
var BASE_URL = "https://api.monday.com/v2";
|
|
60
|
+
function createClient(params) {
|
|
61
|
+
const apiToken = params[parameters.apiToken.slug];
|
|
62
|
+
if (!apiToken) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`monday: missing required parameter: ${parameters.apiToken.slug}`
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
function authHeaders(extra) {
|
|
68
|
+
const headers = new Headers(extra);
|
|
69
|
+
headers.set("Authorization", apiToken);
|
|
70
|
+
headers.set("Content-Type", "application/json");
|
|
71
|
+
return headers;
|
|
72
|
+
}
|
|
73
|
+
async function gql(query, variables) {
|
|
74
|
+
const body = { query };
|
|
75
|
+
if (variables) body.variables = variables;
|
|
76
|
+
const res = await fetch(BASE_URL, {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: authHeaders(),
|
|
79
|
+
body: JSON.stringify(body)
|
|
80
|
+
});
|
|
81
|
+
const json = await res.json();
|
|
82
|
+
if (json.errors && json.errors.length > 0) {
|
|
83
|
+
throw new Error(
|
|
84
|
+
`monday graphql: ${json.errors.map((e) => e.message).join("; ")}`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
if (json.error_message) {
|
|
88
|
+
throw new Error(`monday graphql: ${json.error_message}`);
|
|
89
|
+
}
|
|
90
|
+
if (!json.data) {
|
|
91
|
+
throw new Error("monday graphql: no data in response");
|
|
92
|
+
}
|
|
93
|
+
return json.data;
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
graphql: gql,
|
|
97
|
+
request(init) {
|
|
98
|
+
const headers = new Headers(init?.headers);
|
|
99
|
+
headers.set("Authorization", apiToken);
|
|
100
|
+
headers.set("Content-Type", "application/json");
|
|
101
|
+
return fetch(BASE_URL, { ...init, headers });
|
|
102
|
+
},
|
|
103
|
+
async me() {
|
|
104
|
+
const result = await gql(
|
|
105
|
+
`{ me { id name email enabled is_admin is_guest is_view_only created_at account { id name } } }`
|
|
106
|
+
);
|
|
107
|
+
return result.me;
|
|
108
|
+
},
|
|
109
|
+
async listBoards(options) {
|
|
110
|
+
const result = await gql(
|
|
111
|
+
`query($limit: Int, $page: Int, $ids: [ID!], $workspace_ids: [ID!], $state: State) {
|
|
112
|
+
boards(limit: $limit, page: $page, ids: $ids, workspace_ids: $workspace_ids, state: $state) {
|
|
113
|
+
id name description state board_kind item_terminology updated_at
|
|
114
|
+
workspace { id name kind }
|
|
115
|
+
owners { id name }
|
|
116
|
+
}
|
|
117
|
+
}`,
|
|
118
|
+
{
|
|
119
|
+
limit: options?.limit ?? 25,
|
|
120
|
+
page: options?.page ?? 1,
|
|
121
|
+
ids: options?.ids?.map(String),
|
|
122
|
+
workspace_ids: options?.workspaceIds?.map(String),
|
|
123
|
+
state: options?.state ?? "active"
|
|
124
|
+
}
|
|
125
|
+
);
|
|
126
|
+
return result.boards;
|
|
127
|
+
},
|
|
128
|
+
async getBoard(boardId) {
|
|
129
|
+
const result = await gql(
|
|
130
|
+
`query($ids: [ID!]) {
|
|
131
|
+
boards(ids: $ids) {
|
|
132
|
+
id name description state board_kind item_terminology updated_at
|
|
133
|
+
workspace { id name kind }
|
|
134
|
+
owners { id name }
|
|
135
|
+
groups { id title color position }
|
|
136
|
+
columns { id title type description settings_str archived }
|
|
137
|
+
tags { id name color }
|
|
138
|
+
}
|
|
139
|
+
}`,
|
|
140
|
+
{ ids: [String(boardId)] }
|
|
141
|
+
);
|
|
142
|
+
const board = result.boards?.[0];
|
|
143
|
+
if (!board) {
|
|
144
|
+
throw new Error(`monday: board ${boardId} not found`);
|
|
145
|
+
}
|
|
146
|
+
return board;
|
|
147
|
+
},
|
|
148
|
+
async listItems(boardId, options) {
|
|
149
|
+
const result = await gql(
|
|
150
|
+
`query($ids: [ID!], $limit: Int, $cursor: String) {
|
|
151
|
+
boards(ids: $ids) {
|
|
152
|
+
items_page(limit: $limit, cursor: $cursor) {
|
|
153
|
+
cursor
|
|
154
|
+
items {
|
|
155
|
+
id name state created_at updated_at
|
|
156
|
+
group { id title }
|
|
157
|
+
creator { id name }
|
|
158
|
+
column_values { id type text value column { title } }
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}`,
|
|
163
|
+
{
|
|
164
|
+
ids: [String(boardId)],
|
|
165
|
+
limit: options?.limit ?? 25,
|
|
166
|
+
cursor: options?.cursor ?? null
|
|
167
|
+
}
|
|
168
|
+
);
|
|
169
|
+
const page = result.boards?.[0]?.items_page;
|
|
170
|
+
if (!page) {
|
|
171
|
+
throw new Error(`monday: board ${boardId} not found`);
|
|
172
|
+
}
|
|
173
|
+
return page;
|
|
174
|
+
},
|
|
175
|
+
async getItem(itemId) {
|
|
176
|
+
const result = await gql(
|
|
177
|
+
`query($ids: [ID!]) {
|
|
178
|
+
items(ids: $ids) {
|
|
179
|
+
id name state created_at updated_at
|
|
180
|
+
board { id name }
|
|
181
|
+
group { id title }
|
|
182
|
+
creator { id name }
|
|
183
|
+
column_values { id type text value column { title } }
|
|
184
|
+
}
|
|
185
|
+
}`,
|
|
186
|
+
{ ids: [String(itemId)] }
|
|
187
|
+
);
|
|
188
|
+
const item = result.items?.[0];
|
|
189
|
+
if (!item) {
|
|
190
|
+
throw new Error(`monday: item ${itemId} not found`);
|
|
191
|
+
}
|
|
192
|
+
return item;
|
|
193
|
+
},
|
|
194
|
+
async createItem(input) {
|
|
195
|
+
const result = await gql(
|
|
196
|
+
`mutation($boardId: ID!, $itemName: String!, $groupId: String, $columnValues: JSON, $createLabelsIfMissing: Boolean) {
|
|
197
|
+
create_item(
|
|
198
|
+
board_id: $boardId,
|
|
199
|
+
item_name: $itemName,
|
|
200
|
+
group_id: $groupId,
|
|
201
|
+
column_values: $columnValues,
|
|
202
|
+
create_labels_if_missing: $createLabelsIfMissing
|
|
203
|
+
) { id name state created_at }
|
|
204
|
+
}`,
|
|
205
|
+
{
|
|
206
|
+
boardId: String(input.boardId),
|
|
207
|
+
itemName: input.itemName,
|
|
208
|
+
groupId: input.groupId,
|
|
209
|
+
columnValues: input.columnValues ? JSON.stringify(input.columnValues) : void 0,
|
|
210
|
+
createLabelsIfMissing: input.createLabelsIfMissing ?? false
|
|
211
|
+
}
|
|
212
|
+
);
|
|
213
|
+
return result.create_item;
|
|
214
|
+
},
|
|
215
|
+
async listUsers(options) {
|
|
216
|
+
const result = await gql(
|
|
217
|
+
`query($limit: Int, $page: Int, $kind: UserKind) {
|
|
218
|
+
users(limit: $limit, page: $page, kind: $kind) {
|
|
219
|
+
id name email enabled is_admin is_guest is_view_only created_at
|
|
220
|
+
}
|
|
221
|
+
}`,
|
|
222
|
+
{
|
|
223
|
+
limit: options?.limit ?? 25,
|
|
224
|
+
page: options?.page ?? 1,
|
|
225
|
+
kind: options?.kind ?? "all"
|
|
226
|
+
}
|
|
227
|
+
);
|
|
228
|
+
return result.users;
|
|
229
|
+
},
|
|
230
|
+
async listWorkspaces(options) {
|
|
231
|
+
const result = await gql(
|
|
232
|
+
`query($limit: Int, $page: Int) {
|
|
233
|
+
workspaces(limit: $limit, page: $page) {
|
|
234
|
+
id name kind description state created_at
|
|
235
|
+
}
|
|
236
|
+
}`,
|
|
237
|
+
{
|
|
238
|
+
limit: options?.limit ?? 25,
|
|
239
|
+
page: options?.page ?? 1
|
|
240
|
+
}
|
|
241
|
+
);
|
|
242
|
+
return result.workspaces;
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// ../connectors/src/connector-onboarding.ts
|
|
248
|
+
var ConnectorOnboarding = class {
|
|
249
|
+
/** Phase 1: Connection setup instructions (optional — some connectors don't need this) */
|
|
250
|
+
connectionSetupInstructions;
|
|
251
|
+
/** Phase 2: Data overview instructions */
|
|
252
|
+
dataOverviewInstructions;
|
|
253
|
+
constructor(config) {
|
|
254
|
+
this.connectionSetupInstructions = config.connectionSetupInstructions;
|
|
255
|
+
this.dataOverviewInstructions = config.dataOverviewInstructions;
|
|
256
|
+
}
|
|
257
|
+
getConnectionSetupPrompt(language) {
|
|
258
|
+
return this.connectionSetupInstructions?.[language] ?? null;
|
|
259
|
+
}
|
|
260
|
+
getDataOverviewInstructions(language) {
|
|
261
|
+
return this.dataOverviewInstructions[language];
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
// ../connectors/src/connector-tool.ts
|
|
266
|
+
var ConnectorTool = class {
|
|
267
|
+
name;
|
|
268
|
+
description;
|
|
269
|
+
inputSchema;
|
|
270
|
+
outputSchema;
|
|
271
|
+
_execute;
|
|
272
|
+
constructor(config) {
|
|
273
|
+
this.name = config.name;
|
|
274
|
+
this.description = config.description;
|
|
275
|
+
this.inputSchema = config.inputSchema;
|
|
276
|
+
this.outputSchema = config.outputSchema;
|
|
277
|
+
this._execute = config.execute;
|
|
278
|
+
}
|
|
279
|
+
createTool(connections, config) {
|
|
280
|
+
return {
|
|
281
|
+
description: this.description,
|
|
282
|
+
inputSchema: this.inputSchema,
|
|
283
|
+
outputSchema: this.outputSchema,
|
|
284
|
+
execute: (input) => this._execute(input, connections, config)
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
// ../connectors/src/connector-plugin.ts
|
|
290
|
+
var ConnectorPlugin = class _ConnectorPlugin {
|
|
291
|
+
slug;
|
|
292
|
+
authType;
|
|
293
|
+
name;
|
|
294
|
+
description;
|
|
295
|
+
iconUrl;
|
|
296
|
+
parameters;
|
|
297
|
+
releaseFlag;
|
|
298
|
+
proxyPolicy;
|
|
299
|
+
experimentalAttributes;
|
|
300
|
+
categories;
|
|
301
|
+
onboarding;
|
|
302
|
+
systemPrompt;
|
|
303
|
+
tools;
|
|
304
|
+
query;
|
|
305
|
+
checkConnection;
|
|
306
|
+
constructor(config) {
|
|
307
|
+
this.slug = config.slug;
|
|
308
|
+
this.authType = config.authType;
|
|
309
|
+
this.name = config.name;
|
|
310
|
+
this.description = config.description;
|
|
311
|
+
this.iconUrl = config.iconUrl;
|
|
312
|
+
this.parameters = config.parameters;
|
|
313
|
+
this.releaseFlag = config.releaseFlag;
|
|
314
|
+
this.proxyPolicy = config.proxyPolicy;
|
|
315
|
+
this.experimentalAttributes = config.experimentalAttributes;
|
|
316
|
+
this.categories = config.categories ?? [];
|
|
317
|
+
this.onboarding = config.onboarding;
|
|
318
|
+
this.systemPrompt = config.systemPrompt;
|
|
319
|
+
this.tools = config.tools;
|
|
320
|
+
this.query = config.query;
|
|
321
|
+
this.checkConnection = config.checkConnection;
|
|
322
|
+
}
|
|
323
|
+
get connectorKey() {
|
|
324
|
+
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Create tools for connections that belong to this connector.
|
|
328
|
+
* Filters connections by connectorKey internally.
|
|
329
|
+
* Returns tools keyed as `${connectorKey}_${toolName}`.
|
|
330
|
+
*/
|
|
331
|
+
createTools(connections, config, opts) {
|
|
332
|
+
const myConnections = connections.filter(
|
|
333
|
+
(c) => _ConnectorPlugin.deriveKey(c.connector.slug, c.connector.authType) === this.connectorKey
|
|
334
|
+
);
|
|
335
|
+
const result = {};
|
|
336
|
+
for (const t of Object.values(this.tools)) {
|
|
337
|
+
const tool = t.createTool(myConnections, config);
|
|
338
|
+
const originalToModelOutput = tool.toModelOutput;
|
|
339
|
+
result[`${this.connectorKey}_${t.name}`] = {
|
|
340
|
+
...tool,
|
|
341
|
+
toModelOutput: async (options) => {
|
|
342
|
+
if (!originalToModelOutput) {
|
|
343
|
+
return opts.truncateOutput(options.output);
|
|
344
|
+
}
|
|
345
|
+
const modelOutput = await originalToModelOutput(options);
|
|
346
|
+
if (modelOutput.type === "text" || modelOutput.type === "json") {
|
|
347
|
+
return opts.truncateOutput(modelOutput.value);
|
|
348
|
+
}
|
|
349
|
+
return modelOutput;
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
return result;
|
|
354
|
+
}
|
|
355
|
+
static deriveKey(slug, authType) {
|
|
356
|
+
if (authType) return `${slug}-${authType}`;
|
|
357
|
+
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
358
|
+
// user-password
|
|
359
|
+
"postgresql": "user-password",
|
|
360
|
+
"mysql": "user-password",
|
|
361
|
+
"clickhouse": "user-password",
|
|
362
|
+
"kintone": "user-password",
|
|
363
|
+
"squadbase-db": "user-password",
|
|
364
|
+
// service-account
|
|
365
|
+
"snowflake": "service-account",
|
|
366
|
+
"bigquery": "service-account",
|
|
367
|
+
"google-analytics": "service-account",
|
|
368
|
+
"google-calendar": "service-account",
|
|
369
|
+
"aws-athena": "service-account",
|
|
370
|
+
"redshift": "service-account",
|
|
371
|
+
// api-key
|
|
372
|
+
"databricks": "api-key",
|
|
373
|
+
"dbt": "api-key",
|
|
374
|
+
"airtable": "api-key",
|
|
375
|
+
"openai": "api-key",
|
|
376
|
+
"gemini": "api-key",
|
|
377
|
+
"anthropic": "api-key",
|
|
378
|
+
"wix-store": "api-key"
|
|
379
|
+
};
|
|
380
|
+
const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
|
|
381
|
+
if (fallbackAuthType) return `${slug}-${fallbackAuthType}`;
|
|
382
|
+
return slug;
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
// ../connectors/src/auth-types.ts
|
|
387
|
+
var AUTH_TYPES = {
|
|
388
|
+
OAUTH: "oauth",
|
|
389
|
+
API_KEY: "api-key",
|
|
390
|
+
JWT: "jwt",
|
|
391
|
+
SERVICE_ACCOUNT: "service-account",
|
|
392
|
+
PAT: "pat",
|
|
393
|
+
USER_PASSWORD: "user-password"
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
// ../connectors/src/connectors/monday/setup.ts
|
|
397
|
+
var mondayOnboarding = new ConnectorOnboarding({
|
|
398
|
+
dataOverviewInstructions: {
|
|
399
|
+
en: `1. Call monday_request with query \`{ me { id name email account { id name } } }\` to verify the token and identify the account
|
|
400
|
+
2. Call monday_request with query \`{ boards(limit: 10) { id name state board_kind workspace { id name } } }\` to list boards
|
|
401
|
+
3. For a target board, call monday_request with query \`{ boards(ids: [BOARD_ID]) { id name columns { id title type settings_str } } }\` to inspect column definitions
|
|
402
|
+
4. Sample items with \`{ boards(ids: [BOARD_ID]) { items_page(limit: 5) { cursor items { id name created_at updated_at column_values { id text value } } } } }\`
|
|
403
|
+
5. Explore other resources (workspaces, users, tags) as needed`,
|
|
404
|
+
ja: `1. monday_request \u3067\u30AF\u30A8\u30EA \`{ me { id name email account { id name } } }\` \u3092\u547C\u3073\u51FA\u3057\u3001\u30C8\u30FC\u30AF\u30F3\u306E\u691C\u8A3C\u3068\u30A2\u30AB\u30A6\u30F3\u30C8\u306E\u78BA\u8A8D
|
|
405
|
+
2. monday_request \u3067\u30AF\u30A8\u30EA \`{ boards(limit: 10) { id name state board_kind workspace { id name } } }\` \u3092\u547C\u3073\u51FA\u3057\u3001\u30DC\u30FC\u30C9\u4E00\u89A7\u3092\u53D6\u5F97
|
|
406
|
+
3. \u5BFE\u8C61\u30DC\u30FC\u30C9\u306B\u5BFE\u3057\u3066 \`{ boards(ids: [BOARD_ID]) { id name columns { id title type settings_str } } }\` \u3092\u547C\u3073\u51FA\u3057\u3001\u30AB\u30E9\u30E0\u5B9A\u7FA9\u3092\u78BA\u8A8D
|
|
407
|
+
4. \`{ boards(ids: [BOARD_ID]) { items_page(limit: 5) { cursor items { id name created_at updated_at column_values { id text value } } } } }\` \u3067\u30A2\u30A4\u30C6\u30E0\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0
|
|
408
|
+
5. \u5FC5\u8981\u306B\u5FDC\u3058\u3066\u4ED6\u306E\u30EA\u30BD\u30FC\u30B9\uFF08workspaces\u3001users\u3001tags\uFF09\u3092\u63A2\u7D22`
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
// ../connectors/src/connectors/monday/tools/request.ts
|
|
413
|
+
import { z } from "zod";
|
|
414
|
+
var BASE_URL2 = "https://api.monday.com/v2";
|
|
415
|
+
var REQUEST_TIMEOUT_MS = 6e4;
|
|
416
|
+
var inputSchema = z.object({
|
|
417
|
+
toolUseIntent: z.string().optional().describe(
|
|
418
|
+
"Brief description of what you intend to accomplish with this tool call"
|
|
419
|
+
),
|
|
420
|
+
connectionId: z.string().describe("ID of the monday.com connection to use"),
|
|
421
|
+
query: z.string().describe(
|
|
422
|
+
`GraphQL query or mutation string. Example query: '{ boards(limit: 10) { id name state } }'. Example mutation: 'mutation { create_item(board_id: 123, item_name: "New task") { id name } }'. Pass IDs as strings (the API uses the ID scalar) and JSON column values as escaped JSON strings.`
|
|
423
|
+
),
|
|
424
|
+
variables: z.record(z.string(), z.unknown()).optional().describe(
|
|
425
|
+
`Optional GraphQL variables object. Use with parameterized queries, e.g. { "boardId": "1234567890", "limit": 25 }. Variable types must match the operation's declared types.`
|
|
426
|
+
),
|
|
427
|
+
apiVersion: z.string().optional().describe(
|
|
428
|
+
"Optional monday.com API version header (e.g. '2024-10'). When omitted, the current stable version is used."
|
|
429
|
+
)
|
|
430
|
+
});
|
|
431
|
+
var outputSchema = z.discriminatedUnion("success", [
|
|
432
|
+
z.object({
|
|
433
|
+
success: z.literal(true),
|
|
434
|
+
data: z.record(z.string(), z.unknown())
|
|
435
|
+
}),
|
|
436
|
+
z.object({
|
|
437
|
+
success: z.literal(false),
|
|
438
|
+
error: z.string()
|
|
439
|
+
})
|
|
440
|
+
]);
|
|
441
|
+
var requestTool = new ConnectorTool({
|
|
442
|
+
name: "request",
|
|
443
|
+
description: `Send authenticated GraphQL queries and mutations to the monday.com API (https://api.monday.com/v2).
|
|
444
|
+
Use this tool for all monday.com interactions: querying boards, items, groups, columns, users, workspaces, tags, updates, and performing mutations like create_item, change_column_value, create_board, etc.
|
|
445
|
+
monday.com's API is GraphQL-only \u2014 there is no REST API. All requests are POST with a JSON body containing "query" and optional "variables".
|
|
446
|
+
Items are paginated with a cursor-based \`items_page(limit, cursor)\` field on a board; pass the returned cursor on the next call. Boards/users/workspaces use page-based pagination via \`limit\`/\`page\`. Rate limits are complexity-based per minute, so prefer narrow field selections over wildcards.`,
|
|
447
|
+
inputSchema,
|
|
448
|
+
outputSchema,
|
|
449
|
+
async execute({ connectionId, query, variables, apiVersion }, connections) {
|
|
450
|
+
const connection2 = connections.find((c) => c.id === connectionId);
|
|
451
|
+
if (!connection2) {
|
|
452
|
+
return {
|
|
453
|
+
success: false,
|
|
454
|
+
error: `Connection ${connectionId} not found`
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
console.log(
|
|
458
|
+
`[connector-request] monday/${connection2.name}: GraphQL request`
|
|
459
|
+
);
|
|
460
|
+
try {
|
|
461
|
+
const apiToken = parameters.apiToken.getValue(connection2);
|
|
462
|
+
const controller = new AbortController();
|
|
463
|
+
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
464
|
+
try {
|
|
465
|
+
const body = { query };
|
|
466
|
+
if (variables) body.variables = variables;
|
|
467
|
+
const headers = {
|
|
468
|
+
Authorization: apiToken,
|
|
469
|
+
"Content-Type": "application/json"
|
|
470
|
+
};
|
|
471
|
+
if (apiVersion) headers["API-Version"] = apiVersion;
|
|
472
|
+
const response = await fetch(BASE_URL2, {
|
|
473
|
+
method: "POST",
|
|
474
|
+
headers,
|
|
475
|
+
body: JSON.stringify(body),
|
|
476
|
+
signal: controller.signal
|
|
477
|
+
});
|
|
478
|
+
const result = await response.json();
|
|
479
|
+
if (!response.ok) {
|
|
480
|
+
const errorMessage = typeof result?.error_message === "string" ? result.error_message : typeof result?.message === "string" ? result.message : typeof result?.error === "string" ? result.error : `HTTP ${response.status} ${response.statusText}`;
|
|
481
|
+
return { success: false, error: errorMessage };
|
|
482
|
+
}
|
|
483
|
+
if (result.errors && Array.isArray(result.errors) && result.errors.length > 0) {
|
|
484
|
+
const messages = result.errors.map((e) => e.message).join("; ");
|
|
485
|
+
if (!result.data) {
|
|
486
|
+
return { success: false, error: messages };
|
|
487
|
+
}
|
|
488
|
+
return {
|
|
489
|
+
success: true,
|
|
490
|
+
data: { ...result, _warnings: messages }
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
if (typeof result.error_message === "string") {
|
|
494
|
+
return { success: false, error: result.error_message };
|
|
495
|
+
}
|
|
496
|
+
return {
|
|
497
|
+
success: true,
|
|
498
|
+
data: result.data ?? result
|
|
499
|
+
};
|
|
500
|
+
} finally {
|
|
501
|
+
clearTimeout(timeout);
|
|
502
|
+
}
|
|
503
|
+
} catch (err) {
|
|
504
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
505
|
+
return { success: false, error: msg };
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
// ../connectors/src/connectors/monday/index.ts
|
|
511
|
+
var tools = { request: requestTool };
|
|
512
|
+
var mondayConnector = new ConnectorPlugin({
|
|
513
|
+
slug: "monday",
|
|
514
|
+
authType: AUTH_TYPES.API_KEY,
|
|
515
|
+
name: "monday.com",
|
|
516
|
+
description: "Connect to monday.com Work OS for boards, items, columns, groups, users, and workspaces via the GraphQL API.",
|
|
517
|
+
iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/5ZyTQYHVtA8PPnSusr8HPU/faab9875d83a5d63888875425a540688/monday-icon.svg",
|
|
518
|
+
parameters,
|
|
519
|
+
releaseFlag: { dev1: true, dev2: true, prod: true },
|
|
520
|
+
categories: ["productivity"],
|
|
521
|
+
onboarding: mondayOnboarding,
|
|
522
|
+
systemPrompt: {
|
|
523
|
+
en: `### Tools
|
|
524
|
+
|
|
525
|
+
- \`monday_request\`: The only way to call the monday.com GraphQL API. Use it to query and mutate all monday.com resources: boards, items, groups, columns, column values, users, workspaces, tags, teams, and updates. Authentication is configured automatically. monday.com's API is GraphQL-only \u2014 send a query string and optional variables. Items on a board are paginated with cursor-based \`items_page(limit, cursor)\`; boards/users/workspaces use page-based \`limit\`/\`page\`. IDs are passed as the GraphQL \`ID\` scalar (string).
|
|
526
|
+
|
|
527
|
+
### Business Logic
|
|
528
|
+
|
|
529
|
+
The business logic type for this connector is "typescript". Use the connector SDK in your handler. Do NOT read credentials from environment variables.
|
|
530
|
+
|
|
531
|
+
SDK methods (client created via \`connection(connectionId)\`):
|
|
532
|
+
- \`client.graphql(query, variables?)\` \u2014 send any GraphQL query/mutation. **Returns the GraphQL \`data\` payload directly with the outer \`{ data, errors }\` envelope already stripped.** For \`{ boards { ... } }\` you get \`{ boards: [...] }\`, NOT \`{ data: { boards: [...] } }\`. Access fields as \`result.boards\`, never \`result.data.boards\`. Errors are thrown automatically.
|
|
533
|
+
- \`client.request(init?)\` \u2014 low-level authenticated fetch to the GraphQL endpoint (returns the raw \`Response\`; you parse the full \`{ data, errors }\` envelope yourself)
|
|
534
|
+
- \`client.me()\` \u2014 get the authenticated user and account
|
|
535
|
+
- \`client.listBoards(options?)\` \u2014 list boards with optional ids, workspaceIds, state, page, limit
|
|
536
|
+
- \`client.getBoard(boardId)\` \u2014 fetch a single board with columns, groups, owners, tags
|
|
537
|
+
- \`client.listItems(boardId, options?)\` \u2014 cursor-paginated items on a board (returns \`{ cursor, items }\`)
|
|
538
|
+
- \`client.getItem(itemId)\` \u2014 fetch a single item with column values
|
|
539
|
+
- \`client.createItem(input)\` \u2014 create an item (\`boardId\`, \`itemName\`, optional \`groupId\`, \`columnValues\`)
|
|
540
|
+
- \`client.listUsers(options?)\` \u2014 list users with kind/page/limit
|
|
541
|
+
- \`client.listWorkspaces(options?)\` \u2014 list workspaces with page/limit
|
|
542
|
+
|
|
543
|
+
\`\`\`ts
|
|
544
|
+
import type { Context } from "hono";
|
|
545
|
+
import { connection } from "@squadbase/vite-server/connectors/monday";
|
|
546
|
+
|
|
547
|
+
const monday = connection("<connectionId>");
|
|
548
|
+
|
|
549
|
+
export default async function handler(c: Context) {
|
|
550
|
+
const { boardId, limit = 25, cursor } = await c.req.json<{
|
|
551
|
+
boardId: string;
|
|
552
|
+
limit?: number;
|
|
553
|
+
cursor?: string;
|
|
554
|
+
}>();
|
|
555
|
+
|
|
556
|
+
const { items, cursor: nextCursor } = await monday.listItems(boardId, { limit, cursor });
|
|
557
|
+
|
|
558
|
+
return c.json({ items, cursor: nextCursor });
|
|
559
|
+
}
|
|
560
|
+
\`\`\`
|
|
561
|
+
|
|
562
|
+
#### \`client.graphql()\` return shape (common pitfall)
|
|
563
|
+
|
|
564
|
+
\`client.graphql()\` already unwraps the GraphQL response envelope. **Do not access \`.data\` on the return value** \u2014 it is always \`undefined\` and will silently produce empty results.
|
|
565
|
+
|
|
566
|
+
\`\`\`ts
|
|
567
|
+
// \u2705 Correct \u2014 fields are at the top level
|
|
568
|
+
const res = await monday.graphql<{ boards: { items_page: { items: unknown[] } }[] }>(
|
|
569
|
+
\`query($ids: [ID!], $limit: Int) {
|
|
570
|
+
boards(ids: $ids) {
|
|
571
|
+
items_page(limit: $limit) { cursor items { id name } }
|
|
572
|
+
}
|
|
573
|
+
}\`,
|
|
574
|
+
{ ids: [boardId], limit: 100 },
|
|
575
|
+
);
|
|
576
|
+
const items = res.boards?.[0]?.items_page?.items ?? [];
|
|
577
|
+
|
|
578
|
+
// \u274C Wrong \u2014 \`res.data\` is undefined; \`.data\` was already stripped by the SDK
|
|
579
|
+
const items = res.data?.boards?.[0]?.items_page?.items; // always undefined!
|
|
580
|
+
\`\`\`
|
|
581
|
+
|
|
582
|
+
### monday.com GraphQL API Reference
|
|
583
|
+
|
|
584
|
+
- Endpoint: \`https://api.monday.com/v2\`
|
|
585
|
+
- Authentication: API token passed as \`Authorization: <API_TOKEN>\` header (no \`Bearer\` prefix; handled automatically)
|
|
586
|
+
- All requests are POST with JSON body: \`{ "query": "...", "variables": {...} }\`
|
|
587
|
+
- Optional \`API-Version\` header (e.g. \`2024-10\`) pins a specific API version; otherwise the current stable version is used
|
|
588
|
+
- Rate limit: complexity-based per minute (each query consumes a complexity score). Prefer narrow field selections.
|
|
589
|
+
- IDs are the \`ID\` scalar (serialized as string). Always quote them in variables.
|
|
590
|
+
- Pagination:
|
|
591
|
+
- Items on a board: \`items_page(limit, cursor)\` returns \`{ cursor, items }\`. Pass the returned \`cursor\` next time. \`cursor\` is null when there are no more pages.
|
|
592
|
+
- Boards / users / workspaces: page-based with \`limit\` and \`page\` arguments.
|
|
593
|
+
|
|
594
|
+
#### Common Queries
|
|
595
|
+
- \`{ me { id name email account { id name } } }\` \u2014 authenticated user and account
|
|
596
|
+
- \`{ boards(limit: 10) { id name state board_kind workspace { id name } } }\` \u2014 list boards
|
|
597
|
+
- \`{ boards(ids: [BOARD_ID]) { columns { id title type settings_str } groups { id title } } }\` \u2014 get board schema
|
|
598
|
+
- \`{ boards(ids: [BOARD_ID]) { items_page(limit: 25) { cursor items { id name column_values { id text value } } } } }\` \u2014 list items
|
|
599
|
+
- \`{ items(ids: [ITEM_ID]) { id name column_values { id text value column { title } } } }\` \u2014 get a single item
|
|
600
|
+
- \`{ users(limit: 25) { id name email enabled is_admin is_guest } }\` \u2014 list users
|
|
601
|
+
- \`{ workspaces(limit: 25) { id name kind state } }\` \u2014 list workspaces
|
|
602
|
+
|
|
603
|
+
#### Common Mutations
|
|
604
|
+
- \`mutation { create_item(board_id: BOARD_ID, item_name: "New task", column_values: "{\\"status\\":{\\"label\\":\\"Done\\"}}") { id name } }\` \u2014 create an item (column_values must be a JSON string)
|
|
605
|
+
- \`mutation { change_column_value(board_id: BOARD_ID, item_id: ITEM_ID, column_id: "status", value: "{\\"label\\":\\"Done\\"}") { id } }\` \u2014 update a column value
|
|
606
|
+
- \`mutation { create_update(item_id: ITEM_ID, body: "Hello") { id } }\` \u2014 post an update on an item
|
|
607
|
+
- \`mutation { delete_item(item_id: ITEM_ID) { id } }\` \u2014 delete an item
|
|
608
|
+
|
|
609
|
+
#### Notes
|
|
610
|
+
- \`column_values\` arguments accept a JSON-encoded string; remember to escape inner quotes when embedding in a query string, or pass it via GraphQL variables to avoid escaping.
|
|
611
|
+
- The \`ID\` scalar accepts both numeric and string forms; using strings in variables is the safest.
|
|
612
|
+
- Some fields (e.g. \`board.tags\`) are only populated for boards that explicitly use them.`,
|
|
613
|
+
ja: `### \u30C4\u30FC\u30EB
|
|
614
|
+
|
|
615
|
+
- \`monday_request\`: monday.com GraphQL API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30DC\u30FC\u30C9\u3001\u30A2\u30A4\u30C6\u30E0\u3001\u30B0\u30EB\u30FC\u30D7\u3001\u30AB\u30E9\u30E0\u3001\u30AB\u30E9\u30E0\u5024\u3001\u30E6\u30FC\u30B6\u30FC\u3001\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u3001\u30BF\u30B0\u3001\u30C1\u30FC\u30E0\u3001\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u306A\u3069\u3059\u3079\u3066\u306E\u30EA\u30BD\u30FC\u30B9\u306E\u30AF\u30A8\u30EA\u3068\u30DF\u30E5\u30FC\u30C6\u30FC\u30B7\u30E7\u30F3\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002monday.com \u306E API \u306F GraphQL \u306E\u307F\u3067\u3001\u30AF\u30A8\u30EA\u6587\u5B57\u5217\u3068\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u5909\u6570\u3092\u9001\u4FE1\u3057\u307E\u3059\u3002\u30DC\u30FC\u30C9\u4E0A\u306E\u30A2\u30A4\u30C6\u30E0\u306F\u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9\u306E \`items_page(limit, cursor)\` \u3067\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u3055\u308C\u3001\u30DC\u30FC\u30C9\uFF0F\u30E6\u30FC\u30B6\u30FC\uFF0F\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306F\u30DA\u30FC\u30B8\u30D9\u30FC\u30B9\u306E \`limit\`/\`page\` \u3092\u4F7F\u7528\u3057\u307E\u3059\u3002ID \u306F GraphQL \u306E \`ID\` \u30B9\u30AB\u30E9\u30FC\uFF08\u6587\u5B57\u5217\uFF09\u3068\u3057\u3066\u6E21\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
|
616
|
+
|
|
617
|
+
### Business Logic
|
|
618
|
+
|
|
619
|
+
\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\u74B0\u5883\u5909\u6570\u304B\u3089\u8A8D\u8A3C\u60C5\u5831\u3092\u8AAD\u307F\u53D6\u3089\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002
|
|
620
|
+
|
|
621
|
+
SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8):
|
|
622
|
+
- \`client.graphql(query, variables?)\` \u2014 \u4EFB\u610F\u306EGraphQL\u30AF\u30A8\u30EA/\u30DF\u30E5\u30FC\u30C6\u30FC\u30B7\u30E7\u30F3\u3092\u9001\u4FE1\u3002**\u623B\u308A\u5024\u306F GraphQL \u30EC\u30B9\u30DD\u30F3\u30B9\u306E \`data\` \u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u65E2\u306B\u30A2\u30F3\u30E9\u30C3\u30D7\u3057\u305F\u3082\u306E**\u3002\`{ boards { ... } }\` \u3092\u6295\u3052\u305F\u5834\u5408\u306E\u623B\u308A\u5024\u306F \`{ boards: [...] }\` \u3067\u3042\u308A\u3001\`{ data: { boards: [...] } }\` \u3067\u306F\u306A\u3044\u3002\`result.boards\` \u306E\u3088\u3046\u306B\u30A2\u30AF\u30BB\u30B9\u3057\u3001\`result.data.boards\` \u306E\u3088\u3046\u306B \`.data\` \u3092\u7D4C\u7531\u3057\u3066\u306F\u3044\u3051\u306A\u3044\u3002\u30A8\u30E9\u30FC\u306F\u81EA\u52D5\u3067\u4F8B\u5916\u3068\u3057\u3066\u6295\u3052\u3089\u308C\u308B\u3002
|
|
623
|
+
- \`client.request(init?)\` \u2014 GraphQL\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3078\u306E\u4F4E\u30EC\u30D9\u30EB\u8A8D\u8A3C\u4ED8\u304Dfetch\uFF08\u751F\u306E \`Response\` \u3092\u8FD4\u3059\u3002\`{ data, errors }\` \u30A8\u30F3\u30D9\u30ED\u30FC\u30D7\u3092\u81EA\u5206\u3067\u30D1\u30FC\u30B9\u3059\u308B\u5FC5\u8981\u304C\u3042\u308B\uFF09
|
|
624
|
+
- \`client.me()\` \u2014 \u8A8D\u8A3C\u6E08\u307F\u30E6\u30FC\u30B6\u30FC\u3068\u30A2\u30AB\u30A6\u30F3\u30C8\u3092\u53D6\u5F97
|
|
625
|
+
- \`client.listBoards(options?)\` \u2014 ids/workspaceIds/state/page/limit \u3067\u30DC\u30FC\u30C9\u4E00\u89A7\u3092\u53D6\u5F97
|
|
626
|
+
- \`client.getBoard(boardId)\` \u2014 1\u3064\u306E\u30DC\u30FC\u30C9\u3092 columns/groups/owners/tags \u4ED8\u304D\u3067\u53D6\u5F97
|
|
627
|
+
- \`client.listItems(boardId, options?)\` \u2014 \u30DC\u30FC\u30C9\u4E0A\u306E\u30A2\u30A4\u30C6\u30E0\u3092\u30AB\u30FC\u30BD\u30EB\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u3067\u53D6\u5F97\uFF08\`{ cursor, items }\` \u3092\u8FD4\u3059\uFF09
|
|
628
|
+
- \`client.getItem(itemId)\` \u2014 1\u3064\u306E\u30A2\u30A4\u30C6\u30E0\u3092\u30AB\u30E9\u30E0\u5024\u4ED8\u304D\u3067\u53D6\u5F97
|
|
629
|
+
- \`client.createItem(input)\` \u2014 \u30A2\u30A4\u30C6\u30E0\u3092\u4F5C\u6210 (\`boardId\`, \`itemName\`, \u4EFB\u610F\u3067 \`groupId\`, \`columnValues\`)
|
|
630
|
+
- \`client.listUsers(options?)\` \u2014 kind/page/limit \u3067\u30E6\u30FC\u30B6\u30FC\u4E00\u89A7\u3092\u53D6\u5F97
|
|
631
|
+
- \`client.listWorkspaces(options?)\` \u2014 page/limit \u3067\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u4E00\u89A7\u3092\u53D6\u5F97
|
|
632
|
+
|
|
633
|
+
\`\`\`ts
|
|
634
|
+
import type { Context } from "hono";
|
|
635
|
+
import { connection } from "@squadbase/vite-server/connectors/monday";
|
|
636
|
+
|
|
637
|
+
const monday = connection("<connectionId>");
|
|
638
|
+
|
|
639
|
+
export default async function handler(c: Context) {
|
|
640
|
+
const { boardId, limit = 25, cursor } = await c.req.json<{
|
|
641
|
+
boardId: string;
|
|
642
|
+
limit?: number;
|
|
643
|
+
cursor?: string;
|
|
644
|
+
}>();
|
|
645
|
+
|
|
646
|
+
const { items, cursor: nextCursor } = await monday.listItems(boardId, { limit, cursor });
|
|
647
|
+
|
|
648
|
+
return c.json({ items, cursor: nextCursor });
|
|
649
|
+
}
|
|
650
|
+
\`\`\`
|
|
651
|
+
|
|
652
|
+
#### \`client.graphql()\` \u306E\u623B\u308A\u5024\uFF08\u3088\u304F\u3042\u308B\u9593\u9055\u3044\uFF09
|
|
653
|
+
|
|
654
|
+
\`client.graphql()\` \u306F GraphQL \u30EC\u30B9\u30DD\u30F3\u30B9\u306E \`data\` \u3092\u3059\u3067\u306B\u30A2\u30F3\u30E9\u30C3\u30D7\u3057\u3066\u3044\u308B\u3002**\u623B\u308A\u5024\u306B\u5BFE\u3057\u3066 \`.data\` \u3092\u7D4C\u7531\u3057\u3066\u306F\u3044\u3051\u306A\u3044** \u2014 \u5E38\u306B \`undefined\` \u3068\u306A\u308A\u3001\u7D50\u679C\u304C\u7121\u97F3\u3067\u7A7A\u306B\u306A\u308B\u3002
|
|
655
|
+
|
|
656
|
+
\`\`\`ts
|
|
657
|
+
// \u2705 \u6B63\u3057\u3044 \u2014 \u30D5\u30A3\u30FC\u30EB\u30C9\u306F\u30C8\u30C3\u30D7\u30EC\u30D9\u30EB\u306B\u3042\u308B
|
|
658
|
+
const res = await monday.graphql<{ boards: { items_page: { items: unknown[] } }[] }>(
|
|
659
|
+
\`query($ids: [ID!], $limit: Int) {
|
|
660
|
+
boards(ids: $ids) {
|
|
661
|
+
items_page(limit: $limit) { cursor items { id name } }
|
|
662
|
+
}
|
|
663
|
+
}\`,
|
|
664
|
+
{ ids: [boardId], limit: 100 },
|
|
665
|
+
);
|
|
666
|
+
const items = res.boards?.[0]?.items_page?.items ?? [];
|
|
667
|
+
|
|
668
|
+
// \u274C \u8AA4\u308A \u2014 \`res.data\` \u306F undefined\uFF08SDK\u304C\u65E2\u306B \`.data\` \u3092\u5265\u304C\u3057\u3066\u3044\u308B\uFF09
|
|
669
|
+
const items = res.data?.boards?.[0]?.items_page?.items; // \u5E38\u306B undefined\uFF01
|
|
670
|
+
\`\`\`
|
|
671
|
+
|
|
672
|
+
### monday.com GraphQL API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
|
|
673
|
+
|
|
674
|
+
- \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8: \`https://api.monday.com/v2\`
|
|
675
|
+
- \u8A8D\u8A3C: API\u30C8\u30FC\u30AF\u30F3\u3092 \`Authorization: <API_TOKEN>\` \u30D8\u30C3\u30C0\u30FC\u3067\u9001\u4FE1\uFF08\`Bearer\` \u30D7\u30EC\u30D5\u30A3\u30C3\u30AF\u30B9\u306F\u4E0D\u8981\u3001\u81EA\u52D5\u8A2D\u5B9A\uFF09
|
|
676
|
+
- \u3059\u3079\u3066\u306E\u30EA\u30AF\u30A8\u30B9\u30C8\u306FPOST\u3067JSON\u30DC\u30C7\u30A3: \`{ "query": "...", "variables": {...} }\`
|
|
677
|
+
- \u4EFB\u610F\u306E \`API-Version\` \u30D8\u30C3\u30C0\u30FC\uFF08\u4F8B: \`2024-10\`\uFF09\u3067API\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u56FA\u5B9A\u53EF\u80FD\u3002\u6307\u5B9A\u3057\u306A\u3044\u5834\u5408\u306F\u73FE\u5728\u306E\u5B89\u5B9A\u7248\u304C\u4F7F\u7528\u3055\u308C\u308B
|
|
678
|
+
- \u30EC\u30FC\u30C8\u5236\u9650: 1\u5206\u3042\u305F\u308A\u306E\u8907\u96D1\u5EA6\uFF08complexity\uFF09\u30D9\u30FC\u30B9\u3002\u5404\u30AF\u30A8\u30EA\u306F\u8907\u96D1\u5EA6\u30B9\u30B3\u30A2\u3092\u6D88\u8CBB\u3059\u308B\u305F\u3081\u3001\u5FC5\u8981\u306A\u30D5\u30A3\u30FC\u30EB\u30C9\u3060\u3051\u3092\u9078\u629E\u3059\u308B
|
|
679
|
+
- ID \u306F \`ID\` \u30B9\u30AB\u30E9\u30FC\uFF08\u6587\u5B57\u5217\u3068\u3057\u3066\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u3055\u308C\u308B\uFF09\u3002\u5909\u6570\u3067\u306F\u5FC5\u305A\u6587\u5B57\u5217\u3068\u3057\u3066\u6E21\u3059
|
|
680
|
+
- \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3:
|
|
681
|
+
- \u30DC\u30FC\u30C9\u4E0A\u306E\u30A2\u30A4\u30C6\u30E0: \`items_page(limit, cursor)\` \u304C \`{ cursor, items }\` \u3092\u8FD4\u3059\u3002\u6B21\u56DE\u547C\u3073\u51FA\u3057\u6642\u306B \`cursor\` \u3092\u6E21\u3059\u3002\`cursor\` \u304C null \u306B\u306A\u308C\u3070\u7D42\u7AEF
|
|
682
|
+
- \u30DC\u30FC\u30C9\uFF0F\u30E6\u30FC\u30B6\u30FC\uFF0F\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9: \`limit\` \u3068 \`page\` \u5F15\u6570\u306E\u30DA\u30FC\u30B8\u30D9\u30FC\u30B9
|
|
683
|
+
|
|
684
|
+
#### \u4E3B\u8981\u30AF\u30A8\u30EA
|
|
685
|
+
- \`{ me { id name email account { id name } } }\` \u2014 \u8A8D\u8A3C\u30E6\u30FC\u30B6\u30FC\u3068\u30A2\u30AB\u30A6\u30F3\u30C8
|
|
686
|
+
- \`{ boards(limit: 10) { id name state board_kind workspace { id name } } }\` \u2014 \u30DC\u30FC\u30C9\u4E00\u89A7
|
|
687
|
+
- \`{ boards(ids: [BOARD_ID]) { columns { id title type settings_str } groups { id title } } }\` \u2014 \u30DC\u30FC\u30C9\u306E\u30B9\u30AD\u30FC\u30DE\u53D6\u5F97
|
|
688
|
+
- \`{ boards(ids: [BOARD_ID]) { items_page(limit: 25) { cursor items { id name column_values { id text value } } } } }\` \u2014 \u30A2\u30A4\u30C6\u30E0\u4E00\u89A7
|
|
689
|
+
- \`{ items(ids: [ITEM_ID]) { id name column_values { id text value column { title } } } }\` \u2014 \u5358\u4E00\u30A2\u30A4\u30C6\u30E0\u53D6\u5F97
|
|
690
|
+
- \`{ users(limit: 25) { id name email enabled is_admin is_guest } }\` \u2014 \u30E6\u30FC\u30B6\u30FC\u4E00\u89A7
|
|
691
|
+
- \`{ workspaces(limit: 25) { id name kind state } }\` \u2014 \u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u4E00\u89A7
|
|
692
|
+
|
|
693
|
+
#### \u4E3B\u8981\u30DF\u30E5\u30FC\u30C6\u30FC\u30B7\u30E7\u30F3
|
|
694
|
+
- \`mutation { create_item(board_id: BOARD_ID, item_name: "New task", column_values: "{\\"status\\":{\\"label\\":\\"Done\\"}}") { id name } }\` \u2014 \u30A2\u30A4\u30C6\u30E0\u4F5C\u6210\uFF08column_values \u306F JSON\u6587\u5B57\u5217\uFF09
|
|
695
|
+
- \`mutation { change_column_value(board_id: BOARD_ID, item_id: ITEM_ID, column_id: "status", value: "{\\"label\\":\\"Done\\"}") { id } }\` \u2014 \u30AB\u30E9\u30E0\u5024\u306E\u66F4\u65B0
|
|
696
|
+
- \`mutation { create_update(item_id: ITEM_ID, body: "Hello") { id } }\` \u2014 \u30A2\u30A4\u30C6\u30E0\u306B\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\uFF08\u30B3\u30E1\u30F3\u30C8\uFF09\u3092\u6295\u7A3F
|
|
697
|
+
- \`mutation { delete_item(item_id: ITEM_ID) { id } }\` \u2014 \u30A2\u30A4\u30C6\u30E0\u524A\u9664
|
|
698
|
+
|
|
699
|
+
#### \u6CE8\u610F\u70B9
|
|
700
|
+
- \`column_values\` \u306F JSON\u30A8\u30F3\u30B3\u30FC\u30C9\u3055\u308C\u305F\u6587\u5B57\u5217\u3092\u53D7\u3051\u53D6\u308B\u3002\u30AF\u30A8\u30EA\u6587\u5B57\u5217\u306B\u76F4\u66F8\u304D\u3059\u308B\u969B\u306F\u5185\u5074\u306E\u30AF\u30AA\u30FC\u30C8\u3092\u30A8\u30B9\u30B1\u30FC\u30D7\u3059\u308B\u304B\u3001GraphQL\u5909\u6570\u7D4C\u7531\u3067\u6E21\u3057\u3066\u30A8\u30B9\u30B1\u30FC\u30D7\u3092\u907F\u3051\u308B\u306E\u304C\u5B89\u5168
|
|
701
|
+
- \`ID\` \u30B9\u30AB\u30E9\u30FC\u306F\u6570\u5024\u30FB\u6587\u5B57\u5217\u3069\u3061\u3089\u3082\u53D7\u3051\u4ED8\u3051\u308B\u304C\u3001\u5909\u6570\u3067\u306F\u6587\u5B57\u5217\u3067\u6E21\u3059\u306E\u304C\u5B89\u5168
|
|
702
|
+
- \`board.tags\` \u306E\u3088\u3046\u306B\u3001\u660E\u793A\u7684\u306B\u4F7F\u308F\u308C\u3066\u3044\u308B\u30DC\u30FC\u30C9\u3067\u306E\u307F\u5024\u304C\u8FD4\u308B\u30D5\u30A3\u30FC\u30EB\u30C9\u3082\u3042\u308B`
|
|
703
|
+
},
|
|
704
|
+
tools
|
|
705
|
+
});
|
|
706
|
+
|
|
707
|
+
// src/connectors/create-connector-sdk.ts
|
|
708
|
+
import { readFileSync } from "fs";
|
|
709
|
+
import path from "path";
|
|
710
|
+
|
|
711
|
+
// src/connector-client/env.ts
|
|
712
|
+
function resolveEnvVar(entry, key, connectionId) {
|
|
713
|
+
const envVarName = entry.envVars[key];
|
|
714
|
+
if (!envVarName) {
|
|
715
|
+
throw new Error(`Connection "${connectionId}" is missing envVars mapping for key "${key}"`);
|
|
716
|
+
}
|
|
717
|
+
const value = process.env[envVarName];
|
|
718
|
+
if (!value) {
|
|
719
|
+
throw new Error(`Environment variable "${envVarName}" (for connection "${connectionId}", key "${key}") is not set`);
|
|
720
|
+
}
|
|
721
|
+
return value;
|
|
722
|
+
}
|
|
723
|
+
function resolveEnvVarOptional(entry, key) {
|
|
724
|
+
const envVarName = entry.envVars[key];
|
|
725
|
+
if (!envVarName) return void 0;
|
|
726
|
+
return process.env[envVarName] || void 0;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// src/connector-client/proxy-fetch.ts
|
|
730
|
+
import { getContext } from "hono/context-storage";
|
|
731
|
+
import { getCookie } from "hono/cookie";
|
|
732
|
+
var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
|
|
733
|
+
function normalizeHeaders(input) {
|
|
734
|
+
const out = {};
|
|
735
|
+
if (!input) return out;
|
|
736
|
+
new Headers(input).forEach((value, key) => {
|
|
737
|
+
out[key] = value;
|
|
738
|
+
});
|
|
739
|
+
return out;
|
|
740
|
+
}
|
|
741
|
+
function createSandboxProxyFetch(connectionId) {
|
|
742
|
+
return async (input, init) => {
|
|
743
|
+
const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
|
|
744
|
+
const sandboxId = process.env.INTERNAL_SQUADBASE_SANDBOX_ID;
|
|
745
|
+
if (!token || !sandboxId) {
|
|
746
|
+
throw new Error(
|
|
747
|
+
"Connection proxy is not configured. Please check your deployment settings."
|
|
748
|
+
);
|
|
749
|
+
}
|
|
750
|
+
const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
751
|
+
const originalMethod = init?.method ?? "GET";
|
|
752
|
+
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
753
|
+
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
754
|
+
const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
755
|
+
return fetch(proxyUrl, {
|
|
756
|
+
method: "POST",
|
|
757
|
+
headers: {
|
|
758
|
+
"Content-Type": "application/json",
|
|
759
|
+
Authorization: `Bearer ${token}`
|
|
760
|
+
},
|
|
761
|
+
body: JSON.stringify({
|
|
762
|
+
url: originalUrl,
|
|
763
|
+
method: originalMethod,
|
|
764
|
+
headers: normalizeHeaders(init?.headers),
|
|
765
|
+
body: originalBody
|
|
766
|
+
})
|
|
767
|
+
});
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
function createDeployedAppProxyFetch(connectionId) {
|
|
771
|
+
const projectId = process.env["SQUADBASE_PROJECT_ID"];
|
|
772
|
+
if (!projectId) {
|
|
773
|
+
throw new Error(
|
|
774
|
+
"Connection proxy is not configured. Please check your deployment settings."
|
|
775
|
+
);
|
|
776
|
+
}
|
|
777
|
+
const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
|
|
778
|
+
const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
779
|
+
return async (input, init) => {
|
|
780
|
+
const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
781
|
+
const originalMethod = init?.method ?? "GET";
|
|
782
|
+
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
783
|
+
const c = getContext();
|
|
784
|
+
const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
|
|
785
|
+
if (!appSession) {
|
|
786
|
+
throw new Error(
|
|
787
|
+
"No authentication method available for connection proxy."
|
|
788
|
+
);
|
|
789
|
+
}
|
|
790
|
+
return fetch(proxyUrl, {
|
|
791
|
+
method: "POST",
|
|
792
|
+
headers: {
|
|
793
|
+
"Content-Type": "application/json",
|
|
794
|
+
Authorization: `Bearer ${appSession}`
|
|
795
|
+
},
|
|
796
|
+
body: JSON.stringify({
|
|
797
|
+
url: originalUrl,
|
|
798
|
+
method: originalMethod,
|
|
799
|
+
headers: normalizeHeaders(init?.headers),
|
|
800
|
+
body: originalBody
|
|
801
|
+
})
|
|
802
|
+
});
|
|
803
|
+
};
|
|
804
|
+
}
|
|
805
|
+
function createProxyFetch(connectionId) {
|
|
806
|
+
if (process.env.INTERNAL_SQUADBASE_SANDBOX_ID) {
|
|
807
|
+
return createSandboxProxyFetch(connectionId);
|
|
808
|
+
}
|
|
809
|
+
return createDeployedAppProxyFetch(connectionId);
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
// src/connectors/create-connector-sdk.ts
|
|
813
|
+
function loadConnectionsSync() {
|
|
814
|
+
const filePath = process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
|
|
815
|
+
try {
|
|
816
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
817
|
+
return JSON.parse(raw);
|
|
818
|
+
} catch {
|
|
819
|
+
return {};
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
function createConnectorSdk(plugin, createClient2) {
|
|
823
|
+
return (connectionId) => {
|
|
824
|
+
const connections = loadConnectionsSync();
|
|
825
|
+
const entry = connections[connectionId];
|
|
826
|
+
if (!entry) {
|
|
827
|
+
throw new Error(
|
|
828
|
+
`Connection "${connectionId}" not found in .squadbase/connections.json`
|
|
829
|
+
);
|
|
830
|
+
}
|
|
831
|
+
if (entry.connector.slug !== plugin.slug) {
|
|
832
|
+
throw new Error(
|
|
833
|
+
`Connection "${connectionId}" is not a ${plugin.slug} connection (got "${entry.connector.slug}")`
|
|
834
|
+
);
|
|
835
|
+
}
|
|
836
|
+
const params = {};
|
|
837
|
+
for (const param of Object.values(plugin.parameters)) {
|
|
838
|
+
if (param.required) {
|
|
839
|
+
params[param.slug] = resolveEnvVar(entry, param.slug, connectionId);
|
|
840
|
+
} else {
|
|
841
|
+
const val = resolveEnvVarOptional(entry, param.slug);
|
|
842
|
+
if (val !== void 0) params[param.slug] = val;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
return createClient2(params, createProxyFetch(connectionId));
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
// src/connectors/entries/monday.ts
|
|
850
|
+
var connection = createConnectorSdk(mondayConnector, createClient);
|
|
851
|
+
export {
|
|
852
|
+
connection
|
|
853
|
+
};
|