@gorgo/medusa-integration 0.0.2 → 0.0.4
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/.medusa/server/src/admin/index.js +35 -21
- package/.medusa/server/src/admin/index.mjs +35 -21
- package/.medusa/server/src/api/admin/integrations/__tests__/helpers.unit.spec.d.ts +1 -0
- package/.medusa/server/src/api/admin/integrations/__tests__/helpers.unit.spec.js +30 -0
- package/.medusa/server/src/api/admin/integrations/_helpers.d.ts +3 -3
- package/.medusa/server/src/api/admin/integrations/_helpers.js +8 -8
- package/.medusa/server/src/index.d.ts +1 -1
- package/.medusa/server/src/jobs/__tests__/test-integration-connections.unit.spec.d.ts +1 -0
- package/.medusa/server/src/jobs/__tests__/test-integration-connections.unit.spec.js +27 -0
- package/.medusa/server/src/jobs/test-integration-connections.d.ts +7 -0
- package/.medusa/server/src/jobs/test-integration-connections.js +19 -6
- package/.medusa/server/src/modules/integration/descriptor/__tests__/build-zod.unit.spec.js +43 -1
- package/.medusa/server/src/modules/integration/descriptor/__tests__/define.unit.spec.js +3 -3
- package/.medusa/server/src/modules/integration/descriptor/__tests__/introspect.unit.spec.js +3 -3
- package/.medusa/server/src/modules/integration/descriptor/__tests__/section-write.unit.spec.d.ts +1 -0
- package/.medusa/server/src/modules/integration/descriptor/__tests__/section-write.unit.spec.js +64 -0
- package/.medusa/server/src/modules/integration/descriptor/__tests__/validate.unit.spec.js +28 -2
- package/.medusa/server/src/modules/integration/descriptor/build-zod.js +7 -1
- package/.medusa/server/src/modules/integration/descriptor/define.d.ts +12 -5
- package/.medusa/server/src/modules/integration/descriptor/define.js +2 -2
- package/.medusa/server/src/modules/integration/descriptor/introspect.d.ts +1 -1
- package/.medusa/server/src/modules/integration/descriptor/introspect.js +4 -4
- package/.medusa/server/src/modules/integration/descriptor/meta.d.ts +1 -1
- package/.medusa/server/src/modules/integration/descriptor/section-write.d.ts +10 -0
- package/.medusa/server/src/modules/integration/descriptor/section-write.js +24 -0
- package/.medusa/server/src/modules/integration/loaders/load-providers.js +2 -2
- package/.medusa/server/src/modules/integration/migrations/Migration20260720130920.d.ts +5 -0
- package/.medusa/server/src/modules/integration/migrations/Migration20260720130920.js +18 -0
- package/.medusa/server/src/modules/integration/models/integration.d.ts +1 -1
- package/.medusa/server/src/modules/integration/models/integration.js +3 -3
- package/.medusa/server/src/modules/integration/services/__tests__/integration-module.unit.spec.d.ts +1 -0
- package/.medusa/server/src/modules/integration/services/__tests__/integration-module.unit.spec.js +240 -0
- package/.medusa/server/src/modules/integration/services/__tests__/integration-provider.unit.spec.js +3 -4
- package/.medusa/server/src/modules/integration/services/integration-module.d.ts +5 -5
- package/.medusa/server/src/modules/integration/services/integration-module.js +11 -12
- package/.medusa/server/src/modules/integration/utils/abstract-integration-provider.d.ts +5 -8
- package/.medusa/server/src/modules/integration/utils/abstract-integration-provider.js +4 -5
- package/.medusa/server/src/modules/integration/utils/integration.d.ts +3 -3
- package/.medusa/server/src/modules/integration/utils/integration.js +4 -4
- package/.medusa/server/src/subscribers/__tests__/invalidate-options-cache.unit.spec.d.ts +1 -0
- package/.medusa/server/src/subscribers/__tests__/invalidate-options-cache.unit.spec.js +53 -0
- package/.medusa/server/src/types/http/integration/admin/entities.d.ts +5 -4
- package/.medusa/server/src/types/integration/common.d.ts +3 -3
- package/.medusa/server/src/workflows/integration/steps/apply-integration-section.d.ts +1 -1
- package/.medusa/server/src/workflows/integration/steps/apply-integration-section.js +13 -20
- package/.medusa/server/src/workflows/integration/steps/set-integration-enabled.d.ts +1 -1
- package/.medusa/server/src/workflows/integration/steps/upsert-integration-record.d.ts +2 -2
- package/.medusa/server/src/workflows/integration/workflows/set-integration-enabled.d.ts +1 -1
- package/.medusa/server/src/workflows/integration/workflows/upsert-integration.js +2 -2
- package/README.md +41 -2
- package/README.ru.md +85 -0
- package/package.json +1 -1
|
@@ -24,7 +24,7 @@ const IntegrationIcon = ({
|
|
|
24
24
|
alt,
|
|
25
25
|
size = "base"
|
|
26
26
|
}) => {
|
|
27
|
-
const dim = size === "small" ? "h-6 w-6" : "h-
|
|
27
|
+
const dim = size === "small" ? "h-6 w-6" : "h-10 w-10";
|
|
28
28
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
29
29
|
"div",
|
|
30
30
|
{
|
|
@@ -43,15 +43,15 @@ const IntegrationsPage = () => {
|
|
|
43
43
|
queryFn: () => sdk.client.fetch("/admin/integrations")
|
|
44
44
|
});
|
|
45
45
|
const items = (data == null ? void 0 : data.integrations) ?? [];
|
|
46
|
-
const
|
|
46
|
+
const byCategory = items.reduce((acc, i) => {
|
|
47
47
|
var _a;
|
|
48
|
-
(acc[_a = i.
|
|
48
|
+
(acc[_a = i.category] ?? (acc[_a] = [])).push(i);
|
|
49
49
|
return acc;
|
|
50
50
|
}, {});
|
|
51
51
|
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "divide-y p-0", children: [
|
|
52
52
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: t("integration.list.title") }) }),
|
|
53
|
-
isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center px-6 py-8", children: /* @__PURE__ */ jsxRuntime.jsx(icons.Spinner, { className: "text-ui-fg-subtle animate-spin" }) }) : items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: t("integration.list.empty") }) }) : Object.entries(
|
|
54
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: t(`integration.
|
|
53
|
+
isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center px-6 py-8", children: /* @__PURE__ */ jsxRuntime.jsx(icons.Spinner, { className: "text-ui-fg-subtle animate-spin" }) }) : items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: t("integration.list.empty") }) }) : Object.entries(byCategory).map(([category, group]) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 py-4", children: [
|
|
54
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: t(`integration.categories.${category}`) }),
|
|
55
55
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 flex flex-col gap-2", children: group.map((i) => {
|
|
56
56
|
const configured = i.is_configured && i.is_enabled;
|
|
57
57
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -75,7 +75,7 @@ const IntegrationsPage = () => {
|
|
|
75
75
|
i.provider_id
|
|
76
76
|
);
|
|
77
77
|
}) })
|
|
78
|
-
] },
|
|
78
|
+
] }, category))
|
|
79
79
|
] });
|
|
80
80
|
};
|
|
81
81
|
const config = adminSdk.defineRouteConfig({
|
|
@@ -1683,7 +1683,7 @@ function useForm(props = {}) {
|
|
|
1683
1683
|
_formControl.current.formState = getProxyFormState(formState, control);
|
|
1684
1684
|
return _formControl.current;
|
|
1685
1685
|
}
|
|
1686
|
-
const jsonToText = (v) => v
|
|
1686
|
+
const jsonToText = (v) => v == null || v === "" ? "" : JSON.stringify(v, null, 2);
|
|
1687
1687
|
const JsonField = ({ field, f }) => {
|
|
1688
1688
|
const { t } = reactI18next.useTranslation();
|
|
1689
1689
|
const [raw, setRaw] = React.useState(() => jsonToText(f.value));
|
|
@@ -1703,7 +1703,7 @@ const JsonField = ({ field, f }) => {
|
|
|
1703
1703
|
setRaw(text);
|
|
1704
1704
|
if (text.trim() === "") {
|
|
1705
1705
|
setError(null);
|
|
1706
|
-
f.onChange(
|
|
1706
|
+
f.onChange(null);
|
|
1707
1707
|
return;
|
|
1708
1708
|
}
|
|
1709
1709
|
try {
|
|
@@ -1773,7 +1773,18 @@ function renderControl(field, f, secretConfigured, t) {
|
|
|
1773
1773
|
placeholder,
|
|
1774
1774
|
value: f.value ?? "",
|
|
1775
1775
|
disabled,
|
|
1776
|
-
onChange: (e) => f.onChange(e.target.value === "" ?
|
|
1776
|
+
onChange: (e) => f.onChange(e.target.value === "" ? null : e.target.valueAsNumber)
|
|
1777
|
+
}
|
|
1778
|
+
);
|
|
1779
|
+
case "url":
|
|
1780
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1781
|
+
ui.Input,
|
|
1782
|
+
{
|
|
1783
|
+
type: "url",
|
|
1784
|
+
placeholder,
|
|
1785
|
+
value: f.value ?? "",
|
|
1786
|
+
disabled,
|
|
1787
|
+
onChange: f.onChange
|
|
1777
1788
|
}
|
|
1778
1789
|
);
|
|
1779
1790
|
case "secret":
|
|
@@ -1784,7 +1795,8 @@ function renderControl(field, f, secretConfigured, t) {
|
|
|
1784
1795
|
placeholder: secretConfigured ? t("integration.form.keepSecret") : placeholder ?? "",
|
|
1785
1796
|
value: f.value ?? "",
|
|
1786
1797
|
disabled,
|
|
1787
|
-
onChange: f.onChange
|
|
1798
|
+
onChange: f.onChange,
|
|
1799
|
+
className: !f.value ? "[&~div]:hidden" : void 0
|
|
1788
1800
|
}
|
|
1789
1801
|
);
|
|
1790
1802
|
case "json":
|
|
@@ -1822,10 +1834,11 @@ const EditSectionDrawer = ({
|
|
|
1822
1834
|
providerId,
|
|
1823
1835
|
section,
|
|
1824
1836
|
values,
|
|
1825
|
-
|
|
1837
|
+
configuredSecrets = []
|
|
1826
1838
|
}) => {
|
|
1827
1839
|
const { t } = reactI18next.useTranslation();
|
|
1828
1840
|
const qc = reactQuery.useQueryClient();
|
|
1841
|
+
const configured = new Set(configuredSecrets);
|
|
1829
1842
|
const [defaults] = React.useState(() => sectionDefaults(section, values));
|
|
1830
1843
|
const form = useForm({ values: defaults });
|
|
1831
1844
|
const current = form.watch();
|
|
@@ -1852,7 +1865,7 @@ const EditSectionDrawer = ({
|
|
|
1852
1865
|
{
|
|
1853
1866
|
field: f,
|
|
1854
1867
|
control: form.control,
|
|
1855
|
-
secretConfigured:
|
|
1868
|
+
secretConfigured: configured.has(f.name)
|
|
1856
1869
|
},
|
|
1857
1870
|
f.name
|
|
1858
1871
|
)) }),
|
|
@@ -1946,6 +1959,7 @@ const EditPage = () => {
|
|
|
1946
1959
|
] });
|
|
1947
1960
|
}
|
|
1948
1961
|
const editing = descriptor.sections.find((s) => s.id === editingSection) ?? null;
|
|
1962
|
+
const configuredSecrets = new Set((record == null ? void 0 : record.configured_secrets) ?? []);
|
|
1949
1963
|
const sectionData = {
|
|
1950
1964
|
providerId: provider_id,
|
|
1951
1965
|
identifier: descriptor.identifier,
|
|
@@ -1970,7 +1984,7 @@ const EditPage = () => {
|
|
|
1970
1984
|
{
|
|
1971
1985
|
field: f,
|
|
1972
1986
|
value: (_a = record == null ? void 0 : record.values) == null ? void 0 : _a[f.name],
|
|
1973
|
-
secretConfigured:
|
|
1987
|
+
secretConfigured: configuredSecrets.has(f.name)
|
|
1974
1988
|
}
|
|
1975
1989
|
) }, f.name);
|
|
1976
1990
|
})
|
|
@@ -2011,7 +2025,7 @@ const EditPage = () => {
|
|
|
2011
2025
|
] })
|
|
2012
2026
|
] }),
|
|
2013
2027
|
/* @__PURE__ */ jsxRuntime.jsx(Row, { label: t("integration.labels.status"), children: !isConfigured ? /* @__PURE__ */ jsxRuntime.jsx(ui.StatusBadge, { color: "grey", children: t("integration.status.notConfigured") }) : !isComplete ? /* @__PURE__ */ jsxRuntime.jsx(ui.StatusBadge, { color: "orange", children: t("integration.status.incomplete") }) : /* @__PURE__ */ jsxRuntime.jsx(ui.StatusBadge, { color: record.is_enabled ? "green" : "grey", children: record.is_enabled ? t("integration.status.enabled") : t("integration.status.disabled") }) }),
|
|
2014
|
-
/* @__PURE__ */ jsxRuntime.jsx(Row, { label: t("integration.labels.
|
|
2028
|
+
/* @__PURE__ */ jsxRuntime.jsx(Row, { label: t("integration.labels.category"), children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", color: "grey", children: t(`integration.categories.${descriptor.category}`) }) }),
|
|
2015
2029
|
/* @__PURE__ */ jsxRuntime.jsx(Row, { label: t("integration.labels.lastTest"), children: (record == null ? void 0 : record.last_test_status) ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.StatusBadge, { color: testColor(record.last_test_status), children: t(`integration.testStatus.${record.last_test_status}`) }) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", className: "text-ui-fg-subtle", children: t("integration.labels.neverTested") }) })
|
|
2016
2030
|
] }) }),
|
|
2017
2031
|
mainSections.map(renderSection),
|
|
@@ -2023,7 +2037,7 @@ const EditPage = () => {
|
|
|
2023
2037
|
providerId: provider_id,
|
|
2024
2038
|
section: editing,
|
|
2025
2039
|
values: (record == null ? void 0 : record.values) ?? {},
|
|
2026
|
-
|
|
2040
|
+
configuredSecrets: (record == null ? void 0 : record.configured_secrets) ?? []
|
|
2027
2041
|
},
|
|
2028
2042
|
editing.id
|
|
2029
2043
|
)
|
|
@@ -2072,11 +2086,11 @@ const integration$1 = {
|
|
|
2072
2086
|
},
|
|
2073
2087
|
labels: {
|
|
2074
2088
|
status: "Status",
|
|
2075
|
-
|
|
2089
|
+
category: "Category",
|
|
2076
2090
|
lastTest: "Last test",
|
|
2077
2091
|
neverTested: "Never tested"
|
|
2078
2092
|
},
|
|
2079
|
-
|
|
2093
|
+
categories: {
|
|
2080
2094
|
payment: "Payment",
|
|
2081
2095
|
fulfillment: "Fulfillment",
|
|
2082
2096
|
marketplace: "Marketplace",
|
|
@@ -2109,7 +2123,7 @@ const integration$1 = {
|
|
|
2109
2123
|
form: {
|
|
2110
2124
|
required: "{{field}} is required",
|
|
2111
2125
|
invalidJson: "Invalid JSON",
|
|
2112
|
-
keepSecret: "••••••
|
|
2126
|
+
keepSecret: "•••••• – leave blank to keep",
|
|
2113
2127
|
items: "{{count}} items"
|
|
2114
2128
|
},
|
|
2115
2129
|
toast: {
|
|
@@ -2145,11 +2159,11 @@ const integration = {
|
|
|
2145
2159
|
},
|
|
2146
2160
|
labels: {
|
|
2147
2161
|
status: "Статус",
|
|
2148
|
-
|
|
2162
|
+
category: "Категория",
|
|
2149
2163
|
lastTest: "Последняя проверка",
|
|
2150
2164
|
neverTested: "Не проверялось"
|
|
2151
2165
|
},
|
|
2152
|
-
|
|
2166
|
+
categories: {
|
|
2153
2167
|
payment: "Платежи",
|
|
2154
2168
|
fulfillment: "Доставка",
|
|
2155
2169
|
marketplace: "Маркетплейс",
|
|
@@ -2182,7 +2196,7 @@ const integration = {
|
|
|
2182
2196
|
form: {
|
|
2183
2197
|
required: "Поле «{{field}}» обязательно",
|
|
2184
2198
|
invalidJson: "Некорректный JSON",
|
|
2185
|
-
keepSecret: "••••••
|
|
2199
|
+
keepSecret: "•••••• – оставьте пустым, чтобы не менять",
|
|
2186
2200
|
items: "{{count}} шт."
|
|
2187
2201
|
},
|
|
2188
2202
|
toast: {
|
|
@@ -20,7 +20,7 @@ const IntegrationIcon = ({
|
|
|
20
20
|
alt,
|
|
21
21
|
size = "base"
|
|
22
22
|
}) => {
|
|
23
|
-
const dim = size === "small" ? "h-6 w-6" : "h-
|
|
23
|
+
const dim = size === "small" ? "h-6 w-6" : "h-10 w-10";
|
|
24
24
|
return /* @__PURE__ */ jsx(
|
|
25
25
|
"div",
|
|
26
26
|
{
|
|
@@ -39,15 +39,15 @@ const IntegrationsPage = () => {
|
|
|
39
39
|
queryFn: () => sdk.client.fetch("/admin/integrations")
|
|
40
40
|
});
|
|
41
41
|
const items = (data == null ? void 0 : data.integrations) ?? [];
|
|
42
|
-
const
|
|
42
|
+
const byCategory = items.reduce((acc, i) => {
|
|
43
43
|
var _a;
|
|
44
|
-
(acc[_a = i.
|
|
44
|
+
(acc[_a = i.category] ?? (acc[_a] = [])).push(i);
|
|
45
45
|
return acc;
|
|
46
46
|
}, {});
|
|
47
47
|
return /* @__PURE__ */ jsxs(Container, { className: "divide-y p-0", children: [
|
|
48
48
|
/* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Heading, { level: "h2", children: t("integration.list.title") }) }),
|
|
49
|
-
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center px-6 py-8", children: /* @__PURE__ */ jsx(Spinner, { className: "text-ui-fg-subtle animate-spin" }) }) : items.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: t("integration.list.empty") }) }) : Object.entries(
|
|
50
|
-
/* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: t(`integration.
|
|
49
|
+
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center px-6 py-8", children: /* @__PURE__ */ jsx(Spinner, { className: "text-ui-fg-subtle animate-spin" }) }) : items.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: t("integration.list.empty") }) }) : Object.entries(byCategory).map(([category, group]) => /* @__PURE__ */ jsxs("div", { className: "px-6 py-4", children: [
|
|
50
|
+
/* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", children: t(`integration.categories.${category}`) }),
|
|
51
51
|
/* @__PURE__ */ jsx("div", { className: "mt-2 flex flex-col gap-2", children: group.map((i) => {
|
|
52
52
|
const configured = i.is_configured && i.is_enabled;
|
|
53
53
|
return /* @__PURE__ */ jsxs(
|
|
@@ -71,7 +71,7 @@ const IntegrationsPage = () => {
|
|
|
71
71
|
i.provider_id
|
|
72
72
|
);
|
|
73
73
|
}) })
|
|
74
|
-
] },
|
|
74
|
+
] }, category))
|
|
75
75
|
] });
|
|
76
76
|
};
|
|
77
77
|
const config = defineRouteConfig({
|
|
@@ -1679,7 +1679,7 @@ function useForm(props = {}) {
|
|
|
1679
1679
|
_formControl.current.formState = getProxyFormState(formState, control);
|
|
1680
1680
|
return _formControl.current;
|
|
1681
1681
|
}
|
|
1682
|
-
const jsonToText = (v) => v
|
|
1682
|
+
const jsonToText = (v) => v == null || v === "" ? "" : JSON.stringify(v, null, 2);
|
|
1683
1683
|
const JsonField = ({ field, f }) => {
|
|
1684
1684
|
const { t } = useTranslation();
|
|
1685
1685
|
const [raw, setRaw] = useState(() => jsonToText(f.value));
|
|
@@ -1699,7 +1699,7 @@ const JsonField = ({ field, f }) => {
|
|
|
1699
1699
|
setRaw(text);
|
|
1700
1700
|
if (text.trim() === "") {
|
|
1701
1701
|
setError(null);
|
|
1702
|
-
f.onChange(
|
|
1702
|
+
f.onChange(null);
|
|
1703
1703
|
return;
|
|
1704
1704
|
}
|
|
1705
1705
|
try {
|
|
@@ -1769,7 +1769,18 @@ function renderControl(field, f, secretConfigured, t) {
|
|
|
1769
1769
|
placeholder,
|
|
1770
1770
|
value: f.value ?? "",
|
|
1771
1771
|
disabled,
|
|
1772
|
-
onChange: (e) => f.onChange(e.target.value === "" ?
|
|
1772
|
+
onChange: (e) => f.onChange(e.target.value === "" ? null : e.target.valueAsNumber)
|
|
1773
|
+
}
|
|
1774
|
+
);
|
|
1775
|
+
case "url":
|
|
1776
|
+
return /* @__PURE__ */ jsx(
|
|
1777
|
+
Input,
|
|
1778
|
+
{
|
|
1779
|
+
type: "url",
|
|
1780
|
+
placeholder,
|
|
1781
|
+
value: f.value ?? "",
|
|
1782
|
+
disabled,
|
|
1783
|
+
onChange: f.onChange
|
|
1773
1784
|
}
|
|
1774
1785
|
);
|
|
1775
1786
|
case "secret":
|
|
@@ -1780,7 +1791,8 @@ function renderControl(field, f, secretConfigured, t) {
|
|
|
1780
1791
|
placeholder: secretConfigured ? t("integration.form.keepSecret") : placeholder ?? "",
|
|
1781
1792
|
value: f.value ?? "",
|
|
1782
1793
|
disabled,
|
|
1783
|
-
onChange: f.onChange
|
|
1794
|
+
onChange: f.onChange,
|
|
1795
|
+
className: !f.value ? "[&~div]:hidden" : void 0
|
|
1784
1796
|
}
|
|
1785
1797
|
);
|
|
1786
1798
|
case "json":
|
|
@@ -1818,10 +1830,11 @@ const EditSectionDrawer = ({
|
|
|
1818
1830
|
providerId,
|
|
1819
1831
|
section,
|
|
1820
1832
|
values,
|
|
1821
|
-
|
|
1833
|
+
configuredSecrets = []
|
|
1822
1834
|
}) => {
|
|
1823
1835
|
const { t } = useTranslation();
|
|
1824
1836
|
const qc = useQueryClient();
|
|
1837
|
+
const configured = new Set(configuredSecrets);
|
|
1825
1838
|
const [defaults] = useState(() => sectionDefaults(section, values));
|
|
1826
1839
|
const form = useForm({ values: defaults });
|
|
1827
1840
|
const current = form.watch();
|
|
@@ -1848,7 +1861,7 @@ const EditSectionDrawer = ({
|
|
|
1848
1861
|
{
|
|
1849
1862
|
field: f,
|
|
1850
1863
|
control: form.control,
|
|
1851
|
-
secretConfigured:
|
|
1864
|
+
secretConfigured: configured.has(f.name)
|
|
1852
1865
|
},
|
|
1853
1866
|
f.name
|
|
1854
1867
|
)) }),
|
|
@@ -1942,6 +1955,7 @@ const EditPage = () => {
|
|
|
1942
1955
|
] });
|
|
1943
1956
|
}
|
|
1944
1957
|
const editing = descriptor.sections.find((s) => s.id === editingSection) ?? null;
|
|
1958
|
+
const configuredSecrets = new Set((record == null ? void 0 : record.configured_secrets) ?? []);
|
|
1945
1959
|
const sectionData = {
|
|
1946
1960
|
providerId: provider_id,
|
|
1947
1961
|
identifier: descriptor.identifier,
|
|
@@ -1966,7 +1980,7 @@ const EditPage = () => {
|
|
|
1966
1980
|
{
|
|
1967
1981
|
field: f,
|
|
1968
1982
|
value: (_a = record == null ? void 0 : record.values) == null ? void 0 : _a[f.name],
|
|
1969
|
-
secretConfigured:
|
|
1983
|
+
secretConfigured: configuredSecrets.has(f.name)
|
|
1970
1984
|
}
|
|
1971
1985
|
) }, f.name);
|
|
1972
1986
|
})
|
|
@@ -2007,7 +2021,7 @@ const EditPage = () => {
|
|
|
2007
2021
|
] })
|
|
2008
2022
|
] }),
|
|
2009
2023
|
/* @__PURE__ */ jsx(Row, { label: t("integration.labels.status"), children: !isConfigured ? /* @__PURE__ */ jsx(StatusBadge, { color: "grey", children: t("integration.status.notConfigured") }) : !isComplete ? /* @__PURE__ */ jsx(StatusBadge, { color: "orange", children: t("integration.status.incomplete") }) : /* @__PURE__ */ jsx(StatusBadge, { color: record.is_enabled ? "green" : "grey", children: record.is_enabled ? t("integration.status.enabled") : t("integration.status.disabled") }) }),
|
|
2010
|
-
/* @__PURE__ */ jsx(Row, { label: t("integration.labels.
|
|
2024
|
+
/* @__PURE__ */ jsx(Row, { label: t("integration.labels.category"), children: /* @__PURE__ */ jsx(Badge, { size: "2xsmall", color: "grey", children: t(`integration.categories.${descriptor.category}`) }) }),
|
|
2011
2025
|
/* @__PURE__ */ jsx(Row, { label: t("integration.labels.lastTest"), children: (record == null ? void 0 : record.last_test_status) ? /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(StatusBadge, { color: testColor(record.last_test_status), children: t(`integration.testStatus.${record.last_test_status}`) }) }) : /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "text-ui-fg-subtle", children: t("integration.labels.neverTested") }) })
|
|
2012
2026
|
] }) }),
|
|
2013
2027
|
mainSections.map(renderSection),
|
|
@@ -2019,7 +2033,7 @@ const EditPage = () => {
|
|
|
2019
2033
|
providerId: provider_id,
|
|
2020
2034
|
section: editing,
|
|
2021
2035
|
values: (record == null ? void 0 : record.values) ?? {},
|
|
2022
|
-
|
|
2036
|
+
configuredSecrets: (record == null ? void 0 : record.configured_secrets) ?? []
|
|
2023
2037
|
},
|
|
2024
2038
|
editing.id
|
|
2025
2039
|
)
|
|
@@ -2068,11 +2082,11 @@ const integration$1 = {
|
|
|
2068
2082
|
},
|
|
2069
2083
|
labels: {
|
|
2070
2084
|
status: "Status",
|
|
2071
|
-
|
|
2085
|
+
category: "Category",
|
|
2072
2086
|
lastTest: "Last test",
|
|
2073
2087
|
neverTested: "Never tested"
|
|
2074
2088
|
},
|
|
2075
|
-
|
|
2089
|
+
categories: {
|
|
2076
2090
|
payment: "Payment",
|
|
2077
2091
|
fulfillment: "Fulfillment",
|
|
2078
2092
|
marketplace: "Marketplace",
|
|
@@ -2105,7 +2119,7 @@ const integration$1 = {
|
|
|
2105
2119
|
form: {
|
|
2106
2120
|
required: "{{field}} is required",
|
|
2107
2121
|
invalidJson: "Invalid JSON",
|
|
2108
|
-
keepSecret: "••••••
|
|
2122
|
+
keepSecret: "•••••• – leave blank to keep",
|
|
2109
2123
|
items: "{{count}} items"
|
|
2110
2124
|
},
|
|
2111
2125
|
toast: {
|
|
@@ -2141,11 +2155,11 @@ const integration = {
|
|
|
2141
2155
|
},
|
|
2142
2156
|
labels: {
|
|
2143
2157
|
status: "Статус",
|
|
2144
|
-
|
|
2158
|
+
category: "Категория",
|
|
2145
2159
|
lastTest: "Последняя проверка",
|
|
2146
2160
|
neverTested: "Не проверялось"
|
|
2147
2161
|
},
|
|
2148
|
-
|
|
2162
|
+
categories: {
|
|
2149
2163
|
payment: "Платежи",
|
|
2150
2164
|
fulfillment: "Доставка",
|
|
2151
2165
|
marketplace: "Маркетплейс",
|
|
@@ -2178,7 +2192,7 @@ const integration = {
|
|
|
2178
2192
|
form: {
|
|
2179
2193
|
required: "Поле «{{field}}» обязательно",
|
|
2180
2194
|
invalidJson: "Некорректный JSON",
|
|
2181
|
-
keepSecret: "••••••
|
|
2195
|
+
keepSecret: "•••••• – оставьте пустым, чтобы не менять",
|
|
2182
2196
|
items: "{{count}} шт."
|
|
2183
2197
|
},
|
|
2184
2198
|
toast: {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const globals_1 = require("@jest/globals");
|
|
4
|
+
const _helpers_1 = require("../_helpers");
|
|
5
|
+
const rec = (options) => ({
|
|
6
|
+
id: "int_x",
|
|
7
|
+
provider_id: "int_x",
|
|
8
|
+
category: "payment",
|
|
9
|
+
title: null,
|
|
10
|
+
is_enabled: true,
|
|
11
|
+
last_test_status: null,
|
|
12
|
+
options,
|
|
13
|
+
});
|
|
14
|
+
(0, globals_1.describe)("maskedView", () => {
|
|
15
|
+
(0, globals_1.it)("reports configured secrets per field — only those with a stored value", () => {
|
|
16
|
+
// apiKey has ciphertext, clientSecret is blank → only apiKey counts as configured.
|
|
17
|
+
const v = (0, _helpers_1.maskedView)(rec({ apiKey: "ct", clientSecret: "", terminalKey: "abc" }), ["apiKey", "clientSecret"]);
|
|
18
|
+
(0, globals_1.expect)(v.configured_secrets).toEqual(["apiKey"]);
|
|
19
|
+
});
|
|
20
|
+
(0, globals_1.it)("returns an empty list when no secret is set", () => {
|
|
21
|
+
const v = (0, _helpers_1.maskedView)(rec({ terminalKey: "abc" }), ["apiKey", "clientSecret"]);
|
|
22
|
+
(0, globals_1.expect)(v.configured_secrets).toEqual([]);
|
|
23
|
+
});
|
|
24
|
+
(0, globals_1.it)("never leaks secret ciphertext into values", () => {
|
|
25
|
+
const v = (0, _helpers_1.maskedView)(rec({ apiKey: "ct", terminalKey: "abc" }), ["apiKey"]);
|
|
26
|
+
(0, globals_1.expect)(v.values).toEqual({ terminalKey: "abc" });
|
|
27
|
+
(0, globals_1.expect)(Object.prototype.hasOwnProperty.call(v.values, "apiKey")).toBe(false);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVscGVycy51bml0LnNwZWMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2ludGVncmF0aW9ucy9fX3Rlc3RzX18vaGVscGVycy51bml0LnNwZWMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSwyQ0FBb0Q7QUFDcEQsMENBQXdDO0FBRXhDLE1BQU0sR0FBRyxHQUFHLENBQUMsT0FBZ0MsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNqRCxFQUFFLEVBQUUsT0FBTztJQUNYLFdBQVcsRUFBRSxPQUFPO0lBQ3BCLFFBQVEsRUFBRSxTQUFTO0lBQ25CLEtBQUssRUFBRSxJQUFJO0lBQ1gsVUFBVSxFQUFFLElBQUk7SUFDaEIsZ0JBQWdCLEVBQUUsSUFBSTtJQUN0QixPQUFPO0NBQ1IsQ0FBQyxDQUFBO0FBRUYsSUFBQSxrQkFBUSxFQUFDLFlBQVksRUFBRSxHQUFHLEVBQUU7SUFDMUIsSUFBQSxZQUFFLEVBQUMsdUVBQXVFLEVBQUUsR0FBRyxFQUFFO1FBQy9FLG1GQUFtRjtRQUNuRixNQUFNLENBQUMsR0FBRyxJQUFBLHFCQUFVLEVBQUMsR0FBRyxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsRUFBRSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUMsUUFBUSxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUE7UUFDN0csSUFBQSxnQkFBTSxFQUFDLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUE7SUFDbEQsQ0FBQyxDQUFDLENBQUE7SUFFRixJQUFBLFlBQUUsRUFBQyw2Q0FBNkMsRUFBRSxHQUFHLEVBQUU7UUFDckQsTUFBTSxDQUFDLEdBQUcsSUFBQSxxQkFBVSxFQUFDLEdBQUcsQ0FBQyxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUMsUUFBUSxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUE7UUFDN0UsSUFBQSxnQkFBTSxFQUFDLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQTtJQUMxQyxDQUFDLENBQUMsQ0FBQTtJQUVGLElBQUEsWUFBRSxFQUFDLDJDQUEyQyxFQUFFLEdBQUcsRUFBRTtRQUNuRCxNQUFNLENBQUMsR0FBRyxJQUFBLHFCQUFVLEVBQUMsR0FBRyxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUE7UUFDM0UsSUFBQSxnQkFBTSxFQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQTtRQUNoRCxJQUFBLGdCQUFNLEVBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUE7SUFDOUUsQ0FBQyxDQUFDLENBQUE7QUFDSixDQUFDLENBQUMsQ0FBQSJ9
|
|
@@ -9,8 +9,8 @@ export declare function service(req: MedusaRequest): IntegrationModuleService;
|
|
|
9
9
|
export declare function requireProvider(svc: IntegrationModuleService, providerId: string): void;
|
|
10
10
|
/**
|
|
11
11
|
* Build the client-facing view of a record. Secret options live encrypted inside `options`;
|
|
12
|
-
* they are stripped here so ciphertext never reaches the browser. `
|
|
13
|
-
*
|
|
14
|
-
* the non-secret options.
|
|
12
|
+
* they are stripped here so ciphertext never reaches the browser. `configured_secrets` lists
|
|
13
|
+
* the secret keys that currently have a stored value (per field), so the UI can render a
|
|
14
|
+
* "leave blank to keep" hint on exactly those fields. `values` holds only the non-secret options.
|
|
15
15
|
*/
|
|
16
16
|
export declare function maskedView(record: any, secretKeys: string[]): MaskedIntegration;
|
|
@@ -19,19 +19,19 @@ function requireProvider(svc, providerId) {
|
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
21
|
* Build the client-facing view of a record. Secret options live encrypted inside `options`;
|
|
22
|
-
* they are stripped here so ciphertext never reaches the browser. `
|
|
23
|
-
*
|
|
24
|
-
* the non-secret options.
|
|
22
|
+
* they are stripped here so ciphertext never reaches the browser. `configured_secrets` lists
|
|
23
|
+
* the secret keys that currently have a stored value (per field), so the UI can render a
|
|
24
|
+
* "leave blank to keep" hint on exactly those fields. `values` holds only the non-secret options.
|
|
25
25
|
*/
|
|
26
26
|
function maskedView(record, secretKeys) {
|
|
27
27
|
const secret = new Set(secretKeys);
|
|
28
28
|
const stored = (record.options ?? {});
|
|
29
29
|
const values = {};
|
|
30
|
-
|
|
30
|
+
const configured_secrets = [];
|
|
31
31
|
for (const [k, v] of Object.entries(stored)) {
|
|
32
32
|
if (secret.has(k)) {
|
|
33
33
|
if (v != null && v !== "")
|
|
34
|
-
|
|
34
|
+
configured_secrets.push(k);
|
|
35
35
|
continue;
|
|
36
36
|
}
|
|
37
37
|
values[k] = v;
|
|
@@ -39,12 +39,12 @@ function maskedView(record, secretKeys) {
|
|
|
39
39
|
return {
|
|
40
40
|
id: record.id,
|
|
41
41
|
provider_id: record.provider_id,
|
|
42
|
-
|
|
42
|
+
category: record.category,
|
|
43
43
|
title: record.title ?? null,
|
|
44
44
|
is_enabled: record.is_enabled,
|
|
45
|
-
|
|
45
|
+
configured_secrets,
|
|
46
46
|
last_test_status: record.last_test_status ?? null,
|
|
47
47
|
values,
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
50
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX2hlbHBlcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2ludGVncmF0aW9ucy9faGVscGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQU1BLDBCQUVDO0FBTUQsMENBSUM7QUFRRCxnQ0FzQkM7QUEvQ0QscURBQXVEO0FBQ3ZELDhEQUFpRTtBQUlqRSxTQUFnQixPQUFPLENBQUMsR0FBa0I7SUFDeEMsT0FBTyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxnQ0FBa0IsQ0FBQyxDQUFBO0FBQzlDLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFnQixlQUFlLENBQUMsR0FBNkIsRUFBRSxVQUFrQjtJQUMvRSxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1FBQ25DLE1BQU0sSUFBSSxtQkFBVyxDQUFDLG1CQUFXLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRSx3QkFBd0IsVUFBVSxHQUFHLENBQUMsQ0FBQTtJQUMzRixDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBZ0IsVUFBVSxDQUFDLE1BQVcsRUFBRSxVQUFvQjtJQUMxRCxNQUFNLE1BQU0sR0FBRyxJQUFJLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUNsQyxNQUFNLE1BQU0sR0FBRyxDQUFDLE1BQU0sQ0FBQyxPQUFPLElBQUksRUFBRSxDQUE0QixDQUFBO0lBQ2hFLE1BQU0sTUFBTSxHQUE0QixFQUFFLENBQUE7SUFDMUMsTUFBTSxrQkFBa0IsR0FBYSxFQUFFLENBQUE7SUFDdkMsS0FBSyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztRQUM1QyxJQUFJLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNsQixJQUFJLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUU7Z0JBQUUsa0JBQWtCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQ3JELFNBQVE7UUFDVixDQUFDO1FBQ0QsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQTtJQUNmLENBQUM7SUFDRCxPQUFPO1FBQ0wsRUFBRSxFQUFFLE1BQU0sQ0FBQyxFQUFFO1FBQ2IsV0FBVyxFQUFFLE1BQU0sQ0FBQyxXQUFXO1FBQy9CLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUTtRQUN6QixLQUFLLEVBQUUsTUFBTSxDQUFDLEtBQUssSUFBSSxJQUFJO1FBQzNCLFVBQVUsRUFBRSxNQUFNLENBQUMsVUFBVTtRQUM3QixrQkFBa0I7UUFDbEIsZ0JBQWdCLEVBQUUsTUFBTSxDQUFDLGdCQUFnQixJQUFJLElBQUk7UUFDakQsTUFBTTtLQUNQLENBQUE7QUFDSCxDQUFDIn0=
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { defineIntegration, z } from "./modules/integration/descriptor/define";
|
|
2
2
|
export { AbstractIntegrationProvider } from "./modules/integration/utils/abstract-integration-provider";
|
|
3
|
-
export type { IntegrationDescriptor, IntegrationDescriptorInput,
|
|
3
|
+
export type { IntegrationDescriptor, IntegrationDescriptorInput, CategoryKind, OptionDef, OptionValidateContext, Settings, TestConnectionContext, TestConnectionResult, } from "./modules/integration/descriptor/define";
|
|
4
4
|
export type { FieldControl, I18nKey } from "./modules/integration/descriptor/meta";
|
|
5
5
|
export { collectValidationIssues, isDescriptorComplete } from "./modules/integration/descriptor/validate";
|
|
6
6
|
export type { IntegrationSectionData } from "./types";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const globals_1 = require("@jest/globals");
|
|
4
|
+
const test_integration_connections_1 = require("../test-integration-connections");
|
|
5
|
+
(0, globals_1.describe)("tallyOutcomes", () => {
|
|
6
|
+
(0, globals_1.it)("counts each status into its own bucket (statuses, not display labels)", () => {
|
|
7
|
+
(0, globals_1.expect)((0, test_integration_connections_1.tallyOutcomes)(["passed", "failed", "passed", "skipped", "errored"])).toEqual({
|
|
8
|
+
passed: 2,
|
|
9
|
+
failed: 1,
|
|
10
|
+
skipped: 1,
|
|
11
|
+
errored: 1,
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
(0, globals_1.it)("returns all-zero buckets for no outcomes", () => {
|
|
15
|
+
(0, globals_1.expect)((0, test_integration_connections_1.tallyOutcomes)([])).toEqual({ passed: 0, failed: 0, skipped: 0, errored: 0 });
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
(0, globals_1.describe)("formatConnectionTestSummary", () => {
|
|
19
|
+
(0, globals_1.it)("maps passed→ok and failed→fail in the summary line", () => {
|
|
20
|
+
const line = (0, test_integration_connections_1.formatConnectionTestSummary)({ passed: 2, failed: 1, skipped: 3, errored: 0 });
|
|
21
|
+
(0, globals_1.expect)(line).toContain("ok: 2");
|
|
22
|
+
(0, globals_1.expect)(line).toContain("fail: 1");
|
|
23
|
+
(0, globals_1.expect)(line).toContain("skipped: 3");
|
|
24
|
+
(0, globals_1.expect)(line).toContain("errored: 0");
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC1pbnRlZ3JhdGlvbi1jb25uZWN0aW9ucy51bml0LnNwZWMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvam9icy9fX3Rlc3RzX18vdGVzdC1pbnRlZ3JhdGlvbi1jb25uZWN0aW9ucy51bml0LnNwZWMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSwyQ0FBb0Q7QUFDcEQsa0ZBQTRGO0FBRTVGLElBQUEsa0JBQVEsRUFBQyxlQUFlLEVBQUUsR0FBRyxFQUFFO0lBQzdCLElBQUEsWUFBRSxFQUFDLHVFQUF1RSxFQUFFLEdBQUcsRUFBRTtRQUMvRSxJQUFBLGdCQUFNLEVBQUMsSUFBQSw0Q0FBYSxFQUFDLENBQUMsUUFBUSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7WUFDbEYsTUFBTSxFQUFFLENBQUM7WUFDVCxNQUFNLEVBQUUsQ0FBQztZQUNULE9BQU8sRUFBRSxDQUFDO1lBQ1YsT0FBTyxFQUFFLENBQUM7U0FDWCxDQUFDLENBQUE7SUFDSixDQUFDLENBQUMsQ0FBQTtJQUVGLElBQUEsWUFBRSxFQUFDLDBDQUEwQyxFQUFFLEdBQUcsRUFBRTtRQUNsRCxJQUFBLGdCQUFNLEVBQUMsSUFBQSw0Q0FBYSxFQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUE7SUFDckYsQ0FBQyxDQUFDLENBQUE7QUFDSixDQUFDLENBQUMsQ0FBQTtBQUVGLElBQUEsa0JBQVEsRUFBQyw2QkFBNkIsRUFBRSxHQUFHLEVBQUU7SUFDM0MsSUFBQSxZQUFFLEVBQUMsb0RBQW9ELEVBQUUsR0FBRyxFQUFFO1FBQzVELE1BQU0sSUFBSSxHQUFHLElBQUEsMERBQTJCLEVBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQTtRQUMxRixJQUFBLGdCQUFNLEVBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFBO1FBQy9CLElBQUEsZ0JBQU0sRUFBQyxJQUFJLENBQUMsQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUE7UUFDakMsSUFBQSxnQkFBTSxFQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBQTtRQUNwQyxJQUFBLGdCQUFNLEVBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxDQUFDLFlBQVksQ0FBQyxDQUFBO0lBQ3RDLENBQUMsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUFDLENBQUEifQ==
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import type { MedusaContainer } from "@medusajs/framework/types";
|
|
2
|
+
/** A per-integration test result: the provider's `passed`/`failed`/`skipped`, or `errored` (threw). */
|
|
3
|
+
export type TestOutcome = "passed" | "failed" | "skipped" | "errored";
|
|
4
|
+
export type OutcomeCounts = Record<TestOutcome, number>;
|
|
5
|
+
/** Tally outcomes into per-status buckets. Buckets are keyed by the status itself — no mapping. */
|
|
6
|
+
export declare function tallyOutcomes(outcomes: Iterable<TestOutcome>): OutcomeCounts;
|
|
7
|
+
/** The end-of-run summary line. `passed`→"ok", `failed`→"fail" for human-readable output. */
|
|
8
|
+
export declare function formatConnectionTestSummary(counts: OutcomeCounts): string;
|
|
2
9
|
/**
|
|
3
10
|
* Daily health check: run the connection test for every configured & enabled integration
|
|
4
11
|
* that exposes one. Each test runs through `testIntegrationConnectionWorkflow`, which
|
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.config = void 0;
|
|
4
|
+
exports.tallyOutcomes = tallyOutcomes;
|
|
5
|
+
exports.formatConnectionTestSummary = formatConnectionTestSummary;
|
|
4
6
|
exports.default = testIntegrationConnectionsJob;
|
|
5
7
|
const integration_1 = require("../modules/integration");
|
|
6
8
|
const integration_2 = require("../workflows/integration");
|
|
9
|
+
/** Tally outcomes into per-status buckets. Buckets are keyed by the status itself — no mapping. */
|
|
10
|
+
function tallyOutcomes(outcomes) {
|
|
11
|
+
const counts = { passed: 0, failed: 0, skipped: 0, errored: 0 };
|
|
12
|
+
for (const o of outcomes)
|
|
13
|
+
counts[o]++;
|
|
14
|
+
return counts;
|
|
15
|
+
}
|
|
16
|
+
/** The end-of-run summary line. `passed`→"ok", `failed`→"fail" for human-readable output. */
|
|
17
|
+
function formatConnectionTestSummary(counts) {
|
|
18
|
+
return (`[integration] connection-test job done — ok: ${counts.passed}, fail: ${counts.failed}, ` +
|
|
19
|
+
`skipped: ${counts.skipped}, errored: ${counts.errored}`);
|
|
20
|
+
}
|
|
7
21
|
/**
|
|
8
22
|
* Daily health check: run the connection test for every configured & enabled integration
|
|
9
23
|
* that exposes one. Each test runs through `testIntegrationConnectionWorkflow`, which
|
|
@@ -24,13 +38,13 @@ async function testIntegrationConnectionsJob(container) {
|
|
|
24
38
|
return;
|
|
25
39
|
}
|
|
26
40
|
logger.info(`[integration] connection-test job: testing ${targets.length} integration(s)`);
|
|
27
|
-
const
|
|
41
|
+
const outcomes = [];
|
|
28
42
|
for (const target of targets) {
|
|
29
43
|
try {
|
|
30
44
|
const { result } = await (0, integration_2.testIntegrationConnectionWorkflow)(container).run({
|
|
31
45
|
input: { provider_id: target.provider_id },
|
|
32
46
|
});
|
|
33
|
-
|
|
47
|
+
outcomes.push(result.status);
|
|
34
48
|
const line = `[integration] ${target.provider_id} → ${result.status}${result.message ? `: ${result.message}` : ""}`;
|
|
35
49
|
if (result.status === "failed")
|
|
36
50
|
logger.warn(line);
|
|
@@ -38,16 +52,15 @@ async function testIntegrationConnectionsJob(container) {
|
|
|
38
52
|
logger.info(line);
|
|
39
53
|
}
|
|
40
54
|
catch (e) {
|
|
41
|
-
|
|
55
|
+
outcomes.push("errored");
|
|
42
56
|
logger.error(`[integration] ${target.provider_id} test errored: ${e?.message ?? e}`);
|
|
43
57
|
}
|
|
44
58
|
}
|
|
45
|
-
logger.info(
|
|
46
|
-
`skipped: ${counts.skipped}, errored: ${counts.errored}`);
|
|
59
|
+
logger.info(formatConnectionTestSummary(tallyOutcomes(outcomes)));
|
|
47
60
|
}
|
|
48
61
|
exports.config = {
|
|
49
62
|
name: "test-integration-connections-daily",
|
|
50
63
|
// Once a day, off-peak (03:00). Cron: minute hour day-of-month month day-of-week.
|
|
51
64
|
schedule: "0 3 * * *",
|
|
52
65
|
};
|
|
53
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
66
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC1pbnRlZ3JhdGlvbi1jb25uZWN0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9qb2JzL3Rlc3QtaW50ZWdyYXRpb24tY29ubmVjdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBVUEsc0NBSUM7QUFHRCxrRUFLQztBQVlELGdEQW9DQztBQXJFRCx3REFBMkQ7QUFFM0QsMERBQTRFO0FBTTVFLG1HQUFtRztBQUNuRyxTQUFnQixhQUFhLENBQUMsUUFBK0I7SUFDM0QsTUFBTSxNQUFNLEdBQWtCLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFBO0lBQzlFLEtBQUssTUFBTSxDQUFDLElBQUksUUFBUTtRQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFBO0lBQ3JDLE9BQU8sTUFBTSxDQUFBO0FBQ2YsQ0FBQztBQUVELDZGQUE2RjtBQUM3RixTQUFnQiwyQkFBMkIsQ0FBQyxNQUFxQjtJQUMvRCxPQUFPLENBQ0wsZ0RBQWdELE1BQU0sQ0FBQyxNQUFNLFdBQVcsTUFBTSxDQUFDLE1BQU0sSUFBSTtRQUN6RixZQUFZLE1BQU0sQ0FBQyxPQUFPLGNBQWMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUN6RCxDQUFBO0FBQ0gsQ0FBQztBQUVEOzs7Ozs7Ozs7R0FTRztBQUNZLEtBQUssVUFBVSw2QkFBNkIsQ0FBQyxTQUEwQjtJQUNwRixNQUFNLE1BQU0sR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFTLFFBQVEsQ0FBQyxDQUFBO0lBQ2xELE1BQU0sT0FBTyxHQUE2QixTQUFTLENBQUMsT0FBTyxDQUFDLGdDQUFrQixDQUFDLENBQUE7SUFFL0UsTUFBTSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsd0JBQXdCLEVBQUUsQ0FBQTtJQUN6RCxNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsTUFBTSxDQUM3QixDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLGFBQWEsSUFBSSxDQUFDLENBQUMsVUFBVSxJQUFJLENBQUMsQ0FBQyxtQkFBbUIsQ0FDaEUsQ0FBQTtJQUVELElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUN6QixNQUFNLENBQUMsSUFBSSxDQUFDLHVFQUF1RSxDQUFDLENBQUE7UUFDcEYsT0FBTTtJQUNSLENBQUM7SUFFRCxNQUFNLENBQUMsSUFBSSxDQUFDLDhDQUE4QyxPQUFPLENBQUMsTUFBTSxpQkFBaUIsQ0FBQyxDQUFBO0lBRTFGLE1BQU0sUUFBUSxHQUFrQixFQUFFLENBQUE7SUFFbEMsS0FBSyxNQUFNLE1BQU0sSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUM3QixJQUFJLENBQUM7WUFDSCxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsTUFBTSxJQUFBLCtDQUFpQyxFQUFDLFNBQVMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztnQkFDeEUsS0FBSyxFQUFFLEVBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQyxXQUFXLEVBQUU7YUFDM0MsQ0FBQyxDQUFBO1lBQ0YsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUE7WUFDNUIsTUFBTSxJQUFJLEdBQUcsaUJBQWlCLE1BQU0sQ0FBQyxXQUFXLE1BQU0sTUFBTSxDQUFDLE1BQU0sR0FDakUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQzNDLEVBQUUsQ0FBQTtZQUNGLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxRQUFRO2dCQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUE7O2dCQUM1QyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ3hCLENBQUM7UUFBQyxPQUFPLENBQU0sRUFBRSxDQUFDO1lBQ2hCLFFBQVEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUE7WUFDeEIsTUFBTSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsTUFBTSxDQUFDLFdBQVcsa0JBQWtCLENBQUMsRUFBRSxPQUFPLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQTtRQUN0RixDQUFDO0lBQ0gsQ0FBQztJQUVELE1BQU0sQ0FBQyxJQUFJLENBQUMsMkJBQTJCLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQTtBQUNuRSxDQUFDO0FBRVksUUFBQSxNQUFNLEdBQUc7SUFDcEIsSUFBSSxFQUFFLG9DQUFvQztJQUMxQyxrRkFBa0Y7SUFDbEYsUUFBUSxFQUFFLFdBQVc7Q0FDdEIsQ0FBQSJ9
|