Skip to content

Instantly share code, notes, and snippets.

@hanse
Last active September 26, 2017 21:48
Show Gist options
  • Save hanse/06cc53b8c5d4334a7787949789147830 to your computer and use it in GitHub Desktop.
Save hanse/06cc53b8c5d4334a7787949789147830 to your computer and use it in GitHub Desktop.
const fs = require('fs');
const recast = require('recast');
const humps = require('humps');
const code = fs.readFileSync('./app/actions/ActionTypes.js');
const b = recast.types.builders;
const actions = [];
const ast = recast.parse(code);
recast.types.visit(ast, {
visitObjectExpression(path) {
if (!path.parentPath.node.id) {
return false;
}
const prefix = path.parentPath.node.id.name;
path.node.properties.forEach(property => {
const isAsync = property.value.type === 'CallExpression';
const action = prefix + '.' + property.key.name;
actions.push({ action, prefix, isAsync });
});
return false;
}
});
const pascalize = value => humps.pascalize(value.toLowerCase());
const formatActionType = value => {
const [prefix, action] = value.split('.');
return pascalize(humps.decamelize(prefix) + '_' + action);
};
function buildActionObjectType(name, payloadType, extraProperties = []) {
return b.objectTypeAnnotation([
b.objectTypeProperty(
b.identifier('type'),
b.stringLiteralTypeAnnotation(name, name),
false
),
b.objectTypeProperty(b.identifier('payload'), payloadType, false),
b.objectTypeProperty(b.identifier('meta'), b.anyTypeAnnotation(), false),
...extraProperties
]);
}
function buildActionTypeDeclaration(name, payloadType, extraProperties) {
return b.exportNamedDeclaration(
b.typeAlias(
b.identifier(formatActionType(name)),
null,
buildActionObjectType(name, payloadType, extraProperties)
)
);
}
const flatten = array =>
array.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []);
ast.program.body = [];
const genType = type => b.genericTypeAnnotation(b.identifier(type), null);
function buildAction({ action, isAsync }) {
if (!isAsync) {
return [
buildActionTypeDeclaration(
action,
b.genericTypeAnnotation(b.identifier('any'), null)
)
];
}
return [
buildActionTypeDeclaration(
action,
b.genericTypeAnnotation(b.identifier('any'), null)
),
buildActionTypeDeclaration(
action + '_SUCCEEDED',
b.genericTypeAnnotation(b.identifier('any'), null)
),
buildActionTypeDeclaration(action + '_FAILED', genType('Error'), [
b.objectTypeProperty(b.identifier('error'), genType('true'), false)
])
];
}
actions.forEach(action => {
ast.program.body.push(...buildAction(action));
});
ast.program.body.push(
b.exportNamedDeclaration(
b.typeAlias(
b.identifier('Action'),
null,
b.unionTypeAnnotation(
flatten(
actions.map(({ action, isAsync }) =>
[
b.genericTypeAnnotation(
b.identifier(formatActionType(action)),
null
),
isAsync &&
b.genericTypeAnnotation(
b.identifier(formatActionType(action + '_succeeded')),
null
),
isAsync &&
b.genericTypeAnnotation(
b.identifier(formatActionType(action + '_failed')),
null
)
].filter(Boolean)
)
)
)
)
)
);
console.log(recast.print(ast).code);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment