@trops/dash-core 0.1.53 → 0.1.55

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/index.js CHANGED
@@ -9546,18 +9546,29 @@ function headerTemplateToRows(headerTemplate, nextRowId) {
9546
9546
  }
9547
9547
 
9548
9548
  /**
9549
- * Serialize the current form state into a standard MCP JSON config string.
9549
+ * Serialize the current form state into a bare MCP JSON config string.
9550
9550
  *
9551
- * Output format:
9551
+ * Output format (stdio):
9552
9552
  * {
9553
- * "mcpServers": {
9554
- * "<name>": { "command": ..., "args": [...], "env": {...} }
9555
- * }
9553
+ * "type": "stdio",
9554
+ * "command": "npx",
9555
+ * "args": ["-y", "package-name"],
9556
+ * "env": { "API_KEY": "${API_KEY}" }
9557
+ * }
9558
+ *
9559
+ * Output format (HTTP):
9560
+ * {
9561
+ * "type": "streamable_http",
9562
+ * "url": "https://example.com/mcp",
9563
+ * "headerTemplate": { "Authorization": "Bearer {{apiKey}}" }
9556
9564
  * }
9557
9565
  *
9558
- * @param {string} name - The provider name
9566
+ * Credential values are NOT embedded env values use ${FIELD_NAME} syntax
9567
+ * to reference credential fields entered separately in the form.
9568
+ *
9569
+ * @param {string} name - The provider name (unused in output, kept for API compat)
9559
9570
  * @param {string} transport - "stdio" or "streamable_http"
9560
- * @param {object} fields - { command, args, envMappingRows, url, headerRows, credentialData }
9571
+ * @param {object} fields - { command, args, envMappingRows, url, headerRows }
9561
9572
  * @returns {string} Formatted JSON string
9562
9573
  */
