Skip to content
This repository has been archived by the owner on Aug 28, 2024. It is now read-only.

feat: fetch urls, fix #67 #95

Merged
merged 35 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
e9237aa
feat: add new load util, add file support
hanspagel May 13, 2024
c3acf06
feat: add url plugin
hanspagel May 13, 2024
6677240
refactor: new pipeline api (wip)
hanspagel May 13, 2024
bdd258a
feat: support urls in specifications (wip)
hanspagel May 13, 2024
5032c63
fix: details action is broken
hanspagel May 23, 2024
5aae4fb
refactor: make all pipeline actions work with the queue
hanspagel May 23, 2024
68ff827
refactor: move files around
hanspagel May 23, 2024
96b556a
refactor: rename resolve to dereference
hanspagel May 23, 2024
4fb48b2
docs(changeset): refactor!: when using the pipeline syntax all tasks …
hanspagel May 23, 2024
38ab089
docs(changeset): refactor!: resolve is renamed to dereference
hanspagel May 23, 2024
24f53bc
docs: rewrite the section about file references
hanspagel May 23, 2024
45e9d1b
chore: remove loadFiles utility
hanspagel May 23, 2024
b330c88
docs(changeset): chore!: remove `loadFiles` utility, use `load` instead
hanspagel May 23, 2024
3b59b29
chore: export load utility and all plugins
hanspagel May 23, 2024
2a962dd
chore: add failing test
hanspagel May 23, 2024
fa116fc
fix: file references inside referenced files are broken
hanspagel May 23, 2024
75d3cb4
fix: TS issues
hanspagel May 23, 2024
8674ddc
fix: build
hanspagel May 23, 2024
0ea45cb
chore: exclude all node modules
hanspagel May 23, 2024
68670d7
docs: wording
hanspagel May 23, 2024
89103d8
docs: fix broken import in example
hanspagel May 23, 2024
6ad038b
feat: new pipeline action to get the filesystem
hanspagel May 24, 2024
c01c4d9
refactor: simplify the action queue
hanspagel May 24, 2024
33e02b7
fix: TS issues
hanspagel May 24, 2024
5728fdf
test: filesystem with multiple files has the correct structure
hanspagel May 24, 2024
4f39eb1
feat: better error messages
hanspagel May 24, 2024
ea58615
chore: clean up
hanspagel May 24, 2024
1673346
fix: build
hanspagel May 24, 2024
7139ca8
chore: better types
hanspagel May 24, 2024
4ffbdb9
fix: TS issues
hanspagel May 24, 2024
740ed85
chore: update lock file
hanspagel May 24, 2024
12d4f5b
docs: fix example
hanspagel May 24, 2024
8e7866a
fix: tests
hanspagel May 24, 2024
135242c
fix: typo
hanspagel May 24, 2024
78cd843
fix: doesn’t load urls in passed strings
hanspagel May 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/afraid-parents-burn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@scalar/openapi-parser': minor
---

refactor!: resolve is renamed to dereference
5 changes: 5 additions & 0 deletions .changeset/pink-birds-trade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@scalar/openapi-parser': minor
---

refactor!: when using the pipeline syntax all tasks are queued and only executed when you add .get(), .toJson() or toYaml()
5 changes: 5 additions & 0 deletions .changeset/tasty-donuts-smash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@scalar/openapi-parser': minor
---

