@squadbase/vite-server 0.1.17-dev.24af54e → 0.1.17-dev.3b633bb

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 (73) hide show
  1. package/dist/cli/index.js +1681 -449
  2. package/dist/connectors/airtable-oauth.js +28 -3
  3. package/dist/connectors/airtable.js +28 -3
  4. package/dist/connectors/amplitude.js +28 -3
  5. package/dist/connectors/asana.js +28 -3
  6. package/dist/connectors/attio.js +28 -3
  7. package/dist/connectors/aws-billing.js +28 -3
  8. package/dist/connectors/azure-sql.js +31 -6
  9. package/dist/connectors/backlog-api-key.js +28 -3
  10. package/dist/connectors/clickup.js +28 -3
  11. package/dist/connectors/cosmosdb.js +28 -3
  12. package/dist/connectors/customerio.js +29 -4
  13. package/dist/connectors/dbt.js +28 -3
  14. package/dist/connectors/freshdesk.js +28 -3
  15. package/dist/connectors/freshsales.js +28 -3
  16. package/dist/connectors/freshservice.js +28 -3
  17. package/dist/connectors/gamma.js +30 -5
  18. package/dist/connectors/github.js +28 -3
  19. package/dist/connectors/gmail-oauth.js +28 -3
  20. package/dist/connectors/gmail.js +28 -3
  21. package/dist/connectors/google-ads.js +28 -3
  22. package/dist/connectors/google-analytics-oauth.js +28 -3
  23. package/dist/connectors/google-analytics.js +227 -105
  24. package/dist/connectors/google-audit-log.js +28 -3
  25. package/dist/connectors/google-calendar-oauth.js +28 -3
  26. package/dist/connectors/google-calendar.js +28 -3
  27. package/dist/connectors/google-docs.js +28 -3
  28. package/dist/connectors/google-drive.js +28 -3
  29. package/dist/connectors/google-search-console-oauth.js +28 -3
  30. package/dist/connectors/google-sheets.js +28 -3
  31. package/dist/connectors/google-slides.js +28 -3
  32. package/dist/connectors/grafana.js +28 -3
  33. package/dist/connectors/hubspot-oauth.js +28 -3
  34. package/dist/connectors/hubspot.js +28 -3
  35. package/dist/connectors/influxdb.js +28 -3
  36. package/dist/connectors/intercom-oauth.js +28 -3
  37. package/dist/connectors/intercom.js +28 -3
  38. package/dist/connectors/jdbc.js +28 -3
  39. package/dist/connectors/jira-api-key.js +28 -3
  40. package/dist/connectors/kintone-api-token.js +28 -3
  41. package/dist/connectors/kintone.js +28 -3
  42. package/dist/connectors/linear.js +28 -3
  43. package/dist/connectors/linkedin-ads.js +28 -3
  44. package/dist/connectors/mailchimp-oauth.js +28 -3
  45. package/dist/connectors/mailchimp.js +28 -3
  46. package/dist/connectors/meta-ads-oauth.js +28 -3
  47. package/dist/connectors/meta-ads.js +28 -3
  48. package/dist/connectors/mixpanel.js +28 -3
  49. package/dist/connectors/monday.js +28 -3
  50. package/dist/connectors/mongodb.js +28 -3
  51. package/dist/connectors/notion-oauth.js +28 -3
  52. package/dist/connectors/notion.js +28 -3
  53. package/dist/connectors/oracle.js +54 -14
  54. package/dist/connectors/outlook-oauth.js +28 -3
  55. package/dist/connectors/powerbi-oauth.js +309 -37
  56. package/dist/connectors/salesforce.js +28 -3
  57. package/dist/connectors/semrush.js +366 -46
  58. package/dist/connectors/sentry.js +28 -3
  59. package/dist/connectors/shopify-oauth.js +28 -3
  60. package/dist/connectors/shopify.js +28 -3
  61. package/dist/connectors/sqlserver.js +31 -6
  62. package/dist/connectors/stripe-api-key.js +28 -3
  63. package/dist/connectors/stripe-oauth.js +28 -3
  64. package/dist/connectors/supabase.js +31 -6
  65. package/dist/connectors/tableau.js +246 -78
  66. package/dist/connectors/tiktok-ads.js +28 -3
  67. package/dist/connectors/wix-store.js +28 -3
  68. package/dist/connectors/zendesk-oauth.js +28 -3
  69. package/dist/connectors/zendesk.js +28 -3
  70. package/dist/index.js +1681 -449
  71. package/dist/main.js +1681 -449
  72. package/dist/vite-plugin.js +1681 -449
  73. package/package.json +1 -1
