@denna-labs/spec-client
v1.1.0
Published
TypeScript library + CLI for loading and validating Denna Spec data files.
Readme
@denna-spec/client
TypeScript library + CLI for loading, validating, and generating types from Denna Spec data files.
Denna Spec is a convention for structuring protocol parameters as JSON files validated by JSON Schema 2020-12. This client handles the full lifecycle: schema-driven codegen at build time, and validated + typed data loading at runtime.
Install
npm install @denna-spec/clientQuick start
Load a data file
import { DennaSpec } from '@denna-spec/client';
const denna = new DennaSpec();
const data = await denna.load('shared/stablecoin-addresses.denna-spec.json');
console.log(data.metadata.kind); // "io.denna.defi.address-registry"
console.log(data.addresses);load() does the following in order:
- Resolves the source (file path, URL, or alias from config)
- Fetches and parses the JSON
- Reads the
$schemafield and fetches the schema - Pre-loads any
$ref-referenced schemas from disk to avoid network requests - Validates with Ajv (JSON Schema 2020-12, strict mode)
- Dereferences
$refchains and hydrates missing optional fields with zero values - Returns the typed result
Generate TypeScript types from schemas
import { generateTypes } from '@denna-spec/client';
const output = await generateTypes({
schemas: ['https://spec.denna.io/v1/defi/rates.schema.json'],
output: './generated/denna-types.ts',
});This produces TypeScript interfaces from JSON Schema files, plus a SchemaTypeMap interface that maps schema $id URLs to their root types.
CLI
The package ships a denna CLI with three commands.
denna sync
Regenerate TypeScript types from the schemas listed in denna.config.json.
denna sync
denna sync --config path/to/denna.config.jsondenna load <source>
Load, validate, and print a data file as JSON.
denna load shared/stablecoin-addresses.denna-spec.json
denna load sky:spark/protocol-config --compactdenna validate <sources...>
Validate one or more data files. Supports glob patterns. Exits non-zero on failure.
denna validate shared/*.denna-spec.json
denna validate sky:spark/* sky:obex/*Configuration
Create a denna.config.json in your project root (the CLI auto-discovers it by walking up from cwd):
{
"schemas": [
"https://spec.denna.io/v1/defi/rates.schema.json",
"./local/schemas/custom.schema.json"
],
"output": "./generated/denna-types.ts",
"sources": {
"sky": {
"type": "filesystem",
"path": "../sky-parameters"
},
"remote": {
"type": "github",
"repo": "org/repo",
"ref": "main"
}
}
}| Field | Description |
|-------|-------------|
| schemas | Schema URLs or file paths for codegen (denna sync) |
| output | Output path for generated TypeScript types |
| sources | Named aliases for data sources (filesystem paths or GitHub repos) |
Source aliases
Aliases let you reference data files without full paths:
sky:spark/protocol-configresolves to<source.path>/spark/protocol-config.denna-spec.jsonfor filesystem sources, or the equivalent raw GitHub URL for GitHub sources.- Glob patterns work with aliases:
sky:spark/*
API
DennaSpec
import { DennaSpec } from '@denna-spec/client';
// Auto-discover denna.config.json
const denna = new DennaSpec();
// Explicit config path
const denna = new DennaSpec({ config: './denna.config.json' });
// No config (resolve paths directly)
const denna = new DennaSpec({ config: false });
const data = await denna.load<MyType>('source');generateTypes(options)
import { generateTypes } from '@denna-spec/client';
const ts = await generateTypes({
schemas: ['./schema.json'],
output: './types.ts', // optional — also writes to file
});loadConfig(path) / discoverConfig(startDir)
import { loadConfig, discoverConfig } from '@denna-spec/client';
const configPath = await discoverConfig(process.cwd());
const config = configPath ? await loadConfig(configPath) : null;Errors
All errors extend DennaError:
| Class | When |
|-------|------|
| DennaLoadError | File not found, network error, HTTP error |
| DennaParseError | Invalid JSON or invalid config structure |
| DennaValidationError | Schema validation failure (includes .errors array with paths and messages) |
| DennaSchemaError | Schema fetch/compile failure |
All errors preserve the original cause for debugging.
How data files work
A .denna-spec.json file looks like:
{
"$schema": "https://spec.denna.io/v1/defi/rates.schema.json",
"metadata": { "kind": "io.denna.defi.rates" },
"rates": {
"ssrSpread": { "value": 30, "unit": "bps" }
}
}The $schema field points to the JSON Schema that validates the file. Schemas use JSON Schema 2020-12 and may reference shared type definitions via $ref.
License
MIT
