CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-oas-normalize

Tooling for converting, validating, and parsing OpenAPI, Swagger, and Postman API definitions

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

reference-resolution.mddocs/

Reference Resolution

Advanced reference resolution capabilities for bundling external $ref pointers and dereferencing all references inline, providing complete control over how API definitions handle references.

Capabilities

Bundle Method

Bundle external $ref pointers into the main document, resolving references to external files while preserving internal references.

/**
 * Bundle up the given API definition, resolving any external $ref pointers in the process
 * Internal references are preserved, external files are loaded and embedded
 * @returns Promise resolving to bundled OpenAPI document
 */
async bundle(): Promise<OpenAPI.Document>;

Usage Examples:

import OASNormalize from "oas-normalize";

// API definition with external references
const apiWithExternalRefs = {
  openapi: "3.0.0",
  info: { title: "Pet Store", version: "1.0.0" },
  paths: {
    "/pets": {
      get: {
        responses: {
          "200": {
            description: "Successful response",
            content: {
              "application/json": {
                schema: { $ref: "./schemas/pet.json" }  // External reference
              }
            }
          }
        }
      }
    }
  },
  components: {
    schemas: {
      Error: {  // Internal schema preserved
        type: "object",
        properties: {
          code: { type: "integer" },
          message: { type: "string" }
        }
      }
    }
  }
};

const oas = new OASNormalize(apiWithExternalRefs, { enablePaths: true });
const bundled = await oas.bundle();

// External ./schemas/pet.json is now embedded in the bundled document
// Internal references like #/components/schemas/Error remain as-is
console.log(bundled.components.schemas.Pet); // Now contains the content from pet.json

Dereference Method

Dereference all $ref pointers, both internal and external, creating a fully expanded document with no references.

/**
 * Dereference the given API definition, resolving all $ref pointers inline
 * Creates a fully expanded document with no remaining references
 * @returns Promise resolving to dereferenced OpenAPI document
 */
async dereference(): Promise<OpenAPI.Document>;

Usage Examples:

// API definition with internal references
const apiWithRefs = {
  openapi: "3.0.0",
  info: { title: "Pet Store", version: "1.0.0" },
  paths: {
    "/pets": {
      post: {
        requestBody: {
          $ref: "#/components/requestBodies/Pet"  // Internal reference
        },
        responses: {
          "200": {
            description: "Success",
            content: {
              "application/json": {
                schema: { $ref: "#/components/schemas/Pet" }  // Internal reference
              }
            }
          }
        }
      }
    }
  },
  components: {
    schemas: {
      Pet: {
        type: "object",
        properties: {
          name: { type: "string" },
          category: { $ref: "#/components/schemas/Category" }  // Nested reference
        }
      },
      Category: {
        type: "object",
        properties: {
          id: { type: "integer" },
          name: { type: "string" }
        }
      }
    },
    requestBodies: {
      Pet: {
        description: "Pet object that needs to be added",
        required: true,
        content: {
          "application/json": {
            schema: { $ref: "#/components/schemas/Pet" }
          }
        }
      }
    }
  }
};

const oas = new OASNormalize(apiWithRefs);
const dereferenced = await oas.dereference();

// All $ref pointers are now resolved inline
console.log(dereferenced.paths['/pets'].post.requestBody);
// Contains the full requestBody object instead of { $ref: "..." }

console.log(dereferenced.paths['/pets'].post.requestBody.content['application/json'].schema);
// Contains the full Pet schema with Category schema inlined

Deref Method (Deprecated)

Legacy alias for the dereference method, maintained for backward compatibility.

/**
 * Dereference the given API definition
 * @deprecated Use dereference() instead. Will be removed in a future release.
 * @returns Promise resolving to dereferenced OpenAPI document
 */
async deref(): Promise<OpenAPI.Document>;

Usage Examples:

// Deprecated usage - still works but not recommended
const oas = new OASNormalize(apiSpec);
const dereferenced = await oas.deref();

