Skip to content

Commit

Permalink
Get rid of multiple account_data calls for 3scale docs
Browse files Browse the repository at this point in the history
  • Loading branch information
mayorova committed Apr 20, 2023
1 parent 0700720 commit e6a7755
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 25 deletions.
17 changes: 12 additions & 5 deletions app/javascript/packs/active_docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,23 @@ import SwaggerUI from 'swagger-ui'
import 'swagger-ui/dist/swagger-ui.css'

import { autocompleteRequestInterceptor } from 'ActiveDocs/OAS3Autocomplete'
import { fetchData } from 'utilities/fetchData'

import type { AccountDataResponse } from 'Types/SwaggerTypes'

import 'ActiveDocs/swagger-ui-3-patch.scss'

const accountDataUrl = '/api_docs/account_data.json'

window.SwaggerUI = (args: SwaggerUI.SwaggerUIOptions, serviceEndpoint: string) => {
const requestInterceptor = (request: SwaggerUI.Request) => autocompleteRequestInterceptor(request, accountDataUrl, serviceEndpoint)
fetchData<AccountDataResponse>(accountDataUrl)
.then(accountData => {
const requestInterceptor = (request: SwaggerUI.Request) => autocompleteRequestInterceptor(request, accountData, serviceEndpoint)

SwaggerUI({
...args,
requestInterceptor
} as SwaggerUI.SwaggerUIOptions)
return SwaggerUI({
...args,
requestInterceptor
} as SwaggerUI.SwaggerUIOptions)
})
.catch(error => { console.error(error) })
}
13 changes: 9 additions & 4 deletions app/javascript/packs/provider_active_docs.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
// We can define the 3scale plugins here and export the modified bundle
import 'swagger-ui/dist/swagger-ui.css'

import { renderApiDocs } from 'ActiveDocs/ThreeScaleApiDocs'
import { renderSwaggerUI } from 'ActiveDocs/ThreeScaleApiDocs'

import 'ActiveDocs/swagger-ui-3-provider-patch.scss'

