@orsetra/openapi-editor
v0.2.19
Published
Professional OpenAPI 3.0/3.1 Editor - React component for editing and validating OpenAPI specifications
Maintainers
Readme
@orsetra/openapi-editor
Professional OpenAPI 3.0/3.1 Editor - React component for editing and validating OpenAPI specifications.
Features
- ✅ Full OpenAPI 3.0/3.1 Support - Complete specification editing
- 🎨 Monaco Editor - Powered by VS Code's editor with syntax highlighting
- 🔍 Real-time Validation - Instant feedback on specification errors
- 📁 Multi-file Projects - Support for split specifications with $ref
- 🔄 Sync Integration - Built-in support for external sync providers
- 📦 Import/Export - ZIP file support for project portability
- 🎯 TypeScript - Full type definitions included
- 🌐 Swagger UI Preview - Live preview of your API documentation
- 💾 Local Storage - Automatic persistence of your work
Installation
npm install @orsetra/openapi-editorQuick Start
import { OpenapiEditor, useOpenapiEditor } from '@orsetra/openapi-editor';
import '@orsetra/openapi-editor/dist/style.css';
function App() {
const { editorRef, exportToZip } = useOpenapiEditor();
const handleExport = async () => {
const blob = await exportToZip();
// Save the blob...
};
return (
<div style={{ width: '100vw', height: '100vh' }}>
<OpenapiEditor
ref={editorRef}
menubar={true}
readonly={false}
/>
<button onClick={handleExport}>Export Project</button>
</div>
);
}API Reference
OpenapiEditor Component
Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| menubar | boolean | true | Show/hide the top menubar |
| readonly | boolean | false | Make the editor read-only |
| projectId | string | - | Project ID for synchronization |
| className | string | - | Custom CSS class name |
| style | React.CSSProperties | - | Custom inline styles |
| syncConfig | SyncConfig | - | Sync configuration object |
| autoLoad | boolean | false | Auto-load project on mount |
| onSyncConfigured | function | - | Callback when sync is configured |
| onReady | function | - | Callback when editor is ready |
Ref Methods
const editorRef = useRef<OpenapiEditorRef>(null);
// Load from ZIP
await editorRef.current.loadFromZip(zipBlob);
// Export to ZIP
const blob = await editorRef.current.exportToZip();
// Validate project
const validation = await editorRef.current.isProjectValid();
// Get project info
const info = await editorRef.current.getProjectInfo();
// Get all endpoints
const endpoints = await editorRef.current.getEndpoints();
// Import files
await editorRef.current.importFiles(files, { conflictStrategy: 'overwrite' });useOpenapiEditor Hook
Convenient hook for managing the editor:
const {
editorRef,
isReady,
loadFromZip,
exportToZip,
isProjectValid,
getProjectInfo,
getEndpoints,
importFiles,
openImportModal,
configureSync,
startSync,
stopSync,
syncNow,
getSyncStatus,
resetSync,
loadProjectFromSync,
} = useOpenapiEditor(options);Examples
Basic Editor
import { OpenapiEditor } from '@orsetra/openapi-editor';
import '@orsetra/openapi-editor/dist/style.css';
function BasicEditor() {
return (
<OpenapiEditor
menubar={true}
readonly={false}
/>
);
}With Validation
import { OpenapiEditor, useOpenapiEditor } from '@orsetra/openapi-editor';
function ValidatedEditor() {
const { editorRef, isProjectValid } = useOpenapiEditor();
const handleValidate = async () => {
const result = await isProjectValid();
if (result.valid) {
alert('✅ Specification is valid!');
} else {
console.error('Validation errors:', result.errors);
alert(`❌ Found ${result.errorCount} error(s)`);
}
};
return (
<>
<OpenapiEditor ref={editorRef} />
<button onClick={handleValidate}>Validate</button>
</>
);
}With Sync Provider
import { OpenapiEditor, useOpenapiEditor, SyncProvider } from '@orsetra/openapi-editor';
const syncProvider: SyncProvider = {
loadProject: async (projectId) => {
const response = await fetch(`/api/projects/${projectId}`);
const data = await response.json();
return {
projectId,
projectType: 'oas3:api',
files: data.files,
};
},
syncChanges: async (projectId, changes) => {
const response = await fetch(`/api/projects/${projectId}/sync`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ changes }),
});
return response.json();
},
isReady: async () => {
const response = await fetch('/api/health');
return response.ok;
},
};
function SyncedEditor() {
const { editorRef } = useOpenapiEditor();
return (
<OpenapiEditor
ref={editorRef}
syncConfig={{
provider: syncProvider,
projectId: 'my-project-123',
interval: 30000, // Sync every 30 seconds
autoSync: true,
}}
autoLoad={true}
onSyncConfigured={(event) => {
console.log('Sync configured:', event);
}}
/>
);
}Import/Export
import { useOpenapiEditor } from '@orsetra/openapi-editor';
function ImportExportExample() {
const { editorRef, loadFromZip, exportToZip } = useOpenapiEditor();
const handleImport = async (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (!file) return;
const info = await loadFromZip(file);
console.log(`Loaded: ${info.name} v${info.version}`);
};
const handleExport = async () => {
const blob = await exportToZip();
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'openapi-project.zip';
a.click();
URL.revokeObjectURL(url);
};
return (
<>
<OpenapiEditor ref={editorRef} />
<input type="file" accept=".zip" onChange={handleImport} />
<button onClick={handleExport}>Export</button>
</>
);
}Read-only Viewer
import { OpenapiEditor, useOpenapiEditor } from '@orsetra/openapi-editor';
function ApiViewer() {
const { editorRef, getEndpoints } = useOpenapiEditor();
const showEndpoints = async () => {
const endpoints = await getEndpoints();
console.log('API Endpoints:', endpoints);
};
return (
<>
<OpenapiEditor
ref={editorRef}
readonly={true}
menubar={false}
/>
<button onClick={showEndpoints}>Show Endpoints</button>
</>
);
}TypeScript Support
Full TypeScript definitions are included:
import type {
OpenapiEditorProps,
OpenapiEditorRef,
SyncConfig,
SyncProvider,
FileChange,
SyncResult,
ProjectData,
UseOpenapiEditorOptions,
UseOpenapiEditorReturn,
} from '@orsetra/openapi-editor';Sync Provider Interface
Implement custom sync providers:
interface SyncProvider {
loadProject(projectId: string): Promise<ProjectData>;
syncChanges(projectId: string, changes: FileChange[]): Promise<SyncResult>;
isReady?(): Promise<boolean>;
}
interface ProjectData {
projectId: string;
projectType?: string;
description?: string;
files: Array<{
path: string;
content: string;
format: 'json' | 'yaml';
}>;
}
interface FileChange {
path: string;
type: 'created' | 'modified' | 'deleted';
content: string | null;
format: 'json' | 'yaml';
timestamp: number;
}
interface SyncResult {
success: boolean;
syncedCount: number;
error?: string;
timestamp: number;
}Styling
Import the default styles:
import '@orsetra/openapi-editor/dist/style.css';Or customize with your own CSS by targeting the component classes.
Browser Support
- Chrome/Edge (latest)
- Firefox (latest)
- Safari (latest)
Requirements
- React >= 18.0.0
- react-dom >= 18.0.0
License
MIT © orsetra Team
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
For issues and questions, please use the GitHub Issues page.
