in packages/create/index.js [61:240]
function main(argv, error = console.error, log = console.log) {
const args = require('minimist')(argv, {
boolean: ['typescript'],
});
if (args['help']) {
usage(error);
return 0;
}
if (!args['_'] || args['_'].length < 1) {
error('Please specify the workspace directory\n');
usage(error);
return 1;
}
// Which package manager will be used in the new project
const pkgMgr = args['packageManager'] || detectRunningUnderYarn() ? 'yarn' : 'npm';
log_verbose('Running with', process.argv);
log_verbose('Environment', process.env);
const [wkspDir] = args['_'];
// TODO: user might want these to differ
const wkspName = wkspDir;
if (!validateWorkspaceName(wkspName, error)) {
return 1;
}
log(`Creating Bazel workspace ${wkspName}...`);
fs.mkdirSync(wkspDir);
fs.mkdirSync(path.join(wkspDir, 'tools'));
function write(workspaceRelativePath, content) {
fs.writeFileSync(
path.join(wkspDir, workspaceRelativePath), content + require('os').EOL,
{encoding: 'utf-8'});
}
const devDependencies = {
'@bazel/bazelisk': 'latest',
'@bazel/ibazel': 'latest',
'@bazel/buildifier': 'latest',
};
let rootBuildContent = '# Add rules here to build your software\n' +
'# See https://docs.bazel.build/versions/main/build-ref.html#BUILD_files\n\n';
if (args['typescript']) {
devDependencies['@bazel/typescript'] = 'latest';
devDependencies['typescript'] = 'latest';
write('tsconfig.json', `\
{
// If building without sandboxing, we need to prevent TypeScript from descending into
// Bazel's external folder which contains third-party Bazel dependencies.
"exclude": ["external/*"]
}`);
rootBuildContent += '# Allow any ts_library rules in this workspace to reference the config\n' +
'# Note: if you move the tsconfig.json file to a subdirectory, you can add an alias() here instead\n' +
'# so that ts_library rules still use it by default.\n' +
'# See https://www.npmjs.com/package/@bazel/typescript#installation\n' +
'exports_files(["tsconfig.json"], visibility = ["//:__subpackages__"])\n';
}
write('BUILD.bazel', rootBuildContent);
const yarnInstallCmd =
`# The yarn_install rule runs yarn anytime the package.json or yarn.lock file changes.
# It also extracts and installs any Bazel rules distributed in an npm package.
load("@build_bazel_rules_nodejs//:index.bzl", "yarn_install")
yarn_install(
# Name this npm so that Bazel Label references look like @npm//package
name = "npm",
package_json = "//:package.json",
yarn_lock = "//:yarn.lock",
)`;
const npmInstallCmd =
`# The npm_install rule runs yarn anytime the package.json or package-lock.json file changes.
# It also extracts any Bazel rules distributed in an npm package.
load("@build_bazel_rules_nodejs//:index.bzl", "npm_install")
npm_install(
# Name this npm so that Bazel Label references look like @npm//package
name = "npm",
package_json = "//:package.json",
package_lock_json = "//:package-lock.json",
)`;
let bazelDepsContent = `# Third-party dependencies fetched by Bazel
# Unlike WORKSPACE, the content of this file is unordered.
# We keep them separate to make the WORKSPACE file more maintainable.
# Install the nodejs "bootstrap" package
# This provides the basic tools for running and packaging nodejs programs in Bazel
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
def fetch_dependencies():
http_archive(
name = "build_bazel_rules_nodejs",
sha256 = "c077680a307eb88f3e62b0b662c2e9c6315319385bc8c637a861ffdbed8ca247",
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/5.1.0/rules_nodejs-5.1.0.tar.gz"],
)`
let workspaceContent = `# Bazel workspace created by @bazel/create 0.0.0-PLACEHOLDER
# Declares that this directory is the root of a Bazel workspace.
# See https://docs.bazel.build/versions/main/build-ref.html#workspace
workspace(
# How this workspace would be referenced with absolute labels from another workspace
name = "${wkspName}",
)
load("//tools:bazel_deps.bzl", "fetch_dependencies")
fetch_dependencies()
load("@build_bazel_rules_nodejs//:repositories.bzl", "build_bazel_rules_nodejs_dependencies")
build_bazel_rules_nodejs_dependencies()
${pkgMgr === 'yarn' ? yarnInstallCmd : npmInstallCmd}`;
write('tools/BUILD.bazel', '# Currently there are no targets in this Bazel package')
write('tools/bazel_deps.bzl', bazelDepsContent);
// Don't name it WORKSPACE.bazel since there's a bug with managed_directories
write('WORKSPACE', workspaceContent);
write('.bazelignore', `\
# NB: semantics here are not the same as .gitignore
# see https://github.com/bazelbuild/bazel/issues/8106
# For example, every nested node_modules directory needs to be listed here.
node_modules
dist
bazel-out`);
write(
'package.json',
JSON.stringify(
{
name: wkspName,
version: '0.1.0',
private: true,
devDependencies,
scripts: {
'build': 'bazel build //...',
'test': 'bazel test //...',
}
},
null, 4));
write('.gitignore', `\
.bazelrc.user
dist
bazel-out
node_modules`);
// in the published distribution, this file will appear in the same folder as this file
try {
const rc = require.resolve('./common.bazelrc');
write('.bazelrc', fs.readFileSync(rc));
const version = require.resolve('./.bazelversion');
write('.bazelversion', fs.readFileSync(version));
} catch (_) {
// but running locally against sources, it's in the root of the repo two directories up
if (fs.existsSync('../../common.bazelrc')) {
write('.bazelrc', fs.readFileSync('../../common.bazelrc'));
} else {
error('ERROR: missing common.bazelrc file, continuing with no bazel settings...');
}
write('.bazelversion', 'latest');
}
log(`Successfully created new Bazel workspace at ${path.resolve(wkspDir)}`);
// TODO: we should probably run the package manager install now
log(`Next steps:
1. cd ${wkspDir}
2. ${pkgMgr} install
3. ${pkgMgr === 'yarn' ? 'yarn build' : 'npm run build'}
Note that there is nothing to build, so this trivially succeeds.
4. Add contents to the BUILD.bazel file or create a new BUILD.bazel in a subdirectory.
`);
return 0;
}