https://github.com/bwireman/genus
Type Script and Elixir structs, a monster mash
https://github.com/bwireman/genus
Last synced: 11 months ago
JSON representation
Type Script and Elixir structs, a monster mash
- Host: GitHub
- URL: https://github.com/bwireman/genus
- Owner: bwireman
- License: mit
- Created: 2022-05-15T15:41:20.000Z (about 4 years ago)
- Default Branch: main
- Last Pushed: 2023-03-04T18:45:12.000Z (over 3 years ago)
- Last Synced: 2024-11-07T15:46:09.149Z (over 1 year ago)
- Language: Elixir
- Size: 95.7 KB
- Stars: 5
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Genus
Macro for generating Typescript types and Elixir structs
## Installation
```elixir
def deps do
[
{:genus, git: "git@github.com:bwireman/genus.git"}
]
end
```
## Usage
```elixir
defmodule User do
# load the `tschema` macro
use Genus
tschema name: "User" do
field(:id, :string, required: true)
field(:email, :string)
field(:active, :bool, default: false)
field(:role, :union, "Role", true, [:enduser, :admin, :superuser], default: :enduser)
end
end
```
### Macro Options
- name: Name of the generated TypeScript interface, defaults to the last piece of the module name
- imports: keyword of other imports and import overrides to add to the generated file
### Elixir output
```elixir
defmodule User do
@enforce_keys [:id]
defstruct [id: nil, email: nil, active: false, role: :enduser]
end
```
### Typescript output
```typescript
// Do Not Modify! This file was generated by Genus from an Elixir struct @ Elixir.User
// https://github.com/bwireman/genus
export type Role = "enduser" | "admin" | "superuser"
export interface User {
id: string
email?: string
active: boolean
role: Role
}
export const apply_user = (v: any): User => v
export const build_user = ({ id, email, active, role }: {
id: string
email?: string
active?: boolean
role?: Role
}): User => {
return {
id: id,
email: email || undefined,
active: active || false,
role: role || "enduser",
}
}
export const new_user = (id: string) => build_user({ id })
```
### Config
```elixir
import Config
config :genus,
# path directory to save the write TypeScript code to
# defaults to "./ts"
directory: "types",
# indent spacer for generated TypeScript
# defaults to " "
indent: "\t"
```
## Types
| Format | Elixir type | TS type |
| -------------------------------------------- | ----------- | ----------- |
| (name, :string) | String.t() | string |
| (name, :integer) | integer() | number |
| (name, :float) | float() | number |
| (name, :bool) | bool() | boolean |
| (name) | any() | any |
| (name, :external, type_name) | any() | type_name |
| (name, :list, type_name) | list() | type_name[] |
| (name, :union, type_name, is_string, values) | any() | type_name |
#### Type Options
- type_name `String.t()`: represents the TS type to use
- is_string `bool()`: Should the union be represented as strings in TS
- values `list()`: Values that compose the union
## Field Options
#### `default: value` | `required: true|false`
Fields default to being optional and with a `nil` default in Elixir and nullable with a default of `undefined` in TypeScript. If you specify a value that will be the default value in both Elixir and Typescript. You can also specify `required:` and mark the field as required in both the Elixir struct and the generator function