// Preferred usage
const preferred = await oas.dereference();

Bundle vs Dereference

Bundle: External References Only

Bundling resolves only external file references, keeping internal references intact:

// Before bundling
const spec = {
  paths: {
    "/pets": {
      get: {
        responses: {
          "200": {
            schema: { $ref: "./external-schema.json" }  // External - will be resolved
          },
          "400": {
            schema: { $ref: "#/components/schemas/Error" }  // Internal - preserved
          }
        }
      }
    }
  }
};

const bundled = await new OASNormalize(spec, { enablePaths: true }).bundle();

// After bundling:
// - ./external-schema.json content is embedded
// - #/components/schemas/Error reference remains as $ref

Dereference: All References

Dereferencing resolves all references, creating a fully expanded document:

// Before dereferencing
const spec = {
  paths: {
    "/pets": {
      get: {
        responses: {
          "200": { schema: { $ref: "#/components/schemas/Pet" } }
        }
      }
    }
  },
  components: {
    schemas: {
      Pet: {
        properties: {
          category: { $ref: "#/components/schemas/Category" }
        }
      },
      Category: { type: "object", properties: { name: { type: "string" } } }
    }
  }
};

const dereferenced = await new OASNormalize(spec).dereference();

// After dereferencing:
// - All $ref pointers are replaced with actual content
// - Category schema is inlined within Pet schema
// - No references remain in the document

Postman Collection Handling

Both bundling and dereferencing automatically handle Postman collection conversion:

const postmanCollection = {
  info: { name: "API Collection" },
  item: [/* collection items */]
};

// Postman collections are automatically converted to OpenAPI first
const bundled = await new OASNormalize(postmanCollection).bundle();
const dereferenced = await new OASNormalize(postmanCollection).dereference();

// Both results are OpenAPI documents, not Postman collections
console.log(bundled.openapi); // "3.0.0"
console.log(dereferenced.openapi); // "3.0.0"

Performance and Caching

Both operations are cached to improve performance:

const oas = new OASNormalize(complexSpec);

// First call performs the operation
const bundled1 = await oas.bundle();

// Second call returns cached result
const bundled2 = await oas.bundle();

console.log(bundled1 === bundled2); // true

// Same applies to dereference
const deref1 = await oas.dereference();
const deref2 = await oas.dereference();
console.log(deref1 === deref2); // true

Error Handling

External Reference Resolution Errors

const specWithBadRef = {
  openapi: "3.0.0",
  paths: {
    "/pets": {
      get: {
        responses: {
          "200": {
            schema: { $ref: "./nonexistent-file.json" }
          }
        }
      }
    }
  }
};

try {
  await new OASNormalize(specWithBadRef, { enablePaths: true }).bundle();
} catch (error) {
  console.error("Failed to resolve external reference:", error.message);
}

Security Restrictions

const specWithFileRef = {
  openapi: "3.0.0",
  paths: {
    "/pets": {
      get: {
        parameters: [{
          schema: { $ref: "/etc/passwd" }  // Attempting to read system file
        }]
      }
    }
  }
};

// Without enablePaths, this will fail
try {
  await new OASNormalize(specWithFileRef).bundle();
} catch (error) {
  console.error(error.message); // "Unable to resolve $ref pointer..."
}

Integration with Validation

Reference resolution works seamlessly with validation:

const specWithRefs = {
  // API spec with various $ref pointers
};

const oas = new OASNormalize(specWithRefs);

// Validate the bundled version
const bundled = await oas.bundle();
await new OASNormalize(bundled).validate();

// Or validate the dereferenced version
const dereferenced = await oas.dereference();
await new OASNormalize(dereferenced).validate();

// Direct validation also works (resolves references internally)
await oas.validate();

Install with Tessl CLI

npx tessl i tessl/npm-oas-normalize

docs

core-processing.md

error-handling.md

format-conversion.md

index.md

reference-resolution.md

utility-functions.md

validation.md

tile.json