Skip to content

Easily generate TypeScript schemas, JSON Schemas, or any schema of your choice from cerebris/jsonapi-resources JSONAPI::Resource classes.

License

Notifications You must be signed in to change notification settings

mattkhan/jsonapi-resources-anchor

Repository files navigation

JSON:API Resource Schema Generation: Anchor

Documentation

Easily generate TypeScript schemas, JSON Schemas, or any schema of your choice from cerebris/jsonapi-resources JSONAPI::Resource classes.

Ideally, API schemas have the types of each payload fully specified.

jsonapi-resources-anchor provides:

  • Type inference via the underlying ActiveRecord model of a resource
  • Type annotation, e.g. attribute :name_length, Anchor::Types::Integer
  • Configuration, e.g. setting the case (camel, snake, etc.) of properties and deriving TypeScript comments from database comments
  • TypeScript and JSON Schema generators via Anchor::TypeScript::SchemaGenerator and Anchor::JSONSchema::SchemaGenerator

See the example Rails app for a fully functional app using Anchor.

Installation

gem 'jsonapi-resources-anchor'
bundle install

TypeScript Demo

Given:

ActiveRecord Schema:

  create_table "comments", force: :cascade do |t|
    t.string "text", null: false
    t.string "commentable_type"
    t.bigint "commentable_id"
    t.bigint "user_id", null: false
    t.bigint "deleted_by_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["commentable_type", "commentable_id"], name: "index_comments_on_commentable"
    t.index ["deleted_by_id"], name: "index_comments_on_deleted_by_id"
    t.index ["user_id"], name: "index_comments_on_user_id"
  end

  create_table "posts", force: :cascade do |t|
    t.string "description", null: false
    t.bigint "user_id", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["user_id"], name: "index_posts_on_user_id"
  end

  create_table "users", force: :cascade do |t|
    t.string "name", null: false
    t.integer "integer"
    t.decimal "decimal"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "role"
  end

JSONAPI::Resource classes:

class ApplicationResource < JSONAPI::Resource
  abstract
  include Anchor::SchemaSerializable
end

class CommentResource < ApplicationResource
  attribute :text
  attribute :created_at
  attribute :updated_at
  attribute :inferred_unknown
  attribute :type_given, Anchor::Types::String

  relationship :user, to: :one
  relationship :commentable, Anchor::Types::Relationship.new(resources: [UserResource, PostResource], null: true), polymorphic: true, to: :one
end

class UserResource < ApplicationResource
  attribute :name
  attribute :role, UserRoleEnum

  relationship :comments, to: :many
  relationship :posts, to: :many
end

class UserRoleEnum < Anchor::Types::Enum
  anchor_schema_name "UserRole"

  value :admin, "admin"
  value :content_creator, "content_creator"
  value :external, "external"
  value :guest, "guest"
  value :system, "system"
end

class PostResource < ApplicationResource
  attribute :description

  relationship :user, to: :one
  relationship :comment, to: :many
end

class Schema < Anchor::Schema
  resource CommentResource
  resource UserResource
  resource PostResource

  enum UserRoleEnum
end

Anchor::TypeScript::SchemaGenerator.call(register: Schema.register) will return the schema below in a String:

type Maybe<T> = T | null;

export type Comment = {
  id: number;
  type: "comments";
  text: string;
  created_at: string;
  updated_at: string;
  inferred_unknown: unknown;
  type_given: string;
  relationships: {
    user: User;
    commentable: Maybe<User | Post>;
  };
};

export type User = {
  id: number;
  type: "users";
  name: string;
  role: UserRole;
  relationships: {
    comments: Array<Comment>;
    posts: Array<Post>;
  };
};

export type Post = {
  id: number;
  type: "posts";
  description: string;
  relationships: {
    user: User;
    comment: Array<Comment>;
  };
};

export enum UserRole {
  Admin = "admin",
  ContentCreator = "content_creator",
  External = "external",
  Guest = "guest",
  System = "system",
}

References

Security

Security Policy

About

Easily generate TypeScript schemas, JSON Schemas, or any schema of your choice from cerebris/jsonapi-resources JSONAPI::Resource classes.

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •