UNPKG

fyn

Version:

fyn is the NPM for fynpo -- a zero setup monorepo tool

1,805 lines (1,536 loc) 3.69 MB
#!/usr/bin/env node /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ /***/ "./cli/config/npm-config.js": /***/ ((__unused_webpack_module, exports, __webpack_require__) => { // defaults, types, and shorthands. // from npm /* eslint-disable */ var path = __webpack_require__("path"); var url = __webpack_require__("url"); var Stream = (__webpack_require__("stream").Stream); var semver = __webpack_require__("./node_modules/.f/_/semver/7.7.2/semver/index.js"); var stableFamily = semver.parse(process.version); var nopt = __webpack_require__("./node_modules/.f/_/nopt/5.0.0/nopt/lib/nopt.js"); var os = __webpack_require__("os"); var osenv = __webpack_require__("./node_modules/.f/_/osenv/0.1.5/osenv/osenv.js"); var hasUnicode = __webpack_require__("./node_modules/.f/_/has-unicode/2.0.1/has-unicode/index.js"); var umask = __webpack_require__("./node_modules/.f/_/umask/1.1.0/umask/index.js"); var npmlog = __webpack_require__("./node_modules/.f/_/npmlog/4.1.2/npmlog/log.js"); var _fromString = umask.fromString; // fromString with logging callback umask.fromString = function (val) { _fromString(val, function (err, result) { if (err) { npmlog.warn("invalid umask", err.message); } val = result; }); return val; }; var log; try { log = __webpack_require__("./node_modules/.f/_/npmlog/4.1.2/npmlog/log.js"); } catch (er) { var util = __webpack_require__("util"); log = { warn: function (m) { console.warn(m + " " + util.format.apply(util, [].slice.call(arguments, 1))); } }; } exports.Umask = Umask; function Umask() {} function validateUmask(data, k, val) { return umask.validate(data, k, val); } function validateSemver(data, k, val) { if (!semver.valid(val)) return false; data[k] = semver.valid(val); } function validateStream(data, k, val) { if (!(val instanceof Stream)) return false; data[k] = val; } nopt.typeDefs.semver = { type: semver, validate: validateSemver }; nopt.typeDefs.Stream = { type: Stream, validate: validateStream }; nopt.typeDefs.Umask = { type: Umask, validate: validateUmask }; nopt.invalidHandler = function (k, val, type) { log.warn("invalid config", k + "=" + JSON.stringify(val)); if (Array.isArray(type)) { if (type.indexOf(url) !== -1) type = url;else if (type.indexOf(path) !== -1) type = path; } switch (type) { case Umask: log.warn("invalid config", "Must be umask, octal number in range 0000..0777"); break; case url: log.warn("invalid config", "Must be a full url with 'http://'"); break; case path: log.warn("invalid config", "Must be a valid filesystem path"); break; case Number: log.warn("invalid config", "Must be a numeric value"); break; case Stream: log.warn("invalid config", "Must be an instance of the Stream class"); break; } }; if (!stableFamily || +stableFamily.minor % 2) stableFamily = null;else stableFamily = stableFamily.major + "." + stableFamily.minor; var defaults; var temp = osenv.tmpdir(); var home = osenv.home(); var uidOrPid = process.getuid ? process.getuid() : process.pid; if (home) process.env.HOME = home;else home = path.resolve(temp, "npm-" + uidOrPid); var cacheExtra = process.platform === "win32" ? "npm-cache" : ".npm"; var cacheRoot = process.platform === "win32" && process.env.APPDATA || home; var cache = path.resolve(cacheRoot, cacheExtra); var globalPrefix; Object.defineProperty(exports, "defaults", ({ get: function () { if (defaults) return defaults; if (process.env.PREFIX) { globalPrefix = process.env.PREFIX; } else if (process.platform === "win32") { // c:\node\node.exe --> prefix=c:\node\ globalPrefix = path.dirname(process.execPath); } else { // /usr/local/bin/node --> prefix=/usr/local globalPrefix = path.dirname(path.dirname(process.execPath)); // destdir only is respected on Unix if (process.env.DESTDIR) { globalPrefix = path.join(process.env.DESTDIR, globalPrefix); } } defaults = { access: null, "allow-same-version": false, "always-auth": false, also: null, audit: true, "audit-level": "low", "auth-type": "legacy", "bin-links": true, browser: null, ca: null, cafile: null, cache: cache, "cache-lock-stale": 60000, "cache-lock-retries": 10, "cache-lock-wait": 10000, "cache-max": Infinity, "cache-min": 10, cert: null, cidr: null, color: process.env.NO_COLOR == null, depth: Infinity, description: true, dev: false, "dry-run": false, editor: osenv.editor(), "engine-strict": false, force: false, "fetch-retries": 2, "fetch-retry-factor": 10, "fetch-retry-mintimeout": 10000, "fetch-retry-maxtimeout": 60000, git: "git", "git-tag-version": true, "commit-hooks": true, global: false, globalconfig: path.resolve(globalPrefix, "etc", "npmrc"), "global-style": false, group: process.platform === "win32" ? 0 : process.env.SUDO_GID || process.getgid && process.getgid(), "ham-it-up": false, heading: "npm", "if-present": false, "ignore-prepublish": false, "ignore-scripts": false, "init-module": path.resolve(home, ".npm-init.js"), "init-author-name": "", "init-author-email": "", "init-author-url": "", "init-version": "1.0.0", "init-license": "ISC", json: false, key: null, "legacy-bundling": false, link: false, "local-address": undefined, loglevel: "notice", // logstream: process.stderr, "logs-max": 10, long: false, maxsockets: 50, message: "%s", "metrics-registry": null, "node-options": null, "node-version": process.version, offline: false, "onload-script": false, only: null, optional: true, otp: null, "package-lock": true, "package-lock-only": false, parseable: false, "prefer-offline": false, "prefer-online": false, prefix: globalPrefix, preid: "", // production: process.env.NODE_ENV === "production", // progress: !process.env.TRAVIS && !process.env.CI, proxy: null, "https-proxy": null, noproxy: null, "user-agent": "npm/{npm-version} " + "node/{node-version} " + "{platform} " + "{arch}", "read-only": false, "rebuild-bundle": true, registry: "https://registry.npmjs.org/", rollback: true, save: true, "save-bundle": false, "save-dev": false, "save-exact": false, "save-optional": false, "save-prefix": "^", "save-prod": false, scope: "", "script-shell": null, "scripts-prepend-node-path": "warn-only", searchopts: "", searchexclude: null, searchlimit: 20, searchstaleness: 15 * 60, "send-metrics": false, shell: osenv.shell(), shrinkwrap: true, "sign-git-commit": false, "sign-git-tag": false, "sso-poll-frequency": 500, "sso-type": "oauth", "strict-ssl": true, tag: "latest", "tag-version-prefix": "v", timing: false, tmp: temp, unicode: hasUnicode(), "unsafe-perm": process.platform === "win32" || process.platform === "cygwin" || !(process.getuid && process.setuid && process.getgid && process.setgid) || process.getuid() !== 0, "update-notifier": true, usage: false, user: process.platform === "win32" ? 0 : "nobody", userconfig: path.resolve(home, ".npmrc"), umask: process.umask ? process.umask() : umask.fromString("022"), version: false, versions: false, viewer: process.platform === "win32" ? "browser" : "man", _exit: true }; return defaults; } })); exports.types = { access: [null, "restricted", "public"], "allow-same-version": Boolean, "always-auth": Boolean, also: [null, "dev", "development"], audit: Boolean, "audit-level": ["low", "moderate", "high", "critical"], "auth-type": ["legacy", "sso", "saml", "oauth"], "bin-links": Boolean, browser: [null, String], ca: [null, String, Array], cafile: path, cache: path, "cache-lock-stale": Number, "cache-lock-retries": Number, "cache-lock-wait": Number, "cache-max": Number, "cache-min": Number, cert: [null, String], cidr: [null, String, Array], color: ["always", Boolean], depth: Number, description: Boolean, dev: Boolean, "dry-run": Boolean, editor: String, "engine-strict": Boolean, force: Boolean, "fetch-retries": Number, "fetch-retry-factor": Number, "fetch-retry-mintimeout": Number, "fetch-retry-maxtimeout": Number, git: String, "git-tag-version": Boolean, "commit-hooks": Boolean, global: Boolean, globalconfig: path, "global-style": Boolean, group: [Number, String], "https-proxy": [null, url], "user-agent": String, "ham-it-up": Boolean, heading: String, "if-present": Boolean, "ignore-prepublish": Boolean, "ignore-scripts": Boolean, "init-module": path, "init-author-name": String, "init-author-email": String, "init-author-url": ["", url], "init-license": String, "init-version": semver, json: Boolean, key: [null, String], "legacy-bundling": Boolean, link: Boolean, "local-address": getLocalAddresses(), loglevel: ["silent", "error", "warn", "notice", "http", "timing", "info", "verbose", "silly"], // logstream: Stream, "logs-max": Number, long: Boolean, maxsockets: Number, message: String, "metrics-registry": [null, String], "node-options": [null, String], "node-version": [null, semver], noproxy: [null, String, Array], offline: Boolean, "onload-script": [null, String], only: [null, "dev", "development", "prod", "production"], optional: Boolean, "package-lock": Boolean, otp: [null, String], "package-lock-only": Boolean, parseable: Boolean, "prefer-offline": Boolean, "prefer-online": Boolean, prefix: path, preid: String, // production: Boolean, progress: Boolean, proxy: [null, false, url], // allow proxy to be disabled explicitly "read-only": Boolean, "rebuild-bundle": Boolean, registry: [null, url], rollback: Boolean, save: Boolean, "save-bundle": Boolean, "save-dev": Boolean, "save-exact": Boolean, "save-optional": Boolean, "save-prefix": String, "save-prod": Boolean, scope: String, "script-shell": [null, String], "scripts-prepend-node-path": [false, true, "auto", "warn-only"], searchopts: String, searchexclude: [null, String], searchlimit: Number, searchstaleness: Number, "send-metrics": Boolean, shell: String, shrinkwrap: Boolean, "sign-git-commit": Boolean, "sign-git-tag": Boolean, "sso-poll-frequency": Number, "sso-type": [null, "oauth", "saml"], "strict-ssl": Boolean, tag: String, timing: Boolean, tmp: path, unicode: Boolean, "unsafe-perm": Boolean, "update-notifier": Boolean, usage: Boolean, user: [Number, String], userconfig: path, umask: Umask, version: Boolean, "tag-version-prefix": String, versions: Boolean, viewer: String, _exit: Boolean }; function getLocalAddresses() { var interfaces; // #8094: some environments require elevated permissions to enumerate // interfaces, and synchronously throw EPERM when run without // elevated privileges try { interfaces = os.networkInterfaces(); } catch (e) { interfaces = {}; } return Object.keys(interfaces).map(nic => interfaces[nic].map(({ address }) => address)).reduce((curr, next) => curr.concat(next), []).concat(undefined); } exports.shorthands = { s: ["--loglevel", "silent"], d: ["--loglevel", "info"], dd: ["--loglevel", "verbose"], ddd: ["--loglevel", "silly"], noreg: ["--no-registry"], N: ["--no-registry"], reg: ["--registry"], "no-reg": ["--no-registry"], silent: ["--loglevel", "silent"], verbose: ["--loglevel", "verbose"], quiet: ["--loglevel", "warn"], q: ["--loglevel", "warn"], h: ["--usage"], H: ["--usage"], "?": ["--usage"], help: ["--usage"], v: ["--version"], f: ["--force"], desc: ["--description"], "no-desc": ["--no-description"], local: ["--no-global"], l: ["--long"], m: ["--message"], p: ["--parseable"], porcelain: ["--parseable"], readonly: ["--read-only"], g: ["--global"], S: ["--save"], D: ["--save-dev"], E: ["--save-exact"], O: ["--save-optional"], P: ["--save-prod"], y: ["--yes"], n: ["--no-yes"], B: ["--save-bundle"], C: ["--prefix"] }; /***/ }), /***/ "./cli/default-rc.js": /***/ ((module, __unused_webpack_exports, __webpack_require__) => { "use strict"; const ci = __webpack_require__("./node_modules/.f/_/ci-info/2.0.0/ci-info/index.js"); module.exports = { registry: "https://registry.npmjs.org", targetDir: "node_modules", progress: ci.isCI ? "none" : "normal" }; /***/ }), /***/ "./cli/fyn-cli.js": /***/ ((module, __unused_webpack_exports, __webpack_require__) => { "use strict"; // const Module = require("module"); const Fs = __webpack_require__("./lib/util/file-ops.js"); const Os = __webpack_require__("os"); const Path = __webpack_require__("path"); const Promise = __webpack_require__("./node_modules/.f/_/aveazul/1.0.2/aveazul/lib/aveazul.js"); const Fyn = __webpack_require__("./lib/fyn.js"); const _ = __webpack_require__("./node_modules/.f/_/lodash/4.17.21/lodash/lodash.min.js"); const PkgInstaller = __webpack_require__("./lib/pkg-installer.js"); // const DepData = require("../lib/dep-data"); const semver = __webpack_require__("./node_modules/.f/_/semver/7.7.2/semver/index.js"); const chalk = __webpack_require__("./node_modules/.f/_/chalk/4.1.2/chalk/source/index.js"); const logger = __webpack_require__("./lib/logger.js"); const PromiseQueue = __webpack_require__("./lib/util/promise-queue.js"); const sortObjKeys = __webpack_require__("./lib/util/sort-obj-keys.js"); const fyntil = __webpack_require__("./lib/util/fyntil.js"); const showStat = __webpack_require__("./cli/show-stat.js"); // const showSetupInfo = require("./show-setup-info"); // const logFormat = require("../lib/util/log-format"); const { runNpmScript, addNpmLifecycle } = __webpack_require__("./lib/util/run-npm-script.js"); const npmLifecycle = __webpack_require__("./node_modules/.f/_/npm-lifecycle/3.1.5/npm-lifecycle/index.js"); const npmlog = __webpack_require__("./node_modules/.f/_/npmlog/4.1.2/npmlog/log.js"); const xaa = __webpack_require__("./lib/util/xaa.js"); const { scanFileStats } = __webpack_require__("./lib/util/stat-dir.js"); const { checkPkgNewVersionEngine } = __webpack_require__("./node_modules/.f/_/check-pkg-new-version-engine/1.0.3/check-pkg-new-version-engine/dist/index.js"); const fetch = __webpack_require__("./node_modules/.f/_/node-fetch-npm/2.0.4/node-fetch-npm/src/index.js"); const myPkg = __webpack_require__("./cli/mypkg.js"); const { cleanErrorStack } = __webpack_require__("./node_modules/.f/_/@jchip/error/1.0.3/@jchip/error/dist/index.js"); const { setupNodeGypEnv } = __webpack_require__("./lib/util/setup-node-gyp.js"); const hardLinkDir = __webpack_require__("./lib/util/hard-link-dir.js"); const xsh = __webpack_require__("./node_modules/.f/_/xsh/0.4.5/xsh/lib/index.js"); function checkNewVersion(npmConfig) { checkPkgNewVersionEngine({ pkg: _.pick(myPkg, ["name", "version"]), npmConfig, checkIsNewer: (pkg, distTags, tag) => { const isNewer = semver.gt(distTags[tag], pkg.version); return { isNewer, version: distTags[tag] }; }, fetchJSON: async (url, options) => { const res = await fetch(url, options); return await res.json(); } }); } const { FETCH_META, FETCH_PACKAGE, LOAD_PACKAGE, INSTALL_PACKAGE, spinner } = __webpack_require__("./lib/log-items.js"); const myDir = Path.join(__dirname, ".."); class FynCli { constructor(config) { this._config = config; this._opts = config.opts; if (config.noStartupInfo !== true) this.showStartupInfo(); this._fyn = undefined; } get fyn() { if (!this._fyn) { this._fyn = new Fyn(this._config); } return this._fyn; } showStartupInfo() { logger.verbose(chalk.green("fyn"), "version", myPkg.version, "at", chalk.magenta(myDir)); logger.verbose(chalk.green("NodeJS"), "version", process.version, "at", chalk.magenta(process.execPath)); logger.verbose("env NODE_OPTIONS is", chalk.magenta(process.env.NODE_OPTIONS)); logger.verbose("working dir is", chalk.magenta(this._opts.cwd)); logger.verbose("Max network concurrency is", this._opts.concurrency); } async saveLogs(dbgLog) { return Fs.writeFile(Path.resolve(this._opts.cwd, dbgLog), logger.logData.join("\n") + "\n"); } async fail(msg, err) { const dbgLog = this._opts.saveLogs || Path.join(Os.tmpdir(), `fyn-debug-${process.pid}-${Date.now()}.log`); logger.freezeItems(true); logger.error(msg, `CWD ${this.fyn.cwd}`); logger.error("process.argv", process.argv); logger.error(msg, "Please check for any errors that occur above."); const lessCmd = chalk.magenta(`less -R ${dbgLog}`); logger.error(msg, `Also check ${chalk.magenta(dbgLog)} for more details. ${lessCmd} if you are on Un*x.`); if (err.stack) { logger.error(msg, cleanErrorStack(err)); } else if (err.message) { logger.error(msg, err.message); } await this.saveLogs(dbgLog); fyntil.exit(err); } add(argv) { return this.fyn._initialize().then(() => this._add(argv)); } async _add(argv) { const addSec = async (section, packages) => { if (_.isEmpty(packages)) return []; const items = await xaa.map(packages, async pkgSemver => { const xfp = Path.resolve(pkgSemver); const stat = await xaa.try(() => Fs.stat(xfp)); if (stat && stat.isDirectory()) { pkgSemver = Path.relative(process.cwd(), xfp); if (!pkgSemver.startsWith(`..${Path.sep}`)) { pkgSemver = `.${Path.sep}${pkgSemver}`; } } const posixPath = pkgSemver.replace(/\\/g, "/"); const semverPath = this.fyn.pkgSrcMgr.getSemverAsFilepath(posixPath); logger.info("found semverPath", semverPath); if (semverPath) { return { $: posixPath, name: "", semver: posixPath, semverPath, localType: "hard", section, parent: {} }; } const atX = posixPath.lastIndexOf("@"); return { $: posixPath, name: atX > 0 ? posixPath.substr(0, atX) : posixPath, semver: atX > 0 ? posixPath.substr(atX + 1) : "latest", section, parent: {} }; }); if (!_.isEmpty(items)) { logger.info(`Adding packages to ${section}:`, packages.join(", ")); } return items; }; const sections = { dependencies: "packages", devDependencies: "dev", optionalDependencies: "optional", peerDependencies: "peer" }; let items = []; for (const section in sections) { const argKey = sections[section]; items = items.concat(await addSec(section, argv[argKey])); } if (_.isEmpty(items)) { logger.error("No packages to add"); fyntil.exit(1); } logger.addItem({ name: FETCH_META, color: "green", spinner }); logger.updateItem(FETCH_META, "loading meta..."); const results = []; return new PromiseQueue({ concurrency: 10, stopOnError: true, processItem: item => { let found; return xaa.wrap(() => this._fyn._pkgSrcMgr.fetchLocalItem(item)).then(meta => meta || this.fyn.pkgSrcMgr.fetchMeta(item)).then(meta => { if (!meta) { logger.error("Unable to retrieve meta for package", item.name); return; } // logger.info("adding", x.name, x.semver, meta); // look at dist tags const tags = meta["dist-tags"]; if (meta.local) { logger.info("adding local package at", item.fullPath); item.name = meta.name; item.version = _.get(meta, "json.version"); found = Path.relative(this.fyn.cwd, item.fullPath).replace(/\\/g, "/"); if (found !== item.fullPath && !found.startsWith(".")) { found = `./${found}`; } } else if (tags && tags[item.semver]) { logger.debug("adding with dist tag for", item.name, item.semver, tags[item.semver]); found = `^${tags[item.semver]}`; if (!semver.validRange(found)) found = tags[item.semver]; } else { // search const versions = Object.keys(meta.versions).filter(v => semver.satisfies(v, item.semver)); if (versions.length > 0) { found = item.semver; } else { logger.error(chalk.red(`no matching version found for ${item.$}`)); } } if (found) { logger.info(`found ${found} for ${item.$}`); item.found = found; results.push(item); } }); }, watchTime: 5000 }).addItems(items).resume().wait().then(async () => { logger.removeItem(FETCH_META); if (results.length === 0) { logger.info("No packages found for add"); return false; } const added = _.mapValues(sections, () => []); const pkg = this.fyn._pkg; const pkgFyn = argv.pkgFyn ? (await this.fyn.loadPkgFyn()) || {} : pkg; results.forEach(item => { if (item.semverPath) { // set in package-fyn if (!this._fyn.isFynpo || !this._fyn._fynpo.graph.getPackageByName(item.name)) { _.set(pkgFyn, ["fyn", item.section, item.name], item.found); } // set in package if it's not there if (!_.get(pkg, [item.section, item.name])) { _.set(pkg, [item.section, item.name], item.version ? `^${item.version}` : item.found); } } else { _.set(pkg, [item.section, item.name], item.found); } added[item.section].push(item.name); }); Object.keys(sections).forEach(sec => { if (added[sec].length > 0 && pkg[sec]) { pkg[sec] = sortObjKeys(pkg[sec]); if (_.get(pkgFyn, ["fyn", sec])) { pkgFyn.fyn[sec] = sortObjKeys(pkgFyn.fyn[sec]); } logger.info(`Packages added to ${sec}:`, added[sec].join(", ")); } }); await this.fyn.savePkg(); if (argv.pkgFyn) { await this.fyn.savePkgFyn(pkgFyn); } return true; }); } async remove(argv) { await this.fyn._initialize(); return this._remove(argv); } _remove(argv) { if (_.isEmpty(argv.packages)) { logger.error("No packages to remove"); fyntil.exit(1); } const sections = ["dependencies", "devDependencies", "optionalDependencies", "peerDependencies"]; const packages = argv.packages.slice(); const removed = []; const removeFromSection = sec => { const section = _.get(this.fyn._pkg, sec); const fynSection = _.get(this.fyn._pkg, ["fyn", sec], {}); if (_.isEmpty(section) && _.isEmpty(fynSection)) return; for (let i = 0; i < packages.length; i++) { const pkgName = packages[i]; let found = false; if (fynSection.hasOwnProperty(pkgName)) { delete fynSection[pkgName]; found = true; } if (section.hasOwnProperty(pkgName)) { delete section[pkgName]; found = true; } if (found) { removed.push(pkgName); packages[i] = undefined; } } if (_.isEmpty(section)) { _.unset(this.fyn._pkg, sec); } if (_.isEmpty(fynSection)) { _.unset(this.fyn._pkg, ["fyn", sec]); } }; sections.forEach(removeFromSection); const remaining = packages.filter(x => x); if (!_.isEmpty(remaining)) { logger.error("These packages don't exist in your package.json:", remaining.join(", ")); } if (_.isEmpty(this.fyn._pkg.fyn)) { _.unset(this.fyn._pkg, "fyn"); } if (removed.length > 0) { logger.info("removed packages from package.json:", removed.join(", ")); this.fyn.savePkg(); return true; } logger.error("No package was removed"); return false; } async syncLocalLinks() { await this.fyn._initializePkg(); const { localPkgLinks } = this.fyn._installConfig; if (!_.isEmpty(localPkgLinks)) { for (const vdir in localPkgLinks) { const tgtDir = Path.join(this.fyn._cwd, vdir); const srcDir = Path.join(this.fyn._cwd, localPkgLinks[vdir].srcDir); await hardLinkDir.link(srcDir, tgtDir, { sourceMaps: localPkgLinks[vdir].sourceMaps }); } logger.info(`refreshed linked files for local packages`); } else { logger.info(`There are no local packages`); } } /* * npm scripts execution order on install * 1. preinstall * 1b. install node_modules * 2. install * 3. postinstall * 4. prepare */ install() { let failure; let installLocked; const start = Date.now(); return Promise.try(() => this.fyn._initializePkg()).then(async () => { checkNewVersion(this.fyn._options); if (!this.fyn._changeProdMode && !this.fyn._options.forceInstall && this.fyn._installConfig.time) { const stats = await scanFileStats(this.fyn.cwd); const { latestMtimeMs } = stats; logger.debug("time check from install config - last install time", this.fyn._installConfig.time, "latest file time", latestMtimeMs); logger.debug("stats", JSON.stringify(stats, null, 2)); if (latestMtimeMs < this.fyn._installConfig.time && !(await this.fyn.checkLocalPkgFromInstallConfigNeedInstall()) && // if fyn-lock.yaml has been removed, then run install also this.fyn.checkFynLockExist()) { throw new Error("No Change"); } } installLocked = await this.fyn.createInstallLock(); await this.fyn.readLockFiles(); await this.fyn._startInstall(); const pkg = this.fyn._pkg; const preinstall = _.get(pkg, "scripts.preinstall"); if (preinstall) { logger.addItem({ name: INSTALL_PACKAGE, color: "green", spinner }); return runNpmScript({ appDir: this.fyn.cwd, scripts: ["preinstall"], fyn: this.fyn, depInfo: { name: pkg.name, version: pkg.version, dir: this.fyn.cwd } }).then(() => { logger.removeItem(INSTALL_PACKAGE); }); } }).then(() => { logger.addItem({ name: FETCH_META, color: "green", spinner }); logger.updateItem(FETCH_META, "resolving dependencies..."); return this.fyn.resolveDependencies(); }).then(() => { logger.removeItem(FETCH_META); logger.addItem({ name: FETCH_PACKAGE, color: "green", spinner }); logger.updateItem(FETCH_PACKAGE, "fetching packages..."); logger.addItem({ name: LOAD_PACKAGE, color: "green", spinner }); logger.updateItem(LOAD_PACKAGE, "loading packages..."); return this.fyn.fetchPackages(); }).then(() => { logger.removeItem(FETCH_PACKAGE); logger.removeItem(LOAD_PACKAGE); logger.addItem({ name: INSTALL_PACKAGE, color: "green", spinner }); logger.updateItem(INSTALL_PACKAGE, "installing packages..."); const installer = new PkgInstaller({ fyn: this.fyn }); return installer.install(); }).then(async () => { const pkg = this.fyn._pkg; const pkgScripts = pkg.scripts || {}; const npmInstallScripts = ["install", "postinstall", "prepare"]; // https://docs.npmjs.com/cli/v6/using-npm/scripts#npm-install // Intentionally skipping the deprecated prepublish const scripts = npmInstallScripts.filter(x => pkgScripts[x] !== undefined); if (scripts.length > 0) { await runNpmScript({ appDir: this.fyn.cwd, scripts, fyn: this.fyn, depInfo: { name: pkg.name, version: pkg.version, dir: this.fyn.cwd } }); } // run npm scripts from fynpo, with lifecycle scripts added const _runNpm = this.fyn._runNpm.map(s => Array.isArray(s) ? s.find(s1 => pkgScripts[s1] !== undefined) : s); const fynpoNpmScripts = addNpmLifecycle(_.without(_runNpm, ...npmInstallScripts), pkgScripts); if (fynpoNpmScripts.length > 0) { await runNpmScript({ appDir: this.fyn.cwd, scripts: fynpoNpmScripts, fyn: this.fyn, depInfo: { name: pkg.name, version: pkg.version, dir: this.fyn.cwd } }); } }).then(async () => { logger.removeItem(INSTALL_PACKAGE); const end = Date.now(); await this.fyn.saveFynpoIndirects(); logger.info(chalk.green("complete in total"), chalk.magenta(`${(end - start) / 1000}`) + "secs"); }).catch(err => { if (err.message === "No Change") { logger.info(`No changes detected since last fyn install - nothing to be done. To force install, run 'fyn install --force-install' or 'fyn install --fi'`); } else { failure = err; } }).finally(async () => { if (installLocked === true) { await this.fyn.removeInstallLock(); } if (failure) { await this.fail(chalk.red("install failed:"), failure); return failure; } if (this._opts.saveLogs) { await this.saveLogs(this._opts.saveLogs); } await this.fyn.saveInstallConfig(); fyntil.exit(0); }); } stat(argv) { return showStat(this.fyn, argv.args.packages).finally(() => { return this._opts.saveLogs && this.saveLogs(this._opts.saveLogs); }); } async runScript(pkg, script, env) { const config = x => this.fyn.allrc[x]; const options = { config: this.fyn.allrc, dir: Path.join(this.fyn.cwd, this.fyn.targetDir), failOk: false, force: config("force"), group: config("group"), log: npmlog, ignorePrepublish: config("ignore-prepublish"), ignoreScripts: config("ignore-scripts"), nodeOptions: config("node-options"), production: this.fyn.production, scriptShell: config("script-shell"), scriptsPrependNodePath: config("scripts-prepend-node-path"), unsafePerm: config("unsafe-perm"), user: config("user"), env }; return npmLifecycle(pkg, script, this.fyn.cwd, options); } async runScripts(scripts, { single } = {}) { if (!this.fyn._pkg) { await this.fyn.loadPkg(); } const pkg = Object.assign({}, this.fyn._pkg); pkg._id = `${pkg.name}@${pkg.version}`; const _scripts = [].concat(...scripts.map(s => { if (!single && !s.startsWith("pre") && !s.startsWith("post")) { return [`pre${s}`, s, `post${s}`]; } else { return s; } })); const env = npmLifecycle.initEnv(process.env, this.fyn.production); // add fynpo top dir node_modules/.bin to PATH if (this._config._fynpo.config) { xsh.envPath.addToFront(Path.join(this._config._fynpo.dir, "node_modules/.bin"), env); } setupNodeGypEnv(env); return Promise.each(_scripts, s => _.get(pkg, ["scripts", s]) && this.runScript(pkg, s, Object.assign({}, env))); } async run(argv, script = "") { if (!this._config._fynpo) { this._config._fynpo = {}; } script = script || argv.args.script; if (argv.opts.list || !script) { try { await this.fyn.loadPkg(); if (!argv.opts.list) { console.log(`Lifecycle scripts included in ${this.fyn._pkg.name}:\n`); } console.log(Object.keys(_.get(this.fyn._pkg, "scripts", {})).join("\n")); } finally { fyntil.exit(0); } } await this.fyn.loadPkg(); if (!_.get(this.fyn._pkg, ["scripts", script])) { logger.error(`Error: missing script: ${JSON.stringify(script)} - not found in package.json scripts`); fyntil.exit(1); } return this.runScripts([script]); } } module.exports = FynCli; /***/ }), /***/ "./cli/load-rc.js": /***/ ((module, __unused_webpack_exports, __webpack_require__) => { "use strict"; const os = __webpack_require__("os"); const Fs = __webpack_require__("fs"); const Path = __webpack_require__("path"); const Yaml = __webpack_require__("./node_modules/.f/_/yamljs/0.3.0/yamljs/lib/Yaml.js"); const Ini = __webpack_require__("./node_modules/.f/_/ini/2.0.0/ini/ini.js"); const _ = __webpack_require__("./node_modules/.f/_/lodash/4.17.21/lodash/lodash.min.js"); const logger = __webpack_require__("./lib/logger.js"); const assert = __webpack_require__("assert"); const defaultRc = __webpack_require__("./cli/default-rc.js"); const npmConfig = __webpack_require__("./cli/config/npm-config.js"); const fynTil = __webpack_require__("./lib/util/fyntil.js"); // replace any ${ENV} values with the appropriate environ. // copied from https://github.com/npm/config/blob/1f47a6c6ae7864b412d45c6a4a74930cf3365395/lib/env-replace.js const envExpr = /(?<!\\)(\\*)\$\{([^${}]+)\}/g; function replaceEnv(f, env) { return f.replace(envExpr, (orig, esc, name) => { const val = env[name] !== undefined ? env[name] : `$\{${name}}`; // consume the escape chars that are relevant. if (esc.length % 2) { return orig.slice((esc.length + 1) / 2); } return esc.slice(esc.length / 2) + val; }); } function replaceRcEnv(rc, env) { for (const k in rc) { if (rc[k] && rc[k].replace) { rc[k] = replaceEnv(rc[k], env); } } } function readRc(fname) { const rcFname = Path.basename(fname); try { const rcData = Fs.readFileSync(fname).toString(); let rc; try { assert(rcFname === ".fynrc" && rcData.startsWith("---")); rc = Yaml.parse(rcData); logger.debug(`Loaded ${rcFname} YAML RC`, fname, JSON.stringify(fynTil.removeAuthInfo(rc))); } catch (e) { rc = Ini.parse(rcData); logger.debug(`Loaded ${rcFname} ini RC`, fname, JSON.stringify(fynTil.removeAuthInfo(rc))); } return rc; } catch (e) { if (e.code !== "ENOENT") { logger.error(`Failed to process ${rcFname} RC file`, fname, e.message); } return {}; } } function loadRc(cwd, fynpoDir) { const npmrcData = []; if (cwd === false) { return { npmrc: {} }; } const homeDir = os.homedir(); const files = [process.env.NPM_CONFIG_GLOBALCONFIG, Path.join(process.env.PREFIX || "", "/etc/npmrc"), process.env.NPM_CONFIG_USERCONFIG, Path.join(homeDir, ".npmrc"), Path.join(homeDir, ".fynrc"), // fynpo dir fynpoDir && fynpoDir !== cwd && Path.join(fynpoDir, ".npmrc"), fynpoDir && fynpoDir !== cwd && Path.join(fynpoDir, ".fynrc"), Path.join(cwd, ".npmrc"), Path.join(cwd, ".fynrc")].filter(x => x); const data = files.map(fp => { const x = readRc(fp); if (fp.endsWith("npmrc")) { npmrcData.push(x); } return x; }); const all = _.merge.apply(_, [{}, npmConfig.defaults, defaultRc].concat(data)); const npmrc = _.merge.apply(_, [{}, npmConfig.defaults].concat(npmrcData)); replaceRcEnv(all, process.env); replaceRcEnv(npmrc, process.env); return { all, npmrc, data, npmrcData, files }; } module.exports = loadRc; /***/ }), /***/ "./cli/main.js": /***/ ((module, __unused_webpack_exports, __webpack_require__) => { "use strict"; const Path = __webpack_require__("path"); const chalk = __webpack_require__("./node_modules/.f/_/chalk/4.1.2/chalk/source/index.js"); const Promise = __webpack_require__("./node_modules/.f/_/aveazul/1.0.2/aveazul/lib/aveazul.js"); const FynCli = __webpack_require__("./cli/fyn-cli.js"); const _ = __webpack_require__("./node_modules/.f/_/lodash/4.17.21/lodash/lodash.min.js"); const CliLogger = __webpack_require__("./lib/cli-logger.js"); const logger = __webpack_require__("./lib/logger.js"); const NixClap = __webpack_require__("./node_modules/.f/_/nix-clap/1.3.13/nix-clap/lib/nix-clap.js"); const myPkg = __webpack_require__("./cli/mypkg.js"); const loadRc = __webpack_require__("./cli/load-rc.js"); const defaultRc = __webpack_require__("./cli/default-rc.js"); const fynTil = __webpack_require__("./lib/util/fyntil.js"); const { runInitPackage } = __webpack_require__("./node_modules/.f/_/init-package/1.0.0-fynlocal_h/init-package/dist/index.js"); function setLogLevel(ll) { if (ll) { const levels = Object.keys(CliLogger.Levels); const real = _.find(levels, l => l.startsWith(ll)); const x = CliLogger.Levels[real]; if (x !== undefined) { logger._logLevel = x; } else { logger.error(`Invalid log level "${ll}". Supported levels are: ${levels.join(", ")}`); fynTil.exit(1); } } } const pickEnvOptions = () => { const mapping = { NODE_ENV: { optKey: "production", checkValue: "production" } }; return Object.keys(mapping).reduce((cfg, envKey) => { if (process.env.hasOwnProperty(envKey)) { const m = mapping[envKey]; const ev = process.env[envKey]; cfg[m.optKey] = ev === m.checkValue; logger.info(`setting option ${m.optKey} to ${cfg[m.optKey]} by env ${envKey} value ${ev}`); } }, {}); }; const pickOptions = async (argv, nixClap, checkFynpo = true) => { setLogLevel(argv.opts.logLevel); chalk.enabled = argv.opts.colors; let cwd = argv.opts.cwd || process.cwd(); if (!Path.isAbsolute(cwd)) { cwd = Path.join(process.cwd(), cwd); } let fynpo = {}; if (checkFynpo) { try { fynpo = await fynTil.loadFynpo(cwd); } catch (err) { logger.error(err.stack); process.exit(1); } } const rcData = loadRc(argv.opts.rcfile && cwd, fynpo.dir); const rc = rcData.all || defaultRc; _.defaults(argv.opts, rc); nixClap.applyConfig(pickEnvOptions(), argv); argv.opts.cwd = cwd; chalk.enabled = argv.opts.colors; if (!argv.source.saveLogs.startsWith("cli")) { argv.opts.saveLogs = undefined; } nixClap.applyConfig(_.get(fynpo, "config.fyn.options", {}), argv); logger.debug("Final RC", JSON.stringify(fynTil.removeAuthInfo(argv.opts))); setLogLevel(argv.opts.logLevel); if (argv.opts.progress) logger.setItemType(argv.opts.progress); return { opts: argv.opts, rcData, _cliSource: argv.source, _fynpo: fynpo }; }; const options = { fynlocal: { type: "boolean", desc: "enable/disable fynlocal mode", default: true }, "always-fetch-dist": { type: "boolean", desc: "fetch package dist tarball during dep resolving", default: false }, "central-store": { type: "boolean", alias: ["central", "cs"], desc: "keep single copy of packages in central store", default: false }, copy: { type: "string array", alias: "cp", desc: "copy package even in central store mode" }, "log-level": { alias: "q", type: "string", desc: "One of: debug,verbose,info,warn,error,fyi,none", default: "info" }, "save-logs": { type: "string", alias: "sl", default: "fyn-debug.log", desc: "Save all logs to the specified file" }, colors: { type: "boolean", default: true, desc: "Log with colors (--no-colors turn off)" }, progress: { type: "enum", alias: "pg", requireArg: true, default: "normal", enum: /^(normal|simple|none)$/, desc: "Log progress type: normal,simple,none" }, cwd: { type: "string", requireArg: true, desc: "Change current working dir" }, "fyn-dir": { type: "string", desc: "Dir for cache etc, default {HOME}/.fyn" }, "force-cache": { alias: "f", type: "boolean", desc: "Don't check registry if cache exists." }, offline: { type: "boolean", desc: "Only lockfile or local cache. Fail if miss." }, "lock-only": { alias: "k", type: "boolean", desc: "Only resolve with lockfile. Fail if needs changes." }, "prefer-lock": { type: "boolean", desc: "Prefer resolving with lockfile." }, lockfile: { type: "boolean", alias: "lf", default: true, desc: "Support lockfile" }, "lock-time": { type: "string", desc: "Lock dependencies by time" }, "npm-lock": { type: "boolean", desc: "force on/off loading npm lock" }, "refresh-optionals": { type: "boolean", default: false, desc: "refresh all optionalDependencies" }, "refresh-meta": { type: "boolean", default: false, desc: "force refresh package meta from registry" }, "ignore-dist": { alias: "i", type: "boolean", desc: "Ignore host in tarball URL from meta dist." }, "show-deprecated": { alias: "s", type: "boolean", desc: "Force show deprecated messages" }, "deep-resolve": { alias: "dr", type: "boolean", desc: "Resolve dependency tree as deep as possible" }, "source-maps": { alias: "sm", type: "boolean", default: false, desc: "Generate pseudo source maps for local linked packages" }, production: { type: "boolean", alias: "prod", default: false, desc: "Ignore devDependencies" // allowCmd: ["add", "remove", "install"] }, rcfile: { type: "boolean", default: true, desc: "Load .fynrc and .npmrc files" }, registry: { type: "string", alias: "reg", requireArg: true, desc: "Override registry url" }, concurrency: { type: "number", alias: "cc", desc: "Max network concurrency", default: 15 }, "build-local": { type: "boolean", default: true, desc: "auto run fyn to install and build local dependency packages" }, "flatten-top": { type: "boolean", default: true, desc: "flattening hoists pkg to top level node_modules" }, layout: { type: "enum", default: "normal", // node_modules package directory layouts // normal - top level and hoist deps are all copied node_modules // detail - every packages in their own path with version detail and symlink to node_modules // TODO: simple - where top level deps are copied, but promoted packages are hoisted with symlinks enum: /^(normal|detail)$/, desc: "set node_modules packages layout - normal or detail" }, "meta-memoize": { type: "string", alias: "meta-mem", desc: "a url to a server that helps multiple fyn to share meta cache" } }; const commands = { install: { alias: "i", desc: "Install modules", async exec(argv, parsed) { const cli = new FynCli(await pickOptions(argv, parsed.nixClap)); return cli.install(); }, default: true, options: { "run-npm": { desc: "additional npm scripts to run after install", type: "string array" }, "force-install": { alias: "fi", desc: "force install even if no files changed since last install", type: "boolean" } } }, add: { alias: "a", args: "[packages..]", usage: "$0 $1 [packages..] [--dev <dev packages>]", desc: "add packages to package.json", exec: async (argv, parsed) => { const config = await pickOptions(argv, parsed.nixClap); const lockFile = config.lockfile; config.lockfile = false; const cli = new FynCli(config); const opts = Object.assign({}, argv.opts, argv.args); return cli.add(opts).then(added => { if (!added || !argv.opts.install) return; config.lockfile = lockFile; config.noStartupInfo = true; logger.info("installing..."); fynTil.resetFynpo(); return new FynCli(config).install(); }); }, options: { dev: { alias: ["d"], type: "array", desc: "List of packages to add to devDependencies" }, opt: { type: "array", desc: "List of packages to add to optionalDependencies" }, peer: { alias: ["p"], type: "array", desc: "List of packages to add to peerDependencies" }, install: { type: "boolean", default: true, desc: "Run install after added" }, "pkg-fyn": { type: "boolean", desc: "save fyn section to package-fyn.json", default: false } } }, remove: { alias: "rm", args: "<packages..>", desc: "Remove packages from package.json and install", exec: async (argv, parsed) => { const options = await pickOptions(argv, parsed.nixClap); const lockFile = options.lockfile; options.lockfile = false; const cli = new FynCli(options); const opts = Object.assign({}, argv.opts, argv.args); const removed = await cli.remove(opts); if (removed) { if (!argv.opts.install) return; options.lockfile = lockFile; options.noStartupInfo = true; fynTil.resetFynpo(); logger.info("installing..."); return await new FynCli(options).install(); } }, options: { install: { type: "boolean", default: true, desc: "Run install after removed" } } }, stat: { desc: "Show stats of installed packages", usage: "$0 $1 <package-name>[@semver] [...]", args: "<string packages..>", exec: async (argv, parsed) => { return new FynCli(await pickOptions(argv, parsed.nixClap)).stat(argv); } }, run: { desc: "Run a npm script", args: "[script]", alias: ["rum", "r"], usage: "$0 $1 <command> [-- <args>...]", exec: async (argv, parsed) => { try { const options = await pickOptions(argv, parsed.nixClap, !argv.opts.list); return await new FynCli(options).run(argv); } catch (err) { if (err.errno !== undefined) { process.exit(err.errno); } else { logger.error("fyn run caught error without errno", err); process.exit(1); } } }, options: { list: { desc: "list scripts", alias: "l", type: "boolean" } } }, init: { desc: "initialize a package.json file", usage: "$0 $1 <command> [--yes]", exec: async argv => { try { await runInitPackage(argv.opts.yes); } catch (err) { process.exit(1); } }, options: { yes: { alias: ["y"], desc: "skip prompt and use default values", type: "boolean" } } }, "sync-local": { desc: "Refresh locally linked package files", alias: "sl", async exec(argv, parsed) { try { const opts = await pickOptions(argv, parsed.nixClap, true); const cli = new FynCli(opts); return cli.syncLocalLinks(); } catch (err) { process.exit(1); } } } }; const createNixClap = handlers => { return new NixClap({ Promise, name: myPkg.name, version: myPkg.version, usage: "$0 [options] <command>", handlers }); }; const run = async (args, start, tryRun = true) => { fynTil.resetFynpo(); const handlers = { "parse-fail": parsed => { if (parsed.commands.length < 1 && parsed.error.message.includes("Unknown command")) { parsed.nixClap.skipExec(); } else { parsed.nixClap.showHelp(parsed.error); } }, "unknown-option": () => {} }; if (start === undefined && args !== undefined) { start = 0; } const parsed = await createNixClap(handlers).init(options, commands).parseAsync(args, start); if (!tryRun || !parsed.error) { return; } if (parsed.error && parsed.commands.length < 1) { const x = start === undefined ? 2 : start; const args2 = (args || process.argv).slice(); args2.splice(x, 0, "run"); await createNixClap().init(options, commands).parseAsync(args2, x); } else { parsed.nixClap.showHelp(parsed.error); } }; const fun = () => { const argv = process.argv.slice(); argv.splice(2, 0, "run"); return run(argv, 2, false); }; const nodeGyp = () => { __webpack_require__("./node_modules/.f/_/node-gyp/8.4.1/node-gyp/bin/node-gyp.js"); }; const hardLinkDir = __webpack_require__("./lib/util/hard-link-dir.js"); module.exports = { run, fun, nodeGyp, hardLinkDir }; /***/ }), /***/ "./cli/mypkg.js": /***/ ((module, __unused_webpack_exports, __webpack_require__) => { "use strict"; /* * Avoid webpack bundling the whole package.json if doing require("../package.json") */ const Fs = __webpack_require__("fs"); const Path = __webpack_require__("path"); const myPkg = JSON.parse(Fs.readFileSync(Path.join(__dirname, "../package.json"))); module.exports = myPkg; /***/ }), /***/ "./cli/show-stat.js": /***/ ((module, __unused_webpack_exports, __webpack_require__) => { "use strict"; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else