Skip to content

Commit c1635ca

Browse files
committed
fix swagger $ref resolve error
1 parent af34300 commit c1635ca

6 files changed

Lines changed: 81 additions & 59 deletions

File tree

package-lock.json

Lines changed: 17 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@
2424
"author": "qazsato <qazsato@gmail.com>",
2525
"license": "MIT",
2626
"dependencies": {
27-
"@apidevtools/json-schema-ref-parser": "^11.7.2",
27+
"@apidevtools/json-schema-ref-parser": "^14.1.0",
2828
"commander": "^12.1.0",
2929
"ejs": "^3.1.10",
3030
"inquirer": "^12.0.0",
31-
"js-yaml": "^4.1.0"
31+
"js-yaml": "^4.1.0",
32+
"safe-stable-stringify": "^2.5.0"
3233
},
3334
"devDependencies": {
3435
"@eslint/js": "^9.13.0",

src/constants/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1-
export const UI = ['stoplight', 'swagger', 'redoc']
1+
export const UI = {
2+
STOPLIGHT: 'stoplight',
3+
SWAGGER: 'swagger',
4+
REDOC: 'redoc',
5+
}
26
export const THEME = ['light', 'dark']
37
export const ENABLE_INPUT_EXTS = ['.json', '.yaml', '.yml']

src/index.js

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@
22
import { program } from 'commander'
33
import inquirer from 'inquirer'
44
import fs from 'fs'
5-
import yaml from 'js-yaml'
65
import ejs from 'ejs'
76
import path from 'path'
87
import { fileURLToPath } from 'url'
9-
import $RefParser from '@apidevtools/json-schema-ref-parser'
108
import { UI } from './constants/index.js'
119
import {
1210
validateCommandInput,
@@ -16,9 +14,8 @@ import {
1614
validateInquirerInput,
1715
validateInquirerOutput,
1816
isValidUrl,
19-
isJSON,
20-
isYAML,
2117
} from './utils/validate.js'
18+
import { parseOpenApi } from './utils/parser.js'
2219

2320
const __filename = fileURLToPath(import.meta.url)
2421
const __dirname = path.dirname(__filename)
@@ -50,7 +47,11 @@ function getCliOptions() {
5047
'Output HTML file name',
5148
validateCommandOutput,
5249
)
53-
.option('--ui <ui>', `Choose UI (${UI.join(', ')})`, validateCommandUi)
50+
.option(
51+
'--ui <ui>',
52+
`Choose UI (${Object.values(UI).join(', ')})`,
53+
validateCommandUi,
54+
)
5455
.option('--title <title>', 'Title of the HTML page', 'OpenAPI Docs')
5556
.option('--description <description>', 'Description of the HTML page', '')
5657
.option(
@@ -68,8 +69,8 @@ async function askQuestions(options) {
6869
type: 'list',
6970
name: 'ui',
7071
message: 'Which UI would you like to use?',
71-
default: UI[0],
72-
choices: UI,
72+
default: UI.STOPLIGHT,
73+
choices: Object.values(UI),
7374
when: !options.ui,
7475
},
7576
{
@@ -114,29 +115,15 @@ async function renderOpenApiHtml(result) {
114115
} else {
115116
rawApiDocsText = fs.readFileSync(input, 'utf-8')
116117
}
117-
118-
let rawApiDocs
119-
if (isJSON(rawApiDocsText)) {
120-
rawApiDocs = JSON.parse(rawApiDocsText)
121-
} else if (isYAML(rawApiDocsText)) {
122-
rawApiDocs = yaml.load(rawApiDocsText)
123-
} else {
124-
throw new Error(
125-
'Unsupported file format. Please provide a .json or .yaml/.yml file.',
126-
)
127-
}
128-
129-
// resolve $ref pointers
130-
// https://github.com/APIDevTools/json-schema-ref-parser/blob/main/docs/ref-parser.md#bundleschema-options-callback
131-
const apiDocs = await $RefParser.bundle(rawApiDocs)
118+
const apiDocs = await parseOpenApi(rawApiDocsText, ui)
132119

133120
return ejs.render(template, {
134121
theme: result.theme,
135122
title: result.title,
136123
description: result.description,
137124
jsContent,
138125
cssContent,
139-
apiDocs: JSON.stringify(apiDocs),
126+
apiDocs,
140127
})
141128
}
142129

src/utils/parser.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import $RefParser from '@apidevtools/json-schema-ref-parser'
2+
import stringify from 'safe-stable-stringify'
3+
import yaml from 'js-yaml'
4+
import { UI } from '../constants/index.js'
5+
6+
export async function parseOpenApi(rawApiDocsText, ui) {
7+
let rawApiDocs
8+
if (isJSON(rawApiDocsText)) {
9+
rawApiDocs = JSON.parse(rawApiDocsText)
10+
} else if (isYAML(rawApiDocsText)) {
11+
rawApiDocs = yaml.load(rawApiDocsText)
12+
} else {
13+
throw new Error(
14+
'Unsupported file format. Please provide a .json or .yaml/.yml file.',
15+
)
16+
}
17+
// resolve $ref pointers
18+
if (ui === UI.SWAGGER) {
19+
// https://github.com/APIDevTools/json-schema-ref-parser/blob/main/docs/ref-parser.md#dereferenceschema-options-callback
20+
const apiDocs = await $RefParser.dereference(rawApiDocs)
21+
return stringify(apiDocs)
22+
}
23+
// https://github.com/APIDevTools/json-schema-ref-parser/blob/main/docs/ref-parser.md#bundleschema-options-callback
24+
const apiDocs = await $RefParser.bundle(rawApiDocs)
25+
return JSON.stringify(apiDocs)
26+
}
27+
28+
function isJSON(string) {
29+
try {
30+
JSON.parse(string)
31+
return true
32+
} catch {
33+
return false
34+
}
35+
}
36+
37+
function isYAML(string) {
38+
try {
39+
yaml.load(string)
40+
return true
41+
} catch {
42+
return false
43+
}
44+
}

src/utils/validate.js

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import yaml from 'js-yaml'
21
import { InvalidArgumentError } from 'commander'
32
import { UI, THEME, ENABLE_INPUT_EXTS } from '../constants/index.js'
43

@@ -22,8 +21,8 @@ export function validateCommandOutput(output) {
2221
}
2322

2423
export function validateCommandUi(ui) {
25-
if (!UI.includes(ui)) {
26-
const message = `Please choose from: ${UI.join(', ')}.`
24+
if (!Object.values(UI).includes(ui)) {
25+
const message = `Please choose from: ${Object.values(UI).join(', ')}.`
2726
throw new InvalidArgumentError(message)
2827
}
2928
return ui
@@ -63,24 +62,6 @@ export function isValidUrl(string) {
6362
}
6463
}
6564

66-
export function isJSON(string) {
67-
try {
68-
JSON.parse(string)
69-
return true
70-
} catch {
71-
return false
72-
}
73-
}
74-
75-
export function isYAML(string) {
76-
try {
77-
yaml.load(string)
78-
return true
79-
} catch {
80-
return false
81-
}
82-
}
83-
8465
function isValidInput(input) {
8566
if (isValidUrl(input)) {
8667
return true

0 commit comments

Comments
 (0)