@@ -361,19 +361,34 @@ async function runSetupFlow(flow, params, ctx, config) {
361
361
  };
362
362
  let state = flow.initialState();
363
363
  let answerIdx = 0;
364
+ const pendingParameterUpdates = [];
364
365
  for (const step of flow.steps) {
365
366
  const ans = ctx.answers[answerIdx];
366
367
  if (ans && ans.questionSlug === step.slug) {
367
368
  state = step.applyAnswer(state, ans.answer);
369
+ if (step.toParameterUpdates) {
370
+ pendingParameterUpdates.push(...step.toParameterUpdates(state));
371
+ }
368
372
  answerIdx += 1;
369
373
  continue;
370
374
  }
375
+ const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
371
376
  if (step.type === "text") {
377
+ if (step.fetchOptions) {
378
+ const options2 = await step.fetchOptions(state, runtime);
379
+ if (options2.length === 0) {
380
+ continue;
381
+ }
382
+ }
372
383
  return {
373
384
  type: "nextQuestion",
374
385
  questionSlug: step.slug,
375
386
  question: step.question[ctx.language],
376
- questionType: "text"
387
+ questionType: "text",
388
+ allowFreeText: resolvedAllowFreeText,
389
+ ...pendingParameterUpdates.length > 0 && {
390
+ parameterUpdates: pendingParameterUpdates
391
+ }
377
392
  };
378
393
  }
379
394
  const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
@@ -385,11 +400,21 @@ async function runSetupFlow(flow, params, ctx, config) {
385
400
  questionSlug: step.slug,
386
401
  question: step.question[ctx.language],
387
402
  questionType: step.type,
388
- options
403
+ options,
404
+ allowFreeText: resolvedAllowFreeText,
405
+ ...pendingParameterUpdates.length > 0 && {
406
+ parameterUpdates: pendingParameterUpdates
407
+ }
389
408
  };
390
409
  }
391
410
  const dataInvestigationResult = await flow.finalize(state, runtime);
392
- return { type: "fulfilled", dataInvestigationResult };
411
+ return {
412
+ type: "fulfilled",
413
+ dataInvestigationResult,
414
+ ...pendingParameterUpdates.length > 0 && {
415
+ parameterUpdates: pendingParameterUpdates
416
+ }
417
+ };
393
418
  }
