@kubb/adapter-oas 5.0.0-beta.4 → 5.0.0-beta.40

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/src/adapter.ts CHANGED
@@ -1,21 +1,26 @@
1
1
  import { ast, createAdapter } from '@kubb/core'
2
+ import type { AdapterSource } from '@kubb/core'
3
+ import BaseOas from 'oas'
2
4
  import { DEFAULT_PARSER_OPTIONS } from './constants.ts'
3
- import { applyDiscriminatorInheritance } from './discriminator.ts'
4
- import { parseFromConfig, validateDocument } from './factory.ts'
5
- import { parseOas } from './parser.ts'
6
- import { resolveServerUrl } from './resolvers.ts'
5
+ import { assertInputExists, parseDocument, parseFromConfig, validateDocument } from './factory.ts'
6
+ import { createSchemaParser } from './parser.ts'
7
+ import { getSchemas } from './resolvers.ts'
8
+ import { createInputStream, preScan, resolveBaseUrl } from './stream.ts'
7
9
  import type { AdapterOas, Document } from './types.ts'
8
10
 
9
11
  /**
10
- * Stable string identifier for the OAS adapter used in Kubb's adapter registry.
12
+ * Canonical adapter name for `@kubb/adapter-oas`. Used for driver lookups.
11
13
  */
12
14
  export const adapterOasName = 'oas' satisfies AdapterOas['name']
13
15
 
