@squadbase/vite-server 0.1.8 → 0.1.9-dev.3841401

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 (86) hide show
  1. package/dist/cli/index.js +73422 -59588
  2. package/dist/connectors/airtable-oauth.js +3 -0
  3. package/dist/connectors/airtable.js +3 -0
  4. package/dist/connectors/amplitude.js +3 -0
  5. package/dist/connectors/anthropic.js +3 -0
  6. package/dist/connectors/asana.js +18 -2
  7. package/dist/connectors/attio.js +3 -0
  8. package/dist/connectors/aws-billing.d.ts +5 -0
  9. package/dist/connectors/aws-billing.js +29843 -0
  10. package/dist/connectors/azure-sql.d.ts +5 -0
  11. package/dist/connectors/azure-sql.js +668 -0
  12. package/dist/connectors/backlog-api-key.js +3 -0
  13. package/dist/connectors/clickup.d.ts +5 -0
  14. package/dist/connectors/clickup.js +850 -0
  15. package/dist/connectors/customerio.js +3 -0
  16. package/dist/connectors/dbt.js +3 -0
  17. package/dist/connectors/freshdesk.d.ts +5 -0
  18. package/dist/connectors/freshdesk.js +842 -0
  19. package/dist/connectors/freshsales.d.ts +5 -0
  20. package/dist/connectors/freshsales.js +867 -0
  21. package/dist/connectors/freshservice.d.ts +5 -0
  22. package/dist/connectors/freshservice.js +813 -0
  23. package/dist/connectors/gamma.js +3 -0
  24. package/dist/connectors/gemini.js +3 -0
  25. package/dist/connectors/github.d.ts +5 -0
  26. package/dist/connectors/github.js +963 -0
  27. package/dist/connectors/gmail-oauth.js +18 -2
  28. package/dist/connectors/gmail.js +34 -16
  29. package/dist/connectors/google-ads.js +3 -0
  30. package/dist/connectors/google-analytics-oauth.js +3 -0
  31. package/dist/connectors/google-analytics.js +3 -0
  32. package/dist/connectors/google-audit-log.d.ts +5 -0
  33. package/dist/connectors/google-audit-log.js +813 -0
  34. package/dist/connectors/google-calendar-oauth.js +21 -2
  35. package/dist/connectors/google-calendar.js +140 -73
  36. package/dist/connectors/google-docs.js +21 -2
  37. package/dist/connectors/google-drive.js +18 -2
  38. package/dist/connectors/google-search-console-oauth.d.ts +5 -0
  39. package/dist/connectors/google-search-console-oauth.js +954 -0
  40. package/dist/connectors/google-sheets.js +21 -2
  41. package/dist/connectors/google-slides.js +21 -2
  42. package/dist/connectors/grafana.js +3 -0
  43. package/dist/connectors/hubspot-oauth.js +3 -0
  44. package/dist/connectors/hubspot.js +3 -0
  45. package/dist/connectors/influxdb.js +3 -0
  46. package/dist/connectors/intercom-oauth.js +3 -0
  47. package/dist/connectors/intercom.js +3 -0
  48. package/dist/connectors/jdbc.d.ts +5 -0
  49. package/dist/connectors/jdbc.js +21509 -0
  50. package/dist/connectors/jira-api-key.js +3 -0
  51. package/dist/connectors/kintone-api-token.js +3 -0
  52. package/dist/connectors/kintone.js +3 -0
  53. package/dist/connectors/linear.js +3 -0
  54. package/dist/connectors/linkedin-ads.js +3 -0
  55. package/dist/connectors/mailchimp-oauth.js +3 -0
  56. package/dist/connectors/mailchimp.js +3 -0
  57. package/dist/connectors/meta-ads-oauth.js +3 -0
  58. package/dist/connectors/meta-ads.js +3 -0
  59. package/dist/connectors/mixpanel.js +3 -0
  60. package/dist/connectors/monday.d.ts +5 -0
  61. package/dist/connectors/monday.js +853 -0
  62. package/dist/connectors/notion-oauth.js +3 -0
  63. package/dist/connectors/notion.js +3 -0
  64. package/dist/connectors/openai.js +3 -0
  65. package/dist/connectors/oracle.d.ts +5 -0
  66. package/dist/connectors/oracle.js +676 -0
  67. package/dist/connectors/salesforce.js +3 -0
  68. package/dist/connectors/semrush.d.ts +5 -0
  69. package/dist/connectors/semrush.js +812 -0
  70. package/dist/connectors/sentry.js +3 -0
  71. package/dist/connectors/shopify-oauth.js +3 -0
  72. package/dist/connectors/shopify.js +3 -0
  73. package/dist/connectors/sqlserver.d.ts +5 -0
  74. package/dist/connectors/sqlserver.js +667 -0
  75. package/dist/connectors/stripe-api-key.js +3 -0
  76. package/dist/connectors/stripe-oauth.js +3 -0
  77. package/dist/connectors/supabase.d.ts +5 -0
  78. package/dist/connectors/supabase.js +582 -0
  79. package/dist/connectors/tiktok-ads.js +18 -2
  80. package/dist/connectors/wix-store.js +3 -0
  81. package/dist/connectors/zendesk-oauth.js +3 -0
  82. package/dist/connectors/zendesk.js +3 -0
  83. package/dist/index.js +70184 -56350
  84. package/dist/main.js +70178 -56344
  85. package/dist/vite-plugin.js +71935 -58101
  86. package/package.json +64 -2