document.addEventListener('DOMContentLoaded', () => {
const renderActiveDocs = async () => {
const containerId = 'api-containers'
const container = document.getElementById(containerId)

if (!container) {
throw new Error('The target ID was not found: ' + containerId)
console.error(`The target element with ID ${containerId} was not found`)
return
}

const { baseUrl = '', apiDocsPath = '', apiDocsAccountDataPath = '' } = container.dataset

void renderApiDocs(container, apiDocsPath, baseUrl, apiDocsAccountDataPath)
await renderSwaggerUI(container, apiDocsPath, baseUrl, apiDocsAccountDataPath)
}

document.addEventListener('DOMContentLoaded', () => {
renderActiveDocs().catch(error => { console.error(error) })
})
16 changes: 13 additions & 3 deletions app/javascript/packs/service_active_docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,35 @@ import 'swagger-ui/dist/swagger-ui.css'

import { autocompleteRequestInterceptor } from 'ActiveDocs/OAS3Autocomplete'

import type { AccountDataResponse } from 'Types/SwaggerTypes'

import 'ActiveDocs/swagger-ui-3-provider-patch.scss'
import { fetchData } from '../src/utilities/fetchData'

document.addEventListener('DOMContentLoaded', () => {
const renderActiveDocs = async () => {
const containerId = 'swagger-ui-container'
const DATA_URL = 'p/admin/api_docs/account_data.json'
const container = document.getElementById(containerId)

if (!container) {
throw new Error('The target ID was not found: ' + containerId)
console.error(`Element with ID ${containerId} not found`)
return
}
const { url = '', baseUrl = '', serviceEndpoint = '' } = container.dataset
const accountDataUrl = `${baseUrl}${DATA_URL}`

const requestInterceptor: SwaggerUI.SwaggerUIOptions['requestInterceptor'] = (request) => autocompleteRequestInterceptor(request, accountDataUrl, serviceEndpoint)
const accountData: AccountDataResponse = await fetchData<AccountDataResponse>(accountDataUrl)

const requestInterceptor: SwaggerUI.SwaggerUIOptions['requestInterceptor'] = (request) => autocompleteRequestInterceptor(request, accountData, serviceEndpoint)

SwaggerUI({
url,
// eslint-disable-next-line @typescript-eslint/naming-convention -- SwaggerUI API
dom_id: `#${containerId}`,
requestInterceptor
})
}

document.addEventListener('DOMContentLoaded', () => {
renderActiveDocs().catch(error => { console.error(error) })
})
17 changes: 7 additions & 10 deletions app/javascript/src/ActiveDocs/OAS3Autocomplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@
/* eslint-disable @typescript-eslint/naming-convention */
/* TODO: this module needs to be properly typed !!! */

import { fetchData } from 'utilities/fetchData'

import type { Request as SwaggerUIRequest, Response as SwaggerUIResponse } from 'swagger-ui'
import type { AccountData } from 'Types/SwaggerTypes'
import type { AccountData, AccountDataResponse } from 'Types/SwaggerTypes'

const X_DATA_ATTRIBUTE = 'x-data-threescale-name'

Expand Down Expand Up @@ -114,14 +112,13 @@ export interface Response extends SwaggerUIResponse {
text: string;
}

export const autocompleteOAS3 = async (response: SwaggerUIResponse, accountDataUrl: string, serviceEndpoint: string): Promise<Response> => {
export const autocompleteOAS3 = (response: SwaggerUIResponse, accountData: AccountDataResponse, serviceEndpoint: string): Response => {
const bodyWithServer = injectServerToResponseBody(response.body, serviceEndpoint)
const data = await fetchData<{ results: AccountData }>(accountDataUrl)

let body = undefined
try {
body = data.results
? injectAutocompleteToResponseBody(bodyWithServer, data.results)
body = accountData.results
? injectAutocompleteToResponseBody(bodyWithServer, accountData.results)
: bodyWithServer
} catch (error: unknown) {
console.error(error)
Expand All @@ -141,12 +138,12 @@ export const autocompleteOAS3 = async (response: SwaggerUIResponse, accountDataU
* transformations (inject servers list and autocomplete data) to the response
* keep the responses to the actual API calls (made through 'Try it out') untouched
* @param request request made through Swagger UI
* @param accountDataUrl URL of the data for autocompletion
* @param accountData data for autocompletion
* @param serviceEndpoint Public Base URL of the gateway, that will replace the URL in the "servers" object
*/
export const autocompleteRequestInterceptor = (request: SwaggerUIRequest, accountDataUrl: string, serviceEndpoint: string): Promise<SwaggerUIRequest> | SwaggerUIRequest => {
export const autocompleteRequestInterceptor = (request: SwaggerUIRequest, accountData: AccountDataResponse, serviceEndpoint: string): Promise<SwaggerUIRequest> | SwaggerUIRequest => {
if (request.loadSpec) {
request.responseInterceptor = (response: SwaggerUIResponse) => autocompleteOAS3(response, accountDataUrl, serviceEndpoint)
request.responseInterceptor = (response: SwaggerUIResponse) => autocompleteOAS3(response, accountData, serviceEndpoint)
}
return request
}
9 changes: 6 additions & 3 deletions app/javascript/src/ActiveDocs/ThreeScaleApiDocs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { fetchData } from 'utilities/fetchData'
import { safeFromJsonString } from 'utilities/json-utils'
import { autocompleteRequestInterceptor } from 'ActiveDocs/OAS3Autocomplete'

import type { ApiDocsServices, BackendApiReportBody, BackendApiTransaction, BodyValue, BodyValueObject, FormData } from 'Types/SwaggerTypes'
import type { AccountDataResponse, ApiDocsServices, BackendApiReportBody, BackendApiTransaction, BodyValue, BodyValueObject, FormData } from 'Types/SwaggerTypes'
import type { ExecuteData } from 'swagger-client/es/execute'
import type { SwaggerUIPlugin } from 'swagger-ui'

Expand Down Expand Up @@ -118,8 +118,11 @@ const RequestBodyTransformerPlugin: SwaggerUIPlugin = () => {
}
}

export const renderApiDocs = async (container: HTMLElement, apiDocsPath: string, baseUrl: string, apiDocsAccountDataPath: string): Promise<void> => {
export const renderSwaggerUI = async (container: HTMLElement, apiDocsPath: string, baseUrl: string, accountDataUrl: string): Promise<void> => {
const apiSpecs: ApiDocsServices = await fetchData<ApiDocsServices>(apiDocsPath)

const accountData: AccountDataResponse = await fetchData<AccountDataResponse>(accountDataUrl)

apiSpecs.apis.forEach( api => {
const domId = api.system_name.replace(/_/g, '-')
const url = getApiSpecUrl(baseUrl, api.path)
Expand All @@ -128,7 +131,7 @@ export const renderApiDocs = async (container: HTMLElement, apiDocsPath: string,
url,
// eslint-disable-next-line @typescript-eslint/naming-convention -- Swagger UI
dom_id: `#${domId}`,
requestInterceptor: (request) => autocompleteRequestInterceptor(request, apiDocsAccountDataPath, ''),
requestInterceptor: (request) => autocompleteRequestInterceptor(request, accountData, ''),
tryItOutEnabled: true,
plugins: [
RequestBodyTransformerPlugin
Expand Down
5 changes: 5 additions & 0 deletions app/javascript/src/Types/SwaggerTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ export type AccountData = Record<string, {
value: string;
}[]>

export interface AccountDataResponse {
status: string;
results: AccountData;
}

export interface ApiDocsService {
name: string;
system_name: string;
Expand Down

0 comments on commit e6a7755

Please sign in to comment.