Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic external transformation support to relay-compiler #1710

Closed
wants to merge 1 commit into from
Closed
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
8 changes: 7 additions & 1 deletion packages/relay-compiler/bin/RelayCompilerBin.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ async function run(options: {
schema: string,
src: string,
extensions: Array<string>,
transform: Array<string>,
watch?: ?boolean,
}) {
const schemaPath = path.resolve(process.cwd(), options.schema);
Expand Down Expand Up @@ -87,7 +88,7 @@ Ensure that one such file exists in ${srcDir} or its parents.
default: {
baseDir: srcDir,
getFileFilter: RelayFileIRParser.getFileFilter,
getParser: RelayFileIRParser.getParser,
getParser: RelayFileIRParser.getParser(options.transform),
getSchema: () => getSchema(schemaPath),
watchmanExpression: buildWatchExpression(options),
},
Expand Down Expand Up @@ -193,6 +194,11 @@ const argv = yargs
describe: 'File extensions to compile (--extensions js jsx)',
type: 'string',
},
'transform': {
array: true,
describe: 'Use a transform module on top-level files',
type: 'string',
},
'watch': {
describe: 'If specified, watches files and regenerates on changes',
type: 'boolean',
Expand Down
48 changes: 41 additions & 7 deletions packages/relay-compiler/core/RelayFileIRParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ import type {FileFilter} from 'RelayCodegenWatcher';
import type {DocumentNode} from 'graphql';

// Throws an error if parsing the file fails
function parseFile(file: string): ?DocumentNode {
const text = fs.readFileSync(file, 'utf8');
function parseFile(file: string, text: string): ?DocumentNode {
const moduleName = path.basename(file, path.extname(file));

invariant(
Expand Down Expand Up @@ -71,11 +70,46 @@ function parseFile(file: string): ?DocumentNode {
};
}

function getParser(baseDir: string): FileParser {
return new FileParser({
baseDir,
parse: parseFile,
});
type TransformFactory = (baseDir: string) => (filename: string, text: string) => string
type TransformModule = { default: TransformFactory }

function getParser(transformModules: Array<string> = []) {
return (baseDir: string): FileParser => {
const transformer = getTransformer(baseDir, transformModules)
return new FileParser({
baseDir,
parse: (filename: string) => {
const text = fs.readFileSync(filename, 'utf8');
return parseFile(filename, transformer(filename, text))
},
});
}
}

function getTransformer(baseDir: string, transformModules: Array<string> = []) {
let transformer = (filename: string, text: string) => text
if (transformModules.length) {
transformModules.forEach(moduleName => {
let moduleImpl: TransformFactory
try {
// $FlowFixMe flow doesn't know about __non_webpack_require__
moduleImpl = (__non_webpack_require__(moduleName): TransformFactory)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @wincent - could we use this to require the persist module?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably. I need to re-test my PR. If it doesn't work can try this "one weird trick".

invariant(
moduleImpl.default,
'Transformer module "' + moduleName + '" should have a default export'
);
} catch (e) {
throw new Error(
'Can not resolve transformer module "' + moduleName + '"'
);
}
const transformerImpl = moduleImpl.default(baseDir)
const prevTransformer = transformer
transformer = (filename: string, text: string) => transformerImpl(filename, prevTransformer(filename, text))
})
}

return transformer
}

function getFileFilter(baseDir: string): FileFilter {
Expand Down