function main()

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;
}