@digi-frontend/dgate-api-documentation 4.2.4 → 4.2.6

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.cjs CHANGED
@@ -704,6 +704,99 @@ const getSidebarStyles$1 = (token, scope) => ({
704
704
  }
705
705
  });
706
706
  //#endregion
707
+ //#region src/view/helper/patch-endpoint.ts
708
+ /** Convert an editor ParameterFormValues into an OpenAPI request Parameter. */
709
+ const toOpenApiParam = (p) => ({
710
+ name: p.name,
711
+ in: p.in,
712
+ required: p.required,
713
+ ...p.description ? { description: p.description } : {},
714
+ schema: {
715
+ type: p.type,
716
+ ...p.enum && p.enum.length > 0 ? { enum: p.enum } : {}
717
+ }
718
+ });
719
+ /** Convert editor response ParameterFormValues into an OpenAPI response headers map. */
720
+ const toResponseHeaders = (params) => params.reduce((acc, p) => {
721
+ acc[p.name] = {
722
+ schema: {
723
+ type: p.type,
724
+ ...p.enum && p.enum.length > 0 ? { enum: p.enum } : {}
725
+ },
726
+ required: p.required,
727
+ ...p.description ? { description: p.description } : {}
728
+ };
729
+ return acc;
730
+ }, {});
731
+ /**
732
+ * Apply the local (unsaved) edits for a single endpoint onto a clone of the
733
+ * stored endpoint. Absent edits fall back to the endpoint's existing value, so
734
+ * unedited fields are never wiped.
735
+ */
736
+ const buildPatchedEndpoint = (ep, edits) => {
737
+ const localName = edits.names[ep.id];
738
+ const localDesc = edits.descs[ep.id];
739
+ const localTags = edits.tags[ep.id];
740
+ const localParams = edits.params[ep.id];
741
+ const localResponseParams = edits.responseParams[ep.id];
742
+ const localResponseBody = edits.responseBody[ep.id];
743
+ const parameters = localParams !== void 0 ? localParams.map(toOpenApiParam) : ep.parameters;
744
+ const responseHeadersMap = localResponseParams && localResponseParams.length > 0 ? toResponseHeaders(localResponseParams) : null;
745
+ const responses = Object.fromEntries(Object.entries(ep.responses ?? {}).map(([code, resp]) => {
746
+ const patchedExample = localResponseBody?.[code];
747
+ const existingJson = resp.content?.["application/json"];
748
+ const content = patchedExample !== void 0 ? {
749
+ ...resp.content,
750
+ "application/json": {
751
+ ...existingJson ?? { schema: {} },
752
+ example: patchedExample
753
+ }
754
+ } : resp.content;
755
+ return [code, {
756
+ ...resp,
757
+ headers: responseHeadersMap ?? resp.headers,
758
+ ...content ? { content } : {}
759
+ }];
760
+ }));
761
+ const tags = localTags ?? ep.tags;
762
+ return {
763
+ ...ep,
764
+ summary: localName !== void 0 ? localName : ep.summary,
765
+ description: localDesc !== void 0 ? localDesc : ep.description,
766
+ tags,
767
+ parameters,
768
+ responses
769
+ };
770
+ };
771
+ /**
772
+ * Build a fully-patched copy of `selectedApi` that reflects all unsaved local
773
+ * edits, so View-mode surfaces (API page cards, endpoint detail, Codebox,
774
+ * sidebar tree) preview changes before saving. Endpoints are re-grouped under
775
+ * their edited primary tag. Returns the same `selectedApi` reference when no
776
+ * edit changes the result, to keep memo consumers stable.
777
+ */
778
+ const buildPatchedApi = (selectedApi, edits) => {
779
+ const patchedTags = {};
780
+ Object.entries(selectedApi.tags ?? {}).forEach(([bucketKey, endpoints]) => {
781
+ endpoints.forEach((ep) => {
782
+ const patched = buildPatchedEndpoint(ep, edits);
783
+ const newKey = edits.tags[ep.id]?.[0] ?? ep.tagName ?? bucketKey;
784
+ const endpoint = newKey === patched.tagName ? patched : {
785
+ ...patched,
786
+ tagName: newKey
787
+ };
788
+ (patchedTags[newKey] ??= []).push(endpoint);
789
+ });
790
+ });
791
+ const patched = {
792
+ ...selectedApi,
793
+ title: edits.apiTitle ?? selectedApi.title,
794
+ description: edits.apiDescription ?? selectedApi.description,
795
+ tags: patchedTags
796
+ };
797
+ return JSON.stringify(patched) === JSON.stringify(selectedApi) ? selectedApi : patched;
798
+ };
799
+ //#endregion
707
800
  //#region src/utils/OverflowTooltip.tsx
708
801
  const OverflowTooltip = ({ title, children, className, style, placement }) => {
709
802
  const ref = (0, react.useRef)(null);
@@ -1697,9 +1790,10 @@ const APIPage = ({ apiOverride }) => {
1697
1790
  if (selectedApi?.servers && !selectedUrl) setSelectedUrl(selectedApi?.servers?.[0].url);
1698
1791
  }, [selectedApi?.servers]);
