fyn 0.4.37 → 0.4.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/fyn.js +5 -5
  2. package/package.json +6 -1
package/dist/fyn.js CHANGED
@@ -137,7 +137,7 @@ eval("\n\nconst Fs = __webpack_require__(/*! ./util/file-ops */ \"./lib/util/fil
137
137
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
138
138
 
139
139
  "use strict";
140
- eval("\n/* eslint-disable no-magic-numbers, max-params, max-statements, no-empty */\n\nconst Path = __webpack_require__(/*! path */ \"path\");\n\nconst Fs = __webpack_require__(/*! ./util/file-ops */ \"./lib/util/file-ops.js\");\n\nconst ssri = __webpack_require__(/*! ssri */ \"./node_modules/ssri/index.js\");\n\nconst Tar = __webpack_require__(/*! tar */ \"./node_modules/tar/index.js\");\n\nconst Promise = __webpack_require__(/*! bluebird */ \"./node_modules/bluebird/js/release/bluebird.js\");\n\nconst {\n missPipe\n} = __webpack_require__(/*! ./util/fyntil */ \"./lib/util/fyntil.js\");\n\nconst {\n linkFile\n} = __webpack_require__(/*! ./util/hard-link-dir */ \"./lib/util/hard-link-dir.js\");\n\nconst logger = __webpack_require__(/*! ./logger */ \"./lib/logger.js\");\n\nconst {\n AggregateError\n} = __webpack_require__(/*! @jchip/error */ \"./node_modules/@jchip/error/dist/index.js\");\n/**\n * convert a directory tree structure to a flatten one like:\n * ```\n * {\n * dirs: [\n * \"/dir1\"\n * ],\n * files: [\n * \"/file1\",\n * \"/dir1/file1\"\n * ]\n * }\n * ```\n * @param {*} tree - the dir tree\n * @param {*} output - output object\n * @param {*} baseDir - base dir path\n * @returns flatten dir list\n */\n\n\nfunction flattenTree(tree, output, baseDir) {\n const dirs = Object.keys(tree);\n\n for (const dir of dirs) {\n if (dir === \"/\") continue;\n const fdir = Path.join(baseDir, dir);\n output.dirs.push(fdir);\n flattenTree(tree[dir], output, fdir);\n }\n\n const files = Object.keys(tree[\"/\"]);\n\n for (const file of files) {\n output.files.push(Path.join(baseDir, file));\n }\n\n return output;\n}\n/**\n * create and maintain the fyn central storage\n */\n\n\nclass FynCentral {\n constructor({\n centralDir = \".fyn/_central-storage\"\n }) {\n this._centralDir = Path.resolve(centralDir);\n this._map = new Map();\n }\n\n _analyze(integrity) {\n const sri = ssri.parse(integrity, {\n single: true\n });\n const algorithm = sri.algorithm;\n const hex = sri.hexDigest();\n const segLen = 2;\n const contentPath = Path.join(...[this._centralDir, algorithm].concat(hex.substr(0, segLen), hex.substr(segLen, segLen), hex.substr(segLen * 2)));\n return {\n algorithm,\n contentPath,\n hex\n };\n }\n\n async _loadTree(integrity, info, noSet) {\n if (!info) {\n if (this._map.has(integrity)) {\n info = this._map.get(integrity);\n noSet = true;\n } else {\n info = this._analyze(integrity);\n info.tree = false;\n }\n }\n\n try {\n const stat = await Fs.stat(info.contentPath);\n info.exist = true;\n\n if (stat.isDirectory()) {\n const treeFile = Path.join(info.contentPath, \"tree.json\");\n const tree = await Fs.readFile(treeFile).then(JSON.parse).catch(err => {\n throw new Error(`fyn-central: reading ${treeFile} - ${err.message}`);\n });\n info.tree = tree;\n if (!noSet) this._map.set(integrity, info);\n }\n\n return info;\n } catch (err) {\n return info;\n }\n }\n\n async has(integrity) {\n if (this._map.has(integrity)) return true;\n const info = await this._loadTree(integrity);\n return Boolean(info.tree);\n }\n\n async get(integrity) {\n return await this.getInfo(integrity).contentPath;\n }\n\n async getInfo(integrity) {\n if (this._map.has(integrity)) return this._map.get(integrity);\n const info = await this._loadTree(integrity);\n\n if (!info.tree) {\n throw new Error(`fyn-central can't get package for integrity ${integrity}`);\n }\n\n return info;\n }\n\n async replicate(integrity, destDir) {\n try {\n const info = await this.getInfo(integrity);\n const list = flattenTree(info.tree, {\n dirs: [],\n files: []\n }, \"\");\n\n for (const dir of list.dirs) {\n await Fs.$.mkdirp(Path.join(destDir, dir));\n }\n\n await Promise.map(list.files, file => linkFile(Path.join(info.contentPath, \"package\", file), Path.join(destDir, file)), {\n concurrency: 5\n });\n } catch (err) {\n const msg = `fyn-central can't replicate package at ${destDir} for integrity ${integrity}`;\n throw new AggregateError([err], msg);\n }\n }\n\n _untarStream(tarStream, targetDir) {\n const dirTree = {\n \"/\": {}\n };\n const strip = 1;\n const untarStream = Tar.x({\n strip,\n strict: true,\n C: targetDir,\n onentry: entry => {\n const parts = entry.path.split(/\\/|\\\\/);\n const isDir = entry.type === \"Directory\";\n const dirs = parts.slice(strip, isDir ? parts.length : parts.length - 1);\n const wtree = dirs.reduce((wt, dir) => {\n return wt[dir] || (wt[dir] = {\n \"/\": {}\n });\n }, dirTree);\n if (isDir) return;\n const fname = parts[parts.length - 1];\n\n if (fname) {\n const m = Math.round((entry.mtime ? entry.mtime.getTime() : Date.now()) / 1000);\n wtree[\"/\"][fname] = {\n z: entry.size,\n m,\n $: entry.header.cksumValid && entry.header.cksum\n };\n }\n }\n });\n return missPipe(tarStream, untarStream).then(() => dirTree);\n }\n\n async _acquireTmpLock(info) {\n const tmpLock = `${info.contentPath}.lock`;\n\n try {\n await Fs.$.mkdirp(Path.dirname(info.contentPath));\n await Fs.$.acquireLock(tmpLock, {\n wait: 5 * 60 * 1000,\n pollPeriod: 500,\n stale: 5 * 60 * 1000\n });\n } catch (err) {\n logger.error(\"fyn-central - unable to acquire tmp lock\", tmpLock);\n const msg = err.message && err.message.replace(tmpLock, \"<lockfile>\");\n throw new Error(`Unable to acquire fyn-central tmp lock ${tmpLock} - ${msg}`);\n }\n\n return tmpLock;\n }\n\n async _storeTarStream(info, stream) {\n const tmp = `${info.contentPath}.tmp`;\n await Fs.$.rimraf(tmp); // in case there was any remnant left from an interrupted install\n\n const targetDir = Path.join(tmp, \"package\");\n await Fs.$.mkdirp(targetDir);\n\n if (typeof stream === \"function\") {\n stream = stream();\n }\n\n if (stream.then) {\n stream = await stream;\n } // TODO: user could break during untar and cause corruptted module\n\n\n info.tree = await this._untarStream(stream, targetDir, info);\n await Fs.writeFile(Path.join(tmp, \"tree.json\"), JSON.stringify(info.tree));\n await Fs.rename(tmp, info.contentPath);\n info.exist = true;\n }\n\n async storeTarStream(pkgId, integrity, stream) {\n let tmpLock = false;\n\n try {\n let info = await this._loadTree(integrity);\n\n if (info.exist) {\n logger.debug(\"fyn-central storeTarStream: already exist\", info.contentPath);\n\n if (!info.tree) {\n logger.error(`fyn-central exist package missing tree.json`);\n }\n } else {\n tmpLock = await this._acquireTmpLock(info);\n info = await this._loadTree(integrity, info, true);\n\n if (info.exist) {\n logger.debug(\"fyn-central storeTarStream: found after lock acquired\", info.contentPath);\n\n if (!info.tree) {\n const msg = `fyn-central content exist but no tree.json ${info.contentPath}`;\n logger.error(msg);\n throw new Error(msg);\n }\n } else {\n logger.debug(\"storing tar to central store\", pkgId, integrity);\n await this._storeTarStream(info, stream);\n stream = undefined;\n\n this._map.set(integrity, info);\n\n logger.debug(\"fyn-central storeTarStream: stored\", pkgId, info.contentPath);\n }\n }\n } finally {\n if (stream && stream.destroy !== undefined) {\n stream.destroy();\n }\n\n if (tmpLock) {\n await Fs.$.releaseLock(tmpLock);\n }\n }\n }\n\n}\n\nmodule.exports = FynCentral;\n\n//# sourceURL=webpack://fyn/./lib/fyn-central.js?");
140
+ eval("\n/* eslint-disable no-magic-numbers, max-params, max-statements, no-empty */\n\nconst Path = __webpack_require__(/*! path */ \"path\");\n\nconst Fs = __webpack_require__(/*! ./util/file-ops */ \"./lib/util/file-ops.js\");\n\nconst ssri = __webpack_require__(/*! ssri */ \"./node_modules/ssri/index.js\");\n\nconst Tar = __webpack_require__(/*! tar */ \"./node_modules/tar/index.js\");\n\nconst Promise = __webpack_require__(/*! bluebird */ \"./node_modules/bluebird/js/release/bluebird.js\");\n\nconst {\n missPipe\n} = __webpack_require__(/*! ./util/fyntil */ \"./lib/util/fyntil.js\");\n\nconst {\n linkFile,\n copyFile\n} = __webpack_require__(/*! ./util/hard-link-dir */ \"./lib/util/hard-link-dir.js\");\n\nconst logger = __webpack_require__(/*! ./logger */ \"./lib/logger.js\");\n\nconst {\n AggregateError\n} = __webpack_require__(/*! @jchip/error */ \"./node_modules/@jchip/error/dist/index.js\");\n/**\n * convert a directory tree structure to a flatten one like:\n * ```\n * {\n * dirs: [\n * \"/dir1\"\n * ],\n * files: [\n * \"/file1\",\n * \"/dir1/file1\"\n * ]\n * }\n * ```\n * @param {*} tree - the dir tree\n * @param {*} output - output object\n * @param {*} baseDir - base dir path\n * @returns flatten dir list\n */\n\n\nfunction flattenTree(tree, output, baseDir) {\n const dirs = Object.keys(tree);\n\n for (const dir of dirs) {\n if (dir === \"/\") continue;\n const fdir = Path.join(baseDir, dir);\n output.dirs.push(fdir);\n flattenTree(tree[dir], output, fdir);\n }\n\n const files = Object.keys(tree[\"/\"]);\n\n for (const file of files) {\n output.files.push(Path.join(baseDir, file));\n }\n\n return output;\n}\n/**\n * create and maintain the fyn central storage\n */\n\n\nclass FynCentral {\n constructor({\n centralDir = \".fyn/_central-storage\"\n }) {\n this._centralDir = Path.resolve(centralDir);\n this._map = new Map();\n }\n\n _analyze(integrity) {\n const sri = ssri.parse(integrity, {\n single: true\n });\n const algorithm = sri.algorithm;\n const hex = sri.hexDigest();\n const segLen = 2;\n const contentPath = Path.join(...[this._centralDir, algorithm].concat(hex.substr(0, segLen), hex.substr(segLen, segLen), hex.substr(segLen * 2)));\n return {\n algorithm,\n contentPath,\n hex\n };\n }\n\n async _loadTree(integrity, info, noSet) {\n if (!info) {\n if (this._map.has(integrity)) {\n info = this._map.get(integrity);\n noSet = true;\n } else {\n info = this._analyze(integrity);\n info.tree = false;\n }\n }\n\n try {\n const stat = await Fs.stat(info.contentPath);\n info.exist = true;\n\n if (stat.isDirectory()) {\n await this.readInfoTree(info);\n if (!noSet) this._map.set(integrity, info);\n }\n\n return info;\n } catch (err) {\n return info;\n }\n }\n\n async has(integrity) {\n if (this._map.has(integrity)) return true;\n const info = await this._loadTree(integrity);\n return Boolean(info.tree);\n }\n\n async get(integrity) {\n return await this.getInfo(integrity).contentPath;\n }\n\n async getInfo(integrity) {\n if (this._map.has(integrity)) return this._map.get(integrity);\n const info = await this._loadTree(integrity);\n\n if (!info.tree) {\n throw new Error(`fyn-central can't get package for integrity ${integrity}`);\n }\n\n return info;\n }\n /**\n * Read the content dir tree from file into into\n * (backport from fyn 1.0, for which mutates is used)\n *\n * @param {*} info - info\n */\n\n\n async readInfoTree(info) {\n const treeFile = Path.join(info.contentPath, \"tree.json\");\n\n try {\n const data = await Fs.readFile(treeFile);\n const tree = JSON.parse(data);\n\n if (tree._ >= 1 && tree.$) {\n if (tree.mutates !== undefined) {\n info.mutates = tree.mutates;\n }\n\n info.tree = tree.$;\n info._ = tree._;\n } else {\n info.tree = tree;\n }\n } catch (err) {\n throw new Error(`fyn-central: reading ${treeFile} - ${err.message}`);\n }\n }\n /**\n * Save the content dir tree from info to file\n * (backport from fyn 1.0, for which mutates is used)\n *\n * @param {*} info - info\n * @param {*} path - path to save the file\n */\n\n\n async saveInfoTree(info, path) {\n const treeFile = Path.join(path || info.contentPath, \"tree.json\");\n\n if (info._ >= 1) {\n await Fs.writeFile(treeFile, JSON.stringify({\n $: info.tree,\n mutates: info.mutates,\n _: 1\n }));\n } else {\n await Fs.writeFile(treeFile, JSON.stringify(info.tree));\n }\n }\n\n async replicate(integrity, destDir) {\n try {\n const info = await this.getInfo(integrity);\n const list = flattenTree(info.tree, {\n dirs: [],\n files: []\n }, \"\");\n\n for (const dir of list.dirs) {\n await Fs.$.mkdirp(Path.join(destDir, dir));\n }\n\n await Promise.map(list.files, file => {\n const src = Path.join(info.contentPath, \"package\", file);\n const dest = Path.join(destDir, file); // copy package.json because we modify it\n // TODO: don't modify it?\n\n if (file === \"package.json\") {\n return copyFile(src, dest);\n }\n\n return linkFile(src, dest);\n }, {\n concurrency: 5\n });\n } catch (err) {\n const msg = `fyn-central can't replicate package at ${destDir} for integrity ${integrity}`;\n throw new AggregateError([err], msg);\n }\n }\n\n _untarStream(tarStream, targetDir) {\n const dirTree = {\n \"/\": {}\n };\n const strip = 1;\n const untarStream = Tar.x({\n strip,\n strict: true,\n C: targetDir,\n onentry: entry => {\n const parts = entry.path.split(/\\/|\\\\/);\n const isDir = entry.type === \"Directory\";\n const dirs = parts.slice(strip, isDir ? parts.length : parts.length - 1);\n const wtree = dirs.reduce((wt, dir) => {\n return wt[dir] || (wt[dir] = {\n \"/\": {}\n });\n }, dirTree);\n if (isDir) return;\n const fname = parts[parts.length - 1];\n\n if (fname) {\n const m = Math.round((entry.mtime ? entry.mtime.getTime() : Date.now()) / 1000);\n wtree[\"/\"][fname] = {\n z: entry.size,\n m,\n $: entry.header.cksumValid && entry.header.cksum\n };\n }\n }\n });\n return missPipe(tarStream, untarStream).then(() => dirTree);\n }\n\n async _acquireTmpLock(info) {\n const tmpLock = `${info.contentPath}.lock`;\n\n try {\n await Fs.$.mkdirp(Path.dirname(info.contentPath));\n await Fs.$.acquireLock(tmpLock, {\n wait: 5 * 60 * 1000,\n pollPeriod: 500,\n stale: 5 * 60 * 1000\n });\n } catch (err) {\n logger.error(\"fyn-central - unable to acquire tmp lock\", tmpLock);\n const msg = err.message && err.message.replace(tmpLock, \"<lockfile>\");\n throw new Error(`Unable to acquire fyn-central tmp lock ${tmpLock} - ${msg}`);\n }\n\n return tmpLock;\n }\n\n async _storeTarStream(info, stream) {\n const tmp = `${info.contentPath}.tmp`;\n await Fs.$.rimraf(tmp); // in case there was any remnant left from an interrupted install\n\n const targetDir = Path.join(tmp, \"package\");\n await Fs.$.mkdirp(targetDir);\n\n if (typeof stream === \"function\") {\n stream = stream();\n }\n\n if (stream.then) {\n stream = await stream;\n } // TODO: user could break during untar and cause corruptted module\n\n\n info.tree = await this._untarStream(stream, targetDir, info);\n await this.saveInfoTree(info, tmp);\n await Fs.rename(tmp, info.contentPath);\n info.exist = true;\n }\n\n async storeTarStream(pkgId, integrity, stream) {\n let tmpLock = false;\n\n try {\n let info = await this._loadTree(integrity);\n\n if (info.exist) {\n logger.debug(\"fyn-central storeTarStream: already exist\", info.contentPath);\n\n if (!info.tree) {\n logger.error(`fyn-central exist package missing tree.json`);\n }\n } else {\n tmpLock = await this._acquireTmpLock(info);\n info = await this._loadTree(integrity, info, true);\n\n if (info.exist) {\n logger.debug(\"fyn-central storeTarStream: found after lock acquired\", info.contentPath);\n\n if (!info.tree) {\n const msg = `fyn-central content exist but no tree.json ${info.contentPath}`;\n logger.error(msg);\n throw new Error(msg);\n }\n } else {\n logger.debug(\"storing tar to central store\", pkgId, integrity);\n await this._storeTarStream(info, stream);\n stream = undefined;\n\n this._map.set(integrity, info);\n\n logger.debug(\"fyn-central storeTarStream: stored\", pkgId, info.contentPath);\n }\n }\n } finally {\n if (stream && stream.destroy !== undefined) {\n stream.destroy();\n }\n\n if (tmpLock) {\n await Fs.$.releaseLock(tmpLock);\n }\n }\n }\n\n}\n\nmodule.exports = FynCentral;\n\n//# sourceURL=webpack://fyn/./lib/fyn-central.js?");
141
141
 
142
142
  /***/ }),
