@ethisyscore/plugin-ui 1.127.2 → 1.128.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.
@@ -1,5 +1,5 @@
1
- import { C as ConnectorCanonicalField } from '../../mappingQueryKeys-T-gPzJk1.cjs';
2
- export { a as CONNECTOR_CONTROL_LABEL, b as ConnectorCanonicalFieldKind, c as ConnectorMappingSuggestionResult, d as ConnectorMappingTranslationEditorProps, e as ConnectorMappingTranslationEditorView, M as MappingCompletenessBanner, f as MappingCompletenessBannerProps, g as MappingCompletenessItem, h as MappingCompletenessResult, i as MappingReadiness, P as PLUGIN_PROVIDER_CONTROL_LABEL, j as PROVIDER_CONTROL_LABEL, k as PROVIDER_OPTION_LABEL, S as SUPPRESS_REQUEST_FIELD_VALUE, T as TestToolMappingExtractedField, l as TestToolMappingRequest, m as TestToolMappingResult, n as connectorMappingCompletenessQueryKey, o as connectorMappingsQueryKey, p as connectorMappingsRootQueryKey, q as pluginTargetMappingsQueryKey, s as selectIncompleteOperations, r as selectMappingReadiness, t as selectOptionalIncompleteOperations, u as selectRequiredIncompleteOperations, v as selectRequiredUnmappedOperations } from '../../mappingQueryKeys-T-gPzJk1.cjs';
1
+ import { C as ConnectorCanonicalField } from '../../mappingQueryKeys-DsZJn1sk.cjs';
2
+ export { a as CONNECTOR_CONTROL_LABEL, b as ConnectorCanonicalFieldKind, c as ConnectorMappingSuggestionResult, d as ConnectorMappingTranslationEditorProps, e as ConnectorMappingTranslationEditorView, f as ConnectorMappingTranslationExtras, M as MappingCompletenessBanner, g as MappingCompletenessBannerProps, h as MappingCompletenessItem, i as MappingCompletenessResult, j as MappingReadiness, P as PLUGIN_PROVIDER_CONTROL_LABEL, k as PROVIDER_CONTROL_LABEL, l as PROVIDER_OPTION_LABEL, S as SUPPRESS_REQUEST_FIELD_VALUE, T as TestToolMappingExtractedField, m as TestToolMappingRequest, n as TestToolMappingResult, o as connectorMappingCompletenessQueryKey, p as connectorMappingsQueryKey, q as connectorMappingsRootQueryKey, r as pluginTargetMappingsQueryKey, s as selectIncompleteOperations, t as selectMappingReadiness, u as selectOptionalIncompleteOperations, v as selectRequiredIncompleteOperations, w as selectRequiredUnmappedOperations } from '../../mappingQueryKeys-DsZJn1sk.cjs';
3
3
  import * as react from 'react';
4
4
  import { ReactNode } from 'react';
5
5
 
@@ -1,5 +1,5 @@
1
- import { C as ConnectorCanonicalField } from '../../mappingQueryKeys-T-gPzJk1.js';
2
- export { a as CONNECTOR_CONTROL_LABEL, b as ConnectorCanonicalFieldKind, c as ConnectorMappingSuggestionResult, d as ConnectorMappingTranslationEditorProps, e as ConnectorMappingTranslationEditorView, M as MappingCompletenessBanner, f as MappingCompletenessBannerProps, g as MappingCompletenessItem, h as MappingCompletenessResult, i as MappingReadiness, P as PLUGIN_PROVIDER_CONTROL_LABEL, j as PROVIDER_CONTROL_LABEL, k as PROVIDER_OPTION_LABEL, S as SUPPRESS_REQUEST_FIELD_VALUE, T as TestToolMappingExtractedField, l as TestToolMappingRequest, m as TestToolMappingResult, n as connectorMappingCompletenessQueryKey, o as connectorMappingsQueryKey, p as connectorMappingsRootQueryKey, q as pluginTargetMappingsQueryKey, s as selectIncompleteOperations, r as selectMappingReadiness, t as selectOptionalIncompleteOperations, u as selectRequiredIncompleteOperations, v as selectRequiredUnmappedOperations } from '../../mappingQueryKeys-T-gPzJk1.js';
1
+ import { C as ConnectorCanonicalField } from '../../mappingQueryKeys-DsZJn1sk.js';
2
+ export { a as CONNECTOR_CONTROL_LABEL, b as ConnectorCanonicalFieldKind, c as ConnectorMappingSuggestionResult, d as ConnectorMappingTranslationEditorProps, e as ConnectorMappingTranslationEditorView, f as ConnectorMappingTranslationExtras, M as MappingCompletenessBanner, g as MappingCompletenessBannerProps, h as MappingCompletenessItem, i as MappingCompletenessResult, j as MappingReadiness, P as PLUGIN_PROVIDER_CONTROL_LABEL, k as PROVIDER_CONTROL_LABEL, l as PROVIDER_OPTION_LABEL, S as SUPPRESS_REQUEST_FIELD_VALUE, T as TestToolMappingExtractedField, m as TestToolMappingRequest, n as TestToolMappingResult, o as connectorMappingCompletenessQueryKey, p as connectorMappingsQueryKey, q as connectorMappingsRootQueryKey, r as pluginTargetMappingsQueryKey, s as selectIncompleteOperations, t as selectMappingReadiness, u as selectOptionalIncompleteOperations, v as selectRequiredIncompleteOperations, w as selectRequiredUnmappedOperations } from '../../mappingQueryKeys-DsZJn1sk.js';
3
3
  import * as react from 'react';