1699
1792
  const getEndpointsForSelectedUrl = () => {
1700
- if (!selectedApi) return {};
1701
- const tags = selectedApi.tags || {};
1702
- const curl = selectedApi.curl || [];
1793
+ const api = apiOverride ?? selectedApi;
1794
+ if (!api) return {};
1795
+ const tags = api.tags || {};
1796
+ const curl = api.curl || [];
1703
1797
  const filtered = {};
1704
1798
  Object.keys(tags).forEach((tagKey) => {
1705
1799
  filtered[tagKey] = tags[tagKey].map((endpoint) => {
@@ -7880,8 +7974,9 @@ const EditModeSidebar = ({ selectedItem, onSelectItem, endpoints, hasGeneralErro
7880
7974
  border: "none"
7881
7975
  },
7882
7976
  children: ep.method
7883
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7977
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OverflowTooltip, {
7884
7978
  className: cx("path"),
7979
+ title: ep.path,
7885
7980
  style: { color: selectedItem.type === "endpoint" && selectedItem.key === ep.id ? token.colorPrimary : token.colorText },
7886
7981
  children: ep.path
7887
7982
  })] })
@@ -8660,7 +8755,11 @@ const EndpointPage = () => {
8660
8755
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(antd.Breadcrumb, { items: [
8661
8756
  {
8662
8757
  href: "",
8663
- title: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: selectedApi?.title || "API Name" }),
8758
+ title: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OverflowTooltip, {
8759
+ title: selectedApi?.title || "API Name",
8760
+ style: { maxWidth: "200px" },
8761
+ children: selectedApi?.title || "API Name"
8762
+ }),
8664
8763
  onClick: (e) => {
8665
8764
  e.preventDefault();
8666
8765
  setSelectedNodeKey(selectedApi?.id);
@@ -8683,13 +8782,17 @@ const EndpointPage = () => {
8683
8782
  color: token.colorTextTertiary,
8684
8783
  gap: "0.25rem"
8685
8784
  },
8686
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: selectedEndpoint?.tagName || "default" })
8785
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OverflowTooltip, {
8786
+ title: selectedEndpoint?.tagName || "default",
8787
+ style: { maxWidth: "200px" },
8788
+ children: selectedEndpoint?.tagName || "default"
8789
+ })
8687
8790
  })
8688
8791
  },
8689
8792
  { title: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OverflowTooltip, {
8690
8793
  title: selectedEndpoint?.summary || "Endpoint Name",
8691
8794
  style: { maxWidth: "300px" },
8692
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: selectedEndpoint?.summary || "Endpoint Name" })
8795
+ children: selectedEndpoint?.summary || "Endpoint Name"
8693
8796
  }) }
8694
8797
  ] })]
8695
8798
  }),
@@ -8699,7 +8802,8 @@ const EndpointPage = () => {
8699
8802
  display: "flex",
8700
8803
  alignItems: "center",
8701
8804
  gap: 12,
8702
- margin: 0
8805
+ margin: 0,
8806
+ minWidth: 0
8703
8807
  },
8704
8808
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(antd.Tag, {
8705
8809
  style: {
@@ -8714,7 +8818,11 @@ const EndpointPage = () => {
8714
8818
  children: selectedEndpoint?.method
8715
8819
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OverflowTooltip, {
8716
8820
  title: selectedEndpoint?.summary ?? "--",
8717
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: selectedEndpoint?.summary?.replace(selectedEndpoint?.method, "") ?? "--" })
8821
+ style: {
8822
+ flex: 1,
8823
+ minWidth: 0
8824
+ },
8825
+ children: selectedEndpoint?.summary?.replace(selectedEndpoint?.method, "") ?? "--"
8718
8826
  })]
8719
8827
  }),