143
143
 
@@ -170,7 +170,7 @@ eval("\n\nfunction ownKeys(object, enumerableOnly) { var keys = Object.keys(obje
170
170
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
171
171
 
172
172
  "use strict";
173
- eval("\n/* eslint-disable no-magic-numbers, max-statements, no-eval, camelcase, no-param-reassign */\n//\n// execute npm scripts\n//\n\nconst Path = __webpack_require__(/*! path */ \"path\");\n\nconst optionalRequire = __webpack_require__(/*! optional-require */ \"./node_modules/optional-require/index.js\")(eval(\"require\"));\n\nconst assert = __webpack_require__(/*! assert */ \"assert\");\n\nconst xsh = __webpack_require__(/*! xsh */ \"./node_modules/xsh/lib/index.js\");\n\nconst Promise = __webpack_require__(/*! bluebird */ \"./node_modules/bluebird/js/release/bluebird.js\");\n\nconst chalk = __webpack_require__(/*! chalk */ \"./node_modules/chalk/source/index.js\");\n\nconst _ = __webpack_require__(/*! lodash */ \"./node_modules/.f/_/lodash/4.17.21/lodash/lodash.min.js\");\n\nconst logger = __webpack_require__(/*! ./logger */ \"./lib/logger.js\");\n\nconst logFormat = __webpack_require__(/*! ./util/log-format */ \"./lib/util/log-format.js\");\n\nconst VisualExec = __webpack_require__(/*! visual-exec */ \"./node_modules/visual-exec/lib/visual-exec.js\");\n\nconst fyntil = __webpack_require__(/*! ./util/fyntil */ \"./lib/util/fyntil.js\");\n\nconst requireAt = __webpack_require__(/*! require-at */ \"./node_modules/require-at/require-at.js\");\n\nconst npmConfigEnv = __webpack_require__(/*! ./util/npm-config-env */ \"./lib/util/npm-config-env.js\");\n\nconst readPkgJson = dir => {\n return fyntil.readPkgJson(dir).catch(() => {\n return {};\n });\n};\n\nxsh.Promise = Promise; // When released, all code are bundled into dist/fyn.js\n// When running from original source, this is under lib/lifecycle-scripts.js\n// It's important to maintain same level so \"../package.json\" works.\n\nconst fynInstalledDir = Path.dirname(optionalRequire.resolve(\"../package.json\"));\nconst fynCli = requireAt(fynInstalledDir).resolve(\"./bin/fyn.js\");\n/*\n * ref: https://github.com/npm/npm/blob/75b462c19ea16ef0d7f943f94ff4d255695a5c0d/lib/utils/lifecycle.js\n * docs: https://docs.npmjs.com/misc/scripts\n *\n */\n\nconst ONE_MB = 1024 * 1024;\n\nconst getGlobalNodeModules = () => {\n const nodeDir = Path.dirname(process.execPath);\n\n if (process.platform === \"win32\") {\n // windows put node binary under <installed_dir>/node.exe\n // and node_modules under <installed_dir>/node_modules\n return Path.join(nodeDir, \"node_modules\");\n } else {\n // node install on unix put node binary under <installed_dir>/bin/node\n // and node_modules under <installed_dir>/lib/node_modules\n return Path.join(Path.dirname(nodeDir), \"lib/node_modules\");\n }\n};\n\nclass LifecycleScripts {\n constructor(options) {\n if (typeof options === \"string\") {\n options = {\n dir: options\n };\n }\n\n this._fyn = options._fyn || {};\n this._pkgDir = options.dir;\n this._options = Object.assign({}, options);\n }\n\n _getNpm6NodeGyp({\n version,\n npmDir,\n xrequire\n }) {\n try {\n const npmLifecycleDir = Path.dirname(xrequire.resolve(\"npm-lifecycle/package.json\"));\n return {\n envFile: xrequire.resolve(\"node-gyp/bin/node-gyp\"),\n envPath: Path.join(npmLifecycleDir, \"node-gyp-bin\")\n };\n } catch (err) {\n logger.debug(`failed to resolve node-gyp dir from npm ${version}, using defaults.`, err);\n return {\n envFile: Path.join(npmDir, \"node_modules/node-gyp/bin/node-gyp.js\"),\n envPath: Path.join(npmDir, \"node_modules/npm-lifecycle/node-gyp-bin\")\n };\n }\n }\n\n _getNpm7NodeGyp({\n version,\n npmDir,\n xrequire\n }) {\n try {\n // npm 7 has node-gyp as dep directly\n // node-gyp-bin is under npm/bin\n return {\n envFile: xrequire.resolve(\"node-gyp/bin/node-gyp\"),\n envPath: Path.join(npmDir, \"bin\")\n };\n } catch (err) {\n logger.debug(`failed to resolve node-gyp dir from npm ${version}, using defaults.`, err);\n return {\n envFile: Path.join(npmDir, \"node_modules\", \"node-gyp\", \"bin\", \"node-gyp.js\"),\n envPath: Path.join(npmDir, \"bin\")\n };\n }\n }\n\n _findNodeGypFromNpm(env) {\n const npmDir = Path.join(getGlobalNodeModules(), \"npm\");\n const xrequire = requireAt(npmDir);\n const npmPkg = xrequire(\"./package.json\");\n const version = parseInt(npmPkg.version.split(\".\")[0]);\n\n if (version > 7) {\n logger.error(`Unknown npm version ${version} - can't provide node-gyp binary`);\n return;\n }\n\n const {\n envFile,\n envPath\n } = version <= 6 ? this._getNpm6NodeGyp({\n version: npmPkg.version,\n npmDir,\n xrequire\n }) : this._getNpm7NodeGyp({\n version: npmPkg.version,\n npmDir,\n xrequire\n });\n env.npm_config_node_gyp = envFile;\n xsh.envPath.addToFront(envPath, env);\n logger.debug(`env npm_config_node_gyp set to ${env.npm_config_node_gyp}, path ${envPath} added`);\n }\n\n makeEnv(override) {\n // let env = Object.assign({}, process.env, override);\n // this._addNpmPackageConfig(this._appPkg.config, env);\n // this._addNpmPackageConfig(this._pkg.config, env);\n const env = Object.assign({}, npmConfigEnv(this._pkg, this._fyn.allrc || {}), override);\n\n this._findNodeGypFromNpm(env);\n\n if (this._appDir) {\n xsh.envPath.addToFront(Path.join(this._appDir, \"node_modules/.bin\"), env);\n }\n\n xsh.envPath.addToFront(Path.join(this._pkgDir, \"node_modules/.bin\"), env); // env.npm_lifecycle_event = stage; // TODO\n\n env.npm_node_execpath = env.NODE = env.NODE || process.execPath;\n env.npm_execpath = fynCli;\n env.INIT_CWD = this._fyn.cwd;\n return env;\n }\n\n execute(aliases, silent) {\n return Promise.try(() => this._execute(aliases, silent));\n }\n\n async _initialize() {\n const options = this._options;\n\n if (options.appDir && options.appDir !== options.dir) {\n this._appDir = options.appDir;\n this._appPkg = await readPkgJson(this._appDir);\n } else {\n this._appPkg = {};\n }\n\n this._pkg = options.json || (await readPkgJson(this._pkgDir));\n assert(this._pkg, `Unable to load package.json from ${this._pkgDir}`);\n\n if (!this._pkg.scripts) {\n this._pkg.scripts = {};\n }\n }\n\n async _execute(aliases, silent) {\n if (!this._pkg) {\n await this._initialize();\n }\n\n if (typeof aliases === \"string\") aliases = [aliases];\n\n const name = _.keys(this._pkg.scripts).find(x => aliases.indexOf(x) >= 0);\n\n if (!name || !this._pkg.scripts.hasOwnProperty(name)) {\n return false;\n }\n\n assert(this._pkg.scripts[name], `No npm script ${name} found in package.json in ${this._pkgDir}.`);\n const pkgName = logFormat.pkgId(this._pkg);\n const dimPkgName = chalk.dim(pkgName);\n const scriptName = chalk.magenta(name);\n const script = `\"${chalk.cyan(this._pkg.scripts[name])}\"`;\n const pkgDir = logFormat.pkgPath(this._pkg.name, this._pkgDir);\n logger.verbose(`executing npm script ${scriptName} of ${dimPkgName} '${script}' ${pkgDir}`);\n const child = xsh.exec({\n silent,\n cwd: this._pkgDir,\n env: this.makeEnv({\n PWD: this._pkgDir\n }),\n maxBuffer: ONE_MB\n }, this._pkg.scripts[name]);\n if (!silent) return child.promise;\n const ve = new VisualExec({\n command: this._pkg.scripts[name],\n cwd: this._pkgDir,\n visualLogger: logger,\n displayTitle: `Running ${scriptName} of ${pkgName}`,\n logLabel: `${pkgName} npm script ${scriptName}`,\n outputLabel: `${dimPkgName} npm script ${scriptName}`\n });\n return ve.show(child);\n }\n\n}\n\nmodule.exports = LifecycleScripts;\n\n//# sourceURL=webpack://fyn/./lib/lifecycle-scripts.js?");
173
+ eval("\n/* eslint-disable no-magic-numbers, max-statements, no-eval, camelcase, no-param-reassign */\n//\n// execute npm scripts\n//\n\nconst Path = __webpack_require__(/*! path */ \"path\");\n\nconst optionalRequire = __webpack_require__(/*! optional-require */ \"./node_modules/optional-require/index.js\")(eval(\"require\"));\n\nconst assert = __webpack_require__(/*! assert */ \"assert\");\n\nconst xsh = __webpack_require__(/*! xsh */ \"./node_modules/xsh/lib/index.js\");\n\nconst Promise = __webpack_require__(/*! bluebird */ \"./node_modules/bluebird/js/release/bluebird.js\");\n\nconst chalk = __webpack_require__(/*! chalk */ \"./node_modules/chalk/source/index.js\");\n\nconst _ = __webpack_require__(/*! lodash */ \"./node_modules/.f/_/lodash/4.17.21/lodash/lodash.min.js\");\n\nconst logger = __webpack_require__(/*! ./logger */ \"./lib/logger.js\");\n\nconst logFormat = __webpack_require__(/*! ./util/log-format */ \"./lib/util/log-format.js\");\n\nconst VisualExec = __webpack_require__(/*! visual-exec */ \"./node_modules/visual-exec/lib/visual-exec.js\");\n\nconst fyntil = __webpack_require__(/*! ./util/fyntil */ \"./lib/util/fyntil.js\");\n\nconst requireAt = __webpack_require__(/*! require-at */ \"./node_modules/require-at/require-at.js\");\n\nconst npmConfigEnv = __webpack_require__(/*! ./util/npm-config-env */ \"./lib/util/npm-config-env.js\");\n\nconst readPkgJson = dir => {\n return fyntil.readPkgJson(dir).catch(() => {\n return {};\n });\n};\n\nxsh.Promise = Promise; // When released, all code are bundled into dist/fyn.js\n// When running from original source, this is under lib/lifecycle-scripts.js\n// It's important to maintain same level so \"../package.json\" works.\n\nconst fynInstalledDir = Path.dirname(optionalRequire.resolve(\"../package.json\"));\nconst fynCli = requireAt(fynInstalledDir).resolve(\"./bin/fyn.js\");\n/*\n * ref: https://github.com/npm/npm/blob/75b462c19ea16ef0d7f943f94ff4d255695a5c0d/lib/utils/lifecycle.js\n * docs: https://docs.npmjs.com/misc/scripts\n *\n */\n\nconst ONE_MB = 1024 * 1024;\n\nconst getGlobalNodeModules = () => {\n const nodeDir = Path.dirname(process.execPath);\n\n if (process.platform === \"win32\") {\n // windows put node binary under <installed_dir>/node.exe\n // and node_modules under <installed_dir>/node_modules\n return Path.join(nodeDir, \"node_modules\");\n } else {\n // node install on unix put node binary under <installed_dir>/bin/node\n // and node_modules under <installed_dir>/lib/node_modules\n return Path.join(Path.dirname(nodeDir), \"lib/node_modules\");\n }\n};\n\nclass LifecycleScripts {\n constructor(options) {\n if (typeof options === \"string\") {\n options = {\n dir: options\n };\n }\n\n this._fyn = options._fyn || {};\n this._pkgDir = options.dir;\n this._options = Object.assign({}, options);\n }\n\n _getNpm6NodeGyp({\n version,\n npmDir,\n xrequire\n }) {\n try {\n const npmLifecycleDir = Path.dirname(xrequire.resolve(\"npm-lifecycle/package.json\"));\n return {\n envFile: xrequire.resolve(\"node-gyp/bin/node-gyp\"),\n envPath: Path.join(npmLifecycleDir, \"node-gyp-bin\")\n };\n } catch (err) {\n logger.debug(`failed to resolve node-gyp dir from npm ${version}, using defaults.`, err);\n return {\n envFile: Path.join(npmDir, \"node_modules/node-gyp/bin/node-gyp.js\"),\n envPath: Path.join(npmDir, \"node_modules/npm-lifecycle/node-gyp-bin\")\n };\n }\n }\n\n _getNpm7NodeGyp({\n version,\n npmDir,\n xrequire\n }) {\n try {\n // npm 7 has node-gyp as dep directly\n // node-gyp-bin is under npm/bin\n return {\n envFile: xrequire.resolve(\"node-gyp/bin/node-gyp\"),\n envPath: Path.join(npmDir, \"bin\")\n };\n } catch (err) {\n logger.debug(`failed to resolve node-gyp dir from npm ${version}, using defaults.`, err);\n return {\n envFile: Path.join(npmDir, \"node_modules\", \"node-gyp\", \"bin\", \"node-gyp.js\"),\n envPath: Path.join(npmDir, \"bin\")\n };\n }\n }\n\n _findNodeGypFromNpm(env) {\n const npmDir = Path.join(getGlobalNodeModules(), \"npm\");\n const xrequire = requireAt(npmDir);\n const npmPkg = xrequire(\"./package.json\");\n const version = parseInt(npmPkg.version.split(\".\")[0]);\n\n if (version > 8) {\n logger.error(`Unknown npm version ${version} - can't provide node-gyp binary`);\n return;\n }\n\n const {\n envFile,\n envPath\n } = version <= 6 ? this._getNpm6NodeGyp({\n version: npmPkg.version,\n npmDir,\n xrequire\n }) : this._getNpm7NodeGyp({\n version: npmPkg.version,\n npmDir,\n xrequire\n });\n env.npm_config_node_gyp = envFile;\n xsh.envPath.addToFront(envPath, env);\n logger.debug(`env npm_config_node_gyp set to ${env.npm_config_node_gyp}, path ${envPath} added`);\n }\n\n makeEnv(override) {\n // let env = Object.assign({}, process.env, override);\n // this._addNpmPackageConfig(this._appPkg.config, env);\n // this._addNpmPackageConfig(this._pkg.config, env);\n const env = Object.assign({}, npmConfigEnv(this._pkg, this._fyn.allrc || {}), override);\n\n this._findNodeGypFromNpm(env);\n\n if (this._appDir) {\n xsh.envPath.addToFront(Path.join(this._appDir, \"node_modules/.bin\"), env);\n }\n\n xsh.envPath.addToFront(Path.join(this._pkgDir, \"node_modules/.bin\"), env); // env.npm_lifecycle_event = stage; // TODO\n\n env.npm_node_execpath = env.NODE = env.NODE || process.execPath;\n env.npm_execpath = fynCli;\n env.INIT_CWD = this._fyn.cwd;\n return env;\n }\n\n execute(aliases, silent) {\n return Promise.try(() => this._execute(aliases, silent));\n }\n\n async _initialize() {\n const options = this._options;\n\n if (options.appDir && options.appDir !== options.dir) {\n this._appDir = options.appDir;\n this._appPkg = await readPkgJson(this._appDir);\n } else {\n this._appPkg = {};\n }\n\n this._pkg = options.json || (await readPkgJson(this._pkgDir));\n assert(this._pkg, `Unable to load package.json from ${this._pkgDir}`);\n\n if (!this._pkg.scripts) {\n this._pkg.scripts = {};\n }\n }\n\n async _execute(aliases, silent) {\n if (!this._pkg) {\n await this._initialize();\n }\n\n if (typeof aliases === \"string\") aliases = [aliases];\n\n const name = _.keys(this._pkg.scripts).find(x => aliases.indexOf(x) >= 0);\n\n if (!name || !this._pkg.scripts.hasOwnProperty(name)) {\n return false;\n }\n\n assert(this._pkg.scripts[name], `No npm script ${name} found in package.json in ${this._pkgDir}.`);\n const pkgName = logFormat.pkgId(this._pkg);\n const dimPkgName = chalk.dim(pkgName);\n const scriptName = chalk.magenta(name);\n const script = `\"${chalk.cyan(this._pkg.scripts[name])}\"`;\n const pkgDir = logFormat.pkgPath(this._pkg.name, this._pkgDir);\n logger.verbose(`executing npm script ${scriptName} of ${dimPkgName} '${script}' ${pkgDir}`);\n const child = xsh.exec({\n silent,\n cwd: this._pkgDir,\n env: this.makeEnv({\n PWD: this._pkgDir\n }),\n maxBuffer: ONE_MB\n }, this._pkg.scripts[name]);\n if (!silent) return child.promise;\n const ve = new VisualExec({\n command: this._pkg.scripts[name],\n cwd: this._pkgDir,\n visualLogger: logger,\n displayTitle: `Running ${scriptName} of ${pkgName}`,\n logLabel: `${pkgName} npm script ${scriptName}`,\n outputLabel: `${dimPkgName} npm script ${scriptName}`\n });\n return ve.show(child);\n }\n\n}\n\nmodule.exports = LifecycleScripts;\n\n//# sourceURL=webpack://fyn/./lib/lifecycle-scripts.js?");
174
174
 
175
175
  /***/ }),
