@squadbase/vite-server 0.1.17 → 0.1.18
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 +6404 -3394
- package/dist/main.js +6404 -3394
- package/dist/vite-plugin.js +5961 -2986
- package/package.json +16 -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
|
|
@@ -177,6 +182,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
177
182
|
* `runSetupFlow` from `setup-flow.ts`.
|
|
178
183
|
*/
|
|
179
184
|
setup;
|
|
185
|
+
/**
|
|
186
|
+
* 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
|
|
187
|
+
* メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
|
|
188
|
+
* {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
|
|
189
|
+
* 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
|
|
190
|
+
* `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
|
|
191
|
+
* coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
|
|
192
|
+
*/
|
|
193
|
+
introspect;
|
|
180
194
|
/**
|
|
181
195
|
* Opt-out of the default "verify before save" behavior on connection
|
|
182
196
|
* creation. The backend invokes `checkConnection` synchronously while
|
|
@@ -191,6 +205,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
191
205
|
* the default verify-on-create behavior without opt-in.
|
|
192
206
|
*/
|
|
193
207
|
skipConnectionCheckOnCreate;
|
|
208
|
+
/**
|
|
209
|
+
* 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
|
|
210
|
+
* read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
|
|
211
|
+
* recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
|
|
212
|
+
* driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
|
|
213
|
+
* 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
|
|
214
|
+
*/
|
|
215
|
+
surveyProbes;
|
|
194
216
|
constructor(config) {
|
|
195
217
|
this.slug = config.slug;
|
|
196
218
|
this.authType = config.authType;
|
|
@@ -208,7 +230,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
208
230
|
this.query = config.query;
|
|
209
231
|
this.checkConnection = config.checkConnection;
|
|
210
232
|
this.setup = config.setup;
|
|
233
|
+
this.introspect = config.introspect;
|
|
211
234
|
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
235
|
+
this.surveyProbes = config.surveyProbes;
|
|
212
236
|
}
|
|
213
237
|
get connectorKey() {
|
|
214
238
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -246,25 +270,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
246
270
|
if (authType) return `${slug}-${authType}`;
|
|
247
271
|
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
248
272
|
// user-password
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
273
|
+
postgresql: "user-password",
|
|
274
|
+
mysql: "user-password",
|
|
275
|
+
clickhouse: "user-password",
|
|
276
|
+
kintone: "user-password",
|
|
253
277
|
"squadbase-db": "user-password",
|
|
254
278
|
// service-account
|
|
255
|
-
|
|
256
|
-
|
|
279
|
+
snowflake: "service-account",
|
|
280
|
+
bigquery: "service-account",
|
|
257
281
|
"google-analytics": "service-account",
|
|
258
282
|
"google-calendar": "service-account",
|
|
259
283
|
"aws-athena": "service-account",
|
|
260
|
-
|
|
284
|
+
redshift: "service-account",
|
|
261
285
|
// api-key
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
286
|
+
databricks: "api-key",
|
|
287
|
+
dbt: "api-key",
|
|
288
|
+
airtable: "api-key",
|
|
289
|
+
openai: "api-key",
|
|
290
|
+
gemini: "api-key",
|
|
291
|
+
anthropic: "api-key",
|
|
268
292
|
"wix-store": "api-key"
|
|
269
293
|
};
|
|
270
294
|
const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
-
var __esm = (fn, res) => function __init() {
|
|
4
|
-
|
|
3
|
+
var __esm = (fn, res, err) => function __init() {
|
|
4
|
+
if (err) throw err[0];
|
|
5
|
+
try {
|
|
6
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
7
|
+
} catch (e) {
|
|
8
|
+
throw err = [e], e;
|
|
9
|
+
}
|
|
5
10
|
};
|
|
6
11
|
var __export = (target, all) => {
|
|
7
12
|
for (var name in all)
|
|
@@ -308,7 +313,7 @@ async function runMssqlQuery(parsed, sql, options = {}) {
|
|
|
308
313
|
try {
|
|
309
314
|
const result = await pool.request().query(sql);
|
|
310
315
|
const recordset = result.recordset ?? [];
|
|
311
|
-
return { rows: recordset };
|
|
316
|
+
return { rows: recordset, rowsAffected: result.rowsAffected ?? [] };
|
|
312
317
|
} finally {
|
|
313
318
|
await pool.close();
|
|
314
319
|
}
|
|
@@ -474,6 +479,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
474
479
|
* `runSetupFlow` from `setup-flow.ts`.
|
|
475
480
|
*/
|
|
476
481
|
setup;
|
|
482
|
+
/**
|
|
483
|
+
* 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
|
|
484
|
+
* メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
|
|
485
|
+
* {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
|
|
486
|
+
* 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
|
|
487
|
+
* `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
|
|
488
|
+
* coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
|
|
489
|
+
*/
|
|
490
|
+
introspect;
|
|
477
491
|
/**
|
|
478
492
|
* Opt-out of the default "verify before save" behavior on connection
|
|
479
493
|
* creation. The backend invokes `checkConnection` synchronously while
|
|
@@ -488,6 +502,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
488
502
|
* the default verify-on-create behavior without opt-in.
|
|
489
503
|
*/
|
|
490
504
|
skipConnectionCheckOnCreate;
|
|
505
|
+
/**
|
|
506
|
+
* 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
|
|
507
|
+
* read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
|
|
508
|
+
* recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
|
|
509
|
+
* driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
|
|
510
|
+
* 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
|
|
511
|
+
*/
|
|
512
|
+
surveyProbes;
|
|
491
513
|
constructor(config) {
|
|
492
514
|
this.slug = config.slug;
|
|
493
515
|
this.authType = config.authType;
|
|
@@ -505,7 +527,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
505
527
|
this.query = config.query;
|
|
506
528
|
this.checkConnection = config.checkConnection;
|
|
507
529
|
this.setup = config.setup;
|
|
530
|
+
this.introspect = config.introspect;
|
|
508
531
|
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
532
|
+
this.surveyProbes = config.surveyProbes;
|
|
509
533
|
}
|
|
510
534
|
get connectorKey() {
|
|
511
535
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -543,25 +567,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
543
567
|
if (authType) return `${slug}-${authType}`;
|
|
544
568
|
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
545
569
|
// user-password
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
570
|
+
postgresql: "user-password",
|
|
571
|
+
mysql: "user-password",
|
|
572
|
+
clickhouse: "user-password",
|
|
573
|
+
kintone: "user-password",
|
|
550
574
|
"squadbase-db": "user-password",
|
|
551
575
|
// service-account
|
|
552
|
-
|
|
553
|
-
|
|
576
|
+
snowflake: "service-account",
|
|
577
|
+
bigquery: "service-account",
|
|
554
578
|
"google-analytics": "service-account",
|
|
555
579
|
"google-calendar": "service-account",
|
|
556
580
|
"aws-athena": "service-account",
|
|
557
|
-
|
|
581
|
+
redshift: "service-account",
|
|
558
582
|
// api-key
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
583
|
+
databricks: "api-key",
|
|
584
|
+
dbt: "api-key",
|
|
585
|
+
airtable: "api-key",
|
|
586
|
+
openai: "api-key",
|
|
587
|
+
gemini: "api-key",
|
|
588
|
+
anthropic: "api-key",
|
|
565
589
|
"wix-store": "api-key"
|
|
566
590
|
};
|
|
567
591
|
const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
|
|
@@ -570,6 +594,84 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
570
594
|
}
|
|
571
595
|
};
|
|
572
596
|
|
|
597
|
+
// ../connectors/src/survey-probe.ts
|
|
598
|
+
function rowsOf(output) {
|
|
599
|
+
if (!output || typeof output !== "object") return [];
|
|
600
|
+
const o = output;
|
|
601
|
+
if (o.success === false) return [];
|
|
602
|
+
return Array.isArray(o.rows) ? o.rows : [];
|
|
603
|
+
}
|
|
604
|
+
function pickString(row, candidates) {
|
|
605
|
+
for (const key of candidates) {
|
|
606
|
+
const v = row[key] ?? row[key.toUpperCase()] ?? row[key.toLowerCase()];
|
|
607
|
+
if (typeof v === "string" && v.length > 0) return v;
|
|
608
|
+
}
|
|
609
|
+
return void 0;
|
|
610
|
+
}
|
|
611
|
+
var TABLE_NAME_FIELDS = [
|
|
612
|
+
"table_name",
|
|
613
|
+
"name",
|
|
614
|
+
"tableName",
|
|
615
|
+
"tab_name",
|
|
616
|
+
"Table",
|
|
617
|
+
"table"
|
|
618
|
+
];
|
|
619
|
+
function makeQuoteIdent(opts) {
|
|
620
|
+
if (opts.bracket) {
|
|
621
|
+
return (name) => `[${name.replaceAll("]", "]]")}]`;
|
|
622
|
+
}
|
|
623
|
+
const q = opts.quote ?? '"';
|
|
624
|
+
return (name) => `${q}${name.replaceAll(q, q + q)}${q}`;
|
|
625
|
+
}
|
|
626
|
+
function sampleSql(ref, limit) {
|
|
627
|
+
return `SELECT * FROM (SELECT * FROM ${ref}) AS _sq LIMIT ${limit}`;
|
|
628
|
+
}
|
|
629
|
+
function distinctTables(prior, max) {
|
|
630
|
+
const names = [];
|
|
631
|
+
const seen = /* @__PURE__ */ new Set();
|
|
632
|
+
for (const row of rowsOf(prior[0]?.output)) {
|
|
633
|
+
const name = pickString(row, TABLE_NAME_FIELDS);
|
|
634
|
+
if (!name || seen.has(name)) continue;
|
|
635
|
+
seen.add(name);
|
|
636
|
+
names.push(name);
|
|
637
|
+
if (names.length >= max) break;
|
|
638
|
+
}
|
|
639
|
+
return names;
|
|
640
|
+
}
|
|
641
|
+
function makeStandardSqlSurveyProbes(opts) {
|
|
642
|
+
const queryTool = opts.queryTool ?? "executeQuery";
|
|
643
|
+
const sampleLimit = opts.sampleLimit ?? 5;
|
|
644
|
+
const maxSampleTables = opts.maxSampleTables ?? 4;
|
|
645
|
+
const quoteIdent = makeQuoteIdent(opts);
|
|
646
|
+
const whereSchema = opts.schemaLiteral ? ` WHERE table_schema = '${opts.schemaLiteral.replaceAll("'", "''")}'` : opts.schemaExpr ? ` WHERE table_schema = ${opts.schemaExpr}` : "";
|
|
647
|
+
return (_connectionId, prior) => {
|
|
648
|
+
if (prior.length === 0) {
|
|
649
|
+
return [
|
|
650
|
+
{
|
|
651
|
+
tool: queryTool,
|
|
652
|
+
input: {
|
|
653
|
+
toolUseIntent: "Survey table/column metadata",
|
|
654
|
+
sql: `SELECT table_name, column_name, data_type FROM information_schema.columns${whereSchema} ORDER BY table_name, ordinal_position LIMIT 1000`
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
];
|
|
658
|
+
}
|
|
659
|
+
if (prior.length === 1) {
|
|
660
|
+
return distinctTables(prior, maxSampleTables).map((name) => {
|
|
661
|
+
const ref = opts.schemaLiteral ? `${quoteIdent(opts.schemaLiteral)}.${quoteIdent(name)}` : quoteIdent(name);
|
|
662
|
+
return {
|
|
663
|
+
tool: queryTool,
|
|
664
|
+
input: {
|
|
665
|
+
toolUseIntent: `Sample ${name}`,
|
|
666
|
+
sql: sampleSql(ref, sampleLimit)
|
|
667
|
+
}
|
|
668
|
+
};
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
return [];
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
|
|
573
675
|
// ../connectors/src/setup-flow.ts
|
|
574
676
|
async function runSetupFlow(flow, params, ctx, config) {
|
|
575
677
|
const runtime = {
|
|
@@ -640,6 +742,55 @@ async function resolveSetupSelection(params) {
|
|
|
640
742
|
return resolved.slice(0, limit);
|
|
641
743
|
}
|
|
642
744
|
|
|
745
|
+
// ../connectors/src/introspect-concurrency.ts
|
|
746
|
+
async function mapWithConcurrency(items, limit, fn) {
|
|
747
|
+
const results = new Array(items.length);
|
|
748
|
+
let next = 0;
|
|
749
|
+
const workers = Array.from(
|
|
750
|
+
{ length: Math.min(Math.max(limit, 1), items.length) },
|
|
751
|
+
async () => {
|
|
752
|
+
for (; ; ) {
|
|
753
|
+
const i = next++;
|
|
754
|
+
if (i >= items.length) return;
|
|
755
|
+
results[i] = await fn(items[i]);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
);
|
|
759
|
+
await Promise.all(workers);
|
|
760
|
+
return results;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
// ../connectors/src/introspect-profile.ts
|
|
764
|
+
var DEFAULT_MAX_TABLES = 200;
|
|
765
|
+
var DEFAULT_CONCURRENCY = 5;
|
|
766
|
+
var quoteBracket = (schema, name) => `[${schema.replace(/\]/g, "]]")}].[${name.replace(/\]/g, "]]")}]`;
|
|
767
|
+
async function withRowCounts(ctx, schemaPromise, quoteRef, opts = {}) {
|
|
768
|
+
const schema = await schemaPromise;
|
|
769
|
+
if (!ctx.profile || !ctx.query) return schema;
|
|
770
|
+
return attachRowCounts(ctx.query, schema, quoteRef, opts);
|
|
771
|
+
}
|
|
772
|
+
async function attachRowCounts(run, schema, quoteRef, opts = {}) {
|
|
773
|
+
const targets = schema.tables.slice(0, opts.maxTables ?? DEFAULT_MAX_TABLES);
|
|
774
|
+
await mapWithConcurrency(
|
|
775
|
+
targets,
|
|
776
|
+
opts.concurrency ?? DEFAULT_CONCURRENCY,
|
|
777
|
+
async (table) => {
|
|
778
|
+
try {
|
|
779
|
+
const { rows } = await run(
|
|
780
|
+
`SELECT COUNT(*) AS row_count FROM ${quoteRef(table.schema, table.name)}`
|
|
781
|
+
);
|
|
782
|
+
const first = rows[0] ? Object.values(rows[0])[0] : void 0;
|
|
783
|
+
const rowCount = Number(first);
|
|
784
|
+
if (Number.isFinite(rowCount)) {
|
|
785
|
+
table.profile = { ...table.profile ?? {}, rowCount };
|
|
786
|
+
}
|
|
787
|
+
} catch {
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
);
|
|
791
|
+
return schema;
|
|
792
|
+
}
|
|
793
|
+
|
|
643
794
|
// ../connectors/src/auth-types.ts
|
|
644
795
|
var AUTH_TYPES = {
|
|
645
796
|
OAUTH: "oauth",
|
|
@@ -650,6 +801,69 @@ var AUTH_TYPES = {
|
|
|
650
801
|
USER_PASSWORD: "user-password"
|
|
651
802
|
};
|
|
652
803
|
|
|
804
|
+
// ../connectors/src/introspect-information-schema.ts
|
|
805
|
+
function pickCI(row, key) {
|
|
806
|
+
if (key in row) return String(row[key] ?? "");
|
|
807
|
+
const lower = key.toLowerCase();
|
|
808
|
+
for (const k of Object.keys(row)) {
|
|
809
|
+
if (k.toLowerCase() === lower) return String(row[k] ?? "");
|
|
810
|
+
}
|
|
811
|
+
return "";
|
|
812
|
+
}
|
|
813
|
+
function assembleIntrospectedSchema(input) {
|
|
814
|
+
const { colRows, pkRows = [], fkRows = [] } = input;
|
|
815
|
+
const pkSet = /* @__PURE__ */ new Set();
|
|
816
|
+
for (const r of pkRows) {
|
|
817
|
+
pkSet.add(
|
|
818
|
+
`${pickCI(r, "table_schema")}.${pickCI(r, "table_name")}.${pickCI(r, "column_name")}`
|
|
819
|
+
);
|
|
820
|
+
}
|
|
821
|
+
const fkMap = /* @__PURE__ */ new Map();
|
|
822
|
+
for (const r of fkRows) {
|
|
823
|
+
fkMap.set(
|
|
824
|
+
`${pickCI(r, "table_schema")}.${pickCI(r, "table_name")}.${pickCI(r, "column_name")}`,
|
|
825
|
+
{
|
|
826
|
+
schema: pickCI(r, "foreign_table_schema"),
|
|
827
|
+
table: pickCI(r, "foreign_table_name"),
|
|
828
|
+
column: pickCI(r, "foreign_column_name")
|
|
829
|
+
}
|
|
830
|
+
);
|
|
831
|
+
}
|
|
832
|
+
const tableMap = /* @__PURE__ */ new Map();
|
|
833
|
+
for (const r of colRows) {
|
|
834
|
+
const schema = pickCI(r, "table_schema");
|
|
835
|
+
const name = pickCI(r, "table_name");
|
|
836
|
+
const key = `${schema}.${name}`;
|
|
837
|
+
let table = tableMap.get(key);
|
|
838
|
+
if (!table) {
|
|
839
|
+
table = {
|
|
840
|
+
schema,
|
|
841
|
+
name,
|
|
842
|
+
type: pickCI(r, "table_type").toUpperCase() === "VIEW" ? "view" : "table",
|
|
843
|
+
columns: []
|
|
844
|
+
};
|
|
845
|
+
tableMap.set(key, table);
|
|
846
|
+
}
|
|
847
|
+
const colKey = `${schema}.${name}.${pickCI(r, "column_name")}`;
|
|
848
|
+
const column = {
|
|
849
|
+
name: pickCI(r, "column_name"),
|
|
850
|
+
dataType: pickCI(r, "data_type"),
|
|
851
|
+
nullable: pickCI(r, "is_nullable").toUpperCase() === "YES"
|
|
852
|
+
};
|
|
853
|
+
if (pkSet.has(colKey)) column.isPrimaryKey = true;
|
|
854
|
+
const fk = fkMap.get(colKey);
|
|
855
|
+
if (fk) column.foreignKey = fk;
|
|
856
|
+
table.columns.push(column);
|
|
857
|
+
}
|
|
858
|
+
return { tables: [...tableMap.values()] };
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
// ../connectors/src/lib/sql-dml.ts
|
|
862
|
+
function isDmlStatement(sql) {
|
|
863
|
+
const stripped = sql.replace(/^(\s*(--[^\n]*\n|\/\*[\s\S]*?\*\/))+/, "").trimStart();
|
|
864
|
+
return /^(insert|update|delete|merge)\b/i.test(stripped);
|
|
865
|
+
}
|
|
866
|
+
|
|
653
867
|
// ../connectors/src/lib/unwrap-sample-limit.ts
|
|
654
868
|
var STRICT_WRAPPER_RE = /^\s*SELECT\s+\*\s+FROM\s+\(([\s\S]+)\)\s+AS\s+\w+\s+LIMIT\s+(\d+)\s*;?\s*$/i;
|
|
655
869
|
var TRAILING_LIMIT_RE = /\s+LIMIT\s+(\d+)\s*;?\s*$/i;
|
|
@@ -822,6 +1036,52 @@ var sqlserverSetupFlow = createSqlServerSetupFlow({
|
|
|
822
1036
|
forceEncrypt: false
|
|
823
1037
|
});
|
|
824
1038
|
|
|
1039
|
+
// ../connectors/src/connectors/sqlserver/introspect.ts
|
|
1040
|
+
async function introspectMssql(run) {
|
|
1041
|
+
const [{ rows: colRows }, { rows: pkRows }, { rows: fkRows }] = await Promise.all([
|
|
1042
|
+
// 1) 全カラム(型 / nullable)+ テーブル種別(BASE TABLE / VIEW)
|
|
1043
|
+
run(
|
|
1044
|
+
`SELECT c.TABLE_SCHEMA AS table_schema, c.TABLE_NAME AS table_name,
|
|
1045
|
+
c.COLUMN_NAME AS column_name, c.DATA_TYPE AS data_type,
|
|
1046
|
+
c.IS_NULLABLE AS is_nullable, c.ORDINAL_POSITION AS ordinal_position,
|
|
1047
|
+
t.TABLE_TYPE AS table_type
|
|
1048
|
+
FROM INFORMATION_SCHEMA.COLUMNS c
|
|
1049
|
+
JOIN INFORMATION_SCHEMA.TABLES t
|
|
1050
|
+
ON t.TABLE_SCHEMA = c.TABLE_SCHEMA AND t.TABLE_NAME = c.TABLE_NAME
|
|
1051
|
+
WHERE c.TABLE_SCHEMA NOT IN ('sys', 'INFORMATION_SCHEMA')
|
|
1052
|
+
ORDER BY c.TABLE_SCHEMA, c.TABLE_NAME, c.ORDINAL_POSITION`
|
|
1053
|
+
),
|
|
1054
|
+
// 2) 主キー
|
|
1055
|
+
run(
|
|
1056
|
+
`SELECT tc.TABLE_SCHEMA AS table_schema, tc.TABLE_NAME AS table_name,
|
|
1057
|
+
kcu.COLUMN_NAME AS column_name
|
|
1058
|
+
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
|
|
1059
|
+
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
|
|
1060
|
+
ON kcu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
|
|
1061
|
+
AND kcu.TABLE_SCHEMA = tc.TABLE_SCHEMA
|
|
1062
|
+
AND kcu.TABLE_NAME = tc.TABLE_NAME
|
|
1063
|
+
WHERE tc.CONSTRAINT_TYPE = 'PRIMARY KEY'
|
|
1064
|
+
AND tc.TABLE_SCHEMA NOT IN ('sys', 'INFORMATION_SCHEMA')`
|
|
1065
|
+
),
|
|
1066
|
+
// 3) 外部キー(参照元列 → 参照先列)。sys カタログで複合 FK も 1:1 に解決する。
|
|
1067
|
+
run(
|
|
1068
|
+
`SELECT sch.name AS table_schema, tab.name AS table_name, col.name AS column_name,
|
|
1069
|
+
rsch.name AS foreign_table_schema, rtab.name AS foreign_table_name,
|
|
1070
|
+
rcol.name AS foreign_column_name
|
|
1071
|
+
FROM sys.foreign_key_columns fkc
|
|
1072
|
+
JOIN sys.tables tab ON tab.object_id = fkc.parent_object_id
|
|
1073
|
+
JOIN sys.schemas sch ON sch.schema_id = tab.schema_id
|
|
1074
|
+
JOIN sys.columns col ON col.object_id = fkc.parent_object_id
|
|
1075
|
+
AND col.column_id = fkc.parent_column_id
|
|
1076
|
+
JOIN sys.tables rtab ON rtab.object_id = fkc.referenced_object_id
|
|
1077
|
+
JOIN sys.schemas rsch ON rsch.schema_id = rtab.schema_id
|
|
1078
|
+
JOIN sys.columns rcol ON rcol.object_id = fkc.referenced_object_id
|
|
1079
|
+
AND rcol.column_id = fkc.referenced_column_id`
|
|
1080
|
+
)
|
|
1081
|
+
]);
|
|
1082
|
+
return assembleIntrospectedSchema({ colRows, pkRows, fkRows });
|
|
1083
|
+
}
|
|
1084
|
+
|
|
825
1085
|
// ../connectors/src/connectors/azure-sql/index.ts
|
|
826
1086
|
init_mssql_runner();
|
|
827
1087
|
init_utils();
|
|
@@ -865,6 +1125,9 @@ var outputSchema = z.discriminatedUnion("success", [
|
|
|
865
1125
|
z.object({
|
|
866
1126
|
success: z.literal(true),
|
|
867
1127
|
rowCount: z.number(),
|
|
1128
|
+
rowsAffected: z.number().optional().describe(
|
|
1129
|
+
"Affected rows for INSERT/UPDATE/DELETE; undefined for SELECT"
|
|
1130
|
+
),
|
|
868
1131
|
truncated: z.boolean(),
|
|
869
1132
|
rows: z.array(z.record(z.string(), z.unknown()))
|
|
870
1133
|
}),
|
|
@@ -878,7 +1141,8 @@ var executeQueryTool = new ConnectorTool({
|
|
|
878
1141
|
description: `Execute a T-SQL query against Azure SQL Database. Returns up to ${MAX_ROWS} rows.
|
|
879
1142
|
Use for: schema exploration via \`INFORMATION_SCHEMA\`, data sampling, and analytical queries.
|
|
880
1143
|
Azure SQL is T-SQL: use \`TOP n\` instead of \`LIMIT n\`. Identifiers can be wrapped in square brackets.
|
|
881
|
-
Avoid loading large amounts of data; always include \`TOP\` in queries
|
|
1144
|
+
Avoid loading large amounts of data; always include \`TOP\` in queries.
|
|
1145
|
+
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.`,
|
|
882
1146
|
inputSchema,
|
|
883
1147
|
outputSchema,
|
|
884
1148
|
async execute({ connectionId, sql }, connections) {
|
|
@@ -905,7 +1169,7 @@ Avoid loading large amounts of data; always include \`TOP\` in queries.`,
|
|
|
905
1169
|
};
|
|
906
1170
|
}
|
|
907
1171
|
try {
|
|
908
|
-
const { rows } = await runMssqlQuery(parsed, sql, {
|
|
1172
|
+
const { rows, rowsAffected } = await runMssqlQuery(parsed, sql, {
|
|
909
1173
|
forceEncrypt: true,
|
|
910
1174
|
tunnelParams: connectionParamsToRecord(connection2)
|
|
911
1175
|
});
|
|
@@ -913,6 +1177,9 @@ Avoid loading large amounts of data; always include \`TOP\` in queries.`,
|
|
|
913
1177
|
return {
|
|
914
1178
|
success: true,
|
|
915
1179
|
rowCount: Math.min(rows.length, MAX_ROWS),
|
|
1180
|
+
// tedious counts SELECT result rows in rowsAffected too, so only
|
|
1181
|
+
// report it for DML. Multi-statement batches are summed.
|
|
1182
|
+
rowsAffected: isDmlStatement(sql) ? rowsAffected.reduce((sum, n) => sum + n, 0) : void 0,
|
|
916
1183
|
truncated,
|
|
917
1184
|
rows: rows.slice(0, MAX_ROWS)
|
|
918
1185
|
};
|
|
@@ -973,6 +1240,12 @@ The business logic type for this connector is "sql".
|
|
|
973
1240
|
- \u884C\u6570\u5236\u9650\u306E\u4E92\u63DB\u6027: \u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u306E server-logic \u30B9\u30AD\u30FC\u30DE\u63A8\u8AD6\u306F\u3001\u30AF\u30A8\u30EA\u3092 \`SELECT * FROM (<inner>) AS _sq LIMIT N\` \u306E\u5F62\u3067\u30E9\u30C3\u30D7\u3057\u3066\u304F\u308B\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002T-SQL \u306B\u306F \`LIMIT\` \u304C\u7121\u3044\u305F\u3081\u3001\u30B3\u30CD\u30AF\u30BF\u306F \`query()\` \u5185\u3067\u3053\u306E\u30E9\u30C3\u30D1\u3092\u691C\u51FA\u3057\u3001\`<inner>\` \u3092\u305D\u306E\u307E\u307E\u5B9F\u884C\u3057\u3066 JS \u5074\u3067\u5148\u982D N \u884C\u306B\u5207\u308A\u8A70\u3081\u307E\u3059\u3002\u5229\u7528\u8005\u5074\u3067\u5BFE\u51E6\u3059\u308B\u5FC5\u8981\u306F\u3042\u308A\u307E\u305B\u3093\u304C\u3001\u81EA\u5206\u3067\u66F8\u304F SQL \u3067\u306F \`LIMIT\` \u3092\u4F7F\u308F\u305A \`TOP\` / \`OFFSET ... FETCH NEXT\` \u3092\u4F7F\u3063\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
974
1241
|
},
|
|
975
1242
|
tools,
|
|
1243
|
+
// 決定論的な立ち上げ survey(ルールベース prewarm)。Azure SQL はユーザーオブジェクトが既定 `dbo`、識別子は `[ ]`。
|
|
1244
|
+
surveyProbes: makeStandardSqlSurveyProbes({
|
|
1245
|
+
schemaLiteral: "dbo",
|
|
1246
|
+
bracket: true
|
|
1247
|
+
}),
|
|
1248
|
+
introspect: (ctx) => withRowCounts(ctx, introspectMssql(ctx.query), quoteBracket),
|
|
976
1249
|
setup: (params, ctx, config) => runSetupFlow(azureSqlSetupFlow, params, ctx, config),
|
|
977
1250
|
async checkConnection(params, _config) {
|
|
978
1251
|
return checkMssqlConnection(
|
|
@@ -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
|
|
@@ -173,6 +178,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
173
178
|
* `runSetupFlow` from `setup-flow.ts`.
|
|
174
179
|
*/
|
|
175
180
|
setup;
|
|
181
|
+
/**
|
|
182
|
+
* 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
|
|
183
|
+
* メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
|
|
184
|
+
* {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
|
|
185
|
+
* 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
|
|
186
|
+
* `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
|
|
187
|
+
* coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
|
|
188
|
+
*/
|
|
189
|
+
introspect;
|
|
176
190
|
/**
|
|
177
191
|
* Opt-out of the default "verify before save" behavior on connection
|
|
178
192
|
* creation. The backend invokes `checkConnection` synchronously while
|
|
@@ -187,6 +201,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
187
201
|
* the default verify-on-create behavior without opt-in.
|
|
188
202
|
*/
|
|
189
203
|
skipConnectionCheckOnCreate;
|
|
204
|
+
/**
|
|
205
|
+
* 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
|
|
206
|
+
* read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
|
|
207
|
+
* recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
|
|
208
|
+
* driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
|
|
209
|
+
* 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
|
|
210
|
+
*/
|
|
211
|
+
surveyProbes;
|
|
190
212
|
constructor(config) {
|
|
191
213
|
this.slug = config.slug;
|
|
192
214
|
this.authType = config.authType;
|
|
@@ -204,7 +226,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
204
226
|
this.query = config.query;
|
|
205
227
|
this.checkConnection = config.checkConnection;
|
|
206
228
|
this.setup = config.setup;
|
|
229
|
+
this.introspect = config.introspect;
|
|
207
230
|
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
231
|
+
this.surveyProbes = config.surveyProbes;
|
|
208
232
|
}
|
|
209
233
|
get connectorKey() {
|
|
210
234
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -242,25 +266,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
242
266
|
if (authType) return `${slug}-${authType}`;
|
|
243
267
|
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
244
268
|
// user-password
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
269
|
+
postgresql: "user-password",
|
|
270
|
+
mysql: "user-password",
|
|
271
|
+
clickhouse: "user-password",
|
|
272
|
+
kintone: "user-password",
|
|
249
273
|
"squadbase-db": "user-password",
|
|
250
274
|
// service-account
|
|
251
|
-
|
|
252
|
-
|
|
275
|
+
snowflake: "service-account",
|
|
276
|
+
bigquery: "service-account",
|
|
253
277
|
"google-analytics": "service-account",
|
|
254
278
|
"google-calendar": "service-account",
|
|
255
279
|
"aws-athena": "service-account",
|
|
256
|
-
|
|
280
|
+
redshift: "service-account",
|
|
257
281
|
// api-key
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
282
|
+
databricks: "api-key",
|
|
283
|
+
dbt: "api-key",
|
|
284
|
+
airtable: "api-key",
|
|
285
|
+
openai: "api-key",
|
|
286
|
+
gemini: "api-key",
|
|
287
|
+
anthropic: "api-key",
|
|
264
288
|
"wix-store": "api-key"
|
|
265
289
|
};
|
|
266
290
|
const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
|