@digi-frontend/dgate-api-documentation 1.0.83 → 1.0.85

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/styles.css CHANGED
@@ -1583,11 +1583,14 @@ div.endBtnIcon {
1583
1583
  font-size: 1rem;
1584
1584
  line-height: 1.25rem;
1585
1585
  }
1586
+ .api_docs_header .search_filter_btn .btnContentWrapper .btnContent {
1587
+ font-size: 0.918rem !important;
1588
+ }
1586
1589
  .api_docs_header .search_filter_btn:hover:not(:disabled) {
1587
1590
  color: #000000 !important;
1588
1591
  }
1589
1592
  .api_docs_header .search_filter_btn:hover {
1590
- color: #000;
1593
+ color: #000 !important;
1591
1594
  }
1592
1595
  .api_docs_header .search_filter_btn svg {
1593
1596
  margin-left: 0.5rem;
@@ -1617,12 +1620,15 @@ div.endBtnIcon {
1617
1620
  border: none !important;
1618
1621
  box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
1619
1622
  padding: 0.4rem;
1620
- width: 9.4875rem;
1623
+ width: 10.4875rem;
1621
1624
  font-size: 1rem;
1622
1625
  font-weight: 400;
1623
1626
  line-height: 1.234rem;
1624
1627
  height: 2.25rem;
1625
1628
  }
1629
+ .api_docs_header .api_btn .btnContentWrapper .btnContent {
1630
+ font-size: 0.918rem !important;
1631
+ }
1626
1632
  .api_docs_header .api_btn:hover:not(:disabled) {
1627
1633
  color: #000000 !important;
1628
1634
  }
@@ -2253,60 +2259,70 @@ main .api-details-expanded h3 {
2253
2259
  margin-bottom: 0.5rem;
2254
2260
  }
2255
2261
  main .api-details-expanded .url-box {
2256
- height: 1.75rem;
2257
- justify-content: space-between;
2258
- background-color: #edf1fb !important;
2262
+ background-color: #edf1fb;
2263
+ padding: 0.375rem 0.75rem;
2264
+ border-radius: 0.5rem;
2265
+ display: flex;
2266
+ align-items: center;
2267
+ gap: 0.5rem;
2268
+ font-size: 14px;
2269
+ flex: 1;
2270
+ height: 2.8rem;
2271
+ margin-bottom: 1.5rem;
2272
+ overflow: hidden;
2273
+ }
2274
+ main .api-details-expanded .url-box_text-container {
2275
+ display: flex;
2276
+ align-items: center;
2277
+ flex: 1;
2278
+ overflow: hidden;
2259
2279
  }
2260
- main .api-details-expanded .url-text {
2280
+ main .api-details-expanded .url-box_text-container .url-text {
2261
2281
  color: #3b3f46;
2262
2282
  font-size: 1.25rem;
2263
- letter-spacing: 0px;
2264
2283
  line-height: 1.75rem;
2284
+ max-width: 100%;
2285
+ overflow: hidden;
2286
+ text-overflow: ellipsis;
2287
+ white-space: nowrap;
2288
+ flex: 1;
2265
2289
  }
2266
- main .api-details-expanded .method-label {
2267
- font-size: 0.924rem;
2268
- font-weight: 600;
2290
+ main .api-details-expanded .url-box_text-container .method-label {
2291
+ font-size: 1.25rem;
2269
2292
  padding: 0.125rem 0.5rem;
2270
2293
  border-radius: 0.375rem;
2271
2294
  text-transform: uppercase;
2272
2295
  color: #3aaa35;
2273
2296
  text-decoration: underline;
2274
2297
  }
2275
- main .api-details-expanded .method-label.get {
2298
+ main .api-details-expanded .url-box_text-container .method-label.get {
2276
2299
  color: #3a6cd1;
2277
2300
  }
2278
- main .api-details-expanded .method-label.post {
2301
+ main .api-details-expanded .url-box_text-container .method-label.post {
2279
2302
  color: #3aaa35;
2280
2303
  }
2281
- main .api-details-expanded .method-label.put {
2304
+ main .api-details-expanded .url-box_text-container .method-label.put {
2282
2305
  color: #faad14;
2283
2306
  }
2284
- main .api-details-expanded .method-label.patch {
2307
+ main .api-details-expanded .url-box_text-container .method-label.patch {
2285
2308
  color: #58e2c2;
2286
2309
  }
2287
- main .api-details-expanded .method-label.delete {
2310
+ main .api-details-expanded .url-box_text-container .method-label.delete {
2288
2311
  color: #da3f3f;
2289
2312
  }
2290
- main .api-details-expanded .method-label.head {
2313
+ main .api-details-expanded .url-box_text-container .method-label.head {
2291
2314
  color: #9461c9;
2292
2315
  }
2293
- main .api-details-expanded .method-label.trace {
2316
+ main .api-details-expanded .url-box_text-container .method-label.trace {
2294
2317
  color: #ffa28f;
2295
2318
  }
2296
- main .api-details-expanded .method-label.options {
2319
+ main .api-details-expanded .url-box_text-container .method-label.options {
2297
2320
  color: #495d97;
2298
2321
  }
2299
- main .api-details-expanded .url-box {
2300
- background-color: #f3f4f6;
2301
- padding: 0.375rem 0.75rem;
2302
- border-radius: 0.5rem;
2303
- display: flex;
2304
- align-items: center;
2305
- gap: 0.5rem;
2306
- font-size: 14px;
2307
- flex: 1;
2308
- height: 2.8rem;
2309
- margin-bottom: 1.5rem;
2322
+ main .api-details-expanded .url-box .copy-icon {
2323
+ cursor: pointer;
2324
+ width: 1.5rem;
2325
+ height: 1.5rem;
2310
2326
  }
2311
2327
  main .api-details-expanded .api-desc {
2312
2328
  color: #6b7280;
@@ -2427,9 +2443,4 @@ main .api-details-expanded .response-drop-test {
2427
2443
  justify-content: end !important;
2428
2444
  align-items: end !important;
2429
2445
  align-content: end !important;
2430
- }
2431
- main .api-details-expanded .copy-icon {
2432
- cursor: pointer;
2433
- width: 1.5rem;
2434
- height: 1.5rem;
2435
2446
  }
@@ -3,5 +3,5 @@ import { OpenAPIFile } from '@entities/openApi';
3
3
  import { TransformedOpenApi } from '@entities/transformedOpenApi';
4
4
  export declare const transformOpenApiObject: (openApiJson: OpenAPIFile) => TransformedOpenApi;
5
5
  export declare const transformOpenApiObjectToOrigin: (values: TransformedOpenApi) => OpenAPIFile;
6
- export declare const transformPathsToArray: (paths: OpenAPIFile["paths"]) => TransformedPathsArray | any;
6
+ export declare const transformPathsToArray: (openApiJson: OpenAPIFile) => TransformedPathsArray | any;
7
7
  export declare const transformPathsArrayToOrigin: (paths: TransformedPathsArray) => OpenAPIFile["paths"];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digi-frontend/dgate-api-documentation",
3
- "version": "1.0.83",
3
+ "version": "1.0.85",
4
4
  "main": "dist/src/index.js",
5
5
  "module": "dist/src/index.js",
6
6
  "types": "dist/types/index.d.ts",
@@ -76,6 +76,7 @@ const MethodsAccordion = ({
76
76
  const [enumFields, setEnumFields] = useState([])
77
77
  const [tooltipEnumRef, setTooltipEnumRef] = useState(null)
78
78
  const [currentResponseIndex, setCurrentResponseIndex] = useState<number>(-1)
79
+ const activeAccordionRef = useRef<HTMLDivElement | null>(null)
79
80
  const currentResponse =
80
81
  method.responses.find((res) => Number(res.code) === selectedStatusCode.value) || '{}'
81
82
  const indexRef = useRef(-1)
@@ -91,6 +92,12 @@ const MethodsAccordion = ({
91
92
  setTableData(newTableData)
92
93
  }
93
94
 
95
+ useEffect(() => {
96
+ if (isOpen && activeAccordionRef.current) {
97
+ activeAccordionRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' })
98
+ }
99
+ }, [isOpen])
100
+
94
101
  const generateResponseTableData = (headersObj: any, responseIndex: number) => {
95
102
  const headersByName = Object.keys(headersObj)
96
103
  return headersByName.map((item, index) => {
@@ -721,7 +728,7 @@ const MethodsAccordion = ({
721
728
  }, [tags, method])
722
729
 
723
730
  return (
724
- <div>
731
+ <div ref={activeAccordionRef}>
725
732
  <Accordion
726
733
  expanded={isOpen}
727
734
  onChange={() => setIsOpen(!isOpen)}
@@ -224,9 +224,9 @@ const ParamterTable = ({
224
224
  value: values.schema?.items?.type,
225
225
  }}
226
226
  errorMsg={!!errors?.schema?.items?.type && errors?.schema?.items?.type}
227
- onChange={(item) =>
227
+ onChange={(item) => {
228
228
  setFieldValue('schema.items.type', item?.value?.toLowerCase())
229
- } // Updates state on selection
229
+ }} // Updates state on selection
230
230
  options={[
231
231
  {
232
232
  list: [
@@ -2,6 +2,11 @@ import { TransformedPathsArray } from '@entities/layout.type'
2
2
  import { OpenAPIFile, SecurityScheme } from '@entities/openApi'
3
3
  import { TransformedOpenApi } from '@entities/transformedOpenApi'
4
4
 
5
+ const resolveRef = (ref: string, openApiJson: OpenAPIFile): Object => {
6
+ const parts = ref.replace(/^#\//, '').split('/')
7
+ return parts.reduce((obj, key) => obj?.[key], openApiJson)
8
+ }
9
+
5
10
  export const transformOpenApiObject = (openApiJson: OpenAPIFile): TransformedOpenApi => {
6
11
  if (openApiJson.components && openApiJson.components.securitySchemes) {
7
12
  const authKey = Object.keys(openApiJson.components.securitySchemes)?.at(0)
@@ -17,6 +22,7 @@ export const transformOpenApiObject = (openApiJson: OpenAPIFile): TransformedOpe
17
22
  scheme: 'public',
18
23
  },
19
24
  },
25
+ ...(openApiJson.components || {}),
20
26
  }
21
27
  }
22
28
 
@@ -26,7 +32,7 @@ export const transformOpenApiObject = (openApiJson: OpenAPIFile): TransformedOpe
26
32
 
27
33
  return {
28
34
  ...openApiJson,
29
- paths: transformPathsToArray(openApiJson.paths),
35
+ paths: transformPathsToArray(openApiJson),
30
36
  } as TransformedOpenApi
31
37
  }
32
38
 
@@ -50,7 +56,8 @@ export const transformOpenApiObjectToOrigin = (values: TransformedOpenApi): Open
50
56
  return object
51
57
  }
52
58
 
53
- export const transformPathsToArray = (paths: OpenAPIFile['paths']): TransformedPathsArray | any => {
59
+ export const transformPathsToArray = (openApiJson: OpenAPIFile): TransformedPathsArray | any => {
60
+ const paths: OpenAPIFile['paths'] = openApiJson.paths
54
61
  const transformedPaths = Object.entries(paths).map(([path, methods]) => ({
55
62
  path,
56
63
  methods: Object.entries(methods).map(([method, methodProps]) => {
@@ -61,20 +68,55 @@ export const transformPathsToArray = (paths: OpenAPIFile['paths']): TransformedP
61
68
  summary: methodProps.summary || '',
62
69
  responses: Object.entries(methodProps.responses).map(([code, codeProps]) => {
63
70
  const contentType = Object.keys(codeProps.content || {})[0]
64
- const headers = !codeProps?.headers ? {} : codeProps.headers
71
+ let headers = codeProps?.headers ?? {}
72
+
73
+ // ? Fix headers with items property
74
+ Object.keys(headers).map((header: string) => {
75
+ let headerObj = headers[header]
76
+ if (
77
+ headerObj?.schema &&
78
+ headerObj?.schema?.type &&
79
+ headerObj?.schema?.type != 'array'
80
+ ) {
81
+ delete headers[header]?.schema?.items
82
+ }
83
+ })
84
+
85
+ let schema = codeProps.content?.[contentType]?.schema
86
+ if (schema?.$ref) {
87
+ schema = resolveRef(schema?.$ref, openApiJson)
88
+ } else if (schema?.type == 'array' && schema?.items?.$ref) {
89
+ const resolvedItemSchema = resolveRef(schema.items.$ref, openApiJson)
90
+ schema = {
91
+ ...schema,
92
+ items: resolvedItemSchema,
93
+ }
94
+ }
95
+
65
96
  return {
66
97
  code,
67
98
  headers,
68
99
  content: {
69
100
  contentType,
70
101
  schema: {
71
- ...codeProps.content?.[contentType]?.schema,
72
- properties: JSON.stringify(codeProps.content?.[contentType]?.schema?.properties),
102
+ ...schema,
103
+ properties: JSON.stringify(schema?.properties || schema?.items?.properties),
73
104
  },
74
105
  },
75
106
  }
76
107
  }),
77
108
  }
109
+
110
+ if (!obj.responses.find((item) => item.code == '200')) {
111
+ obj.responses.push({
112
+ code: '200',
113
+ content: {
114
+ contentType: 'application/json',
115
+ schema: {},
116
+ },
117
+ headers: {},
118
+ })
119
+ }
78
120
  // Add parameters if it does not exist in the original JSON
79
121
  if (!methodProps?.parameters) {
80
122
  obj.parameters = []
@@ -84,14 +126,24 @@ export const transformPathsToArray = (paths: OpenAPIFile['paths']): TransformedP
84
126
 
85
127
  if (method.toLowerCase() != 'get') {
86
128
  const contentType = Object.keys(methodProps?.requestBody?.content || {})[0]
87
- const reqSchema = methodProps?.requestBody?.content?.schema
88
- const requestBodyData = methodProps?.requestBody?.content?.schema?.properties
129
+ let reqSchema = methodProps?.requestBody?.content?.[contentType]?.schema
130
+
131
+ if (reqSchema?.$ref) {
132
+ reqSchema = resolveRef(reqSchema.$ref, openApiJson)
133
+ } else if (reqSchema?.type === 'array' && reqSchema.items?.$ref) {
134
+ reqSchema = {
135
+ ...reqSchema,
136
+ items: resolveRef(reqSchema.items.$ref, openApiJson),
137
+ }
138
+ }
139
+
140
+ const requestBodyData = reqSchema
89
141
  ? {
90
142
  content: {
91
143
  contentType,
92
144
  schema: {
93
145
  ...reqSchema,
94
- properties: reqSchema?.properties ? JSON.stringify(reqSchema?.properties) : '{}',
146
+ properties: JSON.stringify(reqSchema?.properties || reqSchema?.items?.properties),
95
147
  },
96
148
  },
97
149
  }
@@ -128,8 +180,18 @@ export const transformPathsArrayToOrigin = (paths: TransformedPathsArray): OpenA
128
180
  acc[path] = methods.reduce(
129
181
  (methodAcc, { type, tags, responses, summary, requestBody, ...rest }) => {
130
182
  // Initialize the method object
183
+ // ? Validate (rest) [parameters]
184
+ let copiedRest = structuredClone(rest || {})
185
+ if (copiedRest && copiedRest.parameters) {
186
+ copiedRest.parameters.map((param) => {
187
+ if (param && param?.schema?.items && param?.schema?.items?.type == 'array') {
188
+ param.schema.items.items = {}
189
+ }
190
+ return param
191
+ })
192
+ }
131
193
  methodAcc[type] = {
132
- ...rest,
194
+ ...copiedRest,
133
195
  tags,
134
196
  summary,
135
197
  responses: responses.reduce((respAcc, { code, content, headers }) => {
@@ -6,7 +6,7 @@ import {
6
6
  RequestOption,
7
7
  } from '../../../../assets/icons/index'
8
8
  import { SelectGroup } from 'digitinary-ui'
9
- import { useEffect, useState } from 'react'
9
+ import { useEffect, useMemo, useState } from 'react'
10
10
  import { EndpointData, OverviewData } from 'src/layout/docsLayout'
11
11
  import { handleStatusColor } from '../../../../helpers/methodAccordion.helper'
12
12
  import { httpStatusCodes } from '../../../../constants/index'
@@ -27,6 +27,13 @@ export const EndpointPage = ({
27
27
  }) => {
28
28
  const [activeTab, setActiveTab] = useState('header')
29
29
  const { toggleSection } = useSectionToggle()
30
+ const fullUrl = useMemo(() => {
31
+ // env gateway url + api version(if appended) + context path
32
+ const url = data.api?.servers?.filter((s) => s.url !== '/')[0]?.url
33
+ const pathParts = data?.path.split('/').slice(2) // slice from index 2 to skip the first empty "" and "comments"
34
+ const fullPath = !!pathParts?.length ? '/' + pathParts.join('/') : '' // this will contain the full path without the context path
35
+ return `${url}${fullPath}`
36
+ }, [data])
30
37
 
31
38
  const httpStatusCodeOptions = httpStatusCodes.map((code) => ({
32
39
  label: (
@@ -81,11 +88,11 @@ export const EndpointPage = ({
81
88
  <h3>{data.api.title}</h3>
82
89
  <h1 className="api-title">{data?.summary}</h1>
83
90
  <div className="url-box">
84
- <div style={{ textAlign: 'center' }}>
91
+ <div className="url-box_text-container">
85
92
  <span className={`method-label ${data?.method?.toLowerCase()}`}>{data.method}</span>
86
- <span className="url-text">{data?.path}</span>
93
+ <span className="url-text">{fullUrl}</span>
87
94
  </div>
88
- <span className="icon" onClick={() => navigator.clipboard.writeText(data?.path)}>
95
+ <span className="copy-icon" onClick={() => navigator.clipboard.writeText(fullUrl)}>
89
96
  <SVGLoader src={CopySticker} />
90
97
  </span>
91
98
  </div>
@@ -101,55 +101,7 @@ main {
101
101
  }
102
102
 
103
103
  .url-box {
104
- height: 1.75rem;
105
- justify-content: space-between;
106
- background-color: #edf1fb !important;
107
- }
108
-
109
- .url-text {
110
- color: #3b3f46;
111
- font-size: 1.25rem;
112
- letter-spacing: 0px;
113
- line-height: 1.75rem;
114
- }
115
-
116
- .method-label {
117
- font-size: 0.924rem;
118
- font-weight: 600;
119
- padding: 0.125rem 0.5rem;
120
- border-radius: 0.375rem;
121
- text-transform: uppercase;
122
- color: #3aaa35;
123
- text-decoration: underline;
124
-
125
- &.get {
126
- color: #3a6cd1;
127
- }
128
- &.post {
129
- color: #3aaa35;
130
- }
131
- &.put {
132
- color: #faad14;
133
- }
134
- &.patch {
135
- color: #58e2c2;
136
- }
137
- &.delete {
138
- color: #da3f3f;
139
- }
140
- &.head {
141
- color: #9461c9;
142
- }
143
- &.trace {
144
- color: #ffa28f;
145
- }
146
- &.options {
147
- color: #495d97;
148
- }
149
- }
150
-
151
- .url-box {
152
- background-color: #f3f4f6;
104
+ background-color: #edf1fb;
153
105
  padding: 0.375rem 0.75rem;
154
106
  border-radius: 0.5rem;
155
107
  display: flex;
@@ -159,6 +111,65 @@ main {
159
111
  flex: 1;
160
112
  height: 2.8rem;
161
113
  margin-bottom: 1.5rem;
114
+ overflow: hidden;
115
+
116
+ &_text-container {
117
+ display: flex;
118
+ align-items: center;
119
+ flex: 1;
120
+ overflow: hidden;
121
+
122
+ .url-text {
123
+ color: #3b3f46;
124
+ font-size: 1.25rem;
125
+ line-height: 1.75rem;
126
+ max-width: 100%;
127
+ overflow: hidden;
128
+ text-overflow: ellipsis;
129
+ white-space: nowrap;
130
+ flex: 1;
131
+ }
132
+
133
+ .method-label {
134
+ font-size: 1.25rem;
135
+ padding: 0.125rem 0.5rem;
136
+ border-radius: 0.375rem;
137
+ text-transform: uppercase;
138
+ color: #3aaa35;
139
+ text-decoration: underline;
140
+
141
+ &.get {
142
+ color: #3a6cd1;
143
+ }
144
+ &.post {
145
+ color: #3aaa35;
146
+ }
147
+ &.put {
148
+ color: #faad14;
149
+ }
150
+ &.patch {
151
+ color: #58e2c2;
152
+ }
153
+ &.delete {
154
+ color: #da3f3f;
155
+ }
156
+ &.head {
157
+ color: #9461c9;
158
+ }
159
+ &.trace {
160
+ color: #ffa28f;
161
+ }
162
+ &.options {
163
+ color: #495d97;
164
+ }
165
+ }
166
+ }
167
+
168
+ .copy-icon {
169
+ cursor: pointer;
170
+ width: 1.5rem;
171
+ height: 1.5rem;
172
+ }
162
173
  }
163
174
 
164
175
  .api-desc {
@@ -299,11 +310,5 @@ main {
299
310
  align-items: end !important;
300
311
  align-content: end !important;
301
312
  }
302
-
303
- .copy-icon {
304
- cursor: pointer;
305
- width: 1.5rem;
306
- height: 1.5rem;
307
- }
308
313
  }
309
314
  }
@@ -27,12 +27,18 @@
27
27
  font-size: 1rem;
28
28
  line-height: 1.25rem;
29
29
 
30
+ .btnContentWrapper {
31
+ .btnContent{
32
+ font-size: 0.918rem !important;
33
+ }
34
+ }
35
+
30
36
  &:hover:not(:disabled) {
31
37
  color: #000000 !important;
32
38
  }
33
39
 
34
40
  &:hover {
35
- color: #000;
41
+ color: #000 !important;
36
42
  }
37
43
 
38
44
  svg {
@@ -68,12 +74,18 @@
68
74
  border: none !important;
69
75
  box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
70
76
  padding: 0.4rem;
71
- width: 9.4875rem;
77
+ width: 10.4875rem;
72
78
  font-size: 1rem;
73
79
  font-weight: 400;
74
80
  line-height: 1.234rem;
75
81
  height: 2.25rem;
76
82
 
83
+ .btnContentWrapper {
84
+ .btnContent{
85
+ font-size: 0.918rem !important;
86
+ }
87
+ }
88
+
77
89
  &:hover:not(:disabled) {
78
90
  color: #000000 !important;
79
91
  }
@@ -49,6 +49,7 @@ const Layout = ({
49
49
  })
50
50
  const { dirty, isValid, isSubmitting, values, setFieldValue, handleSubmit, errors } = formik
51
51
  const [isPublishDialogOpen, setIsPublishDialogOpen] = useState(false)
52
+
52
53
  const [openMethodIndex, setOpenMethodIndex] = useState<number | null>(null)
53
54
 
54
55
  useEffect(() => {
@@ -57,11 +58,6 @@ const Layout = ({
57
58
  }
58
59
  }, [dirty])
59
60
 
60
- // TODO: keep it here until production
61
- useEffect(() => {
62
- console.log({ values, errors })
63
- }, [values])
64
-
65
61
  return (
66
62
  <div className={styles.docsLayout}>
67
63
  {dirty && (
package/variables.txt CHANGED
@@ -1 +1 @@
1
- export APP_VERSION=1.0.82
1
+ export APP_VERSION=1.0.84