npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

odetovibe

v1.0.0

Published

CLI and library for generating TypeScript code from declarative YAML codascon domain schemas

Readme

odetovibe

YAML-to-TypeScript code generation for codascon domains.

Odetovibe reads a declarative YAML schema describing your codascon domain — entity types, operations, and dispatch strategies — and generates the TypeScript scaffolding that enforces the protocol. On re-generation, existing method bodies, business logic and user comments are preserved.

Odetovibe is self-hosted. Its own ETL pipeline (Extract → Transform → Load) is implemented using the codascon protocol, described in YAML, and its TypeScript scaffolding is generated by odetovibe itself.

Install

CLI (global):

npm install -g odetovibe

Library (local):

npm install odetovibe
# or
pnpm add odetovibe

CLI

# See all options
npx odetovibe --help

# Generate TypeScript scaffolding (default: merge mode — preserves existing method bodies)
npx odetovibe schema.yaml --outDir src/

# Unconditional overwrite — replaces all generated files
npx odetovibe schema.yaml --outDir src/ --overwrite

# Strict mode — writes .ode.ts alongside the original on conflict instead of overwriting
npx odetovibe schema.yaml --outDir src/ --no-overwrite

If installed globally, replace npx odetovibe with odetovibe.

Write modes:

| Mode | Flag | Behaviour | | ----------- | ---------------- | ------------------------------------------------------------------------------------------ | | merge | (default) | Reconciles generated structure with existing code — method bodies and JSDoc are preserved | | overwrite | --overwrite | Unconditionally replaces every file | | strict | --no-overwrite | Like merge, but writes filename.ode.ts instead of overwriting on any structural conflict |

YAML Schema

Define your domain declaratively:

namespace: campus

domainTypes:
  Principal: {}
  Student:
    resolverName: resolveStudent
  Professor:
    resolverName: resolveProfessor
  Building: {}
  AccessResult: {}

commands:
  AccessBuildingCommand:
    commandName: accessBuilding
    baseType: Principal
    objectType: Building
    returnType: AccessResult
    subjectUnion: [Student, Professor]
    dispatch:
      Student: BasicAccess
      Professor: FullAccess
    templates:
      AccessTemplate:
        isParameterized: false
        strategies:
          BasicAccess: {}
          FullAccess: {}

Key rules:

  • domainTypes with resolverName become Subject classes; without become interfaces
  • Every entry in subjectUnion must appear in dispatch
  • dispatch values are plain Strategy names, looked up across the Command's templates
  • All Templates generate as abstract classes, regardless of whether strategies is empty or not
  • Template subjectSubset must be a subset of the parent Command's subjectUnion
  • Strategy subjectSubset must be a subset of the parent Template's subjectSubset; invalid (error) when the parent Template is not parameterized

See src/schema.ts for the full schema type definitions and validation rules.

Library API

Odetovibe exposes a three-phase ETL pipeline:

import { Project } from "ts-morph";
import { parseYaml, validateYaml, emitAst, writeFiles } from "odetovibe";

// Extract: parse YAML and validate against schema rules
const configIndex = parseYaml("campus.yaml");
const { valid, validationResults } = validateYaml(configIndex);
if (!valid) {
  for (const validationResult of validationResults) {
    for (const error of validationResult.errors)
      console.error(`[${error.entryKey}] ${error.rule}: ${error.message}`);
  }
  process.exit(1);
}

// Transform: emit TypeScript AST into an in-memory ts-morph Project
const project = new Project({ useInMemoryFileSystem: true });
emitAst(configIndex, { configIndex, project });

// Load: write SourceFiles to disk (merge preserves existing method bodies)
const results = await writeFiles(project, { targetDir: "./src", mode: "merge" });
for (const fileResult of results) {
  if (fileResult.compileErrors) {
    console.error("compile errors →", fileResult.path);
    for (const e of fileResult.compileErrors) console.error(" ", e);
  } else if (fileResult.conflicted) {
    console.warn("conflict →", fileResult.path);
  } else {
    console.log(fileResult.created ? "created" : "updated", fileResult.path);
  }
}

What Gets Generated

For each YAML entry, odetovibe emits:

| YAML entry | Generated output | | ----------------------------------- | ------------------------------------------------------------------------------------- | | domainType with resolverName | class SubjectName extends Subject | | domainType without resolverName | interface TypeName | | command | class CommandName extends Command<...> with typed resolver method stubs | | template | abstract class TemplateName implements Template<...> with a concrete execute stub | | strategy | class StrategyName extends TemplateName |

All classes are fully typed — generic parameters, resolver method signatures, hook properties — so the compiler enforces the codascon protocol from the first run.

License

MIT