@oondemand/oon-core-front 0.3.15 → 0.3.17

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
@@ -3,7 +3,7 @@ import { StrictMode } from "react";
3
3
  import { createRoot } from "react-dom/client";
4
4
 
5
5
  // src/app/OonApp.tsx
6
- import { useMemo as useMemo7 } from "react";
6
+ import { useMemo as useMemo8 } from "react";
7
7
  import { RouterProvider } from "react-router-dom";
8
8
 
9
9
  // src/api/createRestClient.ts
@@ -1647,13 +1647,13 @@ function DynamicForm({ title, eyebrow = "Cadastro", fields, initialValues, submi
1647
1647
  }
1648
1648
 
1649
1649
  // src/components/internal/CoreDetailModal.tsx
1650
- import { useEffect as useEffect6, useMemo as useMemo6, useState as useState9 } from "react";
1650
+ import { useEffect as useEffect6, useMemo as useMemo7, useState as useState9 } from "react";
1651
1651
  import { Box as Box8, Button as Button8, Flex as Flex7, Heading as Heading3, Text as Text10 } from "@chakra-ui/react";
1652
1652
  import { useQuery as useQuery6, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
1653
1653
 
1654
1654
  // src/components/internal/CoreTabbedDetail.tsx
1655
- import { useEffect as useEffect5, useState as useState8 } from "react";
1656
- import { Box as Box7, Button as Button7, Flex as Flex6, Input as Input5, NativeSelect as NativeSelect4, SimpleGrid as SimpleGrid3, Stack as Stack3, Text as Text9 } from "@chakra-ui/react";
1655
+ import { useEffect as useEffect5, useMemo as useMemo6, useState as useState8 } from "react";
1656
+ import { Box as Box7, Button as Button7, Flex as Flex6, Input as Input5, NativeSelect as NativeSelect4, SimpleGrid as SimpleGrid3, Stack as Stack3, Text as Text9, Textarea as Textarea3 } from "@chakra-ui/react";
1657
1657
 
1658
1658
  // src/components/internal/CoreSummaryCards.tsx
1659
1659
  import { SimpleGrid as SimpleGrid2, Box as Box5, Text as Text6, Badge as Badge2 } from "@chakra-ui/react";
@@ -1887,51 +1887,232 @@ function coerce2(value, kind) {
1887
1887
  if (kind === "boolean") return value === "true";
1888
1888
  return value;
1889
1889
  }
1890
- function toValue2(value) {
1891
- return value == null ? "" : String(typeof value === "object" ? value._id ?? "" : value);
1890
+ function toValue2(value, kind) {
1891
+ if (value == null) return "";
1892
+ if (kind === "date") {
1893
+ try {
1894
+ return new Date(value).toISOString().slice(0, 10);
1895
+ } catch {
1896
+ return "";
1897
+ }
1898
+ }
1899
+ if (typeof value === "object") {
1900
+ const record = value;
1901
+ return String(record._id ?? record.id ?? "");
1902
+ }
1903
+ return String(value);
1904
+ }
1905
+ function isMultiline2(field) {
1906
+ return /observa|descricao|mensagem|detalhe|necessidade/i.test(field.field);
1892
1907
  }
1893
- function InlineParentForm({ fields, parent, resource, onSaved }) {
1908
+ function FieldControl({
1909
+ field,
1910
+ value,
1911
+ onChange
1912
+ }) {
1913
+ const label = fieldLabel({ name: field.field, label: field.label });
1914
+ if (field.widget === "checkbox") {
1915
+ const checkedValue = String(field.checkedValue ?? true);
1916
+ const uncheckedValue = String(field.uncheckedValue ?? false);
1917
+ const checked = (value || uncheckedValue) === checkedValue;
1918
+ return /* @__PURE__ */ jsxs10(
1919
+ Box7,
1920
+ {
1921
+ as: "label",
1922
+ display: "flex",
1923
+ minH: "38px",
1924
+ px: "11px",
1925
+ alignItems: "center",
1926
+ gap: "8px",
1927
+ color: "#344054",
1928
+ bg: checked ? "#F0F7FF" : "white",
1929
+ borderWidth: "1px",
1930
+ borderColor: checked ? "#8FC9E7" : "#D5DDE3",
1931
+ borderRadius: "7px",
1932
+ cursor: "pointer",
1933
+ children: [
1934
+ /* @__PURE__ */ jsx14(
1935
+ "input",
1936
+ {
1937
+ type: "checkbox",
1938
+ checked,
1939
+ style: { width: 16, height: 16, accentColor: "#0474AF", cursor: "pointer" },
1940
+ onChange: (event) => onChange(event.currentTarget.checked ? checkedValue : uncheckedValue)
1941
+ }
1942
+ ),
1943
+ /* @__PURE__ */ jsx14(Text9, { as: "span", fontSize: "11px", fontWeight: "600", children: label })
1944
+ ]
1945
+ }
1946
+ );
1947
+ }
1948
+ const control = field.kind === "enum" && field.options?.length ? /* @__PURE__ */ jsxs10(NativeSelect4.Root, { size: "sm", children: [
1949
+ /* @__PURE__ */ jsxs10(NativeSelect4.Field, { value, onChange: (event) => onChange(event.currentTarget.value), children: [
1950
+ /* @__PURE__ */ jsx14("option", { value: "", children: "\u2014 Selecione \u2014" }),
1951
+ field.options.map((option) => /* @__PURE__ */ jsx14("option", { value: option, children: option }, option))
1952
+ ] }),
1953
+ /* @__PURE__ */ jsx14(NativeSelect4.Indicator, {})
1954
+ ] }) : field.kind === "boolean" ? /* @__PURE__ */ jsxs10(NativeSelect4.Root, { size: "sm", children: [
1955
+ /* @__PURE__ */ jsxs10(NativeSelect4.Field, { value, onChange: (event) => onChange(event.currentTarget.value), children: [
1956
+ /* @__PURE__ */ jsx14("option", { value: "", children: "\u2014 Selecione \u2014" }),
1957
+ /* @__PURE__ */ jsx14("option", { value: "true", children: "Sim" }),
1958
+ /* @__PURE__ */ jsx14("option", { value: "false", children: "N\xE3o" })
1959
+ ] }),
1960
+ /* @__PURE__ */ jsx14(NativeSelect4.Indicator, {})
1961
+ ] }) : isMultiline2(field) ? /* @__PURE__ */ jsx14(Textarea3, { rows: 4, resize: "vertical", value, onChange: (event) => onChange(event.currentTarget.value) }) : /* @__PURE__ */ jsx14(
1962
+ Input5,
1963
+ {
1964
+ size: "sm",
1965
+ type: field.kind === "date" ? "date" : ["number", "currency", "currencyConverted"].includes(field.kind ?? "") ? "number" : "text",
1966
+ value,
1967
+ onChange: (event) => onChange(event.currentTarget.value)
1968
+ }
1969
+ );
1970
+ return /* @__PURE__ */ jsxs10(Box7, { children: [
1971
+ /* @__PURE__ */ jsxs10(Text9, { as: "label", display: "block", mb: "5px", color: "#475467", fontSize: "11px", fontWeight: "600", children: [
1972
+ label,
1973
+ field.required ? /* @__PURE__ */ jsx14(Text9, { as: "span", color: "#DC2626", children: " *" }) : null
1974
+ ] }),
1975
+ control
1976
+ ] });
1977
+ }
1978
+ function GroupSection({
1979
+ group,
1980
+ fields,
1981
+ values,
1982
+ onChange
1983
+ }) {
1984
+ if (!fields.length) return null;
1985
+ const columns = group.columns ?? 2;
1986
+ return /* @__PURE__ */ jsxs10(Box7, { p: { base: "12px", md: "14px" }, bg: "#FAFCFD", borderWidth: "1px", borderColor: "#E5E9ED", borderRadius: "9px", children: [
1987
+ /* @__PURE__ */ jsx14(Text9, { color: "#344054", fontSize: "12px", fontWeight: "700", children: group.label }),
1988
+ group.description ? /* @__PURE__ */ jsx14(Text9, { mt: "2px", mb: "12px", color: "#667085", fontSize: "10px", children: group.description }) : /* @__PURE__ */ jsx14(Box7, { h: "10px" }),
1989
+ /* @__PURE__ */ jsx14(SimpleGrid3, { columns: { base: 1, md: Math.min(columns, 2), xl: columns }, gapX: "16px", gapY: "14px", children: fields.map((field) => /* @__PURE__ */ jsx14(
1990
+ FieldControl,
1991
+ {
1992
+ field,
1993
+ value: values[field.field] ?? "",
1994
+ onChange: (value) => onChange(field.field, value)
1995
+ },
1996
+ field.field
1997
+ )) })
1998
+ ] });
1999
+ }
2000
+ function InlineParentForm({
2001
+ fields,
2002
+ groups,
2003
+ parent,
2004
+ resource,
2005
+ onSaved
2006
+ }) {
1894
2007
  const [values, setValues] = useState8({});
1895
2008
  const [saving, setSaving] = useState8(false);
1896
2009
  const [error, setError] = useState8(null);
1897
- useEffect5(() => setValues(Object.fromEntries(fields.map((f) => [f.field, toValue2(parent[f.field])]))), [parent, fields]);
1898
- return /* @__PURE__ */ jsx14("form", { onSubmit: async (event) => {
1899
- event.preventDefault();
1900
- setSaving(true);
2010
+ useEffect5(() => {
2011
+ setValues(Object.fromEntries(fields.map((field) => [field.field, toValue2(parent[field.field], field.kind)])));
2012
+ }, [parent, fields]);
2013
+ const fieldsByName = useMemo6(() => new Map(fields.map((field) => [field.field, field])), [fields]);
2014
+ const change = (field, value) => {
2015
+ setValues((current) => ({ ...current, [field]: value }));
1901
2016
  setError(null);
1902
- try {
1903
- const payload = Object.fromEntries(fields.map((f) => [f.field, coerce2(values[f.field] ?? "", f.kind)]).filter(([, v]) => v !== void 0));
1904
- const saved = parent._id ? await resource.update(String(parent._id), payload) : await resource.create(payload);
1905
- onSaved(saved);
1906
- } catch (err) {
1907
- setError(err);
1908
- } finally {
1909
- setSaving(false);
2017
+ };
2018
+ const renderFields = () => {
2019
+ if (groups?.length) {
2020
+ return /* @__PURE__ */ jsx14(Stack3, { gap: "14px", children: groups.map((group) => /* @__PURE__ */ jsx14(
2021
+ GroupSection,
2022
+ {
2023
+ group,
2024
+ fields: group.fields.map((field) => fieldsByName.get(field)).filter(Boolean),
2025
+ values,
2026
+ onChange: change
2027
+ },
2028
+ `${group.label}-${group.fields.join("-")}`
2029
+ )) });
1910
2030
  }
1911
- }, children: /* @__PURE__ */ jsxs10(Stack3, { gap: 4, children: [
1912
- error ? /* @__PURE__ */ jsx14(Text9, { color: "#B42318", fontSize: "11px", children: "N\xE3o foi poss\xEDvel salvar." }) : null,
1913
- /* @__PURE__ */ jsx14(SimpleGrid3, { columns: { base: 1, md: 2 }, gap: 3, children: fields.map((field) => /* @__PURE__ */ jsxs10(Box7, { children: [
1914
- /* @__PURE__ */ jsx14(Text9, { as: "label", display: "block", mb: "5px", fontSize: "11px", fontWeight: "600", children: fieldLabel({ name: field.field, label: field.label }) }),
1915
- field.kind === "boolean" ? /* @__PURE__ */ jsxs10(NativeSelect4.Root, { size: "sm", children: [
1916
- /* @__PURE__ */ jsxs10(NativeSelect4.Field, { value: values[field.field] ?? "", onChange: (e) => setValues((v) => ({ ...v, [field.field]: e.currentTarget.value })), children: [
1917
- /* @__PURE__ */ jsx14("option", { value: "", children: "\u2014" }),
1918
- /* @__PURE__ */ jsx14("option", { value: "true", children: "Sim" }),
1919
- /* @__PURE__ */ jsx14("option", { value: "false", children: "N\xE3o" })
1920
- ] }),
1921
- /* @__PURE__ */ jsx14(NativeSelect4.Indicator, {})
1922
- ] }) : /* @__PURE__ */ jsx14(Input5, { size: "sm", type: field.kind === "date" ? "date" : ["number", "currency"].includes(field.kind ?? "") ? "number" : "text", value: values[field.field] ?? "", onChange: (e) => setValues((v) => ({ ...v, [field.field]: e.currentTarget.value })) })
1923
- ] }, field.field)) }),
1924
- /* @__PURE__ */ jsx14(Flex6, { justify: "flex-end", children: /* @__PURE__ */ jsx14(Button7, { type: "submit", colorPalette: "brand", loading: saving, children: "Salvar dados principais" }) })
1925
- ] }) });
2031
+ return /* @__PURE__ */ jsx14(SimpleGrid3, { columns: { base: 1, md: 2 }, gap: "14px", children: fields.map((field) => /* @__PURE__ */ jsx14(
2032
+ FieldControl,
2033
+ {
2034
+ field,
2035
+ value: values[field.field] ?? "",
2036
+ onChange: (value) => change(field.field, value)
2037
+ },
2038
+ field.field
2039
+ )) });
2040
+ };
2041
+ return /* @__PURE__ */ jsx14(
2042
+ "form",
2043
+ {
2044
+ onSubmit: async (event) => {
2045
+ event.preventDefault();
2046
+ setSaving(true);
2047
+ setError(null);
2048
+ try {
2049
+ const payload = Object.fromEntries(
2050
+ fields.map((field) => [field.field, coerce2(values[field.field] ?? "", field.kind)]).filter(([, value]) => value !== void 0)
2051
+ );
2052
+ const saved = parent._id ? await resource.update(String(parent._id), payload) : await resource.create(payload);
2053
+ onSaved(saved);
2054
+ } catch (requestError) {
2055
+ setError(requestError);
2056
+ } finally {
2057
+ setSaving(false);
2058
+ }
2059
+ },
2060
+ children: /* @__PURE__ */ jsxs10(Stack3, { gap: "16px", children: [
2061
+ error ? /* @__PURE__ */ jsx14(Text9, { color: "#B42318", fontSize: "11px", children: "N\xE3o foi poss\xEDvel salvar." }) : null,
2062
+ renderFields(),
2063
+ /* @__PURE__ */ jsx14(Flex6, { justify: "flex-end", children: /* @__PURE__ */ jsx14(Button7, { type: "submit", colorPalette: "brand", loading: saving, children: "Salvar dados principais" }) })
2064
+ ] })
2065
+ }
2066
+ );
1926
2067
  }
1927
- function CoreTabbedDetail({ tabs, activeTab, onTabChange, parent, formFields, resource, relations, refreshTokens, onRefresh, onParentSaved }) {
2068
+ function CoreTabbedDetail({
2069
+ tabs,
2070
+ activeTab,
2071
+ onTabChange,
2072
+ parent,
2073
+ formFields,
2074
+ resource,
2075
+ relations,
2076
+ refreshTokens,
2077
+ onRefresh,
2078
+ onParentSaved
2079
+ }) {
1928
2080
  const active = tabs.find((tab) => tab.id === activeTab) ?? tabs[0];
1929
2081
  return /* @__PURE__ */ jsxs10(Stack3, { gap: 4, children: [
1930
2082
  /* @__PURE__ */ jsx14(Flex6, { gap: 2, borderBottomWidth: "1px", borderColor: "#E5E9ED", overflowX: "auto", children: tabs.map((tab) => {
1931
2083
  const disabled = !parent?._id && (tab.type === "relatedGrid" || tab.type === "readonlyGrid" || tab.type === "summary");
1932
- return /* @__PURE__ */ jsx14(Button7, { type: "button", variant: active?.id === tab.id ? "solid" : "ghost", colorPalette: active?.id === tab.id ? "brand" : void 0, disabled, onClick: () => onTabChange(tab.id), children: tab.label }, tab.id);
2084
+ return /* @__PURE__ */ jsx14(
2085
+ Button7,
2086
+ {
2087
+ type: "button",
2088
+ variant: active?.id === tab.id ? "solid" : "ghost",
2089
+ colorPalette: active?.id === tab.id ? "brand" : void 0,
2090
+ disabled,
2091
+ onClick: () => onTabChange(tab.id),
2092
+ children: tab.label
2093
+ },
2094
+ tab.id
2095
+ );
1933
2096
  }) }),
1934
- /* @__PURE__ */ jsx14(Box7, { children: !active ? null : active.type === "summary" && parent ? /* @__PURE__ */ jsx14(CoreSummaryCards, { cards: active.cards, parent, relations }) : active.type === "form" ? /* @__PURE__ */ jsx14(InlineParentForm, { fields: fieldsForTab(formFields, active.fields ?? active.groups?.flatMap((g) => g.fields)), parent: parent ?? {}, resource, onSaved: onParentSaved }) : (active.type === "relatedGrid" || active.type === "readonlyGrid") && parent ? /* @__PURE__ */ jsx14(CoreRelatedGrid, { tab: active, parent, relations, refreshToken: refreshTokens[active.id], onRefresh }) : active.type === "customComponent" ? /* @__PURE__ */ jsxs10(Text9, { color: "#667085", children: [
2097
+ /* @__PURE__ */ jsx14(Box7, { children: !active ? null : active.type === "summary" && parent ? /* @__PURE__ */ jsx14(CoreSummaryCards, { cards: active.cards, parent, relations }) : active.type === "form" ? /* @__PURE__ */ jsx14(
2098
+ InlineParentForm,
2099
+ {
2100
+ fields: fieldsForTab(formFields, active.fields ?? active.groups?.flatMap((group) => group.fields)),
2101
+ groups: active.groups,
2102
+ parent: parent ?? {},
2103
+ resource,
2104
+ onSaved: onParentSaved
2105
+ }
2106
+ ) : (active.type === "relatedGrid" || active.type === "readonlyGrid") && parent ? /* @__PURE__ */ jsx14(
2107
+ CoreRelatedGrid,
2108
+ {
2109
+ tab: active,
2110
+ parent,
2111
+ relations,
2112
+ refreshToken: refreshTokens[active.id],
2113
+ onRefresh
2114
+ }
2115
+ ) : active.type === "customComponent" ? /* @__PURE__ */ jsxs10(Text9, { color: "#667085", children: [
1935
2116
  "Componente customizado: ",
1936
2117
  active.component
1937
2118
  ] }) : /* @__PURE__ */ jsx14(Text9, { color: "#667085", children: "Salve o registro principal para liberar esta aba." }) })
@@ -1940,7 +2121,18 @@ function CoreTabbedDetail({ tabs, activeTab, onTabChange, parent, formFields, re
1940
2121
 
1941
2122
  // src/components/internal/CoreDetailModal.tsx
1942
2123
  import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
1943
- function CoreDetailModal({ model, title, config, recordId, initialRecord, initialTab, relations, onClose, onSaved }) {
2124
+ function CoreDetailModal({
2125
+ model,
2126
+ title,
2127
+ config,
2128
+ formFields,
2129
+ recordId,
2130
+ initialRecord,
2131
+ initialTab,
2132
+ relations,
2133
+ onClose,
2134
+ onSaved
2135
+ }) {
1944
2136
  const schemaQuery = useModelSchema(model);
1945
2137
  const schema = schemaQuery.data;
1946
2138
  const resource = useOonResource(schema?.basePath ?? `/${model.toLowerCase()}s`);
@@ -1948,11 +2140,18 @@ function CoreDetailModal({ model, title, config, recordId, initialRecord, initia
1948
2140
  const [parent, setParent] = useState9(initialRecord);
1949
2141
  const [activeTab, setActiveTab] = useState9(initialTab ?? config.defaultTab ?? config.tabs[0]?.id ?? "dados");
1950
2142
  const [refreshTokens, setRefreshTokens] = useState9({});
1951
- const parentQuery = useQuery6({ queryKey: ["oon", "detail", model, recordId], enabled: !!recordId, queryFn: () => resource.get(recordId) });
2143
+ const parentQuery = useQuery6({
2144
+ queryKey: ["oon", "detail", model, recordId],
2145
+ enabled: !!recordId,
2146
+ queryFn: () => resource.get(recordId)
2147
+ });
1952
2148
  useEffect6(() => {
1953
2149
  if (parentQuery.data) setParent(parentQuery.data);
1954
2150
  }, [parentQuery.data]);
1955
- const formFields = useMemo6(() => schema ? formFieldsFromMeta(schema.fields) : [], [schema]);
2151
+ const resolvedFormFields = useMemo7(
2152
+ () => formFields?.length ? formFields : schema ? formFieldsFromMeta(schema.fields) : [],
2153
+ [formFields, schema]
2154
+ );
1956
2155
  const refresh = (targets) => {
1957
2156
  const list = targets?.length ? targets : ["self"];
1958
2157
  if (list.includes("parent") || list.includes("all")) {
@@ -1962,8 +2161,14 @@ function CoreDetailModal({ model, title, config, recordId, initialRecord, initia
1962
2161
  setRefreshTokens((current) => {
1963
2162
  const next = { ...current };
1964
2163
  for (const target of list) {
1965
- if (target === "all") config.tabs.forEach((tab) => next[tab.id] = (next[tab.id] ?? 0) + 1);
1966
- else if (target !== "parent") next[target === "self" ? activeTab : target] = (next[target === "self" ? activeTab : target] ?? 0) + 1;
2164
+ if (target === "all") {
2165
+ config.tabs.forEach((tab) => {
2166
+ next[tab.id] = (next[tab.id] ?? 0) + 1;
2167
+ });
2168
+ } else if (target !== "parent") {
2169
+ const tabId = target === "self" ? activeTab : target;
2170
+ next[tabId] = (next[tabId] ?? 0) + 1;
2171
+ }
1967
2172
  }
1968
2173
  return next;
1969
2174
  });
@@ -1978,11 +2183,25 @@ function CoreDetailModal({ model, title, config, recordId, initialRecord, initia
1978
2183
  ] }),
1979
2184
  /* @__PURE__ */ jsx15(Button8, { onClick: onClose, children: "Fechar" })
1980
2185
  ] }),
1981
- /* @__PURE__ */ jsx15(Box8, { maxH: "calc(94vh - 73px)", p: "20px", overflowY: "auto", children: schemaQuery.isLoading || parentQuery.isLoading ? /* @__PURE__ */ jsx15(Text10, { children: "Carregando..." }) : /* @__PURE__ */ jsx15(CoreTabbedDetail, { tabs: config.tabs, activeTab, onTabChange: setActiveTab, parent, formFields, resource, relations, refreshTokens, onRefresh: refresh, onParentSaved: (saved) => {
1982
- setParent(saved);
1983
- onSaved?.();
1984
- refresh(["parent"]);
1985
- } }) })
2186
+ /* @__PURE__ */ jsx15(Box8, { maxH: "calc(94vh - 73px)", p: "20px", overflowY: "auto", children: schemaQuery.isLoading || parentQuery.isLoading ? /* @__PURE__ */ jsx15(Text10, { children: "Carregando..." }) : /* @__PURE__ */ jsx15(
2187
+ CoreTabbedDetail,
2188
+ {
2189
+ tabs: config.tabs,
2190
+ activeTab,
2191
+ onTabChange: setActiveTab,
2192
+ parent,
2193
+ formFields: resolvedFormFields,
2194
+ resource,
2195
+ relations,
2196
+ refreshTokens,
2197
+ onRefresh: refresh,
2198
+ onParentSaved: (saved) => {
2199
+ setParent(saved);
2200
+ onSaved?.();
2201
+ refresh(["parent"]);
2202
+ }
2203
+ }
2204
+ ) })
1986
2205
  ] }) });
1987
2206
  }
1988
2207
 
@@ -2098,6 +2317,7 @@ function CoreCollection({ model, label, section = "Cole\xE7\xE3o", mode = "dynam
2098
2317
  model,
2099
2318
  title,
2100
2319
  config: detailModal,
2320
+ formFields: resolvedForm,
2101
2321
  recordId: detailState.row?._id,
2102
2322
  initialRecord: detailState.row,
2103
2323
  initialTab: detailState.initialTab,
@@ -3528,7 +3748,7 @@ function localLoginUrl() {
3528
3748
  return `/login?redirect=${encodeURIComponent(current)}`;
3529
3749
  }
3530
3750
  function OonApp({ config }) {
3531
- const { http, storage, router } = useMemo7(() => {
3751
+ const { http, storage, router } = useMemo8(() => {
3532
3752
  const storage2 = createTokenStorage(config.app.id);
3533
3753
  const externalLoginUrl = config.auth?.loginUrl ?? config.api.meusAppsUrl;
3534
3754
  const http2 = createRestClient({