@squadbase/vite-server 0.1.3-dev.0 → 0.1.3-dev.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/dist/cli/index.js +82859 -9645
  2. package/dist/connectors/airtable-oauth.js +77 -3
  3. package/dist/connectors/airtable.js +85 -2
  4. package/dist/connectors/amplitude.js +85 -2
  5. package/dist/connectors/anthropic.js +85 -2
  6. package/dist/connectors/{slack.d.ts → asana.d.ts} +1 -1
  7. package/dist/connectors/asana.js +744 -0
  8. package/dist/connectors/attio.js +85 -2
  9. package/dist/connectors/{microsoft-teams-oauth.d.ts → customerio.d.ts} +1 -1
  10. package/dist/connectors/customerio.js +716 -0
  11. package/dist/connectors/dbt.js +85 -2
  12. package/dist/connectors/gemini.js +86 -3
  13. package/dist/connectors/{microsoft-teams.d.ts → gmail-oauth.d.ts} +1 -1
  14. package/dist/connectors/gmail-oauth.js +713 -0
  15. package/dist/connectors/gmail.d.ts +5 -0
  16. package/dist/connectors/gmail.js +875 -0
  17. package/dist/connectors/google-ads-oauth.js +78 -4
  18. package/dist/connectors/google-ads.d.ts +5 -0
  19. package/dist/connectors/google-ads.js +867 -0
  20. package/dist/connectors/google-analytics-oauth.js +90 -8
  21. package/dist/connectors/google-analytics.js +85 -2
  22. package/dist/connectors/google-calendar-oauth.d.ts +5 -0
  23. package/dist/connectors/google-calendar-oauth.js +817 -0
  24. package/dist/connectors/google-calendar.d.ts +5 -0
  25. package/dist/connectors/google-calendar.js +991 -0
  26. package/dist/connectors/google-sheets-oauth.js +144 -33
  27. package/dist/connectors/google-sheets.d.ts +5 -0
  28. package/dist/connectors/google-sheets.js +707 -0
  29. package/dist/connectors/grafana.d.ts +5 -0
  30. package/dist/connectors/grafana.js +638 -0
  31. package/dist/connectors/hubspot-oauth.js +77 -3
  32. package/dist/connectors/hubspot.js +89 -6
  33. package/dist/connectors/intercom-oauth.d.ts +5 -0
  34. package/dist/connectors/intercom-oauth.js +584 -0
  35. package/dist/connectors/intercom.d.ts +5 -0
  36. package/dist/connectors/intercom.js +710 -0
  37. package/dist/connectors/jira-api-key.d.ts +5 -0
  38. package/dist/connectors/jira-api-key.js +598 -0
  39. package/dist/connectors/kintone-api-token.js +77 -3
  40. package/dist/connectors/kintone.js +86 -3
  41. package/dist/connectors/linkedin-ads-oauth.d.ts +5 -0
  42. package/dist/connectors/linkedin-ads-oauth.js +848 -0
  43. package/dist/connectors/linkedin-ads.d.ts +5 -0
  44. package/dist/connectors/linkedin-ads.js +865 -0
  45. package/dist/connectors/mailchimp-oauth.d.ts +5 -0
  46. package/dist/connectors/mailchimp-oauth.js +613 -0
  47. package/dist/connectors/mailchimp.d.ts +5 -0
  48. package/dist/connectors/mailchimp.js +729 -0
  49. package/dist/connectors/notion-oauth.d.ts +5 -0
  50. package/dist/connectors/notion-oauth.js +567 -0
  51. package/dist/connectors/notion.d.ts +5 -0
  52. package/dist/connectors/notion.js +663 -0
  53. package/dist/connectors/openai.js +85 -2
  54. package/dist/connectors/shopify-oauth.js +77 -3
  55. package/dist/connectors/shopify.js +85 -2
  56. package/dist/connectors/stripe-api-key.d.ts +5 -0
  57. package/dist/connectors/stripe-api-key.js +600 -0
  58. package/dist/connectors/stripe-oauth.js +77 -3
  59. package/dist/connectors/wix-store.js +85 -2
  60. package/dist/connectors/zendesk-oauth.d.ts +5 -0
  61. package/dist/connectors/zendesk-oauth.js +579 -0
  62. package/dist/connectors/zendesk.d.ts +5 -0
  63. package/dist/connectors/zendesk.js +714 -0
  64. package/dist/index.js +83024 -7099
  65. package/dist/main.js +82988 -7063
  66. package/dist/vite-plugin.js +82862 -6974
  67. package/package.json +86 -2
  68. package/dist/connectors/microsoft-teams-oauth.js +0 -479
  69. package/dist/connectors/microsoft-teams.js +0 -381
  70. package/dist/connectors/slack.js +0 -362