176
176
 
@@ -302,7 +302,7 @@ eval("\n/* eslint-disable no-magic-numbers, max-params, max-statements, complexi
302
302
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
303
303
 
304
304
  "use strict";
305
- eval("\n/* eslint-disable no-magic-numbers, max-statements */\n\nconst Tar = __webpack_require__(/*! tar */ \"./node_modules/tar/index.js\");\n\nconst logger = __webpack_require__(/*! ./logger */ \"./lib/logger.js\");\n\nconst PromiseQueue = __webpack_require__(/*! ./util/promise-queue */ \"./lib/util/promise-queue.js\");\n\nconst logFormat = __webpack_require__(/*! ./util/log-format */ \"./lib/util/log-format.js\");\n\nconst {\n LOAD_PACKAGE\n} = __webpack_require__(/*! ./log-items */ \"./lib/log-items.js\");\n\nconst {\n retry,\n missPipe\n} = __webpack_require__(/*! ./util/fyntil */ \"./lib/util/fyntil.js\");\n\nclass PkgDistExtractor {\n constructor(options) {\n this._promiseQ = new PromiseQueue({\n concurrency: 4,\n // don't want to untar too many files at the same time\n stopOnError: true,\n processItem: (x, id) => this.processItem(x, id)\n });\n this._fyn = options.fyn;\n\n this._promiseQ.on(\"done\", x => this.done(x));\n\n this._promiseQ.on(\"failItem\", x => logger.error(\"dist extractor failed item\", x.error));\n }\n\n addPkgDist(data) {\n this._promiseQ.addItem(data);\n }\n\n once(evt, cb) {\n this._promiseQ.once(evt, cb);\n }\n\n wait() {\n return this._promiseQ.wait();\n }\n\n done(data) {\n logger.debug(\"done dist extracting\", data.totalTime / 1000);\n }\n\n isPending() {\n return this._promiseQ.isPending;\n } // TODO: TASK_TOP_TO_FV - remove this, no longer use.\n // async movePromotedPkgFromFV(pkg, fullOutDir) {\n // logger.debug(\n // \"moving promoted extracted package\",\n // pkg.name,\n // pkg.version,\n // \"to top level\",\n // fullOutDir\n // );\n // // first make sure top dir is clear of any other files\n // // then rename node_modules/${FV_DIR}/<version>/<pkg-name>/ to node_modules/<pkg-name>\n // if (await xaa.try(() => Fs.lstat(fullOutDir))) {\n // await Fs.$.mkdirp(this._fyn.getExtraDir());\n // await Fs.rename(fullOutDir, this._fyn.getExtraDir(`${pkg.name}-${pkg.version}`));\n // }\n // const hostingDir = Path.dirname(fullOutDir);\n // if (!(await xaa.try(() => Fs.stat(hostingDir)))) {\n // await Fs.$.mkdirp(hostingDir);\n // }\n // await Fs.rename(pkg.extracted, fullOutDir);\n // // clean empty node_modules/${FV_DIR}/<version> directory\n // await xaa.try(() => Fs.rmdir(this._fyn.getFvDir(pkg.version)));\n // }\n\n\n async processItem(data) {\n const pkg = data.pkg; // const promotedOpt = _.defaults({ promoted }, _.pick(pkg, \"promoted\"));\n\n const fullOutDir = this._fyn.getInstalledPkgDir(pkg.name, pkg.version);\n\n if (pkg.extracted && pkg.extracted === fullOutDir) {\n // do we have a copy of it in FV_DIR already?\n logger.debug(`package ${pkg.name} ${pkg.version} has already been extracted to ${pkg.extracted}`); // if (pkg.promoted && !promotedOpt.promoted) {\n // await this.movePromotedPkgFromFV(pkg, fullOutDir);\n // }\n } else {\n const json = await this._fyn.ensureProperPkgDir(pkg, fullOutDir);\n if (json) return json;\n await this._fyn.createPkgOutDir(fullOutDir);\n const result = data.result;\n let act;\n let retrieve;\n\n if (typeof result === \"string\") {\n act = \"hardlink\";\n\n retrieve = () => this._fyn.central.replicate(result, fullOutDir);\n } else {\n act = \"extract\";\n\n retrieve = () => {\n const untarStream = Tar.x({\n strip: 1,\n strict: true,\n C: fullOutDir\n });\n return missPipe(result, untarStream);\n };\n }\n\n logger.debug(`${act}ing ${pkg.name} ${pkg.version}`, \"to\", fullOutDir);\n await retrieve();\n pkg.extracted = fullOutDir;\n const msg = logFormat.pkgPath(pkg.name, fullOutDir);\n logger.updateItem(LOAD_PACKAGE, `${act}ed ${msg}`);\n } // when there're numerous fyn with central store enabled install happening,\n // somehow read pkg json of the newly linked package fails, but then the\n // file is there when inspect after. Basically wtf! anyways, throw in some\n // retry, and it does occur and then succeeds. Tested on Macbook pro High Sierra.\n\n\n let retries = 0;\n return retry(() => this._fyn.loadJsonForPkg(pkg, fullOutDir), () => {\n retries++;\n logger.warn(`retrying ${retries} reading package.json`, fullOutDir);\n return true;\n }, 5, 10).tap(pkgJson => {\n if (data.listener) {\n const listener = data.listener;\n setTimeout(() => listener.emit(\"done\", pkgJson), 0);\n }\n });\n }\n\n}\n\nmodule.exports = PkgDistExtractor;\n\n//# sourceURL=webpack://fyn/./lib/pkg-dist-extractor.js?");
305
+ eval("\n/* eslint-disable no-magic-numbers, max-statements */\n\nconst Tar = __webpack_require__(/*! tar */ \"./node_modules/tar/index.js\");\n\nconst logger = __webpack_require__(/*! ./logger */ \"./lib/logger.js\");\n\nconst PromiseQueue = __webpack_require__(/*! ./util/promise-queue */ \"./lib/util/promise-queue.js\");\n\nconst logFormat = __webpack_require__(/*! ./util/log-format */ \"./lib/util/log-format.js\");\n\nconst {\n LOAD_PACKAGE\n} = __webpack_require__(/*! ./log-items */ \"./lib/log-items.js\");\n\nconst {\n retry,\n missPipe\n} = __webpack_require__(/*! ./util/fyntil */ \"./lib/util/fyntil.js\");\n\nclass PkgDistExtractor {\n constructor(options) {\n this._promiseQ = new PromiseQueue({\n concurrency: 4,\n // don't want to untar too many files at the same time\n stopOnError: true,\n processItem: (x, id) => this.processItem(x, id)\n });\n this._fyn = options.fyn;\n\n this._promiseQ.on(\"done\", x => this.done(x));\n\n this._promiseQ.on(\"failItem\", x => logger.error(\"dist extractor failed item\", x.error));\n }\n\n addPkgDist(data) {\n this._promiseQ.addItem(data);\n }\n\n once(evt, cb) {\n this._promiseQ.once(evt, cb);\n }\n\n wait() {\n return this._promiseQ.wait();\n }\n\n done(data) {\n logger.debug(\"done dist extracting\", data.totalTime / 1000);\n }\n\n isPending() {\n return this._promiseQ.isPending;\n } // TODO: TASK_TOP_TO_FV - remove this, no longer use.\n // async movePromotedPkgFromFV(pkg, fullOutDir) {\n // logger.debug(\n // \"moving promoted extracted package\",\n // pkg.name,\n // pkg.version,\n // \"to top level\",\n // fullOutDir\n // );\n // // first make sure top dir is clear of any other files\n // // then rename node_modules/${FV_DIR}/<version>/<pkg-name>/ to node_modules/<pkg-name>\n // if (await xaa.try(() => Fs.lstat(fullOutDir))) {\n // await Fs.$.mkdirp(this._fyn.getExtraDir());\n // await Fs.rename(fullOutDir, this._fyn.getExtraDir(`${pkg.name}-${pkg.version}`));\n // }\n // const hostingDir = Path.dirname(fullOutDir);\n // if (!(await xaa.try(() => Fs.stat(hostingDir)))) {\n // await Fs.$.mkdirp(hostingDir);\n // }\n // await Fs.rename(pkg.extracted, fullOutDir);\n // // clean empty node_modules/${FV_DIR}/<version> directory\n // await xaa.try(() => Fs.rmdir(this._fyn.getFvDir(pkg.version)));\n // }\n\n\n async processItem(data) {\n const pkg = data.pkg; // const promotedOpt = _.defaults({ promoted }, _.pick(pkg, \"promoted\"));\n\n const fullOutDir = this._fyn.getInstalledPkgDir(pkg.name, pkg.version);\n\n if (pkg.extracted && pkg.extracted === fullOutDir) {\n // do we have a copy of it in FV_DIR already?\n logger.debug(`package ${pkg.name} ${pkg.version} has already been extracted to ${pkg.extracted}`); // if (pkg.promoted && !promotedOpt.promoted) {\n // await this.movePromotedPkgFromFV(pkg, fullOutDir);\n // }\n } else {\n const json = await this._fyn.ensureProperPkgDir(pkg, fullOutDir);\n if (json) return json;\n await this._fyn.createPkgOutDir(fullOutDir);\n const result = data.result;\n let act;\n let retrieve;\n\n if (typeof result === \"string\") {\n act = \"hardlink\";\n\n retrieve = () => {\n return this._fyn.central.replicate(result, fullOutDir);\n };\n } else {\n act = \"extract\";\n\n retrieve = () => {\n const untarStream = Tar.x({\n strip: 1,\n strict: true,\n C: fullOutDir\n });\n return missPipe(result, untarStream);\n };\n }\n\n logger.debug(`${act}ing ${pkg.name} ${pkg.version}`, \"to\", fullOutDir);\n await retrieve();\n pkg.extracted = fullOutDir;\n const msg = logFormat.pkgPath(pkg.name, fullOutDir);\n logger.updateItem(LOAD_PACKAGE, `${act}ed ${msg}`);\n } // when there're numerous fyn with central store enabled install happening,\n // somehow read pkg json of the newly linked package fails, but then the\n // file is there when inspect after. Basically wtf! anyways, throw in some\n // retry, and it does occur and then succeeds. Tested on Macbook pro High Sierra.\n\n\n let retries = 0;\n return retry(() => this._fyn.loadJsonForPkg(pkg, fullOutDir), () => {\n retries++;\n logger.warn(`retrying ${retries} reading package.json`, fullOutDir);\n return true;\n }, 5, 10).tap(pkgJson => {\n if (data.listener) {\n const listener = data.listener;\n setTimeout(() => listener.emit(\"done\", pkgJson), 0);\n }\n });\n }\n\n}\n\nmodule.exports = PkgDistExtractor;\n\n//# sourceURL=webpack://fyn/./lib/pkg-dist-extractor.js?");
306
306
 
307
307
  /***/ }),