4
4
  import { ReactNode } from 'react';
5
5
 
@@ -1606,6 +1606,205 @@ function ConnectorMappingView({
1606
1606
  ] }) })
1607
1607
  ] });
1608
1608
  }
1609
+
1610
+ // src/components/connectors/requestTemplates.ts
1611
+ var PLACEHOLDER = /^\{\{([A-Za-z_][A-Za-z0-9_.-]*)\}\}$/;
1612
+ var MAX_REQUEST_TEMPLATES = 4;
1613
+ function parseRequestTemplate(text) {
1614
+ let parsed;
1615
+ try {
1616
+ parsed = JSON.parse(text);
1617
+ } catch {
1618
+ return { value: null, error: "Not valid JSON.", placeholders: [] };
1619
+ }
1620
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
1621
+ return { value: null, error: "A template must be a JSON object.", placeholders: [] };
1622
+ }
1623
+ const placeholders = [];
1624
+ const embedded = [];
1625
+ walkStrings(parsed, (value) => {
1626
+ const match = PLACEHOLDER.exec(value);
1627
+ if (match) {
1628
+ if (!placeholders.includes(match[1])) placeholders.push(match[1]);
1629
+ } else if (value.includes("{{")) {
1630
+ embedded.push(value);
1631
+ }
1632
+ });
1633
+ return {
1634
+ value: parsed,
1635
+ error: embedded.length > 0 ? `A placeholder must be the whole value, like "{{companyName}}": "${embedded[0]}".` : null,
1636
+ placeholders
1637
+ };
1638
+ }
1639
+ function walkStrings(value, onString) {
1640
+ if (typeof value === "string") {
1641
+ onString(value);
1642
+ } else if (Array.isArray(value)) {
1643
+ value.forEach((item) => walkStrings(item, onString));
1644
+ } else if (value !== null && typeof value === "object") {
1645
+ Object.values(value).forEach((item) => walkStrings(item, onString));
1646
+ }
1647
+ }
1648
+ var MAX_ROW_FIELDS_PER_FIELD = 32;
1649
+ var MAX_ROW_FIELD_TEXT_LENGTH = 256;
1650
+ function rowFieldPathError(path) {
1651
+ const trimmed = path.trim();
1652
+ if (trimmed.length === 0) return null;
1653
+ if (!trimmed.startsWith("$.")) return 'A path must start with "$.", e.g. $.company_domain.';
1654
+ if (trimmed.length > MAX_ROW_FIELD_TEXT_LENGTH) return `A path can be at most ${MAX_ROW_FIELD_TEXT_LENGTH} characters.`;
1655
+ return null;
1656
+ }
1657
+ var REQUEST_TEMPLATES_CAPTION = "The first template whose placeholders all have values is sent as the request. Leave empty to use the field map.";
1658
+ function RequestTemplatesSection({
1659
+ rows,
1660
+ canonicalRequestFields,
1661
+ onChange,
1662
+ onAdd,
1663
+ onRemove,
1664
+ onMove
1665
+ }) {
1666
+ const canonicalNames = new Set(canonicalRequestFields.map((field) => field.name));
1667
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1668
+ /* @__PURE__ */ jsx(Typography, { variant: "h6", component: "h2", className: "mb-2", children: "Request templates" }),
1669
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-text-secondary mb-3 block", children: REQUEST_TEMPLATES_CAPTION }),
1670
+ rows.length === 0 ? /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-text-disabled italic mb-3", children: "No request templates configured." }) : /* @__PURE__ */ jsx(Box, { className: "flex flex-col gap-3 mb-3", children: rows.map((row, index) => {
1671
+ const parsed = row.text.trim().length === 0 ? null : parseRequestTemplate(row.text);
1672
+ return /* @__PURE__ */ jsxs(Box, { className: "flex flex-col gap-1", children: [
1673
+ /* @__PURE__ */ jsxs(Box, { className: "flex flex-row items-start gap-2", children: [
1674
+ /* @__PURE__ */ jsxs(FormControl, { variant: "filled", size: "medium", className: "surface mb-0 flex-1", children: [
1675
+ /* @__PURE__ */ jsx(InputLabel, { children: `Template ${index + 1}` }),
1676
+ /* @__PURE__ */ jsx(
1677
+ FilledInput,
1678
+ {
1679
+ multiline: true,
1680
+ minRows: 4,
1681
+ value: row.text,
1682
+ onChange: (e) => onChange(index, e.target.value),
1683
+ inputProps: { "aria-label": `Request template ${index + 1}` },
1684
+ sx: { fontFamily: "monospace" }
1685
+ }
1686
+ )
1687
+ ] }),
1688
+ /* @__PURE__ */ jsxs(Box, { className: "flex flex-col", children: [
1689
+ /* @__PURE__ */ jsx(
1690
+ IconButton,
1691
+ {
1692
+ "aria-label": `Move template ${index + 1} up`,
1693
+ color: "inherit",
1694
+ disabled: index === 0,
1695
+ onClick: () => onMove(index, -1),
1696
+ children: /* @__PURE__ */ jsx(NiChevronUpSmall, { size: "small" })
1697
+ }
1698
+ ),
1699
+ /* @__PURE__ */ jsx(
1700
+ IconButton,
1701
+ {
1702
+ "aria-label": `Move template ${index + 1} down`,
1703
+ color: "inherit",
1704
+ disabled: index === rows.length - 1,
1705
+ onClick: () => onMove(index, 1),
1706
+ children: /* @__PURE__ */ jsx(NiChevronDownSmall, { size: "small" })
1707
+ }
1708
+ ),
1709
+ /* @__PURE__ */ jsx(IconButton, { "aria-label": `Remove template ${index + 1}`, color: "inherit", onClick: () => onRemove(index), children: /* @__PURE__ */ jsx(NiBinEmpty, { size: "small" }) })
1710
+ ] })
1711
+ ] }),
1712
+ parsed?.error && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "error", role: "alert", children: parsed.error }),
1713
+ parsed && parsed.placeholders.length > 0 && /* @__PURE__ */ jsx(Box, { className: "flex flex-wrap gap-1", children: parsed.placeholders.map(
1714
+ (name) => canonicalNames.has(name) ? /* @__PURE__ */ jsx(Chip, { label: `{{${name}}}`, size: "small", variant: "outlined" }, name) : /* @__PURE__ */ jsx(
1715
+ Chip,
1716
+ {
1717
+ label: `{{${name}}} is not a request field`,
1718
+ size: "small",
1719
+ color: "error",
1720
+ variant: "outlined"
1721
+ },
1722
+ name
1723
+ )
1724
+ ) })
1725
+ ] }, row.id);
1726
+ }) }),
1727
+ /* @__PURE__ */ jsx(
1728
+ Button,
1729
+ {
1730
+ variant: "outlined",
1731
+ color: "grey",
1732
+ size: "small",
1733
+ onClick: onAdd,
1734
+ disabled: rows.length >= MAX_REQUEST_TEMPLATES,
1735
+ startIcon: /* @__PURE__ */ jsx(NiPlus, { size: "small" }),
1736
+ sx: { alignSelf: "flex-start" },
1737
+ children: "Add template"
1738
+ }
1739
+ )
1740
+ ] });
1741
+ }
1742
+ function RowFieldsSection({ objectFields, rows, onChange, onAdd, onRemove }) {
1743
+ return /* @__PURE__ */ jsx(Fragment, { children: objectFields.map((field) => {
1744
+ const fieldRows = rows[field.name] ?? [];
1745
+ return /* @__PURE__ */ jsxs(Box, { className: "flex flex-col gap-2 mb-3", children: [
1746
+ /* @__PURE__ */ jsx(Typography, { variant: "h6", component: "h2", children: `Row fields \u2014 ${field.name}` }),
1747
+ /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-text-secondary block", children: [
1748
+ "Rename the fields inside each row of this response. Each path is read from one row, e.g.",
1749
+ " ",
1750
+ /* @__PURE__ */ jsx("code", { children: "$.company_domain" }),
1751
+ "; once you list any, the fields you do not list are dropped."
1752
+ ] }),
1753
+ fieldRows.map((row, index) => /* @__PURE__ */ jsxs(Box, { className: "flex flex-row items-start gap-3", children: [
1754
+ /* @__PURE__ */ jsxs(FormControl, { variant: "filled", size: "medium", className: "surface mb-0", sx: { width: 200, flexShrink: 0 }, children: [
1755
+ /* @__PURE__ */ jsx(InputLabel, { children: "Row field" }),
1756
+ /* @__PURE__ */ jsx(
1757
+ FilledInput,
1758
+ {
1759
+ value: row.key,
1760
+ onChange: (e) => onChange(field.name, index, { key: e.target.value }),
1761
+ inputProps: { "aria-label": `Row field name ${index + 1} for ${field.name}`, maxLength: MAX_ROW_FIELD_TEXT_LENGTH },
1762
+ placeholder: "e.g. domain"
1763
+ }
1764
+ )
1765
+ ] }),
1766
+ /* @__PURE__ */ jsxs(FormControl, { variant: "filled", size: "medium", className: "surface mb-0 flex-1", children: [
1767
+ /* @__PURE__ */ jsx(InputLabel, { children: "JSON path in the row" }),
1768
+ /* @__PURE__ */ jsx(
1769
+ FilledInput,
1770
+ {
1771
+ value: row.path,
1772
+ onChange: (e) => onChange(field.name, index, { path: e.target.value }),
1773
+ inputProps: { "aria-label": `Row field path ${index + 1} for ${field.name}`, maxLength: MAX_ROW_FIELD_TEXT_LENGTH },
1774
+ error: rowFieldPathError(row.path) !== null,
1775
+ placeholder: "e.g. $.company_domain"
1776
+ }
1777
+ ),
1778
+ rowFieldPathError(row.path) && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "error", role: "alert", children: rowFieldPathError(row.path) })
1779
+ ] }),
1780
+ /* @__PURE__ */ jsx(
1781
+ IconButton,
1782
+ {
1783
+ "aria-label": `Remove row field ${index + 1} for ${field.name}`,
1784
+ color: "inherit",
1785
+ onClick: () => onRemove(field.name, index),
1786
+ sx: { mt: 1 },
1787
+ children: /* @__PURE__ */ jsx(NiBinEmpty, { size: "small" })
1788
+ }
1789
+ )
1790
+ ] }, row.id)),
1791
+ /* @__PURE__ */ jsx(
1792
+ Button,
1793
+ {
1794
+ variant: "outlined",
1795
+ color: "grey",
1796
+ size: "small",
1797
+ onClick: () => onAdd(field.name),
1798
+ startIcon: /* @__PURE__ */ jsx(NiPlus, { size: "small" }),
1799
+ disabled: fieldRows.length >= MAX_ROW_FIELDS_PER_FIELD,
1800
+ sx: { alignSelf: "flex-start" },
1801
+ "aria-label": `Add row field to ${field.name}`,
1802
+ children: "Add row field"
1803
+ }
1804
+ )
1805
+ ] }, field.name);
1806
+ }) });
1807
+ }
1609
1808
  var SUPPRESS_REQUEST_FIELD_VALUE = "(suppress)";
