# What Is the `@openmaic/dsl` Package in OpenMAIC?

> Discover the @openmaic/dsl package, the zero-dependency contract keystone of OpenMAIC. Learn about its pure TypeScript types, validators, and normalizers for slide data structures.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: api-reference
- Published: 2026-09-04

---

**The `@openmaic/dsl` package is the zero-dependency contract keystone of the OpenMAIC SDK that provides pure TypeScript types, structural validators, and normalizers for all slide-related data structures.**

The `@openmaic/dsl` package serves as the foundational specification layer for the entire OpenMAIC platform. As the only module in the SDK family that ships with zero runtime dependencies, it defines the canonical data structures for slides, scenes, and actions while providing pure functions for validation, normalization, and migration. Every other OpenMAIC component—from renderers to importers—depends on this package to ensure type safety and structural consistency across the ecosystem.

## Zero-Runtime-Dependency Architecture

The `@openmaic/dsl` package maintains a strict **zero-runtime-dependency** policy. It ships with no dependencies on React, PPTX libraries, ECharts, or any other UI or I/O frameworks, as documented in the source header at [`packages/@openmaic/dsl/src/index.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/packages/@openmaic/dsl/src/index.ts).

This architectural choice ensures that any OpenMAIC module can import the DSL without inflating bundle size or dragging in unwanted framework code. Consequently, the package runs safely in server-side Node.js, Web Workers, and even non-JavaScript environments that consume the build-time JSON Schema artifacts.

## Core Data Structures

The DSL defines the object model for the entire presentation layer through TypeScript interfaces and generated JSON Schema.

### Slide Object Model

The [`packages/@openmaic/dsl/src/slides.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/packages/@openmaic/dsl/src/slides.ts) file exports the fundamental types for slide composition:

- **`Slide`** – The top-level container for a single presentation slide.
- **`PPTElement`** – The base union type for all visual elements, with variants for shapes, text, images, and media slots.
- **Enums** – Element kinds, shape categories, and media slot identifiers.

### Lesson Skeleton and Actions

The [`packages/@openmaic/dsl/src/stage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/packages/@openmaic/dsl/src/stage.ts) file defines the pedagogical structure:

- **`Stage`** – The root document containing scenes and metadata.
- **`Scene<TAction, TContent>`** – A generic container for lesson segments, parameterized by action type and content type.
- **`Action`** – A union type representing interactive triggers (navigation, animation, state changes).
- **Type Guards** – Runtime functions to narrow `Action` and `Scene` variants safely.

## Validation and Normalization Utilities

The package provides pure functions to ensure data integrity without external libraries.

### Structural Validators

The [`packages/@openmaic/dsl/src/validate.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/packages/@openmaic/dsl/src/validate.ts) module exports zero-dependency validation functions:

- **`validateStage`** – Checks a complete `Stage` document for structural errors.
- **`validateScene`** – Validates a single scene's integrity before rendering.
- **`validateAction`** – Confirms that an action object conforms to the expected union variants.

These functions return detailed result objects indicating validity and specific error paths, allowing upstream packages like the renderer to fail gracefully.

### Document Normalizers

The [`packages/@openmaic/dsl/src/normalize.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/packages/@openmaic/dsl/src/normalize.ts) file provides **normalizer functions** that repair and complete partial documents:

- **`normalizeElement`** – Fills required defaults for any `PPTElement` subclass.
- **`normalizeSlide`** – Derives geometry and ensures all mandatory fields exist on a `Slide` object.

Producers use these functions to "repair" documents in-place, ensuring that downstream consumers receive fully populated structures even when input data is incomplete.

## Asset Management and Enumeration

The [`packages/@openmaic/dsl/src/asset-manifest.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/packages/@openmaic/dsl/src/asset-manifest.ts) module exports **`enumerateAssetManifest`**, a pure function that traverses a `Stage` document and lists every media reference without performing I/O operations.

This utility accepts an optional `metadata` callback to fetch external asset properties (size, MIME type) from a database or CDN while keeping the core enumeration logic dependency-free.

## Versioning and Migration

