/metarpheus-tcomb

metarpheus to JS / tcomb

Primary LanguageJavaScriptMIT LicenseMIT

metarpheus-tcomb

Build Status

generate a tcomb domain model interpreting metarpheus output

install

npm i metarpheus-tcomb

usage

metarpheus-tcomb --config=path/to/config/file

usage from node

metarpheusTcomb = require('metarpheus-tcomb')

model = metarpheusTcomb({
  intermRep: {}, // a valid interm. rep. object (output from metarpheus),
  config: {
    // more configuration (see below)
  }
}).model

configuration

An example config file is in config.js

By default, the model is generated into ./model.js

export default {
  intermRepIn: 'test/fixtures/metarpheus-interm-rep.json',
  modelPrelude: `import t from 'tcomb';
`,
  apiPrelude: `import t from 'tcomb';
import * as m from './model';
`,
  apiModelPrefix: 'm.',
  modelOut: 'model.js',
  apiOut: 'api.js',
  overrides: {
    Date: (_, { prefix = '' }) => `${prefix}MyDateType`
  }
};

Note: for node usage, you shouldn't provide intermRepIn, modelOut, apiOut via config. You should pass intermRep as a separate parameter, and the model and api outputs are returned by the node api function.

Example

Here's the gist:

sealed trait UserType extends CaseEnum
object UserType {
  case object User extends UserType
  case object SuperUser extends UserType
}

/**
  * A user
  *
  * @param _id ID of the user
  * @param username username
  * @param userType type of the user
  */
case class User(
  _id: Id[User],
  username: String,
  userType: UserType)


val route = {
  pathPrefix("users") {
    (get & pathCommit(`:Id`[User]) /**
      get user by id
    */) (returns[User].ctrlu(userController.findById)) ~
    (post & pathCommit("logout") /**
      performs the logout for the currently logged user
    */) (returns[Unit].ctrlu(userController.logout))
  }
}

becomes...

export const UserType = t.enums.of([
  'User',
  'SuperUser'
], 'UserType');

export const User = t.struct({
  _id: Id/*Id[User]*/, // ID of the user
  username: t.String, // username
  userType: UserType // type of the user
}, 'User');

export const api = [
  // GET /users/ : get user by id
  {
    method: 'get',
    name: ['userController', 'findById'],
    authenticated: true,
    returnType: User,
    route: (...routeParams) => ['users', routeParams[0]].join('/'),
    routeParamTypes: [Id/*Id[User]*/],
    params: {}
  },
  // POST /users/logout : performs the logout for the currently logged user
  {
    method: 'post',
    name: ['userController', 'logout'],
    authenticated: true,
    returnType: User,
    route: (...routeParams) => ['users', 'logout'].join('/'),
    routeParamTypes: [],
    params: {}
  }
];

TODO

the api part should probably be moved to its own repo, left it here for simplicity for now.

apiOut config param is thus optional