@digi-frontend/dgate-api-documentation 4.0.5 → 4.0.7

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.mjs CHANGED
@@ -2669,6 +2669,7 @@ const PARAM_IN_OPTIONS = [
2669
2669
  value: "path"
2670
2670
  }
2671
2671
  ];
2672
+ const RESPONSE_PARAM_IN_OPTIONS = PARAM_IN_OPTIONS.filter((o) => o.value === "header");
2672
2673
  const PARAM_TYPE_OPTIONS = [
2673
2674
  {
2674
2675
  label: "string",
@@ -2695,7 +2696,7 @@ const PARAM_TYPE_OPTIONS = [
2695
2696
  value: "object"
2696
2697
  }
2697
2698
  ];
2698
- const AddParameterDrawer = ({ open, onClose, onAdd, onEdit, mode = "add", initialValues }) => {
2699
+ const AddParameterDrawer = ({ open, onClose, onAdd, onEdit, mode = "add", initialValues, source }) => {
2699
2700
  const [form] = Form.useForm();
2700
2701
  const [messageApi, contextHolder] = message.useMessage();
2701
2702
  const [confirmModalOpen, setConfirmModalOpen] = useState(false);
@@ -2913,6 +2914,7 @@ const AddParameterDrawer = ({ open, onClose, onAdd, onEdit, mode = "add", initia
2913
2914
  }
2914
2915
  }));
2915
2916
  const isAddEnabled = mode === "edit" ? hasChanges : !!(nameValue?.trim() && inValue && typeValue);
2917
+ const paramInOptions = source === "response" ? RESPONSE_PARAM_IN_OPTIONS : PARAM_IN_OPTIONS;
2916
2918
  const resetForm = () => {
2917
2919
  form.resetFields();
2918
2920
  setEnumInput("");
@@ -3017,10 +3019,11 @@ const AddParameterDrawer = ({ open, onClose, onAdd, onEdit, mode = "add", initia
3017
3019
  className: cx("form-body"),
3018
3020
  initialValues: {
3019
3021
  required: true,
3020
- in: "query",
3022
+ in: source === "response" ? "header" : "query",
3021
3023
  type: "string"
3022
3024
  },
3023
- onValuesChange: () => {
3025
+ onValuesChange: (_changed, allValues) => {
3026
+ if (allValues.in === "path") form.setFieldValue("required", true);
3024
3027
  if (mode === "edit" && initialValues) {
3025
3028
  const current = form.getFieldsValue();
3026
3029
  setHasChanges(current.name !== initialValues.name || current.in !== initialValues.in || current.type !== initialValues.type || current.required !== initialValues.required || (current.description ?? "") !== (initialValues.description ?? "") || JSON.stringify(enumValues) !== JSON.stringify(initialValues.enum ?? []));
@@ -3065,7 +3068,7 @@ const AddParameterDrawer = ({ open, onClose, onAdd, onEdit, mode = "add", initia
3065
3068
  children: /* @__PURE__ */ jsx(Select, {
3066
3069
  size: "large",
3067
3070
  placeholder: "Select",
3068
- options: PARAM_IN_OPTIONS
3071
+ options: paramInOptions
3069
3072
  })
3070
3073
  }),
3071
3074
  /* @__PURE__ */ jsx(Form.Item, {
@@ -3092,12 +3095,20 @@ const AddParameterDrawer = ({ open, onClose, onAdd, onEdit, mode = "add", initia
3092
3095
  children: /* @__PURE__ */ jsxs("div", {
3093
3096
  className: cx("switch-row"),
3094
3097
  children: [/* @__PURE__ */ jsx(Switch, {
3095
- checked: requiredValue ?? true,
3098
+ checked: inValue === "path" ? true : requiredValue ?? true,
3099
+ disabled: inValue === "path",
3096
3100
  onChange: (checked) => form.setFieldValue("required", checked),
3097
- style: { backgroundColor: requiredValue ?? true ? token.colorPrimary : void 0 }
3098
- }), /* @__PURE__ */ jsx("span", {
3101
+ style: { backgroundColor: (inValue === "path" ? true : requiredValue ?? true) ? token.colorPrimary : void 0 }
3102
+ }), /* @__PURE__ */ jsxs("span", {
3099
3103
  className: cx("switch-label"),
3100
- children: "Required?"
3104
+ children: ["Required?", inValue === "path" && /* @__PURE__ */ jsx("span", {
3105
+ style: {
3106
+ color: token.colorTextTertiary,
3107
+ fontSize: 12,
3108
+ marginLeft: 4
3109
+ },
3110
+ children: "(Always required for path parameter)"
3111
+ })]
3101
3112
  })]
3102
3113
  })
3103
3114
  }),
@@ -3270,7 +3281,7 @@ const buildViewParamRows = (params) => params.map((p, idx) => ({
3270
3281
  description: p.description ?? "",
3271
3282
  enum: p.enum ?? []
3272
3283
  }));
3273
- const EndpointsSection = ({ endpointsByTag, collapsed = false, onToggleCollapse, endpointNames, endpointDescs, endpointTags, availableTags, onEndpointNameChange, onEndpointDescChange, onEndpointTagsChange, endpointParams, onAddParameter, onEditParameter, onDeleteParameter, endpointResponseParams, onAddResponseParameter, onEditResponseParameter, onDeleteResponseParameter, mode = "edit", selectedEndpointKey }) => {
3284
+ const EndpointsSection = ({ endpointsByTag, collapsed = false, onToggleCollapse, endpointNames, endpointDescs, endpointTags, availableTags, onEndpointNameChange, onEndpointDescChange, onEndpointTagsChange, endpointParams, onAddParameter, onEditParameter, onDeleteParameter, endpointResponseParams, onAddResponseParameter, onEditResponseParameter, onDeleteResponseParameter, onRequestContentChange, onResponseContentChange, requestBodySchemas, responseBodySchemas, mode = "edit", selectedEndpointKey }) => {
3274
3285
  const [expandedId, setExpandedId] = useState(null);
3275
3286
  const [activeTab, setActiveTab] = useState("general");
3276
3287
  useEffect(() => {
@@ -3311,6 +3322,48 @@ const EndpointsSection = ({ endpointsByTag, collapsed = false, onToggleCollapse,
3311
3322
  const [showResponseSearch, setShowResponseSearch] = useState({});
3312
3323
  const debouncedRequestSearches = useDebounce(requestSearches);
3313
3324
  const debouncedResponseSearches = useDebounce(responseSearches);
3325
+ const [editableRequestContent, setEditableRequestContent] = useState({});
3326
+ const [editableResponseContent, setEditableResponseContent] = useState({});
3327
+ useEffect(() => {
3328
+ if (!openRequestPanels.size) return;
3329
+ openRequestPanels.forEach((epId) => {
3330
+ if (editableRequestContent[epId] !== void 0) return;
3331
+ const val = requestBodySchemas?.[epId];
3332
+ const json = val ? JSON.stringify(val, null, 2) : "";
3333
+ setEditableRequestContent((prev) => ({
3334
+ ...prev,
3335
+ [epId]: json
3336
+ }));
3337
+ });
3338
+ }, [openRequestPanels, requestBodySchemas]);
3339
+ useEffect(() => {
3340
+ if (!openResponsePanels.size) return;
3341
+ openResponsePanels.forEach((epId) => {
3342
+ if (editableResponseContent[epId] !== void 0) return;
3343
+ const val = responseBodySchemas?.[epId];
3344
+ const json = val ? JSON.stringify(val, null, 2) : "";
3345
+ setEditableResponseContent((prev) => ({
3346
+ ...prev,
3347
+ [epId]: json
3348
+ }));
3349
+ });
3350
+ }, [openResponsePanels, responseBodySchemas]);
3351
+ const handleValidate = (content) => {
3352
+ try {
3353
+ JSON.parse(content);
3354
+ message.success("Definition is valid JSON.");
3355
+ } catch {
3356
+ message.error("Invalid JSON definition.");
3357
+ }
3358
+ };
3359
+ const handleBeautify = (content, setter) => {
3360
+ try {
3361
+ const parsed = JSON.parse(content);
3362
+ setter(JSON.stringify(parsed, null, 2));
3363
+ } catch {
3364
+ message.error("Could not beautify — content is not valid JSON.");
3365
+ }
3366
+ };
3314
3367
  const { selectNodeByKey } = useNodeSelection();
3315
3368
  const { token: antdToken } = theme.useToken();
3316
3369
  const isMobile = !useBreakpoint$2().md;
@@ -3465,6 +3518,7 @@ const EndpointsSection = ({ endpointsByTag, collapsed = false, onToggleCollapse,
3465
3518
  userSelect: "none",
3466
3519
  "&:hover": { background: token.colorFillTertiary }
3467
3520
  },
3521
+ [scope("param-row--open")]: { borderRadius: `${token.borderRadius}px ${token.borderRadius}px 0 0` },
3468
3522
  [scope("param-row-icon")]: {
3469
3523
  fontSize: 12,
3470
3524
  transition: "transform 0.2s"
@@ -3472,10 +3526,13 @@ const EndpointsSection = ({ endpointsByTag, collapsed = false, onToggleCollapse,
3472
3526
  [scope("param-row-icon--open")]: { transform: "rotate(180deg)" },
3473
3527
  [scope("code-panel")]: {
3474
3528
  width: "100%",
3475
- overflow: "hidden"
3529
+ overflow: "hidden",
3530
+ background: "#1D2856",
3531
+ borderBottomLeftRadius: 8,
3532
+ borderBottomRightRadius: 8
3476
3533
  },
3477
3534
  [scope("code-area")]: {
3478
- background: token.colorBgSpotlight,
3535
+ background: "#1D2856",
3479
3536
  padding: "10px 12px",
3480
3537
  fontFamily: "Cairo, sans-serif",
3481
3538
  fontSize: 14,
@@ -3487,7 +3544,7 @@ const EndpointsSection = ({ endpointsByTag, collapsed = false, onToggleCollapse,
3487
3544
  display: "block"
3488
3545
  },
3489
3546
  [scope("code-footer")]: {
3490
- background: token.colorBgSpotlight,
3547
+ background: "#161D40",
3491
3548
  padding: 12,
3492
3549
  borderBottomLeftRadius: 8,
3493
3550
  borderBottomRightRadius: 8,
@@ -4471,8 +4528,8 @@ const EndpointsSection = ({ endpointsByTag, collapsed = false, onToggleCollapse,
4471
4528
  className: cx("pagination")
4472
4529
  })] });
4473
4530
  })(),
4474
- /* @__PURE__ */ jsxs("div", {
4475
- className: cx("param-row"),
4531
+ !["GET", "DELETE"].includes(ep.method) && /* @__PURE__ */ jsxs("div", {
4532
+ className: cx("param-row", openRequestPanels.has(ep.id) ? "param-row--open" : ""),
4476
4533
  style: { marginTop: token.margin },
4477
4534
  onClick: () => toggleRequestPanel(ep.id),
4478
4535
  children: [/* @__PURE__ */ jsx(DownOutlined, { className: cx("param-row-icon", openRequestPanels.has(ep.id) ? "param-row-icon--open" : "") }), /* @__PURE__ */ jsxs("span", {
@@ -4483,29 +4540,43 @@ const EndpointsSection = ({ endpointsByTag, collapsed = false, onToggleCollapse,
4483
4540
  })]
4484
4541
  })]
4485
4542
  }),
4486
- openRequestPanels.has(ep.id) && /* @__PURE__ */ jsxs("div", {
4543
+ !["GET", "DELETE"].includes(ep.method) && openRequestPanels.has(ep.id) && /* @__PURE__ */ jsxs("div", {
4487
4544
  className: cx("code-panel"),
4488
- children: [/* @__PURE__ */ jsx("code", {
4489
- className: cx("code-area"),
4490
- children: JSON.stringify((endpointParams[ep.id] ?? []).map((p) => ({
4491
- name: p.name,
4492
- in: p.in,
4493
- type: p.type,
4494
- required: p.required,
4495
- ...p.description ? { description: p.description } : {},
4496
- ...p.enum && p.enum.length > 0 ? { enum: p.enum } : {}
4497
- })), null, 2)
4545
+ children: [/* @__PURE__ */ jsx(Input.TextArea, {
4546
+ value: editableRequestContent[ep.id] ?? "",
4547
+ onChange: (e) => {
4548
+ setEditableRequestContent((prev) => ({
4549
+ ...prev,
4550
+ [ep.id]: e.target.value
4551
+ }));
4552
+ onRequestContentChange?.(ep.id, e.target.value);
4553
+ },
4554
+ rows: Math.max(3, (editableRequestContent[ep.id] ?? "").split("\n").length),
4555
+ style: {
4556
+ fontFamily: "monospace",
4557
+ fontSize: "0.75rem",
4558
+ background: "#1D2856",
4559
+ color: "#fff",
4560
+ outline: "none",
4561
+ boxShadow: "none",
4562
+ border: "none"
4563
+ }
4498
4564
  }), /* @__PURE__ */ jsxs("div", {
4499
4565
  className: cx("code-footer"),
4500
4566
  children: [/* @__PURE__ */ jsx(Button, {
4501
4567
  ghost: true,
4502
4568
  size: "small",
4503
4569
  className: cx("code-btn"),
4570
+ onClick: () => handleValidate(editableRequestContent[ep.id] ?? ""),
4504
4571
  children: "Validate"
4505
4572
  }), /* @__PURE__ */ jsx(Button, {
4506
4573
  ghost: true,
4507
4574
  size: "small",
4508
4575
  className: cx("code-btn"),
4576
+ onClick: () => handleBeautify(editableRequestContent[ep.id] ?? "", (v) => setEditableRequestContent((prev) => ({
4577
+ ...prev,
4578
+ [ep.id]: v
4579
+ }))),
4509
4580
  children: "Beautify"
4510
4581
  })]
4511
4582
  })]
@@ -4931,7 +5002,7 @@ const EndpointsSection = ({ endpointsByTag, collapsed = false, onToggleCollapse,
4931
5002
  })] });
4932
5003
  })(),
4933
5004
  /* @__PURE__ */ jsxs("div", {
4934
- className: cx("param-row"),
5005
+ className: cx("param-row", openResponsePanels.has(ep.id) ? "param-row--open" : ""),
4935
5006
  style: { marginTop: token.margin },
4936
5007
  onClick: () => toggleResponsePanel(ep.id),
4937
5008
  children: [
@@ -4951,27 +5022,41 @@ const EndpointsSection = ({ endpointsByTag, collapsed = false, onToggleCollapse,
4951
5022
  }),
4952
5023
  openResponsePanels.has(ep.id) && /* @__PURE__ */ jsxs("div", {
4953
5024
  className: cx("code-panel"),
4954
- children: [/* @__PURE__ */ jsx("code", {
4955
- className: cx("code-area"),
4956
- children: JSON.stringify((endpointResponseParams[ep.id] ?? []).map((p) => ({
4957
- name: p.name,
4958
- in: p.in,
4959
- type: p.type,
4960
- required: p.required,
4961
- ...p.description ? { description: p.description } : {},
4962
- ...p.enum && p.enum.length > 0 ? { enum: p.enum } : {}
4963
- })), null, 2)
5025
+ children: [/* @__PURE__ */ jsx(Input.TextArea, {
5026
+ value: editableResponseContent[ep.id] ?? "",
5027
+ onChange: (e) => {
5028
+ setEditableResponseContent((prev) => ({
5029
+ ...prev,
5030
+ [ep.id]: e.target.value
5031
+ }));
5032
+ onResponseContentChange?.(ep.id, e.target.value);
5033
+ },
5034
+ rows: Math.max(3, (editableResponseContent[ep.id] ?? "").split("\n").length),
5035
+ style: {
5036
+ fontFamily: "monospace",
5037
+ fontSize: "0.75rem",
5038
+ background: "#1D2856",
5039
+ color: "#fff",
5040
+ outline: "none",
5041
+ boxShadow: "none",
5042
+ border: "none"
5043
+ }
4964
5044
  }), /* @__PURE__ */ jsxs("div", {
4965
5045
  className: cx("code-footer"),
4966
5046
  children: [/* @__PURE__ */ jsx(Button, {
4967
5047
  ghost: true,
4968
5048
  size: "small",
4969
5049
  className: cx("code-btn"),
5050
+ onClick: () => handleValidate(editableResponseContent[ep.id] ?? ""),
4970
5051
  children: "Validate"
4971
5052
  }), /* @__PURE__ */ jsx(Button, {
4972
5053
  ghost: true,
4973
5054
  size: "small",
4974
5055
  className: cx("code-btn"),
5056
+ onClick: () => handleBeautify(editableResponseContent[ep.id] ?? "", (v) => setEditableResponseContent((prev) => ({
5057
+ ...prev,
5058
+ [ep.id]: v
5059
+ }))),
4975
5060
  children: "Beautify"
4976
5061
  })]
4977
5062
  })]
@@ -5118,7 +5203,8 @@ const EndpointsSection = ({ endpointsByTag, collapsed = false, onToggleCollapse,
5118
5203
  setParamDrawerEndpointId(null);
5119
5204
  setParamDrawerMode("add");
5120
5205
  setEditParamIdx(null);
5121
- }
5206
+ },
5207
+ source: drawerSource
5122
5208
  })
5123
5209
  ]
5124
5210
  }));
@@ -5707,8 +5793,8 @@ const EndpointsSection = ({ endpointsByTag, collapsed = false, onToggleCollapse,
5707
5793
  className: cx("pagination")
5708
5794
  })] });
5709
5795
  })(),
5710
- /* @__PURE__ */ jsxs("div", {
5711
- className: cx("param-row"),
5796
+ !["GET", "DELETE"].includes(ep.method) && /* @__PURE__ */ jsxs("div", {
5797
+ className: cx("param-row", openRequestPanels.has(ep.id) ? "param-row--open" : ""),
5712
5798
  style: { marginTop: token.margin },
5713
5799
  onClick: () => toggleRequestPanel(ep.id),
5714
5800
  children: [/* @__PURE__ */ jsx(DownOutlined, { className: cx("param-row-icon", openRequestPanels.has(ep.id) ? "param-row-icon--open" : "") }), /* @__PURE__ */ jsxs("span", {
@@ -5719,29 +5805,43 @@ const EndpointsSection = ({ endpointsByTag, collapsed = false, onToggleCollapse,
5719
5805
  })]
5720
5806
  })]
5721
5807
  }),
5722
- openRequestPanels.has(ep.id) && /* @__PURE__ */ jsxs("div", {
5808
+ !["GET", "DELETE"].includes(ep.method) && openRequestPanels.has(ep.id) && /* @__PURE__ */ jsxs("div", {
5723
5809
  className: cx("code-panel"),
5724
- children: [/* @__PURE__ */ jsx("code", {
5725
- className: cx("code-area"),
5726
- children: JSON.stringify((endpointParams[ep.id] ?? []).map((p) => ({
5727
- name: p.name,
5728
- in: p.in,
5729
- type: p.type,
5730
- required: p.required,
5731
- ...p.description ? { description: p.description } : {},
5732
- ...p.enum && p.enum.length > 0 ? { enum: p.enum } : {}
5733
- })), null, 2)
5810
+ children: [/* @__PURE__ */ jsx(Input.TextArea, {
5811
+ value: editableRequestContent[ep.id] ?? "",
5812
+ onChange: (e) => {
5813
+ setEditableRequestContent((prev) => ({
5814
+ ...prev,
5815
+ [ep.id]: e.target.value
5816
+ }));
5817
+ onRequestContentChange?.(ep.id, e.target.value);
5818
+ },
5819
+ rows: Math.max(3, (editableRequestContent[ep.id] ?? "").split("\n").length),
5820
+ style: {
5821
+ fontFamily: "monospace",
5822
+ fontSize: "0.75rem",
5823
+ background: "#1D2856",
5824
+ color: "#fff",
5825
+ outline: "none",
5826
+ boxShadow: "none",
5827
+ border: "none"
5828
+ }
5734
5829
  }), /* @__PURE__ */ jsxs("div", {
5735
5830
  className: cx("code-footer"),
5736
5831
  children: [/* @__PURE__ */ jsx(Button, {
5737
5832
  ghost: true,
5738
5833
  size: "small",
5739
5834
  className: cx("code-btn"),
5835
+ onClick: () => handleValidate(editableRequestContent[ep.id] ?? ""),
5740
5836
  children: "Validate"
5741
5837
  }), /* @__PURE__ */ jsx(Button, {
5742
5838
  ghost: true,
5743
5839
  size: "small",
5744
5840
  className: cx("code-btn"),
5841
+ onClick: () => handleBeautify(editableRequestContent[ep.id] ?? "", (v) => setEditableRequestContent((prev) => ({
5842
+ ...prev,
5843
+ [ep.id]: v
5844
+ }))),
5745
5845
  children: "Beautify"
5746
5846
  })]
5747
5847
  })]
@@ -6165,7 +6265,7 @@ const EndpointsSection = ({ endpointsByTag, collapsed = false, onToggleCollapse,
6165
6265
  })] });
6166
6266
  })(),
6167
6267
  /* @__PURE__ */ jsxs("div", {
6168
- className: cx("param-row"),
6268
+ className: cx("param-row", openResponsePanels.has(ep.id) ? "param-row--open" : ""),
6169
6269
  style: { marginTop: token.margin },
6170
6270
  onClick: () => toggleResponsePanel(ep.id),
6171
6271
  children: [
@@ -6185,27 +6285,41 @@ const EndpointsSection = ({ endpointsByTag, collapsed = false, onToggleCollapse,
6185
6285
  }),
6186
6286
  openResponsePanels.has(ep.id) && /* @__PURE__ */ jsxs("div", {
6187
6287
  className: cx("code-panel"),
6188
- children: [/* @__PURE__ */ jsx("code", {
6189
- className: cx("code-area"),
6190
- children: JSON.stringify((endpointResponseParams[ep.id] ?? []).map((p) => ({
6191
- name: p.name,
6192
- in: p.in,
6193
- type: p.type,
6194
- required: p.required,
6195
- ...p.description ? { description: p.description } : {},
6196
- ...p.enum && p.enum.length > 0 ? { enum: p.enum } : {}
6197
- })), null, 2)
6288
+ children: [/* @__PURE__ */ jsx(Input.TextArea, {
6289
+ value: editableResponseContent[ep.id] ?? "",
6290
+ onChange: (e) => {
6291
+ setEditableResponseContent((prev) => ({
6292
+ ...prev,
6293
+ [ep.id]: e.target.value
6294
+ }));
6295
+ onResponseContentChange?.(ep.id, e.target.value);
6296
+ },
6297
+ rows: Math.max(3, (editableResponseContent[ep.id] ?? "").split("\n").length),
6298
+ style: {
6299
+ fontFamily: "monospace",
6300
+ fontSize: "0.75rem",
6301
+ background: "#1D2856",
6302
+ color: "#fff",
6303
+ outline: "none",
6304
+ boxShadow: "none",
6305
+ border: "none"
6306
+ }
6198
6307
  }), /* @__PURE__ */ jsxs("div", {
6199
6308
  className: cx("code-footer"),
6200
6309
  children: [/* @__PURE__ */ jsx(Button, {
6201
6310
  ghost: true,
6202
6311
  size: "small",
6203
6312
  className: cx("code-btn"),
6313
+ onClick: () => handleValidate(editableResponseContent[ep.id] ?? ""),
6204
6314
  children: "Validate"
6205
6315
  }), /* @__PURE__ */ jsx(Button, {
6206
6316
  ghost: true,
6207
6317
  size: "small",
6208
6318
  className: cx("code-btn"),
6319
+ onClick: () => handleBeautify(editableResponseContent[ep.id] ?? "", (v) => setEditableResponseContent((prev) => ({
6320
+ ...prev,
6321
+ [ep.id]: v
6322
+ }))),
6209
6323
  children: "Beautify"
6210
6324
  })]
6211
6325
  })]
@@ -6354,7 +6468,8 @@ const EndpointsSection = ({ endpointsByTag, collapsed = false, onToggleCollapse,
6354
6468
  setParamDrawerEndpointId(null);
6355
6469
  setParamDrawerMode("add");
6356
6470
  setEditParamIdx(null);
6357
- }
6471
+ },
6472
+ source: drawerSource
6358
6473
  })
6359
6474
  ]
6360
6475
  }));
@@ -6856,9 +6971,9 @@ const TagsSection = ({ tags, collapsed, onToggleCollapse, onAddTag, onEditTag, o
6856
6971
  };
6857
6972
  //#endregion
6858
6973
  //#region src/view/components/ApiPage/components/AddTagDrawer.tsx
6859
- const TAG_NAME_REGEX = /^[A-Za-z0-9_-]+$/;
6860
- const TAG_DESC_REGEX = /^[A-Za-z0-9_-]+$/;
6861
- const EXT_DESC_REGEX = /^[A-Za-z0-9_-]+$/;
6974
+ const TAG_NAME_REGEX = /^[A-Za-z0-9_\s-]+$/;
6975
+ const TAG_DESC_REGEX = /^[A-Za-z0-9_\s-]+$/;
6976
+ const EXTERNAL_DOCS_DESC_REGEX = /^[A-Za-z0-9_\s-]+$/;
6862
6977
  const AddTagDrawer = ({ open, onClose, mode, initialValues, onAddTag, onEditTag }) => {
6863
6978
  const [form] = Form.useForm();
6864
6979
  const [messageApi, contextHolder] = message.useMessage();
@@ -7099,7 +7214,7 @@ const AddTagDrawer = ({ open, onClose, mode, initialValues, onAddTag, onEditTag
7099
7214
  },
7100
7215
  {
7101
7216
  pattern: TAG_NAME_REGEX,
7102
- message: "Only letters, numbers, underscores, and hyphens"
7217
+ message: "Only letters, numbers, spaces, underscores, and hyphens"
7103
7218
  }
7104
7219
  ],
7105
7220
  children: /* @__PURE__ */ jsx(Input, {
@@ -7120,10 +7235,10 @@ const AddTagDrawer = ({ open, onClose, mode, initialValues, onAddTag, onEditTag
7120
7235
  rules: [{
7121
7236
  max: 50,
7122
7237
  message: "Maximum 50 characters"
7123
- }, { validator: (_, value) => {
7124
- if (!value || TAG_DESC_REGEX.test(value)) return Promise.resolve();
7125
- return Promise.reject(/* @__PURE__ */ new Error("Only letters, numbers, underscores, and hyphens"));
7126
- } }],
7238
+ }, {
7239
+ pattern: TAG_DESC_REGEX,
7240
+ message: "Only letters, numbers, spaces, _ and - allowed"
7241
+ }],
7127
7242
  children: /* @__PURE__ */ jsx(Input.TextArea, {
7128
7243
  showCount: true,
7129
7244
  maxLength: 50,
@@ -7143,10 +7258,10 @@ const AddTagDrawer = ({ open, onClose, mode, initialValues, onAddTag, onEditTag
7143
7258
  rules: [{
7144
7259
  max: 25,
7145
7260
  message: "Maximum 25 characters"
7146
- }, { validator: (_, value) => {
7147
- if (!value || EXT_DESC_REGEX.test(value)) return Promise.resolve();
7148
- return Promise.reject(/* @__PURE__ */ new Error("Only letters, numbers, underscores, and hyphens"));
7149
- } }],
7261
+ }, {
7262
+ pattern: EXTERNAL_DOCS_DESC_REGEX,
7263
+ message: "Only letters, numbers, spaces, _ and - allowed"
7264
+ }],
7150
7265
  children: /* @__PURE__ */ jsx(Input, {
7151
7266
  showCount: true,
7152
7267
  maxLength: 25,
@@ -7168,8 +7283,8 @@ const AddTagDrawer = ({ open, onClose, mode, initialValues, onAddTag, onEditTag
7168
7283
  children: "External Docs Link"
7169
7284
  }),
7170
7285
  rules: [{
7171
- max: 512,
7172
- message: "Maximum 512 characters"
7286
+ max: 500,
7287
+ message: "Maximum 500 characters"
7173
7288
  }, { validator: async () => {
7174
7289
  const desc = form.getFieldValue("externalDocsDescription");
7175
7290
  const link = form.getFieldValue("externalDocsLink");
@@ -8505,7 +8620,7 @@ const Codebox$1 = ({ code, language, wrapLongLines }) => {
8505
8620
  //#endregion
8506
8621
  //#region src/view/console/CodeboxSidebar.tsx
8507
8622
  function CodeboxSidebar$1() {
8508
- const { selectedEndpoint, selectedApi, activeRequestTab, selectedStatusCode, statusCodeOptions, setSelectedStatusCode } = useStore(({ view }) => view);
8623
+ const { selectedEndpoint, selectedApi, selectedStatusCode, statusCodeOptions, setSelectedStatusCode } = useStore(({ view }) => view);
8509
8624
  const httpStatusOptions = useMemo(() => statusCodeOptions.map((code) => ({
8510
8625
  value: code,
8511
8626
  label: /* @__PURE__ */ jsxs("span", {
@@ -8538,7 +8653,7 @@ function CodeboxSidebar$1() {
8538
8653
  const queryParams = params.filter((p) => p.in === "query");
8539
8654
  return [`curl --location '${serverUrl}${resolvedPath}${queryParams.length > 0 ? "?" + queryParams.map((p) => `${p.name}=sample-value`).join("&") : ""}'`, ...params.filter((p) => p.in === "header").map((p) => `--header '${p.name}: sample-value'`)];
8540
8655
  })();
8541
- const hasActiveTabParams = (selectedEndpoint?.parameters ?? []).some((p) => p.in === activeRequestTab);
8656
+ const hasAnyParams = (selectedEndpoint?.parameters ?? []).some((p) => p.in === "header" || p.in === "path" || p.in === "query");
8542
8657
  const { token: antdToken, theme: themeConfig } = theme.useToken();
8543
8658
  const isDark = themeConfig.id == 1;
8544
8659
  const headerBg = isDark ? antdToken.colorBgElevated : "#1d2856";
@@ -8660,7 +8775,7 @@ function CodeboxSidebar$1() {
8660
8775
  }));
8661
8776
  return /* @__PURE__ */ jsxs("div", {
8662
8777
  className: cx("container"),
8663
- children: [hasActiveTabParams && /* @__PURE__ */ jsxs("div", {
8778
+ children: [hasAnyParams && /* @__PURE__ */ jsxs("div", {
8664
8779
  className: cx("rightCard", "rightCardRequest"),
8665
8780
  children: [/* @__PURE__ */ jsxs("div", {
8666
8781
  className: cx("rightCardHeader"),
@@ -8827,7 +8942,7 @@ const ConsoleDocumentationLayout = ({ data, preSelectedApi, handleVisitLandingPa
8827
8942
  const [apiNameTouched, setApiNameTouched] = useState(false);
8828
8943
  const [localDescription, setLocalDescription] = useState("");
8829
8944
  const [descriptionTouched, setDescriptionTouched] = useState(false);
8830
- const hasApiNameError = apiNameTouched && (!localApiName.trim() || !/^[A-Za-z0-9_-]+$/.test(localApiName.trim()));
8945
+ const hasApiNameError = apiNameTouched && (!localApiName.trim() || !/^[A-Za-z0-9_\s-]+$/.test(localApiName.trim()));
8831
8946
  const hasDescriptionError = descriptionTouched && !localDescription.trim();
8832
8947
  const hasGeneralError = hasApiNameError || hasDescriptionError;
8833
8948
  const [saveErrors, setSaveErrors] = useState([]);
@@ -8837,6 +8952,8 @@ const ConsoleDocumentationLayout = ({ data, preSelectedApi, handleVisitLandingPa
8837
8952
  const [endpointTags, setEndpointTags] = useState({});
8838
8953
  const [endpointParams, setEndpointParams] = useState({});
8839
8954
  const [endpointResponseParams, setEndpointResponseParams] = useState({});
8955
+ const [endpointRequestBody, setEndpointRequestBody] = useState({});
8956
+ const [endpointResponseBody, setEndpointResponseBody] = useState({});
8840
8957
  const [tagDrawerState, setTagDrawerState] = useState({
8841
8958
  open: false,
8842
8959
  mode: "add"
@@ -8847,7 +8964,7 @@ const ConsoleDocumentationLayout = ({ data, preSelectedApi, handleVisitLandingPa
8847
8964
  });
8848
8965
  const [localTags, setLocalTags] = useState([]);
8849
8966
  const [messageApi, contextHolder] = message.useMessage();
8850
- const { focusedContent, selectedNodeKey, selectedApi, originalData, builtTreeData, selectedEndpoint, setOriginalData, setTransformedData, setBuiltTreeData, setFocusedContent, setExpandedKeys, setSelectedEndpoint } = useStore(({ view }) => view);
8967
+ const { focusedContent, selectedNodeKey, selectedApi, originalData, transformedData, builtTreeData, selectedEndpoint, setOriginalData, setTransformedData, setBuiltTreeData, setSelectedApi, setFocusedContent, setExpandedKeys, setSelectedEndpoint } = useStore(({ view }) => view);
8851
8968
  const { selectFirstApi, selectPreSelectedApi, clearSelection } = useNodeSelection();
8852
8969
  const hasInitializedRef = useRef(false);
8853
8970
  const { useBreakpoint } = Grid;
@@ -9071,10 +9188,50 @@ const ConsoleDocumentationLayout = ({ data, preSelectedApi, handleVisitLandingPa
9071
9188
  });
9072
9189
  return result;
9073
9190
  }, [originalData, selectedApi]);
9191
+ const initialEndpointRequestBody = useMemo(() => {
9192
+ if (!originalData || !selectedApi) return {};
9193
+ const rawFile = originalData.find((f) => Object.keys(f.paths)[0] === selectedApi.contextPath);
9194
+ if (!rawFile) return {};
9195
+ const pathMethodToId = {};
9196
+ Object.values(selectedApi.tags).flat().forEach((ep) => {
9197
+ pathMethodToId[`${ep.path}||${ep.method.toLowerCase()}`] = ep.id;
9198
+ });
9199
+ const result = {};
9200
+ Object.entries(rawFile.paths).forEach(([path, methods]) => {
9201
+ Object.entries(methods).forEach(([method, operation]) => {
9202
+ const schema = operation.requestBody?.content?.["application/json"]?.schema;
9203
+ const epId = pathMethodToId[`${path}||${method}`];
9204
+ if (epId && schema) result[epId] = schema;
9205
+ });
9206
+ });
9207
+ return result;
9208
+ }, [originalData, selectedApi]);
9209
+ const initialEndpointResponseBody = useMemo(() => {
9210
+ if (!originalData || !selectedApi) return {};
9211
+ const rawFile = originalData.find((f) => Object.keys(f.paths)[0] === selectedApi.contextPath);
9212
+ if (!rawFile) return {};
9213
+ const pathMethodToId = {};
9214
+ Object.values(selectedApi.tags).flat().forEach((ep) => {
9215
+ pathMethodToId[`${ep.path}||${ep.method.toLowerCase()}`] = ep.id;
9216
+ });
9217
+ const result = {};
9218
+ Object.entries(rawFile.paths).forEach(([path, methods]) => {
9219
+ Object.entries(methods).forEach(([method, operation]) => {
9220
+ const responses = operation.responses;
9221
+ if (!responses) return;
9222
+ const schema = responses["200" in responses ? "200" : Object.keys(responses)[0]]?.content?.["application/json"]?.schema;
9223
+ const epId = pathMethodToId[`${path}||${method}`];
9224
+ if (epId && schema) result[epId] = schema;
9225
+ });
9226
+ });
9227
+ return result;
9228
+ }, [originalData, selectedApi]);
9074
9229
  useEffect(() => {
9075
9230
  setLocalTags(tagMetadata);
9076
9231
  setEndpointParams(initialEndpointParams);
9077
9232
  setEndpointResponseParams(initialEndpointResponseParams);
9233
+ setEndpointRequestBody(initialEndpointRequestBody);
9234
+ setEndpointResponseBody(initialEndpointResponseBody);
9078
9235
  }, [selectedApi]);
9079
9236
  const hasChanges = useMemo(() => {
9080
9237
  if (!selectedApi) return false;
@@ -9289,11 +9446,45 @@ const ConsoleDocumentationLayout = ({ data, preSelectedApi, handleVisitLandingPa
9289
9446
  else delete methodObj["x-response-params"];
9290
9447
  }
9291
9448
  });
9449
+ Object.entries(endpointRequestBody).forEach(([id, schema]) => {
9450
+ const loc = idToPathMethod[id];
9451
+ if (!loc) return;
9452
+ const pathEntry = cloned.paths[loc.path];
9453
+ if (!pathEntry) return;
9454
+ const methodObj = pathEntry[loc.method];
9455
+ if (!methodObj) return;
9456
+ const methodObjAny = methodObj;
9457
+ if (!methodObjAny.requestBody) methodObjAny.requestBody = {};
9458
+ const rb = methodObjAny.requestBody;
9459
+ if (!rb.content) rb.content = {};
9460
+ rb.content["application/json"] = { schema };
9461
+ });
9462
+ Object.entries(endpointResponseBody).forEach(([id, schema]) => {
9463
+ const loc = idToPathMethod[id];
9464
+ if (!loc) return;
9465
+ const pathEntry = cloned.paths[loc.path];
9466
+ if (!pathEntry) return;
9467
+ const methodObj = pathEntry[loc.method];
9468
+ if (!methodObj) return;
9469
+ const methodObjAny = methodObj;
9470
+ if (!methodObjAny.responses) return;
9471
+ const responses = methodObjAny.responses;
9472
+ const statusCode = "200" in responses ? "200" : Object.keys(responses)[0];
9473
+ if (!responses[statusCode]) return;
9474
+ if (!responses[statusCode].content) responses[statusCode].content = {};
9475
+ responses[statusCode].content["application/json"] = { schema };
9476
+ });
9292
9477
  try {
9293
9478
  await onSave?.(cloned);
9294
9479
  setBannerVisible(false);
9295
9480
  setSaveErrors([]);
9296
9481
  messageApi.success("Changes have been saved and published successfully.");
9482
+ setOriginalData(originalData.map((f) => Object.keys(f.paths)[0] === selectedApi.contextPath ? cloned : f));
9483
+ const newTransformed = [cloned].map(transformOpenApiToDocs)[0];
9484
+ const newTransformedData = (transformedData ?? []).map((t) => t.contextPath === selectedApi.contextPath ? newTransformed : t);
9485
+ setTransformedData(newTransformedData);
9486
+ setBuiltTreeData(buildTreeDataStructure(newTransformedData) ?? []);
9487
+ setSelectedApi(newTransformed);
9297
9488
  } catch (err) {
9298
9489
  let messages = [];
9299
9490
  if (err && typeof err === "object" && "errors" in err) {
@@ -9628,7 +9819,29 @@ const ConsoleDocumentationLayout = ({ data, preSelectedApi, handleVisitLandingPa
9628
9819
  [endpointId]: prev[endpointId]?.filter((_, i) => i !== idx) ?? []
9629
9820
  }));
9630
9821
  setBannerVisible(true);
9631
- }
9822
+ },
9823
+ onRequestContentChange: (endpointId, jsonString) => {
9824
+ try {
9825
+ const schema = JSON.parse(jsonString);
9826
+ setEndpointRequestBody((prev) => ({
9827
+ ...prev,
9828
+ [endpointId]: schema
9829
+ }));
9830
+ setBannerVisible(true);
9831
+ } catch {}
9832
+ },
9833
+ onResponseContentChange: (endpointId, jsonString) => {
9834
+ try {
9835
+ const schema = JSON.parse(jsonString);
9836
+ setEndpointResponseBody((prev) => ({
9837
+ ...prev,
9838
+ [endpointId]: schema
9839
+ }));
9840
+ setBannerVisible(true);
9841
+ } catch {}
9842
+ },
9843
+ requestBodySchemas: endpointRequestBody,
9844
+ responseBodySchemas: endpointResponseBody
9632
9845
  }, resetKey)
9633
9846
  })
9634
9847
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -9767,7 +9980,29 @@ const ConsoleDocumentationLayout = ({ data, preSelectedApi, handleVisitLandingPa
9767
9980
  [endpointId]: prev[endpointId]?.filter((_, i) => i !== idx) ?? []
9768
9981
  }));
9769
9982
  setBannerVisible(true);
9770
- }
9983
+ },
9984
+ onRequestContentChange: (endpointId, jsonString) => {
9985
+ try {
9986
+ const schema = JSON.parse(jsonString);
9987
+ setEndpointRequestBody((prev) => ({
9988
+ ...prev,
9989
+ [endpointId]: schema
9990
+ }));
9991
+ setBannerVisible(true);
9992
+ } catch {}
9993
+ },
9994
+ onResponseContentChange: (endpointId, jsonString) => {
9995
+ try {
9996
+ const schema = JSON.parse(jsonString);
9997
+ setEndpointResponseBody((prev) => ({
9998
+ ...prev,
9999
+ [endpointId]: schema
10000
+ }));
10001
+ setBannerVisible(true);
10002
+ } catch {}
10003
+ },
10004
+ requestBodySchemas: endpointRequestBody,
10005
+ responseBodySchemas: endpointResponseBody
9771
10006
  }, resetKey)
9772
10007
  ] })
9773
10008
  })]