@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
|
|
@@ -245,6 +250,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
245
250
|
* `runSetupFlow` from `setup-flow.ts`.
|
|
246
251
|
*/
|
|
247
252
|
setup;
|
|
253
|
+
/**
|
|
254
|
+
* 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
|
|
255
|
+
* メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
|
|
256
|
+
* {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
|
|
257
|
+
* 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
|
|
258
|
+
* `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
|
|
259
|
+
* coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
|
|
260
|
+
*/
|
|
261
|
+
introspect;
|
|
248
262
|
/**
|
|
249
263
|
* Opt-out of the default "verify before save" behavior on connection
|
|
250
264
|
* creation. The backend invokes `checkConnection` synchronously while
|
|
@@ -259,6 +273,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
259
273
|
* the default verify-on-create behavior without opt-in.
|
|
260
274
|
*/
|
|
261
275
|
skipConnectionCheckOnCreate;
|
|
276
|
+
/**
|
|
277
|
+
* 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
|
|
278
|
+
* read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
|
|
279
|
+
* recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
|
|
280
|
+
* driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
|
|
281
|
+
* 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
|
|
282
|
+
*/
|
|
283
|
+
surveyProbes;
|
|
262
284
|
constructor(config) {
|
|
263
285
|
this.slug = config.slug;
|
|
264
286
|
this.authType = config.authType;
|
|
@@ -276,7 +298,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
276
298
|
this.query = config.query;
|
|
277
299
|
this.checkConnection = config.checkConnection;
|
|
278
300
|
this.setup = config.setup;
|
|
301
|
+
this.introspect = config.introspect;
|
|
279
302
|
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
303
|
+
this.surveyProbes = config.surveyProbes;
|
|
280
304
|
}
|
|
281
305
|
get connectorKey() {
|
|
282
306
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -314,25 +338,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
314
338
|
if (authType) return `${slug}-${authType}`;
|
|
315
339
|
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
316
340
|
// user-password
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
341
|
+
postgresql: "user-password",
|
|
342
|
+
mysql: "user-password",
|
|
343
|
+
clickhouse: "user-password",
|
|
344
|
+
kintone: "user-password",
|
|
321
345
|
"squadbase-db": "user-password",
|
|
322
346
|
// service-account
|
|
323
|
-
|
|
324
|
-
|
|
347
|
+
snowflake: "service-account",
|
|
348
|
+
bigquery: "service-account",
|
|
325
349
|
"google-analytics": "service-account",
|
|
326
350
|
"google-calendar": "service-account",
|
|
327
351
|
"aws-athena": "service-account",
|
|
328
|
-
|
|
352
|
+
redshift: "service-account",
|
|
329
353
|
// api-key
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
354
|
+
databricks: "api-key",
|
|
355
|
+
dbt: "api-key",
|
|
356
|
+
airtable: "api-key",
|
|
357
|
+
openai: "api-key",
|
|
358
|
+
gemini: "api-key",
|
|
359
|
+
anthropic: "api-key",
|
|
336
360
|
"wix-store": "api-key"
|
|
337
361
|
};
|
|
338
362
|
const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
|
|
@@ -597,6 +621,50 @@ var notionSetupFlow = {
|
|
|
597
621
|
}
|
|
598
622
|
};
|
|
599
623
|
|
|
624
|
+
// ../connectors/src/connectors/notion/introspect.ts
|
|
625
|
+
var MAX_PAGES = 20;
|
|
626
|
+
var PAGE_SIZE = 100;
|
|
627
|
+
async function introspectNotion(ctx) {
|
|
628
|
+
const tables = [];
|
|
629
|
+
let cursor;
|
|
630
|
+
for (let page = 0; page < MAX_PAGES; page++) {
|
|
631
|
+
const body = {
|
|
632
|
+
filter: { property: "object", value: "database" },
|
|
633
|
+
page_size: PAGE_SIZE
|
|
634
|
+
};
|
|
635
|
+
if (cursor) body.start_cursor = cursor;
|
|
636
|
+
const res = await apiFetch(ctx.params, "/search", {
|
|
637
|
+
method: "POST",
|
|
638
|
+
body: JSON.stringify(body)
|
|
639
|
+
});
|
|
640
|
+
if (!res.ok) {
|
|
641
|
+
throw new Error(`notion: search failed (${res.status})`);
|
|
642
|
+
}
|
|
643
|
+
const data = await res.json();
|
|
644
|
+
for (const db of data.results ?? []) {
|
|
645
|
+
const name = (db.title ?? []).map((t) => t.plain_text ?? "").join("").trim() || "Untitled";
|
|
646
|
+
const columns = Object.entries(
|
|
647
|
+
db.properties ?? {}
|
|
648
|
+
).map(([propName, prop]) => {
|
|
649
|
+
const column = {
|
|
650
|
+
name: propName,
|
|
651
|
+
dataType: prop.type ?? "unknown",
|
|
652
|
+
nullable: true
|
|
653
|
+
};
|
|
654
|
+
if (prop.type === "title") column.isPrimaryKey = true;
|
|
655
|
+
if (prop.type === "relation" && prop.relation?.database_id) {
|
|
656
|
+
column.foreignKey = { table: prop.relation.database_id, column: "" };
|
|
657
|
+
}
|
|
658
|
+
return column;
|
|
659
|
+
});
|
|
660
|
+
tables.push({ schema: "", name, type: "table", columns });
|
|
661
|
+
}
|
|
662
|
+
if (!data.has_more || !data.next_cursor) break;
|
|
663
|
+
cursor = data.next_cursor;
|
|
664
|
+
}
|
|
665
|
+
return { tables };
|
|
666
|
+
}
|
|
667
|
+
|
|
600
668
|
// ../connectors/src/connectors/notion/tools/request.ts
|
|
601
669
|
import { z } from "zod";
|
|
602
670
|
var BASE_URL3 = "https://api.notion.com/v1";
|
|
@@ -832,6 +900,7 @@ export default async function handler(c: Context) {
|
|
|
832
900
|
- 25\u4EF6\u4EE5\u4E0A\u306E\u30A2\u30A4\u30C6\u30E0\u3092\u6301\u3064\u30D7\u30ED\u30D1\u30C6\u30A3\uFF08people\u3001relation\u306A\u3069\uFF09\u306F\u5B8C\u5168\u306A\u30C7\u30FC\u30BF\u53D6\u5F97\u306B\u30D7\u30ED\u30D1\u30C6\u30A3\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u304C\u5FC5\u8981\u3067\u3059`
|
|
833
901
|
},
|
|
834
902
|
tools,
|
|
903
|
+
introspect: (ctx) => introspectNotion(ctx),
|
|
835
904
|
setup: (params, ctx, config) => runSetupFlow(notionSetupFlow, params, ctx, config),
|
|
836
905
|
async checkConnection(params, _config) {
|
|
837
906
|
const apiKey = params[parameters.apiKey.slug];
|
|
@@ -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
|
|
@@ -105,6 +110,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
105
110
|
* `runSetupFlow` from `setup-flow.ts`.
|
|
106
111
|
*/
|
|
107
112
|
setup;
|
|
113
|
+
/**
|
|
114
|
+
* 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
|
|
115
|
+
* メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
|
|
116
|
+
* {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
|
|
117
|
+
* 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
|
|
118
|
+
* `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
|
|
119
|
+
* coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
|
|
120
|
+
*/
|
|
121
|
+
introspect;
|
|
108
122
|
/**
|
|
109
123
|
* Opt-out of the default "verify before save" behavior on connection
|
|
110
124
|
* creation. The backend invokes `checkConnection` synchronously while
|
|
@@ -119,6 +133,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
119
133
|
* the default verify-on-create behavior without opt-in.
|
|
120
134
|
*/
|
|
121
135
|
skipConnectionCheckOnCreate;
|
|
136
|
+
/**
|
|
137
|
+
* 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
|
|
138
|
+
* read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
|
|
139
|
+
* recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
|
|
140
|
+
* driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
|
|
141
|
+
* 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
|
|
142
|
+
*/
|
|
143
|
+
surveyProbes;
|
|
122
144
|
constructor(config) {
|
|
123
145
|
this.slug = config.slug;
|
|
124
146
|
this.authType = config.authType;
|
|
@@ -136,7 +158,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
136
158
|
this.query = config.query;
|
|
137
159
|
this.checkConnection = config.checkConnection;
|
|
138
160
|
this.setup = config.setup;
|
|
161
|
+
this.introspect = config.introspect;
|
|
139
162
|
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
163
|
+
this.surveyProbes = config.surveyProbes;
|
|
140
164
|
}
|
|
141
165
|
get connectorKey() {
|
|
142
166
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -174,25 +198,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
174
198
|
if (authType) return `${slug}-${authType}`;
|
|
175
199
|
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
176
200
|
// user-password
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
201
|
+
postgresql: "user-password",
|
|
202
|
+
mysql: "user-password",
|
|
203
|
+
clickhouse: "user-password",
|
|
204
|
+
kintone: "user-password",
|
|
181
205
|
"squadbase-db": "user-password",
|
|
182
206
|
// service-account
|
|
183
|
-
|
|
184
|
-
|
|
207
|
+
snowflake: "service-account",
|
|
208
|
+
bigquery: "service-account",
|
|
185
209
|
"google-analytics": "service-account",
|
|
186
210
|
"google-calendar": "service-account",
|
|
187
211
|
"aws-athena": "service-account",
|
|
188
|
-
|
|
212
|
+
redshift: "service-account",
|
|
189
213
|
// api-key
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
214
|
+
databricks: "api-key",
|
|
215
|
+
dbt: "api-key",
|
|
216
|
+
airtable: "api-key",
|
|
217
|
+
openai: "api-key",
|
|
218
|
+
gemini: "api-key",
|
|
219
|
+
anthropic: "api-key",
|
|
196
220
|
"wix-store": "api-key"
|
|
197
221
|
};
|
|
198
222
|
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)
|
|
@@ -334,10 +339,16 @@ async function runOracleQuery(parsed, sql, options = {}) {
|
|
|
334
339
|
outFormat: oracledb.OUT_FORMAT_OBJECT,
|
|
335
340
|
// Bound by the connector's own row cap, but keep the driver from
|
|
336
341
|
// streaming arbitrarily large result sets.
|
|
337
|
-
maxRows: 5e3
|
|
342
|
+
maxRows: 5e3,
|
|
343
|
+
// oracledb defaults to autoCommit=false, which silently rolls back
|
|
344
|
+
// DML when the connection closes.
|
|
345
|
+
autoCommit: true
|
|
338
346
|
}
|
|
339
347
|
);
|
|
340
|
-
return {
|
|
348
|
+
return {
|
|
349
|
+
rows: result.rows ?? [],
|
|
350
|
+
rowsAffected: result.rowsAffected
|
|
351
|
+
};
|
|
341
352
|
} finally {
|
|
342
353
|
try {
|
|
343
354
|
await connection2.close();
|
|
@@ -508,6 +519,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
508
519
|
* `runSetupFlow` from `setup-flow.ts`.
|
|
509
520
|
*/
|
|
510
521
|
setup;
|
|
522
|
+
/**
|
|
523
|
+
* 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
|
|
524
|
+
* メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
|
|
525
|
+
* {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
|
|
526
|
+
* 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
|
|
527
|
+
* `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
|
|
528
|
+
* coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
|
|
529
|
+
*/
|
|
530
|
+
introspect;
|
|
511
531
|
/**
|
|
512
532
|
* Opt-out of the default "verify before save" behavior on connection
|
|
513
533
|
* creation. The backend invokes `checkConnection` synchronously while
|
|
@@ -522,6 +542,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
522
542
|
* the default verify-on-create behavior without opt-in.
|
|
523
543
|
*/
|
|
524
544
|
skipConnectionCheckOnCreate;
|
|
545
|
+
/**
|
|
546
|
+
* 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
|
|
547
|
+
* read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
|
|
548
|
+
* recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
|
|
549
|
+
* driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
|
|
550
|
+
* 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
|
|
551
|
+
*/
|
|
552
|
+
surveyProbes;
|
|
525
553
|
constructor(config) {
|
|
526
554
|
this.slug = config.slug;
|
|
527
555
|
this.authType = config.authType;
|
|
@@ -539,7 +567,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
539
567
|
this.query = config.query;
|
|
540
568
|
this.checkConnection = config.checkConnection;
|
|
541
569
|
this.setup = config.setup;
|
|
570
|
+
this.introspect = config.introspect;
|
|
542
571
|
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
572
|
+
this.surveyProbes = config.surveyProbes;
|
|
543
573
|
}
|
|
544
574
|
get connectorKey() {
|
|
545
575
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -577,25 +607,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
577
607
|
if (authType) return `${slug}-${authType}`;
|
|
578
608
|
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
579
609
|
// user-password
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
610
|
+
postgresql: "user-password",
|
|
611
|
+
mysql: "user-password",
|
|
612
|
+
clickhouse: "user-password",
|
|
613
|
+
kintone: "user-password",
|
|
584
614
|
"squadbase-db": "user-password",
|
|
585
615
|
// service-account
|
|
586
|
-
|
|
587
|
-
|
|
616
|
+
snowflake: "service-account",
|
|
617
|
+
bigquery: "service-account",
|
|
588
618
|
"google-analytics": "service-account",
|
|
589
619
|
"google-calendar": "service-account",
|
|
590
620
|
"aws-athena": "service-account",
|
|
591
|
-
|
|
621
|
+
redshift: "service-account",
|
|
592
622
|
// api-key
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
623
|
+
databricks: "api-key",
|
|
624
|
+
dbt: "api-key",
|
|
625
|
+
airtable: "api-key",
|
|
626
|
+
openai: "api-key",
|
|
627
|
+
gemini: "api-key",
|
|
628
|
+
anthropic: "api-key",
|
|
599
629
|
"wix-store": "api-key"
|
|
600
630
|
};
|
|
601
631
|
const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
|
|
@@ -604,6 +634,80 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
604
634
|
}
|
|
605
635
|
};
|
|
606
636
|
|
|
637
|
+
// ../connectors/src/survey-probe.ts
|
|
638
|
+
function rowsOf(output) {
|
|
639
|
+
if (!output || typeof output !== "object") return [];
|
|
640
|
+
const o = output;
|
|
641
|
+
if (o.success === false) return [];
|
|
642
|
+
return Array.isArray(o.rows) ? o.rows : [];
|
|
643
|
+
}
|
|
644
|
+
function pickString(row, candidates) {
|
|
645
|
+
for (const key of candidates) {
|
|
646
|
+
const v = row[key] ?? row[key.toUpperCase()] ?? row[key.toLowerCase()];
|
|
647
|
+
if (typeof v === "string" && v.length > 0) return v;
|
|
648
|
+
}
|
|
649
|
+
return void 0;
|
|
650
|
+
}
|
|
651
|
+
var TABLE_NAME_FIELDS = [
|
|
652
|
+
"table_name",
|
|
653
|
+
"name",
|
|
654
|
+
"tableName",
|
|
655
|
+
"tab_name",
|
|
656
|
+
"Table",
|
|
657
|
+
"table"
|
|
658
|
+
];
|
|
659
|
+
function makeQuoteIdent(opts) {
|
|
660
|
+
if (opts.bracket) {
|
|
661
|
+
return (name) => `[${name.replaceAll("]", "]]")}]`;
|
|
662
|
+
}
|
|
663
|
+
const q = opts.quote ?? '"';
|
|
664
|
+
return (name) => `${q}${name.replaceAll(q, q + q)}${q}`;
|
|
665
|
+
}
|
|
666
|
+
function sampleSql(ref, limit) {
|
|
667
|
+
return `SELECT * FROM (SELECT * FROM ${ref}) AS _sq LIMIT ${limit}`;
|
|
668
|
+
}
|
|
669
|
+
function distinctTables(prior, max) {
|
|
670
|
+
const names = [];
|
|
671
|
+
const seen = /* @__PURE__ */ new Set();
|
|
672
|
+
for (const row of rowsOf(prior[0]?.output)) {
|
|
673
|
+
const name = pickString(row, TABLE_NAME_FIELDS);
|
|
674
|
+
if (!name || seen.has(name)) continue;
|
|
675
|
+
seen.add(name);
|
|
676
|
+
names.push(name);
|
|
677
|
+
if (names.length >= max) break;
|
|
678
|
+
}
|
|
679
|
+
return names;
|
|
680
|
+
}
|
|
681
|
+
function makeOracleSurveyProbes(opts) {
|
|
682
|
+
const queryTool = opts?.queryTool ?? "executeQuery";
|
|
683
|
+
const sampleLimit = opts?.sampleLimit ?? 5;
|
|
684
|
+
const maxSampleTables = opts?.maxSampleTables ?? 4;
|
|
685
|
+
const quoteIdent = makeQuoteIdent({ quote: '"' });
|
|
686
|
+
return (_connectionId, prior) => {
|
|
687
|
+
if (prior.length === 0) {
|
|
688
|
+
return [
|
|
689
|
+
{
|
|
690
|
+
tool: queryTool,
|
|
691
|
+
input: {
|
|
692
|
+
toolUseIntent: "Survey table/column metadata",
|
|
693
|
+
sql: "SELECT table_name, column_name, data_type FROM user_tab_columns ORDER BY table_name, column_id FETCH FIRST 1000 ROWS ONLY"
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
];
|
|
697
|
+
}
|
|
698
|
+
if (prior.length === 1) {
|
|
699
|
+
return distinctTables(prior, maxSampleTables).map((name) => ({
|
|
700
|
+
tool: queryTool,
|
|
701
|
+
input: {
|
|
702
|
+
toolUseIntent: `Sample ${name}`,
|
|
703
|
+
sql: sampleSql(quoteIdent(name), sampleLimit)
|
|
704
|
+
}
|
|
705
|
+
}));
|
|
706
|
+
}
|
|
707
|
+
return [];
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
|
|
607
711
|
// ../connectors/src/setup-flow.ts
|
|
608
712
|
async function runSetupFlow(flow, params, ctx, config) {
|
|
609
713
|
const runtime = {
|
|
@@ -674,6 +778,58 @@ async function resolveSetupSelection(params) {
|
|
|
674
778
|
return resolved.slice(0, limit);
|
|
675
779
|
}
|
|
676
780
|
|
|
781
|
+
// ../connectors/src/introspect-concurrency.ts
|
|
782
|
+
async function mapWithConcurrency(items, limit, fn) {
|
|
783
|
+
const results = new Array(items.length);
|
|
784
|
+
let next = 0;
|
|
785
|
+
const workers = Array.from(
|
|
786
|
+
{ length: Math.min(Math.max(limit, 1), items.length) },
|
|
787
|
+
async () => {
|
|
788
|
+
for (; ; ) {
|
|
789
|
+
const i = next++;
|
|
790
|
+
if (i >= items.length) return;
|
|
791
|
+
results[i] = await fn(items[i]);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
);
|
|
795
|
+
await Promise.all(workers);
|
|
796
|
+
return results;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
// ../connectors/src/introspect-profile.ts
|
|
800
|
+
var DEFAULT_MAX_TABLES = 200;
|
|
801
|
+
var DEFAULT_CONCURRENCY = 5;
|
|
802
|
+
function dq(ident) {
|
|
803
|
+
return `"${ident.replace(/"/g, '""')}"`;
|
|
804
|
+
}
|
|
805
|
+
var quoteAnsi = (schema, name) => [...schema.split("."), name].map(dq).join(".");
|
|
806
|
+
async function withRowCounts(ctx, schemaPromise, quoteRef, opts = {}) {
|
|
807
|
+
const schema = await schemaPromise;
|
|
808
|
+
if (!ctx.profile || !ctx.query) return schema;
|
|
809
|
+
return attachRowCounts(ctx.query, schema, quoteRef, opts);
|
|
810
|
+
}
|
|
811
|
+
async function attachRowCounts(run, schema, quoteRef, opts = {}) {
|
|
812
|
+
const targets = schema.tables.slice(0, opts.maxTables ?? DEFAULT_MAX_TABLES);
|
|
813
|
+
await mapWithConcurrency(
|
|
814
|
+
targets,
|
|
815
|
+
opts.concurrency ?? DEFAULT_CONCURRENCY,
|
|
816
|
+
async (table) => {
|
|
817
|
+
try {
|
|
818
|
+
const { rows } = await run(
|
|
819
|
+
`SELECT COUNT(*) AS row_count FROM ${quoteRef(table.schema, table.name)}`
|
|
820
|
+
);
|
|
821
|
+
const first = rows[0] ? Object.values(rows[0])[0] : void 0;
|
|
822
|
+
const rowCount = Number(first);
|
|
823
|
+
if (Number.isFinite(rowCount)) {
|
|
824
|
+
table.profile = { ...table.profile ?? {}, rowCount };
|
|
825
|
+
}
|
|
826
|
+
} catch {
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
);
|
|
830
|
+
return schema;
|
|
831
|
+
}
|
|
832
|
+
|
|
677
833
|
// ../connectors/src/auth-types.ts
|
|
678
834
|
var AUTH_TYPES = {
|
|
679
835
|
OAUTH: "oauth",
|
|
@@ -684,6 +840,63 @@ var AUTH_TYPES = {
|
|
|
684
840
|
USER_PASSWORD: "user-password"
|
|
685
841
|
};
|
|
686
842
|
|
|
843
|
+
// ../connectors/src/introspect-information-schema.ts
|
|
844
|
+
function pickCI(row, key) {
|
|
845
|
+
if (key in row) return String(row[key] ?? "");
|
|
846
|
+
const lower = key.toLowerCase();
|
|
847
|
+
for (const k of Object.keys(row)) {
|
|
848
|
+
if (k.toLowerCase() === lower) return String(row[k] ?? "");
|
|
849
|
+
}
|
|
850
|
+
return "";
|
|
851
|
+
}
|
|
852
|
+
function assembleIntrospectedSchema(input) {
|
|
853
|
+
const { colRows, pkRows = [], fkRows = [] } = input;
|
|
854
|
+
const pkSet = /* @__PURE__ */ new Set();
|
|
855
|
+
for (const r of pkRows) {
|
|
856
|
+
pkSet.add(
|
|
857
|
+
`${pickCI(r, "table_schema")}.${pickCI(r, "table_name")}.${pickCI(r, "column_name")}`
|
|
858
|
+
);
|
|
859
|
+
}
|
|
860
|
+
const fkMap = /* @__PURE__ */ new Map();
|
|
861
|
+
for (const r of fkRows) {
|
|
862
|
+
fkMap.set(
|
|
863
|
+
`${pickCI(r, "table_schema")}.${pickCI(r, "table_name")}.${pickCI(r, "column_name")}`,
|
|
864
|
+
{
|
|
865
|
+
schema: pickCI(r, "foreign_table_schema"),
|
|
866
|
+
table: pickCI(r, "foreign_table_name"),
|
|
867
|
+
column: pickCI(r, "foreign_column_name")
|
|
868
|
+
}
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
const tableMap = /* @__PURE__ */ new Map();
|
|
872
|
+
for (const r of colRows) {
|
|
873
|
+
const schema = pickCI(r, "table_schema");
|
|
874
|
+
const name = pickCI(r, "table_name");
|
|
875
|
+
const key = `${schema}.${name}`;
|
|
876
|
+
let table = tableMap.get(key);
|
|
877
|
+
if (!table) {
|
|
878
|
+
table = {
|
|
879
|
+
schema,
|
|
880
|
+
name,
|
|
881
|
+
type: pickCI(r, "table_type").toUpperCase() === "VIEW" ? "view" : "table",
|
|
882
|
+
columns: []
|
|
883
|
+
};
|
|
884
|
+
tableMap.set(key, table);
|
|
885
|
+
}
|
|
886
|
+
const colKey = `${schema}.${name}.${pickCI(r, "column_name")}`;
|
|
887
|
+
const column = {
|
|
888
|
+
name: pickCI(r, "column_name"),
|
|
889
|
+
dataType: pickCI(r, "data_type"),
|
|
890
|
+
nullable: pickCI(r, "is_nullable").toUpperCase() === "YES"
|
|
891
|
+
};
|
|
892
|
+
if (pkSet.has(colKey)) column.isPrimaryKey = true;
|
|
893
|
+
const fk = fkMap.get(colKey);
|
|
894
|
+
if (fk) column.foreignKey = fk;
|
|
895
|
+
table.columns.push(column);
|
|
896
|
+
}
|
|
897
|
+
return { tables: [...tableMap.values()] };
|
|
898
|
+
}
|
|
899
|
+
|
|
687
900
|
// ../connectors/src/lib/unwrap-sample-limit.ts
|
|
688
901
|
var STRICT_WRAPPER_RE = /^\s*SELECT\s+\*\s+FROM\s+\(([\s\S]+)\)\s+AS\s+\w+\s+LIMIT\s+(\d+)\s*;?\s*$/i;
|
|
689
902
|
var TRAILING_LIMIT_RE = /\s+LIMIT\s+(\d+)\s*;?\s*$/i;
|
|
@@ -904,6 +1117,58 @@ var oracleSetupFlow = {
|
|
|
904
1117
|
}
|
|
905
1118
|
};
|
|
906
1119
|
|
|
1120
|
+
// ../connectors/src/connectors/oracle/introspect.ts
|
|
1121
|
+
var OWNER_NOT_IN = [...INTERNAL_OWNERS].map((o) => `'${o}'`).join(", ");
|
|
1122
|
+
function ownerFilter(ownerCol) {
|
|
1123
|
+
return `${ownerCol} NOT IN (${OWNER_NOT_IN}) AND ${ownerCol} NOT LIKE 'APEX_%'`;
|
|
1124
|
+
}
|
|
1125
|
+
async function introspectOracle(run) {
|
|
1126
|
+
const [{ rows: colRows }, { rows: pkRows }, { rows: fkRows }] = await Promise.all([
|
|
1127
|
+
// 1) 全カラム(型 / nullable)+ テーブル種別(TABLE / VIEW)
|
|
1128
|
+
run(
|
|
1129
|
+
`SELECT c.owner AS table_schema, c.table_name AS table_name,
|
|
1130
|
+
c.column_name AS column_name, c.data_type AS data_type,
|
|
1131
|
+
CASE WHEN c.nullable = 'Y' THEN 'YES' ELSE 'NO' END AS is_nullable,
|
|
1132
|
+
c.column_id AS ordinal_position,
|
|
1133
|
+
CASE WHEN o.object_type = 'VIEW' THEN 'VIEW' ELSE 'BASE TABLE' END AS table_type
|
|
1134
|
+
FROM all_tab_columns c
|
|
1135
|
+
JOIN all_objects o
|
|
1136
|
+
ON o.owner = c.owner AND o.object_name = c.table_name
|
|
1137
|
+
AND o.object_type IN ('TABLE', 'VIEW')
|
|
1138
|
+
WHERE ${ownerFilter("c.owner")}
|
|
1139
|
+
ORDER BY c.owner, c.table_name, c.column_id`
|
|
1140
|
+
),
|
|
1141
|
+
// 2) 主キー(CONSTRAINT_TYPE = 'P')
|
|
1142
|
+
run(
|
|
1143
|
+
`SELECT ac.owner AS table_schema, ac.table_name AS table_name,
|
|
1144
|
+
acc.column_name AS column_name
|
|
1145
|
+
FROM all_constraints ac
|
|
1146
|
+
JOIN all_cons_columns acc
|
|
1147
|
+
ON acc.owner = ac.owner AND acc.constraint_name = ac.constraint_name
|
|
1148
|
+
WHERE ac.constraint_type = 'P'
|
|
1149
|
+
AND ${ownerFilter("ac.owner")}`
|
|
1150
|
+
),
|
|
1151
|
+
// 3) 外部キー(CONSTRAINT_TYPE = 'R')。参照元 → 参照先を position で突き合わせる。
|
|
1152
|
+
run(
|
|
1153
|
+
`SELECT ac.owner AS table_schema, ac.table_name AS table_name,
|
|
1154
|
+
acc.column_name AS column_name,
|
|
1155
|
+
rac.owner AS foreign_table_schema, rac.table_name AS foreign_table_name,
|
|
1156
|
+
racc.column_name AS foreign_column_name
|
|
1157
|
+
FROM all_constraints ac
|
|
1158
|
+
JOIN all_cons_columns acc
|
|
1159
|
+
ON acc.owner = ac.owner AND acc.constraint_name = ac.constraint_name
|
|
1160
|
+
JOIN all_constraints rac
|
|
1161
|
+
ON rac.owner = ac.r_owner AND rac.constraint_name = ac.r_constraint_name
|
|
1162
|
+
JOIN all_cons_columns racc
|
|
1163
|
+
ON racc.owner = rac.owner AND racc.constraint_name = rac.constraint_name
|
|
1164
|
+
AND racc.position = acc.position
|
|
1165
|
+
WHERE ac.constraint_type = 'R'
|
|
1166
|
+
AND ${ownerFilter("ac.owner")}`
|
|
1167
|
+
)
|
|
1168
|
+
]);
|
|
1169
|
+
return assembleIntrospectedSchema({ colRows, pkRows, fkRows });
|
|
1170
|
+
}
|
|
1171
|
+
|
|
907
1172
|
// ../connectors/src/connectors/oracle/tools/execute-query.ts
|
|
908
1173
|
import { z } from "zod";
|
|
909
1174
|
init_oracle_runner();
|
|
@@ -923,6 +1188,9 @@ var outputSchema = z.discriminatedUnion("success", [
|
|
|
923
1188
|
z.object({
|
|
924
1189
|
success: z.literal(true),
|
|
925
1190
|
rowCount: z.number(),
|
|
1191
|
+
rowsAffected: z.number().optional().describe(
|
|
1192
|
+
"Affected rows for INSERT/UPDATE/DELETE; undefined for SELECT"
|
|
1193
|
+
),
|
|
926
1194
|
truncated: z.boolean(),
|
|
927
1195
|
rows: z.array(z.record(z.string(), z.unknown()))
|
|
928
1196
|
}),
|
|
@@ -937,7 +1205,8 @@ var executeQueryTool = new ConnectorTool({
|
|
|
937
1205
|
Use for: schema exploration via \`USER_TABLES\` / \`USER_TAB_COLUMNS\` / \`ALL_TABLES\`, data sampling, and analytical queries.
|
|
938
1206
|
Oracle uses \`FETCH FIRST n ROWS ONLY\` (12c+) or \`ROWNUM\` for row limiting \u2014 there is no \`LIMIT\` keyword.
|
|
939
1207
|
Unquoted identifiers are stored upper-case (\`SELECT * FROM employees\` resolves to \`EMPLOYEES\`).
|
|
940
|
-
Do NOT terminate statements with a semicolon; the driver rejects trailing terminators
|
|
1208
|
+
Do NOT terminate statements with a semicolon; the driver rejects trailing terminators.
|
|
1209
|
+
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.`,
|
|
941
1210
|
inputSchema,
|
|
942
1211
|
outputSchema,
|
|
943
1212
|
async execute({ connectionId, sql }, connections) {
|
|
@@ -965,13 +1234,15 @@ Do NOT terminate statements with a semicolon; the driver rejects trailing termin
|
|
|
965
1234
|
}
|
|
966
1235
|
try {
|
|
967
1236
|
const cleanSql = sql.replace(/;\s*$/, "");
|
|
968
|
-
const { rows } = await runOracleQuery(parsed, cleanSql, {
|
|
1237
|
+
const { rows, rowsAffected } = await runOracleQuery(parsed, cleanSql, {
|
|
969
1238
|
tunnelParams: connectionParamsToRecord(connection2)
|
|
970
1239
|
});
|
|
971
1240
|
const truncated = rows.length > MAX_ROWS;
|
|
972
1241
|
return {
|
|
973
1242
|
success: true,
|
|
974
1243
|
rowCount: Math.min(rows.length, MAX_ROWS),
|
|
1244
|
+
// oracledb sets rowsAffected only for DML; undefined for SELECT.
|
|
1245
|
+
rowsAffected,
|
|
975
1246
|
truncated,
|
|
976
1247
|
rows: rows.slice(0, MAX_ROWS)
|
|
977
1248
|
};
|
|
@@ -1037,6 +1308,9 @@ The business logic type for this connector is "sql".
|
|
|
1037
1308
|
- \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\u3002Oracle \u306B\u306F \`LIMIT\` \u30AD\u30FC\u30EF\u30FC\u30C9\u304C\u5B58\u5728\u3057\u306A\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 \`FETCH FIRST N ROWS ONLY\` / \`OFFSET m ROWS FETCH NEXT N ROWS ONLY\` / \`ROWNUM\` \u3092\u4F7F\u3063\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
1038
1309
|
},
|
|
1039
1310
|
tools,
|
|
1311
|
+
// 決定論的な立ち上げ survey(ルールベース prewarm)。Oracle は USER_TAB_COLUMNS でメタ取得。
|
|
1312
|
+
surveyProbes: makeOracleSurveyProbes(),
|
|
1313
|
+
introspect: (ctx) => withRowCounts(ctx, introspectOracle(ctx.query), quoteAnsi),
|
|
1040
1314
|
setup: (params, ctx, config) => runSetupFlow(oracleSetupFlow, params, ctx, config),
|
|
1041
1315
|
async checkConnection(params, _config) {
|
|
1042
1316
|
return checkOracleConnection(
|