Home

Awesome

babel-plugin-flow-to-json

Build Status

This plugin transforms flow types to JSON schema. You can manually validate data at runtime.

Example and why

// animals.js
type DogProps = {
  age: number,
  color: string
};
export class Dog {
  // $flow-to-json
  static properties: DogProps;
  constructor(props: DogProps) {
    this.props = props;
    // lots of logic
  }
}
type CatProps = {
  color: string,
  hasFur: boolean
};
export class Cat {
  // $flow-to-json
  static properties: CatProps;
  constructor(props: CatProps) {
    this.props = props;
    // lots of logic
  }
}
// api.js
import Ajv from 'ajv';
import * as animanls from 'animals';

const ajv = new Ajv();

router.post('/create-animal', ctx => {
  const { type, properties: requestProps } = ctx.request.body;
  const Animal = animals[type];
  if (!Animal) {
    ctx.throw(404);
  }
  if (!ajv.validate(Animal.properties, requestProps)) {
    ctx.status = 400;
    ctx.body = ajv.errors;
    return;
  }
  // your logic
});

It is nice to be able to do some validation at runtime with no writing JSON schema with already implemented Flow types. The animal types above would be transformed to:

export class Dog {
  // $flow-to-json
  static properties = {
    type: 'object',
    properties: {
      age: {
        type: 'number'
      },
      color: {
        type: 'string'
      }
    },
    required: ['age', 'color']
  };
  constructor(props) {
    this.props = props;
    // lots of logic
  }
}

export class Cat {
  // $flow-to-json
  static properties = {
    type: 'object',
    properties: {
      color: {
        type: 'string'
      },
      hasFur: {
        type: 'boolean'
      }
    },
    required: ['color', 'hasFur']
  };
  constructor(props) {
    this.props = props;
    // lots of logic
  }
}

Usage

yarn add babel-plugin-flow-to-json

Be sure to remove preset flow and place transform-flow-strip-types after flow-to-json to keep the flow types for json schema plugin.

.babelrc

{
    "presets": [
-       "flow"
    ],
    "plugins": [
+        "flow-to-json",
+        "transform-flow-strip-types"
    ]
}

Plugin transforms static properties of classes with flow types and leading comment $flow-to-json

More complex example

In:

type Element = {
  id: number,
  name: ?string
};

type Foo = {
  baz?: number,
  qux: Array<Element | number>
};

class Bar {
  // $flow-to-json
  static prop: Foo;
}

Out:

class Bar {
  static prop = {
    type: 'object',
    properties: {
      baz: {
        type: 'number'
      },
      qux: {
        type: 'array',
        items: {
          anyOf: [
            {
              type: 'object',
              properties: {
                id: {
                  type: 'number'
                },
                name: {
                  anyOf: [
                    {
                      type: 'null'
                    },
                    {
                      type: 'string'
                    }
                  ]
                }
              },
              required: ['id', 'name']
            },
            {
              type: 'number'
            }
          ]
        }
      }
    },
    required: ['qux']
  };
}

Supported

Broken

Not implemented