14
16
  /**
15
- * Creates the default OpenAPI / Swagger adapter for Kubb.
17
+ * Default Kubb adapter for OpenAPI 2.0, 3.0, and 3.1 specifications. Reads the
18
+ * file at `input.path`, validates it, resolves the base URL, and converts every
19
+ * schema and operation into the universal AST that every downstream plugin
20
+ * consumes.
16
21
  *
17
- * Parses the spec, optionally validates it, resolves the base URL, and converts
18
- * everything into an `InputNode` that downstream plugins consume.
22
+ * Configure once on `defineConfig`. The adapter's choices (date representation,
23
+ * integer width, server URL) apply to every plugin in the build.
19
24
  *
20
25
  * @example
21
26
  * ```ts
@@ -24,8 +29,13 @@ export const adapterOasName = 'oas' satisfies AdapterOas['name']
24
29
  * import { pluginTs } from '@kubb/plugin-ts'
25
30
  *
26
31
  * export default defineConfig({
27
- * adapter: adapterOas({ dateType: 'date', serverIndex: 0 }),
28
- * input: { path: './openapi.yaml' },
32
+ * input: { path: './petStore.yaml' },
33
+ * output: { path: './src/gen' },
34
+ * adapter: adapterOas({
35
+ * serverIndex: 0,
36
+ * discriminator: 'inherit',
37
+ * dateType: 'date',
38
+ * }),
29
39
  * plugins: [pluginTs()],
30
40
  * })
31
41
  * ```
@@ -37,6 +47,7 @@ export const adapterOas = createAdapter<AdapterOas>((options) => {
37
47
  serverIndex,
38
48
  serverVariables,
39
49
  discriminator = 'strict',
50
+ dedupe = true,
40
51
  dateType = DEFAULT_PARSER_OPTIONS.dateType,
41
52
  integerType = DEFAULT_PARSER_OPTIONS.integerType,
42
53
  unknownType = DEFAULT_PARSER_OPTIONS.unknownType,
@@ -44,10 +55,115 @@ export const adapterOas = createAdapter<AdapterOas>((options) => {
44
55
  emptySchemaType = unknownType || DEFAULT_PARSER_OPTIONS.emptySchemaType,
45
56
  } = options
46
57
 
47
- // Let-binding so parse() can replace it with a simple reassignment (no clear+loop).
58
+ const parserOptions: ast.ParserOptions = {
59
+ ...DEFAULT_PARSER_OPTIONS,
60
+ dateType,
61
+ integerType,
62
+ unknownType,
63
+ emptySchemaType,
64
+ enumSuffix,
65
+ }
66
+
48
67
  let nameMapping = new Map<string, string>()
49
- let parsedDocument: Document | null
50
- let inputNode: ast.InputNode | null
68
+ let parsedDocument: Document | null = null
69
+
70
+ // Cache per source and per document so one adapter instance reused across a `defineConfig` array
71
+ // parses each config's spec instead of replaying the first one. Keying the document by its source
72
+ // object still collapses a config's concurrent `stream()` (build) and `parse()` (studio) calls,
73
+ // which share one source object, onto a single parse. The document-derived caches key off the
74
+ // resulting document, so distinct configs (distinct documents) stay isolated.
75
+ const documentCache = new WeakMap<AdapterSource, Promise<Document>>()
76
+ const schemasCache = new WeakMap<Document, Promise<ReturnType<typeof getSchemas>['schemas']>>()
77
+ const baseOasCache = new WeakMap<Document, BaseOas>()
78
+ const schemaParserCache = new WeakMap<Document, ReturnType<typeof createSchemaParser>>()
79
+ const preScanCache = new WeakMap<Document, ReturnType<typeof preScan>>()
80
+
81
+ function ensureDocument(source: AdapterSource): Promise<Document> {
82
+ const cached = documentCache.get(source)
83
+ if (cached) return cached
84
+
85
+ const promise = (async () => {
86
+ const fresh = await parseFromConfig(source)
87
+ if (validate) await validateDocument(fresh)
88
+ parsedDocument = fresh
89
+ return fresh
90
+ })()
91
+ documentCache.set(source, promise)
92
+ return promise
93
+ }
94
+
95
+ function ensureSchemas(document: Document): Promise<ReturnType<typeof getSchemas>['schemas']> {
96
+ const cached = schemasCache.get(document)
97
+ if (cached) return cached
98
+
99
+ const promise = Promise.resolve().then(() => {
100
+ const result = getSchemas(document, { contentType })
101
+ nameMapping = result.nameMapping
102
+ return result.schemas
103
+ })
104
+ schemasCache.set(document, promise)
105
+ return promise
106
+ }
107
+
108
+ function ensureBaseOas(document: Document): BaseOas {
109
+ const cached = baseOasCache.get(document)
110
+ if (cached) return cached
111
+
112
+ const baseOas = new BaseOas(document)
113
+ baseOasCache.set(document, baseOas)
114
+ return baseOas
115
+ }
116
+
117
+ function ensureSchemaParser(document: Document): ReturnType<typeof createSchemaParser> {
118
+ const cached = schemaParserCache.get(document)
119
+ if (cached) return cached
120
+
121
+ const parser = createSchemaParser({ document, contentType })
122
+ schemaParserCache.set(document, parser)
123
+ return parser
124
+ }
125
+
126
+ function ensurePreScan(
127
+ document: Document,
128
+ schemas: ReturnType<typeof getSchemas>['schemas'],
129
+ parseSchema: ReturnType<typeof ensureSchemaParser>['parseSchema'],
130
+ parseOperation: ReturnType<typeof ensureSchemaParser>['parseOperation'],
131
+ baseOas: BaseOas,
132
+ ): ReturnType<typeof preScan> {
133
+ const cached = preScanCache.get(document)
134
+ if (cached) return cached
135
+
136
+ const result = preScan({ schemas, parseSchema, parseOperation, baseOas, parserOptions, discriminator, dedupe })
137
+ preScanCache.set(document, result)
138
+ return result
139
+ }
140
+
141
+ async function createStream(source: AdapterSource): Promise<ast.InputStreamNode> {
142
+ const document = await ensureDocument(source)
143
+ const schemas = await ensureSchemas(document)
144
+ const { parseSchema, parseOperation } = ensureSchemaParser(document)
145
+ const baseOas = ensureBaseOas(document)
146
+ const { refAliasMap, enumNames, circularNames, discriminatorChildMap, dedupePlan } = ensurePreScan(document, schemas, parseSchema, parseOperation, baseOas)
147
+
148
+ return createInputStream({
149
+ schemas,
150
+ parseSchema,
151
+ parseOperation,
152
+ baseOas,
153
+ parserOptions,
154
+ refAliasMap,
155
+ discriminatorChildMap,
156
+ dedupePlan,
157
+ meta: {
158
+ title: document.info?.title,
159
+ description: document.info?.description,
160
+ version: document.info?.version,
161
+ baseURL: resolveBaseUrl({ document, serverIndex, serverVariables }),
162
+ circularNames,
163
+ enumNames,
164
+ },
165
+ })
166
+ }
51
167
 
52
168
  return {
53
169
  name: adapterOasName,
@@ -58,6 +174,7 @@ export const adapterOas = createAdapter<AdapterOas>((options) => {
58
174
  serverIndex,
59
175
  serverVariables,
60
176
  discriminator,
177
+ dedupe,
61
178
  dateType,
62
179
  integerType,
63
180
  unknownType,
@@ -69,8 +186,10 @@ export const adapterOas = createAdapter<AdapterOas>((options) => {
69
186
  get document() {
70
187
  return parsedDocument
71
188
  },
72
- get inputNode() {
73
- return inputNode
189
+ async validate(input, options) {
190
+ await assertInputExists(input)
191
+ const document = await parseDocument(input)
192
+ await validateDocument(document, options)
74
193
  },
75
194
  getImports(node, resolve) {
76
195
  return ast.collectImports({
@@ -78,49 +197,25 @@ export const adapterOas = createAdapter<AdapterOas>((options) => {
78
197
  nameMapping,
79
198
  resolve: (schemaName) => {
80
199
  const result = resolve(schemaName)
81
- if (!result) return
200
+ if (!result) return null
82
201
 
83
202
  return ast.createImport({ name: [result.name], path: result.path })
84
203
  },
85
204
  })
86
205
  },
87
206
  async parse(source) {
88
- const document = await parseFromConfig(source)
207
+ const streamNode = await createStream(source)
89
208
 
90
- if (validate) {
91
- await validateDocument(document)
209
+ const collect = async <T>(iter: AsyncIterable<T>): Promise<Array<T>> => {
210
+ const out: Array<T> = []
211
+ for await (const item of iter) out.push(item)
212
+ return out
92
213
  }
93
214
 
94
- const server = serverIndex !== undefined ? document.servers?.at(serverIndex) : undefined
95
- const baseURL = server?.url ? resolveServerUrl(server, serverVariables) : undefined
96
-
97
- const { root: parsedRoot, nameMapping: parsedNameMapping } = parseOas(document, {
98
- contentType,
99
- dateType,
100
- integerType,
101
- unknownType,
102
- emptySchemaType,
103
- enumSuffix,
104
- })
105
-
106
- const node = discriminator === 'inherit' ? applyDiscriminatorInheritance(parsedRoot) : parsedRoot
107
-
108
- // This must happen after parseOas() because legacy enum remapping is finalized there.
109
- nameMapping = parsedNameMapping
110
- // Expose the raw document so consumers (e.g. plugin-redoc) can access it.
111
- parsedDocument = document
112
-
113
- inputNode = ast.createInput({
114
- ...node,
115
- meta: {
116
- title: document.info?.title,
117
- description: document.info?.description,
118
- version: document.info?.version,
119
- baseURL,
120
- },
121
- })
215
+ const [schemas, operations] = await Promise.all([collect(streamNode.schemas), collect(streamNode.operations)])
122
216
 
123
- return inputNode
217
+ return ast.createInput({ schemas, operations, meta: streamNode.meta })
124
218
  },
219
+ stream: createStream,
125
220
  }
126
221
  })
package/src/constants.ts CHANGED
@@ -79,6 +79,14 @@ export const structuralKeys = new Set(['properties', 'items', 'additionalPropert
79
79
  * formatMap['float'] // 'number'
80
80
  * ```
81
81
  */