chore!: remove `loadFiles` utility, use `load` instead
27 changes: 17 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ if (!result.valid) {
### Resolve references

```ts
import { resolve } from '@scalar/openapi-parser'
import { dereference } from '@scalar/openapi-parser'

const specification = `{
"openapi": "3.1.0",
Expand All @@ -67,7 +67,7 @@ const specification = `{
"paths": {}
}`

const result = await resolve(specification)
const result = await dereference(specification)
```

## Modify an OpenAPI specification
Expand Down Expand Up @@ -128,21 +128,28 @@ const result = openapi()
.get()
```

## Advanced: File references
## Advanced: URL and file references

You can reference other files, too. To do that, the parser needs to know what files are available.

```ts
import { loadFiles } from '@scalar/openapi-parser'
import {
dereference,
fetchUrlsPlugin,
load,
readFilesPlugin,
} from '@scalar/openapi-parser'

// Load a file and all referenced files
const filesystem = await load('./openapi.yaml', {
plugins: [readFilesPlugin, fetchUrlsPlugin],
})

// load a file and all referenced files
const filesystem = loadFiles('./openapi.yaml')
// instead of just passing a single specification, pass the whole “filesystem”
const result = await resolve(filesystem)
// Instead of just passing a single specification, pass the whole “filesystem”
const result = await dereference(filesystem)
```

You don’t have to use `loadFiles`, though. You just need to stick to the format. That enables you store the files
wherever you want (maybe in a database?) or to use the package in a browser environment.
As you see, `load()` supports plugin. You can write your own plugin, if you’d like to fetch API defintions from another data source, for example your database. Look at the source code of the `readFilesPlugin` to learn how this could look like.

## Community

Expand Down
31 changes: 25 additions & 6 deletions demo/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
<script setup lang="ts">
import { normalize, resolveReferences, toJson } from '@scalar/openapi-parser'
import { fetchUrlsPlugin, openapi } from '@scalar/openapi-parser'
import { onMounted, ref, watch } from 'vue'
const value = ref(
JSON.stringify(
{
openapi: '3.1.0',
info: {
title: 'Hello World',
version: '1.0.0',
info: {},
paths: {
'/foobar': {
post: {
requestBody: {
$ref: '#/components/requestBodies/Foobar',
},
},
},
},
components: {
requestBodies: {
Foobar: {
content: {},
},
},
},
paths: {},
},
null,
2,
Expand All @@ -34,7 +46,14 @@ watch(value, async (newValue) => {
watch(
value,
async (newValue) => {
result.value = toJson(resolveReferences(normalize(newValue)))
result.value = (
await openapi()
.load(newValue, {
plugins: [fetchUrlsPlugin],
})
.dereference()
.get()
)?.schema
},
{
immediate: true,
Expand Down
17 changes: 12 additions & 5 deletions demo/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
import vue from '@vitejs/plugin-vue'
import { builtinModules } from 'node:module'
import path from 'node:path'
import { defineConfig } from 'vite'

// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
build: {
rollupOptions: {
external: [...builtinModules, ...builtinModules.map((m) => `node:${m}`)],
},
},
resolve: {
alias: [
// Resolve the uncompiled source code for all @scalar packages
// It’s working with the alias, too. It’s just required to enable HMR.
// It also does not match components since we want the built version
{
// Resolve the uncompiled source code for all @scalar packages
// @scalar/* -> packages/*/
// (not @scalar/components/*/style.css)
find: /^@scalar\/(?!(openapi-parser|snippetz|components\/style\.css|components\b))(.+)/,
replacement: path.resolve(__dirname, '../packages/$2/src/index.ts'),
// Resolve the uncompiled source code for @scalar/openapi-parser packages
find: '@scalar/openapi-parser',
replacement: path.resolve(
__dirname,
'../packages/openapi-parser/src/index.ts',
),
},
],
},
Expand Down
8 changes: 4 additions & 4 deletions packages/openapi-parser/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ npm add @scalar/openapi-parser
### Parse

```ts
import { resolve } from '@scalar/openapi-parser'
import { dereference } from '@scalar/openapi-parser'

const file = `{
"openapi": "3.1.0",
Expand All @@ -30,7 +30,7 @@ const file = `{
"paths": {}
}`

const result = await resolve(file)
const result = await dereference(file)
```

### Validate
Expand Down Expand Up @@ -59,7 +59,7 @@ if (!result.valid) {
### Version

```ts
import { resolve } from '@scalar/openapi-parser'
import { dereference } from '@scalar/openapi-parser'

const file = `{
"openapi": "3.1.0",
Expand All @@ -70,7 +70,7 @@ const file = `{
"paths": {}
}`

const result = await resolve(file)
const result = await dereference(file)

console.log(result.version)
```
2 changes: 1 addition & 1 deletion packages/openapi-parser/createProfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ const specification = {
paths: {},
}

await openapi().load(structuredClone(specification)).resolve()
await openapi().load(structuredClone(specification)).dereference().get()

console.profileEnd()
1 change: 0 additions & 1 deletion packages/openapi-parser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
"ajv-formats": "^3.0.1",
"jsonpointer": "^5.0.1",
"leven": "^4.0.0",
"openapi-types": "^12.1.3",
"yaml": "^2.4.2"
}
}
1 change: 1 addition & 0 deletions packages/openapi-parser/src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export const ERRORS = {
'Cannot find supported Swagger/OpenAPI version in specification, version must be a string.',
INVALID_REFERENCE: 'Can’t resolve reference: %s',
EXTERNAL_REFERENCE_NOT_FOUND: 'Can’t resolve external reference: %s',
FILE_DOES_NOT_EXIST: 'File does not exist: %s',
} as const

export type VALIDATOR_ERROR = keyof typeof ERRORS
Loading