1610
1809
  function isSuppressed(value) {
1611
1810
  return value?.trim().toLowerCase() === SUPPRESS_REQUEST_FIELD_VALUE;
@@ -1623,6 +1822,8 @@ function ConnectorMappingTranslationEditorView({
1623
1822
  requestFieldMap,
1624
1823
  responseFieldPaths,
1625
1824
  staticRequestFields,
1825
+ requestTemplates,
1826
+ responseItemFieldPaths,
1626
1827
  onSave,
1627
1828
  onCancel,
1628
1829
  onTestMapping,
@@ -1650,6 +1851,52 @@ function ConnectorMappingTranslationEditorView({
1650
1851
  const [rawJsonExpanded, setRawJsonExpanded] = useState(false);
1651
1852
  const [suggestionError, setSuggestionError] = useState(null);
1652
1853
  const [isSuggesting, setIsSuggesting] = useState(false);
1854
+ const showTemplates = requestTemplates !== void 0;
1855
+ const objectResponseFields = canonicalResponseFields.filter((field) => field.kind === "Object");
1856
+ const showRowFields = responseItemFieldPaths !== void 0 && objectResponseFields.length > 0;
1857
+ const templateRowIdRef = useRef(0);
1858
+ const [templateRows, setTemplateRows] = useState(
1859
+ () => (requestTemplates ?? []).flatMap((template) => {
1860
+ let text;
1861
+ try {
1862
+ text = JSON.stringify(template, null, 2);
1863
+ } catch {
1864
+ text = void 0;
1865
+ }
1866
+ return text === void 0 ? [] : [{ id: templateRowIdRef.current++, text }];
1867
+ })
1868
+ );
1869
+ const rowFieldIdRef = useRef(0);
1870
+ const [rowFieldRows, setRowFieldRows] = useState(
1871
+ () => Object.fromEntries(
1872
+ Object.entries(responseItemFieldPaths ?? {}).map(([field, paths]) => [
1873
+ field,
1874
+ Object.entries(paths).map(([key, path]) => ({ id: rowFieldIdRef.current++, key, path }))
1875
+ ])
1876
+ )
1877
+ );
1878
+ 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));
1879
+ const handleTemplateChange = (index, text) => setTemplateRows((prev) => prev.map((row, i) => i === index ? { ...row, text } : row));
1880
+ const handleAddTemplate = () => setTemplateRows(
1881
+ (prev) => prev.length >= MAX_REQUEST_TEMPLATES ? prev : [...prev, { id: templateRowIdRef.current++, text: "" }]
1882
+ );
1883
+ const handleRemoveTemplate = (index) => setTemplateRows((prev) => prev.filter((_, i) => i !== index));
1884
+ const handleMoveTemplate = (index, direction) => setTemplateRows((prev) => {
1885
+ const target = index + direction;
1886
+ if (target < 0 || target >= prev.length) return prev;
1887
+ const next = [...prev];
1888
+ [next[index], next[target]] = [next[target], next[index]];
1889
+ return next;
1890
+ });
1891
+ const handleRowFieldChange = (field, index, patch) => setRowFieldRows((prev) => ({
1892
+ ...prev,
1893
+ [field]: (prev[field] ?? []).map((row, i) => i === index ? { ...row, ...patch } : row)
1894
+ }));
1895
+ const handleAddRowField = (field) => setRowFieldRows((prev) => ({
1896
+ ...prev,
1897
+ [field]: [...prev[field] ?? [], { id: rowFieldIdRef.current++, key: "", path: "" }]
1898
+ }));
1899
+ const handleRemoveRowField = (field, index) => setRowFieldRows((prev) => ({ ...prev, [field]: (prev[field] ?? []).filter((_, i) => i !== index) }));
1653
1900
  const handleRequestChange = (canonicalName, value) => {
1654
1901
  setRequestValues((prev) => ({ ...prev, [canonicalName]: value }));
1655
1902
  };
@@ -1675,11 +1922,17 @@ function ConnectorMappingTranslationEditorView({
1675
1922
  const requestMap = stripEmpty(requestValues);
1676
1923
  const responseMap = stripEmpty(responseValues);
1677
1924
  const staticMap = staticRowsToMap(staticRows);
1678
- onSave(
1679
- Object.keys(requestMap).length === 0 ? null : requestMap,
1680
- Object.keys(responseMap).length === 0 ? null : responseMap,
1681
- Object.keys(staticMap).length === 0 ? null : staticMap
1682
- );
1925
+ const request = Object.keys(requestMap).length === 0 ? null : requestMap;
1926
+ const response = Object.keys(responseMap).length === 0 ? null : responseMap;
1927
+ const statics = Object.keys(staticMap).length === 0 ? null : staticMap;
1928
+ if (!showTemplates && !showRowFields) {
1929
+ onSave(request, response, statics);
1930
+ return;
1931
+ }
1932
+ const extras = {};
1933
+ if (showTemplates) extras.requestTemplates = templateRowsToWire(templateRows);
1934
+ if (showRowFields) extras.responseItemFieldPaths = rowFieldRowsToWire(rowFieldRows, objectResponseFields);
1935
+ onSave(request, response, statics, extras);
1683
1936
  };
1684
1937
  const handleTest = async () => {
1685
1938
  if (!onTestMapping) return;
@@ -1855,6 +2108,33 @@ function ConnectorMappingTranslationEditorView({
1855
2108
  children: "Add parameter"
1856
2109
  }
1857
2110
  ),
2111
+ showTemplates && /* @__PURE__ */ jsxs(Fragment, { children: [
2112
+ /* @__PURE__ */ jsx(Divider, { className: "my-4" }),
2113
+ /* @__PURE__ */ jsx(
2114
+ RequestTemplatesSection,
2115
+ {
2116
+ rows: templateRows,
2117
+ canonicalRequestFields,
2118
+ onChange: handleTemplateChange,
2119
+ onAdd: handleAddTemplate,
2120
+ onRemove: handleRemoveTemplate,
2121
+ onMove: handleMoveTemplate
2122
+ }
2123
+ )
2124
+ ] }),
2125
+ showRowFields && objectResponseFields.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
2126
+ /* @__PURE__ */ jsx(Divider, { className: "my-4" }),
2127
+ /* @__PURE__ */ jsx(
2128
+ RowFieldsSection,
2129
+ {
2130
+ objectFields: objectResponseFields,
2131
+ rows: rowFieldRows,
2132
+ onChange: handleRowFieldChange,
2133
+ onAdd: handleAddRowField,
2134
+ onRemove: handleRemoveRowField
2135
+ }
2136
+ )
2137
+ ] }),
1858
2138
  (onTestMapping || onSuggestTranslation) && /* @__PURE__ */ jsxs(Fragment, { children: [
1859
2139
  /* @__PURE__ */ jsx(Divider, { className: "my-4" }),
1860
2140
  /* @__PURE__ */ jsx(Typography, { variant: "h6", component: "h2", className: "mb-2", children: "Test with sample inputs" }),
@@ -2010,6 +2290,7 @@ function ConnectorMappingTranslationEditorView({
2010
2290
  color: "primary",
2011
2291
  onClick: handleSave,
2012
2292
  "data-testid": "save-translation-button",
2293
+ disabled: hasInvalidTemplate,
2013
2294
  children: "Save"
2014
2295
  }
2015
2296
  )
@@ -2069,22 +2350,27 @@ function FieldRow({
2069
2350
  ] });
2070
2351
  }
2071
2352
  function stripEmpty(values) {
2072
- const out = {};
2073
- for (const [key, value] of Object.entries(values)) {
2074
- if (value.trim().length > 0) {
2075
- out[key] = value.trim();
2076
- }
2077
- }
2078
- return out;
2353
+ return Object.fromEntries(
2354
+ Object.entries(values).filter(([, value]) => value.trim().length > 0).map(([key, value]) => [key, value.trim()])
2355
+ );
2079
2356
  }
2080
2357
  function staticRowsToMap(rows) {
2081
- const out = {};
2082
- for (const { key, value } of rows) {
2083
- if (key.trim().length > 0) {
2084
- out[key.trim()] = value;
2085
- }
2086
- }
2087
- return out;
2358
+ return Object.fromEntries(rows.filter(({ key }) => key.trim().length > 0).map(({ key, value }) => [key.trim(), value]));
2359
+ }
2360
+ function templateRowsToWire(rows) {
2361
+ const templates = rows.filter((row) => row.text.trim().length > 0).map((row) => parseRequestTemplate(row.text).value).filter((value) => value !== null);
2362
+ return templates.length === 0 ? null : templates;
2363
+ }
2364
+ function rowFieldRowsToWire(rows, objectFields) {
2365
+ const out = Object.fromEntries(
2366
+ objectFields.map((field) => {
2367
+ const paths = Object.fromEntries(
2368
+ (rows[field.name] ?? []).filter(({ key, path }) => key.trim().length > 0 && path.trim().length > 0).map(({ key, path }) => [key.trim(), path.trim()])
2369
+ );
2370
+ return [field.name, paths];
2371
+ }).filter(([, paths]) => Object.keys(paths).length > 0)
2372
+ );
2373
+ return Object.keys(out).length === 0 ? null : out;
2088
2374
  }
2089
2375
 
2090
2376
  // src/components/connectors/mappingQueryKeys.ts