82
+ /**
83
+ * Formats `convertFormat` maps to a dedicated type without going through `formatMap`:
84
+ * `int64` and the date/time family. Keep this in sync with the `convertFormat`
85
+ * special-cases in `parser.ts`. `isHandledFormat` reads it so the
86
+ * `KUBB_UNSUPPORTED_FORMAT` diagnostic and the parser agree on what is handled.
87
+ */
88
+ export const specialCasedFormats: ReadonlySet<string> = new Set(['int64', 'date-time', 'date', 'time'])
89
+
82
90
  export const formatMap = {
83
91
  uuid: 'uuid',
84
92
  email: 'email',
package/src/dialect.ts ADDED
@@ -0,0 +1,38 @@
1
+ import { ast } from '@kubb/core'
2
+ import { isDiscriminator, isNullable, isReference } from './guards.ts'
3
+ import { resolveRef } from './refs.ts'
4
+ import type { SchemaObject } from './types.ts'
5
+
6
+ /**
7
+ * The OpenAPI / Swagger dialect, the default used by `@kubb/adapter-oas`.
8
+ *
9
+ * Implements the spec-agnostic {@link ast.SchemaDialect} contract: it isolates the
10
+ * decisions that differ between specs (nullability, `$ref`, discriminator, binary,
11
+ * ref resolution) so the converter pipeline and dispatch rules stay shared. A
12
+ * future adapter (e.g. AsyncAPI) ships its own dialect, `type: ['null', …]`
13
+ * nullability, no discriminator object, binary via `contentEncoding` and reuses
14
+ * the rest unchanged.
15
+ *
16
+ * Formats (`uuid`, `email`, dates, …) are intentionally NOT here: they are shared
17
+ * JSON Schema vocabulary, so the converters keep that common case.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * const parser = createSchemaParser(context) // uses oasDialect
22
+ * const parser = createSchemaParser(context, oasDialect) // explicit
23
+ * ```
24
+ */
25
+ export const oasDialect = ast.defineSchemaDialect({
26
+ name: 'oas',
27
+ isNullable,
28
+ isReference,
29
+ isDiscriminator,
30
+ isBinary: (schema: SchemaObject) => schema.type === 'string' && schema.contentMediaType === 'application/octet-stream',
31
+ resolveRef,
32
+ })
33
+
34
+ /**
35
+ * The concrete dialect type for `@kubb/adapter-oas`. Keeps the OAS guard predicates
36
+ * (`isReference`, `isDiscriminator`) intact so converters narrow schemas after a check.
37
+ */
38
+ export type OasDialect = typeof oasDialect
@@ -1,29 +1,22 @@
1
1
  import { ast } from '@kubb/core'
2
+ import type { SchemaNodeByType } from '@kubb/ast'
2
3
 
3
- type DiscriminatorTarget = {
4
+ export type DiscriminatorTarget = {
4
5
  propertyName: string
5
6
  enumValues: Array<string | number | boolean>
6
7
  }
7
8
 
8
9
  /**
9
- * Injects discriminator enum values into child schemas so they know which value identifies them.
10
+ * Builds a map of child schema names discriminator patch data by scanning the given
11
+ * top-level AST schema nodes for union schemas that carry a `discriminatorPropertyName`.
10
12
  *
11
- * Finds every union schema in `input.schemas` that has a `discriminatorPropertyName`, collects the
12
- * enum value each union member is mapped to, then adds (or replaces) that property on the matching
13
- * child object schema.
14
- *
15
- * Returns a new `InputNode` — the original is never mutated.
16
- *
17
- * @example
18
- * ```ts
19
- * const { root } = parseOas(document, options)
20
- * const next = applyDiscriminatorInheritance(root)
21
- * ```
13
+ * The streaming path calls this on a small pre-parsed subset of schemas (only the
14
+ * discriminator parents) rather than on all schemas at once.
22
15
  */
23
- export function applyDiscriminatorInheritance(root: ast.InputNode): ast.InputNode {
16
+ export function buildDiscriminatorChildMap(schemas: Array<ast.SchemaNode>): Map<string, DiscriminatorTarget> {
24
17
  const childMap = new Map<string, DiscriminatorTarget>()
25
18
 
26
- for (const schema of root.schemas) {
19
+ for (const schema of schemas) {
27
20
  // Case 1: top-level schema is a union (oneOf/anyOf with discriminator)
28
21
  // Case 2: top-level schema is an intersection wrapping a union (oneOf/anyOf + shared properties)
29
22
  let unionNode = ast.narrowSchema(schema, 'union')
@@ -50,8 +43,8 @@ export function applyDiscriminatorInheritance(root: ast.InputNode): ast.InputNod
50
43
  const intersectionNode = ast.narrowSchema(member, 'intersection')
51
44
  if (!intersectionNode?.members) continue
52
45
 
53
- let refNode: ReturnType<typeof ast.narrowSchema<'ref'>> | undefined
54
- let objNode: ReturnType<typeof ast.narrowSchema<'object'>> | undefined
46
+ let refNode: SchemaNodeByType['ref'] | null = null
47
+ let objNode: SchemaNodeByType['object'] | null = null
55
48
 
56
49
  for (const m of intersectionNode.members) {
57
50
  refNode ??= ast.narrowSchema(m, 'ref')
@@ -61,48 +54,39 @@ export function applyDiscriminatorInheritance(root: ast.InputNode): ast.InputNod
61
54
  if (!refNode?.name || !objNode) continue
62
55
 
63
56
  const prop = objNode.properties.find((p) => p.name === discriminatorPropertyName)
64
- const enumNode = prop ? ast.narrowSchema(prop.schema, 'enum') : undefined
57
+ const enumNode = prop ? ast.narrowSchema(prop.schema, 'enum') : null
65
58
  if (!enumNode?.enumValues?.length) continue
66
59
 
67
60
  const enumValues = enumNode.enumValues.filter((v): v is string | number | boolean => v !== null)
68
61
  if (!enumValues.length) continue
69
62
 
70
63
  const existing = childMap.get(refNode.name)
71
- if (existing) {
72
- existing.enumValues.push(...enumValues)
73
- } else {
74
- childMap.set(refNode.name, {
75
- propertyName: discriminatorPropertyName,
76
- enumValues: [...enumValues],
77
- })
64
+ if (!existing) {
65
+ childMap.set(refNode.name, { propertyName: discriminatorPropertyName, enumValues: [...enumValues] })
66
+ continue
78
67
  }
68
+ existing.enumValues.push(...enumValues)
79
69
  }
80
70
  }
81
71
 
82
- if (childMap.size === 0) return root
83
-
84
- return ast.transform(root, {
85
- schema(node, { parent }) {
86
- if (parent?.kind !== 'Input' || !node.name) return
87
-
88
- const entry = childMap.get(node.name)
89
- if (!entry) return
72
+ return childMap
73
+ }
90
74
 
91
- const objectNode = ast.narrowSchema(node, 'object')
92
- if (!objectNode) return
75
+ /**
76
+ * Patches a single top-level `SchemaNode` with its discriminator entry (adds or replaces
77
+ * the discriminant property). Used by the streaming path to apply patches inline per yield
78
+ * without buffering all schemas.
79
+ */
80
+ export function patchDiscriminatorNode(node: ast.SchemaNode, entry: { propertyName: string; enumValues: Array<string | number | boolean> }): ast.SchemaNode {
81
+ const objectNode = ast.narrowSchema(node, 'object')
82
+ if (!objectNode) return node
93
83
 
94
- const { propertyName, enumValues } = entry
95
- const enumSchema = ast.createSchema({ type: 'enum', enumValues })
96
- const newProp = ast.createProperty({
97
- name: propertyName,
98
- required: true,
99
- schema: enumSchema,
100
- })
84
+ const { propertyName, enumValues } = entry
85
+ const enumSchema = ast.createSchema({ type: 'enum', enumValues })
86
+ const newProp = ast.createProperty({ name: propertyName, required: true, schema: enumSchema })
101
87
 
102
- const existingIdx = objectNode.properties.findIndex((p) => p.name === propertyName)
103
- const newProperties = existingIdx >= 0 ? objectNode.properties.map((p, i) => (i === existingIdx ? newProp : p)) : [...objectNode.properties, newProp]
88
+ const existingIdx = objectNode.properties.findIndex((p) => p.name === propertyName)
89
+ const newProperties = existingIdx >= 0 ? objectNode.properties.map((p, i) => (i === existingIdx ? newProp : p)) : [...objectNode.properties, newProp]
104
90
 
105
- return { ...objectNode, properties: newProperties }
106
- },
107
- })
91
+ return { ...objectNode, properties: newProperties }
108
92
  }
package/src/factory.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import path from 'node:path'
2
- import { mergeDeep, URLPath } from '@internals/utils'
2
+ import { exists, mergeDeep, URLPath } from '@internals/utils'
3
+ import { Diagnostics } from '@kubb/core'
3
4
  import type { AdapterSource } from '@kubb/core'
4
5
  import { bundle, loadConfig } from '@redocly/openapi-core'
5
6
  import OASNormalize from 'oas-normalize'
@@ -74,13 +75,16 @@ export async function parseDocument(pathOrApi: string | Document, { canBundle =
74
75
  * ```
75
76
  */
76
77
  export async function mergeDocuments(pathOrApi: Array<string | Document>): Promise<Document> {
77
- const documents: Document[] = []
78
- for (const p of pathOrApi) {
79
- documents.push(await parseDocument(p, { enablePaths: false, canBundle: false }))
80
- }
78
+ const documents = await Promise.all(pathOrApi.map((p) => parseDocument(p, { enablePaths: false, canBundle: false })))
81
79
 
82
80
  if (documents.length === 0) {
83
- throw new Error('No OAS documents provided for merging.')
81
+ throw new Diagnostics.Error({
82
+ code: Diagnostics.code.inputRequired,
83
+ severity: 'error',
84
+ message: 'No OAS documents were provided for merging.',
85
+ help: 'Pass at least one path or document to `input.path`.',
86
+ location: { kind: 'config' },
87
+ })
84
88
  }
85
89
 
86
90
  const seed: Document = {
@@ -102,9 +106,9 @@ export async function mergeDocuments(pathOrApi: Array<string | Document>): Promi
102
106
  * Creates a `Document` from an `AdapterSource`.
103
107
  *
104
108
  * Handles all three source types:
105
- * - `{ type: 'path' }` resolves and bundles a local file path or remote URL.
106
- * - `{ type: 'paths' }` merges multiple file paths into a single document.
107
- * - `{ type: 'data' }` parses an inline string (YAML/JSON) or raw object.
109
+ * - `{ type: 'path' }` resolves and bundles a local file path or remote URL.
110
+ * - `{ type: 'paths' }` merges multiple file paths into a single document.
111
+ * - `{ type: 'data' }` parses an inline string (YAML/JSON) or raw object.
108
112
  *
109
113
  * @example
110
114
  * ```ts
@@ -112,7 +116,7 @@ export async function mergeDocuments(pathOrApi: Array<string | Document>): Promi
112
116
  * const document = await parseFromConfig({ type: 'data', data: '{"openapi":"3.0.0",...}' })
113
117
  * ```
114
118
  */
115
- export function parseFromConfig(source: AdapterSource): Promise<Document> {
119
+ export async function parseFromConfig(source: AdapterSource): Promise<Document> {
116
120
  if (source.type === 'data') {
117
121
  if (typeof source.data === 'object') {
118
122
  return parseDocument(structuredClone(source.data) as Document)
@@ -130,7 +134,29 @@ export function parseFromConfig(source: AdapterSource): Promise<Document> {
130
134
  return parseDocument(source.path)
131
135
  }
132
136
 
133
- return parseDocument(path.resolve(path.dirname(source.path), source.path))
137
+ const resolved = path.resolve(path.dirname(source.path), source.path)
138
+ await assertInputExists(resolved)
139
+ return parseDocument(resolved)
140
+ }
141
+
142
+ /**
143
+ * Throws a coded `KUBB_INPUT_NOT_FOUND` diagnostic when a local input path does not exist.
144
+ * URLs are skipped, and a malformed but readable file is left for `parseDocument` to surface
145
+ * its parse error instead.
146
+ */
147
+ export async function assertInputExists(input: string): Promise<void> {
148
+ if (new URLPath(input).isURL) {
149
+ return
150
+ }
151
+ if (!(await exists(input))) {
152
+ throw new Diagnostics.Error({
153
+ code: Diagnostics.code.inputNotFound,
154
+ severity: 'error',
155
+ message: `Cannot read the file set in \`input.path\` (or via \`kubb generate PATH\`): ${input}`,
156
+ help: 'Check that the path exists and is readable, then set it in `input.path` or pass it as `kubb generate PATH`.',
157
+ location: { kind: 'config' },
158
+ })
159
+ }
134
160
  }
135
161
 
136
162
  /**
@@ -160,6 +186,6 @@ export async function validateDocument(document: Document, { throwOnError = fals
160
186
  throw error
161
187
  }
162
188
 
163
- // Validation failures are non-fatal mirror plugin-oas behavior
189
+ // Validation failures are non-fatal, mirror plugin-oas behavior
164
190
  }
165
191
  }
package/src/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { adapterOas, adapterOasName } from './adapter.ts'
2
- export type { ParseOptions, ValidateDocumentOptions } from './factory.ts'
3
- export { mergeDocuments, parseDocument, parseFromConfig, validateDocument } from './factory.ts'
2
+ export type { ValidateDocumentOptions } from './factory.ts'
3
+ export { mergeDocuments } from './factory.ts'
4
4
  export type {
5
5
  AdapterOas,
6
6
  AdapterOasOptions,