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
94 changes: 46 additions & 48 deletions gulp_scripts/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,47 @@ const { series } = require("gulp");
const getFormatter = require("./formatter");
const getWebpackBundle = require("./webpackBundle");
const getCleaner = require("./cleaner");
const ts = require("gulp-typescript");
const sourcemaps = require("gulp-sourcemaps");
const { runTypeScriptCompile } = require("./typescriptCli");
const nls = require("vscode-nls-dev");
const filter = require("gulp-filter");
const minimist = require("minimist");
const log = require("fancy-log");
const preprocess = require("gulp-preprocess");
const es = require("event-stream");

const tsProject = ts.createProject("tsconfig.json");
const knownOptions = {
string: "env",
default: { env: "production" },
};
const options = minimist(process.argv.slice(2), knownOptions);

const buildTask = gulp.series(getFormatter.lint, function runBuild(done) {
build(true, true).once("finish", () => {
done();
});
const buildTask = gulp.series(getFormatter.lint, async function runBuild() {
await build(true, true);
});

// Generates ./dist/nls.bundle.<language_id>.json from files in ./i18n/** *//<src_path>/<filename>.i18n.json
// Localized strings are read from these files at runtime.
const generateSrcLocBundle = () => {
// Transpile the TS to JS, and let vscode-nls-dev scan the files for calls to localize.
return tsProject
.src()
.pipe(sourcemaps.init())
.pipe(tsProject())
.js.pipe(nls.createMetaDataFiles())
.pipe(nls.createAdditionalLanguageFiles(defaultLanguages, "i18n"))
.pipe(nls.bundleMetaDataFiles(fullExtensionName, "dist"))
.pipe(nls.bundleLanguageFiles())
.pipe(
filter([
"**/nls.bundle.*.json",
"**/nls.metadata.header.json",
"**/nls.metadata.json",
"!src/**",
]),
)
.pipe(gulp.dest("dist"));
return runTypeScriptCompile().then(() =>
streamToPromise(
gulp
.src(["src/**/*.js"], { base: ".", allowEmpty: true })
.pipe(nls.createMetaDataFiles())
.pipe(nls.createAdditionalLanguageFiles(defaultLanguages, "i18n"))
.pipe(nls.bundleMetaDataFiles(fullExtensionName, "dist"))
.pipe(nls.bundleLanguageFiles())
.pipe(
filter([
"**/nls.bundle.*.json",
"**/nls.metadata.header.json",
"**/nls.metadata.json",
"!src/**",
]),
)
.pipe(gulp.dest("dist")),
),
);
};

const defaultLanguages = [
Expand Down Expand Up @@ -75,18 +73,16 @@ const fullExtensionName = isNightly
? "msjsdiag.vscode-react-native-preview"
: "msjsdiag.vscode-react-native";

function build(failOnError, buildNls) {
async function build(failOnError, buildNls) {
const isProd = options.env === "production";
const preprocessorContext = isProd ? { PROD: true } : { DEBUG: true };
let gotError = false;
log(`Building with preprocessor context: ${JSON.stringify(preprocessorContext)}`);
const tsResult = tsProject
.src()
.pipe(preprocess({ context: preprocessorContext })) //To set environment variables in-line
.pipe(sourcemaps.init())
.pipe(tsProject());

return tsResult.js
await runTypeScriptCompile();

const stream = gulp
.src(["src/**/*.js", "test/**/*.js"], { base: ".", allowEmpty: true })
.pipe(preprocess({ context: preprocessorContext })) //To set environment variables in-line
.pipe(buildNls ? nls.rewriteLocalizeCalls() : es.through())
.pipe(
buildNls
Expand All @@ -95,35 +91,37 @@ function build(failOnError, buildNls) {
)
.pipe(buildNls ? nls.bundleMetaDataFiles(fullExtensionName, ".") : es.through())
.pipe(buildNls ? nls.bundleLanguageFiles() : es.through())
.pipe(sourcemaps.write(".", { includeContent: false, sourceRoot: "." }))
.pipe(gulp.dest(file => file.cwd))
.once("error", () => {
gotError = true;
})
.once("finish", () => {
if (failOnError && gotError) {
process.exit(1);
}
});
.pipe(gulp.dest(file => file.cwd));

try {
await streamToPromise(stream);
} catch (error) {
if (failOnError) {
throw error;
}
}
}

// TODO: The file property should point to the generated source (this implementation adds an extra folder to the path)
// We should also make sure that we always generate urls in all the path properties (We shouldn"t have \\s. This seems to
// be an issue on Windows platforms)
function runBuild(done) {
build(true, true).once("finish", () => {
done();
});
build(true, true).then(() => done(), done);
}

function buildDev(done) {
build(true, false).once("finish", () => {
done();
});
build(true, false).then(() => done(), done);
}

const buildProd = series(getCleaner.clean, getWebpackBundle.webpackBundle, generateSrcLocBundle);

function streamToPromise(stream) {
return new Promise((resolve, reject) => {
stream.once("error", reject);
stream.once("finish", resolve);
});
}

module.exports = {
buildTask,
buildDev,
Expand Down
35 changes: 26 additions & 9 deletions gulp_scripts/formatter.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const { series } = require("gulp");
const cp = require("child_process");
const log = require("fancy-log");

const runPrettier = async fix => {
const child = cp.fork(
Expand All @@ -15,7 +16,7 @@ const runPrettier = async fix => {
"!test/smoke/.vscode-test/**",
"!src/**/*.d.ts",
"!SECURITY.md",
"!test/smoke/resources/sampleReactNativeProject/**"
"!test/smoke/resources/sampleReactNativeProject/**",
],
{
stdio: "inherit",
Expand All @@ -30,13 +31,11 @@ const runPrettier = async fix => {
};

function formatPrettier(cb) {
runPrettier(true);
cb();
runPrettier(true).then(() => cb(), cb);
}

function lintPrettier(cb) {
runPrettier(false);
cb();
runPrettier(false).then(() => cb(), cb);
}

/**
Expand All @@ -47,6 +46,13 @@ function lintPrettier(cb) {
* @param {OptionsT} options_
*/
const runEslint = async options_ => {
if (!hasTypeScriptJavaScriptApi()) {
log(
"Skipping ESLint because the installed TypeScript package does not expose the legacy JavaScript API.",
);
return;
}

/** @type {OptionsT} */
const options = Object.assign({ color: true, fix: false }, options_);

Expand All @@ -71,13 +77,11 @@ const runEslint = async options_ => {
};

function formatEslint(cb) {
runEslint({ fix: true });
cb();
runEslint({ fix: true }).then(() => cb(), cb);
}

function lintEslint(cb) {
runEslint({ fix: false });
cb();
runEslint({ fix: false }).then(() => cb(), cb);
}

const lint = series(lintPrettier, lintEslint);
Expand All @@ -92,3 +96,16 @@ module.exports = {
lintEslint,
lint: lint,
};

function hasTypeScriptJavaScriptApi() {
try {
require.resolve("typescript");
return true;
} catch (error) {
if (error && error.code === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
return false;
}

throw error;
}
}
23 changes: 23 additions & 0 deletions gulp_scripts/typescriptCli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const cp = require("child_process");
const path = require("path");

function runTypeScriptCompile() {
return new Promise((resolve, reject) => {
const child = cp.fork(
path.join(appRoot, "node_modules", "typescript", "bin", "tsc"),
["-p", "tsconfig.json"],
{
cwd: appRoot,
stdio: "inherit",
},
);

child.on("exit", code => {
code ? reject(new Error(`tsc exited with code ${code}`)) : resolve();
});
});
}

module.exports = {
runTypeScriptCompile,
};
32 changes: 19 additions & 13 deletions gulp_scripts/webpackBundle.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
const webpack = require("webpack");
const TerserPlugin = require("terser-webpack-plugin");
const path = require("path");
const gulp = require("gulp");
const preprocess = require("gulp-preprocess");
const { runTypeScriptCompile } = require("./typescriptCli");
const srcPath = "src";
const distDir = appRoot + "/dist";
const distSrcDir = `${distDir}/src`;

/** Run webpack to bundle the extension output files */
async function webpackBundle() {
await runTypeScriptCompile();
await preprocessCompiledJavaScript();

const packages = [
{
entry: `${srcPath}/extension/rn-extension.ts`,
entry: `${srcPath}/extension/rn-extension.js`,
filename: "rn-extension.js",
library: true,
},
Expand All @@ -36,12 +42,12 @@ async function runWebpack({
},
devtool: devtool,
resolve: {
extensions: [".js", ".ts", ".json"],
extensions: [".js", ".json"],
},
module: {
rules: [
{
test: /\.ts$/,
test: /\.js$/,
exclude: /node_modules/,
use: [
{
Expand All @@ -52,16 +58,6 @@ async function runWebpack({
base: path.join(appRoot),
},
},
{
// configure TypeScript loader:
// * enable sources maps for end-to-end source maps
loader: "ts-loader",
options: {
compilerOptions: {
sourceMap: true,
},
},
},
],
},
],
Expand Down Expand Up @@ -120,3 +116,13 @@ async function runWebpack({
module.exports = {
webpackBundle,
};

function preprocessCompiledJavaScript() {
return new Promise((resolve, reject) => {
gulp.src(["src/**/*.js"], { base: ".", allowEmpty: true })
.pipe(preprocess({ context: { PROD: true } }))
.pipe(gulp.dest(file => file.cwd))
.once("error", reject)
.once("finish", resolve);
});
}
Loading