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

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) => {
@@ -9283,17 +9377,27 @@ const ConsoleDocumentationLayout = ({ data, preSelectedApi, handleVisitLandingPa
9283
9377
  const viewModeApi = (0, react$1.useMemo)(() => {
9284
9378
  if (!selectedApi) return null;
9285
9379
  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
- };
9380
+ return buildPatchedApi(selectedApi, {
9381
+ apiTitle: localApiName,
9382
+ apiDescription: localDescription,
9383
+ names: endpointNames,
9384
+ descs: endpointDescs,
9385
+ tags: endpointTags,
9386
+ params: endpointParams,
9387
+ responseParams: endpointResponseParams,
9388
+ responseBody: endpointResponseBody
9389
+ });
9292
9390
  }, [
9293
9391
  mode,
9294
9392
  selectedApi,
9295
9393
  localApiName,
9296
- localDescription
9394
+ localDescription,
9395
+ endpointNames,
9396
+ endpointDescs,
9397
+ endpointTags,
9398
+ endpointParams,
9399
+ endpointResponseParams,
9400
+ endpointResponseBody
9297
9401
  ]);
9298
9402
  (0, react$1.useEffect)(() => {
9299
9403
  return () => {
@@ -9619,58 +9723,32 @@ const ConsoleDocumentationLayout = ({ data, preSelectedApi, handleVisitLandingPa
9619
9723
  setBannerVisible(hasChanges);
9620
9724
  }, [hasChanges]);
9621
9725
  (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;
9726
+ if (mode !== "view" || !selectedEndpoint || !viewModeApi) return;
9727
+ const patched = Object.values(viewModeApi.tags ?? {}).flat().find((e) => e.id === selectedEndpoint.id);
9728
+ if (!patched) return;
9729
+ 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
9730
  setSelectedEndpoint({
9657
- ...selectedEndpoint,
9658
- summary: patchedSummary,
9659
- description: patchedDesc,
9660
- tags: patchedTags,
9661
- parameters: openApiParams,
9662
- responses: patchedResponses
9731
+ ...patched,
9732
+ parentApiId: selectedEndpoint.parentApiId
9663
9733
  });
9664
9734
  }, [
9665
9735
  mode,
9666
9736
  selectedEndpoint,
9667
- endpointNames,
9668
- endpointDescs,
9669
- endpointTags,
9670
- endpointParams,
9671
- endpointResponseParams,
9737
+ viewModeApi,
9672
9738
  setSelectedEndpoint
9673
9739
  ]);
9740
+ (0, react$1.useEffect)(() => {
9741
+ if (!selectedApi || !transformedData?.length) return;
9742
+ const rebuilt = buildTreeDataStructure(mode === "view" && viewModeApi ? transformedData.map((api) => api.contextPath === selectedApi.contextPath ? viewModeApi : api) : transformedData);
9743
+ if (JSON.stringify(rebuilt) !== JSON.stringify(builtTreeData)) setBuiltTreeData(rebuilt);
9744
+ }, [
9745
+ mode,
9746
+ viewModeApi,
9747
+ transformedData,
9748
+ selectedApi,
9749
+ builtTreeData,
9750
+ setBuiltTreeData
9751
+ ]);
9674
9752
  const handleAddTag = (tag) => {
9675
9753
  const newTag = {
9676
9754
  name: tag.name,