@kubb/oas 4.33.1 → 4.33.3

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
@@ -38,11 +38,9 @@ jsonpointer = __toESM(jsonpointer);
38
38
  let oas = require("oas");
39
39
  oas = __toESM(oas);
40
40
  let oas_utils = require("oas/utils");
41
- let node_fs = require("node:fs");
42
- node_fs = __toESM(node_fs);
43
41
  let node_path = require("node:path");
44
42
  node_path = __toESM(node_path);
45
- let _readme_openapi_parser = require("@readme/openapi-parser");
43
+ let _redocly_openapi_core = require("@redocly/openapi-core");
46
44
  let oas_types = require("oas/types");
47
45
  let oas_normalize = require("oas-normalize");
48
46
  oas_normalize = __toESM(oas_normalize);
@@ -4543,96 +4541,16 @@ function getDefaultValue(schema) {
4543
4541
  }
4544
4542
  if (schema.type === "object" || schema.properties) return "{}";
4545
4543
  }
4546
- /**
4547
- * Recursively collect all external local-file $ref prefixes (e.g. "api-definitions.yml")
4548
- * from an object tree. URL refs (http/https) are ignored.
4549
- */
4550
- function collectExternalFilePaths(obj, files) {
4551
- if (!obj || typeof obj !== "object") return;
4552
- if (Array.isArray(obj)) {
4553
- for (const item of obj) collectExternalFilePaths(item, files);
4554
- return;
4555
- }
4556
- for (const [key, value] of Object.entries(obj)) if (key === "$ref" && typeof value === "string") {
4557
- const hashIdx = value.indexOf("#");
4558
- const filePart = hashIdx > 0 ? value.slice(0, hashIdx) : hashIdx === -1 ? value : "";
4559
- if (filePart && !filePart.startsWith("http://") && !filePart.startsWith("https://")) files.add(filePart);
4560
- } else collectExternalFilePaths(value, files);
4561
- }
4562
- /**
4563
- * Replace all $refs that start with `externalFile#` with the corresponding
4564
- * internal ref (i.e. just the fragment part, `#/...`).
4565
- */
4566
- function replaceExternalRefsInPlace(obj, externalFile) {
4567
- if (!obj || typeof obj !== "object") return;
4568
- if (Array.isArray(obj)) {
4569
- for (const item of obj) replaceExternalRefsInPlace(item, externalFile);
4570
- return;
4571
- }
4572
- const record = obj;
4573
- for (const key of Object.keys(record)) {
4574
- const value = record[key];
4575
- if (key === "$ref" && typeof value === "string" && value.startsWith(`${externalFile}#`)) record[key] = value.slice(externalFile.length);
4576
- else if (value && typeof value === "object") replaceExternalRefsInPlace(value, externalFile);
4577
- }
4578
- }
4579
- /**
4580
- * Before bundling, scan the main spec file for external local-file references and merge
4581
- * their `components` sections into the main document. This ensures that schemas defined
4582
- * in external files (e.g. `api-definitions.yml#/components/schemas/Parcel`) end up in
4583
- * `#/components/schemas/Parcel` of the bundled output, rather than being inlined as
4584
- * anonymous path-based refs.
4585
- *
4586
- * Returns the merged document, or `null` if no external file components were found.
4587
- */
4588
- function mergeExternalFileComponents(mainFilePath) {
4589
- let mainContent;
4590
- try {
4591
- mainContent = node_fs.default.readFileSync(mainFilePath, "utf-8");
4592
- } catch {
4593
- return null;
4594
- }
4595
- const mainDoc = import_yaml.parse(mainContent);
4596
- if (!mainDoc || typeof mainDoc !== "object") return null;
4597
- const mainDir = node_path.default.dirname(mainFilePath);
4598
- const externalFiles = /* @__PURE__ */ new Set();
4599
- collectExternalFilePaths(mainDoc, externalFiles);
4600
- if (externalFiles.size === 0) return null;
4601
- let hasMergedComponents = false;
4602
- for (const externalFile of externalFiles) {
4603
- const externalFilePath = node_path.default.resolve(mainDir, externalFile);
4604
- let externalContent;
4605
- try {
4606
- externalContent = node_fs.default.readFileSync(externalFilePath, "utf-8");
4607
- } catch {
4608
- continue;
4609
- }
4610
- const externalDoc = import_yaml.parse(externalContent);
4611
- if (!externalDoc?.components || typeof externalDoc.components !== "object") continue;
4612
- const mainComponents = mainDoc.components ?? {};
4613
- mainDoc.components = mainComponents;
4614
- for (const [componentType, components] of Object.entries(externalDoc.components)) {
4615
- if (!components || typeof components !== "object") continue;
4616
- mainComponents[componentType] = {
4617
- ...components,
4618
- ...mainComponents[componentType] ?? {}
4619
- };
4620
- hasMergedComponents = true;
4621
- }
4622
- }
4623
- if (!hasMergedComponents) return null;
4624
- for (const externalFile of externalFiles) replaceExternalRefsInPlace(mainDoc, externalFile);
4625
- return mainDoc;
4626
- }
4627
- async function parse(pathOrApi, { oasClass = Oas, enablePaths = true } = {}) {
4628
- if (typeof pathOrApi === "string" && !pathOrApi.match(/\n/) && !pathOrApi.match(/^\s*\{/) && enablePaths) try {
4629
- return parse(await (0, _readme_openapi_parser.bundle)(mergeExternalFileComponents(pathOrApi) ?? pathOrApi), {
4630
- oasClass,
4631
- enablePaths
4632
- });
4633
- } catch (e) {
4634
- console.warn(`[kubb] Failed to bundle external $refs in "${pathOrApi}": ${e.message}. Falling back to plain load.`);
4635
- }
4544
+ async function parse(pathOrApi, { oasClass = Oas, canBundle = true, enablePaths = true } = {}) {
4545
+ if (typeof pathOrApi === "string" && canBundle) return parse((await (0, _redocly_openapi_core.bundle)({
4546
+ ref: pathOrApi,
4547
+ config: await (0, _redocly_openapi_core.loadConfig)(),
4548
+ base: pathOrApi
4549
+ })).bundle.parsed, {
4550
+ oasClass,
4551
+ canBundle,
4552
+ enablePaths
4553
+ });
4636
4554
  const document = await new oas_normalize.default(pathOrApi, {
4637
4555
  enablePaths,
4638
4556
  colorizeErrors: true
@@ -4646,7 +4564,8 @@ async function parse(pathOrApi, { oasClass = Oas, enablePaths = true } = {}) {
4646
4564
  async function merge(pathOrApi, { oasClass = Oas } = {}) {
4647
4565
  const instances = await Promise.all(pathOrApi.map((p) => parse(p, {
4648
4566
  oasClass,
4649
- enablePaths: false
4567
+ enablePaths: false,
4568
+ canBundle: false
4650
4569
  })));
4651
4570
  if (instances.length === 0) throw new Error("No OAS instances provided for merging.");
4652
4571
  return parse(instances.reduce((acc, current) => {
@@ -5031,9 +4950,14 @@ var Oas = class extends oas.default {
5031
4950
  }
5032
4951
  getParametersSchema(operation, inKey) {
5033
4952
  const { contentType = operation.getContentType() } = this.#options;
5034
- const params = operation.getParameters().map((schema) => {
5035
- return this.dereferenceWithRef(schema);
5036
- }).filter((v) => v.in === inKey);
4953
+ const resolveParams = (params) => params.map((p) => this.dereferenceWithRef(p)).filter((p) => !!p && typeof p === "object" && "in" in p && "name" in p);
4954
+ const operationParams = resolveParams(operation.schema?.parameters || []);
4955
+ const pathItem = this.api?.paths?.[operation.path];
4956
+ const pathLevelParams = resolveParams(pathItem && !isReference(pathItem) && pathItem.parameters ? pathItem.parameters : []);
4957
+ const paramMap = /* @__PURE__ */ new Map();
4958
+ for (const p of pathLevelParams) if (p.name && p.in) paramMap.set(`${p.in}:${p.name}`, p);
4959
+ for (const p of operationParams) if (p.name && p.in) paramMap.set(`${p.in}:${p.name}`, p);
4960
+ const params = Array.from(paramMap.values()).filter((v) => v.in === inKey);
5037
4961
  if (!params.length) return null;
5038
4962
  return params.reduce((schema, pathParameters) => {
5039
4963
  const property = pathParameters.content?.[contentType]?.schema ?? pathParameters.schema;