Multi-file OpenAPI document workspace with cross-file reference resolution and validation. The workspace system enables working with OpenAPI specifications split across multiple files, providing seamless reference resolution and document management.
Create and configure workspaces for managing multiple OpenAPI document files.
/**
* Create an OpenAPI workspace for multi-file document management
* @param workspace - Workspace configuration with document files
* @returns Configured workspace instance
*/
function createOpenAPIWorkspace<T extends OpenAPI2Document | OpenAPI3Document>(
workspace: WorkspaceConfig<T>
): OpenAPIWorkspace<T>;
/**
* Workspace configuration
*/
interface WorkspaceConfig<T extends OpenAPI2Document | OpenAPI3Document> {
/** Document specifications by file path */
specs: { [filePath: string]: T } | Map<string, T>;
}
/**
* Workspace instance for document management
*/
interface OpenAPIWorkspace<T extends OpenAPI2Document | OpenAPI3Document> {
/** Map of document specifications by file path */
specs: Map<string, T>;
/** Resolve references across documents */
resolveReference<T>(args: ResolveReferenceArgs): T;
}Usage Examples:
import {
createOpenAPIWorkspace,
OpenAPI3Document
} from "@azure-tools/openapi";
// Create workspace with multiple documents
const mainDoc: OpenAPI3Document = {
openapi: "3.0.0",
info: { title: "Main API", version: "1.0.0" },
paths: {
"/users": {
get: {
responses: {
"200": {
description: "Success",
content: {
"application/json": {
schema: { $ref: "schemas.yaml#/components/schemas/User" }
}
}
}
}
}
}
}
};
const schemasDoc: OpenAPI3Document = {
openapi: "3.0.0",
info: { title: "Schemas", version: "1.0.0" },
paths: {},
components: {
schemas: {
User: {
type: "object",
properties: {
id: { type: "string" },
name: { type: "string" }
}
}
}
}
};
// Create workspace
const workspace = createOpenAPIWorkspace({
specs: {
"main.yaml": mainDoc,
"schemas.yaml": schemasDoc
}
});
// Access documents
console.log(workspace.specs.get("main.yaml"));
console.log(workspace.specs.get("schemas.yaml"));Resolve references across multiple documents within a workspace.
/**
* Reference resolution arguments (union type)
*/
type ResolveReferenceArgs = TargetedJsonRef | ResolveReferenceRelativeTo;
/**
* Direct file and path reference
*/
interface TargetedJsonRef {
/** Target file name */
file: string;
/** JSON path within the file */
path?: string;
}
/**
* Reference with relative context
*/
interface ResolveReferenceRelativeTo {
/** Reference string as it appears */
ref: string;
/** File where the reference was defined */
relativeTo: string;
}Usage Examples:
import { createOpenAPIWorkspace } from "@azure-tools/openapi";
const workspace = createOpenAPIWorkspace({
specs: {
"main.yaml": mainDoc,
"schemas.yaml": schemasDoc
}
});
// Resolve direct reference
const userSchema = workspace.resolveReference({
file: "schemas.yaml",
path: "/components/schemas/User"
});
console.log(userSchema); // The User schema object
// Resolve relative reference
const resolvedSchema = workspace.resolveReference({
ref: "schemas.yaml#/components/schemas/User",
relativeTo: "main.yaml"
});
console.log(resolvedSchema); // Same User schema object
// Resolve local reference (within same file)
const localRef = workspace.resolveReference({
ref: "#/components/schemas/LocalType",
relativeTo: "schemas.yaml"
});Handle reference resolution errors and invalid workspace configurations.
/**
* Error thrown for invalid references
*/
class InvalidRefError extends Error {}Error Handling Examples:
import { createOpenAPIWorkspace, InvalidRefError } from "@azure-tools/openapi";
const workspace = createOpenAPIWorkspace({
specs: {
"main.yaml": mainDoc
}
});
// Handle invalid references
try {
const result = workspace.resolveReference({
file: "nonexistent.yaml",
path: "/components/schemas/User"
});
} catch (error) {
if (error instanceof InvalidRefError) {
console.error("Reference not found:", error.message);
// Error message: "Ref file 'nonexistent.yaml' doesn't exists in workspace."
}
}
// Handle invalid paths
try {
const result = workspace.resolveReference({
file: "main.yaml",
path: "/components/schemas/NonExistentSchema"
});
} catch (error) {
console.error("Invalid path:", error.message);
}import { createOpenAPIWorkspace, OpenAPI3Document } from "@azure-tools/openapi";
// Start with empty workspace
const workspace = createOpenAPIWorkspace<OpenAPI3Document>({
specs: new Map()
});
// Dynamically add documents
function addDocument(filePath: string, document: OpenAPI3Document) {
workspace.specs.set(filePath, document);
}
// Load documents dynamically
addDocument("api.yaml", apiDoc);
addDocument("components.yaml", componentsDoc);
// Now resolve references
const schema = workspace.resolveReference({
file: "components.yaml",
path: "/components/schemas/User"
});// Common reference patterns in multi-file setups
// 1. Component references
const componentRef = {
ref: "components.yaml#/components/schemas/User",
relativeTo: "api.yaml"
};
// 2. Parameter references
const paramRef = {
ref: "parameters.yaml#/components/parameters/PageLimit",
relativeTo: "api.yaml"
};
// 3. Response references
const responseRef = {
ref: "responses.yaml#/components/responses/NotFound",
relativeTo: "api.yaml"
};
// Resolve all references
const component = workspace.resolveReference(componentRef);
const parameter = workspace.resolveReference(paramRef);
const response = workspace.resolveReference(responseRef);import { createOpenAPIWorkspace } from "@azure-tools/openapi";
function validateWorkspace<T extends OpenAPI2Document | OpenAPI3Document>(
workspace: OpenAPIWorkspace<T>
): { isValid: boolean; errors: string[] } {
const errors: string[] = [];
// Check if all files exist
workspace.specs.forEach((doc, filePath) => {
if (!doc) {
errors.push(`Document at ${filePath} is null or undefined`);
}
});
// Validate cross-references (example validation)
// This would involve parsing all $ref strings and checking they resolve
return {
isValid: errors.length === 0,
errors
};
}
const workspace = createOpenAPIWorkspace({ specs: documentsMap });
const validation = validateWorkspace(workspace);
if (!validation.isValid) {
console.error("Workspace validation errors:", validation.errors);
}The workspace system integrates seamlessly with the common reference resolution utilities:
import {
createOpenAPIWorkspace,
dereference,
isReference
} from "@azure-tools/openapi";
const workspace = createOpenAPIWorkspace({ specs: documentsMap });
// Get a document
const mainDoc = workspace.specs.get("main.yaml");
// Find a reference in the document
const someRef = mainDoc?.paths["/users"]?.get?.responses["200"]?.content?.["application/json"]?.schema;
if (someRef && isReference(someRef)) {
// Option 1: Use workspace to resolve cross-file references
if (someRef.$ref.includes("#")) {
const [file, path] = someRef.$ref.split("#");
if (file) {
const resolved = workspace.resolveReference({
file: file,
path: path
});
console.log("Cross-file resolved:", resolved);
}
}
// Option 2: Use dereference for same-file references
const resolved = dereference(mainDoc, someRef);
console.log("Same-file resolved:", resolved.instance);
}interface WorkspaceConfig<T extends OpenAPI2Document | OpenAPI3Document> {
specs: { [filePath: string]: T } | Map<string, T>;
}
interface OpenAPIWorkspace<T extends OpenAPI2Document | OpenAPI3Document> {
specs: Map<string, T>;
resolveReference<T>(args: ResolveReferenceArgs): T;
}
interface TargetedJsonRef {
file: string;
path?: string;
}
interface ResolveReferenceRelativeTo {
ref: string;
relativeTo: string;
}
type ResolveReferenceArgs = TargetedJsonRef | ResolveReferenceRelativeTo;
class InvalidRefError extends Error {}