or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

bundling.mddereferencing.mdindex.mdparsing.mdresolution.mdvalidation.md
tile.json

dereferencing.mddocs/

API Dereferencing

Dereferences all $ref pointers in OpenAPI/Swagger specifications by replacing them with their resolved values. This creates a plain JavaScript object tree with no JSON references, ideal for programmatic usage while maintaining object reference equality.

Capabilities

Dereference Function

Replaces all $ref pointers with their resolved values, creating a fully expanded API definition.

/**
 * Dereferences all $ref pointers, replacing each reference with its resolved value
 * @param path - File path or URL of the OpenAPI definition (optional if api provided)
 * @param api - OpenAPI definition object to dereference instead of reading from path
 * @param options - Dereferencing options (optional)
 * @param callback - Error-first callback (optional, returns Promise if omitted)
 * @returns Promise resolving to the dereferenced OpenAPI definition
 */
function dereference(
  path?: string,
  api?: OpenAPI.Document,
  options?: SwaggerParser.Options,
  callback?: SwaggerParser.ApiCallback
): Promise<OpenAPI.Document>;

Instance Dereference Method

Dereference method available on SwaggerParser instances.

/**
 * Instance method for dereferencing OpenAPI specifications
 * @param path - File path or URL of the OpenAPI definition
 * @param api - OpenAPI definition object to dereference instead of reading from path
 * @param options - Dereferencing options
 * @param callback - Error-first callback
 * @returns Promise resolving to the dereferenced OpenAPI definition
 */
public dereference(
  path?: string,
  api?: OpenAPI.Document,
  options?: SwaggerParser.Options,
  callback?: SwaggerParser.ApiCallback
): Promise<OpenAPI.Document>;

Usage Examples:

import SwaggerParser from "@apidevtools/swagger-parser";

// Basic dereferencing
const api = await SwaggerParser.dereference("./petstore.yaml");

// No $ref pointers in the result
console.log(api.paths["/pets"].get.responses["200"].schema);
// Direct object instead of { $ref: "#/definitions/Pet" }

// Dereference from URL
const api = await SwaggerParser.dereference("https://api.example.com/openapi.yaml");

// Dereference with options
const api = await SwaggerParser.dereference("./api.yaml", {
  dereference: {
    circular: true,    // Allow circular references
    excludedPathMatcher: (path) => path.includes("examples")
  }
});

// Using callback style
SwaggerParser.dereference("./api.yaml", (err, api) => {
  if (err) {
    console.error("Dereferencing failed:", err);
  } else {
    console.log("Dereferenced API paths:", Object.keys(api.paths));
  }
});

// Using instance
const parser = new SwaggerParser();
const api = await parser.dereference("./api.yaml");

// Access dereferenced content directly
const userSchema = api.components.schemas.User; // Direct object, no $ref
console.log("User properties:", userSchema.properties);

Object Reference Equality

Dereferencing maintains object reference equality - all $ref pointers to the same value resolve to the same object instance:

const api = await SwaggerParser.dereference("./api.yaml");

// Both references point to the same object instance
const schema1 = api.paths["/users"].get.responses["200"].schema;
const schema2 = api.paths["/users"].post.requestBody.content["application/json"].schema;

console.log(schema1 === schema2); // true if they reference the same schema

Dereferencing vs Bundling

Dereferencing

  • Replaces all $ref pointers with actual values
  • Creates larger file sizes due to duplication
  • Risk of circular references affecting JSON.stringify()
  • Ideal for programmatic object traversal

Bundling

  • Preserves $ref pointers internally
  • Smaller file sizes, no duplication
  • Safe for JSON.stringify()
  • Ideal for distribution and storage
// Compare sizes
const bundled = await SwaggerParser.bundle("./api.yaml");
const dereferenced = await SwaggerParser.dereference("./api.yaml");

console.log("Bundled size:", JSON.stringify(bundled).length);
console.log("Dereferenced size:", JSON.stringify(dereferenced).length);
// Dereferenced is typically much larger

Circular Reference Handling

interface DereferenceOptions {
  /** How to handle circular references */
  circular?: boolean | "ignore";
  /** Function to exclude certain paths from dereferencing */
  excludedPathMatcher?: (path: string) => boolean;
}

Circular Reference Options

// Allow circular references (default: false)
const api = await SwaggerParser.dereference("./api.yaml", {
  dereference: {
    circular: true  // Creates circular object references
  }
});

// Ignore circular references - don't dereference them
const api = await SwaggerParser.dereference("./api.yaml", {
  dereference: {
    circular: "ignore"  // Leaves circular $refs as-is
  }
});

// Throw error on circular references
const api = await SwaggerParser.dereference("./api.yaml", {
  dereference: {
    circular: false  // Throws ReferenceError if circular refs found
  }
});

Working with Dereferenced APIs

const api = await SwaggerParser.dereference("./api.yaml");

// Direct object access - no $ref resolution needed
function analyzeSchema(schema) {
  // Can directly access properties without worrying about $refs
  if (schema.type === "object") {
    console.log("Properties:", Object.keys(schema.properties || {}));
  }
  if (schema.type === "array") {
    console.log("Items type:", schema.items.type);
  }
}

// Traverse all schemas
if (api.components && api.components.schemas) {
  Object.entries(api.components.schemas).forEach(([name, schema]) => {
    console.log(`Analyzing schema: ${name}`);
    analyzeSchema(schema);
  });
}

// Traverse all path responses
Object.entries(api.paths).forEach(([path, pathItem]) => {
  Object.entries(pathItem).forEach(([method, operation]) => {
    if (operation.responses) {
      Object.entries(operation.responses).forEach(([code, response]) => {
        if (response.schema) {
          console.log(`Response ${code} schema for ${method} ${path}`);
          analyzeSchema(response.schema);
        }
      });
    }
  });
});

Performance Considerations

Dereferencing can be memory-intensive for large APIs:

// For large APIs, consider selective dereferencing
const api = await SwaggerParser.dereference("./large-api.yaml", {
  dereference: {
    excludedPathMatcher: (path) => {
      // Skip dereferencing examples to save memory
      return path.includes("examples") || path.includes("x-");
    }
  }
});

Error Handling

try {
  const api = await SwaggerParser.dereference("./api.yaml");
} catch (error) {
  // Circular reference errors
  if (error instanceof ReferenceError && error.message.includes("circular")) {
    console.error("Circular references detected - use circular: true option");
  }
  
  // Resolution errors
  if (error.code === "ENOENT") {
    console.error("Referenced file not found:", error.path);
  }
  
  // Parse errors
  if (error instanceof SyntaxError) {
    console.error("Parse error in referenced file:", error.message);
  }
}

JSON Serialization Warnings

const api = await SwaggerParser.dereference("./api.yaml", {
  dereference: { circular: true }
});

// This may throw "Converting circular structure to JSON"
try {
  const json = JSON.stringify(api);
} catch (error) {
  console.error("Cannot serialize circular structure");
  // Use JSON.stringify with replacer, or use bundle() instead
}

Common Dereferencing Errors:

  • Circular reference errors when circular: false
  • Memory issues with very large APIs
  • JSON serialization errors with circular structures
  • File resolution errors for external references
  • Invalid $ref pointer syntax