@squadbase/vite-server 0.1.17 → 0.1.19-dev.a00d9c3
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 +5961 -2986
- package/dist/connectors/airtable-oauth.js +39 -15
- package/dist/connectors/airtable.js +86 -15
- package/dist/connectors/amplitude.js +39 -15
- package/dist/connectors/anthropic.js +39 -15
- package/dist/connectors/asana.js +39 -15
- package/dist/connectors/attio.js +39 -15
- package/dist/connectors/aws-billing.js +39 -15
- package/dist/connectors/azure-sql.js +291 -18
- package/dist/connectors/backlog-api-key.js +39 -15
- package/dist/connectors/clickup.js +39 -15
- package/dist/connectors/cosmosdb.js +39 -15
- package/dist/connectors/customerio.js +39 -15
- package/dist/connectors/dbt.js +39 -15
- package/dist/connectors/freshdesk.js +39 -15
- package/dist/connectors/freshsales.js +39 -15
- package/dist/connectors/freshservice.js +39 -15
- package/dist/connectors/gamma.js +39 -15
- package/dist/connectors/gemini.js +39 -15
- package/dist/connectors/github.js +39 -15
- package/dist/connectors/gmail-oauth.js +32 -13
- package/dist/connectors/gmail.js +39 -15
- package/dist/connectors/google-ads.js +39 -15
- package/dist/connectors/google-analytics-oauth.js +40 -16
- package/dist/connectors/google-analytics.js +39 -15
- package/dist/connectors/google-audit-log.js +39 -15
- package/dist/connectors/google-calendar-oauth.js +40 -16
- package/dist/connectors/google-calendar.js +39 -15
- package/dist/connectors/google-docs.js +32 -13
- package/dist/connectors/google-drive.js +32 -13
- package/dist/connectors/google-search-console-oauth.js +39 -15
- package/dist/connectors/google-sheets.js +138 -195
- package/dist/connectors/google-slides.js +32 -13
- package/dist/connectors/grafana.js +39 -15
- package/dist/connectors/hackernews.d.ts +5 -0
- package/dist/connectors/hackernews.js +909 -0
- package/dist/connectors/hubspot-oauth.js +32 -13
- package/dist/connectors/hubspot.js +39 -15
- package/dist/connectors/influxdb.js +39 -15
- package/dist/connectors/intercom-oauth.js +32 -13
- package/dist/connectors/intercom.js +39 -15
- package/dist/connectors/jdbc.js +70 -19
- package/dist/connectors/jira-api-key.js +39 -15
- package/dist/connectors/kintone-api-token.js +39 -15
- package/dist/connectors/kintone.js +128 -15
- package/dist/connectors/linear.js +39 -15
- package/dist/connectors/linkedin-ads.js +39 -15
- package/dist/connectors/mailchimp-oauth.js +39 -15
- package/dist/connectors/mailchimp.js +39 -15
- package/dist/connectors/meta-ads-oauth.js +39 -15
- package/dist/connectors/meta-ads.js +39 -15
- package/dist/connectors/mixpanel.js +39 -15
- package/dist/connectors/monday.js +39 -15
- package/dist/connectors/mongodb.js +39 -15
- package/dist/connectors/notion-oauth.js +32 -13
- package/dist/connectors/notion.js +84 -15
- package/dist/connectors/openai.js +39 -15
- package/dist/connectors/oracle.js +293 -19
- package/dist/connectors/outlook-oauth.js +33 -14
- package/dist/connectors/powerbi-oauth.js +33 -14
- package/dist/connectors/salesforce.js +108 -15
- package/dist/connectors/semrush.js +39 -15
- package/dist/connectors/sentry.js +39 -15
- package/dist/connectors/shopify-oauth.js +32 -13
- package/dist/connectors/shopify.js +39 -15
- package/dist/connectors/slack.d.ts +5 -0
- package/dist/connectors/slack.js +656 -0
- package/dist/connectors/sqlserver.js +291 -18
- package/dist/connectors/stripe-api-key.js +39 -15
- package/dist/connectors/stripe-oauth.js +32 -13
- package/dist/connectors/supabase.js +293 -16
- package/dist/connectors/tableau.js +40 -16
- package/dist/connectors/tiktok-ads.js +39 -15
- package/dist/connectors/wix-store.js +39 -15
- package/dist/connectors/x.d.ts +5 -0
- package/dist/connectors/x.js +951 -0
- package/dist/connectors/zendesk-oauth.js +32 -13
- package/dist/connectors/zendesk.js +39 -15
- package/dist/index.js +6425 -3397
- package/dist/main.js +6425 -3397
- package/dist/vite-plugin.js +5965 -2987
- package/package.json +13 -4
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
2
|
-
var __esm = (fn, res) => function __init() {
|
|
3
|
-
|
|
2
|
+
var __esm = (fn, res, err) => function __init() {
|
|
3
|
+
if (err) throw err[0];
|
|
4
|
+
try {
|
|
5
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
|
+
} catch (e) {
|
|
7
|
+
throw err = [e], e;
|
|
8
|
+
}
|
|
4
9
|
};
|
|
5
10
|
|
|
6
11
|
// ../connectors/src/parameter-definition.ts
|
|
@@ -169,6 +174,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
169
174
|
* `runSetupFlow` from `setup-flow.ts`.
|
|
170
175
|
*/
|
|
171
176
|
setup;
|
|
177
|
+
/**
|
|
178
|
+
* 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
|
|
179
|
+
* メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
|
|
180
|
+
* {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
|
|
181
|
+
* 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
|
|
182
|
+
* `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
|
|
183
|
+
* coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
|
|
184
|
+
*/
|
|
185
|
+
introspect;
|
|
172
186
|
/**
|
|
173
187
|
* Opt-out of the default "verify before save" behavior on connection
|
|
174
188
|
* creation. The backend invokes `checkConnection` synchronously while
|
|
@@ -183,6 +197,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
183
197
|
* the default verify-on-create behavior without opt-in.
|
|
184
198
|
*/
|
|
185
199
|
skipConnectionCheckOnCreate;
|
|
200
|
+
/**
|
|
201
|
+
* 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
|
|
202
|
+
* read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
|
|
203
|
+
* recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
|
|
204
|
+
* driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
|
|
205
|
+
* 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
|
|
206
|
+
*/
|
|
207
|
+
surveyProbes;
|
|
186
208
|
constructor(config) {
|
|
187
209
|
this.slug = config.slug;
|
|
188
210
|
this.authType = config.authType;
|
|
@@ -200,7 +222,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
200
222
|
this.query = config.query;
|
|
201
223
|
this.checkConnection = config.checkConnection;
|
|
202
224
|
this.setup = config.setup;
|
|
225
|
+
this.introspect = config.introspect;
|
|
203
226
|
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
227
|
+
this.surveyProbes = config.surveyProbes;
|
|
204
228
|
}
|
|
205
229
|
get connectorKey() {
|
|
206
230
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -238,25 +262,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
238
262
|
if (authType) return `${slug}-${authType}`;
|
|
239
263
|
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
240
264
|
// user-password
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
265
|
+
postgresql: "user-password",
|
|
266
|
+
mysql: "user-password",
|
|
267
|
+
clickhouse: "user-password",
|
|
268
|
+
kintone: "user-password",
|
|
245
269
|
"squadbase-db": "user-password",
|
|
246
270
|
// service-account
|
|
247
|
-
|
|
248
|
-
|
|
271
|
+
snowflake: "service-account",
|
|
272
|
+
bigquery: "service-account",
|
|
249
273
|
"google-analytics": "service-account",
|
|
250
274
|
"google-calendar": "service-account",
|
|
251
275
|
"aws-athena": "service-account",
|
|
252
|
-
|
|
276
|
+
redshift: "service-account",
|
|
253
277
|
// api-key
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
278
|
+
databricks: "api-key",
|
|
279
|
+
dbt: "api-key",
|
|
280
|
+
airtable: "api-key",
|
|
281
|
+
openai: "api-key",
|
|
282
|
+
gemini: "api-key",
|
|
283
|
+
anthropic: "api-key",
|
|
260
284
|
"wix-store": "api-key"
|
|
261
285
|
};
|
|
262
286
|
const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
|
|
@@ -265,6 +289,84 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
265
289
|
}
|
|
266
290
|
};
|
|
267
291
|
|
|
292
|
+
// ../connectors/src/survey-probe.ts
|
|
293
|
+
function rowsOf(output) {
|
|
294
|
+
if (!output || typeof output !== "object") return [];
|
|
295
|
+
const o = output;
|
|
296
|
+
if (o.success === false) return [];
|
|
297
|
+
return Array.isArray(o.rows) ? o.rows : [];
|
|
298
|
+
}
|
|
299
|
+
function pickString(row, candidates) {
|
|
300
|
+
for (const key of candidates) {
|
|
301
|
+
const v = row[key] ?? row[key.toUpperCase()] ?? row[key.toLowerCase()];
|
|
302
|
+
if (typeof v === "string" && v.length > 0) return v;
|
|
303
|
+
}
|
|
304
|
+
return void 0;
|
|
305
|
+
}
|
|
306
|
+
var TABLE_NAME_FIELDS = [
|
|
307
|
+
"table_name",
|
|
308
|
+
"name",
|
|
309
|
+
"tableName",
|
|
310
|
+
"tab_name",
|
|
311
|
+
"Table",
|
|
312
|
+
"table"
|
|
313
|
+
];
|
|
314
|
+
function makeQuoteIdent(opts) {
|
|
315
|
+
if (opts.bracket) {
|
|
316
|
+
return (name) => `[${name.replaceAll("]", "]]")}]`;
|
|
317
|
+
}
|
|
318
|
+
const q = opts.quote ?? '"';
|
|
319
|
+
return (name) => `${q}${name.replaceAll(q, q + q)}${q}`;
|
|
320
|
+
}
|
|
321
|
+
function sampleSql(ref, limit) {
|
|
322
|
+
return `SELECT * FROM (SELECT * FROM ${ref}) AS _sq LIMIT ${limit}`;
|
|
323
|
+
}
|
|
324
|
+
function distinctTables(prior, max) {
|
|
325
|
+
const names = [];
|
|
326
|
+
const seen = /* @__PURE__ */ new Set();
|
|
327
|
+
for (const row of rowsOf(prior[0]?.output)) {
|
|
328
|
+
const name = pickString(row, TABLE_NAME_FIELDS);
|
|
329
|
+
if (!name || seen.has(name)) continue;
|
|
330
|
+
seen.add(name);
|
|
331
|
+
names.push(name);
|
|
332
|
+
if (names.length >= max) break;
|
|
333
|
+
}
|
|
334
|
+
return names;
|
|
335
|
+
}
|
|
336
|
+
function makeStandardSqlSurveyProbes(opts) {
|
|
337
|
+
const queryTool = opts.queryTool ?? "executeQuery";
|
|
338
|
+
const sampleLimit = opts.sampleLimit ?? 5;
|
|
339
|
+
const maxSampleTables = opts.maxSampleTables ?? 4;
|
|
340
|
+
const quoteIdent = makeQuoteIdent(opts);
|
|
341
|
+
const whereSchema = opts.schemaLiteral ? ` WHERE table_schema = '${opts.schemaLiteral.replaceAll("'", "''")}'` : opts.schemaExpr ? ` WHERE table_schema = ${opts.schemaExpr}` : "";
|
|
342
|
+
return (_connectionId, prior) => {
|
|
343
|
+
if (prior.length === 0) {
|
|
344
|
+
return [
|
|
345
|
+
{
|
|
346
|
+
tool: queryTool,
|
|
347
|
+
input: {
|
|
348
|
+
toolUseIntent: "Survey table/column metadata",
|
|
349
|
+
sql: `SELECT table_name, column_name, data_type FROM information_schema.columns${whereSchema} ORDER BY table_name, ordinal_position LIMIT 1000`
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
];
|
|
353
|
+
}
|
|
354
|
+
if (prior.length === 1) {
|
|
355
|
+
return distinctTables(prior, maxSampleTables).map((name) => {
|
|
356
|
+
const ref = opts.schemaLiteral ? `${quoteIdent(opts.schemaLiteral)}.${quoteIdent(name)}` : quoteIdent(name);
|
|
357
|
+
return {
|
|
358
|
+
tool: queryTool,
|
|
359
|
+
input: {
|
|
360
|
+
toolUseIntent: `Sample ${name}`,
|
|
361
|
+
sql: sampleSql(ref, sampleLimit)
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
return [];
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
|
|
268
370
|
// ../connectors/src/setup-flow.ts
|
|
269
371
|
async function runSetupFlow(flow, params, ctx, config) {
|
|
270
372
|
const runtime = {
|
|
@@ -335,6 +437,58 @@ async function resolveSetupSelection(params) {
|
|
|
335
437
|
return resolved.slice(0, limit);
|
|
336
438
|
}
|
|
337
439
|
|
|
440
|
+
// ../connectors/src/introspect-concurrency.ts
|
|
441
|
+
async function mapWithConcurrency(items, limit, fn) {
|
|
442
|
+
const results = new Array(items.length);
|
|
443
|
+
let next = 0;
|
|
444
|
+
const workers = Array.from(
|
|
445
|
+
{ length: Math.min(Math.max(limit, 1), items.length) },
|
|
446
|
+
async () => {
|
|
447
|
+
for (; ; ) {
|
|
448
|
+
const i = next++;
|
|
449
|
+
if (i >= items.length) return;
|
|
450
|
+
results[i] = await fn(items[i]);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
);
|
|
454
|
+
await Promise.all(workers);
|
|
455
|
+
return results;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// ../connectors/src/introspect-profile.ts
|
|
459
|
+
var DEFAULT_MAX_TABLES = 200;
|
|
460
|
+
var DEFAULT_CONCURRENCY = 5;
|
|
461
|
+
function dq(ident) {
|
|
462
|
+
return `"${ident.replace(/"/g, '""')}"`;
|
|
463
|
+
}
|
|
464
|
+
var quoteAnsi = (schema, name) => [...schema.split("."), name].map(dq).join(".");
|
|
465
|
+
async function withRowCounts(ctx, schemaPromise, quoteRef, opts = {}) {
|
|
466
|
+
const schema = await schemaPromise;
|
|
467
|
+
if (!ctx.profile || !ctx.query) return schema;
|
|
468
|
+
return attachRowCounts(ctx.query, schema, quoteRef, opts);
|
|
469
|
+
}
|
|
470
|
+
async function attachRowCounts(run, schema, quoteRef, opts = {}) {
|
|
471
|
+
const targets = schema.tables.slice(0, opts.maxTables ?? DEFAULT_MAX_TABLES);
|
|
472
|
+
await mapWithConcurrency(
|
|
473
|
+
targets,
|
|
474
|
+
opts.concurrency ?? DEFAULT_CONCURRENCY,
|
|
475
|
+
async (table) => {
|
|
476
|
+
try {
|
|
477
|
+
const { rows } = await run(
|
|
478
|
+
`SELECT COUNT(*) AS row_count FROM ${quoteRef(table.schema, table.name)}`
|
|
479
|
+
);
|
|
480
|
+
const first = rows[0] ? Object.values(rows[0])[0] : void 0;
|
|
481
|
+
const rowCount = Number(first);
|
|
482
|
+
if (Number.isFinite(rowCount)) {
|
|
483
|
+
table.profile = { ...table.profile ?? {}, rowCount };
|
|
484
|
+
}
|
|
485
|
+
} catch {
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
);
|
|
489
|
+
return schema;
|
|
490
|
+
}
|
|
491
|
+
|
|
338
492
|
// ../connectors/src/auth-types.ts
|
|
339
493
|
var AUTH_TYPES = {
|
|
340
494
|
OAUTH: "oauth",
|
|
@@ -360,6 +514,116 @@ function buildPositionalParams(sql, namedParams) {
|
|
|
360
514
|
return { text, values };
|
|
361
515
|
}
|
|
362
516
|
|
|
517
|
+
// ../connectors/src/introspect-information-schema.ts
|
|
518
|
+
function pickCI(row, key) {
|
|
519
|
+
if (key in row) return String(row[key] ?? "");
|
|
520
|
+
const lower = key.toLowerCase();
|
|
521
|
+
for (const k of Object.keys(row)) {
|
|
522
|
+
if (k.toLowerCase() === lower) return String(row[k] ?? "");
|
|
523
|
+
}
|
|
524
|
+
return "";
|
|
525
|
+
}
|
|
526
|
+
function assembleIntrospectedSchema(input) {
|
|
527
|
+
const { colRows, pkRows = [], fkRows = [] } = input;
|
|
528
|
+
const pkSet = /* @__PURE__ */ new Set();
|
|
529
|
+
for (const r of pkRows) {
|
|
530
|
+
pkSet.add(
|
|
531
|
+
`${pickCI(r, "table_schema")}.${pickCI(r, "table_name")}.${pickCI(r, "column_name")}`
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
const fkMap = /* @__PURE__ */ new Map();
|
|
535
|
+
for (const r of fkRows) {
|
|
536
|
+
fkMap.set(
|
|
537
|
+
`${pickCI(r, "table_schema")}.${pickCI(r, "table_name")}.${pickCI(r, "column_name")}`,
|
|
538
|
+
{
|
|
539
|
+
schema: pickCI(r, "foreign_table_schema"),
|
|
540
|
+
table: pickCI(r, "foreign_table_name"),
|
|
541
|
+
column: pickCI(r, "foreign_column_name")
|
|
542
|
+
}
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
const tableMap = /* @__PURE__ */ new Map();
|
|
546
|
+
for (const r of colRows) {
|
|
547
|
+
const schema = pickCI(r, "table_schema");
|
|
548
|
+
const name = pickCI(r, "table_name");
|
|
549
|
+
const key = `${schema}.${name}`;
|
|
550
|
+
let table = tableMap.get(key);
|
|
551
|
+
if (!table) {
|
|
552
|
+
table = {
|
|
553
|
+
schema,
|
|
554
|
+
name,
|
|
555
|
+
type: pickCI(r, "table_type").toUpperCase() === "VIEW" ? "view" : "table",
|
|
556
|
+
columns: []
|
|
557
|
+
};
|
|
558
|
+
tableMap.set(key, table);
|
|
559
|
+
}
|
|
560
|
+
const colKey = `${schema}.${name}.${pickCI(r, "column_name")}`;
|
|
561
|
+
const column = {
|
|
562
|
+
name: pickCI(r, "column_name"),
|
|
563
|
+
dataType: pickCI(r, "data_type"),
|
|
564
|
+
nullable: pickCI(r, "is_nullable").toUpperCase() === "YES"
|
|
565
|
+
};
|
|
566
|
+
if (pkSet.has(colKey)) column.isPrimaryKey = true;
|
|
567
|
+
const fk = fkMap.get(colKey);
|
|
568
|
+
if (fk) column.foreignKey = fk;
|
|
569
|
+
table.columns.push(column);
|
|
570
|
+
}
|
|
571
|
+
return { tables: [...tableMap.values()] };
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// ../connectors/src/connectors/postgresql/introspect.ts
|
|
575
|
+
async function introspectPostgresql(run) {
|
|
576
|
+
const SCHEMA_FILTER = `c.table_schema NOT IN ('pg_catalog', 'information_schema') AND c.table_schema NOT LIKE 'pg\\_%'`;
|
|
577
|
+
const [{ rows: colRows }, { rows: pkRows }, { rows: fkRows }] = await Promise.all([
|
|
578
|
+
// 1) 全カラム(型 / nullable)+ テーブル種別(BASE TABLE / VIEW)
|
|
579
|
+
run(
|
|
580
|
+
`SELECT c.table_schema, c.table_name, c.column_name, c.data_type,
|
|
581
|
+
c.is_nullable, c.ordinal_position, t.table_type
|
|
582
|
+
FROM information_schema.columns c
|
|
583
|
+
JOIN information_schema.tables t
|
|
584
|
+
ON t.table_schema = c.table_schema AND t.table_name = c.table_name
|
|
585
|
+
WHERE ${SCHEMA_FILTER}
|
|
586
|
+
ORDER BY c.table_schema, c.table_name, c.ordinal_position`
|
|
587
|
+
),
|
|
588
|
+
// 2) 主キー(schema.table.column)
|
|
589
|
+
run(
|
|
590
|
+
`SELECT tc.table_schema, tc.table_name, kcu.column_name
|
|
591
|
+
FROM information_schema.table_constraints tc
|
|
592
|
+
JOIN information_schema.key_column_usage kcu
|
|
593
|
+
ON kcu.constraint_name = tc.constraint_name
|
|
594
|
+
AND kcu.table_schema = tc.table_schema
|
|
595
|
+
WHERE tc.constraint_type = 'PRIMARY KEY'
|
|
596
|
+
AND tc.table_schema NOT IN ('pg_catalog', 'information_schema')
|
|
597
|
+
AND tc.table_schema NOT LIKE 'pg\\_%'`
|
|
598
|
+
),
|
|
599
|
+
// 3) 外部キー(参照元 → 参照先)。
|
|
600
|
+
// 複合 FK を正しく対応付けるため、`constraint_column_usage`(順序非保証 + constraint_name のみの
|
|
601
|
+
// join で複合キーが直積爆発する)を使わず、`referential_constraints` 経由で参照先 unique 制約へ辿り、
|
|
602
|
+
// FK 列の `position_in_unique_constraint` を参照先列の `ordinal_position` に突き合わせて 1:1 に組む。
|
|
603
|
+
run(
|
|
604
|
+
`SELECT tc.table_schema, tc.table_name, kcu.column_name,
|
|
605
|
+
fkcu.table_schema AS foreign_table_schema,
|
|
606
|
+
fkcu.table_name AS foreign_table_name,
|
|
607
|
+
fkcu.column_name AS foreign_column_name
|
|
608
|
+
FROM information_schema.table_constraints tc
|
|
609
|
+
JOIN information_schema.key_column_usage kcu
|
|
610
|
+
ON kcu.constraint_name = tc.constraint_name
|
|
611
|
+
AND kcu.constraint_schema = tc.constraint_schema
|
|
612
|
+
JOIN information_schema.referential_constraints rc
|
|
613
|
+
ON rc.constraint_name = tc.constraint_name
|
|
614
|
+
AND rc.constraint_schema = tc.constraint_schema
|
|
615
|
+
JOIN information_schema.key_column_usage fkcu
|
|
616
|
+
ON fkcu.constraint_name = rc.unique_constraint_name
|
|
617
|
+
AND fkcu.constraint_schema = rc.unique_constraint_schema
|
|
618
|
+
AND fkcu.ordinal_position = kcu.position_in_unique_constraint
|
|
619
|
+
WHERE tc.constraint_type = 'FOREIGN KEY'
|
|
620
|
+
AND tc.table_schema NOT IN ('pg_catalog', 'information_schema')
|
|
621
|
+
AND tc.table_schema NOT LIKE 'pg\\_%'`
|
|
622
|
+
)
|
|
623
|
+
]);
|
|
624
|
+
return assembleIntrospectedSchema({ colRows, pkRows, fkRows });
|
|
625
|
+
}
|
|
626
|
+
|
|
363
627
|
// ../connectors/src/connectors/supabase/setup.ts
|
|
364
628
|
var supabaseOnboarding = new ConnectorOnboarding({
|
|
365
629
|
dataOverviewInstructions: {
|
|
@@ -537,6 +801,9 @@ var outputSchema = z.discriminatedUnion("success", [
|
|
|
537
801
|
z.object({
|
|
538
802
|
success: z.literal(true),
|
|
539
803
|
rowCount: z.number(),
|
|
804
|
+
rowsAffected: z.number().optional().describe(
|
|
805
|
+
"Affected rows for INSERT/UPDATE/DELETE; undefined for SELECT"
|
|
806
|
+
),
|
|
540
807
|
truncated: z.boolean(),
|
|
541
808
|
rows: z.array(z.record(z.string(), z.unknown()))
|
|
542
809
|
}),
|
|
@@ -550,7 +817,8 @@ var executeQueryTool = new ConnectorTool({
|
|
|
550
817
|
description: `Execute SQL against a Supabase Postgres database. Returns up to ${MAX_ROWS} rows.
|
|
551
818
|
Use for: schema exploration (information_schema), data sampling, and analytical queries against Supabase tables.
|
|
552
819
|
User tables live in the \`public\` schema by default; Supabase-managed metadata lives in \`auth\` and \`storage\`.
|
|
553
|
-
Avoid loading large amounts of data; always include LIMIT in queries
|
|
820
|
+
Avoid loading large amounts of data; always include LIMIT in queries.
|
|
821
|
+
For INSERT/UPDATE/DELETE, \`rowCount\` is 0 and \`rows\` is empty (rowCount counts returned rows, not affected rows) \u2014 this is normal, not a failure; check \`rowsAffected\` for the number of affected rows. Use RETURNING to get written rows back in \`rows\`.`,
|
|
554
822
|
inputSchema,
|
|
555
823
|
outputSchema,
|
|
556
824
|
async execute({ connectionId, sql }, connections) {
|
|
@@ -578,9 +846,13 @@ Avoid loading large amounts of data; always include LIMIT in queries.`,
|
|
|
578
846
|
const result = await pool.query(sql);
|
|
579
847
|
const rows = result.rows;
|
|
580
848
|
const truncated = rows.length > MAX_ROWS;
|
|
849
|
+
const isDml = ["INSERT", "UPDATE", "DELETE", "MERGE"].includes(
|
|
850
|
+
result.command
|
|
851
|
+
);
|
|
581
852
|
return {
|
|
582
853
|
success: true,
|
|
583
854
|
rowCount: Math.min(rows.length, MAX_ROWS),
|
|
855
|
+
rowsAffected: isDml ? result.rowCount ?? 0 : void 0,
|
|
584
856
|
truncated,
|
|
585
857
|
rows: rows.slice(0, MAX_ROWS)
|
|
586
858
|
};
|
|
@@ -646,6 +918,11 @@ The business logic type for this connector is "sql".
|
|
|
646
918
|
- \u30AF\u30A8\u30EA\u306B\u306F\u5FC5\u305A LIMIT \u3092\u542B\u3081\u3066\u304F\u3060\u3055\u3044`
|
|
647
919
|
},
|
|
648
920
|
tools,
|
|
921
|
+
// 決定論的な立ち上げ survey(ルールベース prewarm)。Supabase は Postgres で公開スキーマは `public`。
|
|
922
|
+
surveyProbes: makeStandardSqlSurveyProbes({ schemaLiteral: "public" }),
|
|
923
|
+
// Supabase は PostgreSQL なので postgresql の introspect をそのまま流用する
|
|
924
|
+
// (exploreData / DataContextIndex の対象に含めるため)。
|
|
925
|
+
introspect: (ctx) => withRowCounts(ctx, introspectPostgresql(ctx.query), quoteAnsi),
|
|
649
926
|
setup: (params, ctx, config) => runSetupFlow(supabaseSetupFlow, params, ctx, config),
|
|
650
927
|
async checkConnection(params, _config) {
|
|
651
928
|
const { Pool } = await import("pg");
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
2
|
-
var __esm = (fn, res) => function __init() {
|
|
3
|
-
|
|
2
|
+
var __esm = (fn, res, err) => function __init() {
|
|
3
|
+
if (err) throw err[0];
|
|
4
|
+
try {
|
|
5
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
|
+
} catch (e) {
|
|
7
|
+
throw err = [e], e;
|
|
8
|
+
}
|
|
4
9
|
};
|
|
5
10
|
|
|
6
11
|
// ../connectors/src/parameter-definition.ts
|
|
@@ -266,6 +271,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
266
271
|
* `runSetupFlow` from `setup-flow.ts`.
|
|
267
272
|
*/
|
|
268
273
|
setup;
|
|
274
|
+
/**
|
|
275
|
+
* 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
|
|
276
|
+
* メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
|
|
277
|
+
* {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
|
|
278
|
+
* 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
|
|
279
|
+
* `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
|
|
280
|
+
* coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
|
|
281
|
+
*/
|
|
282
|
+
introspect;
|
|
269
283
|
/**
|
|
270
284
|
* Opt-out of the default "verify before save" behavior on connection
|
|
271
285
|
* creation. The backend invokes `checkConnection` synchronously while
|
|
@@ -280,6 +294,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
280
294
|
* the default verify-on-create behavior without opt-in.
|
|
281
295
|
*/
|
|
282
296
|
skipConnectionCheckOnCreate;
|
|
297
|
+
/**
|
|
298
|
+
* 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
|
|
299
|
+
* read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
|
|
300
|
+
* recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
|
|
301
|
+
* driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
|
|
302
|
+
* 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
|
|
303
|
+
*/
|
|
304
|
+
surveyProbes;
|
|
283
305
|
constructor(config) {
|
|
284
306
|
this.slug = config.slug;
|
|
285
307
|
this.authType = config.authType;
|
|
@@ -297,7 +319,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
297
319
|
this.query = config.query;
|
|
298
320
|
this.checkConnection = config.checkConnection;
|
|
299
321
|
this.setup = config.setup;
|
|
322
|
+
this.introspect = config.introspect;
|
|
300
323
|
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
324
|
+
this.surveyProbes = config.surveyProbes;
|
|
301
325
|
}
|
|
302
326
|
get connectorKey() {
|
|
303
327
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -335,25 +359,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
335
359
|
if (authType) return `${slug}-${authType}`;
|
|
336
360
|
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
337
361
|
// user-password
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
362
|
+
postgresql: "user-password",
|
|
363
|
+
mysql: "user-password",
|
|
364
|
+
clickhouse: "user-password",
|
|
365
|
+
kintone: "user-password",
|
|
342
366
|
"squadbase-db": "user-password",
|
|
343
367
|
// service-account
|
|
344
|
-
|
|
345
|
-
|
|
368
|
+
snowflake: "service-account",
|
|
369
|
+
bigquery: "service-account",
|
|
346
370
|
"google-analytics": "service-account",
|
|
347
371
|
"google-calendar": "service-account",
|
|
348
372
|
"aws-athena": "service-account",
|
|
349
|
-
|
|
373
|
+
redshift: "service-account",
|
|
350
374
|
// api-key
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
375
|
+
databricks: "api-key",
|
|
376
|
+
dbt: "api-key",
|
|
377
|
+
airtable: "api-key",
|
|
378
|
+
openai: "api-key",
|
|
379
|
+
gemini: "api-key",
|
|
380
|
+
anthropic: "api-key",
|
|
357
381
|
"wix-store": "api-key"
|
|
358
382
|
};
|
|
359
383
|
const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
|
|
@@ -917,7 +941,7 @@ var tableauConnector = new ConnectorPlugin({
|
|
|
917
941
|
description: "Connect to Tableau Cloud or Tableau Server via a Personal Access Token (PAT). Use it to enumerate projects, workbooks, views, and data sources, and to pull view data.",
|
|
918
942
|
iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/3ejrZvfw7zCDa3FPbUNQx9/d810e117b3a86c45dd96205453bf67a0/tableau-icon.svg",
|
|
919
943
|
parameters,
|
|
920
|
-
releaseFlag: { dev1: true, dev2:
|
|
944
|
+
releaseFlag: { dev1: true, dev2: true, prod: true },
|
|
921
945
|
categories: ["bi"],
|
|
922
946
|
onboarding: tableauOnboarding,
|
|
923
947
|
systemPrompt: {
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
2
|
-
var __esm = (fn, res) => function __init() {
|
|
3
|
-
|
|
2
|
+
var __esm = (fn, res, err) => function __init() {
|
|
3
|
+
if (err) throw err[0];
|
|
4
|
+
try {
|
|
5
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
|
+
} catch (e) {
|
|
7
|
+
throw err = [e], e;
|
|
8
|
+
}
|
|
4
9
|
};
|
|
5
10
|
|
|
6
11
|
// ../connectors/src/parameter-definition.ts
|
|
@@ -132,6 +137,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
132
137
|
* `runSetupFlow` from `setup-flow.ts`.
|
|
133
138
|
*/
|
|
134
139
|
setup;
|
|
140
|
+
/**
|
|
141
|
+
* 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
|
|
142
|
+
* メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
|
|
143
|
+
* {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
|
|
144
|
+
* 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
|
|
145
|
+
* `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
|
|
146
|
+
* coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
|
|
147
|
+
*/
|
|
148
|
+
introspect;
|
|
135
149
|
/**
|
|
136
150
|
* Opt-out of the default "verify before save" behavior on connection
|
|
137
151
|
* creation. The backend invokes `checkConnection` synchronously while
|
|
@@ -146,6 +160,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
146
160
|
* the default verify-on-create behavior without opt-in.
|
|
147
161
|
*/
|
|
148
162
|
skipConnectionCheckOnCreate;
|
|
163
|
+
/**
|
|
164
|
+
* 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
|
|
165
|
+
* read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
|
|
166
|
+
* recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
|
|
167
|
+
* driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
|
|
168
|
+
* 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
|
|
169
|
+
*/
|
|
170
|
+
surveyProbes;
|
|
149
171
|
constructor(config) {
|
|
150
172
|
this.slug = config.slug;
|
|
151
173
|
this.authType = config.authType;
|
|
@@ -163,7 +185,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
163
185
|
this.query = config.query;
|
|
164
186
|
this.checkConnection = config.checkConnection;
|
|
165
187
|
this.setup = config.setup;
|
|
188
|
+
this.introspect = config.introspect;
|
|
166
189
|
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
190
|
+
this.surveyProbes = config.surveyProbes;
|
|
167
191
|
}
|
|
168
192
|
get connectorKey() {
|
|
169
193
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -201,25 +225,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
201
225
|
if (authType) return `${slug}-${authType}`;
|
|
202
226
|
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
203
227
|
// user-password
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
228
|
+
postgresql: "user-password",
|
|
229
|
+
mysql: "user-password",
|
|
230
|
+
clickhouse: "user-password",
|
|
231
|
+
kintone: "user-password",
|
|
208
232
|
"squadbase-db": "user-password",
|
|
209
233
|
// service-account
|
|
210
|
-
|
|
211
|
-
|
|
234
|
+
snowflake: "service-account",
|
|
235
|
+
bigquery: "service-account",
|
|
212
236
|
"google-analytics": "service-account",
|
|
213
237
|
"google-calendar": "service-account",
|
|
214
238
|
"aws-athena": "service-account",
|
|
215
|
-
|
|
239
|
+
redshift: "service-account",
|
|
216
240
|
// api-key
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
241
|
+
databricks: "api-key",
|
|
242
|
+
dbt: "api-key",
|
|
243
|
+
airtable: "api-key",
|
|
244
|
+
openai: "api-key",
|
|
245
|
+
gemini: "api-key",
|
|
246
|
+
anthropic: "api-key",
|
|
223
247
|
"wix-store": "api-key"
|
|
224
248
|
};
|
|
225
249
|
const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
|