Skip to content

Add support for JSON Schema#101

Open
safwanyp wants to merge 6 commits intoplatformatic:mainfrom
safwanyp:feat/json-schema
Open

Add support for JSON Schema#101
safwanyp wants to merge 6 commits intoplatformatic:mainfrom
safwanyp:feat/json-schema

Conversation

@safwanyp
Copy link

@safwanyp safwanyp commented Mar 8, 2026

Fixes #98

AI Usage

Used GPT-5.4 and 5.3-Codex during dev. Not sure why but it did not sign off on the commits which is why I'm mentioning it here. I also Kimi 2.5 and Opus 4.6 for interrogating over my thoughts - they were not used for wiritng code.

Testing

The docs in the repo seem out of date. I do not have enough context to confidently update them even with AI assistance, which is why I ran my tests selectively with

node --test packages/massimo-cli/test/json-schema-declarations.test.js packages/massimo-cli/test/json-schema-reference.test.js packages/massimo-cli/test/json-schema-render-type.test.js packages/massimo-cli/test/json-schema-scanner.test.js packages/massimo-cli/test/cli-json-schema.test.js

Quick Summary

This PR adds a JSON Schema generator to massimo-clie.

Scope:

  • parse a local JSON or YAML schema
  • generate deterministic .d.ts output
  • expose it through the CLI via --type json-schema
  • keep the implementation modular enough to evolve without turning it into a maze of tiny files like in my tool lol

As outlined in the linked issue, the intention is to generate types. Clients are not in scope of this PR.

What has been added

The implementation lives in packages/massimo-cli/lib/json-schema. I decided to keep it completely isolated to keep the blast radius as close to this new feature as possible. The only time I change something outside of this, is when adding a new flag to the CLI.

At a high level, the generator is split into four phases:

  1. scan: walk the schema and collect path-indexed state - schema nodes, refs, metadata, candidates for names.
  2. canonicalize: turn scan time names into stable declaration names and compute teh small set of safe alias reuses.
  3. build declaration graph: decide whhich declarations should exist, how unions should expand, and which declarations depend on others.
  4. validate and render: reject invalid declaration graphs and then emit to the final .d.ts in deterministic order.

This split in the processing is the main design choice in this PR.

CLI wiring is also included in the changes:

massimo path/to/schema.json --type json-schema --name mytypes --types-only

The current CLI handles:

  • local files only
  • types only
  • no frontend mode
  • no client generation

Why this structure

The main issue in my early iterations was that the output depended on traversal order of the schema. That is what pushed the implementation towards the aforementioned "four phases". Eventually my goal got super clear - same schema in, same declaration out. In line with this goal the implementation prefers determinism over super-specific outputs.

Conscious decisions

  • determinism over aggressive alias reuse
    • if naming is ambiguous, the pipeline prefers a distinct stable name over a potential conflict
  • separate inline rendering from declaration emission
    • rendering string | number inline is a different concern from deciding whether a named declaration should exist
  • keep object unions in the declaration layer
    • base/branch/union shaping lives in the declaration graph instead of the low-level renderers
  • keep the first CLI integration narrow
    • avoids overpromising remote-schema or client-generation behavior too early since I need to familiarize myself with the way that works

I've tried to make the commits easy to digest and review. Some bias may have crept in to how each commit is structured, but I hope it's not too messy.

Validation

The branch is in a reviewable state:

  • tests I added are passing
  • linter produces no issues

Follow-Up Work

The next sensible extensions are:

  1. Broaden schema coverage with more fixtures
    • recursive schemas
    • external refs
    • heavier allOf
    • record-like objects
    • mixed nullable/type-array shapes
  2. Expand supported JSON Schema surface area carefully
  3. Improve output ergonomics without sacrificing on the determinism
    • better naming heuristics
    • fewer redundant helper aliases
    • cleaner nested union public surfaces
  4. Revisit CLI scope later if there is demand
    • richer UX around JSON Schema inputs
    • possibly broader input support
    • not sure if this will be the case cuz based on my posts in some forums, people just default to tools like zod now.

This is the first time I am contributing what I think is a relatively chunky "first vertical slice" in a tool. Feedback is always something i'm looking for and I truuuuly appreciate the time you (the reviewer) will take.

Happy reviewing (hopefully)! 🪿

@safwanyp safwanyp force-pushed the feat/json-schema branch 4 times, most recently from 6df3734 to cd249fc Compare March 12, 2026 23:11
Signed-off-by: Safwan Parkar <self@safwanyp.com>
Signed-off-by: Safwan Parkar <self@safwanyp.com>
Signed-off-by: Safwan Parkar <self@safwanyp.com>
Signed-off-by: Safwan Parkar <self@safwanyp.com>
Signed-off-by: Safwan Parkar <self@safwanyp.com>
Signed-off-by: Safwan Parkar <self@safwanyp.com>
@safwanyp safwanyp marked this pull request as ready for review March 13, 2026 13:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: Support for generating type defs from JSON Schemas

1 participant