@@ -61,6 +61,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
61
61
  releaseFlag;
62
62
  proxyPolicy;
63
63
  experimentalAttributes;
64
+ categories;
64
65
  onboarding;
65
66
  systemPrompt;
66
67
  tools;
@@ -76,6 +77,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
76
77
  this.releaseFlag = config.releaseFlag;
77
78
  this.proxyPolicy = config.proxyPolicy;
78
79
  this.experimentalAttributes = config.experimentalAttributes;
80
+ this.categories = config.categories ?? [];
79
81
  this.onboarding = config.onboarding;
80
82
  this.systemPrompt = config.systemPrompt;
81
83
  this.tools = config.tools;
@@ -318,6 +320,7 @@ var stripeOauthConnector = new ConnectorPlugin({
318
320
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/2QNK0u2doqp41uL0POS4Ks/7a92367e2388ec77c7f4ada143606f9a/stripe.jpeg",
319
321
  parameters,
320
322
  releaseFlag: { dev1: true, dev2: false, prod: false },
323
+ categories: ["finance"],
321
324
  onboarding: stripeOnboarding,
322
325
  proxyPolicy: {
323
326
  allowlist: [
@@ -0,0 +1,5 @@
1
+ import * as _squadbase_connectors_sdk from '@squadbase/connectors/sdk';
2
+
3
+ declare const connection: (connectionId: string) => _squadbase_connectors_sdk.SupabaseConnectorSdk;
4
+
5
+ export { connection };
@@ -0,0 +1,582 @@
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/supabase/parameters.ts
46
+ var parameters = {
47
+ connectionUrl: new ParameterDefinition({
48
+ slug: "connection-url",
49
+ name: "Supabase Connection URL",
50
+ description: "The Supabase Postgres connection string. Copy it from the Supabase dashboard (Project Settings \u2192 Database \u2192 Connection string). Use the Transaction pooler (port 6543) URL for serverless workloads, e.g. `postgresql://postgres.<project-ref>:<password>@aws-0-<region>.pooler.supabase.com:6543/postgres`.",
51
+ envVarBaseKey: "SUPABASE_DB_URL",
52
+ type: "text",
53
+ secret: true,
54
+ required: true
55
+ })
56
+ };
57
+
58
+ // ../connectors/src/connectors/supabase/sdk/index.ts
59
+ function createClient(params) {
60
+ const connectionUrl = params[parameters.connectionUrl.slug];
61
+ if (!connectionUrl) {
62
+ throw new Error(
63
+ `supabase: missing required parameter: ${parameters.connectionUrl.slug}`
64
+ );
65
+ }
66
+ async function runQuery(sql, queryParams) {
67
+ try {
68
+ const { Pool } = await import("pg");
69
+ const pool = new Pool({
70
+ connectionString: connectionUrl,
71
+ ssl: { rejectUnauthorized: false },
72
+ connectionTimeoutMillis: 1e4,
73
+ statement_timeout: 6e4
74
+ });
75
+ try {
76
+ const result = await pool.query(sql, queryParams);
77
+ return result.rows;
78
+ } finally {
79
+ await pool.end();
80
+ }
81
+ } catch (err) {
82
+ const msg = err instanceof Error ? err.message : String(err);
83
+ throw new Error(msg.replaceAll(connectionUrl, "***"));
84
+ }
85
+ }
86
+ return {
87
+ query: runQuery
88
+ };
89
+ }
90
+
91
+ // ../connectors/src/connector-onboarding.ts
92
+ var ConnectorOnboarding = class {
93
+ /** Phase 1: Connection setup instructions (optional — some connectors don't need this) */
94
+ connectionSetupInstructions;
95
+ /** Phase 2: Data overview instructions */
96
+ dataOverviewInstructions;
97
+ constructor(config) {
98
+ this.connectionSetupInstructions = config.connectionSetupInstructions;
99
+ this.dataOverviewInstructions = config.dataOverviewInstructions;
100
+ }
101
+ getConnectionSetupPrompt(language) {
102
+ return this.connectionSetupInstructions?.[language] ?? null;
103
+ }
104
+ getDataOverviewInstructions(language) {
105
+ return this.dataOverviewInstructions[language];
106
+ }
107
+ };
108
+
109
+ // ../connectors/src/connector-tool.ts
110
+ var ConnectorTool = class {
111
+ name;
112
+ description;
113
+ inputSchema;
114
+ outputSchema;
115
+ _execute;
116
+ constructor(config) {
117
+ this.name = config.name;
118
+ this.description = config.description;
119
+ this.inputSchema = config.inputSchema;
120
+ this.outputSchema = config.outputSchema;
121
+ this._execute = config.execute;
122
+ }
123
+ createTool(connections, config) {
124
+ return {
125
+ description: this.description,
126
+ inputSchema: this.inputSchema,
127
+ outputSchema: this.outputSchema,
128
+ execute: (input) => this._execute(input, connections, config)
129
+ };
130
+ }
131
+ };
132
+
133
+ // ../connectors/src/connector-plugin.ts
134
+ var ConnectorPlugin = class _ConnectorPlugin {
135
+ slug;
136
+ authType;
137
+ name;
138
+ description;
139
+ iconUrl;
140
+ parameters;
141
+ releaseFlag;
142
+ proxyPolicy;
143
+ experimentalAttributes;
144
+ categories;
145
+ onboarding;
146
+ systemPrompt;
147
+ tools;
148
+ query;
149
+ checkConnection;
150
+ constructor(config) {
151
+ this.slug = config.slug;
152
+ this.authType = config.authType;
153
+ this.name = config.name;
154
+ this.description = config.description;
155
+ this.iconUrl = config.iconUrl;
156
+ this.parameters = config.parameters;
157
+ this.releaseFlag = config.releaseFlag;
158
+ this.proxyPolicy = config.proxyPolicy;
159
+ this.experimentalAttributes = config.experimentalAttributes;
160
+ this.categories = config.categories ?? [];
161
+ this.onboarding = config.onboarding;
162
+ this.systemPrompt = config.systemPrompt;
163
+ this.tools = config.tools;
164
+ this.query = config.query;
165
+ this.checkConnection = config.checkConnection;
166
+ }
167
+ get connectorKey() {
168
+ return _ConnectorPlugin.deriveKey(this.slug, this.authType);
169
+ }
170
+ /**
171
+ * Create tools for connections that belong to this connector.
172
+ * Filters connections by connectorKey internally.
173
+ * Returns tools keyed as `${connectorKey}_${toolName}`.
174
+ */
175
+ createTools(connections, config, opts) {
176
+ const myConnections = connections.filter(
177
+ (c) => _ConnectorPlugin.deriveKey(c.connector.slug, c.connector.authType) === this.connectorKey
178
+ );
179
+ const result = {};
180
+ for (const t of Object.values(this.tools)) {
181
+ const tool = t.createTool(myConnections, config);
182
+ const originalToModelOutput = tool.toModelOutput;
183
+ result[`${this.connectorKey}_${t.name}`] = {
184
+ ...tool,
185
+ toModelOutput: async (options) => {
186
+ if (!originalToModelOutput) {
187
+ return opts.truncateOutput(options.output);
188
+ }
189
+ const modelOutput = await originalToModelOutput(options);
190
+ if (modelOutput.type === "text" || modelOutput.type === "json") {
191
+ return opts.truncateOutput(modelOutput.value);
192
+ }
193
+ return modelOutput;
194
+ }
195
+ };
196
+ }
197
+ return result;
198
+ }
199
+ static deriveKey(slug, authType) {
200
+ if (authType) return `${slug}-${authType}`;
201
+ const LEGACY_NULL_AUTH_TYPE_MAP = {
202
+ // user-password
203
+ "postgresql": "user-password",
204
+ "mysql": "user-password",
205
+ "clickhouse": "user-password",
206
+ "kintone": "user-password",
207
+ "squadbase-db": "user-password",
208
+ // service-account
209
+ "snowflake": "service-account",
210
+ "bigquery": "service-account",
211
+ "google-analytics": "service-account",
212
+ "google-calendar": "service-account",
213
+ "aws-athena": "service-account",
214
+ "redshift": "service-account",
215
+ // api-key
216
+ "databricks": "api-key",
217
+ "dbt": "api-key",
218
+ "airtable": "api-key",
219
+ "openai": "api-key",
220
+ "gemini": "api-key",
221
+ "anthropic": "api-key",
222
+ "wix-store": "api-key"
223
+ };
224
+ const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
225
+ if (fallbackAuthType) return `${slug}-${fallbackAuthType}`;
226
+ return slug;
227
+ }
228
+ };
229
+
230
+ // ../connectors/src/auth-types.ts
231
+ var AUTH_TYPES = {
232
+ OAUTH: "oauth",
233
+ API_KEY: "api-key",
234
+ JWT: "jwt",
235
+ SERVICE_ACCOUNT: "service-account",
236
+ PAT: "pat",
237
+ USER_PASSWORD: "user-password"
238
+ };
239
+
240
+ // ../connectors/src/lib/query-utils.ts
241
+ function buildPositionalParams(sql, namedParams) {
242
+ if (!namedParams) return { text: sql, values: [] };
243
+ const values = [];
244
+ const nameToIndex = /* @__PURE__ */ new Map();
245
+ const text = sql.replace(/\{\{(\w+)\}\}/g, (_match, name) => {
246
+ if (!nameToIndex.has(name)) {
247
+ values.push(namedParams[name] ?? null);
248
+ nameToIndex.set(name, values.length);
249
+ }
250
+ return `$${nameToIndex.get(name)}`;
251
+ });
252
+ return { text, values };
253
+ }
254
+
255
+ // ../connectors/src/connectors/supabase/setup.ts
256
+ var supabaseOnboarding = new ConnectorOnboarding({
257
+ dataOverviewInstructions: {
258
+ en: `1. Use executeQuery to list tables in the \`public\` schema: \`SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'\`
259
+ 2. Most Supabase projects also expose Auth/Storage tables in dedicated schemas (\`auth\`, \`storage\`). Inspect them with \`SELECT table_schema, table_name FROM information_schema.tables WHERE table_schema IN ('auth', 'storage')\` only when the user explicitly needs them
260
+ 3. For key tables, fetch column info: \`SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'xxx'\`
261
+ 4. Sample up to 3 tables with \`SELECT * FROM <table_name> LIMIT 5\` if column info alone is insufficient`,
262
+ ja: `1. executeQuery \u3067 \`public\` \u30B9\u30AD\u30FC\u30DE\u306E\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7\u3092\u53D6\u5F97: \`SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'\`
263
+ 2. Supabase\u306F Auth / Storage \u7528\u306E\u30C6\u30FC\u30D6\u30EB\u3092 \`auth\` / \`storage\` \u30B9\u30AD\u30FC\u30DE\u306B\u6301\u3061\u307E\u3059\u3002\u30E6\u30FC\u30B6\u30FC\u304C\u660E\u793A\u7684\u306B\u5FC5\u8981\u3068\u3057\u3066\u3044\u308B\u5834\u5408\u306E\u307F \`SELECT table_schema, table_name FROM information_schema.tables WHERE table_schema IN ('auth', 'storage')\` \u3067\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044
264
+ 3. \u4E3B\u8981\u30C6\u30FC\u30D6\u30EB\u306E\u30AB\u30E9\u30E0\u60C5\u5831\u3092\u53D6\u5F97: \`SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'xxx'\`
265
+ 4. \u30AB\u30E9\u30E0\u60C5\u5831\u3060\u3051\u3067\u306F\u4E0D\u5341\u5206\u306A\u5834\u5408\u3001\u6700\u59273\u30C6\u30FC\u30D6\u30EB\u3092 \`SELECT * FROM <table_name> LIMIT 5\` \u3067\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0`
266
+ }
267
+ });
268
+
269
+ // ../connectors/src/connectors/supabase/tools/execute-query.ts
270
+ import { z } from "zod";
271
+ var MAX_ROWS = 500;
272
+ var CONNECT_TIMEOUT_MS = 1e4;
273
+ var STATEMENT_TIMEOUT_MS = 6e4;
274
+ var inputSchema = z.object({
275
+ toolUseIntent: z.string().optional().describe(
276
+ "Brief description of what you intend to accomplish with this tool call"
277
+ ),
278
+ connectionId: z.string().describe("ID of the Supabase connection to use"),
279
+ sql: z.string().describe(
280
+ "PostgreSQL SQL query targeting the Supabase project. Use the `public` schema unless the user explicitly references Supabase Auth (`auth.*`) or Storage (`storage.*`). Always include LIMIT."
281
+ )
282
+ });
283
+ var outputSchema = z.discriminatedUnion("success", [
284
+ z.object({
285
+ success: z.literal(true),
286
+ rowCount: z.number(),
287
+ truncated: z.boolean(),
288
+ rows: z.array(z.record(z.string(), z.unknown()))
289
+ }),
290
+ z.object({
291
+ success: z.literal(false),
292
+ error: z.string()
293
+ })
294
+ ]);
295
+ var executeQueryTool = new ConnectorTool({
296
+ name: "executeQuery",
297
+ description: `Execute SQL against a Supabase Postgres database. Returns up to ${MAX_ROWS} rows.
298
+ Use for: schema exploration (information_schema), data sampling, and analytical queries against Supabase tables.
299
+ User tables live in the \`public\` schema by default; Supabase-managed metadata lives in \`auth\` and \`storage\`.
300
+ Avoid loading large amounts of data; always include LIMIT in queries.`,
301
+ inputSchema,
302
+ outputSchema,
303
+ async execute({ connectionId, sql }, connections) {
304
+ const connection2 = connections.find((c) => c.id === connectionId);
305
+ if (!connection2) {
306
+ return {
307
+ success: false,
308
+ error: `Connection ${connectionId} not found`
309
+ };
310
+ }
311
+ console.log(
312
+ `[connector-query] supabase/${connection2.name}: ${sql}`
313
+ );
314
+ let connectionUrl;
315
+ try {
316
+ const { Pool } = await import("pg");
317
+ connectionUrl = parameters.connectionUrl.getValue(connection2);
318
+ const pool = new Pool({
319
+ connectionString: connectionUrl,
320
+ ssl: { rejectUnauthorized: false },
321
+ connectionTimeoutMillis: CONNECT_TIMEOUT_MS,
322
+ statement_timeout: STATEMENT_TIMEOUT_MS
323
+ });
324
+ try {
325
+ const result = await pool.query(sql);
326
+ const rows = result.rows;
327
+ const truncated = rows.length > MAX_ROWS;
328
+ return {
329
+ success: true,
330
+ rowCount: Math.min(rows.length, MAX_ROWS),
331
+ truncated,
332
+ rows: rows.slice(0, MAX_ROWS)
333
+ };
334
+ } finally {
335
+ await pool.end();
336
+ }
337
+ } catch (err) {
338
+ let msg = err instanceof Error ? err.message : String(err);
339
+ if (connectionUrl) {
340
+ msg = msg.replaceAll(connectionUrl, "***");
341
+ }
342
+ return { success: false, error: msg };
343
+ }
344
+ }
345
+ });
346
+
347
+ // ../connectors/src/connectors/supabase/index.ts
348
+ var tools = { executeQuery: executeQueryTool };
349
+ var supabaseConnector = new ConnectorPlugin({
350
+ slug: "supabase",
351
+ authType: AUTH_TYPES.USER_PASSWORD,
352
+ name: "Supabase",
353
+ description: "Connect to a Supabase project's Postgres database to query application tables and Supabase-managed schemas (auth, storage).",
354
+ iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/14k0U6F9PVovVjYjWyNzKb/2c4ff53adbe9334a63fee0a13d9f050a/supabase-icon.webp",
355
+ parameters,
356
+ releaseFlag: { dev1: true, dev2: true, prod: true },
357
+ categories: ["database"],
358
+ onboarding: supabaseOnboarding,
359
+ systemPrompt: {
360
+ en: `### Tools
361
+
362
+ - \`supabase_executeQuery\`: Executes a PostgreSQL query against the Supabase project's database and returns rows. Use this for schema exploration via \`information_schema.tables\`/\`columns\` and for sampling data. See the SQL Reference below for syntax notes and Supabase-specific schemas.
363
+
364
+ ### Business Logic
365
+
366
+ The business logic type for this connector is "sql".
367
+
368
+ ### SQL Reference
369
+ - Schema layout:
370
+ - User tables live in the \`public\` schema by default.
371
+ - Supabase Auth tables live in the \`auth\` schema (e.g. \`auth.users\`).
372
+ - Supabase Storage tables live in the \`storage\` schema (e.g. \`storage.objects\`, \`storage.buckets\`).
373
+ - Schema exploration:
374
+ - List user tables: \`SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'\`
375
+ - List columns: \`SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'xxx'\`
376
+ - Always include LIMIT in queries`,
377
+ ja: `### \u30C4\u30FC\u30EB
378
+
379
+ - \`supabase_executeQuery\`: Supabase\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E Postgres \u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u5BFE\u3057\u3066\u30AF\u30A8\u30EA\u3092\u5B9F\u884C\u3057\u3001\u884C\u30C7\u30FC\u30BF\u3092\u8FD4\u3057\u307E\u3059\u3002\`information_schema.tables\`/\`columns\` \u3092\u4F7F\u3063\u305F\u30B9\u30AD\u30FC\u30DE\u63A2\u7D22\u3084\u30C7\u30FC\u30BF\u306E\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0\u306B\u4F7F\u3044\u307E\u3059\u3002\u69CB\u6587\u306E\u6CE8\u610F\u70B9\u3068 Supabase \u56FA\u6709\u306E\u30B9\u30AD\u30FC\u30DE\u306F\u4E0B\u90E8\u306E\u300CSQL \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
380
+
381
+ ### Business Logic
382
+
383
+ \u3053\u306E\u30B3\u30CD\u30AF\u30BF\u306E\u30D3\u30B8\u30CD\u30B9\u30ED\u30B8\u30C3\u30AF\u30BF\u30A4\u30D7\u306F "sql" \u3067\u3059\u3002
384
+
385
+ ### SQL \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
386
+ - \u30B9\u30AD\u30FC\u30DE\u69CB\u6210:
387
+ - \u30E6\u30FC\u30B6\u30FC\u306E\u30C6\u30FC\u30D6\u30EB\u306F\u30C7\u30D5\u30A9\u30EB\u30C8\u3067 \`public\` \u30B9\u30AD\u30FC\u30DE\u306B\u5B58\u5728\u3057\u307E\u3059\u3002
388
+ - Supabase Auth \u306E\u30C6\u30FC\u30D6\u30EB\u306F \`auth\` \u30B9\u30AD\u30FC\u30DE\u306B\u5B58\u5728\u3057\u307E\u3059\uFF08\u4F8B: \`auth.users\`\uFF09\u3002
389
+ - Supabase Storage \u306E\u30C6\u30FC\u30D6\u30EB\u306F \`storage\` \u30B9\u30AD\u30FC\u30DE\u306B\u5B58\u5728\u3057\u307E\u3059\uFF08\u4F8B: \`storage.objects\`, \`storage.buckets\`\uFF09\u3002
390
+ - \u30B9\u30AD\u30FC\u30DE\u63A2\u7D22:
391
+ - \u30E6\u30FC\u30B6\u30FC\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7: \`SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'\`
392
+ - \u30AB\u30E9\u30E0\u4E00\u89A7: \`SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'xxx'\`
393
+ - \u30AF\u30A8\u30EA\u306B\u306F\u5FC5\u305A LIMIT \u3092\u542B\u3081\u3066\u304F\u3060\u3055\u3044`
394
+ },
395
+ tools,
396
+ async checkConnection(params, _config) {
397
+ const { Pool } = await import("pg");
398
+ const connectionUrl = params[parameters.connectionUrl.slug];
399
+ const pool = new Pool({
400
+ connectionString: connectionUrl,
401
+ ssl: { rejectUnauthorized: false },
402
+ connectionTimeoutMillis: 1e4
403
+ });
404
+ try {
405
+ await pool.query("SELECT 1");
406
+ return { success: true };
407
+ } catch (error) {
408
+ return {
409
+ success: false,
410
+ error: error instanceof Error ? error.message : String(error)
411
+ };
412
+ } finally {
413
+ await pool.end();
414
+ }
415
+ },
416
+ async query(params, sql, namedParams) {
417
+ const { Pool } = await import("pg");
418
+ const cleanSql = sql.replace(/;\s*$/, "");
419
+ const { text, values } = buildPositionalParams(cleanSql, namedParams);
420
+ const connectionUrl = params[parameters.connectionUrl.slug];
421
+ const pool = new Pool({
422
+ connectionString: connectionUrl,
423
+ ssl: { rejectUnauthorized: false },
424
+ connectionTimeoutMillis: 1e4,
425
+ statement_timeout: 6e4
426
+ });
427
+ try {
428
+ const result = await pool.query(text, values);
429
+ return { rows: result.rows };
430
+ } finally {
431
+ await pool.end();
432
+ }
433
+ }
434
+ });
435
+
436
+ // src/connectors/create-connector-sdk.ts
437
+ import { readFileSync } from "fs";
438
+ import path from "path";
439
+
440
+ // src/connector-client/env.ts
441
+ function resolveEnvVar(entry, key, connectionId) {
442
+ const envVarName = entry.envVars[key];
443
+ if (!envVarName) {
444
+ throw new Error(`Connection "${connectionId}" is missing envVars mapping for key "${key}"`);
445
+ }
446
+ const value = process.env[envVarName];
447
+ if (!value) {
448
+ throw new Error(`Environment variable "${envVarName}" (for connection "${connectionId}", key "${key}") is not set`);
449
+ }
450
+ return value;
451
+ }
452
+ function resolveEnvVarOptional(entry, key) {
453
+ const envVarName = entry.envVars[key];
454
+ if (!envVarName) return void 0;
455
+ return process.env[envVarName] || void 0;
456
+ }
457
+
458
+ // src/connector-client/proxy-fetch.ts
459
+ import { getContext } from "hono/context-storage";
460
+ import { getCookie } from "hono/cookie";
461
+ var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
462
+ function normalizeHeaders(input) {
463
+ const out = {};
464
+ if (!input) return out;
465
+ new Headers(input).forEach((value, key) => {
466
+ out[key] = value;
467
+ });
468
+ return out;
469
+ }
470
+ function createSandboxProxyFetch(connectionId) {
471
+ return async (input, init) => {
472
+ const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
473
+ const sandboxId = process.env.INTERNAL_SQUADBASE_SANDBOX_ID;
474
+ if (!token || !sandboxId) {
475
+ throw new Error(
476
+ "Connection proxy is not configured. Please check your deployment settings."
477
+ );
478
+ }
479
+ const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
480
+ const originalMethod = init?.method ?? "GET";
481
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
482
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
483
+ const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
484
+ return fetch(proxyUrl, {
485
+ method: "POST",
486
+ headers: {
487
+ "Content-Type": "application/json",
488
+ Authorization: `Bearer ${token}`
489
+ },
490
+ body: JSON.stringify({
491
+ url: originalUrl,
492
+ method: originalMethod,
493
+ headers: normalizeHeaders(init?.headers),
494
+ body: originalBody
495
+ })
496
+ });
497
+ };
498
+ }
499
+ function createDeployedAppProxyFetch(connectionId) {
500
+ const projectId = process.env["SQUADBASE_PROJECT_ID"];
501
+ if (!projectId) {
502
+ throw new Error(
503
+ "Connection proxy is not configured. Please check your deployment settings."
504
+ );
505
+ }
506
+ const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
507
+ const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
508
+ return async (input, init) => {
509
+ const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
510
+ const originalMethod = init?.method ?? "GET";
511
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
512
+ const c = getContext();
513
+ const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
514
+ if (!appSession) {
515
+ throw new Error(
516
+ "No authentication method available for connection proxy."
517
+ );
518
+ }
519
+ return fetch(proxyUrl, {
520
+ method: "POST",
521
+ headers: {
522
+ "Content-Type": "application/json",
523
+ Authorization: `Bearer ${appSession}`
524
+ },
525
+ body: JSON.stringify({
526
+ url: originalUrl,
527
+ method: originalMethod,
528
+ headers: normalizeHeaders(init?.headers),
529
+ body: originalBody
530
+ })
531
+ });
532
+ };
533
+ }
534
+ function createProxyFetch(connectionId) {
535
+ if (process.env.INTERNAL_SQUADBASE_SANDBOX_ID) {
536
+ return createSandboxProxyFetch(connectionId);
537
+ }
538
+ return createDeployedAppProxyFetch(connectionId);
539
+ }
540
+
541
+ // src/connectors/create-connector-sdk.ts
542
+ function loadConnectionsSync() {
543
+ const filePath = process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
544
+ try {
545
+ const raw = readFileSync(filePath, "utf-8");
546
+ return JSON.parse(raw);
547
+ } catch {
548
+ return {};
549
+ }
550
+ }
551
+ function createConnectorSdk(plugin, createClient2) {
552
+ return (connectionId) => {
553
+ const connections = loadConnectionsSync();
554
+ const entry = connections[connectionId];
555
+ if (!entry) {
556
+ throw new Error(
557
+ `Connection "${connectionId}" not found in .squadbase/connections.json`
558
+ );
559
+ }
560
+ if (entry.connector.slug !== plugin.slug) {
561
+ throw new Error(
562
+ `Connection "${connectionId}" is not a ${plugin.slug} connection (got "${entry.connector.slug}")`
563
+ );
564
+ }
565
+ const params = {};
566
+ for (const param of Object.values(plugin.parameters)) {
567
+ if (param.required) {
568
+ params[param.slug] = resolveEnvVar(entry, param.slug, connectionId);
569
+ } else {
570
+ const val = resolveEnvVarOptional(entry, param.slug);
571
+ if (val !== void 0) params[param.slug] = val;
572
+ }
573
+ }
574
+ return createClient2(params, createProxyFetch(connectionId));
575
+ };
576
+ }
577
+
578
+ // src/connectors/entries/supabase.ts
579
+ var connection = createConnectorSdk(supabaseConnector, createClient);
580
+ export {
581
+ connection
582
+ };
@@ -105,6 +105,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
105
105
  releaseFlag;
106
106
  proxyPolicy;
107
107
  experimentalAttributes;
108
+ categories;
108
109
  onboarding;
109
110
  systemPrompt;
110
111
  tools;
@@ -120,6 +121,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
120
121
  this.releaseFlag = config.releaseFlag;
121
122
  this.proxyPolicy = config.proxyPolicy;
122
123
  this.experimentalAttributes = config.experimentalAttributes;
124
+ this.categories = config.categories ?? [];
123
125
  this.onboarding = config.onboarding;
124
126
  this.systemPrompt = config.systemPrompt;
125
127
  this.tools = config.tools;
@@ -199,6 +201,16 @@ var AUTH_TYPES = {
199
201
  USER_PASSWORD: "user-password"
200
202
  };
201
203
 
204
+ // ../connectors/src/lib/normalize-path.ts
205
+ function normalizeRequestPath(path2, basePathSegment) {
206
+ let p = path2.trim();
207
+ if (!p.startsWith("/")) p = "/" + p;
208
+ if (p === basePathSegment || p.startsWith(basePathSegment + "/")) {
209
+ p = p.slice(basePathSegment.length) || "/";
210
+ }
211
+ return p;
212
+ }
213
+
202
214
  // ../connectors/src/connectors/tiktok-ads/tools/list-advertisers.ts
203
215
  import { z } from "zod";
204
216
  var BASE_URL2 = "https://business-api.tiktok.com/open_api/v1.3/";
@@ -373,7 +385,9 @@ var parameters = {
373
385
 
374
386
  // ../connectors/src/connectors/tiktok-ads/tools/request.ts
375
387
  import { z as z2 } from "zod";
376
- var BASE_URL3 = "https://business-api.tiktok.com/open_api/v1.3/";
388
+ var BASE_HOST = "https://business-api.tiktok.com";
389
+ var BASE_PATH_SEGMENT = "/open_api/v1.3";
390
+ var BASE_URL3 = `${BASE_HOST}${BASE_PATH_SEGMENT}`;
377
391
  var REQUEST_TIMEOUT_MS2 = 6e4;
378
392
  var cachedToken2 = null;
379
393
  async function getProxyToken2(config) {
@@ -449,7 +463,8 @@ The advertiser_id is automatically injected if configured.`,
449
463
  );
450
464
  try {
451
465
  const advertiserId = parameters.advertiserId.tryGetValue(connection2) ?? "";
452
- let url = `${BASE_URL3}${path2}`;
466
+ const normalizedPath = normalizeRequestPath(path2, BASE_PATH_SEGMENT);
467
+ let url = `${BASE_URL3}${normalizedPath}`;
453
468
  if (method === "GET") {
454
469
  const params = new URLSearchParams(queryParams ?? {});
455
470
  if (advertiserId && !params.has("advertiser_id")) {
@@ -519,6 +534,7 @@ var tiktokAdsConnector = new ConnectorPlugin({
519
534
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/01jHuwvmhe4ts0wj23Hxpm/afac9fa50ac5b353927900a122e898ab/tiktok.webp",
520
535
  parameters,
521
536
  releaseFlag: { dev1: true, dev2: false, prod: false },
537
+ categories: ["marketing"],
522
538
  onboarding: tiktokAdsOnboarding,
523
539
  proxyPolicy: {
524
540
  allowlist: [
@@ -252,6 +252,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
252
252
  releaseFlag;
253
253
  proxyPolicy;
254
254
  experimentalAttributes;
255
+ categories;
255
256
  onboarding;
256
257
  systemPrompt;
257
258
  tools;
@@ -267,6 +268,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
267
268
  this.releaseFlag = config.releaseFlag;
268
269
  this.proxyPolicy = config.proxyPolicy;
269
270
  this.experimentalAttributes = config.experimentalAttributes;
271
+ this.categories = config.categories ?? [];
270
272
  this.onboarding = config.onboarding;
271
273
  this.systemPrompt = config.systemPrompt;
272
274
  this.tools = config.tools;
@@ -438,6 +440,7 @@ var wixStoreConnector = new ConnectorPlugin({
438
440
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/YyFxclQFzROIYpFam6vRK/e7e75d3feac49a1cc5e433c147216d23/Wix_logo_black.svg",
439
441
  parameters,
440
442
  releaseFlag: { dev1: true, dev2: true, prod: true },
443
+ categories: ["ecommerce"],
441
444
  onboarding: wixStoreOnboarding,
442
445
  systemPrompt: {
443
446
  en: `### Tools