The [`packages/@openmaic/dsl/src/version.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/packages/@openmaic/dsl/src/version.ts) file manages contract evolution:

- **`DSL_VERSION`** – The current serialized contract version constant.
- **`migrate`** – A pure function that applies a migration ladder to upgrade documents from older schema versions to the current specification.

Because the JSON Schema artifacts are generated from the TypeScript types at build time, the validators and cross-language schema definitions remain perfectly aligned across versions.

## Role in the OpenMAIC Ecosystem

The `@openmaic/dsl` package functions as the **contractual boundary** between data producers and consumers. In [`render-service/src/main.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/render-service/src/main.ts), the renderer imports `validateScene` from the DSL to pre-validate scenes before rendering, preventing runtime crashes from malformed data.

By isolating the data contract from UI, storage, and generation concerns, the DSL enables independent evolution of:

- **Rendering engines** (React, Canvas, WebGL).
- **Import pipelines** (PPTX, PDF, custom formats).
- **Storage adapters** (local, cloud, embedded).

Any package under `@openmaic/*` imports types, validators, and normalizers from `@openmaic/dsl`, ensuring that a change to the core data model propagates consistently across the entire codebase.

## Practical Usage Examples

### Validating a Scene Before Rendering

```typescript
import { validateScene } from '@openmaic/dsl';

const result = validateScene(rawScene);
if (!result.valid) {
  console.error('Scene validation failed:', result.errors);
}

```

### Normalizing a Slide for Consistency

```typescript
import { normalizeSlide } from '@openmaic/dsl';

const cleanSlide = normalizeSlide(rawSlide);
// cleanSlide now contains all required fields and derived geometry

```

### Enumerating Media Assets

```typescript
import { enumerateAssetManifest } from '@openmaic/dsl';

const manifest = enumerateAssetManifest(stageDoc, {
  metadata(ref, kind) {
    // Optional: fetch size/mime from a DB or CDN
    return undefined;
  },
});
console.log(manifest.entries);

```

### Migrating Legacy Documents

```typescript
import { migrate, DSL_VERSION } from '@openmaic/dsl';

const migratedDoc = migrate(oldDoc);
// migratedDoc.dslVersion now equals the current DSL_VERSION

```

## Summary

- **The `@openmaic/dsl` package** is the zero-dependency specification layer that defines all data structures for the OpenMAIC platform.
- **It provides pure TypeScript types** for `Slide`, `PPTElement`, `Stage`, `Scene`, and `Action` unions without any framework dependencies.
- **Structural integrity** is enforced through `validateStage`, `validateScene`, and `validateAction` in [`validate.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/validate.ts).
- **Data repair** is handled by `normalizeSlide` and `normalizeElement` functions that fill defaults and derive geometry.
- **Asset enumeration** via `enumerateAssetManifest` extracts media references without I/O dependencies.
- **Contract versioning** uses `DSL_VERSION` and the `migrate` function to upgrade legacy documents safely.
- **Cross-package compatibility** is guaranteed because every OpenMAIC module—from renderers to importers—depends on this single source of truth.

## Frequently Asked Questions

### Why does `@openmaic/dsl` maintain zero runtime dependencies?

The package ships with no external dependencies to prevent bundle bloat and framework lock-in. This allows the DSL to run in constrained environments like Web Workers, serverless functions, and non-JavaScript consumers that rely solely on the generated JSON Schema, while ensuring that importing the contract does not drag in React, PPTX parsers, or charting libraries.

### What is the difference between validation and normalization in the DSL?

**Validation** (via `validateScene`, `validateStage`) performs structural checks against the schema and returns boolean results with error details, never modifying the input object. **Normalization** (via `normalizeSlide`, `normalizeElement`) mutates or returns new objects with filled default values and computed properties, ensuring downstream consumers receive complete data structures even from partial or legacy inputs.

### How does `@openmaic/dsl` handle schema changes over time?

The package manages evolution through the `DSL_VERSION` constant and the `migrate` function exported from [`version.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/version.ts). When older documents are loaded, `migrate` applies a pure functional ladder to transform them to the current schema version. Because TypeScript types generate the JSON Schema at build time, the migration logic and validators remain synchronized with the type definitions.

### Can I use `@openmaic/dsl` outside of a Node.js environment?

Yes. Because the package contains only pure TypeScript/JavaScript with zero native or Node-specific dependencies, it executes safely in browsers, Web Workers, and embedded JavaScript engines. Additionally, the build process generates standalone JSON Schema files that non-JavaScript consumers can use to validate OpenMAIC documents in other languages.