308
308
 
@@ -335,7 +335,7 @@ eval("\n\nconst Path = __webpack_require__(/*! path */ \"path\");\n\nconst Promi
335
335
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
336
336
 
337
337
  "use strict";
338
- eval("\n/* eslint-disable max-nested-callbacks */\n\nconst assert = __webpack_require__(/*! assert */ \"assert\");\n\nconst xsh = __webpack_require__(/*! xsh */ \"./node_modules/xsh/lib/index.js\");\n\nconst _ = __webpack_require__(/*! lodash */ \"./node_modules/.f/_/lodash/4.17.21/lodash/lodash.min.js\");\n\nconst Promise = __webpack_require__(/*! bluebird */ \"./node_modules/bluebird/js/release/bluebird.js\");\n\nconst PromiseQueue = __webpack_require__(/*! ./util/promise-queue */ \"./lib/util/promise-queue.js\");\n\nconst logger = __webpack_require__(/*! ./logger */ \"./lib/logger.js\");\n\nconst Inflight = __webpack_require__(/*! ./util/inflight */ \"./lib/util/inflight.js\");\n\nconst LifecycleScripts = __webpack_require__(/*! ./lifecycle-scripts */ \"./lib/lifecycle-scripts.js\");\n\nconst chalk = __webpack_require__(/*! chalk */ \"./node_modules/chalk/source/index.js\");\n\nconst hardLinkDir = __webpack_require__(/*! ./util/hard-link-dir */ \"./lib/util/hard-link-dir.js\");\n\nconst longPending = __webpack_require__(/*! ./long-pending */ \"./lib/long-pending.js\");\n\nconst logFormat = __webpack_require__(/*! ./util/log-format */ \"./lib/util/log-format.js\");\n\nconst PkgDepLinker = __webpack_require__(/*! ./pkg-dep-linker */ \"./lib/pkg-dep-linker.js\");\n\nconst semverUtil = __webpack_require__(/*! ./util/semver */ \"./lib/util/semver.js\");\n\nconst {\n readPkgJson\n} = __webpack_require__(/*! ./util/fyntil */ \"./lib/util/fyntil.js\");\n\nconst {\n OPTIONAL_RESOLVER\n} = __webpack_require__(/*! ./log-items */ \"./lib/log-items.js\");\n\nxsh.Promise = Promise; //\n// resolve optional dependencies\n//\n// If a package is in optional dep, then it should be:\n//\n// - the package itself resolved to a version with its meta.\n// - queue up for deferred processing until regular dep are all resolved\n// - optional packages are fetched and extracted to FV_DIR\n// - execute its preinstall script\n// - package that failed is ignore\n// - package that passed is added back to the regular resolving pipeline\n// - all results saved for logging at the end\n// - expect final clean-up to remove any ignored packages\n//\n\nclass PkgOptResolver {\n constructor(options) {\n this._optPkgCount = 0;\n this._passedPkgs = [];\n this._checkedPkgs = {}; //\n // for remembering that we've extrated a package by name@version ID\n // to FV_DIR so we can avoid extrating it later\n //\n\n this._resolving = false;\n this._extractedPkgs = {};\n this._failedChecks = [];\n this._failedPkgs = [];\n this._depResolver = options.depResolver;\n this._inflights = new Inflight();\n this._fyn = options.fyn;\n this._depLinker = new PkgDepLinker({\n fyn: this._fyn\n });\n this.setupQ();\n }\n\n setupQ() {\n this._promiseQ = new PromiseQueue({\n concurrency: 2,\n stopOnError: false,\n watchTime: 2000,\n processItem: x => this.optCheck(x)\n });\n\n this._promiseQ.on(\"watch\", items => {\n items.watched = items.watched.filter(x => !x.item.runningScript);\n items.still = items.still.filter(x => !x.item.runningScript);\n items.total = items.watched.length + items.still.length;\n longPending.onWatch(items, {\n makeId: item => {\n item = item.item;\n return chalk.magenta(`${item.name}@${item.resolved}`);\n }\n });\n });\n\n this._promiseQ.on(\"done\", () => logger.removeItem(OPTIONAL_RESOLVER));\n\n this._promiseQ.on(\"fail\", x => logger.error(\"opt-check fail\", x));\n\n this._promiseQ.on(\"failItem\", x => logger.error(\"opt-check failItem\", x.error));\n } //\n // optDep should contain:\n // - the item for the optional dep\n // - the meta info for the whole package\n //\n\n\n add(optDep) {\n this._optPkgCount++;\n\n this._promiseQ.addItem(optDep, true);\n }\n\n start() {\n this._promiseQ._process();\n }\n\n isExtracted(name, version) {\n return this._extractedPkgs[`${name}@${version}`];\n } //\n // - check if installed under node_modules\n // - check if installed under FV_DIR\n // - if none, then fetch tarball and extract to FV_DIR\n // - run preinstall npm script\n // - check if exit 0 or not\n // - 0: add item back to resolve\n // - not: add item to queue for logging at end\n //\n\n /* eslint-disable max-statements */\n\n\n optCheck(data) {\n const name = data.item.name;\n const version = data.item.resolved;\n const pkgId = `${name}@${version}`;\n const displayId = logFormat.pkgId(data.item);\n\n const processCheckResult = promise => {\n return promise.then(res => {\n if (res.passed) {\n // exec exit status 0, add to defer resolve queue\n this._passedPkgs.push(data);\n } else {\n // exec failed, add to queue for logging at end\n this._failedPkgs.push(data);\n\n this._failedChecks.push({\n err: res.err,\n data\n });\n }\n });\n };\n\n const addChecked = res => {\n if (!this._checkedPkgs[pkgId]) {\n this._checkedPkgs[pkgId] = res;\n }\n };\n\n const logFail = msg => {\n logger.warn(chalk.yellow(`optional dep check failed`), displayId, chalk.yellow(`- ${msg}`));\n logger.info(chalk.green(` you may ignore this since it is optional but some features may be missing`));\n };\n\n const logPass = (msg, level) => {\n level = level || \"verbose\";\n logger[level](chalk.green(`optional dep check passed`), displayId, chalk.green(`- ${msg}`));\n }; // already check completed, just use existing result\n\n\n const checkedPkgRes = this._checkedPkgs[pkgId];\n\n if (checkedPkgRes) {\n return processCheckResult(Promise.resolve(checkedPkgRes));\n } // already check in progress\n\n\n const inflight = this._inflights.get(pkgId);\n\n if (inflight) {\n logger.debug(\"opt check reusing existing inflight for\", pkgId);\n return processCheckResult(inflight);\n }\n\n if (!this._fyn.refreshOptionals && _.get(data, [\"meta\", \"versions\", version, \"optFailed\"])) {\n logFail(\"by flag optFailed in lockfile\");\n const rx = {\n passed: false,\n err: new Error(\"optional dep fail by flag optFailed in lockfile\")\n };\n addChecked(rx);\n return processCheckResult(Promise.resolve(rx));\n }\n\n const checkPkg = path => {\n return readPkgJson(path, true).then(pkg => {\n return semverUtil.equal(pkg.version, version) && {\n path,\n pkg\n };\n });\n };\n\n const fvInstalledPath = this._fyn.getInstalledPkgDir(name, version);\n\n const linkLocalPackage = async () => {\n const meta = data.meta;\n\n const local = meta.local || _.get(meta, [\"versions\", version, \"local\"]);\n\n logger.debug(\"opt resolver\", name, version, \"local\", local);\n if (!local) return false;\n const dist = meta.versions[version].dist;\n logger.debug(\"opt resolver linking local package\", name, version, dist);\n\n if (local === \"sym\") {\n // await this._depLinker.symlinkLocalPackage(fvInstalledPath, dist.fullPath);\n throw new Error(\"only hard linking local mode supported now. symlinking local deprecated\");\n } else {\n await hardLinkDir.link(dist.fullPath, fvInstalledPath, {\n sourceMaps: this._fyn._options.sourceMaps\n });\n }\n\n return checkPkg(fvInstalledPath);\n }; // is it under node_modules/<name> and has the right version?\n\n\n const promise = Promise.try(() => {\n if (data.err) {\n return \"metaFail\";\n }\n\n const pkgFromMeta = data.meta.versions[version];\n const scripts = pkgFromMeta.scripts;\n\n if (pkgFromMeta.fromLocked) {\n // it's locked meta and hasPI is not 1\n if (!this._fyn.refreshOptionals && pkgFromMeta.hasPI !== 1) {\n return pkgFromMeta;\n }\n } else if (!scripts || !scripts.preinstall) {\n // full meta and doesn't have scripts or preinstall in scripts\n return pkgFromMeta;\n } // package actually has preinstall script, first check if it's already\n // installed at top level in node_modules\n\n\n const pkg = Object.assign({}, pkgFromMeta, {\n name,\n version\n });\n return this._fyn._distFetcher.findPkgInNodeModules(pkg).then(find => {\n if (find.pkgJson) {\n return {\n pkg: find.pkgJson,\n path: find.existDir\n };\n }\n\n if (this._fyn.lockOnly) {\n // regen only, don't bother fetching anything\n return \"lockOnlyFail\";\n } // no existing install found, try to link local or fetch tarball into\n // ${FV_DIR}/<version>/<name>.\n\n\n return linkLocalPackage().then(linked => {\n if (linked) return linked;\n return this._fyn._distFetcher.putPkgInNodeModules(pkg, false, true).then(() => checkPkg(fvInstalledPath)).catch(() => {\n return \"fetchFail\";\n });\n });\n });\n }) // .catch(async () => {\n // return (await linkLocalPackage()) || fetchPkgTarball(fvInstalledPath);\n // })\n .then(res => {\n if (res === \"lockOnlyFail\") {\n logFail(\"lock only but no package tarball\");\n return {\n passed: false\n };\n }\n\n if (res === \"fetchFail\") {\n logFail(\"fetch tarball failed, your install likely will be bad.\");\n return {\n passed: false\n };\n }\n\n if (res === \"metaFail\") {\n logFail(\"fetch meta failed\");\n return {\n passed: false\n };\n } // run npm script `preinstall`\n\n\n if (!this._fyn.refreshOptionals && _.get(res, \"pkg._fyn.preinstall\")) {\n // package already installed and its package.json has _fyn.preinstall set\n // so do not run preinstall script again\n logPass(\"_fyn.preinstall from package.json is true => script already passed\");\n return {\n passed: true\n };\n } else if (_.get(res, \"pkg.scripts.preinstall\")) {\n data.runningScript = true;\n logger.updateItem(OPTIONAL_RESOLVER, `running preinstall for ${displayId}`);\n const ls = new LifecycleScripts({\n appDir: this._fyn.cwd,\n _fyn: this._fyn,\n dir: res.path,\n json: res.pkg\n });\n return ls.execute([\"preinstall\"], true).then(() => {\n logPass(\"preinstall script exit with code 0\", \"info\");\n return {\n passed: true\n };\n }).catch(err => {\n logFail(\"preinstall script failed\");\n return {\n passed: false,\n err\n };\n });\n } else {\n // no preinstall script, always pass\n logPass(`package ${name} has no preinstall script`);\n return {\n passed: true\n };\n }\n }).tap(res => {\n assert(this._checkedPkgs[pkgId] === undefined, `opt-resolver already checked package ${pkgId}`);\n addChecked(res);\n }).finally(() => {\n this._inflights.remove(pkgId);\n });\n\n this._inflights.add(pkgId, promise);\n\n return processCheckResult(promise);\n }\n\n resolve() {\n this._optPkgCount = 0;\n this._resolving = true;\n this.start();\n return this._promiseQ.wait().then(async () => {\n for (const x of this._passedPkgs) {\n x.item.optChecked = true;\n await this._depResolver.addPackageResolution(x.item, x.meta, x.item.resolved);\n }\n\n for (const x of this._failedPkgs) {\n x.item.optChecked = true;\n x.item.optFailed = _.get(x, [\"meta\", \"versions\", x.item.resolved, \"optFailed\"], 1);\n await this._depResolver.addPackageResolution(x.item, x.meta, x.item.resolved);\n }\n\n this._passedPkgs = [];\n this._failedPkgs = [];\n this._resolving = false;\n\n this._depResolver.start();\n });\n }\n\n isPending() {\n return this._resolving === true;\n }\n\n isEmpty() {\n return this._optPkgCount === 0;\n }\n\n}\n\nmodule.exports = PkgOptResolver;\n\n//# sourceURL=webpack://fyn/./lib/pkg-opt-resolver.js?");
338
+ eval("\n/* eslint-disable max-nested-callbacks */\n\nconst assert = __webpack_require__(/*! assert */ \"assert\");\n\nconst xsh = __webpack_require__(/*! xsh */ \"./node_modules/xsh/lib/index.js\");\n\nconst _ = __webpack_require__(/*! lodash */ \"./node_modules/.f/_/lodash/4.17.21/lodash/lodash.min.js\");\n\nconst Promise = __webpack_require__(/*! bluebird */ \"./node_modules/bluebird/js/release/bluebird.js\");\n\nconst PromiseQueue = __webpack_require__(/*! ./util/promise-queue */ \"./lib/util/promise-queue.js\");\n\nconst logger = __webpack_require__(/*! ./logger */ \"./lib/logger.js\");\n\nconst Inflight = __webpack_require__(/*! ./util/inflight */ \"./lib/util/inflight.js\");\n\nconst LifecycleScripts = __webpack_require__(/*! ./lifecycle-scripts */ \"./lib/lifecycle-scripts.js\");\n\nconst chalk = __webpack_require__(/*! chalk */ \"./node_modules/chalk/source/index.js\");\n\nconst hardLinkDir = __webpack_require__(/*! ./util/hard-link-dir */ \"./lib/util/hard-link-dir.js\");\n\nconst longPending = __webpack_require__(/*! ./long-pending */ \"./lib/long-pending.js\");\n\nconst logFormat = __webpack_require__(/*! ./util/log-format */ \"./lib/util/log-format.js\");\n\nconst PkgDepLinker = __webpack_require__(/*! ./pkg-dep-linker */ \"./lib/pkg-dep-linker.js\");\n\nconst semverUtil = __webpack_require__(/*! ./util/semver */ \"./lib/util/semver.js\");\n\nconst {\n readPkgJson\n} = __webpack_require__(/*! ./util/fyntil */ \"./lib/util/fyntil.js\");\n\nconst {\n OPTIONAL_RESOLVER\n} = __webpack_require__(/*! ./log-items */ \"./lib/log-items.js\");\n\nxsh.Promise = Promise; //\n// resolve optional dependencies\n//\n// If a package is in optional dep, then it should be:\n//\n// - the package itself resolved to a version with its meta.\n// - queue up for deferred processing until regular dep are all resolved\n// - optional packages are fetched and extracted to FV_DIR\n// - execute its preinstall script\n// - package that failed is ignore\n// - package that passed is added back to the regular resolving pipeline\n// - all results saved for logging at the end\n// - expect final clean-up to remove any ignored packages\n//\n\nclass PkgOptResolver {\n constructor(options) {\n this._optPkgCount = 0;\n this._passedPkgs = [];\n this._checkedPkgs = {}; //\n // for remembering that we've extrated a package by name@version ID\n // to FV_DIR so we can avoid extrating it later\n //\n\n this._resolving = false;\n this._extractedPkgs = {};\n this._failedChecks = [];\n this._failedPkgs = [];\n this._depResolver = options.depResolver;\n this._inflights = new Inflight();\n this._fyn = options.fyn;\n this._depLinker = new PkgDepLinker({\n fyn: this._fyn\n });\n this.setupQ();\n }\n\n setupQ() {\n this._promiseQ = new PromiseQueue({\n concurrency: 2,\n stopOnError: false,\n watchTime: 2000,\n processItem: x => this.optCheck(x)\n });\n\n this._promiseQ.on(\"watch\", items => {\n items.watched = items.watched.filter(x => !x.item.runningScript);\n items.still = items.still.filter(x => !x.item.runningScript);\n items.total = items.watched.length + items.still.length;\n longPending.onWatch(items, {\n makeId: item => {\n item = item.item;\n return chalk.magenta(`${item.name}@${item.resolved}`);\n }\n });\n });\n\n this._promiseQ.on(\"done\", () => logger.removeItem(OPTIONAL_RESOLVER));\n\n this._promiseQ.on(\"fail\", x => logger.error(\"opt-check fail\", x));\n\n this._promiseQ.on(\"failItem\", x => logger.error(\"opt-check failItem\", x.error));\n } //\n // optDep should contain:\n // - the item for the optional dep\n // - the meta info for the whole package\n //\n\n\n add(optDep) {\n this._optPkgCount++;\n\n this._promiseQ.addItem(optDep, true);\n }\n\n start() {\n this._promiseQ._process();\n }\n\n isExtracted(name, version) {\n return this._extractedPkgs[`${name}@${version}`];\n } //\n // - check if installed under node_modules\n // - check if installed under FV_DIR\n // - if none, then fetch tarball and extract to FV_DIR\n // - run preinstall npm script\n // - check if exit 0 or not\n // - 0: add item back to resolve\n // - not: add item to queue for logging at end\n //\n\n /* eslint-disable max-statements */\n\n\n optCheck(data) {\n const name = data.item.name;\n const version = data.item.resolved;\n const pkgId = `${name}@${version}`;\n const displayId = logFormat.pkgId(data.item);\n\n const processCheckResult = promise => {\n return promise.then(res => {\n if (res.passed) {\n // exec exit status 0, add to defer resolve queue\n this._passedPkgs.push(data);\n } else {\n // exec failed, add to queue for logging at end\n this._failedPkgs.push(data);\n\n this._failedChecks.push({\n err: res.err,\n data\n });\n }\n });\n };\n\n const addChecked = res => {\n if (!this._checkedPkgs[pkgId]) {\n this._checkedPkgs[pkgId] = res;\n }\n };\n\n const logFail = msg => {\n logger.warn(chalk.yellow(`optional dep check failed`), displayId, chalk.yellow(`- ${msg}`));\n logger.info(chalk.green(` you may ignore this since it is optional but some features may be missing`));\n };\n\n const logPass = (msg, level) => {\n level = level || \"verbose\";\n logger[level](chalk.green(`optional dep check passed`), displayId, chalk.green(`- ${msg}`));\n }; // already check completed, just use existing result\n\n\n const checkedPkgRes = this._checkedPkgs[pkgId];\n\n if (checkedPkgRes) {\n return processCheckResult(Promise.resolve(checkedPkgRes));\n } // already check in progress\n\n\n const inflight = this._inflights.get(pkgId);\n\n if (inflight) {\n logger.debug(\"opt check reusing existing inflight for\", pkgId);\n return processCheckResult(inflight);\n }\n\n if (!this._fyn.refreshOptionals && _.get(data, [\"meta\", \"versions\", version, \"optFailed\"])) {\n logFail(\"by flag optFailed in lockfile\");\n const rx = {\n passed: false,\n err: new Error(\"optional dep fail by flag optFailed in lockfile\")\n };\n addChecked(rx);\n return processCheckResult(Promise.resolve(rx));\n }\n\n const checkPkg = path => {\n return readPkgJson(path, true).then(pkg => {\n return semverUtil.equal(pkg.version, version) && {\n path,\n pkg\n };\n });\n };\n\n const fvInstalledPath = this._fyn.getInstalledPkgDir(name, version);\n\n const linkLocalPackage = async () => {\n const meta = data.meta;\n\n const local = meta.local || _.get(meta, [\"versions\", version, \"local\"]);\n\n logger.debug(\"opt resolver\", name, version, \"local\", local);\n if (!local) return false;\n const dist = meta.versions[version].dist;\n logger.debug(\"opt resolver linking local package\", name, version, dist);\n\n if (local === \"sym\") {\n // await this._depLinker.symlinkLocalPackage(fvInstalledPath, dist.fullPath);\n throw new Error(\"only hard linking local mode supported now. symlinking local deprecated\");\n } else {\n await hardLinkDir.link(dist.fullPath, fvInstalledPath, {\n sourceMaps: this._fyn._options.sourceMaps\n });\n }\n\n return checkPkg(fvInstalledPath);\n }; // is it under node_modules/<name> and has the right version?\n\n\n const promise = Promise.try(() => {\n if (data.err) {\n return \"metaFail\";\n }\n\n const pkgFromMeta = data.meta.versions[version];\n const scripts = pkgFromMeta.scripts;\n\n if (pkgFromMeta.fromLocked) {\n // it's locked meta and hasPI is not 1\n if (!this._fyn.refreshOptionals && pkgFromMeta.hasPI !== 1) {\n return pkgFromMeta;\n }\n } else if (!scripts || !scripts.preinstall) {\n // full meta and doesn't have scripts or preinstall in scripts\n return pkgFromMeta;\n } // package actually has preinstall script, first check if it's already\n // installed at top level in node_modules\n\n\n const pkg = Object.assign({}, pkgFromMeta, {\n name,\n version\n });\n return this._fyn._distFetcher.findPkgInNodeModules(pkg).then(find => {\n if (find.pkgJson) {\n return {\n pkg: find.pkgJson,\n path: find.existDir\n };\n }\n\n if (this._fyn.lockOnly) {\n // regen only, don't bother fetching anything\n return \"lockOnlyFail\";\n } // no existing install found, try to link local or fetch tarball into\n // ${FV_DIR}/<version>/<name>.\n\n\n return linkLocalPackage().then(linked => {\n if (linked) return linked;\n return this._fyn._distFetcher.putPkgInNodeModules(pkg, false, true).then(() => checkPkg(fvInstalledPath)).catch(() => {\n return \"fetchFail\";\n });\n });\n });\n }) // .catch(async () => {\n // return (await linkLocalPackage()) || fetchPkgTarball(fvInstalledPath);\n // })\n .then(res => {\n if (res === \"lockOnlyFail\") {\n logFail(\"lock only but no package tarball\");\n return {\n passed: false\n };\n }\n\n if (res === \"fetchFail\") {\n logFail(\"fetch tarball failed, your install likely will be bad.\");\n return {\n passed: false\n };\n }\n\n if (res === \"metaFail\") {\n logFail(\"fetch meta failed\");\n return {\n passed: false\n };\n } // run npm script `preinstall`\n\n\n if (!this._fyn.refreshOptionals && _.get(res, \"pkg._fyn.preinstall\")) {\n // package already installed and its package.json has _fyn.preinstall set\n // so do not run preinstall script again\n logPass(`_fyn.preinstall from package.json is '${res.pkg._fyn.preinstall}' => script already passed`);\n return {\n passed: true\n };\n } else if (_.get(res, \"pkg.scripts.preinstall\")) {\n data.runningScript = true;\n logger.updateItem(OPTIONAL_RESOLVER, `running preinstall for ${displayId}`);\n const ls = new LifecycleScripts({\n appDir: this._fyn.cwd,\n _fyn: this._fyn,\n dir: res.path,\n json: res.pkg\n });\n return ls.execute([\"preinstall\"], true).then(() => {\n logPass(\"preinstall script exit with code 0\", \"info\");\n return {\n passed: true\n };\n }).catch(err => {\n logFail(\"preinstall script failed\");\n return {\n passed: false,\n err\n };\n });\n } else {\n // no preinstall script, always pass\n logPass(`package ${name} has no preinstall script`);\n return {\n passed: true\n };\n }\n }).tap(res => {\n assert(this._checkedPkgs[pkgId] === undefined, `opt-resolver already checked package ${pkgId}`);\n addChecked(res);\n }).finally(() => {\n this._inflights.remove(pkgId);\n });\n\n this._inflights.add(pkgId, promise);\n\n return processCheckResult(promise);\n }\n\n resolve() {\n this._optPkgCount = 0;\n this._resolving = true;\n this.start();\n return this._promiseQ.wait().then(async () => {\n for (const x of this._passedPkgs) {\n x.item.optChecked = true;\n await this._depResolver.addPackageResolution(x.item, x.meta, x.item.resolved);\n }\n\n for (const x of this._failedPkgs) {\n x.item.optChecked = true;\n x.item.optFailed = _.get(x, [\"meta\", \"versions\", x.item.resolved, \"optFailed\"], 1);\n await this._depResolver.addPackageResolution(x.item, x.meta, x.item.resolved);\n }\n\n this._passedPkgs = [];\n this._failedPkgs = [];\n this._resolving = false;\n\n this._depResolver.start();\n });\n }\n\n isPending() {\n return this._resolving === true;\n }\n\n isEmpty() {\n return this._optPkgCount === 0;\n }\n\n}\n\nmodule.exports = PkgOptResolver;\n\n//# sourceURL=webpack://fyn/./lib/pkg-opt-resolver.js?");
339
339
 
340
340
  /***/ }),