394
419
  async function resolveSetupSelection(params) {
395
420
  const { selected, allSentinel, fetchAll, limit } = params;
@@ -593,7 +618,8 @@ var semrushOnboarding = new ConnectorOnboarding({
593
618
  });
594
619
 
595
620
  // ../connectors/src/connectors/semrush/utils.ts
596
- var PROJECTS_BASE_URL = "https://api.semrush.com/management/v1";
621
+ var BASE_URL3 = "https://api.semrush.com";
622
+ var PROJECTS_BASE_URL = `${BASE_URL3}/management/v1`;
597
623
  function projectsApiFetch(params, path2, init) {
598
624
  const apiKey = params[parameters.apiKey.slug];
599
625
  if (!apiKey) {
@@ -610,10 +636,103 @@ function projectsApiFetch(params, path2, init) {
610
636
  if (!headers.has("Accept")) headers.set("Accept", "application/json");
611
637
  return fetch(url.toString(), { ...init, headers });
612
638
  }
639
+ async function reportFetch(params, query) {
640
+ const apiKey = params[parameters.apiKey.slug];
641
+ if (!apiKey) {
642
+ throw new Error(
643
+ `semrush: missing required parameter: ${parameters.apiKey.slug}`
644
+ );
645
+ }
646
+ const url = new URL(`${BASE_URL3}/`);
647
+ for (const [k, v] of Object.entries(query)) {
648
+ url.searchParams.set(k, v);
649
+ }
650
+ url.searchParams.set("key", apiKey);
651
+ const res = await fetch(url.toString());
652
+ const text = await res.text();
653
+ if (text.startsWith("ERROR ")) throw new Error(text.trim());
654
+ return parseSemicolonCsv(text);
655
+ }
656
+ async function backlinksFetch(params, query) {
657
+ const apiKey = params[parameters.apiKey.slug];
658
+ if (!apiKey) {
659
+ throw new Error(
660
+ `semrush: missing required parameter: ${parameters.apiKey.slug}`
661
+ );
662
+ }
663
+ const url = new URL(`${BASE_URL3}/analytics/v1/`);
664
+ for (const [k, v] of Object.entries(query)) {
665
+ url.searchParams.set(k, v);
666
+ }
667
+ url.searchParams.set("key", apiKey);
668
+ const res = await fetch(url.toString());
669
+ const text = await res.text();
670
+ if (text.startsWith("ERROR ")) throw new Error(text.trim());
671
+ return parseSemicolonCsv(text);
672
+ }
673
+ function parseSemicolonCsv(raw) {
674
+ const lines = raw.trim().split("\n").filter(Boolean);
675
+ if (lines.length === 0) return { columns: [], rows: [] };
676
+ const columns = lines[0].split(";");
677
+ const rows = lines.slice(1).map((line) => {
678
+ const values = line.split(";");
679
+ const row = {};
680
+ for (let i = 0; i < columns.length; i++) {
681
+ row[columns[i]] = values[i] ?? "";
682
+ }
683
+ return row;
684
+ });
685
+ return { columns, rows };
686
+ }
613
687
 
614
688
  // ../connectors/src/connectors/semrush/setup-flow.ts
615
689
  var ALL_PROJECTS = "__ALL_PROJECTS__";
616
690
  var SEMRUSH_SETUP_MAX_PROJECTS = 10;
691
+ var SEMRUSH_DATABASES = [
692
+ { value: "us", label: "United States" },
693
+ { value: "uk", label: "United Kingdom" },
694
+ { value: "ca", label: "Canada" },
695
+ { value: "au", label: "Australia" },
696
+ { value: "de", label: "Germany" },
697
+ { value: "fr", label: "France" },
698
+ { value: "es", label: "Spain" },
699
+ { value: "it", label: "Italy" },
700
+ { value: "br", label: "Brazil" },
701
+ { value: "jp", label: "Japan" },
702
+ { value: "in", label: "India" },
703
+ { value: "ru", label: "Russia" },
704
+ { value: "nl", label: "Netherlands" },
705
+ { value: "se", label: "Sweden" },
706
+ { value: "mx", label: "Mexico" },
707
+ { value: "kr", label: "South Korea" },
708
+ { value: "sg", label: "Singapore" },
709
+ { value: "hk", label: "Hong Kong" },
710
+ { value: "tw", label: "Taiwan" }
711
+ ];
712
+ var REPORT_TYPE_LABELS = {
713
+ domain_overview: {
714
+ en: "Domain Overview (rank, traffic, keyword count)",
715
+ ja: "Domain Overview (\u30E9\u30F3\u30AF\u30FB\u30C8\u30E9\u30D5\u30A3\u30C3\u30AF\u30FB\u30AD\u30FC\u30EF\u30FC\u30C9\u6570)"
716
+ },
717
+ organic_search: {
718
+ en: "Organic Search (top organic keywords)",
719
+ ja: "Organic Search (\u4E0A\u4F4D\u30AA\u30FC\u30AC\u30CB\u30C3\u30AF\u30AD\u30FC\u30EF\u30FC\u30C9)"
720
+ },
721
+ paid_search: {
722
+ en: "Paid Search (top paid keywords)",
723
+ ja: "Paid Search (\u4E0A\u4F4D\u6709\u6599\u30AD\u30FC\u30EF\u30FC\u30C9)"
724
+ },
725
+ backlinks: {
726
+ en: "Backlinks (referring domains, backlink count)",
727
+ ja: "Backlinks (\u53C2\u7167\u30C9\u30E1\u30A4\u30F3\u30FB\u88AB\u30EA\u30F3\u30AF\u6570)"
728
+ }
729
+ };
730
+ var REPORT_TYPE_VALUES = [
731
+ "domain_overview",
732
+ "organic_search",
733
+ "paid_search",
734
+ "backlinks"
735
+ ];
617
736
  function projectId(p) {
618
737
  const raw = p.project_id ?? p.id;
619
738
  return raw == null ? "" : String(raw);
@@ -622,7 +741,7 @@ function projectName(p) {
622
741
  return p.project_name ?? p.name ?? p.domain ?? p.url ?? projectId(p);
623
742
  }
624
743
  function projectDomain(p) {
625
- return p.domain ?? p.url ?? "";
744
+ return p.domain ?? p.domain_unicode ?? p.url ?? "";
626
745
  }
627
746
  function projectCreatedAt(p) {
628
747
  return p.created_at ?? p.date_created ?? "";
@@ -630,13 +749,19 @@ function projectCreatedAt(p) {
630
749
  async function fetchProjects(params) {
631
750
  let res;
632
751
  try {
633
- res = await projectsApiFetch(params, "/projects/");
752
+ res = await projectsApiFetch(params, "/projects");
634
753
  } catch (err) {
635
- return { ok: false, error: err instanceof Error ? err.message : String(err) };
754
+ return {
755
+ ok: false,
756
+ error: err instanceof Error ? err.message : String(err)
757
+ };
636
758
  }
637
759
  if (!res.ok) {
638
760
  const body2 = await res.text().catch(() => res.statusText);
639
- return { ok: false, error: `HTTP ${res.status} ${body2 || res.statusText}` };
761
+ return {
762
+ ok: false,
763
+ error: `HTTP ${res.status} ${body2 || res.statusText}`
764
+ };
640
765
  }
641
766
  let body;
642
767
  try {
@@ -650,9 +775,171 @@ async function fetchProjects(params) {
650
775
  const projects = Array.isArray(body) ? body : Array.isArray(body?.projects) ? body.projects : Array.isArray(body?.data) ? body.data : [];
651
776
  return { ok: true, projects };
652
777
  }
778
+ function formatNumber(n) {
779
+ return n.toLocaleString("en-US");
780
+ }
781
+ async function fetchDomainOverview(params, domain, database) {
782
+ const sections = [];
783
+ try {
784
+ const report = await reportFetch(params, {
785
+ type: "domain_ranks",
786
+ domain,
787
+ database
788
+ });
789
+ if (report.rows.length === 0) {
790
+ sections.push("_No data found for this domain._", "");
791
+ return sections;
792
+ }
793
+ const row = report.rows[0];
794
+ sections.push("| Metric | Value |");
795
+ sections.push("|--------|-------|");
796
+ sections.push(
797
+ `| Rank | ${row["Rank"] ?? "-"} |`,
798
+ `| Organic Keywords | ${formatNumber(Number(row["Organic Keywords"]) || 0)} |`,
799
+ `| Organic Traffic | ${formatNumber(Number(row["Organic Traffic"]) || 0)} |`,
800
+ `| Organic Cost | $${formatNumber(Number(row["Organic Cost"]) || 0)} |`,
801
+ `| Adwords Keywords | ${formatNumber(Number(row["Adwords Keywords"]) || 0)} |`,
802
+ `| Adwords Traffic | ${formatNumber(Number(row["Adwords Traffic"]) || 0)} |`,
803
+ `| Adwords Cost | $${formatNumber(Number(row["Adwords Cost"]) || 0)} |`
804
+ );
805
+ sections.push("");
806
+ } catch (err) {
807
+ sections.push(
808
+ `_Error: ${err instanceof Error ? err.message : String(err)}_`,
809
+ ""
810
+ );
811
+ }
812
+ return sections;
813
+ }
814
+ async function fetchOrganicSearch(params, domain, database) {
815
+ return fetchKeywordReport(params, "domain_organic", domain, database);
816
+ }
817
+ async function fetchPaidSearch(params, domain, database) {
818
+ return fetchKeywordReport(params, "domain_adwords", domain, database);
819
+ }
820
+ async function fetchKeywordReport(params, type, domain, database) {
821
+ const sections = [];
822
+ try {
823
+ const report = await reportFetch(params, {
824
+ type,
825
+ domain,
826
+ database,
827
+ display_limit: "5"
828
+ });
829
+ if (report.rows.length === 0) {
830
+ sections.push("_No data found._", "");
831
+ return sections;
832
+ }
833
+ sections.push(...renderCsvTable(report, 5));
834
+ sections.push("");
835
+ } catch (err) {
836
+ sections.push(
837
+ `_Error: ${err instanceof Error ? err.message : String(err)}_`,
838
+ ""
839
+ );
840
+ }
841
+ return sections;
842
+ }
843
+ async function fetchBacklinks(params, domain) {
844
+ const sections = [];
845
+ try {
846
+ const report = await backlinksFetch(params, {
847
+ type: "backlinks_overview",
848
+ target: domain,
849
+ target_type: "root_domain"
850
+ });
851
+ if (report.rows.length === 0) {
852
+ sections.push("_No backlink data found._", "");
853
+ return sections;
854
+ }
855
+ const row = report.rows[0];
856
+ sections.push("| Metric | Value |");
857
+ sections.push("|--------|-------|");
858
+ for (const col of report.columns) {
859
+ sections.push(`| ${col} | ${formatNumber(Number(row[col]) || 0)} |`);
860
+ }
861
+ sections.push("");
862
+ } catch (err) {
863
+ sections.push(
864
+ `_Error: ${err instanceof Error ? err.message : String(err)}_`,
865
+ ""
866
+ );
867
+ }
868
+ return sections;
869
+ }
870
+ function renderCsvTable(report, maxRows) {
871
+ const cols = report.columns;
872
+ const rows = report.rows.slice(0, maxRows);
873
+ const lines = [];
874
+ lines.push(`| ${cols.join(" | ")} |`);
875
+ lines.push(`|${cols.map(() => "---").join("|")}|`);
876
+ for (const row of rows) {
877
+ const cells = cols.map((c) => (row[c] ?? "").replace(/\|/g, "\\|"));
878
+ lines.push(`| ${cells.join(" | ")} |`);
879
+ }
880
+ return lines;
881
+ }
653
882
  var semrushSetupFlow = {
654
883
  initialState: () => ({}),
655
884
  steps: [
885
+ {
886
+ slug: "domain",
887
+ type: "select",
888
+ allowFreeText: true,
889
+ question: {
890
+ ja: "\u5206\u6790\u5BFE\u8C61\u306E\u30C9\u30E1\u30A4\u30F3\u3092\u9078\u629E\u307E\u305F\u306F\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
891
+ en: "Select or enter the domain to analyze"
892
+ },
893
+ async fetchOptions(_state, rt) {
894
+ const result = await fetchProjects(rt.params);
895
+ if (!result.ok || result.projects.length === 0) return [];
896
+ const seen = /* @__PURE__ */ new Set();
897
+ const options = [];
898
+ for (const p of result.projects) {
899
+ const d = projectDomain(p);
900
+ if (d && !seen.has(d)) {
901
+ seen.add(d);
902
+ options.push({
903
+ value: d,
904
+ label: `${d} (${projectName(p)})`
905
+ });
906
+ }
907
+ }
908
+ return options;
909
+ },
910
+ applyAnswer: (state, answer) => ({ ...state, domain: answer[0] })
911
+ },
912
+ {
913
+ slug: "database",
914
+ type: "select",
915
+ allowFreeText: false,
916
+ question: {
917
+ ja: "\u30EA\u30FC\u30B8\u30E7\u30F3\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u5BFE\u8C61\u30C9\u30E1\u30A4\u30F3\u306E\u4E3B\u8981\u5E02\u5834\uFF09",
918
+ en: "Select the region (primary market for the target domain)"
919
+ },
920
+ async fetchOptions() {
921
+ return SEMRUSH_DATABASES.map((db) => ({
922
+ value: db.value,
923
+ label: `${db.label} (${db.value})`
924
+ }));
925
+ },
926
+ applyAnswer: (state, answer) => ({ ...state, database: answer[0] })
927
+ },
928
+ {
929
+ slug: "reportTypes",
930
+ type: "multiSelect",
931
+ question: {
932
+ ja: "\u63A2\u7D22\u3059\u308B\u30EC\u30DD\u30FC\u30C8\u7A2E\u5225\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
933
+ en: "Select report types to explore (multi-select allowed)"
934
+ },
935
+ async fetchOptions(_state, rt) {
936
+ return REPORT_TYPE_VALUES.map((value) => ({
937
+ value,
938
+ label: REPORT_TYPE_LABELS[value][rt.language]
939
+ }));
940
+ },
941
+ applyAnswer: (state, answer) => ({ ...state, reportTypes: answer })
942
+ },
656
943
  {
657
944
  slug: "projects",
658
945
  type: "multiSelect",
@@ -669,7 +956,9 @@ var semrushSetupFlow = {
669
956
  const id = projectId(p);
670
957
  if (!id) return null;
671
958
  return { value: id, label: projectName(p) };
672
- }).filter((opt) => opt !== null);
959
+ }).filter(
960
+ (opt) => opt !== null
961
+ );
673
962
  if (options.length === 0) return [];
674
963
  return [
675
964
  {
@@ -683,49 +972,80 @@ var semrushSetupFlow = {
683
972
  }
684
973
  ],
685
974
  async finalize(state, rt) {
686
- const sections = ["## Semrush", ""];
687
- if (!state.projects?.length) {
975
+ if (!state.domain || !state.database || !state.reportTypes) {
976
+ throw new Error("Semrush setup: incomplete state on finalize");
977
+ }
978
+ const domain = state.domain;
979
+ const database = state.database;
980
+ const selected = state.reportTypes.filter(
981
+ (r) => REPORT_TYPE_VALUES.includes(r)
982
+ );
983
+ const sections = [
984
+ "## Semrush",
985
+ "",
986
+ `**Domain:** ${domain}`,
987
+ `**Region:** ${database}`,
988
+ ""
989
+ ];
990
+ for (const reportType of selected) {
688
991
  sections.push(
689
- "_No Semrush Projects API access detected; Standard Analytics reports run by domain/keyword and don't require pre-selection._",
992
+ `### ${REPORT_TYPE_LABELS[reportType].en}`,
690
993
  ""
691
994
  );
692
- return sections.join("\n");
693
- }
694
- const result = await fetchProjects(rt.params);
695
- if (!result.ok) {
696
- throw new Error(
697
- `semrush: listProjects failed on finalize: ${result.error}`
698
- );
699
- }
700
- const projectByIdMap = /* @__PURE__ */ new Map();
701
- for (const p of result.projects) {
702
- const id = projectId(p);
703
- if (id) projectByIdMap.set(id, p);
704
- }
705
- const targetIds = await resolveSetupSelection({
706
- selected: state.projects,
707
- allSentinel: ALL_PROJECTS,
708
- fetchAll: async () => result.projects.map((p) => projectId(p)).filter((id) => id),
709
- limit: SEMRUSH_SETUP_MAX_PROJECTS
710
- });
711
- if (!targetIds.length) {
712
- sections.push("_No projects selected._", "");
713
- return sections.join("\n");
995
+ switch (reportType) {
996
+ case "domain_overview":
997
+ sections.push(
998
+ ...await fetchDomainOverview(rt.params, domain, database)
999
+ );
1000
+ break;
1001
+ case "organic_search":
1002
+ sections.push(
1003
+ ...await fetchOrganicSearch(rt.params, domain, database)
1004
+ );
1005
+ break;
1006
+ case "paid_search":
1007
+ sections.push(
1008
+ ...await fetchPaidSearch(rt.params, domain, database)
1009
+ );
1010
+ break;
1011
+ case "backlinks":
1012
+ sections.push(...await fetchBacklinks(rt.params, domain));
1013
+ break;
1014
+ }
714
1015
  }
715
- sections.push("| Project | Domain | Created |");
716
- sections.push("|---------|--------|---------|");
717
- for (const id of targetIds) {
718
- const p = projectByIdMap.get(id);
719
- if (!p) {
720
- sections.push(`| ${id} | - | - |`);
721
- continue;
1016
+ if (state.projects?.length) {
1017
+ const result = await fetchProjects(rt.params);
1018
+ if (result.ok) {
1019
+ const projectByIdMap = /* @__PURE__ */ new Map();
1020
+ for (const p of result.projects) {
1021
+ const id = projectId(p);
1022
+ if (id) projectByIdMap.set(id, p);
1023
+ }
1024
+ const targetIds = await resolveSetupSelection({
1025
+ selected: state.projects,
1026
+ allSentinel: ALL_PROJECTS,
1027
+ fetchAll: async () => result.projects.map((p) => projectId(p)).filter((id) => id),
1028
+ limit: SEMRUSH_SETUP_MAX_PROJECTS
1029
+ });
1030
+ if (targetIds.length > 0) {
1031
+ sections.push("### Projects", "");
1032
+ sections.push("| Project | Domain | Created |");
1033
+ sections.push("|---------|--------|---------|");
1034
+ for (const id of targetIds) {
1035
+ const p = projectByIdMap.get(id);
1036
+ if (!p) {
1037
+ sections.push(`| ${id} | - | - |`);
1038
+ continue;
1039
+ }
1040
+ const name = projectName(p).replace(/\|/g, "\\|");
1041
+ const dom = projectDomain(p).replace(/\|/g, "\\|") || "-";
1042
+ const created = projectCreatedAt(p) || "-";
1043
+ sections.push(`| ${name} | ${dom} | ${created} |`);
1044
+ }
1045
+ sections.push("");
1046
+ }
722
1047
  }
723
- const name = projectName(p).replace(/\|/g, "\\|");
724
- const domain = projectDomain(p).replace(/\|/g, "\\|") || "-";
725
- const created = projectCreatedAt(p) || "-";
726
- sections.push(`| ${name} | ${domain} | ${created} |`);
727
1048
  }
728
- sections.push("");
729
1049
  return sections.join("\n");
730
1050
  }
731
1051
  };
@@ -352,19 +352,34 @@ async function runSetupFlow(flow, params, ctx, config) {
352
352
  };
353
353
  let state = flow.initialState();
354
354
  let answerIdx = 0;
355
+ const pendingParameterUpdates = [];
355
356
  for (const step of flow.steps) {
356
357
  const ans = ctx.answers[answerIdx];
357
358
  if (ans && ans.questionSlug === step.slug) {
358
359
  state = step.applyAnswer(state, ans.answer);
360
+ if (step.toParameterUpdates) {
361
+ pendingParameterUpdates.push(...step.toParameterUpdates(state));
362
+ }
359
363
  answerIdx += 1;
360
364
  continue;
361
365
  }
366
+ const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
362
367
  if (step.type === "text") {
368
+ if (step.fetchOptions) {
369
+ const options2 = await step.fetchOptions(state, runtime);
370
+ if (options2.length === 0) {
371
+ continue;
372
+ }
373
+ }
363
374
  return {
364
375
  type: "nextQuestion",
365
376
  questionSlug: step.slug,
366
377
  question: step.question[ctx.language],
367
- questionType: "text"
378
+ questionType: "text",
379
+ allowFreeText: resolvedAllowFreeText,
380
+ ...pendingParameterUpdates.length > 0 && {
381
+ parameterUpdates: pendingParameterUpdates
382
+ }
368
383
  };
369
384
  }
370
385
  const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
@@ -376,11 +391,21 @@ async function runSetupFlow(flow, params, ctx, config) {
376
391
  questionSlug: step.slug,
377
392
  question: step.question[ctx.language],
378
393
  questionType: step.type,
379
- options
394
+ options,
395
+ allowFreeText: resolvedAllowFreeText,
396
+ ...pendingParameterUpdates.length > 0 && {
397
+ parameterUpdates: pendingParameterUpdates
398
+ }
380
399
  };
381
400
  }
382
401
  const dataInvestigationResult = await flow.finalize(state, runtime);
383
- return { type: "fulfilled", dataInvestigationResult };
402
+ return {
403
+ type: "fulfilled",
404
+ dataInvestigationResult,
405
+ ...pendingParameterUpdates.length > 0 && {
406
+ parameterUpdates: pendingParameterUpdates
407
+ }
408
+ };
384
409
  }
385
410
  async function resolveSetupSelection(params) {
386
411
  const { selected, allSentinel, fetchAll, limit } = params;
@@ -178,19 +178,34 @@ async function runSetupFlow(flow, params, ctx, config) {
178
178
  };
179
179
  let state = flow.initialState();
180
180
  let answerIdx = 0;
181
+ const pendingParameterUpdates = [];
181
182
  for (const step of flow.steps) {
182
183
  const ans = ctx.answers[answerIdx];
183
184
  if (ans && ans.questionSlug === step.slug) {
184
185
  state = step.applyAnswer(state, ans.answer);
186
+ if (step.toParameterUpdates) {
187
+ pendingParameterUpdates.push(...step.toParameterUpdates(state));
188
+ }
185
189
  answerIdx += 1;
186
190
  continue;
187
191
  }
192
+ const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
188
193
  if (step.type === "text") {
194
+ if (step.fetchOptions) {
195
+ const options2 = await step.fetchOptions(state, runtime);
196
+ if (options2.length === 0) {
197
+ continue;
198
+ }
199
+ }
189
200
  return {
190
201
  type: "nextQuestion",
191
202
  questionSlug: step.slug,
192
203
  question: step.question[ctx.language],
193
- questionType: "text"
204
+ questionType: "text",
205
+ allowFreeText: resolvedAllowFreeText,
206
+ ...pendingParameterUpdates.length > 0 && {
207
+ parameterUpdates: pendingParameterUpdates
208
+ }
194
209
  };
195
210
  }
196
211
  const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
@@ -202,11 +217,21 @@ async function runSetupFlow(flow, params, ctx, config) {
202
217
  questionSlug: step.slug,
203
218
  question: step.question[ctx.language],
204
219
  questionType: step.type,
205
- options
220
+ options,
221
+ allowFreeText: resolvedAllowFreeText,
222
+ ...pendingParameterUpdates.length > 0 && {
223
+ parameterUpdates: pendingParameterUpdates
224
+ }
206
225
  };
207
226
  }
208
227
  const dataInvestigationResult = await flow.finalize(state, runtime);
209
- return { type: "fulfilled", dataInvestigationResult };
228
+ return {
229
+ type: "fulfilled",
230
+ dataInvestigationResult,
231
+ ...pendingParameterUpdates.length > 0 && {
232
+ parameterUpdates: pendingParameterUpdates
233
+ }
234
+ };
210
235
  }
211
236
 
212
237
  // ../connectors/src/auth-types.ts
@@ -465,19 +465,34 @@ async function runSetupFlow(flow, params, ctx, config) {
465
465
  };
466
466
  let state = flow.initialState();
467
467
  let answerIdx = 0;
468
+ const pendingParameterUpdates = [];
468
469
  for (const step of flow.steps) {
469
470
  const ans = ctx.answers[answerIdx];
470
471
  if (ans && ans.questionSlug === step.slug) {
471
472
  state = step.applyAnswer(state, ans.answer);
473
+ if (step.toParameterUpdates) {
474
+ pendingParameterUpdates.push(...step.toParameterUpdates(state));
475
+ }
472
476
  answerIdx += 1;
473
477
  continue;
474
478
  }
479
+ const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
475
480
  if (step.type === "text") {
481
+ if (step.fetchOptions) {
482
+ const options2 = await step.fetchOptions(state, runtime);
483
+ if (options2.length === 0) {
484
+ continue;
485
+ }
486
+ }
476
487
  return {
477
488
  type: "nextQuestion",
478
489
  questionSlug: step.slug,
479
490
  question: step.question[ctx.language],
480
- questionType: "text"
491
+ questionType: "text",
492
+ allowFreeText: resolvedAllowFreeText,
493
+ ...pendingParameterUpdates.length > 0 && {
494
+ parameterUpdates: pendingParameterUpdates
495
+ }
481
496
  };
482
497
  }
483
498
  const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
@@ -489,11 +504,21 @@ async function runSetupFlow(flow, params, ctx, config) {
489
504
  questionSlug: step.slug,
490
505
  question: step.question[ctx.language],
491
506
  questionType: step.type,
492
- options
507
+ options,
508
+ allowFreeText: resolvedAllowFreeText,
509
+ ...pendingParameterUpdates.length > 0 && {
510
+ parameterUpdates: pendingParameterUpdates
511
+ }
493
512
  };
494
513
  }
495
514
  const dataInvestigationResult = await flow.finalize(state, runtime);
496
- return { type: "fulfilled", dataInvestigationResult };
515
+ return {
516
+ type: "fulfilled",
517
+ dataInvestigationResult,
518
+ ...pendingParameterUpdates.length > 0 && {
519
+ parameterUpdates: pendingParameterUpdates
520
+ }
521
+ };
497
522
  }
498
523
 
499
524
  // ../connectors/src/auth-types.ts