@squadbase/vite-server 0.1.12-dev.93b8799 → 0.1.17-dev.24af54e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/cli/index.js +12128 -934
  2. package/dist/connectors/airtable-oauth.js +248 -46
  3. package/dist/connectors/airtable.js +285 -51
  4. package/dist/connectors/amplitude.js +288 -47
  5. package/dist/connectors/anthropic.js +126 -47
  6. package/dist/connectors/asana.js +293 -49
  7. package/dist/connectors/attio.js +268 -49
  8. package/dist/connectors/aws-billing.js +253 -46
  9. package/dist/connectors/azure-sql.js +387 -102
  10. package/dist/connectors/backlog-api-key.js +283 -47
  11. package/dist/connectors/clickup.js +304 -49
  12. package/dist/connectors/cosmosdb.js +271 -50
  13. package/dist/connectors/customerio.js +285 -47
  14. package/dist/connectors/dbt.js +306 -47
  15. package/dist/connectors/freshdesk.js +308 -53
  16. package/dist/connectors/freshsales.js +299 -52
  17. package/dist/connectors/freshservice.js +327 -53
  18. package/dist/connectors/gamma.js +293 -52
  19. package/dist/connectors/gemini.js +125 -47
  20. package/dist/connectors/github.js +352 -49
  21. package/dist/connectors/gmail-oauth.js +170 -7
  22. package/dist/connectors/gmail.js +316 -47
  23. package/dist/connectors/google-ads.js +254 -46
  24. package/dist/connectors/google-analytics-oauth.js +276 -46
  25. package/dist/connectors/google-analytics.js +378 -49
  26. package/dist/connectors/google-audit-log.js +404 -47
  27. package/dist/connectors/google-calendar-oauth.js +225 -46
  28. package/dist/connectors/google-calendar.js +325 -47
  29. package/dist/connectors/google-docs.js +186 -6
  30. package/dist/connectors/google-drive.js +228 -5
  31. package/dist/connectors/google-search-console-oauth.js +222 -46
  32. package/dist/connectors/google-sheets.js +238 -47
  33. package/dist/connectors/google-slides.js +171 -6
  34. package/dist/connectors/grafana.js +298 -49
  35. package/dist/connectors/hubspot-oauth.js +174 -5
  36. package/dist/connectors/hubspot.js +272 -49
  37. package/dist/connectors/influxdb.js +382 -51
  38. package/dist/connectors/intercom-oauth.js +176 -5
  39. package/dist/connectors/intercom.js +268 -49
  40. package/dist/connectors/jdbc.js +728 -110
  41. package/dist/connectors/jira-api-key.js +292 -47
  42. package/dist/connectors/kintone-api-token.js +247 -47
  43. package/dist/connectors/kintone.js +294 -47
  44. package/dist/connectors/linear.js +296 -49
  45. package/dist/connectors/linkedin-ads.js +234 -50
  46. package/dist/connectors/mailchimp-oauth.js +234 -46
  47. package/dist/connectors/mailchimp.js +286 -49
  48. package/dist/connectors/meta-ads-oauth.js +239 -48
  49. package/dist/connectors/meta-ads.js +251 -50
  50. package/dist/connectors/mixpanel.js +304 -47
  51. package/dist/connectors/monday.js +326 -49
  52. package/dist/connectors/mongodb.js +285 -57
  53. package/dist/connectors/notion-oauth.js +197 -5
  54. package/dist/connectors/notion.js +289 -51
  55. package/dist/connectors/openai.js +125 -47
  56. package/dist/connectors/oracle.js +405 -103
  57. package/dist/connectors/outlook-oauth.js +170 -5
  58. package/dist/connectors/powerbi-oauth.js +217 -5
  59. package/dist/connectors/salesforce.js +350 -49
  60. package/dist/connectors/semrush.js +280 -49
  61. package/dist/connectors/sentry.js +255 -50
  62. package/dist/connectors/shopify-oauth.js +153 -5
  63. package/dist/connectors/shopify.js +323 -47
  64. package/dist/connectors/sqlserver.js +381 -102
  65. package/dist/connectors/stripe-api-key.js +235 -46
  66. package/dist/connectors/stripe-oauth.js +168 -5
  67. package/dist/connectors/supabase.js +269 -48
  68. package/dist/connectors/tableau.js +337 -206
  69. package/dist/connectors/tiktok-ads.js +245 -48
  70. package/dist/connectors/wix-store.js +286 -49
  71. package/dist/connectors/zendesk-oauth.js +205 -5
  72. package/dist/connectors/zendesk.js +324 -47
  73. package/dist/index.d.ts +149 -1
  74. package/dist/index.js +18297 -6886
  75. package/dist/main.js +12785 -1382
  76. package/dist/vite-plugin.js +12140 -936
  77. package/package.json +1 -1