8720
8828
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Paragraph, {
@@ -9283,17 +9391,27 @@ const ConsoleDocumentationLayout = ({ data, preSelectedApi, handleVisitLandingPa
9283
9391
  const viewModeApi = (0, react$1.useMemo)(() => {
9284
9392
  if (!selectedApi) return null;
9285
9393
  if (mode !== "view") return selectedApi;
9286
- if (localApiName === selectedApi.title && localDescription === selectedApi.description) return selectedApi;
9287
- return {
9288
- ...selectedApi,
9289
- title: localApiName,
9290
- description: localDescription
9291
- };
9394
+ return buildPatchedApi(selectedApi, {
9395
+ apiTitle: localApiName,
9396
+ apiDescription: localDescription,
9397
+ names: endpointNames,
9398
+ descs: endpointDescs,
9399
+ tags: endpointTags,
9400
+ params: endpointParams,
9401
+ responseParams: endpointResponseParams,
9402
+ responseBody: endpointResponseBody
9403
+ });
9292
9404
  }, [
9293
9405
  mode,
9294
9406
  selectedApi,
9295
9407
  localApiName,
9296
- localDescription
9408
+ localDescription,
9409
+ endpointNames,
9410
+ endpointDescs,
9411
+ endpointTags,
9412
+ endpointParams,
9413
+ endpointResponseParams,
9414
+ endpointResponseBody
9297
9415
  ]);
9298
9416
  (0, react$1.useEffect)(() => {
9299
9417
  return () => {
@@ -9619,58 +9737,32 @@ const ConsoleDocumentationLayout = ({ data, preSelectedApi, handleVisitLandingPa
9619
9737
  setBannerVisible(hasChanges);
9620
9738
  }, [hasChanges]);
9621
9739
  (0, react$1.useEffect)(() => {
9622
- if (mode !== "view" || !selectedEndpoint) return;
9623
- const epId = selectedEndpoint.id;
9624
- const localName = endpointNames[epId];
9625
- const localDesc = endpointDescs[epId];
9626
- const localEpTags = endpointTags[epId];
9627
- const patchedSummary = localName !== void 0 && localName !== selectedEndpoint.summary ? localName : selectedEndpoint.summary;
9628
- const patchedDesc = localDesc !== void 0 && localDesc !== selectedEndpoint.description ? localDesc : selectedEndpoint.description;
9629
- const patchedTags = localEpTags !== void 0 && JSON.stringify(localEpTags) !== JSON.stringify(selectedEndpoint.tags ?? []) ? localEpTags : selectedEndpoint.tags;
9630
- const openApiParams = (endpointParams[epId] ?? []).map((p) => ({
9631
- name: p.name,
9632
- in: p.in,
9633
- required: p.required,
9634
- ...p.description ? { description: p.description } : {},
9635
- schema: {
9636
- type: p.type,
9637
- ...p.enum && p.enum.length > 0 ? { enum: p.enum } : {}
9638
- }
9639
- }));
9640
- const responseHeadersMap = (endpointResponseParams[epId] ?? []).reduce((acc, p) => {
9641
- acc[p.name] = {
9642
- schema: {
9643
- type: p.type,
9644
- ...p.enum && p.enum.length > 0 ? { enum: p.enum } : {}
9645
- },
9646
- required: p.required,
9647
- ...p.description ? { description: p.description } : {}
9648
- };
9649
- return acc;
9650
- }, {});
9651
- const patchedResponses = Object.fromEntries(Object.entries(selectedEndpoint.responses ?? {}).map(([code, resp]) => [code, {
9652
- ...resp,
9653
- headers: Object.keys(responseHeadersMap).length > 0 ? responseHeadersMap : resp.headers
9654
- }]));
9655
- if (selectedEndpoint.summary === patchedSummary && selectedEndpoint.description === patchedDesc && JSON.stringify(selectedEndpoint.tags ?? []) === JSON.stringify(patchedTags ?? []) && JSON.stringify(selectedEndpoint.parameters ?? []) === JSON.stringify(openApiParams) && JSON.stringify(selectedEndpoint.responses) === JSON.stringify(patchedResponses)) return;
9740
+ if (mode !== "view" || !selectedEndpoint || !viewModeApi) return;
9741
+ const patched = Object.values(viewModeApi.tags ?? {}).flat().find((e) => e.id === selectedEndpoint.id);
9742
+ if (!patched) return;
9743
+ if (selectedEndpoint.summary === patched.summary && selectedEndpoint.description === patched.description && JSON.stringify(selectedEndpoint.tags ?? []) === JSON.stringify(patched.tags ?? []) && JSON.stringify(selectedEndpoint.parameters ?? []) === JSON.stringify(patched.parameters ?? []) && JSON.stringify(selectedEndpoint.responses) === JSON.stringify(patched.responses)) return;
9656
9744
  setSelectedEndpoint({
9657
- ...selectedEndpoint,
9658
- summary: patchedSummary,
9659
- description: patchedDesc,
9660
- tags: patchedTags,
9661
- parameters: openApiParams,
9662
- responses: patchedResponses
9745
+ ...patched,
9746
+ parentApiId: selectedEndpoint.parentApiId
9663
9747
  });
9664
9748
  }, [
9665
9749
  mode,
9666
9750
  selectedEndpoint,
9667
- endpointNames,
9668
- endpointDescs,
9669
- endpointTags,
9670
- endpointParams,
9671
- endpointResponseParams,
9751
+ viewModeApi,
9672
9752
  setSelectedEndpoint
9673
9753
  ]);
9754
+ (0, react$1.useEffect)(() => {
9755
+ if (!selectedApi || !transformedData?.length) return;
9756
+ const rebuilt = buildTreeDataStructure(mode === "view" && viewModeApi ? transformedData.map((api) => api.contextPath === selectedApi.contextPath ? viewModeApi : api) : transformedData);
9757
+ if (JSON.stringify(rebuilt) !== JSON.stringify(builtTreeData)) setBuiltTreeData(rebuilt);
9758
+ }, [
9759
+ mode,
9760
+ viewModeApi,
9761
+ transformedData,
9762
+ selectedApi,
9763
+ builtTreeData,
9764
+ setBuiltTreeData
9765
+ ]);
9674
9766
  const handleAddTag = (tag) => {
9675
9767
  const newTag = {
9676
9768
  name: tag.name,