Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/babel-plugin-flow-runtime/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ The plugin supports the following options:
- `assert` - Boolean, indicates whether types should be asserted at runtime. Defaults to `true` if `process.env.NODE_ENV === 'development'`, otherwise `false`.
- `annotate` - Boolean, indicates whether object or function values that have type annotations should be decorated with those types at runtime. Defaults to `true`.
- `libraryName` - String, indicates which runtime to use. Defaults to `flow-runtime`
- `libraryImport` - String, either `import` or `require`, indicates how the runtime should be loaded. Defaults to `import`.


If `assert` is `true`, the following code:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default class ConversionContext {

libraryName: string = 'flow-runtime';
libraryId: string = 't';
libraryImport: string = 'import';
shouldImport: boolean = true;
shouldAssert: boolean = true;
shouldWarn: boolean = false;
Expand Down
51 changes: 51 additions & 0 deletions packages/babel-plugin-flow-runtime/src/__tests__/transform.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,55 @@ describe('transform', () => {
});
}
}

it('should support requiring the runtime library', () => {
testTransform(`
type User = {
id: number;
name: string;
};
`, {assert: true, annotate: false, libraryImport: 'require'}, `
const t = require("flow-runtime");

const User = t.type("User", t.object(
t.property("id", t.number()),
t.property("name", t.string())
));
`);
});

it('should support requiring a custom runtime library', () => {
testTransform(`
type User = {
id: number;
};
`, {
assert: true,
annotate: false,
libraryName: './custom-flow-runtime',
libraryImport: 'require'
}, `
const t = require("./custom-flow-runtime");

const User = t.type("User", t.object(
t.property("id", t.number())
));
`);
});

it('should reuse an existing required runtime binding', () => {
testTransform(`
const rt = require("flow-runtime");

type User = {
id: number;
};
`, {assert: true, annotate: false, libraryImport: 'require'}, `
const rt = require("flow-runtime");

const User = rt.type("User", rt.object(
rt.property("id", rt.number())
));
`);
});
});
21 changes: 15 additions & 6 deletions packages/babel-plugin-flow-runtime/src/attachImport.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,21 @@ import type {NodePath} from '@babel/traverse';

export default function attachImport (context: ConversionContext, program: NodePath) {

const importDeclaration = t.importDeclaration(
[t.importDefaultSpecifier(t.identifier(context.libraryId))],
t.stringLiteral(context.libraryName)
);

importDeclaration.importKind = 'value';
const importDeclaration = context.libraryImport === 'require'
? t.variableDeclaration('const', [
t.variableDeclarator(
t.identifier(context.libraryId),
t.callExpression(t.identifier('require'), [t.stringLiteral(context.libraryName)])
)
])
: t.importDeclaration(
[t.importDefaultSpecifier(t.identifier(context.libraryId))],
t.stringLiteral(context.libraryName)
);

if (t.isImportDeclaration(importDeclaration)) {
importDeclaration.importKind = 'value';
}

context.shouldImport = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export type Options = {
// deprecated
decorate?: boolean;
libraryName?: string,
libraryImport?: string,
optInOnly?: boolean;
};

Expand All @@ -23,6 +24,10 @@ export default function createConversionContext (options: Options): ConversionCo
context.libraryName = options.libraryName;
}

if (options.libraryImport) {
context.libraryImport = options.libraryImport;
}

context.optInOnly = options.optInOnly ? true : false;

context.shouldAssert = options.assert === undefined
Expand Down
14 changes: 14 additions & 0 deletions packages/babel-plugin-flow-runtime/src/firstPassVisitors.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,20 @@ export default function firstPassVisitors (context: ConversionContext): Object {
context.lastImportDeclaration = path;
},
VariableDeclarator (path: NodePath) {
const init = path.get('init');
const idPath = path.get('id');

if (
context.libraryImport === 'require' &&
idPath.isIdentifier() &&
init.isCallExpression() &&
init.get('callee').isIdentifier({name: 'require'}) &&
init.get('arguments.0').isStringLiteral({value: context.libraryName})
) {
context.shouldImport = false;
context.libraryId = idPath.node.name;
}

for (const id of findIdentifiers(path.get('id'))) {
const {name} = id.node;
context.defineValue(name, path);
Expand Down