@kubb/adapter-oas 5.0.0-beta.106 → 5.0.0-beta.108
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/README.md +10 -8
- package/dist/index.cjs +83 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +83 -8
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -45,29 +45,31 @@ import { defineConfig } from 'kubb'
|
|
|
45
45
|
import { adapterOas } from '@kubb/adapter-oas'
|
|
46
46
|
|
|
47
47
|
export default defineConfig({
|
|
48
|
-
input:
|
|
49
|
-
path: './openapi.yaml',
|
|
50
|
-
},
|
|
48
|
+
input: './openapi.yaml',
|
|
51
49
|
output: {
|
|
52
50
|
path: './src/gen',
|
|
53
51
|
},
|
|
54
|
-
|
|
52
|
+
adapter: adapterOas(),
|
|
55
53
|
})
|
|
56
54
|
```
|
|
57
55
|
|
|
56
|
+
`input` accepts a file path, a URL, an inline JSON or YAML string, or a parsed spec object.
|
|
57
|
+
|
|
58
58
|
## API
|
|
59
59
|
|
|
60
60
|
### `adapterOas(options?)`
|
|
61
61
|
|
|
62
|
-
Creates the OAS adapter instance. Pass it
|
|
62
|
+
Creates the OAS adapter instance. Pass it as `adapter` in `defineConfig`.
|
|
63
63
|
|
|
64
|
-
### `
|
|
64
|
+
### `adapterOasName`
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
The adapter's name, `'oas'`. Use it to identify this adapter in a Kubb config.
|
|
67
67
|
|
|
68
68
|
### Types
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
The package re-exports the OpenAPI types it works with: `ContentType`, `DiscriminatorObject`, `Document`,
|
|
71
|
+
`MediaTypeObject`, `Operation`, `ReferenceObject`, `ResponseObject`, and `SchemaObject`. Its own option types are
|
|
72
|
+
`AdapterOas`, `AdapterOasOptions`, and `AdapterOasResolvedOptions`.
|
|
71
73
|
|
|
72
74
|
## Supporting Kubb
|
|
73
75
|
|
package/dist/index.cjs
CHANGED
|
@@ -38,8 +38,8 @@ let _kubb_kit = require("@kubb/kit");
|
|
|
38
38
|
const DEFAULT_PARSER_OPTIONS = {
|
|
39
39
|
dateType: "string",
|
|
40
40
|
integerType: "bigint",
|
|
41
|
-
unknownType: "
|
|
42
|
-
emptySchemaType: "
|
|
41
|
+
unknownType: "unknown",
|
|
42
|
+
emptySchemaType: "unknown",
|
|
43
43
|
enumSuffix: "enum"
|
|
44
44
|
};
|
|
45
45
|
/**
|
|
@@ -247,6 +247,20 @@ function pascalCase(text, { prefix = "", suffix = "" } = {}) {
|
|
|
247
247
|
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
|
|
248
248
|
}
|
|
249
249
|
//#endregion
|
|
250
|
+
//#region ../../internals/utils/src/errors.ts
|
|
251
|
+
/**
|
|
252
|
+
* Extracts a human-readable message from any thrown value.
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
* ```ts
|
|
256
|
+
* getErrorMessage(new Error('oops')) // 'oops'
|
|
257
|
+
* getErrorMessage('plain string') // 'plain string'
|
|
258
|
+
* ```
|
|
259
|
+
*/
|
|
260
|
+
function getErrorMessage(value) {
|
|
261
|
+
return value instanceof Error ? value.message : String(value);
|
|
262
|
+
}
|
|
263
|
+
//#endregion
|
|
250
264
|
//#region ../../internals/utils/src/runtime.ts
|
|
251
265
|
/**
|
|
252
266
|
* Detects the JavaScript runtime executing the current process and exposes its name and version.
|
|
@@ -349,11 +363,50 @@ async function read(path) {
|
|
|
349
363
|
//#endregion
|
|
350
364
|
//#region src/load/source.ts
|
|
351
365
|
const urlRegExp = /^https?:\/+/i;
|
|
366
|
+
/**
|
|
367
|
+
* Node reports every connection failure as `TypeError: fetch failed` and keeps the useful part
|
|
368
|
+
* (`connect ECONNREFUSED 127.0.0.1:8000`) on `cause`, one level deeper again when a host resolves
|
|
369
|
+
* to several addresses and the attempts collect into an `AggregateError`.
|
|
370
|
+
*/
|
|
371
|
+
function describeFetchFailure(error) {
|
|
372
|
+
if (error instanceof AggregateError && error.errors.length > 0) return describeFetchFailure(error.errors[0]);
|
|
373
|
+
if (error instanceof Error && error.cause instanceof Error) return describeFetchFailure(error.cause) || error.message;
|
|
374
|
+
return getErrorMessage(error);
|
|
375
|
+
}
|
|
376
|
+
function helpForStatus(status) {
|
|
377
|
+
if (status === 401 || status === 403) return "The server refused the request. Kubb sends no credentials, so serve the document without authentication or download it and set `input` to the local file.";
|
|
378
|
+
if (status === 404) return "Check the URL. Open it in a browser or with `curl` to confirm it serves the OpenAPI document.";
|
|
379
|
+
if (status >= 500) return "The server failed while serving the document. Check that it is healthy, then run Kubb again.";
|
|
380
|
+
return "Open the URL in a browser or with `curl` to see what the server returns, then point `input` at a URL that serves the OpenAPI document.";
|
|
381
|
+
}
|
|
382
|
+
async function fetchSource(url) {
|
|
383
|
+
try {
|
|
384
|
+
return await fetch(url);
|
|
385
|
+
} catch (error) {
|
|
386
|
+
throw new _kubb_core.Diagnostics.Error({
|
|
387
|
+
code: _kubb_core.Diagnostics.code.inputUnreachable,
|
|
388
|
+
severity: "error",
|
|
389
|
+
message: `Cannot reach ${url.href}: ${describeFetchFailure(error)}`,
|
|
390
|
+
help: "Check that the host is running and reachable from this machine. For a local server, start it and confirm the port matches the one in `input`.",
|
|
391
|
+
location: { kind: "config" },
|
|
392
|
+
cause: error instanceof Error ? error : void 0
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
}
|
|
352
396
|
async function readSource(sourcePath) {
|
|
353
397
|
if (urlRegExp.test(sourcePath)) {
|
|
354
398
|
const url = new URL(sourcePath);
|
|
355
|
-
const response = await
|
|
356
|
-
if (!response.ok)
|
|
399
|
+
const response = await fetchSource(url);
|
|
400
|
+
if (!response.ok) {
|
|
401
|
+
const status = response.statusText ? `${response.status} ${response.statusText}` : String(response.status);
|
|
402
|
+
throw new _kubb_core.Diagnostics.Error({
|
|
403
|
+
code: _kubb_core.Diagnostics.code.inputRequestFailed,
|
|
404
|
+
severity: "error",
|
|
405
|
+
message: `The server at ${url.href} answered with HTTP ${status} instead of the OpenAPI document.`,
|
|
406
|
+
help: helpForStatus(response.status),
|
|
407
|
+
location: { kind: "config" }
|
|
408
|
+
});
|
|
409
|
+
}
|
|
357
410
|
return response.text();
|
|
358
411
|
}
|
|
359
412
|
return read(sourcePath);
|
|
@@ -369,7 +422,8 @@ async function resolveSource(sourcePath) {
|
|
|
369
422
|
}
|
|
370
423
|
/**
|
|
371
424
|
* Throws a coded `KUBB_INPUT_NOT_FOUND` diagnostic when a local input path does not exist.
|
|
372
|
-
* URLs are skipped
|
|
425
|
+
* URLs are skipped: a remote input reports `KUBB_INPUT_REQUEST_FAILED` or `KUBB_INPUT_UNREACHABLE`
|
|
426
|
+
* from the request itself. A malformed but readable file is left for `parseDocument` to surface
|
|
373
427
|
* its parse error instead.
|
|
374
428
|
*/
|
|
375
429
|
async function assertInputExists(input) {
|
|
@@ -449,6 +503,24 @@ async function parseFromConfig(source) {
|
|
|
449
503
|
return parseDocument(resolved);
|
|
450
504
|
}
|
|
451
505
|
/**
|
|
506
|
+
* Asserts the parsed input is an OpenAPI or Swagger document.
|
|
507
|
+
*
|
|
508
|
+
* {@link validateDocument} keeps spec violations non-fatal so imperfect but usable documents still
|
|
509
|
+
* generate. That leniency also swallowed input that is not a document at all, which then produced
|
|
510
|
+
* an empty build with a success exit code. A missing version field is the one failure that cannot
|
|
511
|
+
* be a usable document, so it is fatal regardless of the `validate` option.
|
|
512
|
+
*/
|
|
513
|
+
function assertDocument(document) {
|
|
514
|
+
if (document && ("openapi" in document || "swagger" in document)) return;
|
|
515
|
+
throw new _kubb_core.Diagnostics.Error({
|
|
516
|
+
code: _kubb_core.Diagnostics.code.invalidDocument,
|
|
517
|
+
severity: "error",
|
|
518
|
+
message: "The resolved `input` is not an OpenAPI or Swagger document: it declares no `openapi` or `swagger` version.",
|
|
519
|
+
help: "Point `input` at a document that declares `openapi` or `swagger`. If you pass an object, pass the spec itself rather than a wrapper such as `{ path }` or `{ data }`.",
|
|
520
|
+
location: { kind: "config" }
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
452
524
|
* Validates an OpenAPI document using `@readme/openapi-parser` with colorized error output.
|
|
453
525
|
*
|
|
454
526
|
* @example
|
|
@@ -1623,9 +1695,9 @@ function convertObject({ schema, name, nullable, defaultValue, rawOptions, optio
|
|
|
1623
1695
|
/**
|
|
1624
1696
|
* Converts an OAS 3.1 `prefixItems` tuple into a `TupleSchemaNode`.
|
|
1625
1697
|
*/
|
|
1626
|
-
function convertTuple({ schema, name, nullable, defaultValue, rawOptions, parse }) {
|
|
1698
|
+
function convertTuple({ schema, name, nullable, defaultValue, rawOptions, options, parse }) {
|
|
1627
1699
|
const tupleItems = (schema.prefixItems ?? []).map((item) => parse({ schema: item }, rawOptions));
|
|
1628
|
-
const rest = schema.items === false ? void 0 : !schema.items || schema.items === true ? _kubb_ast.ast.factory.createSchema({ type:
|
|
1700
|
+
const rest = schema.items === false ? void 0 : !schema.items || schema.items === true ? _kubb_ast.ast.factory.createSchema({ type: options.unknownType }) : parse({ schema: schema.items }, rawOptions);
|
|
1629
1701
|
return createNode({
|
|
1630
1702
|
schema,
|
|
1631
1703
|
name,
|
|
@@ -2491,13 +2563,16 @@ const adapterOas = (0, _kubb_core.createAdapter)((options) => {
|
|
|
2491
2563
|
},
|
|
2492
2564
|
async validate(input, options) {
|
|
2493
2565
|
await assertInputExists(input);
|
|
2494
|
-
|
|
2566
|
+
const document = await parseDocument(input);
|
|
2567
|
+
assertDocument(document);
|
|
2568
|
+
await validateDocument(document, options);
|
|
2495
2569
|
},
|
|
2496
2570
|
async parse(source) {
|
|
2497
2571
|
const cached = inputCache.get(source);
|
|
2498
2572
|
if (cached) return cached;
|
|
2499
2573
|
const promise = (async () => {
|
|
2500
2574
|
const document = await parseFromConfig(source);
|
|
2575
|
+
assertDocument(document);
|
|
2501
2576
|
if (validate) await validateDocument(document);
|
|
2502
2577
|
parsedDocument = document;
|
|
2503
2578
|
const refs = createRefs(document);
|