UNPKG

neon-cli

Version:

Build and load native Rust/Neon modules.

256 lines (255 loc) 11.5 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = require("fs"); const inquirer_1 = require("inquirer"); const path_1 = __importDefault(require("path")); const handlebars_1 = __importDefault(require("handlebars")); const semver_1 = __importDefault(require("semver")); const style = __importStar(require("../style")); const validateLicense = require("validate-npm-package-license"); const validateName = require("validate-npm-package-name"); const JSON = __importStar(require("ts-typed-json")); const git_config_1 = __importDefault(require("git-config")); const { readFile, stat } = fs_1.promises; const ROOT_DIR = path_1.default.resolve(__dirname, "..", ".."); const TEMPLATES_DIR = path_1.default.resolve(ROOT_DIR, "templates"); const NEON_CLI_VERSION = JSON.asString(JSON.asObject(JSON.loadSync(path_1.default.resolve(ROOT_DIR, "package.json"))).version); function compile(filename) { return __awaiter(this, void 0, void 0, function* () { let source = yield readFile(path_1.default.resolve(TEMPLATES_DIR, filename), { encoding: "utf8", }); return handlebars_1.default.compile(source, { noEscape: true }); }); } const GITIGNORE_TEMPLATE = compile(".gitignore.hbs"); const CARGO_TEMPLATE = compile("Cargo.toml.hbs"); const NPM_TEMPLATE = compile("package.json.hbs"); const INDEXJS_TEMPLATE = compile("index.js.hbs"); const LIBRS_TEMPLATE = compile("lib.rs.hbs"); const README_TEMPLATE = compile("README.md.hbs"); const BUILDRS_TEMPLATE = compile("build.rs.hbs"); function guessAuthor() { return __awaiter(this, void 0, void 0, function* () { let author = { name: process.env.USER || process.env.USERNAME, email: undefined, }; try { let config = git_config_1.default.sync(); if (config.user.name) { author.name = config.user.name; } if (config.user.email) { author.email = config.user.email; } return author; } catch (e) { return author; } }); } function parseNeonVersion(flag) { return __awaiter(this, void 0, void 0, function* () { if (!flag) { return { type: "version", value: NEON_CLI_VERSION }; } if (semver_1.default.valid(flag)) { return { type: "version", value: flag }; } if (semver_1.default.validRange(flag)) { return { type: "range", value: flag }; } let stats = yield stat(flag); if (!stats.isDirectory()) { throw new Error("Specified path to Neon is not a directory"); } return { type: path_1.default.isAbsolute(flag) ? "absolute" : "relative", value: flag }; }); } function wizard(pwd, name, neon, features, noDefaultFeatures) { return __awaiter(this, void 0, void 0, function* () { let warning = "WARN: `neon new` is deprecated. To create a new project use `npm init neon my-project`."; let banner = "".padStart(warning.length + 4, "#"); console.warn(`${banner}\n# ${warning} #\n${banner}\n`); let its = validateName(name); if (!its.validForNewPackages) { let errors = (its.errors || []).concat(its.warnings || []); throw new Error("Sorry, " + errors.join(" and ") + "."); } // check for a scoped name let scoped = name.match(/@([^\/]+)\/(.*)/); let [, scope, local] = scoped ? scoped : [, null, name]; console.log("This utility will walk you through creating the " + style.project(name) + " Neon project."); console.log("It only covers the most common items, and tries to guess sensible defaults."); console.log(); console.log("Press ^C at any time to quit."); let root = path_1.default.resolve(pwd, local); let guess = yield guessAuthor(); let answers = yield (0, inquirer_1.prompt)([ { type: "input", name: "version", message: "version", default: "0.1.0", validate: function (input) { if (semver_1.default.valid(input)) { return true; } return "Invalid version: " + input; }, }, { type: "input", name: "description", message: "description" }, { type: "input", name: "node", message: "node entry point", default: "lib/index.js", }, { type: "input", name: "git", message: "git repository" }, { type: "input", name: "author", message: "author", default: guess.name }, { type: "input", name: "email", message: "email", default: guess.email }, { type: "input", name: "license", message: "license", default: "MIT", validate: function (input) { let its = validateLicense(input); if (its.validForNewPackages) { return true; } let errors = its.warnings || []; return "Sorry, " + errors.join(" and ") + "."; }, }, ]); answers.name = { npm: { full: name, scope: scope, local: local, }, cargo: { external: local, internal: local.replace(/-/g, "_"), }, }; answers.description = escapeQuotes(answers.description); answers.git = encodeURI(answers.git); answers.author = escapeQuotes(answers.author); let neonVersion = yield parseNeonVersion(neon); let simple = (neonVersion.type === "version" || neonVersion.type === "range") && !features && !noDefaultFeatures; let libs = { simple, noDefaultFeatures }; if (neonVersion.type === "relative") { let neon = path_1.default.relative(path_1.default.join(name, "native"), neonVersion.value); libs.paths = { neon: JSON.stringify(neon), "neon-build": JSON.stringify(path_1.default.join(neon, "crates", "neon-build")), }; } else if (neonVersion.type === "absolute") { libs.paths = { neon: JSON.stringify(neonVersion.value), "neon-build": JSON.stringify(path_1.default.resolve(neonVersion.value, "crates", "neon-build")), }; } else { libs.version = JSON.stringify(neonVersion.value); } if (features) { libs.features = features.split(/\s+/).map(JSON.stringify); } let cli = JSON.stringify(neonVersion.type === "version" ? "^" + neonVersion.value : neonVersion.type === "relative" ? "file:" + path_1.default.join(path_1.default.relative(name, neonVersion.value), "cli") : neonVersion.type === "absolute" ? "file:" + path_1.default.resolve(neonVersion.value, "cli") : neonVersion.value); let ctx = { project: answers, neon: { cli, libs }, }; let lib = path_1.default.resolve(root, path_1.default.dirname(answers.node)); let native_ = path_1.default.resolve(root, "native"); let src = path_1.default.resolve(native_, "src"); (0, fs_1.mkdirSync)(lib, { recursive: true }); (0, fs_1.mkdirSync)(src, { recursive: true }); (0, fs_1.writeFileSync)(path_1.default.resolve(root, ".gitignore"), (yield GITIGNORE_TEMPLATE)(ctx), { flag: "wx" }); (0, fs_1.writeFileSync)(path_1.default.resolve(root, "package.json"), (yield NPM_TEMPLATE)(ctx), { flag: "wx", }); (0, fs_1.writeFileSync)(path_1.default.resolve(native_, "Cargo.toml"), (yield CARGO_TEMPLATE)(ctx), { flag: "wx" }); (0, fs_1.writeFileSync)(path_1.default.resolve(root, "README.md"), (yield README_TEMPLATE)(ctx), { flag: "wx", }); (0, fs_1.writeFileSync)(path_1.default.resolve(root, answers.node), (yield INDEXJS_TEMPLATE)(ctx), { flag: "wx" }); (0, fs_1.writeFileSync)(path_1.default.resolve(src, "lib.rs"), (yield LIBRS_TEMPLATE)(ctx), { flag: "wx", }); (0, fs_1.writeFileSync)(path_1.default.resolve(native_, "build.rs"), (yield BUILDRS_TEMPLATE)(ctx), { flag: "wx" }); let relativeRoot = path_1.default.relative(pwd, root); let relativeNode = path_1.default.relative(pwd, path_1.default.resolve(root, answers.node)); let relativeRust = path_1.default.relative(pwd, path_1.default.resolve(src, "lib.rs")); console.log(); console.log("Woo-hoo! Your Neon project has been created in: " + style.path(relativeRoot)); console.log(); console.log("The main Node entry point is at: " + style.path(relativeNode)); console.log("The main Rust entry point is at: " + style.path(relativeRust)); console.log(); console.log("To build your project, just run " + style.command("npm install") + " from within the " + style.path(relativeRoot) + " directory."); console.log("Then you can test it out with " + style.command("node -e 'require(\"./\")'") + "."); console.log(); console.log("Happy hacking!"); }); } exports.default = wizard; function escapeQuotes(str) { return str.replace(/"/g, '\\"'); }