api
This commit is contained in:
13
frontend/web/api-doc/docker/configurator/helpers.js
Normal file
13
frontend/web/api-doc/docker/configurator/helpers.js
Normal file
@ -0,0 +1,13 @@
|
||||
module.exports.indent = function indent(str, len, fromLine = 0) {
|
||||
|
||||
return str
|
||||
.split("\n")
|
||||
.map((line, i) => {
|
||||
if (i + 1 >= fromLine) {
|
||||
return `${Array(len + 1).join(" ")}${line}`
|
||||
} else {
|
||||
return line
|
||||
}
|
||||
})
|
||||
.join("\n")
|
||||
}
|
52
frontend/web/api-doc/docker/configurator/index.js
Executable file
52
frontend/web/api-doc/docker/configurator/index.js
Executable file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Replace static code with configured data based on environment-variables.
|
||||
* This code should be called BEFORE the webserver serve the api-documentation.
|
||||
*/
|
||||
const fs = require("fs")
|
||||
const path = require("path")
|
||||
|
||||
const translator = require("./translator")
|
||||
const oauthBlockBuilder = require("./oauth")
|
||||
const indent = require("./helpers").indent
|
||||
|
||||
const START_MARKER = "//<editor-fold desc=\"Changeable Configuration Block\">"
|
||||
const END_MARKER = "//</editor-fold>"
|
||||
|
||||
const targetPath = path.normalize(process.cwd() + "/" + process.argv[2])
|
||||
|
||||
const originalHtmlContent = fs.readFileSync(targetPath, "utf8")
|
||||
|
||||
const startMarkerIndex = originalHtmlContent.indexOf(START_MARKER)
|
||||
const endMarkerIndex = originalHtmlContent.indexOf(END_MARKER)
|
||||
|
||||
const beforeStartMarkerContent = originalHtmlContent.slice(0, startMarkerIndex)
|
||||
const afterEndMarkerContent = originalHtmlContent.slice(
|
||||
endMarkerIndex + END_MARKER.length
|
||||
)
|
||||
|
||||
if (startMarkerIndex < 0 || endMarkerIndex < 0) {
|
||||
console.error("ERROR: Swagger UI was unable to inject Docker configuration data!")
|
||||
console.error("! This can happen when you provide custom HTML/JavaScript to Swagger UI.")
|
||||
console.error("! ")
|
||||
console.error(`! In order to solve this, add the "${START_MARKER}"`)
|
||||
console.error(`! and "${END_MARKER}" markers to your JavaScript.`)
|
||||
console.error("! See the repository for an example:")
|
||||
console.error("! https://github.com/swagger-api/swagger-ui/blob/8c946a02e73ef877d73b7635de27924418ba50f3/dist/swagger-initializer.js#L2-L19")
|
||||
console.error("! ")
|
||||
console.error("! If you're seeing this message and aren't using custom HTML,")
|
||||
console.error("! this message may be a bug. Please file an issue:")
|
||||
console.error("! https://github.com/swagger-api/swagger-ui/issues/new/choose")
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
fs.writeFileSync(
|
||||
targetPath,
|
||||
`${beforeStartMarkerContent}
|
||||
${START_MARKER}
|
||||
window.ui = SwaggerUIBundle({
|
||||
${indent(translator(process.env, {injectBaseConfig: true}), 8, 2)}
|
||||
})
|
||||
${indent(oauthBlockBuilder(process.env), 6, 2)}
|
||||
${END_MARKER}
|
||||
${afterEndMarkerContent}`
|
||||
)
|
55
frontend/web/api-doc/docker/configurator/oauth.js
Normal file
55
frontend/web/api-doc/docker/configurator/oauth.js
Normal file
@ -0,0 +1,55 @@
|
||||
const translator = require("./translator")
|
||||
const indent = require("./helpers").indent
|
||||
|
||||
const oauthBlockSchema = {
|
||||
OAUTH_CLIENT_ID: {
|
||||
type: "string",
|
||||
name: "clientId"
|
||||
},
|
||||
OAUTH_CLIENT_SECRET: {
|
||||
type: "string",
|
||||
name: "clientSecret",
|
||||
onFound: () => console.warn("Swagger UI warning: don't use `OAUTH_CLIENT_SECRET` in production!")
|
||||
},
|
||||
OAUTH_REALM: {
|
||||
type: "string",
|
||||
name: "realm"
|
||||
},
|
||||
OAUTH_APP_NAME: {
|
||||
type: "string",
|
||||
name: "appName"
|
||||
},
|
||||
OAUTH_SCOPE_SEPARATOR: {
|
||||
type: "string",
|
||||
name: "scopeSeparator"
|
||||
},
|
||||
OAUTH_SCOPES: {
|
||||
type: "string",
|
||||
name: "scopes"
|
||||
},
|
||||
OAUTH_ADDITIONAL_PARAMS: {
|
||||
type: "object",
|
||||
name: "additionalQueryStringParams"
|
||||
},
|
||||
OAUTH_USE_BASIC_AUTH: {
|
||||
type: "boolean",
|
||||
name: "useBasicAuthenticationWithAccessCodeGrant"
|
||||
},
|
||||
OAUTH_USE_PKCE: {
|
||||
type: "boolean",
|
||||
name: "usePkceWithAuthorizationCodeGrant"
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function oauthBlockBuilder(env) {
|
||||
const translatorResult = translator(env, { schema: oauthBlockSchema })
|
||||
|
||||
if(translatorResult) {
|
||||
return (
|
||||
`ui.initOAuth({
|
||||
${indent(translatorResult, 2)}
|
||||
})`)
|
||||
}
|
||||
|
||||
return ``
|
||||
}
|
111
frontend/web/api-doc/docker/configurator/translator.js
Normal file
111
frontend/web/api-doc/docker/configurator/translator.js
Normal file
@ -0,0 +1,111 @@
|
||||
// Converts an object of environment variables into a Swagger UI config object
|
||||
const configSchema = require("./variables")
|
||||
|
||||
const defaultBaseConfig = {
|
||||
url: {
|
||||
value: "https://petstore.swagger.io/v2/swagger.json",
|
||||
schema: {
|
||||
type: "string",
|
||||
base: true
|
||||
}
|
||||
},
|
||||
dom_id: {
|
||||
value: "#swagger-ui",
|
||||
schema: {
|
||||
type: "string",
|
||||
base: true
|
||||
}
|
||||
},
|
||||
deepLinking: {
|
||||
value: "true",
|
||||
schema: {
|
||||
type: "boolean",
|
||||
base: true
|
||||
}
|
||||
},
|
||||
presets: {
|
||||
value: `[\n SwaggerUIBundle.presets.apis,\n SwaggerUIStandalonePreset\n]`,
|
||||
schema: {
|
||||
type: "array",
|
||||
base: true
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
value: `[\n SwaggerUIBundle.plugins.DownloadUrl\n]`,
|
||||
schema: {
|
||||
type: "array",
|
||||
base: true
|
||||
}
|
||||
},
|
||||
layout: {
|
||||
value: "StandaloneLayout",
|
||||
schema: {
|
||||
type: "string",
|
||||
base: true
|
||||
}
|
||||
},
|
||||
queryConfigEnabled: {
|
||||
value: "false",
|
||||
schema: {
|
||||
type: "boolean",
|
||||
base: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function objectToKeyValueString(env, { injectBaseConfig = false, schema = configSchema, baseConfig = defaultBaseConfig } = {}) {
|
||||
let valueStorage = injectBaseConfig ? Object.assign({}, baseConfig) : {}
|
||||
const keys = Object.keys(env)
|
||||
|
||||
// Compute an intermediate representation that holds candidate values and schemas.
|
||||
//
|
||||
// This is useful for deduping between multiple env keys that set the same
|
||||
// config variable.
|
||||
|
||||
keys.forEach(key => {
|
||||
const varSchema = schema[key]
|
||||
const value = env[key]
|
||||
|
||||
if(!varSchema) return
|
||||
|
||||
if(varSchema.onFound) {
|
||||
varSchema.onFound()
|
||||
}
|
||||
|
||||
const storageContents = valueStorage[varSchema.name]
|
||||
|
||||
if(storageContents) {
|
||||
if (varSchema.legacy === true && !storageContents.schema.base) {
|
||||
// If we're looking at a legacy var, it should lose out to any already-set value
|
||||
// except for base values
|
||||
return
|
||||
}
|
||||
delete valueStorage[varSchema.name]
|
||||
}
|
||||
|
||||
valueStorage[varSchema.name] = {
|
||||
value,
|
||||
schema: varSchema
|
||||
}
|
||||
})
|
||||
|
||||
// Compute a key:value string based on valueStorage's contents.
|
||||
|
||||
let result = ""
|
||||
|
||||
Object.keys(valueStorage).forEach(key => {
|
||||
const value = valueStorage[key]
|
||||
|
||||
const escapedName = /[^a-zA-Z0-9]/.test(key) ? `"${key}"` : key
|
||||
|
||||
if (value.schema.type === "string") {
|
||||
result += `${escapedName}: "${value.value}",\n`
|
||||
} else {
|
||||
result += `${escapedName}: ${value.value === "" ? `undefined` : value.value},\n`
|
||||
}
|
||||
})
|
||||
|
||||
return result.trim()
|
||||
}
|
||||
|
||||
module.exports = objectToKeyValueString
|
125
frontend/web/api-doc/docker/configurator/variables.js
Normal file
125
frontend/web/api-doc/docker/configurator/variables.js
Normal file
@ -0,0 +1,125 @@
|
||||
const standardVariables = {
|
||||
CONFIG_URL: {
|
||||
type: "string",
|
||||
name: "configUrl"
|
||||
},
|
||||
DOM_ID: {
|
||||
type: "string",
|
||||
name: "dom_id"
|
||||
},
|
||||
SPEC: {
|
||||
type: "object",
|
||||
name: "spec"
|
||||
},
|
||||
URL: {
|
||||
type: "string",
|
||||
name: "url"
|
||||
},
|
||||
URLS: {
|
||||
type: "array",
|
||||
name: "urls"
|
||||
},
|
||||
URLS_PRIMARY_NAME: {
|
||||
type: "string",
|
||||
name: "urls.primaryName"
|
||||
},
|
||||
QUERY_CONFIG_ENABLED: {
|
||||
type: "boolean",
|
||||
name: "queryConfigEnabled"
|
||||
},
|
||||
LAYOUT: {
|
||||
type: "string",
|
||||
name: "layout"
|
||||
},
|
||||
DEEP_LINKING: {
|
||||
type: "boolean",
|
||||
name: "deepLinking"
|
||||
},
|
||||
DISPLAY_OPERATION_ID: {
|
||||
type: "boolean",
|
||||
name: "displayOperationId"
|
||||
},
|
||||
DEFAULT_MODELS_EXPAND_DEPTH: {
|
||||
type: "number",
|
||||
name: "defaultModelsExpandDepth"
|
||||
},
|
||||
DEFAULT_MODEL_EXPAND_DEPTH: {
|
||||
type: "number",
|
||||
name: "defaultModelExpandDepth"
|
||||
},
|
||||
DEFAULT_MODEL_RENDERING: {
|
||||
type: "string",
|
||||
name: "defaultModelRendering"
|
||||
},
|
||||
DISPLAY_REQUEST_DURATION: {
|
||||
type: "boolean",
|
||||
name: "displayRequestDuration"
|
||||
},
|
||||
DOC_EXPANSION: {
|
||||
type: "string",
|
||||
name: "docExpansion"
|
||||
},
|
||||
FILTER: {
|
||||
type: "string",
|
||||
name: "filter"
|
||||
},
|
||||
MAX_DISPLAYED_TAGS: {
|
||||
type: "number",
|
||||
name: "maxDisplayedTags"
|
||||
},
|
||||
SHOW_EXTENSIONS: {
|
||||
type: "boolean",
|
||||
name: "showExtensions"
|
||||
},
|
||||
SHOW_COMMON_EXTENSIONS: {
|
||||
type: "boolean",
|
||||
name: "showCommonExtensions"
|
||||
},
|
||||
USE_UNSAFE_MARKDOWN: {
|
||||
type: "boolean",
|
||||
name: "useUnsafeMarkdown"
|
||||
},
|
||||
OAUTH2_REDIRECT_URL: {
|
||||
type: "string",
|
||||
name: "oauth2RedirectUrl"
|
||||
},
|
||||
PERSIST_AUTHORIZATION: {
|
||||
type: "boolean",
|
||||
name: "persistAuthorization"
|
||||
},
|
||||
SHOW_MUTATED_REQUEST: {
|
||||
type: "boolean",
|
||||
name: "showMutatedRequest"
|
||||
},
|
||||
SUPPORTED_SUBMIT_METHODS: {
|
||||
type: "array",
|
||||
name: "supportedSubmitMethods"
|
||||
},
|
||||
TRY_IT_OUT_ENABLED: {
|
||||
type: "boolean",
|
||||
name: "tryItOutEnabled"
|
||||
},
|
||||
VALIDATOR_URL: {
|
||||
type: "string",
|
||||
name: "validatorUrl"
|
||||
},
|
||||
WITH_CREDENTIALS: {
|
||||
type: "boolean",
|
||||
name: "withCredentials",
|
||||
}
|
||||
}
|
||||
|
||||
const legacyVariables = {
|
||||
API_URL: {
|
||||
type: "string",
|
||||
name: "url",
|
||||
legacy: true
|
||||
},
|
||||
API_URLS: {
|
||||
type: "array",
|
||||
name: "urls",
|
||||
legacy: true
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Object.assign({}, standardVariables, legacyVariables)
|
Reference in New Issue
Block a user