objection-generator
Generates objection.js
models in Typescript
from a YAML specification.
- Generate your initial set of
objection.js
models from a YAML file - Supports
$ref
for re-using common definitions - Can also generate a basic
knex
migration file based on the YAML file
Installation
Install the CLI utility
$ npm i objection-generator -g
Install knex + objection (if you do not have it installed)
$ npm i knex objection --save
Usage
Objection.js model generation
$ objection-generator generate <specFile> <outDir>
objection-generator generate <specFile> <outDir> Generates objection.js models from a YAML file Positionals: specFile The YAML file to use to generate models. [string] [required] outDir The directory to output the models. [string] [required] [string] [required]
Sample output
Using the sample.yaml
spec in this project:
$ objection-generator generate sample.yaml /tmp/lib
Will generate the following folder structure:
/tmp/lib/
├── models/
│ ├── BaseModel.ts
│ ├── <model>.ts
Will generate models that look like this:
Knex configuration
You must use knexSnakeCaseMappers
in your knex
configuration.
Knex migration generation
The YAML can also be used to generate a basic migration file. This can be used as a good starting base for building a desired migration.
Limitations
There are many limitations to the generation since there is not an exact mapping between JSON schema types / information in the objection models to an exact database specification.
Some limitations include:
- No foreign keys are generated (PRs welcomed - make use of the
relations
please) - No through tables are generated
PRs are welcomed for improvements!
Usage
$ objection-generator knex <specFile> <outDir>
objection-generator knex <specFile> <outDir> Generates a basic knex migration from a YAML file Positionals: specFile The YAML file to use to generate models. [string] [required] outDir The directory to output the models. [string] [required] [string] [required]
Sample output
Using the sample.yaml
spec in this project:
$ objection-generator knex sample.yaml /tmp/lib
Will generate the following folder structure:
/tmp/lib/
├── migrations/
│ └── 000-init.js
└── migrate.js
Example migration output:
{ await knexschema await knexschema await knexschema} { await knexschema await knexschema await knexschema} moduleexports = up down
Run the migration
The output includes a sample migration script that uses sqlite3
as the
database driver for quick prototyping.
$ npm i sqlite3 --save-dev
$ node <outputDir>/migrate.js
Modify this file to your liking to work with your own database.
YAML spec
See sample.yaml
for an example spec.
config: model: # Adds a prefix to the class names of the generated objection.js models classNamePrefix: # Adds a postfix to the class names of the generated objection.js models classNamePostfix: Model # Objection models to generate models: # Defines an objection model named Person (actually PersonModel with the postfix) Person: # database table name tableName: persons # maps to Model#jsonSchema() # https://json-schema.org/understanding-json-schema/reference/type.html # https://vincit.github.io/objection.js/guide/models.html#examples jsonSchema: required: ['name', 'username'] properties: id: type: string name: type: string minLength: 1 maxLength: 100 age: # You can define a re-usable set of properties and reference them via $ref $ref: '#/components/fieldProperties/age' gender: type: string enum: ['Male', 'Female', 'Other'] default: 'Female' favFood: type: string enum: ['pine-apple', 'blueBerry', 'cheese_pizza'] childrenCount: type: number default: 0 username: allOf: # combine a ref and a non-ref, see json schema spec for more info - $ref: '#/components/fieldProperties/username' - default: 'default-user' someOtherField: type: string created: type: string format: date-time # Define relations - maps to Model#relationMappings() # https://vincit.github.io/objection.js/guide/relations.html#examples relations: movies: relation: Model.ManyToManyRelation modelClass: Movie join: from: persons.id through: from: persons_movies.personId to: persons_movies.movieId to: movies.id reviews: relation: Model.HasManyRelation modelClass: Review join: from: persons.id to: review.authorId # Section for knex-specific generation database: # define unique indices unique: # made-up name for the unique index uniq_username: # columns to add to unique index # values will always be converted to snake case columns: ['username'] # Define indices index: # made-up name for the index name_age_index: # columns to index # values will always be converted to snake case columns: ['age', 'name'] exclude: # exclude these fields from being generated in the migration file # this is if you want to have a field defined in the model # but not in the database columns: ['someOtherField'] Movie: tableName: movies jsonSchema: required: ['name'] properties: id: type: string name: type: string minLength: 1 maxLength: 255 relations: reviews: relation: Model.HasManyRelation modelClass: Review join: from: movie.id to: review.movieId Review: tableName: reviews # If you want to use a primary key that's not called "id" idColumn: reviewId jsonSchema: required: ['authorId', 'movieId'] properties: reviewId: type: string authorId: type: string movieId: type: string content: type: string relations: author: relation: Model.HasOneRelation modelClass: Person join: from: reviews.authorId to: persons.id # components are re-usable elements that can be # referenced in the model via $ref components: # This is a made up section used for # defining common field properties fieldProperties: age: type: ['number', 'null'] username: type: string minLength: 1 maxLength: 25