341
341
 
@@ -423,7 +423,7 @@ eval("\n/* eslint-disable no-process-exit, max-params */\n\n/* eslint-disable no
423
423
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
424
424
 
425
425
  "use strict";
426
- eval("\n/* eslint-disable max-params, max-statements, complexity */\n\n/*\n * clone another directory by:\n * - Creating the same directories\n * - Hard link physical files\n * - Transfer symlinks (ensure the same symlink name exist but with target adjusted)\n */\n\nconst Path = __webpack_require__(/*! path */ \"path\");\n\nconst Fs = __webpack_require__(/*! ./file-ops */ \"./lib/util/file-ops.js\");\n\nconst xaa = __webpack_require__(/*! ./xaa */ \"./lib/util/xaa.js\");\n\nconst npmPacklist = __webpack_require__(/*! npm-packlist */ \"./node_modules/npm-packlist/index.js\");\n\nconst fynTil = __webpack_require__(/*! ./fyntil */ \"./lib/util/fyntil.js\");\n\nconst logger = __webpack_require__(/*! ../logger */ \"./lib/logger.js\");\n\nconst {\n SourceMapGenerator\n} = __webpack_require__(/*! source-map */ \"./node_modules/source-map/source-map.js\");\n\nconst ci = __webpack_require__(/*! ci-info */ \"./node_modules/ci-info/index.js\");\n\nasync function linkFile(srcFp, destFp, srcStat) {\n try {\n return await Fs.link(srcFp, destFp);\n } catch (e) {\n if (e.code !== \"EEXIST\") throw e;\n\n if (srcStat === undefined) {\n srcStat = await xaa.try(() => Fs.stat(srcFp));\n }\n\n if (!srcStat) throw e;\n const destStat = await Fs.stat(destFp);\n\n if (srcStat.ino !== destStat.ino) {\n await Fs.unlink(destFp);\n return await linkFile(srcFp, destFp, null);\n }\n }\n\n return undefined;\n}\n\nasync function prepDestDir(dest) {\n const statDest = await xaa.try(() => Fs.lstat(dest));\n const destFiles = {};\n\n if (!statDest) {\n try {\n await Fs.mkdir(dest);\n } catch (e) {\n await Fs.$.mkdirp(dest);\n }\n } else if (!statDest.isDirectory()) {\n await Fs.unlink(dest);\n return prepDestDir(dest);\n } else {\n (await Fs.readdir(dest)).forEach(x => destFiles[x] = false);\n }\n\n return destFiles;\n}\n\nasync function cleanExtraDest(dest, destFiles) {\n for (const k in destFiles) {\n if (destFiles[k] === false) {\n logger.debug(`removing extra local link file ${k}`);\n await Fs.$.rimraf(Path.join(dest, k));\n }\n }\n}\n\nconst FILES = Symbol(\"files\");\n\nasync function generatePackTree(path) {\n const files = await npmPacklist({\n path\n });\n logger.debug(`local package linking - pack tree returned ${files.length} files to link`, JSON.stringify(files, null, 2));\n\n if (files.length > 1000) {\n logger.warn(`Local linking package at ${path} has more than ${files.length} files.\n >>> This is unusual, please check package .npmignore or 'files' in package.json <<<`);\n }\n\n const fmap = {\n [FILES]: []\n };\n files.sort().forEach(filePath => {\n const dir = Path.dirname(filePath);\n\n if (dir === \".\") {\n fmap[FILES].push(filePath);\n return;\n }\n\n let dmap = fmap; // npm pack list always generate file path with /\n\n dir.split(\"/\").forEach(d => {\n if (!dmap[d]) {\n dmap[d] = {\n [FILES]: []\n };\n }\n\n dmap = dmap[d];\n });\n dmap[FILES].push(Path.basename(filePath));\n });\n return fmap;\n}\n\nconst FYN_SOURCE_MAP_SIG = \"fynSourceMap=\";\nconst SOURCE_MAP_URL_SIG = \"sourceMappingURL=\";\n/**\n * search for the last sourceMappingURL from a source content\n *\n * @param {*} content\n * @returns\n */\n\nfunction getSourceMapConfig(content, sig = SOURCE_MAP_URL_SIG) {\n const regex = new RegExp( // from /(?:\\/\\/[@#][\\s]*${sig}([^\\s'\"]+)[\\s]*$)|(?:\\/\\*[@#][\\s]*${sig}([^\\s*'\"]+)[\\s]*(?:\\*\\/)[\\s]*$)/\n `(?:\\\\/\\\\/[@#][\\\\s]*${sig}([^\\\\s'\"]+)[\\\\s]*$)|(?:\\\\/\\\\*[@#][\\\\s]*${sig}([^\\\\s*'\"]+)[\\\\s]*(?:\\\\*\\\\/)[\\\\s]*$)`, \"gm\");\n let match;\n let lastMatch; // search for the last occurrence of sourceMappingURL\n\n while (match = regex.exec(content)) {\n lastMatch = match;\n }\n\n return lastMatch && lastMatch[1];\n}\n/**\n * process or generate source map back to original file\n *\n * @param {*} param0\n */\n\n\nasync function handleSourceMap({\n file,\n destFiles,\n src,\n dest,\n srcFp,\n destFp,\n sourceMaps\n}) {\n const ext = !ci.isCI && Path.extname(file); // native plain js or mjs files should map back to the original local files\n // and it may or may not have source map file\n\n if (ext !== \".js\" && ext !== \".mjs\") {\n return;\n }\n\n const checkFynMapped = x => {\n return !(x === \"false\" || x === \"no\" || x === \"off\" || x === \"0\");\n };\n\n const content = await Fs.readFile(srcFp, \"utf-8\");\n const fynMapFlag = getSourceMapConfig(content, FYN_SOURCE_MAP_SIG);\n const hasFynMapFlag = typeof fynMapFlag === \"string\";\n const sourceMapFile = getSourceMapConfig(content);\n const isFynMapped = checkFynMapped(fynMapFlag); // file contains source map URL that's not marked for fyn, try copy it and rewrite sources\n\n if (!hasFynMapFlag && sourceMapFile) {\n if (Path.isAbsolute(sourceMapFile)) {\n logger.info(`File ${srcFp} sourcemap ${sourceMapFile} is full path - can't rewrite it`);\n return;\n }\n\n const srcMapFp = Path.join(src, sourceMapFile);\n const mapContent = await xaa.try(() => Fs.readFile(srcMapFp, \"utf-8\"));\n\n if (!mapContent) {\n logger.debug(`Sourcemap of file not found: ${srcFp} - ${sourceMapFile}`);\n return;\n } // file has source map, need to update map file to point back to original location for source\n\n\n const mapData = JSON.parse(mapContent);\n const {\n sourceRoot = \"\"\n } = mapData;\n delete mapData.sourceRoot;\n mapData.sources = mapData.sources.map(s => {\n const source1 = sourceRoot + s;\n const source2 = Path.isAbsolute(source1) ? source1 : Path.join(src, source1);\n const relPath = Path.relative(dest, source2);\n logger.debug(`Rewriting map file source to ${relPath} from ${dest} to ${source2}`);\n return relPath;\n });\n const destMapFp = Path.join(dest, sourceMapFile);\n await xaa.try(() => Fs.writeFile(destMapFp, JSON.stringify(mapData)), () => {\n logger.info(`Failed to save rewritten source map file ${destMapFp}`);\n }); // TODO: what if sourceMapFile is not next to the source file?\n\n destFiles[sourceMapFile] = true;\n return;\n }\n\n if (!sourceMaps) {\n return;\n } // file is marked for fynMapped or it doesn't have source map so fyn needs to generate one for it\n\n\n if (isFynMapped || !sourceMapFile && !hasFynMapFlag) {\n const fileMap = `${file}.fyn.map`;\n const destMapFp = Path.join(dest, fileMap);\n logger.debug(`Generating map file for ${srcFp} to ${destFp}`);\n const allLines = content.split(\"\\n\");\n const count = allLines.length;\n const sourceMap = new SourceMapGenerator({\n file\n });\n const source = Path.relative(dest, srcFp);\n\n for (let line = 1; line <= count; line++) {\n const length = allLines[line - 1].length; // source map format doesn't have a way to say just 1-1 map back to source\n // so we are mapping every line and every column directly, it's a waste, but\n // the only way to achieve this.\n\n for (let column = 0; column < length; column++) {\n sourceMap.addMapping({\n generated: {\n line,\n column\n },\n source,\n original: {\n line,\n column\n }\n });\n }\n }\n\n await Fs.writeFile(destMapFp, sourceMap.toString());\n destFiles[fileMap] = true; // sourcemap url didn't exist, save it to source file\n\n if (!sourceMapFile) {\n const sep = content.endsWith(\"\\n\") ? \"\" : \"\\n\";\n const fynMapStr = hasFynMapFlag ? \"\" : `//# ${FYN_SOURCE_MAP_SIG}${fynMapFlag || \"true\"}\\n`;\n await Fs.writeFile(destFp, `${content}${sep}${fynMapStr}//# ${SOURCE_MAP_URL_SIG}${fileMap}\\n`);\n }\n }\n}\n/**\n * Link tree of files generated from npm pack\n *\n * @param {*} tree\n * @param {*} src\n * @param {*} dest\n * @param {*} sym1\n */\n\n\nasync function linkPackTree({\n tree,\n src,\n dest,\n sym1,\n sourceMaps\n}) {\n const files = tree[FILES];\n const destFiles = await prepDestDir(dest); //\n // create hardlinks to files\n //\n\n for (const file of files) {\n // In non-CI mode, skip linking source map file by matching for extensions like .js.map\n // because we rewrite their sources and copy them already\n if (!ci.isCI && file.match(/.+\\..+\\.map$/)) {\n continue;\n }\n\n destFiles[file] = true;\n const srcFp = Path.join(src, file);\n const destFp = Path.join(dest, file);\n await linkFile(srcFp, destFp);\n await handleSourceMap({\n file,\n destFiles,\n src,\n dest,\n srcFp,\n destFp,\n sourceMaps\n });\n } //\n // handle sub directories\n //\n\n\n const dirs = Object.keys(tree).sort();\n\n for (const dir of dirs) {\n // in case the tree is generated without top level dir by itself\n // tree is generated to always use / for path separator\n destFiles[dir.split(\"/\")[0]] = true;\n const srcFp = Path.join(src, dir);\n const destFp = Path.join(dest, dir);\n\n if (!sym1) {\n // recursively duplicate sub dirs with hardlinks\n await linkPackTree({\n tree: tree[dir],\n src: srcFp,\n dest: destFp,\n sourceMaps\n });\n } else {\n // make symlink to directories in the top level\n await fynTil.symlinkDir(destFp, srcFp);\n }\n }\n\n logger.debug(`linkPackTree src: ${src} dest: ${dest} - destFiles ${JSON.stringify(destFiles)}`); // any file exist in dest but not in src are removed\n\n await cleanExtraDest(dest, destFiles);\n}\n\nasync function link(src, dest, {\n sourceMaps = true\n} = {}) {\n const tree = await generatePackTree(src);\n return await linkPackTree({\n tree,\n src,\n dest,\n sourceMaps\n });\n}\n\nasync function linkSym1(src, dest) {\n const tree = await generatePackTree(src);\n return await linkPackTree({\n tree,\n src,\n dest,\n sym1: true\n });\n}\n\nmodule.exports = {\n link,\n linkFile,\n linkSym1\n};\n\n//# sourceURL=webpack://fyn/./lib/util/hard-link-dir.js?");
426
+ eval("\n/* eslint-disable max-params, max-statements, complexity */\n\n/*\n * clone another directory by:\n * - Creating the same directories\n * - Hard link physical files\n * - Transfer symlinks (ensure the same symlink name exist but with target adjusted)\n */\n\nconst Path = __webpack_require__(/*! path */ \"path\");\n\nconst Fs = __webpack_require__(/*! ./file-ops */ \"./lib/util/file-ops.js\");\n\nconst xaa = __webpack_require__(/*! ./xaa */ \"./lib/util/xaa.js\");\n\nconst npmPacklist = __webpack_require__(/*! npm-packlist */ \"./node_modules/npm-packlist/index.js\");\n\nconst fynTil = __webpack_require__(/*! ./fyntil */ \"./lib/util/fyntil.js\");\n\nconst logger = __webpack_require__(/*! ../logger */ \"./lib/logger.js\");\n\nconst {\n SourceMapGenerator\n} = __webpack_require__(/*! source-map */ \"./node_modules/source-map/source-map.js\");\n\nconst ci = __webpack_require__(/*! ci-info */ \"./node_modules/ci-info/index.js\");\n\nasync function linkFile(srcFp, destFp, srcStat) {\n try {\n return await Fs.link(srcFp, destFp);\n } catch (e) {\n if (e.code !== \"EEXIST\") throw e;\n\n if (srcStat === undefined) {\n srcStat = await xaa.try(() => Fs.stat(srcFp));\n }\n\n if (!srcStat) throw e;\n const destStat = await Fs.stat(destFp);\n\n if (srcStat.ino !== destStat.ino) {\n await Fs.unlink(destFp);\n return await linkFile(srcFp, destFp, null);\n }\n }\n\n return undefined;\n}\n\nasync function copyFile(srcFp, destFp) {\n if (Fs.copyFile) {\n return Fs.copyFile(srcFp, destFp);\n } else {\n const srcData = await Fs.readFile(srcFp);\n return Fs.writeFile(destFp, srcData);\n }\n}\n\nasync function prepDestDir(dest) {\n const statDest = await xaa.try(() => Fs.lstat(dest));\n const destFiles = {};\n\n if (!statDest) {\n try {\n await Fs.mkdir(dest);\n } catch (e) {\n await Fs.$.mkdirp(dest);\n }\n } else if (!statDest.isDirectory()) {\n await Fs.unlink(dest);\n return prepDestDir(dest);\n } else {\n (await Fs.readdir(dest)).forEach(x => destFiles[x] = false);\n }\n\n return destFiles;\n}\n\nasync function cleanExtraDest(dest, destFiles) {\n for (const k in destFiles) {\n if (destFiles[k] === false) {\n logger.debug(`removing extra local link file ${k}`);\n await Fs.$.rimraf(Path.join(dest, k));\n }\n }\n}\n\nconst FILES = Symbol(\"files\");\n\nasync function generatePackTree(path) {\n const files = await npmPacklist({\n path\n });\n logger.debug(`local package linking - pack tree returned ${files.length} files to link`, JSON.stringify(files, null, 2));\n\n if (files.length > 1000) {\n logger.warn(`Local linking package at ${path} has more than ${files.length} files.\n >>> This is unusual, please check package .npmignore or 'files' in package.json <<<`);\n }\n\n const fmap = {\n [FILES]: []\n };\n files.sort().forEach(filePath => {\n const dir = Path.dirname(filePath);\n\n if (dir === \".\") {\n fmap[FILES].push(filePath);\n return;\n }\n\n let dmap = fmap; // npm pack list always generate file path with /\n\n dir.split(\"/\").forEach(d => {\n if (!dmap[d]) {\n dmap[d] = {\n [FILES]: []\n };\n }\n\n dmap = dmap[d];\n });\n dmap[FILES].push(Path.basename(filePath));\n });\n return fmap;\n}\n\nconst FYN_SOURCE_MAP_SIG = \"fynSourceMap=\";\nconst SOURCE_MAP_URL_SIG = \"sourceMappingURL=\";\n/**\n * search for the last sourceMappingURL from a source content\n *\n * @param {*} content\n * @returns\n */\n\nfunction getSourceMapConfig(content, sig = SOURCE_MAP_URL_SIG) {\n const regex = new RegExp( // from /(?:\\/\\/[@#][\\s]*${sig}([^\\s'\"]+)[\\s]*$)|(?:\\/\\*[@#][\\s]*${sig}([^\\s*'\"]+)[\\s]*(?:\\*\\/)[\\s]*$)/\n `(?:\\\\/\\\\/[@#][\\\\s]*${sig}([^\\\\s'\"]+)[\\\\s]*$)|(?:\\\\/\\\\*[@#][\\\\s]*${sig}([^\\\\s*'\"]+)[\\\\s]*(?:\\\\*\\\\/)[\\\\s]*$)`, \"gm\");\n let match;\n let lastMatch; // search for the last occurrence of sourceMappingURL\n\n while (match = regex.exec(content)) {\n lastMatch = match;\n }\n\n return lastMatch && lastMatch[1];\n}\n/**\n * process or generate source map back to original file\n *\n * @param {*} param0\n */\n\n\nasync function handleSourceMap({\n file,\n destFiles,\n src,\n dest,\n srcFp,\n destFp,\n sourceMaps\n}) {\n const ext = !ci.isCI && Path.extname(file); // native plain js or mjs files should map back to the original local files\n // and it may or may not have source map file\n\n if (ext !== \".js\" && ext !== \".mjs\") {\n return;\n }\n\n const checkFynMapped = x => {\n return !(x === \"false\" || x === \"no\" || x === \"off\" || x === \"0\");\n };\n\n const content = await Fs.readFile(srcFp, \"utf-8\");\n const fynMapFlag = getSourceMapConfig(content, FYN_SOURCE_MAP_SIG);\n const hasFynMapFlag = typeof fynMapFlag === \"string\";\n const sourceMapFile = getSourceMapConfig(content);\n const isFynMapped = checkFynMapped(fynMapFlag); // file contains source map URL that's not marked for fyn, try copy it and rewrite sources\n\n if (!hasFynMapFlag && sourceMapFile) {\n if (Path.isAbsolute(sourceMapFile)) {\n logger.info(`File ${srcFp} sourcemap ${sourceMapFile} is full path - can't rewrite it`);\n return;\n }\n\n const srcMapFp = Path.join(src, sourceMapFile);\n const mapContent = await xaa.try(() => Fs.readFile(srcMapFp, \"utf-8\"));\n\n if (!mapContent) {\n logger.debug(`Sourcemap of file not found: ${srcFp} - ${sourceMapFile}`);\n return;\n } // file has source map, need to update map file to point back to original location for source\n\n\n const mapData = JSON.parse(mapContent);\n const {\n sourceRoot = \"\"\n } = mapData;\n delete mapData.sourceRoot;\n mapData.sources = mapData.sources.map(s => {\n const source1 = sourceRoot + s;\n const source2 = Path.isAbsolute(source1) ? source1 : Path.join(src, source1);\n const relPath = Path.relative(dest, source2);\n logger.debug(`Rewriting map file source to ${relPath} from ${dest} to ${source2}`);\n return relPath;\n });\n const destMapFp = Path.join(dest, sourceMapFile);\n await xaa.try(() => Fs.writeFile(destMapFp, JSON.stringify(mapData)), () => {\n logger.info(`Failed to save rewritten source map file ${destMapFp}`);\n }); // TODO: what if sourceMapFile is not next to the source file?\n\n destFiles[sourceMapFile] = true;\n return;\n }\n\n if (!sourceMaps) {\n return;\n } // file is marked for fynMapped or it doesn't have source map so fyn needs to generate one for it\n\n\n if (isFynMapped || !sourceMapFile && !hasFynMapFlag) {\n const fileMap = `${file}.fyn.map`;\n const destMapFp = Path.join(dest, fileMap);\n logger.debug(`Generating map file for ${srcFp} to ${destFp}`);\n const allLines = content.split(\"\\n\");\n const count = allLines.length;\n const sourceMap = new SourceMapGenerator({\n file\n });\n const source = Path.relative(dest, srcFp);\n\n for (let line = 1; line <= count; line++) {\n const length = allLines[line - 1].length; // source map format doesn't have a way to say just 1-1 map back to source\n // so we are mapping every line and every column directly, it's a waste, but\n // the only way to achieve this.\n\n for (let column = 0; column < length; column++) {\n sourceMap.addMapping({\n generated: {\n line,\n column\n },\n source,\n original: {\n line,\n column\n }\n });\n }\n }\n\n await Fs.writeFile(destMapFp, sourceMap.toString());\n destFiles[fileMap] = true; // sourcemap url didn't exist, save it to source file\n\n if (!sourceMapFile) {\n const sep = content.endsWith(\"\\n\") ? \"\" : \"\\n\";\n const fynMapStr = hasFynMapFlag ? \"\" : `//# ${FYN_SOURCE_MAP_SIG}${fynMapFlag || \"true\"}\\n`;\n await Fs.writeFile(destFp, `${content}${sep}${fynMapStr}//# ${SOURCE_MAP_URL_SIG}${fileMap}\\n`);\n }\n }\n}\n/**\n * Link tree of files generated from npm pack\n *\n * @param {*} tree\n * @param {*} src\n * @param {*} dest\n * @param {*} sym1\n */\n\n\nasync function linkPackTree({\n tree,\n src,\n dest,\n sym1,\n sourceMaps\n}) {\n const files = tree[FILES];\n const destFiles = await prepDestDir(dest); //\n // create hardlinks to files\n //\n\n for (const file of files) {\n // In non-CI mode, skip linking source map file by matching for extensions like .js.map\n // because we rewrite their sources and copy them already\n if (!ci.isCI && file.match(/.+\\..+\\.map$/)) {\n continue;\n }\n\n destFiles[file] = true;\n const srcFp = Path.join(src, file);\n const destFp = Path.join(dest, file);\n await linkFile(srcFp, destFp);\n await handleSourceMap({\n file,\n destFiles,\n src,\n dest,\n srcFp,\n destFp,\n sourceMaps\n });\n } //\n // handle sub directories\n //\n\n\n const dirs = Object.keys(tree).sort();\n\n for (const dir of dirs) {\n // in case the tree is generated without top level dir by itself\n // tree is generated to always use / for path separator\n destFiles[dir.split(\"/\")[0]] = true;\n const srcFp = Path.join(src, dir);\n const destFp = Path.join(dest, dir);\n\n if (!sym1) {\n // recursively duplicate sub dirs with hardlinks\n await linkPackTree({\n tree: tree[dir],\n src: srcFp,\n dest: destFp,\n sourceMaps\n });\n } else {\n // make symlink to directories in the top level\n await fynTil.symlinkDir(destFp, srcFp);\n }\n }\n\n logger.debug(`linkPackTree src: ${src} dest: ${dest} - destFiles ${JSON.stringify(destFiles)}`); // any file exist in dest but not in src are removed\n\n await cleanExtraDest(dest, destFiles);\n}\n\nasync function link(src, dest, {\n sourceMaps = true\n} = {}) {\n const tree = await generatePackTree(src);\n return await linkPackTree({\n tree,\n src,\n dest,\n sourceMaps\n });\n}\n\nasync function linkSym1(src, dest) {\n const tree = await generatePackTree(src);\n return await linkPackTree({\n tree,\n src,\n dest,\n sym1: true\n });\n}\n\nmodule.exports = {\n link,\n linkFile,\n copyFile,\n linkSym1\n};\n\n//# sourceURL=webpack://fyn/./lib/util/hard-link-dir.js?");
427
427
 
428
428
  /***/ }),
429
429
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fyn",
3
- "version": "0.4.37",
3
+ "version": "0.4.41",
4
4
  "description": "A fast node package manager for better productivity and efficiency",
5
5
  "main": "./bin/fyn.js",
6
6
  "scripts": {
@@ -10,6 +10,11 @@
10
10
  "fyn": "./bin/fyn.js",
11
11
  "fun": "./bin/fun.js"
12
12
  },
13
+ "publishConfig": {
14
+ "access": "public",
15
+ "registry": "https://registry.npmjs.com/",
16
+ "tag": "0.4.x"
17
+ },
13
18
  "files": [
14
19
  "bin",
15
20
  "dist"