@@ -0,0 +1,663 @@
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/notion/parameters.ts
46
+ var parameters = {
47
+ apiKey: new ParameterDefinition({
48
+ slug: "api-key",
49
+ name: "Notion Internal Integration Token",
50
+ description: "The Internal Integration Token from your Notion integration settings (starts with ntn_ or secret_).",
51
+ envVarBaseKey: "NOTION_API_KEY",
52
+ type: "text",
53
+ secret: true,
54
+ required: true
55
+ })
56
+ };
57
+
58
+ // ../connectors/src/connectors/notion/sdk/index.ts
59
+ var BASE_URL = "https://api.notion.com/v1";
60
+ var NOTION_VERSION = "2022-06-28";
61
+ function createClient(params) {
62
+ const apiKey = params[parameters.apiKey.slug];
63
+ if (!apiKey) {
64
+ throw new Error(
65
+ `notion: missing required parameter: ${parameters.apiKey.slug}`
66
+ );
67
+ }
68
+ function authHeaders(extra) {
69
+ const headers = new Headers(extra);
70
+ headers.set("Authorization", `Bearer ${apiKey}`);
71
+ headers.set("Notion-Version", NOTION_VERSION);
72
+ headers.set("Content-Type", "application/json");
73
+ return headers;
74
+ }
75
+ async function assertOk(res, label) {
76
+ if (!res.ok) {
77
+ const body = await res.text().catch(() => "(unreadable body)");
78
+ throw new Error(
79
+ `notion ${label}: ${res.status} ${res.statusText} \u2014 ${body}`
80
+ );
81
+ }
82
+ }
83
+ return {
84
+ request(path2, init) {
85
+ const url = `${BASE_URL}${path2.startsWith("/") ? "" : "/"}${path2}`;
86
+ const headers = new Headers(init?.headers);
87
+ headers.set("Authorization", `Bearer ${apiKey}`);
88
+ headers.set("Notion-Version", NOTION_VERSION);
89
+ headers.set("Content-Type", "application/json");
90
+ return fetch(url, { ...init, headers });
91
+ },
92
+ async search(options) {
93
+ const body = {};
94
+ if (options?.query) body.query = options.query;
95
+ if (options?.filter) body.filter = options.filter;
96
+ if (options?.sort) body.sort = options.sort;
97
+ if (options?.start_cursor) body.start_cursor = options.start_cursor;
98
+ if (options?.page_size) body.page_size = options.page_size;
99
+ const res = await fetch(`${BASE_URL}/search`, {
100
+ method: "POST",
101
+ headers: authHeaders(),
102
+ body: JSON.stringify(body)
103
+ });
104
+ await assertOk(res, "search");
105
+ return await res.json();
106
+ },
107
+ async queryDatabase(databaseId, options) {
108
+ const body = {};
109
+ if (options?.filter) body.filter = options.filter;
110
+ if (options?.sorts) body.sorts = options.sorts;
111
+ if (options?.start_cursor) body.start_cursor = options.start_cursor;
112
+ if (options?.page_size) body.page_size = options.page_size;
113
+ const res = await fetch(
114
+ `${BASE_URL}/databases/${encodeURIComponent(databaseId)}/query`,
115
+ {
116
+ method: "POST",
117
+ headers: authHeaders(),
118
+ body: JSON.stringify(body)
119
+ }
120
+ );
121
+ await assertOk(res, "queryDatabase");
122
+ return await res.json();
123
+ },
124
+ async getPage(pageId) {
125
+ const res = await fetch(
126
+ `${BASE_URL}/pages/${encodeURIComponent(pageId)}`,
127
+ { method: "GET", headers: authHeaders() }
128
+ );
129
+ await assertOk(res, "getPage");
130
+ return await res.json();
131
+ },
132
+ async getDatabase(databaseId) {
133
+ const res = await fetch(
134
+ `${BASE_URL}/databases/${encodeURIComponent(databaseId)}`,
135
+ { method: "GET", headers: authHeaders() }
136
+ );
137
+ await assertOk(res, "getDatabase");
138
+ return await res.json();
139
+ },
140
+ async getBlockChildren(blockId, options) {
141
+ const params2 = new URLSearchParams();
142
+ if (options?.start_cursor)
143
+ params2.set("start_cursor", options.start_cursor);
144
+ if (options?.page_size)
145
+ params2.set("page_size", String(options.page_size));
146
+ const qs = params2.toString();
147
+ const url = `${BASE_URL}/blocks/${encodeURIComponent(blockId)}/children${qs ? `?${qs}` : ""}`;
148
+ const res = await fetch(url, { method: "GET", headers: authHeaders() });
149
+ await assertOk(res, "getBlockChildren");
150
+ return await res.json();
151
+ },
152
+ async listUsers(options) {
153
+ const params2 = new URLSearchParams();
154
+ if (options?.start_cursor)
155
+ params2.set("start_cursor", options.start_cursor);
156
+ if (options?.page_size)
157
+ params2.set("page_size", String(options.page_size));
158
+ const qs = params2.toString();
159
+ const url = `${BASE_URL}/users${qs ? `?${qs}` : ""}`;
160
+ const res = await fetch(url, { method: "GET", headers: authHeaders() });
161
+ await assertOk(res, "listUsers");
162
+ return await res.json();
163
+ }
164
+ };
165
+ }
166
+
167
+ // ../connectors/src/connector-onboarding.ts
168
+ var ConnectorOnboarding = class {
169
+ /** Phase 1: Connection setup instructions (optional — some connectors don't need this) */
170
+ connectionSetupInstructions;
171
+ /** Phase 2: Data overview instructions */
172
+ dataOverviewInstructions;
173
+ constructor(config) {
174
+ this.connectionSetupInstructions = config.connectionSetupInstructions;
175
+ this.dataOverviewInstructions = config.dataOverviewInstructions;
176
+ }
177
+ getConnectionSetupPrompt(language) {
178
+ return this.connectionSetupInstructions?.[language] ?? null;
179
+ }
180
+ getDataOverviewInstructions(language) {
181
+ return this.dataOverviewInstructions[language];
182
+ }
183
+ };
184
+
185
+ // ../connectors/src/connector-tool.ts
186
+ var ConnectorTool = class {
187
+ name;
188
+ description;
189
+ inputSchema;
190
+ outputSchema;
191
+ _execute;
192
+ constructor(config) {
193
+ this.name = config.name;
194
+ this.description = config.description;
195
+ this.inputSchema = config.inputSchema;
196
+ this.outputSchema = config.outputSchema;
197
+ this._execute = config.execute;
198
+ }
199
+ createTool(connections, config) {
200
+ return {
201
+ description: this.description,
202
+ inputSchema: this.inputSchema,
203
+ outputSchema: this.outputSchema,
204
+ execute: (input) => this._execute(input, connections, config)
205
+ };
206
+ }
207
+ };
208
+
209
+ // ../connectors/src/connector-plugin.ts
210
+ var ConnectorPlugin = class _ConnectorPlugin {
211
+ slug;
212
+ authType;
213
+ name;
214
+ description;
215
+ iconUrl;
216
+ parameters;
217
+ releaseFlag;
218
+ proxyPolicy;
219
+ experimentalAttributes;
220
+ onboarding;
221
+ systemPrompt;
222
+ tools;
223
+ query;
224
+ checkConnection;
225
+ constructor(config) {
226
+ this.slug = config.slug;
227
+ this.authType = config.authType;
228
+ this.name = config.name;
229
+ this.description = config.description;
230
+ this.iconUrl = config.iconUrl;
231
+ this.parameters = config.parameters;
232
+ this.releaseFlag = config.releaseFlag;
233
+ this.proxyPolicy = config.proxyPolicy;
234
+ this.experimentalAttributes = config.experimentalAttributes;
235
+ this.onboarding = config.onboarding;
236
+ this.systemPrompt = config.systemPrompt;
237
+ this.tools = config.tools;
238
+ this.query = config.query;
239
+ this.checkConnection = config.checkConnection;
240
+ }
241
+ get connectorKey() {
242
+ return _ConnectorPlugin.deriveKey(this.slug, this.authType);
243
+ }
244
+ /**
245
+ * Create tools for connections that belong to this connector.
246
+ * Filters connections by connectorKey internally.
247
+ * Returns tools keyed as `${connectorKey}_${toolName}`.
248
+ */
249
+ createTools(connections, config) {
250
+ const myConnections = connections.filter(
251
+ (c) => _ConnectorPlugin.deriveKey(c.connector.slug, c.connector.authType) === this.connectorKey
252
+ );
253
+ const result = {};
254
+ for (const t of Object.values(this.tools)) {
255
+ result[`${this.connectorKey}_${t.name}`] = t.createTool(
256
+ myConnections,
257
+ config
258
+ );
259
+ }
260
+ return result;
261
+ }
262
+ static deriveKey(slug, authType) {
263
+ return authType ? `${slug}-${authType}` : slug;
264
+ }
265
+ };
266
+
267
+ // ../connectors/src/auth-types.ts
268
+ var AUTH_TYPES = {
269
+ OAUTH: "oauth",
270
+ API_KEY: "api-key",
271
+ JWT: "jwt",
272
+ SERVICE_ACCOUNT: "service-account",
273
+ PAT: "pat",
274
+ USER_PASSWORD: "user-password"
275
+ };
276
+
277
+ // ../connectors/src/connectors/notion/setup.ts
278
+ var notionOnboarding = new ConnectorOnboarding({
279
+ dataOverviewInstructions: {
280
+ en: `1. Call notion_request with POST /search and { "page_size": 5 } to discover available pages and databases
281
+ 2. For each database found, call notion_request with POST /databases/{database_id}/query and { "page_size": 5 } to sample records and understand the schema
282
+ 3. Call notion_request with GET /users to list workspace members
283
+ 4. Explore page content with GET /blocks/{page_id}/children as needed`,
284
+ ja: `1. notion_request \u3067 POST /search \u3092 { "page_size": 5 } \u3067\u547C\u3073\u51FA\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A\u30DA\u30FC\u30B8\u3068\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u691C\u51FA
285
+ 2. \u898B\u3064\u304B\u3063\u305F\u5404\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u3064\u3044\u3066\u3001notion_request \u3067 POST /databases/{database_id}/query \u3092 { "page_size": 5 } \u3067\u547C\u3073\u51FA\u3057\u3001\u30EC\u30B3\u30FC\u30C9\u306E\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0\u3068\u30B9\u30AD\u30FC\u30DE\u306E\u628A\u63E1\u3092\u884C\u3046
286
+ 3. notion_request \u3067 GET /users \u3092\u547C\u3073\u51FA\u3057\u3001\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u30E1\u30F3\u30D0\u30FC\u3092\u4E00\u89A7\u8868\u793A
287
+ 4. \u5FC5\u8981\u306B\u5FDC\u3058\u3066 GET /blocks/{page_id}/children \u3067\u30DA\u30FC\u30B8\u30B3\u30F3\u30C6\u30F3\u30C4\u3092\u63A2\u7D22`
288
+ }
289
+ });
290
+
291
+ // ../connectors/src/connectors/notion/tools/request.ts
292
+ import { z } from "zod";
293
+ var BASE_URL2 = "https://api.notion.com/v1";
294
+ var NOTION_VERSION2 = "2022-06-28";
295
+ var REQUEST_TIMEOUT_MS = 6e4;
296
+ var inputSchema = z.object({
297
+ toolUseIntent: z.string().optional().describe(
298
+ "Brief description of what you intend to accomplish with this tool call"
299
+ ),
300
+ connectionId: z.string().describe("ID of the Notion connection to use"),
301
+ method: z.enum(["GET", "POST", "PATCH", "DELETE"]).describe(
302
+ "HTTP method. GET for reading resources, POST for searching/querying/creating, PATCH for updating, DELETE for deleting."
303
+ ),
304
+ path: z.string().describe(
305
+ "API path (e.g., '/search', '/databases/{id}/query', '/pages/{id}', '/blocks/{id}/children')"
306
+ ),
307
+ body: z.record(z.string(), z.unknown()).optional().describe("Request body (JSON) for POST/PATCH requests")
308
+ });
309
+ var outputSchema = z.discriminatedUnion("success", [
310
+ z.object({
311
+ success: z.literal(true),
312
+ status: z.number(),
313
+ data: z.record(z.string(), z.unknown())
314
+ }),
315
+ z.object({
316
+ success: z.literal(false),
317
+ error: z.string()
318
+ })
319
+ ]);
320
+ var requestTool = new ConnectorTool({
321
+ name: "request",
322
+ description: `Send authenticated requests to the Notion API.
323
+ Authentication (Bearer token) and Notion-Version header are configured automatically.
324
+ Use this tool for all Notion API interactions: searching pages/databases, querying databases, retrieving pages and blocks, managing content.
325
+ Pagination uses cursor-based start_cursor and page_size (max 100).`,
326
+ inputSchema,
327
+ outputSchema,
328
+ async execute({ connectionId, method, path: path2, body }, connections) {
329
+ const connection2 = connections.find((c) => c.id === connectionId);
330
+ if (!connection2) {
331
+ return {
332
+ success: false,
333
+ error: `Connection ${connectionId} not found`
334
+ };
335
+ }
336
+ console.log(
337
+ `[connector-request] notion/${connection2.name}: ${method} ${path2}`
338
+ );
339
+ try {
340
+ const apiKey = parameters.apiKey.getValue(connection2);
341
+ const url = `${BASE_URL2}${path2.startsWith("/") ? "" : "/"}${path2}`;
342
+ const controller = new AbortController();
343
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
344
+ try {
345
+ const response = await fetch(url, {
346
+ method,
347
+ headers: {
348
+ Authorization: `Bearer ${apiKey}`,
349
+ "Notion-Version": NOTION_VERSION2,
350
+ "Content-Type": "application/json"
351
+ },
352
+ body: body ? JSON.stringify(body) : void 0,
353
+ signal: controller.signal
354
+ });
355
+ const data = await response.json();
356
+ if (!response.ok) {
357
+ const errorMessage = typeof data?.message === "string" ? data.message : typeof data?.code === "string" ? data.code : `HTTP ${response.status} ${response.statusText}`;
358
+ return { success: false, error: errorMessage };
359
+ }
360
+ return { success: true, status: response.status, data };
361
+ } finally {
362
+ clearTimeout(timeout);
363
+ }
364
+ } catch (err) {
365
+ const msg = err instanceof Error ? err.message : String(err);
366
+ return { success: false, error: msg };
367
+ }
368
+ }
369
+ });
370
+
371
+ // ../connectors/src/connectors/notion/index.ts
372
+ var tools = { request: requestTool };
373
+ var notionConnector = new ConnectorPlugin({
374
+ slug: "notion",
375
+ authType: AUTH_TYPES.API_KEY,
376
+ name: "Notion",
377
+ description: "Connect to Notion to query databases, pages, and workspace content using an Internal Integration Token.",
378
+ iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/797V5GDDTA8bsfKUHBCoQO/290ec49b70b68ddb4acd3bf0a6ab8bda/notion-icon.webp",
379
+ parameters,
380
+ releaseFlag: { dev1: true, dev2: false, prod: false },
381
+ onboarding: notionOnboarding,
382
+ systemPrompt: {
383
+ en: `### Tools
384
+
385
+ - \`notion_request\`: The only way to call the Notion REST API. Use it to search pages and databases, query database records, retrieve page content and blocks, and manage workspace data. Authentication (Bearer token) and Notion-Version header are configured automatically. Pagination uses cursor-based \`start_cursor\` and \`page_size\` (max 100) with \`has_more\` and \`next_cursor\` in the response.
386
+
387
+ ### Business Logic
388
+
389
+ The business logic type for this connector is "typescript". Use the connector SDK in your handler. Do NOT read credentials from environment variables.
390
+
391
+ SDK methods (client created via \`connection(connectionId)\`):
392
+ - \`client.request(path, init?)\` \u2014 low-level authenticated fetch
393
+ - \`client.search(options?)\` \u2014 search pages and databases by title
394
+ - \`client.queryDatabase(databaseId, options?)\` \u2014 query database records with filter/sorts/pagination
395
+ - \`client.getPage(pageId)\` \u2014 retrieve a page
396
+ - \`client.getDatabase(databaseId)\` \u2014 retrieve a database schema
397
+ - \`client.getBlockChildren(blockId, options?)\` \u2014 retrieve child blocks of a page or block
398
+ - \`client.listUsers(options?)\` \u2014 list workspace users
399
+
400
+ \`\`\`ts
401
+ import type { Context } from "hono";
402
+ import { connection } from "@squadbase/vite-server/connectors/notion";
403
+
404
+ const notion = connection("<connectionId>");
405
+
406
+ export default async function handler(c: Context) {
407
+ const { databaseId, pageSize = 25 } = await c.req.json<{
408
+ databaseId: string;
409
+ pageSize?: number;
410
+ }>();
411
+
412
+ const { results } = await notion.queryDatabase(databaseId, {
413
+ page_size: pageSize,
414
+ });
415
+
416
+ return c.json({ records: results });
417
+ }
418
+ \`\`\`
419
+
420
+ ### Notion REST API Reference
421
+
422
+ - Base URL: \`https://api.notion.com/v1\`
423
+ - Authentication: Bearer token (handled automatically)
424
+ - Notion-Version: 2022-06-28 (set automatically)
425
+ - Pagination: Cursor-based with \`start_cursor\`, \`page_size\` (max 100), \`has_more\`, \`next_cursor\`
426
+
427
+ #### Common Endpoints
428
+ - POST \`/search\` \u2014 Search pages and databases by title. Body: \`{ query, filter: { property: "object", value: "page"|"database" }, sort, start_cursor, page_size }\`
429
+ - GET \`/databases/{id}\` \u2014 Retrieve a database (schema, properties)
430
+ - POST \`/databases/{id}/query\` \u2014 Query a database. Body: \`{ filter, sorts, start_cursor, page_size }\`
431
+ - GET \`/pages/{id}\` \u2014 Retrieve a page (properties, metadata)
432
+ - GET \`/pages/{id}/properties/{property_id}\` \u2014 Retrieve a specific page property (for large properties)
433
+ - GET \`/blocks/{id}/children\` \u2014 List child blocks (page content). Query: \`start_cursor\`, \`page_size\`
434
+ - GET \`/blocks/{id}\` \u2014 Retrieve a single block
435
+ - PATCH \`/blocks/{id}/children\` \u2014 Append block children
436
+ - GET \`/users\` \u2014 List workspace users. Query: \`start_cursor\`, \`page_size\`
437
+ - GET \`/users/{id}\` \u2014 Retrieve a user
438
+ - GET \`/users/me\` \u2014 Get the bot user
439
+ - POST \`/pages\` \u2014 Create a page (in a database or as a child of a page)
440
+ - PATCH \`/pages/{id}\` \u2014 Update page properties
441
+ - POST \`/databases\` \u2014 Create a database
442
+ - PATCH \`/databases/{id}\` \u2014 Update a database
443
+ - PATCH \`/blocks/{id}\` \u2014 Update a block
444
+ - DELETE \`/blocks/{id}\` \u2014 Delete a block
445
+ - GET \`/comments?block_id={id}\` \u2014 Retrieve comments on a block or page
446
+ - POST \`/comments\` \u2014 Create a comment
447
+
448
+ #### Tips
449
+ - Use POST /search to discover databases and pages shared with the integration
450
+ - Database queries return page objects with properties matching the database schema
451
+ - Block children are only first-level; recurse for nested content
452
+ - Properties with more than 25 items (e.g., people, relation) need the property endpoint for full data`,
453
+ ja: `### \u30C4\u30FC\u30EB
454
+
455
+ - \`notion_request\`: Notion REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30DA\u30FC\u30B8\u3084\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u691C\u7D22\u3001\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30EC\u30B3\u30FC\u30C9\u306E\u30AF\u30A8\u30EA\u3001\u30DA\u30FC\u30B8\u30B3\u30F3\u30C6\u30F3\u30C4\u3084\u30D6\u30ED\u30C3\u30AF\u306E\u53D6\u5F97\u3001\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u30C7\u30FC\u30BF\u306E\u7BA1\u7406\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08Bearer\u30C8\u30FC\u30AF\u30F3\uFF09\u3068Notion-Version\u30D8\u30C3\u30C0\u30FC\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u306F\u30EC\u30B9\u30DD\u30F3\u30B9\u306E \`has_more\` \u3068 \`next_cursor\` \u306B\u3088\u308B\u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9\u3067\u3001\`start_cursor\` \u3068 \`page_size\`\uFF08\u6700\u5927100\uFF09\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
456
+
457
+ ### Business Logic
458
+
459
+ \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
460
+
461
+ SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8):
462
+ - \`client.request(path, init?)\` \u2014 \u4F4E\u30EC\u30D9\u30EB\u306E\u8A8D\u8A3C\u4ED8\u304Dfetch
463
+ - \`client.search(options?)\` \u2014 \u30BF\u30A4\u30C8\u30EB\u3067\u30DA\u30FC\u30B8\u3068\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u691C\u7D22
464
+ - \`client.queryDatabase(databaseId, options?)\` \u2014 \u30D5\u30A3\u30EB\u30BF/\u30BD\u30FC\u30C8/\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u4ED8\u304D\u3067\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30EC\u30B3\u30FC\u30C9\u3092\u30AF\u30A8\u30EA
465
+ - \`client.getPage(pageId)\` \u2014 \u30DA\u30FC\u30B8\u3092\u53D6\u5F97
466
+ - \`client.getDatabase(databaseId)\` \u2014 \u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30B9\u30AD\u30FC\u30DE\u3092\u53D6\u5F97
467
+ - \`client.getBlockChildren(blockId, options?)\` \u2014 \u30DA\u30FC\u30B8\u307E\u305F\u306F\u30D6\u30ED\u30C3\u30AF\u306E\u5B50\u30D6\u30ED\u30C3\u30AF\u3092\u53D6\u5F97
468
+ - \`client.listUsers(options?)\` \u2014 \u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u30E6\u30FC\u30B6\u30FC\u3092\u4E00\u89A7\u8868\u793A
469
+
470
+ \`\`\`ts
471
+ import type { Context } from "hono";
472
+ import { connection } from "@squadbase/vite-server/connectors/notion";
473
+
474
+ const notion = connection("<connectionId>");
475
+
476
+ export default async function handler(c: Context) {
477
+ const { databaseId, pageSize = 25 } = await c.req.json<{
478
+ databaseId: string;
479
+ pageSize?: number;
480
+ }>();
481
+
482
+ const { results } = await notion.queryDatabase(databaseId, {
483
+ page_size: pageSize,
484
+ });
485
+
486
+ return c.json({ records: results });
487
+ }
488
+ \`\`\`
489
+
490
+ ### Notion REST API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
491
+
492
+ - \u30D9\u30FC\u30B9URL: \`https://api.notion.com/v1\`
493
+ - \u8A8D\u8A3C: Bearer\u30C8\u30FC\u30AF\u30F3\uFF08\u81EA\u52D5\u8A2D\u5B9A\uFF09
494
+ - Notion-Version: 2022-06-28\uFF08\u81EA\u52D5\u8A2D\u5B9A\uFF09
495
+ - \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3: \u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9\uFF08\`start_cursor\`, \`page_size\`\uFF08\u6700\u5927100\uFF09, \`has_more\`, \`next_cursor\`\uFF09
496
+
497
+ #### \u4E3B\u8981\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8
498
+ - POST \`/search\` \u2014 \u30DA\u30FC\u30B8\u3068\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30BF\u30A4\u30C8\u30EB\u3067\u691C\u7D22\u3002Body: \`{ query, filter: { property: "object", value: "page"|"database" }, sort, start_cursor, page_size }\`
499
+ - GET \`/databases/{id}\` \u2014 \u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u53D6\u5F97\uFF08\u30B9\u30AD\u30FC\u30DE\u3001\u30D7\u30ED\u30D1\u30C6\u30A3\uFF09
500
+ - POST \`/databases/{id}/query\` \u2014 \u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30AF\u30A8\u30EA\u3002Body: \`{ filter, sorts, start_cursor, page_size }\`
501
+ - GET \`/pages/{id}\` \u2014 \u30DA\u30FC\u30B8\u3092\u53D6\u5F97\uFF08\u30D7\u30ED\u30D1\u30C6\u30A3\u3001\u30E1\u30BF\u30C7\u30FC\u30BF\uFF09
502
+ - GET \`/pages/{id}/properties/{property_id}\` \u2014 \u7279\u5B9A\u306E\u30DA\u30FC\u30B8\u30D7\u30ED\u30D1\u30C6\u30A3\u3092\u53D6\u5F97\uFF08\u5927\u304D\u306A\u30D7\u30ED\u30D1\u30C6\u30A3\u7528\uFF09
503
+ - GET \`/blocks/{id}/children\` \u2014 \u5B50\u30D6\u30ED\u30C3\u30AF\u3092\u4E00\u89A7\u8868\u793A\uFF08\u30DA\u30FC\u30B8\u30B3\u30F3\u30C6\u30F3\u30C4\uFF09\u3002Query: \`start_cursor\`, \`page_size\`
504
+ - GET \`/blocks/{id}\` \u2014 \u5358\u4E00\u30D6\u30ED\u30C3\u30AF\u3092\u53D6\u5F97
505
+ - PATCH \`/blocks/{id}/children\` \u2014 \u5B50\u30D6\u30ED\u30C3\u30AF\u3092\u8FFD\u52A0
506
+ - GET \`/users\` \u2014 \u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u30E6\u30FC\u30B6\u30FC\u3092\u4E00\u89A7\u8868\u793A\u3002Query: \`start_cursor\`, \`page_size\`
507
+ - GET \`/users/{id}\` \u2014 \u30E6\u30FC\u30B6\u30FC\u3092\u53D6\u5F97
508
+ - GET \`/users/me\` \u2014 \u30DC\u30C3\u30C8\u30E6\u30FC\u30B6\u30FC\u3092\u53D6\u5F97
509
+ - POST \`/pages\` \u2014 \u30DA\u30FC\u30B8\u3092\u4F5C\u6210\uFF08\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u5185\u307E\u305F\u306F\u30DA\u30FC\u30B8\u306E\u5B50\u3068\u3057\u3066\uFF09
510
+ - PATCH \`/pages/{id}\` \u2014 \u30DA\u30FC\u30B8\u30D7\u30ED\u30D1\u30C6\u30A3\u3092\u66F4\u65B0
511
+ - POST \`/databases\` \u2014 \u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u4F5C\u6210
512
+ - PATCH \`/databases/{id}\` \u2014 \u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u66F4\u65B0
513
+ - PATCH \`/blocks/{id}\` \u2014 \u30D6\u30ED\u30C3\u30AF\u3092\u66F4\u65B0
514
+ - DELETE \`/blocks/{id}\` \u2014 \u30D6\u30ED\u30C3\u30AF\u3092\u524A\u9664
515
+ - GET \`/comments?block_id={id}\` \u2014 \u30D6\u30ED\u30C3\u30AF\u307E\u305F\u306F\u30DA\u30FC\u30B8\u306E\u30B3\u30E1\u30F3\u30C8\u3092\u53D6\u5F97
516
+ - POST \`/comments\` \u2014 \u30B3\u30E1\u30F3\u30C8\u3092\u4F5C\u6210
517
+
518
+ #### \u30D2\u30F3\u30C8
519
+ - POST /search \u3092\u4F7F\u7528\u3057\u3066\u30A4\u30F3\u30C6\u30B0\u30EC\u30FC\u30B7\u30E7\u30F3\u3068\u5171\u6709\u3055\u308C\u305F\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3084\u30DA\u30FC\u30B8\u3092\u691C\u51FA\u3057\u307E\u3059
520
+ - \u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30AF\u30A8\u30EA\u306F\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30B9\u30AD\u30FC\u30DE\u306B\u4E00\u81F4\u3059\u308B\u30D7\u30ED\u30D1\u30C6\u30A3\u3092\u6301\u3064\u30DA\u30FC\u30B8\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3092\u8FD4\u3057\u307E\u3059
521
+ - \u30D6\u30ED\u30C3\u30AF\u306E\u5B50\u306F\u6700\u521D\u306E\u30EC\u30D9\u30EB\u306E\u307F\u3067\u3059\u3002\u30CD\u30B9\u30C8\u3055\u308C\u305F\u30B3\u30F3\u30C6\u30F3\u30C4\u306B\u306F\u518D\u5E30\u304C\u5FC5\u8981\u3067\u3059
522
+ - 25\u4EF6\u4EE5\u4E0A\u306E\u30A2\u30A4\u30C6\u30E0\u3092\u6301\u3064\u30D7\u30ED\u30D1\u30C6\u30A3\uFF08people\u3001relation\u306A\u3069\uFF09\u306F\u5B8C\u5168\u306A\u30C7\u30FC\u30BF\u53D6\u5F97\u306B\u30D7\u30ED\u30D1\u30C6\u30A3\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u304C\u5FC5\u8981\u3067\u3059`
523
+ },
524
+ tools
525
+ });
526
+
527
+ // src/connectors/create-connector-sdk.ts
528
+ import { readFileSync } from "fs";
529
+ import path from "path";
530
+
531
+ // src/connector-client/env.ts
532
+ function resolveEnvVar(entry, key, connectionId) {
533
+ const envVarName = entry.envVars[key];
534
+ if (!envVarName) {
535
+ throw new Error(`Connection "${connectionId}" is missing envVars mapping for key "${key}"`);
536
+ }
537
+ const value = process.env[envVarName];
538
+ if (!value) {
539
+ throw new Error(`Environment variable "${envVarName}" (for connection "${connectionId}", key "${key}") is not set`);
540
+ }
541
+ return value;
542
+ }
543
+ function resolveEnvVarOptional(entry, key) {
544
+ const envVarName = entry.envVars[key];
545
+ if (!envVarName) return void 0;
546
+ return process.env[envVarName] || void 0;
547
+ }
548
+
549
+ // src/connector-client/proxy-fetch.ts
550
+ import { getContext } from "hono/context-storage";
551
+ import { getCookie } from "hono/cookie";
552
+ var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
553
+ function createSandboxProxyFetch(connectionId) {
554
+ return async (input, init) => {
555
+ const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
556
+ const sandboxId = process.env.INTERNAL_SQUADBASE_SANDBOX_ID;
557
+ if (!token || !sandboxId) {
558
+ throw new Error(
559
+ "Connection proxy is not configured. Please check your deployment settings."
560
+ );
561
+ }
562
+ const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
563
+ const originalMethod = init?.method ?? "GET";
564
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
565
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
566
+ const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
567
+ return fetch(proxyUrl, {
568
+ method: "POST",
569
+ headers: {
570
+ "Content-Type": "application/json",
571
+ Authorization: `Bearer ${token}`
572
+ },
573
+ body: JSON.stringify({
574
+ url: originalUrl,
575
+ method: originalMethod,
576
+ body: originalBody
577
+ })
578
+ });
579
+ };
580
+ }
581
+ function createDeployedAppProxyFetch(connectionId) {
582
+ const projectId = process.env["SQUADBASE_PROJECT_ID"];
583
+ if (!projectId) {
584
+ throw new Error(
585
+ "Connection proxy is not configured. Please check your deployment settings."
586
+ );
587
+ }
588
+ const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
589
+ const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
590
+ return async (input, init) => {
591
+ const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
592
+ const originalMethod = init?.method ?? "GET";
593
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
594
+ const c = getContext();
595
+ const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
596
+ if (!appSession) {
597
+ throw new Error(
598
+ "No authentication method available for connection proxy."
599
+ );
600
+ }
601
+ return fetch(proxyUrl, {
602
+ method: "POST",
603
+ headers: {
604
+ "Content-Type": "application/json",
605
+ Authorization: `Bearer ${appSession}`
606
+ },
607
+ body: JSON.stringify({
608
+ url: originalUrl,
609
+ method: originalMethod,
610
+ body: originalBody
611
+ })
612
+ });
613
+ };
614
+ }
615
+ function createProxyFetch(connectionId) {
616
+ if (process.env.INTERNAL_SQUADBASE_SANDBOX_ID) {
617
+ return createSandboxProxyFetch(connectionId);
618
+ }
619
+ return createDeployedAppProxyFetch(connectionId);
620
+ }
621
+
622
+ // src/connectors/create-connector-sdk.ts
623
+ function loadConnectionsSync() {
624
+ const filePath = process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
625
+ try {
626
+ const raw = readFileSync(filePath, "utf-8");
627
+ return JSON.parse(raw);
628
+ } catch {
629
+ return {};
630
+ }
631
+ }
632
+ function createConnectorSdk(plugin, createClient2) {
633
+ return (connectionId) => {
634
+ const connections = loadConnectionsSync();
635
+ const entry = connections[connectionId];
636
+ if (!entry) {
637
+ throw new Error(
638
+ `Connection "${connectionId}" not found in .squadbase/connections.json`
639
+ );
640
+ }
641
+ if (entry.connector.slug !== plugin.slug) {
642
+ throw new Error(
643
+ `Connection "${connectionId}" is not a ${plugin.slug} connection (got "${entry.connector.slug}")`
644
+ );
645
+ }
646
+ const params = {};
647
+ for (const param of Object.values(plugin.parameters)) {
648
+ if (param.required) {
649
+ params[param.slug] = resolveEnvVar(entry, param.slug, connectionId);
650
+ } else {
651
+ const val = resolveEnvVarOptional(entry, param.slug);
652
+ if (val !== void 0) params[param.slug] = val;
653
+ }
654
+ }
655
+ return createClient2(params, createProxyFetch(connectionId));
656
+ };
657
+ }
658
+
659
+ // src/connectors/entries/notion.ts
660
+ var connection = createConnectorSdk(notionConnector, createClient);
661
+ export {
662
+ connection
663
+ };