serverest 3.0.1 → 3.1.1
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/docs/flags/flag_peru.svg +10 -0
- package/docs/images/serverest_logo.svg +116 -0
- package/package.json +4 -1
- package/src/app.js +1 -1
- package/src/controllers/produtos-controller.js +65 -65
- package/src/swagger/index.js +62 -0
- package/src/swagger/scripts/01-config.js +10 -0
- package/src/swagger/scripts/02-language-storage.js +55 -0
- package/src/swagger/scripts/03-release-toast.js +158 -0
- package/src/swagger/scripts/04-ui-translations.js +92 -0
- package/src/swagger/scripts/05-swagger-spec.js +110 -0
- package/src/swagger/scripts/06-language-switcher.js +68 -0
- package/src/swagger/scripts/07-doc-lifecycle.js +163 -0
- package/src/swagger/styles/language-switcher.css +64 -0
- package/src/swagger/{custom-css.css → styles/release-toast.css} +1 -60
- package/src/swagger/styles/topbar.css +56 -0
- package/src/swagger/swagger-sw.js +2 -2
- package/src/swagger/translations/en.js +23 -0
- package/src/swagger/translations/es.js +23 -0
- package/src/swagger/translations/pt-BR.js +23 -0
- package/docs/flags/flag_spain.svg +0 -2552
- package/docs/images/serverest_logo.png +0 -0
- package/src/swagger/custom-js.js +0 -609
- package/src/swagger/customization.js +0 -25
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
const swaggerSpecCache = {}
|
|
2
|
+
|
|
3
|
+
function updateSpecUrlInDom (specUrlString) {
|
|
4
|
+
const root = document.querySelector('.swagger-ui')
|
|
5
|
+
if (!root) return
|
|
6
|
+
root.querySelectorAll('input').forEach(input => {
|
|
7
|
+
if (input.value && input.value.includes('swagger.json')) {
|
|
8
|
+
input.value = specUrlString
|
|
9
|
+
}
|
|
10
|
+
})
|
|
11
|
+
root.querySelectorAll('a[href*="swagger.json"]').forEach(a => {
|
|
12
|
+
if (a.getAttribute('href') && a.getAttribute('href').includes('swagger.json')) {
|
|
13
|
+
a.setAttribute('href', specUrlString)
|
|
14
|
+
}
|
|
15
|
+
})
|
|
16
|
+
if (root.querySelectorAll) {
|
|
17
|
+
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false)
|
|
18
|
+
const textNodes = []
|
|
19
|
+
while (walker.nextNode()) textNodes.push(walker.currentNode)
|
|
20
|
+
textNodes.forEach(node => {
|
|
21
|
+
if (node.nodeValue && node.nodeValue.includes('swagger.json?lang=')) {
|
|
22
|
+
node.nodeValue = node.nodeValue.replace(
|
|
23
|
+
/https?:\/\/[^"\s]+\/swagger\.json\?lang=[^"\s&]+/g,
|
|
24
|
+
specUrlString
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function prefetchSwaggerSpecs () {
|
|
32
|
+
const code = getCurrentLanguageCode()
|
|
33
|
+
const url = '/swagger.json?lang=' + encodeURIComponent(code)
|
|
34
|
+
fetch(url)
|
|
35
|
+
.then(r => r.json())
|
|
36
|
+
.then(spec => { swaggerSpecCache[code] = spec })
|
|
37
|
+
.catch(() => {})
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function updateSwaggerSpec (language, shouldRefreshOpenOps = false) {
|
|
41
|
+
const specUrl = new URL('/swagger.json', window.location.origin)
|
|
42
|
+
specUrl.searchParams.set('lang', language)
|
|
43
|
+
updateSpecUrlInDom(specUrl.toString())
|
|
44
|
+
const applySpec = (spec) => {
|
|
45
|
+
if (!window.ui || !window.ui.specActions) return
|
|
46
|
+
resetTranslationCache()
|
|
47
|
+
window.ui.specActions.updateSpec(JSON.stringify(spec))
|
|
48
|
+
if (window.ui.specActions.updateUrl) {
|
|
49
|
+
window.ui.specActions.updateUrl(specUrl.toString())
|
|
50
|
+
}
|
|
51
|
+
setTimeout(() => updateSpecUrlInDom(specUrl.toString()), 0)
|
|
52
|
+
if (window.ui.specActions.updateJsonSpec) {
|
|
53
|
+
window.ui.specActions.updateJsonSpec(spec)
|
|
54
|
+
}
|
|
55
|
+
let parsedSpec = null
|
|
56
|
+
if (window.ui.specActions.parseToJson) {
|
|
57
|
+
parsedSpec = window.ui.specActions.parseToJson(JSON.stringify(spec))
|
|
58
|
+
}
|
|
59
|
+
if (parsedSpec && window.ui.specActions.updateJsonSpec) {
|
|
60
|
+
window.ui.specActions.updateJsonSpec(parsedSpec)
|
|
61
|
+
}
|
|
62
|
+
if (window.ui.specActions.updateResolved) {
|
|
63
|
+
window.ui.specActions.updateResolved(parsedSpec || spec)
|
|
64
|
+
}
|
|
65
|
+
if (window.ui.specActions.invalidateResolvedSubtreeCache) {
|
|
66
|
+
window.ui.specActions.invalidateResolvedSubtreeCache()
|
|
67
|
+
}
|
|
68
|
+
if (window.ui.specActions.resolveSpec) {
|
|
69
|
+
const resolveResult = window.ui.specActions.resolveSpec(specUrl.toString())
|
|
70
|
+
if (resolveResult && typeof resolveResult.catch === 'function') {
|
|
71
|
+
resolveResult.catch(() => {})
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (shouldRefreshOpenOps) {
|
|
75
|
+
refreshOpenOperations()
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const cached = swaggerSpecCache[language]
|
|
79
|
+
if (cached) {
|
|
80
|
+
applySpec(cached)
|
|
81
|
+
return
|
|
82
|
+
}
|
|
83
|
+
fetch(specUrl.toString())
|
|
84
|
+
.then(response => response.json())
|
|
85
|
+
.then(spec => {
|
|
86
|
+
swaggerSpecCache[language] = spec
|
|
87
|
+
applySpec(spec)
|
|
88
|
+
})
|
|
89
|
+
.catch(() => {})
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function refreshOpenOperations () {
|
|
93
|
+
const openOperations = document.querySelectorAll('.opblock.is-open .opblock-summary')
|
|
94
|
+
if (!openOperations.length) return
|
|
95
|
+
const requestResolvedSubtree = window.ui?.specActions?.requestResolvedSubtree
|
|
96
|
+
if (requestResolvedSubtree) {
|
|
97
|
+
openOperations.forEach(summary => {
|
|
98
|
+
const opblock = summary.closest('.opblock')
|
|
99
|
+
if (!opblock) return
|
|
100
|
+
const methodText = opblock.querySelector('.opblock-summary-method')?.textContent?.trim() || ''
|
|
101
|
+
const pathText = opblock.querySelector('.opblock-summary-path')?.textContent?.trim() || ''
|
|
102
|
+
if (!methodText || !pathText) return
|
|
103
|
+
requestResolvedSubtree(['paths', pathText, methodText.toLowerCase()])
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
openOperations.forEach(summary => summary.click())
|
|
107
|
+
setTimeout(() => {
|
|
108
|
+
openOperations.forEach(summary => summary.click())
|
|
109
|
+
}, 0)
|
|
110
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const lastLanguageKey = 'swaggerLastLanguage'
|
|
2
|
+
|
|
3
|
+
function renderLanguageSwitcher (parent) {
|
|
4
|
+
if (document.querySelector('.lang-switcher')) return
|
|
5
|
+
const root = parent || document.querySelector('.swagger-ui')
|
|
6
|
+
if (!root) return
|
|
7
|
+
const currentLang = getPreferredLanguage()
|
|
8
|
+
root.setAttribute('data-docs-lang', currentLang)
|
|
9
|
+
const wrapper = document.createElement('div')
|
|
10
|
+
wrapper.className = 'lang-switcher'
|
|
11
|
+
wrapper.setAttribute('aria-label', 'Seleção de idioma')
|
|
12
|
+
let glowTimeoutId = null
|
|
13
|
+
supportedLanguages.forEach(language => {
|
|
14
|
+
const button = document.createElement('button')
|
|
15
|
+
button.type = 'button'
|
|
16
|
+
button.className = 'lang-switcher__button'
|
|
17
|
+
button.setAttribute('data-lang', language.code)
|
|
18
|
+
button.setAttribute('aria-label', language.label)
|
|
19
|
+
button.setAttribute('title', language.label)
|
|
20
|
+
const flagUrl = flagUrls[language.code]
|
|
21
|
+
if (flagUrl) {
|
|
22
|
+
const img = document.createElement('img')
|
|
23
|
+
img.className = 'lang-switcher__flag'
|
|
24
|
+
img.src = flagUrl
|
|
25
|
+
img.alt = ''
|
|
26
|
+
img.width = 20
|
|
27
|
+
img.height = 14
|
|
28
|
+
button.appendChild(img)
|
|
29
|
+
} else {
|
|
30
|
+
button.textContent = language.code
|
|
31
|
+
}
|
|
32
|
+
if (language.code === currentLang) {
|
|
33
|
+
button.classList.add('is-active')
|
|
34
|
+
}
|
|
35
|
+
button.addEventListener('click', () => {
|
|
36
|
+
if (language.code === getPreferredLanguage()) return
|
|
37
|
+
const previousLanguage = getPreferredLanguage()
|
|
38
|
+
window.sessionStorage.setItem(lastLanguageKey, previousLanguage)
|
|
39
|
+
setPreferredLanguage(language.code)
|
|
40
|
+
root.setAttribute('data-docs-lang', language.code)
|
|
41
|
+
if (glowTimeoutId) clearTimeout(glowTimeoutId)
|
|
42
|
+
wrapper.classList.remove('lang-switcher--glow')
|
|
43
|
+
wrapper.removeAttribute('data-glow-lang')
|
|
44
|
+
wrapper.offsetHeight
|
|
45
|
+
wrapper.classList.add('lang-switcher--glow')
|
|
46
|
+
wrapper.setAttribute('data-glow-lang', language.code)
|
|
47
|
+
glowTimeoutId = setTimeout(() => {
|
|
48
|
+
glowTimeoutId = null
|
|
49
|
+
wrapper.classList.remove('lang-switcher--glow')
|
|
50
|
+
wrapper.removeAttribute('data-glow-lang')
|
|
51
|
+
}, 1000)
|
|
52
|
+
const url = new URL(window.location.href)
|
|
53
|
+
url.searchParams.set('lang', language.code)
|
|
54
|
+
window.history.replaceState({}, '', url.toString())
|
|
55
|
+
wrapper.querySelectorAll('.lang-switcher__button').forEach(el => {
|
|
56
|
+
el.classList.toggle('is-active', el.getAttribute('data-lang') === language.code)
|
|
57
|
+
})
|
|
58
|
+
resetTranslationCache()
|
|
59
|
+
const shouldRefresh = setRefreshFlagFromState(language.code)
|
|
60
|
+
updateSwaggerSpec(language.code, shouldRefresh)
|
|
61
|
+
applyTranslations(language.code)
|
|
62
|
+
setTimeout(() => applyTranslations(language.code), 100)
|
|
63
|
+
updateReleaseToastLanguage(language.code)
|
|
64
|
+
})
|
|
65
|
+
wrapper.appendChild(button)
|
|
66
|
+
})
|
|
67
|
+
root.appendChild(wrapper)
|
|
68
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
let endpointBlockOpen = false
|
|
2
|
+
|
|
3
|
+
function hasOpenOperationHash () {
|
|
4
|
+
return typeof window.location.hash === 'string' && window.location.hash.includes('/')
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function setEndpointBlockOpen (open) {
|
|
8
|
+
endpointBlockOpen = !!open
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function shouldRefreshEndpointBlockNow (currentLanguage) {
|
|
12
|
+
if (!endpointBlockOpen) return false
|
|
13
|
+
const lastLang = window.sessionStorage.getItem(lastLanguageKey)
|
|
14
|
+
return !lastLang || lastLang !== currentLanguage
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function setRefreshFlagFromState (currentLanguage) {
|
|
18
|
+
return shouldRefreshEndpointBlockNow(currentLanguage)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const docsVersionKey = 'serverest-docs-version'
|
|
22
|
+
|
|
23
|
+
function clearCachesAndReloadForNewVersion (newVersion) {
|
|
24
|
+
const unregister = typeof navigator !== 'undefined' && navigator.serviceWorker && navigator.serviceWorker.getRegistrations
|
|
25
|
+
? navigator.serviceWorker.getRegistrations().then(regs => Promise.all(regs.map(r => r.unregister())))
|
|
26
|
+
: Promise.resolve()
|
|
27
|
+
const clearCaches = typeof caches !== 'undefined' && caches.keys
|
|
28
|
+
? caches.keys().then(keys => Promise.all(keys.map(k => caches.delete(k))))
|
|
29
|
+
: Promise.resolve()
|
|
30
|
+
Promise.all([unregister, clearCaches]).then(() => {
|
|
31
|
+
window.sessionStorage.setItem(docsVersionKey, newVersion)
|
|
32
|
+
window.location.reload()
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function checkVersionThenObserve () {
|
|
37
|
+
const root = document.querySelector('.swagger-ui')
|
|
38
|
+
if (root) {
|
|
39
|
+
runVersionCheckAndObserve()
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
const mo = new MutationObserver(function () {
|
|
43
|
+
if (document.querySelector('.swagger-ui')) {
|
|
44
|
+
mo.disconnect()
|
|
45
|
+
runVersionCheckAndObserve()
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
mo.observe(document.documentElement, { childList: true, subtree: true })
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function runVersionCheckAndObserve () {
|
|
52
|
+
const normalizedCurrent = normalizeVersion(currentVersion)
|
|
53
|
+
const storedVersion = window.sessionStorage.getItem(docsVersionKey)
|
|
54
|
+
if (storedVersion && storedVersion !== normalizedCurrent) {
|
|
55
|
+
clearCachesAndReloadForNewVersion(normalizedCurrent)
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
if (!storedVersion) {
|
|
59
|
+
window.sessionStorage.setItem(docsVersionKey, normalizedCurrent)
|
|
60
|
+
}
|
|
61
|
+
observe()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function registerServiceWorker () {
|
|
65
|
+
if (typeof navigator !== 'undefined' && 'serviceWorker' in navigator) {
|
|
66
|
+
navigator.serviceWorker.register('/swagger-sw.js').catch(() => {})
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function observe () {
|
|
71
|
+
const root = document.querySelector('.swagger-ui')
|
|
72
|
+
if (!root) {
|
|
73
|
+
setTimeout(observe, 500)
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
registerServiceWorker()
|
|
77
|
+
if (window.performance && window.performance.getEntriesByType) {
|
|
78
|
+
const navEntries = window.performance.getEntriesByType('navigation')
|
|
79
|
+
if (navEntries && navEntries[0] && navEntries[0].type === 'reload') {
|
|
80
|
+
window.sessionStorage.removeItem(lastLanguageKey)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const queryLanguage = getLanguageFromQuery()
|
|
84
|
+
const preferred = getPreferredLanguage()
|
|
85
|
+
const language = queryLanguage || preferred
|
|
86
|
+
if (language !== preferred) {
|
|
87
|
+
window.sessionStorage.setItem(lastLanguageKey, preferred)
|
|
88
|
+
setPreferredLanguage(language)
|
|
89
|
+
}
|
|
90
|
+
if (!queryLanguage) {
|
|
91
|
+
const url = new URL(window.location.href)
|
|
92
|
+
url.searchParams.set('lang', language)
|
|
93
|
+
window.history.replaceState({}, '', url.toString())
|
|
94
|
+
}
|
|
95
|
+
let translationScheduled = false
|
|
96
|
+
const scheduleTranslations = () => {
|
|
97
|
+
if (translationScheduled) return
|
|
98
|
+
translationScheduled = true
|
|
99
|
+
setTimeout(() => {
|
|
100
|
+
translationScheduled = false
|
|
101
|
+
applyTranslations(getPreferredLanguage())
|
|
102
|
+
}, 0)
|
|
103
|
+
}
|
|
104
|
+
const observer = new MutationObserver(scheduleTranslations)
|
|
105
|
+
observer.observe(root, { childList: true, subtree: true })
|
|
106
|
+
root.addEventListener('click', event => {
|
|
107
|
+
if (!event.isTrusted) return
|
|
108
|
+
const summary = event.target.closest ? event.target.closest('.opblock-summary') : null
|
|
109
|
+
if (!summary) return
|
|
110
|
+
const opblock = summary.closest('.opblock')
|
|
111
|
+
if (!opblock) return
|
|
112
|
+
setTimeout(() => {
|
|
113
|
+
if (opblock.classList.contains('is-open')) {
|
|
114
|
+
setEndpointBlockOpen(true)
|
|
115
|
+
window.sessionStorage.setItem(lastLanguageKey, getPreferredLanguage())
|
|
116
|
+
} else {
|
|
117
|
+
setEndpointBlockOpen(false)
|
|
118
|
+
}
|
|
119
|
+
}, 0)
|
|
120
|
+
})
|
|
121
|
+
renderLanguageSwitcher(root)
|
|
122
|
+
setupTopbarLogo(root)
|
|
123
|
+
scheduleTranslations()
|
|
124
|
+
if (hasOpenOperationHash()) {
|
|
125
|
+
setEndpointBlockOpen(true)
|
|
126
|
+
}
|
|
127
|
+
const shouldRefreshEndpointBlock = setRefreshFlagFromState(language)
|
|
128
|
+
updateSwaggerSpec(language, shouldRefreshEndpointBlock)
|
|
129
|
+
runReleaseCheck()
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function setupTopbarLogo (root) {
|
|
133
|
+
function run () {
|
|
134
|
+
const wrapper = root.querySelector('.topbar-wrapper')
|
|
135
|
+
const link = wrapper && wrapper.querySelector('.link')
|
|
136
|
+
if (!wrapper || !link) return
|
|
137
|
+
if (document.getElementById('serverest-logo')) return
|
|
138
|
+
const logo = document.createElement('div')
|
|
139
|
+
logo.id = 'serverest-logo'
|
|
140
|
+
logo.className = 'topbar-logo'
|
|
141
|
+
wrapper.insertBefore(logo, link)
|
|
142
|
+
link.style.display = 'none'
|
|
143
|
+
link.removeAttribute('href')
|
|
144
|
+
link.setAttribute('aria-hidden', 'true')
|
|
145
|
+
}
|
|
146
|
+
run()
|
|
147
|
+
setTimeout(run, 300)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function init () {
|
|
151
|
+
preloadFlags()
|
|
152
|
+
preloadSwaggerJson()
|
|
153
|
+
prefetchSwaggerSpecs()
|
|
154
|
+
if (document.body) renderReleaseToast()
|
|
155
|
+
checkVersionThenObserve()
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (document.readyState === 'loading') {
|
|
159
|
+
document.addEventListener('DOMContentLoaded', init)
|
|
160
|
+
} else {
|
|
161
|
+
init()
|
|
162
|
+
}
|
|
163
|
+
})()
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/* Seletor de idioma (bandeiras) */
|
|
2
|
+
.swagger-ui .lang-switcher {
|
|
3
|
+
position: fixed;
|
|
4
|
+
left: 16px;
|
|
5
|
+
top: 24px;
|
|
6
|
+
display: flex;
|
|
7
|
+
gap: 6px;
|
|
8
|
+
background: rgba(255, 255, 255, 0.92);
|
|
9
|
+
border: 1px solid #e5e7eb;
|
|
10
|
+
border-radius: 999px;
|
|
11
|
+
padding: 4px 8px;
|
|
12
|
+
z-index: 9999;
|
|
13
|
+
box-shadow: 0px 2px 5px rgba(124, 58, 237, 0.5);
|
|
14
|
+
transition: box-shadow 1.5s ease-out;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.swagger-ui .lang-switcher.lang-switcher--glow {
|
|
18
|
+
transition: box-shadow 0.15s ease-out;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.swagger-ui .lang-switcher__button {
|
|
22
|
+
border: 0;
|
|
23
|
+
border-radius: 999px;
|
|
24
|
+
background: transparent;
|
|
25
|
+
cursor: pointer;
|
|
26
|
+
font-size: 16px;
|
|
27
|
+
line-height: 1;
|
|
28
|
+
padding: 4px;
|
|
29
|
+
opacity: 0.6;
|
|
30
|
+
display: inline-flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
justify-content: center;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.swagger-ui .lang-switcher__flag {
|
|
36
|
+
display: block;
|
|
37
|
+
width: 20px;
|
|
38
|
+
height: 14px;
|
|
39
|
+
border-radius: 2px;
|
|
40
|
+
object-fit: cover;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.swagger-ui .lang-switcher__button:hover {
|
|
44
|
+
opacity: 1;
|
|
45
|
+
transform: translateY(-2px);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.swagger-ui .lang-switcher__button.is-active {
|
|
49
|
+
opacity: 1;
|
|
50
|
+
transform: scale(1.3);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* Brilho (shadow) em volta do lang-switcher na cor do país */
|
|
54
|
+
.swagger-ui .lang-switcher[data-glow-lang='pt-BR'].lang-switcher--glow {
|
|
55
|
+
box-shadow: 0 0 6px #009739, 0 0 15px #009739;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.swagger-ui .lang-switcher[data-glow-lang='en'].lang-switcher--glow {
|
|
59
|
+
box-shadow: 0 0 6px #2c6bff, 0 0 15px #2c6bff;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.swagger-ui .lang-switcher[data-glow-lang='es'].lang-switcher--glow {
|
|
63
|
+
box-shadow: 0 0 6px #ff2b2b, 0 0 15px #ff2b2b;
|
|
64
|
+
}
|
|
@@ -1,63 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
display: block;
|
|
3
|
-
height: 60px;
|
|
4
|
-
background: url(/images/serverest_logo.png) no-repeat center / contain;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
.swagger-ui .topbar-wrapper .link svg { display: none; }
|
|
8
|
-
|
|
9
|
-
.swagger-ui .topbar { background-color: #000000; border-bottom: 20px solid #7900e2; }
|
|
10
|
-
|
|
11
|
-
.swagger-ui .markdown code,
|
|
12
|
-
.swagger-ui .renderedMarkdown code {
|
|
13
|
-
font-size: 12px;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
.swagger-ui .lang-switcher {
|
|
17
|
-
position: fixed;
|
|
18
|
-
left: 16px;
|
|
19
|
-
top: 16px;
|
|
20
|
-
display: flex;
|
|
21
|
-
gap: 6px;
|
|
22
|
-
background: rgba(255, 255, 255, 0.92);
|
|
23
|
-
border: 1px solid #e5e7eb;
|
|
24
|
-
border-radius: 999px;
|
|
25
|
-
padding: 4px 8px;
|
|
26
|
-
z-index: 9999;
|
|
27
|
-
box-shadow: 0px 2px 5px rgba(124, 58, 237, 0.5);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
.swagger-ui .lang-switcher__button {
|
|
31
|
-
border: 0;
|
|
32
|
-
background: transparent;
|
|
33
|
-
cursor: pointer;
|
|
34
|
-
font-size: 16px;
|
|
35
|
-
line-height: 1;
|
|
36
|
-
padding: 4px;
|
|
37
|
-
opacity: 0.6;
|
|
38
|
-
display: inline-flex;
|
|
39
|
-
align-items: center;
|
|
40
|
-
justify-content: center;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.swagger-ui .lang-switcher__flag {
|
|
44
|
-
display: block;
|
|
45
|
-
width: 20px;
|
|
46
|
-
height: 14px;
|
|
47
|
-
border-radius: 2px;
|
|
48
|
-
object-fit: cover;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
.swagger-ui .lang-switcher__button:hover {
|
|
52
|
-
opacity: 1;
|
|
53
|
-
transform: translateY(-2px);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
.swagger-ui .lang-switcher__button.is-active {
|
|
57
|
-
opacity: 1;
|
|
58
|
-
transform: scale(1.3);
|
|
59
|
-
}
|
|
60
|
-
|
|
1
|
+
/* Toast de nova release disponível */
|
|
61
2
|
.swagger-ui .release-toast,
|
|
62
3
|
.release-toast {
|
|
63
4
|
position: fixed;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/* Topbar: link nativo desabilitado; logo exibida em #serverest-logo.topbar-logo (criado via JS) */
|
|
2
|
+
.swagger-ui .topbar-wrapper {
|
|
3
|
+
display: flex;
|
|
4
|
+
align-items: center;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.swagger-ui .topbar-wrapper .link {
|
|
8
|
+
display: none;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/* Logo = só o SVG (id + classe), proporção exata, letras brancas, fundo transparente */
|
|
12
|
+
#serverest-logo.topbar-logo {
|
|
13
|
+
position: relative;
|
|
14
|
+
display: block;
|
|
15
|
+
width: calc(60px * 3864 / 1530);
|
|
16
|
+
height: 60px;
|
|
17
|
+
padding: 0;
|
|
18
|
+
flex-shrink: 0;
|
|
19
|
+
overflow: hidden;
|
|
20
|
+
background: transparent;
|
|
21
|
+
box-sizing: border-box;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#serverest-logo.topbar-logo::before {
|
|
25
|
+
content: '';
|
|
26
|
+
position: absolute;
|
|
27
|
+
left: -2px;
|
|
28
|
+
top: 0;
|
|
29
|
+
right: -2px;
|
|
30
|
+
bottom: 0;
|
|
31
|
+
width: calc(100% + 4px);
|
|
32
|
+
height: 100%;
|
|
33
|
+
background-color: #ffffff;
|
|
34
|
+
-webkit-mask-image: linear-gradient(white, white), url(/images/serverest_logo.svg);
|
|
35
|
+
-webkit-mask-size: 100% 100%, 100% 100%;
|
|
36
|
+
-webkit-mask-position: center, center;
|
|
37
|
+
-webkit-mask-repeat: no-repeat, no-repeat;
|
|
38
|
+
-webkit-mask-composite: destination-out;
|
|
39
|
+
mask-image: linear-gradient(white, white), url(/images/serverest_logo.svg);
|
|
40
|
+
mask-size: 100% 100%, 100% 100%;
|
|
41
|
+
mask-position: center, center;
|
|
42
|
+
mask-repeat: no-repeat, no-repeat;
|
|
43
|
+
mask-composite: exclude;
|
|
44
|
+
pointer-events: none;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.swagger-ui .topbar {
|
|
48
|
+
position: relative;
|
|
49
|
+
background-color: #000000;
|
|
50
|
+
border-bottom: 20px solid #7900e2;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.swagger-ui .markdown code,
|
|
54
|
+
.swagger-ui .renderedMarkdown code {
|
|
55
|
+
font-size: 12px;
|
|
56
|
+
}
|
|
@@ -30,9 +30,9 @@ const PREFETCH_PATHS = [
|
|
|
30
30
|
'/swagger.json?lang=es',
|
|
31
31
|
'/favicon.ico',
|
|
32
32
|
'/flags/flag_brazil.svg',
|
|
33
|
-
'/flags/
|
|
33
|
+
'/flags/flag_peru.svg',
|
|
34
34
|
'/flags/flag_uk.svg',
|
|
35
|
-
'/images/serverest_logo.
|
|
35
|
+
'/images/serverest_logo.svg',
|
|
36
36
|
'/swagger-ui.css',
|
|
37
37
|
'/swagger-ui-init.js',
|
|
38
38
|
'/swagger-ui-bundle.js',
|
|
@@ -2,6 +2,29 @@
|
|
|
2
2
|
'use strict'
|
|
3
3
|
|
|
4
4
|
module.exports = {
|
|
5
|
+
'ui.parameters': 'Parameters',
|
|
6
|
+
'ui.parameter': 'Parameter',
|
|
7
|
+
'ui.responses': 'Responses',
|
|
8
|
+
'ui.response': 'Response',
|
|
9
|
+
'ui.request_body': 'Request body',
|
|
10
|
+
'ui.response_body': 'Response body',
|
|
11
|
+
'ui.example_value': 'Example Value',
|
|
12
|
+
'ui.model': 'Model',
|
|
13
|
+
'ui.value': 'Value',
|
|
14
|
+
'ui.description': 'Description',
|
|
15
|
+
'ui.required': 'Required',
|
|
16
|
+
'ui.try_it_out': 'Try it out',
|
|
17
|
+
'ui.execute': 'Execute',
|
|
18
|
+
'ui.cancel': 'Cancel',
|
|
19
|
+
'ui.clear': 'Clear',
|
|
20
|
+
'ui.authorize': 'Authorize',
|
|
21
|
+
'ui.servers': 'Servers',
|
|
22
|
+
'ui.no_parameters': 'No parameters',
|
|
23
|
+
'ui.no_responses': 'No responses',
|
|
24
|
+
'ui.loading': 'LOADING',
|
|
25
|
+
'ui.download': 'Download',
|
|
26
|
+
'ui.available_authorizations': 'Available authorizations',
|
|
27
|
+
'ui.example_lower': 'example',
|
|
5
28
|
'info.description': '**ServeRest is a free REST API that simulates a virtual store to serve as study material for API testing.**\n\n**Don\'t forget to follow the [project author](https://github.com/PauloGoncalvesBH) and star the repository: [github.com/ServeRest/ServeRest](https://github.com/ServeRest/ServeRest)**\n\nThis page documents all routes and how to access them. For more details about ServeRest (how to run locally using Docker or NPM, change authentication timeout, etc), see [the ServeRest repository](https://github.com/serverest/serverest).\n\nUsing Postman? Import the [Swagger JSON](https://raw.githubusercontent.com/ServeRest/ServeRest/trunk/docs/swagger.json) to access the collections.\n\nDoing load testing? Read the \'[Load Testing](https://github.com/ServeRest/ServeRest#teste-de-carga)\' section.\n\n\nThank you ♥ to everyone who supports the project [financially](https://opencollective.com/serverest#section-contributors) or [with code, ideas, and promotion](https://github.com/ServeRest/ServeRest#contribuidores-); thanks to you **more than R$ 2000,00 were donated to the NGO [Todas as letras](https://todasasletras.org/)** so far.\n\nServeRest has a front-end in beta; check it out: [front.serverest.dev](https://front.serverest.dev).\n\nNeed help? [Open an issue](https://github.com/ServeRest/ServeRest/issues) or contact the project maintainer:\n',
|
|
6
29
|
'tags.login.description': 'Authenticate your user to create a cart and, if you are an admin, manage products',
|
|
7
30
|
'tags.usuarios.description': 'Manage users, check login data, and create admin users',
|
|
@@ -2,6 +2,29 @@
|
|
|
2
2
|
'use strict'
|
|
3
3
|
|
|
4
4
|
module.exports = {
|
|
5
|
+
'ui.parameters': 'Parámetros',
|
|
6
|
+
'ui.parameter': 'Parámetro',
|
|
7
|
+
'ui.responses': 'Respuestas',
|
|
8
|
+
'ui.response': 'Respuesta',
|
|
9
|
+
'ui.request_body': 'Cuerpo de la solicitud',
|
|
10
|
+
'ui.response_body': 'Cuerpo de la respuesta',
|
|
11
|
+
'ui.example_value': 'Ejemplo',
|
|
12
|
+
'ui.model': 'Modelo',
|
|
13
|
+
'ui.value': 'Valor',
|
|
14
|
+
'ui.description': 'Descripción',
|
|
15
|
+
'ui.required': 'Obligatorio',
|
|
16
|
+
'ui.try_it_out': 'Probar',
|
|
17
|
+
'ui.execute': 'Ejecutar',
|
|
18
|
+
'ui.cancel': 'Cancelar',
|
|
19
|
+
'ui.clear': 'Limpiar',
|
|
20
|
+
'ui.authorize': 'Autorizar',
|
|
21
|
+
'ui.servers': 'Servidores',
|
|
22
|
+
'ui.no_parameters': 'Sin parámetros',
|
|
23
|
+
'ui.no_responses': 'Sin respuestas',
|
|
24
|
+
'ui.loading': 'Cargando',
|
|
25
|
+
'ui.download': 'Descargar',
|
|
26
|
+
'ui.available_authorizations': 'Autenticaciones disponibles',
|
|
27
|
+
'ui.example_lower': 'ejemplo',
|
|
5
28
|
'info.description': '**ServeRest es una API REST gratuita que simula una tienda virtual para servir como material de estudio para pruebas de API.**\n\n**No olvides seguir al [autor del proyecto](https://github.com/PauloGoncalvesBH) y dar una estrella al repositorio: [github.com/ServeRest/ServeRest](https://github.com/ServeRest/ServeRest)**\n\nEsta página documenta todas las rutas y cómo acceder a ellas. Para más detalles sobre ServeRest (cómo ejecutar localmente usando Docker o NPM, cambiar el tiempo de expiración de autenticación, etc.) visita [el repositorio de ServeRest](https://github.com/serverest/serverest).\n\n¿Usas Postman? Importa el [JSON de Swagger](https://raw.githubusercontent.com/ServeRest/ServeRest/trunk/docs/swagger.json) para acceder a las colecciones.\n\n¿Vas a hacer pruebas de carga? Lee la sección \'[Pruebas de carga](https://github.com/ServeRest/ServeRest#teste-de-carga)\'.\n\n\nMuchas gracias ♥ a todos los que apoyan el proyecto [financieramente](https://opencollective.com/serverest#section-contributors) o [con código, ideas y difusión](https://github.com/ServeRest/ServeRest#contribuidores-), gracias a ustedes **más de R$ 2000,00 fueron donados a la ONG [Todas as letras](https://todasasletras.org/)** hasta el momento.\n\nServeRest tiene un front-end en beta, no dejes de conocerlo: [front.serverest.dev](https://front.serverest.dev).\n\n¿Necesitas ayuda? [Abre un issue](https://github.com/ServeRest/ServeRest/issues) o contacta al mantenedor del proyecto:\n',
|
|
6
29
|
'tags.login.description': 'Autentica a tu usuario para crear un carrito y, si eres administrador, gestionar los productos',
|
|
7
30
|
'tags.usuarios.description': 'Gestiona usuarios, consulta datos para inicio de sesión y crea administradores',
|
|
@@ -2,6 +2,29 @@
|
|
|
2
2
|
'use strict'
|
|
3
3
|
|
|
4
4
|
module.exports = {
|
|
5
|
+
'ui.parameters': 'Parâmetros',
|
|
6
|
+
'ui.parameter': 'Parâmetro',
|
|
7
|
+
'ui.responses': 'Respostas',
|
|
8
|
+
'ui.response': 'Resposta',
|
|
9
|
+
'ui.request_body': 'Corpo da requisição',
|
|
10
|
+
'ui.response_body': 'Corpo da resposta',
|
|
11
|
+
'ui.example_value': 'Exemplo',
|
|
12
|
+
'ui.model': 'Modelo',
|
|
13
|
+
'ui.value': 'Valor',
|
|
14
|
+
'ui.description': 'Descrição',
|
|
15
|
+
'ui.required': 'Obrigatório',
|
|
16
|
+
'ui.try_it_out': 'Testar',
|
|
17
|
+
'ui.execute': 'Executar',
|
|
18
|
+
'ui.cancel': 'Cancelar',
|
|
19
|
+
'ui.clear': 'Limpar',
|
|
20
|
+
'ui.authorize': 'Autorizar',
|
|
21
|
+
'ui.servers': 'Servidores',
|
|
22
|
+
'ui.no_parameters': 'Sem parâmetros',
|
|
23
|
+
'ui.no_responses': 'Sem respostas',
|
|
24
|
+
'ui.loading': 'Carregando',
|
|
25
|
+
'ui.download': 'Baixar',
|
|
26
|
+
'ui.available_authorizations': 'Autenticações disponíveis',
|
|
27
|
+
'ui.example_lower': 'exemplo',
|
|
5
28
|
'info.description': '**O ServeRest é uma API REST gratuita que simula uma loja virtual com intuito de servir de material de estudos de testes de API.**\n\n**Não deixe de seguir o [autor do projeto](https://github.com/PauloGoncalvesBH) e deixar um star no repositório: [github.com/ServeRest/ServeRest](https://github.com/ServeRest/ServeRest)**\n\nEssa página documenta todas as rotas e como acessá-las. Para mais detalhes do ServeRest (como executar localmente utilizando Docker ou NPM, alterar timeout de autenticação, etc) acesse [o repositório do ServeRest](https://github.com/serverest/serverest).\n\nEstá utilizando Postman? Importe o [JSON do Swagger](https://raw.githubusercontent.com/ServeRest/ServeRest/trunk/docs/swagger.json) para ter acesso às collections.\n\nVai fazer teste de carga? Leia a seção \'[Teste de Carga](https://github.com/ServeRest/ServeRest#teste-de-carga)\'.\n\n\nMuito obrigado ♥ a todos que apoiam o projeto [financeiramente](https://opencollective.com/serverest#section-contributors) ou [com código, ideias e divulgação](https://github.com/ServeRest/ServeRest#contribuidores-), graças a vocês **mais de R$ 2000,00 foram doados para a ONG [Todas as letras](https://todasasletras.org/)** até o momento.\n\nO ServeRest possui um front, com status em beta, não deixe de conhecer: [front.serverest.dev](https://front.serverest.dev).\n\nPrecisa de apoio? [Abra uma issue](https://github.com/ServeRest/ServeRest/issues) ou contate o mantenedor do projeto:\n',
|
|
6
29
|
'tags.login.description': 'Autentique o seu usuário para montar um carrinho e, se for administrador, gerenciar os produtos',
|
|
7
30
|
'tags.usuarios.description': 'Gerencie os usuários, consulte dados para login e cadastre administrador',
|