Tanu.js Save

An oversimplification of the TypeScript Compiler API for defining and generating source files.

Project README

Tanu 🦝

A simplified abstraction of the TypeScript Compiler API for defining and generating source files.

npm GitHub issues GitHub Repo stars

Why?

I've always hated the fact that the majority of packages generate TypeScript files from a ridiculously long template literal string, It's not type safe or even readable at all, and I saw a cool tweet.

Yes Matt, It does exist now.

What does Tanu mean? 🦝

Tanuki (a cute animal) but I removed the last two characters cause tanuki was already taken on npm, and sounded cool enough for me. Naming things is hard, okay?

How do I use this?

const User = t.interface("User", {
  id: t.number(),
  email: t.string(),
  name: t.optional({
    first: t.string(),
    last: t.string(),
  }),
});

const MemberRole = t.enum("MemberRole", [
  "DEFAULT",
  "PRIVILEGED",
  "ADMINISTRATOR",
]);

const Member = t.interface("Member", {
  user: User,
  role: MemberRole,
});

const Organization = t.interface("Organization", {
  name: t.comment(t.string(), [
    "The organization name.",
    "@see https://example.com/organization-name",
  ]),
  description: t.optional(t.string()),
  members: t.array(Member),
});

const result = await t.generate([User, MemberRole, Member, Organization]);
console.log(result);
// the generated result.

export interface User {
  id: number;
  email: string;
  name?:
    | {
        first: string;
        last: string;
      }
    | undefined;
}
export enum MemberRole {
  DEFAULT,
  PRIVILEGED,
  ADMINISTRATOR,
}
export interface Member {
  user: User;
  role: MemberRole;
}
export interface Organization {
  /**
   * The organization name.
   * @see https://example.com/organization-name
   */
  name: string;
  description?: string | undefined;
  members: Array<Member>;
}

What about interfaces that reference themselves, or cross-reference each other?

Passing in a callback to the t.interface method will lazily populate the interface with its returned values. This will ensure that you can self-reference or cross-reference the interface, and it will be available by generation.

import { t } from "tanu.js";

const User = t.interface("User", () => ({
  users: t.array(User),
  posts: t.array(Post),
  authoredComments: t.array(Comment),
}));

const Post = t.interface("Post", () => ({
  author: User,
  text: t.string(),
  images: t.array(t.string()),
  postComments: t.array(Comment),
}));

const Comment = t.interface("Comment", {
  author: User,
  post: Post,
  text: t.string(),
});

const CommentReply = t.type("CommentReply", () => ({
  parent: CommentReply,
  author: User,
  post: Post,
  text: t.string(),
}));

const result = await t.generate([User, Post, Comment, CommentReply]);
console.log(result);
// the generated result

export interface User {
  users: Array<User>;
  posts: Array<Post>;
  authoredComments: Array<Comment>;
}
export interface Post {
  author: User;
  text: string;
  images: Array<string>;
  postComments: Array<Comment>;
}
export interface Comment {
  author: User;
  post: Post;
  text: string;
}
export type CommentReply = {
  parent: CommentReply;
  author: User;
  post: Post;
  text: string;
};
Open Source Agenda is not affiliated with "Tanu.js" Project. README Source: ariesclark/tanu.js
Stars
133
Open Issues
2
Last Commit
1 year ago
Repository
License
MIT

Open Source Agenda Badge

Open Source Agenda Rating