9563
9574
  function formStateToMcpJson(name, transport, fields) {
@@ -9570,9 +9581,7 @@ function formStateToMcpJson(name, transport, fields) {
9570
9581
  _fields$url = fields.url,
9571
9582
  url = _fields$url === void 0 ? "" : _fields$url,
9572
9583
  _fields$headerRows = fields.headerRows,
9573
- headerRows = _fields$headerRows === void 0 ? [] : _fields$headerRows,
9574
- _fields$credentialDat = fields.credentialData,
9575
- credentialData = _fields$credentialDat === void 0 ? {} : _fields$credentialDat;
9584
+ headerRows = _fields$headerRows === void 0 ? [] : _fields$headerRows;
9576
9585
  var serverConfig;
9577
9586
  if (transport === "stdio") {
9578
9587
  var argsArray = args.trim().split(/\s+/).filter(Boolean);
@@ -9580,11 +9589,12 @@ function formStateToMcpJson(name, transport, fields) {
9580
9589
  envMappingRows.forEach(function (row) {
9581
9590
  var envVar = row.envVar.trim();
9582
9591
  var credField = row.credField.trim();
9583
- if (envVar) {
9584
- env[envVar] = credentialData[credField] || "";
9592
+ if (envVar && credField) {
9593
+ env[envVar] = "${".concat(credField, "}");
9585
9594
  }
9586
9595
  });
9587
9596
  serverConfig = {
9597
+ type: "stdio",
9588
9598
  command: command.trim()
9589
9599
  };
9590
9600
  if (argsArray.length > 0) serverConfig.args = argsArray;
@@ -9592,29 +9602,36 @@ function formStateToMcpJson(name, transport, fields) {
9592
9602
  } else {
9593
9603
  // streamable_http
9594
9604
  serverConfig = {
9605
+ type: "streamable_http",
9595
9606
  url: url.trim()
9596
9607
  };
9597
- var headers = {};
9608
+ var headerTemplate = {};
9598
9609
  headerRows.forEach(function (row) {
9599
9610
  var hName = row.headerName.trim();
9600
9611
  var hValue = row.headerValue.trim();
9601
9612
  if (hName && hValue) {
9602
- headers[hName] = hValue;
9613
+ headerTemplate[hName] = hValue;
9603
9614
  }
9604
9615
  });
9605
- if (Object.keys(headers).length > 0) serverConfig.headers = headers;
9616
+ if (Object.keys(headerTemplate).length > 0) serverConfig.headerTemplate = headerTemplate;
9606
9617
  }
9607
- return JSON.stringify({
9608
- mcpServers: _defineProperty({}, name || "server-name", serverConfig)
9609
- }, null, 2);
9618
+ return JSON.stringify(serverConfig, null, 2);
9610
9619
  }
9611
9620
 
9612
9621
  /**
9613
- * Parse a standard MCP JSON config string back into form state.
9622
+ * Parse an MCP JSON config string back into form state.
9614
9623
  *
9615
- * Accepts:
9616
- * - { "mcpServers": { "name": { ... } } }
9617
- * - Bare server config: { "command": ..., "args": [...] }
9624
+ * Accepts multiple input formats:
9625
+ * - Bare config: { "command": ..., "args": [...], "env": { "KEY": "${FIELD}" } }
9626
+ * - Wrapped: { "mcpServers": { "name": { ... } } } — unwraps and uses key as providerName
9627
+ *
9628
+ * Transport detection:
9629
+ * - Explicit `type` or `transport` field
9630
+ * - Inferred: `url` present → streamable_http, `command` present → stdio
9631
+ *
9632
+ * stdio env value parsing:
9633
+ * - "${FIELD_NAME}" → envVar = key, credField = FIELD_NAME (reference syntax)
9634
+ * - "literal-value" → envVar = key, credField = key, credentialData[key] = value
9618
9635
  *
9619
9636
  * @param {string} jsonString - The JSON to parse
9620
9637
  * @param {Function} nextRowId - Function that returns a unique row ID
@@ -9641,15 +9658,22 @@ function mcpJsonToFormState(jsonString, nextRowId) {
9641
9658
  var _entries$ = _slicedToArray(entries[0], 2);
9642
9659
  providerName = _entries$[0];
9643
9660
  serverConfig = _entries$[1];
9644
- } else if (parsed.command || parsed.url) {
9661
+ } else if (parsed.command || parsed.url || parsed.type || parsed.transport) {
9645
9662
  serverConfig = parsed;
9646
9663
  } else {
9647
9664
  return {
9648
- error: "Unrecognized format: expected mcpServers object or bare server config"
9665
+ error: "Unrecognized format: expected a server config with command, url, or type"
9649
9666
  };
9650
9667
  }
9651
- var isHttp = !!serverConfig.url;
9652
- var transport = isHttp ? "streamable_http" : "stdio";
9668
+
9669
+ // Determine transport from type/transport field or infer from contents
9670
+ var explicitType = serverConfig.type || serverConfig.transport;
9671
+ var transport;
9672
+ if (explicitType) {
9673
+ transport = explicitType === "stdio" ? "stdio" : "streamable_http";
9674
+ } else {
9675
+ transport = serverConfig.url ? "streamable_http" : "stdio";
9676
+ }
9653
9677
  var result = {
9654
9678
  providerName: providerName,
9655
9679
  transport: transport,
@@ -9669,12 +9693,24 @@ function mcpJsonToFormState(jsonString, nextRowId) {
9669
9693
  var _ref6 = _slicedToArray(_ref5, 2),
9670
9694
  envVar = _ref6[0],
9671
9695
  value = _ref6[1];
9672
- result.envMappingRows.push({
9673
- id: nextRowId(),
9674
- envVar: envVar,
9675
- credField: envVar
9676
- });
9677
- result.credentialData[envVar] = value || "";
9696
+ // Check for ${FIELD_NAME} reference syntax
9697
+ var refMatch = typeof value === "string" && value.match(/^\$\{(.+)\}$/);
9698
+ if (refMatch) {
9699
+ // Reference syntax — credField is the extracted name, no credential value
9700
+ result.envMappingRows.push({
9701
+ id: nextRowId(),
9702
+ envVar: envVar,
9703
+ credField: refMatch[1]
9704
+ });
9705
+ } else {
9706
+ // Literal value — use envVar as credField and store the value
9707
+ result.envMappingRows.push({
9708
+ id: nextRowId(),
9709
+ envVar: envVar,
9710
+ credField: envVar
9711
+ });
9712
+ result.credentialData[envVar] = value || "";
9713
+ }
9678
9714
  });
9679
9715
  }
9680
9716
  } else {
@@ -26775,7 +26811,7 @@ var CustomMcpServerForm = function CustomMcpServerForm(_ref2) {
26775
26811
  setJsonError(null);
26776
26812
  },
26777
26813
  language: "json",
26778
- placeholder: '{\n "mcpServers": {\n "server-name": {\n "command": "npx",\n "args": ["-y", "package-name"],\n "env": {\n "API_KEY": "your-key"\n }\n }\n }\n}'
26814
+ placeholder: '{\n "type": "stdio",\n "command": "npx",\n "args": ["-y", "package-name"],\n "env": {\n "API_KEY": "${API_KEY}"\n }\n}'
26779
26815
  })]
26780
26816
  }), viewMode === "form" && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
26781
26817
  children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
@@ -27624,42 +27660,46 @@ var ProvidersSection = function ProvidersSection(_ref) {
27624
27660
  var appContext = React.useContext(AppContext);
27625
27661
  var providers = (appContext === null || appContext === void 0 ? void 0 : appContext.providers) || {};
27626
27662
  var refreshProviders = appContext === null || appContext === void 0 ? void 0 : appContext.refreshProviders;
27627
- var _useState = React.useState(null),
27663
+ var _useState = React.useState("credentials"),
27628
27664
  _useState2 = _slicedToArray(_useState, 2),
27629
- selectedName = _useState2[0],
27630
- setSelectedName = _useState2[1];
27631
- var _useState3 = React.useState(false),
27665
+ providerTab = _useState2[0],
27666
+ setProviderTab = _useState2[1];
27667
+ var _useState3 = React.useState(null),
27632
27668
  _useState4 = _slicedToArray(_useState3, 2),
27633
- isCreating = _useState4[0],
27634
- setIsCreating = _useState4[1];
27669
+ selectedName = _useState4[0],
27670
+ setSelectedName = _useState4[1];
27635
27671
  var _useState5 = React.useState(false),
27636
27672
  _useState6 = _slicedToArray(_useState5, 2),
27637
- isEditing = _useState6[0],
27638
- setIsEditing = _useState6[1];
27639
- var _useState7 = React.useState(""),
27673
+ isCreating = _useState6[0],
27674
+ setIsCreating = _useState6[1];
27675
+ var _useState7 = React.useState(false),
27640
27676
  _useState8 = _slicedToArray(_useState7, 2),
27641
- formName = _useState8[0],
27642
- setFormName = _useState8[1];
27677
+ isEditing = _useState8[0],
27678
+ setIsEditing = _useState8[1];
27643
27679
  var _useState9 = React.useState(""),
27644
27680
  _useState0 = _slicedToArray(_useState9, 2),
27645
- formType = _useState0[0],
27646
- setFormType = _useState0[1];
27647
- var _useState1 = React.useState({}),
27681
+ formName = _useState0[0],
27682
+ setFormName = _useState0[1];
27683
+ var _useState1 = React.useState(""),
27648
27684
  _useState10 = _slicedToArray(_useState1, 2),
27649
- formCredentials = _useState10[0],
27650
- setFormCredentials = _useState10[1];
27651
- var _useState11 = React.useState(null),
27685
+ formType = _useState10[0],
27686
+ setFormType = _useState10[1];
27687
+ var _useState11 = React.useState({}),
27652
27688
  _useState12 = _slicedToArray(_useState11, 2),
27653
- deleteTarget = _useState12[0],
27654
- setDeleteTarget = _useState12[1];
27655
- var _useState13 = React.useState(false),
27689
+ formCredentials = _useState12[0],
27690
+ setFormCredentials = _useState12[1];
27691
+ var _useState13 = React.useState(null),
27656
27692
  _useState14 = _slicedToArray(_useState13, 2),
27657
- isAddingMcp = _useState14[0],
27658
- setIsAddingMcp = _useState14[1];
27693
+ deleteTarget = _useState14[0],
27694
+ setDeleteTarget = _useState14[1];
27659
27695
  var _useState15 = React.useState(false),
27660
27696
  _useState16 = _slicedToArray(_useState15, 2),
27661
- isEditingMcp = _useState16[0],
27662
- setIsEditingMcp = _useState16[1];
27697
+ isAddingMcp = _useState16[0],
27698
+ setIsAddingMcp = _useState16[1];
27699
+ var _useState17 = React.useState(false),
27700
+ _useState18 = _slicedToArray(_useState17, 2),
27701
+ isEditingMcp = _useState18[0],
27702
+ setIsEditingMcp = _useState18[1];
27663
27703
 
27664
27704
  // Row ID counter for env/header rows in MCP edit mode
27665
27705
  var nextRowIdRef = React.useRef(0);
@@ -27702,6 +27742,7 @@ var ProvidersSection = function ProvidersSection(_ref) {
27702
27742
  credentials: credentials
27703
27743
  }, function () {
27704
27744
  resetForm();
27745
+ setProviderTab("credentials");
27705
27746
  refreshProviders && refreshProviders();
27706
27747
  }, function (e, err) {
27707
27748
  return (void 0);
@@ -27710,6 +27751,7 @@ var ProvidersSection = function ProvidersSection(_ref) {
27710
27751
  function handleStartEdit(name, provider) {
27711
27752
  setSelectedName(name);
27712
27753
  setIsCreating(false);
27754
+ setProviderTab(provider.providerClass === "mcp" ? "mcp" : "credentials");
27713
27755
  if (provider.providerClass === "mcp") {
27714
27756
  setIsEditingMcp(true);
27715
27757
  setIsEditing(false);
@@ -27774,6 +27816,7 @@ var ProvidersSection = function ProvidersSection(_ref) {
27774
27816
  setIsAddingMcp(false);
27775
27817
  refreshProviders && refreshProviders();
27776
27818
  setSelectedName(providerName);
27819
+ setProviderTab("mcp");
27777
27820
  }, function (e, err) {
27778
27821
  return (void 0);
27779
27822
  });
@@ -27795,6 +27838,7 @@ var ProvidersSection = function ProvidersSection(_ref) {
27795
27838
  mcpConfig: mcpConfig
27796
27839
  }, function () {
27797
27840
  setSelectedName(providerName);
27841
+ setProviderTab("mcp");
27798
27842
  setIsEditingMcp(false);
27799
27843
  resetForm();
27800
27844
  refreshProviders && refreshProviders();
@@ -27819,19 +27863,39 @@ var ProvidersSection = function ProvidersSection(_ref) {
27819
27863
  // eslint-disable-next-line react-hooks/exhaustive-deps
27820
27864
  }, [createRequested]);
27821
27865
  var selectedProvider = selectedName && providers[selectedName] ? providers[selectedName] : null;
27822
- var listContent = /*#__PURE__*/jsxRuntime.jsxs(DashReact.Sidebar.Content, {
27823
- children: [credentialProviders.length > 0 && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
27824
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27825
- className: "px-3 py-2 text-xs font-semibold opacity-40 uppercase tracking-wider",
27826
- children: "API Credentials"
27827
- }), credentialProviders.map(function (_ref8) {
27866
+ var activeProviders = providerTab === "credentials" ? credentialProviders : mcpProviders;
27867
+ var activeIcon = providerTab === "credentials" ? "key" : "server";
27868
+ var listContent = /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
27869
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27870
+ className: "px-2 pt-2",
27871
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.Tabs3, {
27872
+ value: providerTab,
27873
+ onValueChange: setProviderTab,
27874
+ backgroundColor: "bg-transparent",
27875
+ spacing: "p-0",
27876
+ children: /*#__PURE__*/jsxRuntime.jsxs(DashReact.Tabs3.List, {
27877
+ className: "w-full flex",
27878
+ spacing: "p-0.5",
27879
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Tabs3.Trigger, {
27880
+ value: "credentials",
27881
+ className: "flex-1",
27882
+ children: "API Credentials"
27883
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Tabs3.Trigger, {
27884
+ value: "mcp",
27885
+ className: "flex-1",
27886
+ children: "MCP Servers"
27887
+ })]
27888
+ })
27889
+ })
27890
+ }), /*#__PURE__*/jsxRuntime.jsxs(DashReact.Sidebar.Content, {
27891
+ children: [activeProviders.map(function (_ref8) {
27828
27892
  var _ref9 = _slicedToArray(_ref8, 2),
27829
27893
  name = _ref9[0],
27830
27894
  provider = _ref9[1];
27831
27895
  var isSelected = selectedName === name && !isCreating;
27832
27896
  return /*#__PURE__*/jsxRuntime.jsx(DashReact.Sidebar.Item, {
27833
27897
  icon: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27834
- icon: "key",
27898
+ icon: activeIcon,
27835
27899
  className: "h-3.5 w-3.5"
27836
27900
  }),
27837
27901
  active: isSelected,
@@ -27848,54 +27912,25 @@ var ProvidersSection = function ProvidersSection(_ref) {
27848
27912
  className: isSelected ? "bg-white/10 opacity-100" : "",
27849
27913
  children: name
27850
27914
  }, name);
27851
- })]
27852
- }), mcpProviders.length > 0 && /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
27853
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
27854
- className: "px-3 py-2 text-xs font-semibold opacity-40 uppercase tracking-wider mt-2",
27855
- children: "MCP Servers"
27856
- }), mcpProviders.map(function (_ref0) {
27857
- var _ref1 = _slicedToArray(_ref0, 2),
27858
- name = _ref1[0],
27859
- provider = _ref1[1];
27860
- var isSelected = selectedName === name && !isCreating;
27861
- return /*#__PURE__*/jsxRuntime.jsx(DashReact.Sidebar.Item, {
27862
- icon: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27863
- icon: "server",
27864
- className: "h-3.5 w-3.5"
27865
- }),
27866
- active: isSelected,
27915
+ }), activeProviders.length === 0 && /*#__PURE__*/jsxRuntime.jsx("span", {
27916
+ className: "text-sm opacity-40 py-8 text-center",
27917
+ children: providerTab === "credentials" ? "No API credentials configured" : "No MCP servers configured"
27918
+ }), providerTab === "mcp" && /*#__PURE__*/jsxRuntime.jsx("div", {
27919
+ className: "px-3 py-3 mt-2 border-t border-white/10",
27920
+ children: /*#__PURE__*/jsxRuntime.jsxs("button", {
27867
27921
  onClick: function onClick() {
27868
- setSelectedName(name);
27922
+ setIsAddingMcp(true);
27923
+ setSelectedName(null);
27869
27924
  setIsCreating(false);
27870
27925
  setIsEditing(false);
27871
- setIsAddingMcp(false);
27872
- resetForm();
27873
27926
  },
27874
- badge: provider.type ? /*#__PURE__*/jsxRuntime.jsx(DashReact.Tag3, {
27875
- text: provider.type
27876
- }) : null,
27877
- className: isSelected ? "bg-white/10 opacity-100" : "",
27878
- children: name
27879
- }, name);
27927
+ className: "flex items-center gap-2 text-sm text-blue-400 hover:text-blue-300 transition-colors w-full",
27928
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27929
+ icon: "plus",
27930
+ className: "h-3 w-3"
27931
+ }), "Add MCP Server"]
27932
+ })
27880
27933
  })]
27881
- }), providerEntries.length === 0 && /*#__PURE__*/jsxRuntime.jsx("span", {
27882
- className: "text-sm opacity-40 py-8 text-center",
27883
- children: "No providers configured"
27884
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
27885
- className: "px-3 py-3 mt-2 border-t border-white/10",
27886
- children: /*#__PURE__*/jsxRuntime.jsxs("button", {
27887
- onClick: function onClick() {
27888
- setIsAddingMcp(true);
27889
- setSelectedName(null);
27890
- setIsCreating(false);
27891
- setIsEditing(false);
27892
- },
27893
- className: "flex items-center gap-2 text-sm text-blue-400 hover:text-blue-300 transition-colors w-full",
27894
- children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
27895
- icon: "plus",
27896
- className: "h-3 w-3"
27897
- }), "Add MCP Server"]
27898
- })
27899
27934
  })]
27900
27935
  });
27901
27936
  var detailContent = null;