@kubb/adapter-oas 5.0.0-beta.109 → 5.0.0-beta.110

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/dist/index.cjs CHANGED
@@ -413,11 +413,20 @@ async function readSource(sourcePath) {
413
413
  /**
414
414
  * Reads and parses one source file or URL referenced during bundling: YAML/JSON is parsed into an
415
415
  * object, Markdown is returned as-is (bundled inline rather than dereferenced).
416
+ *
417
+ * JSON is valid YAML, so `yaml`'s `parse` handles both, but its general-purpose parser (comments,
418
+ * anchors, block scalars, multi-document streams) does much more work than `JSON.parse` needs to.
419
+ * `JSON.parse` runs first and fails fast on the first non-JSON character, so a real YAML document
420
+ * falls through to `parse` at negligible cost.
416
421
  */
417
422
  async function resolveSource(sourcePath) {
418
423
  const data = await readSource(sourcePath);
419
424
  if (sourcePath.toLowerCase().endsWith(".md")) return data;
420
- return (0, yaml.parse)(data);
425
+ try {
426
+ return JSON.parse(data);
427
+ } catch {
428
+ return (0, yaml.parse)(data);
429
+ }
421
430
  }
422
431
  /**
423
432
  * Throws a coded `KUBB_INPUT_NOT_FOUND` diagnostic when a local input path does not exist.
@@ -438,6 +447,19 @@ async function assertInputExists(input) {
438
447
  //#endregion
439
448
  //#region src/load/normalize.ts
440
449
  /**
450
+ * True when `node` contains a `$ref` pointing outside the current document (a relative path,
451
+ * absolute path, or URL). An internal `#/...` fragment does not count.
452
+ *
453
+ * `Object.values` reads array elements and object property values alike, so the same recursion
454
+ * walks both without a separate array branch.
455
+ */
456
+ function hasExternalRef(node) {
457
+ if (!node || typeof node !== "object") return false;
458
+ const ref = node.$ref;
459
+ if (typeof ref === "string" && !ref.startsWith("#")) return true;
460
+ return Object.values(node).some(hasExternalRef);
461
+ }
462
+ /**
441
463
  * Bundles a multi-file OpenAPI document into a single document via `api-ref-bundler`.
442
464
  *
443
465
  * External file schemas are hoisted into named `components.schemas` entries, so a property
@@ -445,6 +467,11 @@ async function assertInputExists(input) {
445
467
  * can then emit a named type with an import instead of inlining the shape. Sources are read with
446
468
  * the Bun-aware `read` util for local YAML and JSON files, and with `fetch` for HTTP(S) URLs.
447
469
  *
470
+ * A document with no `$ref` outside itself has nothing to bundle, so it skips `api-ref-bundler`
471
+ * and returns as parsed. `bundle` only rewrites external refs into internal ones; on an
472
+ * all-internal document it is a no-op that still walks the whole tree to confirm that, which
473
+ * costs real time on a large spec.
474
+ *
448
475
  * @example Local file
449
476
  * `const document = await bundleDocument('./openapi.yaml')`
450
477
  *
@@ -461,7 +488,8 @@ async function bundleDocument(pathOrUrl) {
461
488
  cache.set(key, result);
462
489
  return result;
463
490
  };
464
- await resolver(pathOrUrl);
491
+ const root = await resolver(pathOrUrl);
492
+ if (typeof root === "object" && root !== null && !hasExternalRef(root)) return root;
465
493
  return await (0, api_ref_bundler.bundle)(pathOrUrl, resolver);
466
494
  }
467
495
  /**