@ethisyscore/plugin-ui 1.131.1 → 1.133.0

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.
@@ -1656,6 +1656,18 @@ function rowFieldPathError(path) {
1656
1656
  if (trimmed.length > MAX_ROW_FIELD_TEXT_LENGTH) return `A path can be at most ${MAX_ROW_FIELD_TEXT_LENGTH} characters.`;
1657
1657
  return null;
1658
1658
  }
1659
+ var DUPLICATE_ROW_FIELD_KEY_ERROR = "This key is already used";
1660
+ function duplicateRowFieldKeyIndexes(rows) {
1661
+ const seen = /* @__PURE__ */ new Set();
1662
+ const duplicates = /* @__PURE__ */ new Set();
1663
+ rows.forEach(({ key }, index) => {
1664
+ const trimmed = key.trim();
1665
+ if (trimmed.length === 0) return;
1666
+ if (seen.has(trimmed)) duplicates.add(index);
1667
+ else seen.add(trimmed);
1668
+ });
1669
+ return duplicates;
1670
+ }
1659
1671
  var REQUEST_TEMPLATES_CAPTION = "The first template whose placeholders all have values is sent as the request. Leave empty to use the field map.";
1660
1672
  function RequestTemplatesSection({
1661
1673
  rows,
@@ -1744,6 +1756,7 @@ function RequestTemplatesSection({
1744
1756
  function RowFieldsSection({ objectFields, rows, onChange, onAdd, onRemove }) {
1745
1757
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: objectFields.map((field) => {
1746
1758
  const fieldRows = rows[field.name] ?? [];
1759
+ const duplicateKeys = duplicateRowFieldKeyIndexes(fieldRows);
1747
1760
  return /* @__PURE__ */ jsxRuntime.jsxs(material.Box, { className: "flex flex-col gap-2 mb-3", children: [
1748
1761
  /* @__PURE__ */ jsxRuntime.jsx(material.Typography, { variant: "h6", component: "h2", children: `Row fields \u2014 ${field.name}` }),
1749
1762
  /* @__PURE__ */ jsxRuntime.jsxs(material.Typography, { variant: "caption", className: "text-text-secondary block", children: [
@@ -1761,9 +1774,11 @@ function RowFieldsSection({ objectFields, rows, onChange, onAdd, onRemove }) {
1761
1774
  value: row.key,
1762
1775
  onChange: (e) => onChange(field.name, index, { key: e.target.value }),
1763
1776
  inputProps: { "aria-label": `Row field name ${index + 1} for ${field.name}`, maxLength: MAX_ROW_FIELD_TEXT_LENGTH },
1777
+ error: duplicateKeys.has(index),
1764
1778
  placeholder: "e.g. domain"
1765
1779
  }
1766
- )
1780
+ ),
1781
+ duplicateKeys.has(index) && /* @__PURE__ */ jsxRuntime.jsx(material.Typography, { variant: "caption", color: "error", role: "alert", children: DUPLICATE_ROW_FIELD_KEY_ERROR })
1767
1782
  ] }),
1768
1783
  /* @__PURE__ */ jsxRuntime.jsxs(material.FormControl, { variant: "filled", size: "medium", className: "surface mb-0 flex-1", children: [
1769
1784
  /* @__PURE__ */ jsxRuntime.jsx(material.InputLabel, { children: "JSON path in the row" }),
@@ -1877,7 +1892,9 @@ function ConnectorMappingTranslationEditorView({
1877
1892
  ])
1878
1893
  )
1879
1894
  );
1880
- const hasInvalidTemplate = showTemplates && templateRows.some((row) => row.text.trim().length > 0 && parseRequestTemplate(row.text).error !== null) || showRowFields && objectResponseFields.some((field) => (rowFieldRows[field.name] ?? []).some((row) => rowFieldPathError(row.path) !== null));
1895
+ const hasInvalidTemplate = showTemplates && templateRows.some((row) => row.text.trim().length > 0 && parseRequestTemplate(row.text).error !== null) || showRowFields && objectResponseFields.some(
1896
+ (field) => (rowFieldRows[field.name] ?? []).some((row) => rowFieldPathError(row.path) !== null) || duplicateRowFieldKeyIndexes(rowFieldRows[field.name] ?? []).size > 0
1897
+ );
1881
1898
  const handleTemplateChange = (index, text) => setTemplateRows((prev) => prev.map((row, i) => i === index ? { ...row, text } : row));
1882
1899
  const handleAddTemplate = () => setTemplateRows(
1883
1900
  (prev) => prev.length >= MAX_REQUEST_TEMPLATES ? prev : [...prev, { id: templateRowIdRef.current++, text: "" }]
@@ -1920,6 +1937,13 @@ function ConnectorMappingTranslationEditorView({
1920
1937
  const handleRemoveStaticRow = (index) => {
1921
1938
  setStaticRows((prev) => prev.filter((_, i) => i !== index));
1922
1939
  };
1940
+ const buildExtras = () => {
1941
+ if (!showTemplates && !showRowFields) return void 0;
1942
+ const extras = {};
1943
+ if (showTemplates) extras.requestTemplates = templateRowsToWire(templateRows);
1944
+ if (showRowFields) extras.responseItemFieldPaths = rowFieldRowsToWire(rowFieldRows, objectResponseFields);
1945
+ return extras;
1946
+ };
1923
1947
  const handleSave = () => {
1924
1948
  const requestMap = stripEmpty(requestValues);
1925
1949
  const responseMap = stripEmpty(responseValues);
@@ -1927,13 +1951,11 @@ function ConnectorMappingTranslationEditorView({
1927
1951
  const request = Object.keys(requestMap).length === 0 ? null : requestMap;
1928
1952
  const response = Object.keys(responseMap).length === 0 ? null : responseMap;
1929
1953
  const statics = Object.keys(staticMap).length === 0 ? null : staticMap;
1930
- if (!showTemplates && !showRowFields) {
1954
+ const extras = buildExtras();
1955
+ if (extras === void 0) {
1931
1956
  onSave(request, response, statics);
1932
1957
  return;
1933
1958
  }
1934
- const extras = {};
1935
- if (showTemplates) extras.requestTemplates = templateRowsToWire(templateRows);
1936
- if (showRowFields) extras.responseItemFieldPaths = rowFieldRowsToWire(rowFieldRows, objectResponseFields);
1937
1959
  onSave(request, response, statics, extras);
1938
1960
  };
1939
1961
  const handleTest = async () => {
@@ -1952,7 +1974,8 @@ function ConnectorMappingTranslationEditorView({
1952
1974
  responseFieldPaths: Object.keys(responseMap).length === 0 ? null : responseMap,
1953
1975
  staticRequestFields: Object.keys(staticMap).length === 0 ? null : staticMap
1954
1976
  };
1955
- const result = await onTestMapping(request);
1977
+ const extras = buildExtras();
1978
+ const result = extras === void 0 ? await onTestMapping(request) : await onTestMapping(request, extras);
1956
1979
  setTestResult(result);
1957
1980
  } catch {
1958
1981
  setTestResult({
@@ -2254,6 +2277,22 @@ function ConnectorMappingTranslationEditorView({
2254
2277
  },
2255
2278
  ef.canonicalField
2256
2279
  )) }),
2280
+ testResult.requestArgumentsJson && /* @__PURE__ */ jsxRuntime.jsxs(material.Box, { className: "mt-2", "data-testid": "test-request-sent", children: [
2281
+ /* @__PURE__ */ jsxRuntime.jsx(material.Typography, { variant: "caption", color: "text.secondary", children: "Request sent" }),
2282
+ /* @__PURE__ */ jsxRuntime.jsx(
2283
+ material.Box,
2284
+ {
2285
+ component: "pre",
2286
+ className: "mt-1 overflow-auto rounded p-3 text-xs",
2287
+ sx: {
2288
+ maxHeight: 240,
2289
+ backgroundColor: "action.hover",
2290
+ fontFamily: "monospace"
2291
+ },
2292
+ children: testResult.requestArgumentsJson
2293
+ }
2294
+ )
2295
+ ] }),
2257
2296
  testResult.rawResponseJson && /* @__PURE__ */ jsxRuntime.jsxs(material.Box, { className: "mt-2", children: [
2258
2297
  /* @__PURE__ */ jsxRuntime.jsx(
2259
2298
  material.Button,