Skip to content
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
74 changes: 70 additions & 4 deletions scripts/js-api/build-types/buildGeneratedTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const {ENTRY_POINT, IGNORE_PATTERNS, TYPES_OUTPUT_DIR} = require('../config');
const getRequireStack = require('./resolution/getRequireStack');
const translatedModuleTemplate = require('./templates/translatedModule.d.ts-template');
const translateSourceFile = require('./translateSourceFile');
const {promises: fs} = require('fs');
const {promises: fs, watch: fsWatch} = require('fs');
const micromatch = require('micromatch');
const path = require('path');
const {styleText} = require('util');
Expand All @@ -28,7 +28,7 @@ const {styleText} = require('util');
* [flow-api-translator](https://www.npmjs.com/package/flow-api-translator)
* along with our own pre and post-processing.
*/
async function buildGeneratedTypes(): Promise<void> {
async function buildGeneratedTypes(): Promise<Set<string>> {
const files = new Set<string>([path.join(REPO_ROOT, ENTRY_POINT)]);
const translatedFiles = new Set<string>();
const dependencyEdges: DependencyEdges = [];
Expand Down Expand Up @@ -83,7 +83,7 @@ async function buildGeneratedTypes(): Promise<void> {
' API translation encountered errors.\n',
);
process.exitCode = 1;
return;
return translatedFiles;
}

const touchedPackages = new Set<string>(
Expand All @@ -100,6 +100,7 @@ async function buildGeneratedTypes(): Promise<void> {
);
}
console.log('');
return translatedFiles;
}

type DependencyEdges = Array<[string, string]>;
Expand Down Expand Up @@ -208,4 +209,69 @@ class ModuleTranslationError extends Error {
}
}

module.exports = buildGeneratedTypes;
async function translateFile(file: string): Promise<void> {
const buildPath = getBuildPath(file);
const source = await fs.readFile(file, 'utf-8');
const {result: typescriptDef} = await translateSourceFile(source, file);
await fs.mkdir(path.dirname(buildPath), {recursive: true});
await fs.writeFile(
buildPath,
translatedModuleTemplate({
originalFileName: path.relative(REPO_ROOT, file),
source: stripDocblock(typescriptDef),
tripleSlashDirectives: extractTripleSlashDirectives(source),
}),
);
}

function watchGeneratedTypes(translatedFiles: Set<string>): void {
console.log(
styleText(['bold', 'inverse'], ' Watching for changes... ') + '\n',
);

const packageDirs = new Set(
Array.from(translatedFiles).map(file =>
path.join(
PACKAGES_DIR,
path.relative(PACKAGES_DIR, file).split(path.sep)[0],
),
),
);

for (const packageDir of packageDirs) {
fsWatch(packageDir, {recursive: true}, (eventType, filename) => {
if (filename == null) {
return;
}
const filePath = path.join(packageDir, filename);
if (!translatedFiles.has(filePath)) {
return;
}
process.stdout.write(
styleText('dim', 'File changed: ') +
path.relative(REPO_ROOT, filePath) +
'\n',
);
translateFile(filePath).then(
() => {
process.stdout.write(
styleText('green', ' ✔') +
' Rebuilt ' +
path.relative(REPO_ROOT, filePath) +
'\n',
);
},
(err: Error) => {
process.stderr.write(
styleText('red', ' ✖ Build error: ') + err.message + '\n',
);
},
);
});
}
}

module.exports = {
buildGeneratedTypes,
watchGeneratedTypes,
};
15 changes: 12 additions & 3 deletions scripts/js-api/build-types/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
require('../../shared/babelRegister').registerForScript();

const buildApiSnapshot = require('./buildApiSnapshot');
const buildGeneratedTypes = require('./buildGeneratedTypes');
const {
buildGeneratedTypes,
watchGeneratedTypes,
} = require('./buildGeneratedTypes');
const debug = require('debug');
const {parseArgs, styleText} = require('util');

Expand All @@ -22,6 +25,7 @@ const config = {
help: {type: 'boolean'},
'skip-snapshot': {type: 'boolean'},
validate: {type: 'boolean'},
watch: {type: 'boolean'},
},
};

Expand All @@ -33,6 +37,7 @@ async function main() {
help,
'skip-snapshot': skipSnapshot,
validate,
watch,
},
/* $FlowFixMe[incompatible-type] Natural Inference rollout. See
* https://fburl.com/workplace/6291gfvu */
Expand All @@ -52,6 +57,8 @@ async function main() {
--skip-snapshot Skip API snapshot generation.
--validate Validate if the current API snapshot on disk is up to
date. Exits with an error if differences are detected.
--watch Watch for file changes and rebuild incrementally. Skips
API snapshot generation.
`);
process.exitCode = 0;
return;
Expand All @@ -69,9 +76,11 @@ async function main() {
) +
'\n',
);
await buildGeneratedTypes();
const translatedFiles = await buildGeneratedTypes();

if (!skipSnapshot) {
if (watch === true) {
watchGeneratedTypes(translatedFiles);
} else if (!skipSnapshot) {
console.log(
styleText(['bold', 'inverse'], ' Building API snapshot ') + '\n',
);
Expand Down
Loading