@@ -1,48 +1,60 @@
1
+ var __getOwnPropNames = Object.getOwnPropertyNames;
2
+ var __esm = (fn, res) => function __init() {
3
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
4
+ };
5
+
1
6
  // ../connectors/src/parameter-definition.ts
2
- var ParameterDefinition = class {
3
- slug;
4
- name;
5
- description;
6
- envVarBaseKey;
7
- type;
8
- secret;
9
- required;
10
- constructor(config) {
11
- this.slug = config.slug;
12
- this.name = config.name;
13
- this.description = config.description;
14
- this.envVarBaseKey = config.envVarBaseKey;
15
- this.type = config.type;
16
- this.secret = config.secret;
17
- this.required = config.required;
18
- }
19
- /**
20
- * Get the parameter value from a ConnectorConnectionObject.
21
- */
22
- getValue(connection2) {
23
- const param = connection2.parameters.find(
24
- (p) => p.parameterSlug === this.slug
25
- );
26
- if (!param || param.value == null) {
27
- throw new Error(
28
- `Parameter "${this.slug}" not found or has no value in connection "${connection2.id}"`
29
- );
30
- }
31
- return param.value;
32
- }
33
- /**
34
- * Try to get the parameter value. Returns undefined if not found (for optional params).
35
- */
36
- tryGetValue(connection2) {
37
- const param = connection2.parameters.find(
38
- (p) => p.parameterSlug === this.slug
39
- );
40
- if (!param || param.value == null) return void 0;
41
- return param.value;
7
+ var ParameterDefinition;
8
+ var init_parameter_definition = __esm({
9
+ "../connectors/src/parameter-definition.ts"() {
10
+ "use strict";
11
+ ParameterDefinition = class {
12
+ slug;
13
+ name;
14
+ description;
15
+ envVarBaseKey;
16
+ type;
17
+ secret;
18
+ required;
19
+ constructor(config) {
20
+ this.slug = config.slug;
21
+ this.name = config.name;
22
+ this.description = config.description;
23
+ this.envVarBaseKey = config.envVarBaseKey;
24
+ this.type = config.type;
25
+ this.secret = config.secret;
26
+ this.required = config.required;
27
+ }
28
+ /**
29
+ * Get the parameter value from a ConnectorConnectionObject.
30
+ */
31
+ getValue(connection2) {
32
+ const param = connection2.parameters.find(
33
+ (p) => p.parameterSlug === this.slug
34
+ );
35
+ if (!param || param.value == null) {
36
+ throw new Error(
37
+ `Parameter "${this.slug}" not found or has no value in connection "${connection2.id}"`
38
+ );
39
+ }
40
+ return param.value;
41
+ }
42
+ /**
43
+ * Try to get the parameter value. Returns undefined if not found (for optional params).
44
+ */
45
+ tryGetValue(connection2) {
46
+ const param = connection2.parameters.find(
47
+ (p) => p.parameterSlug === this.slug
48
+ );
49
+ if (!param || param.value == null) return void 0;
50
+ return param.value;
51
+ }
52
+ };
42
53
  }
43
- };
54
+ });
44
55
 
45
56
  // ../connectors/src/connectors/notion/parameters.ts
57
+ init_parameter_definition();
46
58
  var parameters = {
47
59
  apiKey: new ParameterDefinition({
48
60
  slug: "api-key",
@@ -231,6 +243,20 @@ var ConnectorPlugin = class _ConnectorPlugin {
231
243
  * `runSetupFlow` from `setup-flow.ts`.
232
244
  */
233
245
  setup;
246
+ /**
247
+ * Opt-out of the default "verify before save" behavior on connection
248
+ * creation. The backend invokes `checkConnection` synchronously while
249
+ * creating the connection and aborts (no row inserted) if it fails — this
250
+ * flag disables that for connectors where the check cannot succeed pre-save:
251
+ *
252
+ * - `squadbase-db` populates `connection-url` only after Neon provisioning
253
+ * - OAuth connectors require an OAuth-aware proxyFetch keyed by the
254
+ * connectionId, which doesn't exist until the row is saved
255
+ *
256
+ * Exceptions are the explicit position; new credential-input connectors get
257
+ * the default verify-on-create behavior without opt-in.
258
+ */
259
+ skipConnectionCheckOnCreate;
234
260
  constructor(config) {
235
261
  this.slug = config.slug;
236
262
  this.authType = config.authType;
@@ -248,6 +274,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
248
274
  this.query = config.query;
249
275
  this.checkConnection = config.checkConnection;
250
276
  this.setup = config.setup;
277
+ this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
251
278
  }
252
279
  get connectorKey() {
253
280
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -312,6 +339,51 @@ var ConnectorPlugin = class _ConnectorPlugin {
312
339
  }
313
340
  };
314
341
 
342
+ // ../connectors/src/setup-flow.ts
343
+ async function runSetupFlow(flow, params, ctx, config) {
344
+ const runtime = {
345
+ params,
346
+ language: ctx.language,
347
+ config
348
+ };
349
+ let state = flow.initialState();
350
+ let answerIdx = 0;
351
+ for (const step of flow.steps) {
352
+ const ans = ctx.answers[answerIdx];
353
+ if (ans && ans.questionSlug === step.slug) {
354
+ state = step.applyAnswer(state, ans.answer);
355
+ answerIdx += 1;
356
+ continue;
357
+ }
358
+ if (step.type === "text") {
359
+ return {
360
+ type: "nextQuestion",
361
+ questionSlug: step.slug,
362
+ question: step.question[ctx.language],
363
+ questionType: "text"
364
+ };
365
+ }
366
+ const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
367
+ if (options.length === 0) {
368
+ continue;
369
+ }
370
+ return {
371
+ type: "nextQuestion",
372
+ questionSlug: step.slug,
373
+ question: step.question[ctx.language],
374
+ questionType: step.type,
375
+ options
376
+ };
377
+ }
378
+ const dataInvestigationResult = await flow.finalize(state, runtime);
379
+ return { type: "fulfilled", dataInvestigationResult };
380
+ }
381
+ async function resolveSetupSelection(params) {
382
+ const { selected, allSentinel, fetchAll, limit } = params;
383
+ const resolved = selected.includes(allSentinel) ? await fetchAll() : selected.filter((v) => v !== allSentinel);
384
+ return resolved.slice(0, limit);
385
+ }
386
+
315
387
  // ../connectors/src/auth-types.ts
316
388
  var AUTH_TYPES = {
317
389
  OAUTH: "oauth",
@@ -336,10 +408,123 @@ var notionOnboarding = new ConnectorOnboarding({
336
408
  }
337
409
  });
338
410
 
339
- // ../connectors/src/connectors/notion/tools/request.ts
340
- import { z } from "zod";
411
+ // ../connectors/src/connectors/notion/utils.ts
341
412
  var BASE_URL2 = "https://api.notion.com/v1";
342
413
  var NOTION_VERSION2 = "2022-06-28";
414
+ async function apiFetch(params, path2, init) {
415
+ const apiKey = params[parameters.apiKey.slug];
416
+ if (!apiKey) {
417
+ throw new Error("notion: missing required parameter: api-key");
418
+ }
419
+ const url = `${BASE_URL2}${path2.startsWith("/") ? "" : "/"}${path2}`;
420
+ const headers = new Headers(init?.headers);
421
+ headers.set("Authorization", `Bearer ${apiKey}`);
422
+ headers.set("Notion-Version", NOTION_VERSION2);
423
+ if (init?.body && !headers.has("Content-Type")) {
424
+ headers.set("Content-Type", "application/json");
425
+ }
426
+ return fetch(url, { ...init, headers });
427
+ }
428
+
429
+ // ../connectors/src/connectors/notion/setup-flow.ts
430
+ var ALL_DATABASES = "__ALL_DATABASES__";
431
+ var NOTION_SETUP_MAX_DATABASES = 20;
432
+ function databaseTitle(db) {
433
+ const parts = (db.title ?? []).map((t) => t.plain_text ?? "").filter((s) => s);
434
+ return parts.join("").trim() || "(Untitled)";
435
+ }
436
+ async function searchDatabases(params) {
437
+ const results = [];
438
+ let startCursor;
439
+ for (let i = 0; i < 20; i++) {
440
+ const body = {
441
+ filter: { property: "object", value: "database" },
442
+ page_size: 100
443
+ };
444
+ if (startCursor) body.start_cursor = startCursor;
445
+ const res = await apiFetch(params, "/search", {
446
+ method: "POST",
447
+ body: JSON.stringify(body)
448
+ });
449
+ if (!res.ok) {
450
+ const text = await res.text().catch(() => res.statusText);
451
+ throw new Error(`notion: search failed (${res.status}): ${text}`);
452
+ }
453
+ const data = await res.json();
454
+ for (const r of data.results ?? []) results.push(r);
455
+ if (!data.has_more || !data.next_cursor) break;
456
+ startCursor = data.next_cursor;
457
+ }
458
+ return results;
459
+ }
460
+ async function getDatabase(params, databaseId) {
461
+ const res = await apiFetch(params, `/databases/${databaseId}`);
462
+ if (!res.ok) {
463
+ const text = await res.text().catch(() => res.statusText);
464
+ throw new Error(
465
+ `notion: getDatabase ${databaseId} failed (${res.status}): ${text}`
466
+ );
467
+ }
468
+ return await res.json();
469
+ }
470
+ var notionSetupFlow = {
471
+ initialState: () => ({}),
472
+ steps: [
473
+ {
474
+ slug: "databases",
475
+ type: "multiSelect",
476
+ question: {
477
+ ja: "\u5BFE\u8C61\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
478
+ en: "Select target databases (multi-select allowed)"
479
+ },
480
+ async fetchOptions(_state, rt) {
481
+ const dbs = await searchDatabases(rt.params);
482
+ const dbOptions = dbs.filter((db) => db.id).map((db) => ({ value: db.id, label: databaseTitle(db) }));
483
+ return [
484
+ {
485
+ value: ALL_DATABASES,
486
+ label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9" : "All databases"
487
+ },
488
+ ...dbOptions
489
+ ];
490
+ },
491
+ applyAnswer: (state, answer) => ({ ...state, databases: answer })
492
+ }
493
+ ],
494
+ async finalize(state, rt) {
495
+ if (!state.databases) {
496
+ throw new Error("Notion setup: incomplete state on finalize");
497
+ }
498
+ const targetIds = await resolveSetupSelection({
499
+ selected: state.databases,
500
+ allSentinel: ALL_DATABASES,
501
+ fetchAll: async () => {
502
+ const dbs = await searchDatabases(rt.params);
503
+ return dbs.map((db) => db.id).filter((id) => id);
504
+ },
505
+ limit: NOTION_SETUP_MAX_DATABASES
506
+ });
507
+ const sections = ["## Notion", ""];
508
+ for (const dbId of targetIds) {
509
+ const db = await getDatabase(rt.params, dbId);
510
+ const title = databaseTitle(db);
511
+ sections.push(`### Database: ${title}`, "", `- id: \`${db.id}\``, "");
512
+ sections.push("| Property | Type |");
513
+ sections.push("|----------|------|");
514
+ for (const [name, def] of Object.entries(db.properties ?? {})) {
515
+ const escapedName = name.replace(/\|/g, "\\|");
516
+ sections.push(`| ${escapedName} | ${def?.type ?? "-"} |`);
517
+ }
518
+ sections.push("");
519
+ }
520
+ return sections.join("\n");
521
+ }
522
+ };
523
+
524
+ // ../connectors/src/connectors/notion/tools/request.ts
525
+ import { z } from "zod";
526
+ var BASE_URL3 = "https://api.notion.com/v1";
527
+ var NOTION_VERSION3 = "2022-06-28";
343
528
  var REQUEST_TIMEOUT_MS = 6e4;
344
529
  var inputSchema = z.object({
345
530
  toolUseIntent: z.string().optional().describe(
@@ -386,7 +571,7 @@ Pagination uses cursor-based start_cursor and page_size (max 100).`,
386
571
  );
387
572
  try {
388
573
  const apiKey = parameters.apiKey.getValue(connection2);
389
- const url = `${BASE_URL2}${path2.startsWith("/") ? "" : "/"}${path2}`;
574
+ const url = `${BASE_URL3}${path2.startsWith("/") ? "" : "/"}${path2}`;
390
575
  const controller = new AbortController();
391
576
  const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
392
577
  try {
@@ -394,7 +579,7 @@ Pagination uses cursor-based start_cursor and page_size (max 100).`,
394
579
  method,
395
580
  headers: {
396
581
  Authorization: `Bearer ${apiKey}`,
397
- "Notion-Version": NOTION_VERSION2,
582
+ "Notion-Version": NOTION_VERSION3,
398
583
  "Content-Type": "application/json"
399
584
  },
400
585
  body: body ? JSON.stringify(body) : void 0,
@@ -570,7 +755,40 @@ export default async function handler(c: Context) {
570
755
  - \u30D6\u30ED\u30C3\u30AF\u306E\u5B50\u306F\u6700\u521D\u306E\u30EC\u30D9\u30EB\u306E\u307F\u3067\u3059\u3002\u30CD\u30B9\u30C8\u3055\u308C\u305F\u30B3\u30F3\u30C6\u30F3\u30C4\u306B\u306F\u518D\u5E30\u304C\u5FC5\u8981\u3067\u3059
571
756
  - 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`
572
757
  },
573
- tools
758
+ tools,
759
+ setup: (params, ctx, config) => runSetupFlow(notionSetupFlow, params, ctx, config),
760
+ async checkConnection(params, _config) {
761
+ const apiKey = params[parameters.apiKey.slug];
762
+ if (!apiKey) {
763
+ return {
764
+ success: false,
765
+ error: `Missing required parameter: ${parameters.apiKey.slug}`
766
+ };
767
+ }
768
+ try {
769
+ const res = await fetch("https://api.notion.com/v1/users/me", {
770
+ method: "GET",
771
+ headers: {
772
+ Authorization: `Bearer ${apiKey}`,
773
+ "Notion-Version": "2022-06-28",
774
+ Accept: "application/json"
775
+ }
776
+ });
777
+ if (!res.ok) {
778
+ const errorText = await res.text().catch(() => res.statusText);
779
+ return {
780
+ success: false,
781
+ error: `Notion API failed: HTTP ${res.status} ${errorText}`
782
+ };
783
+ }
784
+ return { success: true };
785
+ } catch (error) {
786
+ return {
787
+ success: false,
788
+ error: error instanceof Error ? error.message : String(error)
789
+ };
790
+ }
791
+ }
574
792
  });
575
793
 
576
794
  // src/connectors/create-connector-sdk.ts
@@ -599,6 +817,7 @@ function resolveEnvVarOptional(entry, key) {
599
817
  import { getContext } from "hono/context-storage";
600
818
  import { getCookie } from "hono/cookie";
601
819
  var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
820
+ var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
602
821
  function normalizeHeaders(input) {
603
822
  const out = {};
604
823
  if (!input) return out;
@@ -607,6 +826,11 @@ function normalizeHeaders(input) {
607
826
  });
608
827
  return out;
609
828
  }
829
+ function extractInputUrl(input) {
830
+ if (typeof input === "string") return input;
831
+ if (input instanceof URL) return input.href;
832
+ return input.url;
833
+ }
610
834
  function createSandboxProxyFetch(connectionId) {
611
835
  return async (input, init) => {
612
836
  const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
@@ -616,10 +840,17 @@ function createSandboxProxyFetch(connectionId) {
616
840
  "Connection proxy is not configured. Please check your deployment settings."
617
841
  );
618
842
  }
619
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
843
+ const originalUrl = extractInputUrl(input);
844
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
845
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
846
+ const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
847
+ return fetch(sessionUrl, {
848
+ method: "POST",
849
+ headers: { Authorization: `Bearer ${token}` }
850
+ });
851
+ }
620
852
  const originalMethod = init?.method ?? "GET";
621
853
  const originalBody = init?.body ? JSON.parse(init.body) : void 0;
622
- const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
623
854
  const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
624
855
  return fetch(proxyUrl, {
625
856
  method: "POST",
@@ -645,10 +876,9 @@ function createDeployedAppProxyFetch(connectionId) {
645
876
  }
646
877
  const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
647
878
  const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
879
+ const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
648
880
  return async (input, init) => {
649
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
650
- const originalMethod = init?.method ?? "GET";
651
- const originalBody = init?.body ? JSON.parse(init.body) : void 0;
881
+ const originalUrl = extractInputUrl(input);
652
882
  const c = getContext();
653
883
  const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
654
884
  if (!appSession) {
@@ -656,6 +886,14 @@ function createDeployedAppProxyFetch(connectionId) {
656
886
  "No authentication method available for connection proxy."
657
887
  );
658
888
  }
889
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
890
+ return fetch(sessionUrl, {
891
+ method: "POST",
892
+ headers: { Authorization: `Bearer ${appSession}` }
893
+ });
894
+ }
895
+ const originalMethod = init?.method ?? "GET";
896
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
659
897
  return fetch(proxyUrl, {
660
898
  method: "POST",
661
899
  headers: {
@@ -1,48 +1,60 @@
1
+ var __getOwnPropNames = Object.getOwnPropertyNames;
2
+ var __esm = (fn, res) => function __init() {
3
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
4
+ };
5
+
1
6
  // ../connectors/src/parameter-definition.ts
2
- var ParameterDefinition = class {
3
- slug;
4
- name;
5
- description;
6
- envVarBaseKey;
7
- type;
8
- secret;
9
- required;
10
- constructor(config) {
11
- this.slug = config.slug;
12
- this.name = config.name;
13
- this.description = config.description;
14
- this.envVarBaseKey = config.envVarBaseKey;
15
- this.type = config.type;
16
- this.secret = config.secret;
17
- this.required = config.required;
18
- }
19
- /**
20
- * Get the parameter value from a ConnectorConnectionObject.
21
- */
22
- getValue(connection2) {
23
- const param = connection2.parameters.find(
24
- (p) => p.parameterSlug === this.slug
25
- );
26
- if (!param || param.value == null) {
27
- throw new Error(
28
- `Parameter "${this.slug}" not found or has no value in connection "${connection2.id}"`
29
- );
30
- }
31
- return param.value;
32
- }
33
- /**
34
- * Try to get the parameter value. Returns undefined if not found (for optional params).
35
- */
36
- tryGetValue(connection2) {
37
- const param = connection2.parameters.find(
38
- (p) => p.parameterSlug === this.slug
39
- );
40
- if (!param || param.value == null) return void 0;
41
- return param.value;
7
+ var ParameterDefinition;
8
+ var init_parameter_definition = __esm({
9
+ "../connectors/src/parameter-definition.ts"() {
10
+ "use strict";
11
+ ParameterDefinition = class {
12
+ slug;
13
+ name;
14
+ description;
15
+ envVarBaseKey;
16
+ type;
17
+ secret;
18
+ required;
19
+ constructor(config) {
20
+ this.slug = config.slug;
21
+ this.name = config.name;
22
+ this.description = config.description;
23
+ this.envVarBaseKey = config.envVarBaseKey;
24
+ this.type = config.type;
25
+ this.secret = config.secret;
26
+ this.required = config.required;
27
+ }
28
+ /**
29
+ * Get the parameter value from a ConnectorConnectionObject.
30
+ */
31
+ getValue(connection2) {
32
+ const param = connection2.parameters.find(
33
+ (p) => p.parameterSlug === this.slug
34
+ );
35
+ if (!param || param.value == null) {
36
+ throw new Error(
37
+ `Parameter "${this.slug}" not found or has no value in connection "${connection2.id}"`
38
+ );
39
+ }
40
+ return param.value;
41
+ }
42
+ /**
43
+ * Try to get the parameter value. Returns undefined if not found (for optional params).
44
+ */
45
+ tryGetValue(connection2) {
46
+ const param = connection2.parameters.find(
47
+ (p) => p.parameterSlug === this.slug
48
+ );
49
+ if (!param || param.value == null) return void 0;
50
+ return param.value;
51
+ }
52
+ };
42
53
  }
43
- };
54
+ });
44
55
 
45
56
  // ../connectors/src/connectors/openai/parameters.ts
57
+ init_parameter_definition();
46
58
  var parameters = {
47
59
  apiKey: new ParameterDefinition({
48
60
  slug: "api-key",
@@ -91,6 +103,20 @@ var ConnectorPlugin = class _ConnectorPlugin {
91
103
  * `runSetupFlow` from `setup-flow.ts`.
92
104
  */
93
105
  setup;
106
+ /**
107
+ * Opt-out of the default "verify before save" behavior on connection
108
+ * creation. The backend invokes `checkConnection` synchronously while
109
+ * creating the connection and aborts (no row inserted) if it fails — this
110
+ * flag disables that for connectors where the check cannot succeed pre-save:
111
+ *
112
+ * - `squadbase-db` populates `connection-url` only after Neon provisioning
113
+ * - OAuth connectors require an OAuth-aware proxyFetch keyed by the
114
+ * connectionId, which doesn't exist until the row is saved
115
+ *
116
+ * Exceptions are the explicit position; new credential-input connectors get
117
+ * the default verify-on-create behavior without opt-in.
118
+ */
119
+ skipConnectionCheckOnCreate;
94
120
  constructor(config) {
95
121
  this.slug = config.slug;
96
122
  this.authType = config.authType;
@@ -108,6 +134,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
108
134
  this.query = config.query;
109
135
  this.checkConnection = config.checkConnection;
110
136
  this.setup = config.setup;
137
+ this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
111
138
  }
112
139
  get connectorKey() {
113
140
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -241,7 +268,38 @@ export default async function handler(c: Context) {
241
268
  }
242
269
  \`\`\``
243
270
  },
244
- tools
271
+ tools,
272
+ async checkConnection(params, _config) {
273
+ try {
274
+ const apiKey = params[parameters.apiKey.slug];
275
+ if (!apiKey) {
276
+ return {
277
+ success: false,
278
+ error: "Missing required parameter: api-key"
279
+ };
280
+ }
281
+ const res = await fetch("https://api.openai.com/v1/models", {
282
+ method: "GET",
283
+ headers: {
284
+ Authorization: `Bearer ${apiKey}`,
285
+ Accept: "application/json"
286
+ }
287
+ });
288
+ if (!res.ok) {
289
+ const errorText = await res.text().catch(() => res.statusText);
290
+ return {
291
+ success: false,
292
+ error: `OpenAI API failed: HTTP ${res.status} ${errorText}`
293
+ };
294
+ }
295
+ return { success: true };
296
+ } catch (error) {
297
+ return {
298
+ success: false,
299
+ error: error instanceof Error ? error.message : String(error)
300
+ };
301
+ }
302
+ }
245
303
  });
246
304
 
247
305
  // src/connectors/create-connector-sdk.ts
@@ -270,6 +328,7 @@ function resolveEnvVarOptional(entry, key) {
270
328
  import { getContext } from "hono/context-storage";
271
329
  import { getCookie } from "hono/cookie";
272
330
  var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
331
+ var TABLEAU_SESSION_SENTINEL_URL = "squadbase://tableau-session/";
273
332
  function normalizeHeaders(input) {
274
333
  const out = {};
275
334
  if (!input) return out;
@@ -278,6 +337,11 @@ function normalizeHeaders(input) {
278
337
  });
279
338
  return out;
280
339
  }
340
+ function extractInputUrl(input) {
341
+ if (typeof input === "string") return input;
342
+ if (input instanceof URL) return input.href;
343
+ return input.url;
344
+ }
281
345
  function createSandboxProxyFetch(connectionId) {
282
346
  return async (input, init) => {
283
347
  const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
@@ -287,10 +351,17 @@ function createSandboxProxyFetch(connectionId) {
287
351
  "Connection proxy is not configured. Please check your deployment settings."
288
352
  );
289
353
  }
290
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
354
+ const originalUrl = extractInputUrl(input);
355
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
356
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
357
+ const sessionUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
358
+ return fetch(sessionUrl, {
359
+ method: "POST",
360
+ headers: { Authorization: `Bearer ${token}` }
361
+ });
362
+ }
291
363
  const originalMethod = init?.method ?? "GET";
292
364
  const originalBody = init?.body ? JSON.parse(init.body) : void 0;
293
- const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
294
365
  const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
295
366
  return fetch(proxyUrl, {
296
367
  method: "POST",
@@ -316,10 +387,9 @@ function createDeployedAppProxyFetch(connectionId) {
316
387
  }
317
388
  const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
318
389
  const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
390
+ const sessionUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/tableau-session`;
319
391
  return async (input, init) => {
320
- const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
321
- const originalMethod = init?.method ?? "GET";
322
- const originalBody = init?.body ? JSON.parse(init.body) : void 0;
392
+ const originalUrl = extractInputUrl(input);
323
393
  const c = getContext();
324
394
  const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
325
395
  if (!appSession) {
@@ -327,6 +397,14 @@ function createDeployedAppProxyFetch(connectionId) {
327
397
  "No authentication method available for connection proxy."
328
398
  );
329
399
  }
400
+ if (originalUrl === TABLEAU_SESSION_SENTINEL_URL) {
401
+ return fetch(sessionUrl, {
402
+ method: "POST",
403
+ headers: { Authorization: `Bearer ${appSession}` }
404
+ });
405
+ }
406
+ const originalMethod = init?.method ?? "GET";
407
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
330
408
  return fetch(proxyUrl, {
331
409
  method: "POST",
332
410
  headers: {