fyn 3.1.7 → 3.1.9
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.
- package/README.md +6 -0
- package/bin/index.mjs +4 -1
- package/dist/fyn.mjs +216 -39
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -16,6 +16,12 @@ cd <your-project>
|
|
|
16
16
|
fyn
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
+
On an existing install, fyn checks file modification times before reinstalling. This scan
|
|
20
|
+
prunes directories and files matched by repository and nested `.gitignore` rules, alongside
|
|
21
|
+
its built-in exclusions. The rules apply even to tracked source files; manifests, lockfiles,
|
|
22
|
+
install configuration and changes to the consulted ignore rules are still checked.
|
|
23
|
+
Use `fyn --fi` to bypass this freshness check and force installation.
|
|
24
|
+
|
|
19
25
|
Want to add a package on your local disk as a dependency to your project? Do this:
|
|
20
26
|
|
|
21
27
|
```sh
|
package/bin/index.mjs
CHANGED
|
@@ -40,4 +40,7 @@ export const run = async (...args) => (await load()).run(...args);
|
|
|
40
40
|
*/
|
|
41
41
|
export const fun = async (...args) => (await load()).fun(...args);
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
/** Resolve the generated audit report path using fyn's installation configuration. */
|
|
44
|
+
export const getAuditFilePath = async (...args) => (await load()).getAuditFilePath(...args);
|
|
45
|
+
|
|
46
|
+
export default { run, fun, getAuditFilePath };
|
package/dist/fyn.mjs
CHANGED
|
@@ -1624,7 +1624,7 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1624
1624
|
* @returns Promise that resolves after the delay
|
|
1625
1625
|
*/
|
|
1626
1626
|
delay(ms) {
|
|
1627
|
-
return delay
|
|
1627
|
+
return this.then((value) => AveAzul.delay(ms, value));
|
|
1628
1628
|
}
|
|
1629
1629
|
/**
|
|
1630
1630
|
* Bluebird-style timeout() method
|
|
@@ -1662,8 +1662,8 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1662
1662
|
* @returns Promise that maintains the rejection
|
|
1663
1663
|
*/
|
|
1664
1664
|
tapCatch(fn) {
|
|
1665
|
-
return this.catch((err) => {
|
|
1666
|
-
fn(err);
|
|
1665
|
+
return this.catch(async (err) => {
|
|
1666
|
+
await fn(err);
|
|
1667
1667
|
throw err;
|
|
1668
1668
|
});
|
|
1669
1669
|
}
|
|
@@ -1703,7 +1703,9 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1703
1703
|
* @returns Promise that rejects with the given reason
|
|
1704
1704
|
*/
|
|
1705
1705
|
throw(reason) {
|
|
1706
|
-
return
|
|
1706
|
+
return this.then(() => {
|
|
1707
|
+
throw reason;
|
|
1708
|
+
});
|
|
1707
1709
|
}
|
|
1708
1710
|
/**
|
|
1709
1711
|
* Bluebird-style catchThrow() that catches an error and throws a new one
|
|
@@ -1756,6 +1758,8 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1756
1758
|
});
|
|
1757
1759
|
}
|
|
1758
1760
|
some(count) {
|
|
1761
|
+
if ((count | 0) !== count || count < 0) return AveAzul.reject(/* @__PURE__ */ new TypeError("expecting a non-negative integer"));
|
|
1762
|
+
if (count === 0) return AveAzul.resolve([]);
|
|
1759
1763
|
return this.then((args) => {
|
|
1760
1764
|
const arr = toArray$1(args);
|
|
1761
1765
|
return new AveAzul((resolve, reject) => {
|
|
@@ -1763,6 +1767,10 @@ var AveAzul = class AveAzul extends Promise {
|
|
|
1763
1767
|
const results = [];
|
|
1764
1768
|
const len = arr.length;
|
|
1765
1769
|
let settled = false;
|
|
1770
|
+
if (count > len) {
|
|
1771
|
+
settled = true;
|
|
1772
|
+
reject(/* @__PURE__ */ new RangeError(`Input array must contain at least ${count} items but contains only ${len} items`));
|
|
1773
|
+
}
|
|
1766
1774
|
const addDone = (result) => {
|
|
1767
1775
|
if (settled) return;
|
|
1768
1776
|
results.push(result);
|
|
@@ -2054,7 +2062,7 @@ AveAzul.OperationalError = OperationalError;
|
|
|
2054
2062
|
AveAzul.isOperationalError = isOperationalError;
|
|
2055
2063
|
AveAzul.isProgrammerError = isProgrammerError;
|
|
2056
2064
|
AveAzul.Disposer = Disposer;
|
|
2057
|
-
addStaticAny(AveAzul);
|
|
2065
|
+
addStaticAny(AveAzul, true);
|
|
2058
2066
|
setupNotImplemented(AveAzul);
|
|
2059
2067
|
|
|
2060
2068
|
//#endregion
|
|
@@ -26965,6 +26973,65 @@ const join2 = (sep, a, b) => {
|
|
|
26965
26973
|
else return a + sep + b;
|
|
26966
26974
|
};
|
|
26967
26975
|
|
|
26976
|
+
//#endregion
|
|
26977
|
+
//#region node_modules/filter-scan-dir/dist/gitignore.js
|
|
26978
|
+
function ancestorDirs(dir) {
|
|
26979
|
+
const dirs = [dir];
|
|
26980
|
+
for (let current = dir;;) {
|
|
26981
|
+
if (fs.existsSync(Path.join(current, ".git"))) return dirs.reverse();
|
|
26982
|
+
const parent = Path.dirname(current);
|
|
26983
|
+
if (parent === current) return [dir];
|
|
26984
|
+
dirs.push(parent);
|
|
26985
|
+
current = parent;
|
|
26986
|
+
}
|
|
26987
|
+
}
|
|
26988
|
+
var GitignoreRules = class GitignoreRules {
|
|
26989
|
+
constructor(rules = []) {
|
|
26990
|
+
this.rules = rules;
|
|
26991
|
+
}
|
|
26992
|
+
ignores(file, directory) {
|
|
26993
|
+
let ignored = false;
|
|
26994
|
+
for (const { dir, matcher } of this.rules) {
|
|
26995
|
+
const relative = Path.relative(dir, file).split(Path.sep).join("/");
|
|
26996
|
+
if (!relative) continue;
|
|
26997
|
+
const result = matcher.test(relative + (directory ? "/" : ""));
|
|
26998
|
+
if (result.ignored) ignored = true;
|
|
26999
|
+
else if (result.unignored) ignored = false;
|
|
27000
|
+
}
|
|
27001
|
+
return ignored;
|
|
27002
|
+
}
|
|
27003
|
+
add(dir, source, parse) {
|
|
27004
|
+
return new GitignoreRules([...this.rules, {
|
|
27005
|
+
dir,
|
|
27006
|
+
matcher: parse(source)
|
|
27007
|
+
}]);
|
|
27008
|
+
}
|
|
27009
|
+
static loadSync(dir, parse, parent) {
|
|
27010
|
+
let rules = parent || new GitignoreRules();
|
|
27011
|
+
for (const base of parent ? [dir] : ancestorDirs(dir)) {
|
|
27012
|
+
if (!parent && rules.ignores(base, true)) rules = new GitignoreRules();
|
|
27013
|
+
try {
|
|
27014
|
+
rules = rules.add(base, fs.readFileSync(Path.join(base, ".gitignore"), "utf8"), parse);
|
|
27015
|
+
} catch (error) {
|
|
27016
|
+
if (error.code !== "ENOENT" && error.code !== "ENOTDIR") throw error;
|
|
27017
|
+
}
|
|
27018
|
+
}
|
|
27019
|
+
return rules;
|
|
27020
|
+
}
|
|
27021
|
+
static async load(dir, parse, parent) {
|
|
27022
|
+
let rules = parent || new GitignoreRules();
|
|
27023
|
+
for (const base of parent ? [dir] : ancestorDirs(dir)) {
|
|
27024
|
+
if (!parent && rules.ignores(base, true)) rules = new GitignoreRules();
|
|
27025
|
+
try {
|
|
27026
|
+
rules = rules.add(base, await fs.promises.readFile(Path.join(base, ".gitignore"), "utf8"), parse);
|
|
27027
|
+
} catch (error) {
|
|
27028
|
+
if (error.code !== "ENOENT" && error.code !== "ENOTDIR") throw error;
|
|
27029
|
+
}
|
|
27030
|
+
}
|
|
27031
|
+
return rules;
|
|
27032
|
+
}
|
|
27033
|
+
};
|
|
27034
|
+
|
|
26968
27035
|
//#endregion
|
|
26969
27036
|
//#region node_modules/filter-scan-dir/dist/index.js
|
|
26970
27037
|
/**
|
|
@@ -27051,9 +27118,10 @@ function processFile(options, extras) {
|
|
|
27051
27118
|
}
|
|
27052
27119
|
return false;
|
|
27053
27120
|
}
|
|
27054
|
-
function acceptEntry(options, entry, path) {
|
|
27121
|
+
function acceptEntry(options, entry, path, gitignore) {
|
|
27055
27122
|
const isDirectory = entry.isDirectory();
|
|
27056
27123
|
if (isDirectory && options._ignoreDirs.has(entry.name)) return false;
|
|
27124
|
+
if (gitignore === null || gitignore === void 0 ? void 0 : gitignore.ignores(Path.resolve(options.dir, path, entry.name), isDirectory)) return false;
|
|
27057
27125
|
if (options.prefilter && !options.prefilter(entry.name, path, entry)) return false;
|
|
27058
27126
|
if (isDirectory) return true;
|
|
27059
27127
|
if (options.ignoreExt.length || options.filterExt.length) {
|
|
@@ -27096,7 +27164,7 @@ function releaseDirectory(options) {
|
|
|
27096
27164
|
* @param level
|
|
27097
27165
|
* @returns
|
|
27098
27166
|
*/
|
|
27099
|
-
async function walk(path, options, level = 0) {
|
|
27167
|
+
async function walk(path, options, level = 0, parentRules) {
|
|
27100
27168
|
let promises = [];
|
|
27101
27169
|
let hasSlot = false;
|
|
27102
27170
|
try {
|
|
@@ -27107,6 +27175,7 @@ async function walk(path, options, level = 0) {
|
|
|
27107
27175
|
}
|
|
27108
27176
|
if (options._stopped) return void 0;
|
|
27109
27177
|
const dir = Path.join(options.dir, path);
|
|
27178
|
+
const gitignore = options.gitignore ? await GitignoreRules.load(Path.resolve(dir), options.gitignore, parentRules) : void 0;
|
|
27110
27179
|
let files = await asyncReaddir(dir, options.readdirOpts);
|
|
27111
27180
|
if (options.sortFiles) {
|
|
27112
27181
|
if (!options.readdirOpts) files = files.sort();
|
|
@@ -27116,7 +27185,7 @@ async function walk(path, options, level = 0) {
|
|
|
27116
27185
|
const extrasFiles = options.fullStat && options._earlyFilter && (options.filter || options.filterDir) ? files.map((entry) => entry.name) : files;
|
|
27117
27186
|
for (let ix = 0; !options._stopped && ix < files.length; ix++) {
|
|
27118
27187
|
const file = files[ix];
|
|
27119
|
-
if (options._earlyFilter && !acceptEntry(options, file, path)) continue;
|
|
27188
|
+
if (options._earlyFilter && !acceptEntry(options, file, path, gitignore)) continue;
|
|
27120
27189
|
let extras;
|
|
27121
27190
|
if (options.fullStat) {
|
|
27122
27191
|
const name = options._earlyFilter ? file.name : file;
|
|
@@ -27143,7 +27212,7 @@ async function walk(path, options, level = 0) {
|
|
|
27143
27212
|
break;
|
|
27144
27213
|
}
|
|
27145
27214
|
if (!flags.skip && level < options.maxLevel) {
|
|
27146
|
-
const walkP = walk(extras.dirFile, options, level + 1);
|
|
27215
|
+
const walkP = walk(extras.dirFile, options, level + 1, gitignore);
|
|
27147
27216
|
if (options.concurrency > 1) {
|
|
27148
27217
|
promises.push(walkP);
|
|
27149
27218
|
if (promises.length >= options.concurrency) {
|
|
@@ -27207,7 +27276,7 @@ function makeOptions(opts) {
|
|
|
27207
27276
|
_earlyFilter: false,
|
|
27208
27277
|
_ignoreDirs: new Set([].concat(options.ignoreDirs || []))
|
|
27209
27278
|
});
|
|
27210
|
-
opts2._earlyFilter = !!opts2.prefilter || opts2._ignoreDirs.size > 0 || opts2.ignoreExt.length > 0 || opts2.filterExt.length > 0;
|
|
27279
|
+
opts2._earlyFilter = !!opts2.gitignore || !!opts2.prefilter || opts2._ignoreDirs.size > 0 || opts2.ignoreExt.length > 0 || opts2.filterExt.length > 0;
|
|
27211
27280
|
if (!opts2.fullStat || opts2._earlyFilter) opts2.readdirOpts = { withFileTypes: true };
|
|
27212
27281
|
return opts2;
|
|
27213
27282
|
}
|
|
@@ -28836,20 +28905,20 @@ const resolveAutoSearch = (val) => {
|
|
|
28836
28905
|
if (val === false) return {
|
|
28837
28906
|
enable: false,
|
|
28838
28907
|
respectGitignore: false,
|
|
28839
|
-
stopOnPackageJsonFound:
|
|
28908
|
+
stopOnPackageJsonFound: true
|
|
28840
28909
|
};
|
|
28841
28910
|
if (val && typeof val === "object") {
|
|
28842
28911
|
const obj = val;
|
|
28843
28912
|
return {
|
|
28844
28913
|
enable: obj.enable !== false,
|
|
28845
28914
|
respectGitignore: obj.respectGitignore === true,
|
|
28846
|
-
stopOnPackageJsonFound: obj.stopOnPackageJsonFound
|
|
28915
|
+
stopOnPackageJsonFound: obj.stopOnPackageJsonFound !== false
|
|
28847
28916
|
};
|
|
28848
28917
|
}
|
|
28849
28918
|
return {
|
|
28850
28919
|
enable: true,
|
|
28851
28920
|
respectGitignore: false,
|
|
28852
|
-
stopOnPackageJsonFound:
|
|
28921
|
+
stopOnPackageJsonFound: true
|
|
28853
28922
|
};
|
|
28854
28923
|
};
|
|
28855
28924
|
/**
|
|
@@ -28857,12 +28926,12 @@ const resolveAutoSearch = (val) => {
|
|
|
28857
28926
|
*
|
|
28858
28927
|
* Accepts both shapes:
|
|
28859
28928
|
*
|
|
28860
|
-
* - **array** - the historical form. Treated as `publishInclude`,
|
|
28861
|
-
* `respectGitignore` off. It no longer narrows discovery.
|
|
28929
|
+
* - **array** - the historical form. Treated as additive `include` and `publishInclude`,
|
|
28930
|
+
* with auto-search on and `respectGitignore` off. It no longer narrows discovery.
|
|
28862
28931
|
* - **object** - `{ autoSearch, include, exclude, publishInclude, publishExclude }`.
|
|
28863
28932
|
*
|
|
28864
|
-
* Defaults: `autoSearch` on, `respectGitignore` off. With auto-search
|
|
28865
|
-
* `include` falls back to `["packages/*"]`.
|
|
28933
|
+
* Defaults: `autoSearch` on, `respectGitignore` off, stop at package.json. With auto-search
|
|
28934
|
+
* off and no `include`, `include` falls back to `["packages/*"]`.
|
|
28866
28935
|
*
|
|
28867
28936
|
* @param packages - the raw `packages` value from fynpo.json / fynpo.config.js
|
|
28868
28937
|
* @returns the resolved config, every field populated
|
|
@@ -28874,7 +28943,7 @@ function resolvePackagesConfig(packages) {
|
|
|
28874
28943
|
autoSearch: {
|
|
28875
28944
|
enable: true,
|
|
28876
28945
|
respectGitignore: false,
|
|
28877
|
-
stopOnPackageJsonFound:
|
|
28946
|
+
stopOnPackageJsonFound: true
|
|
28878
28947
|
},
|
|
28879
28948
|
include: list,
|
|
28880
28949
|
exclude: [],
|
|
@@ -28898,9 +28967,9 @@ function resolvePackagesConfig(packages) {
|
|
|
28898
28967
|
* Decide how to scan for packages.
|
|
28899
28968
|
*
|
|
28900
28969
|
* `include` does NOT turn auto-search off - auto-search is on by default and stays on, so it
|
|
28901
|
-
* still decides *how the tree is walked*. `include`
|
|
28902
|
-
*
|
|
28903
|
-
*
|
|
28970
|
+
* still decides *how the tree is walked*. `include` adds explicit paths below package
|
|
28971
|
+
* boundaries. Only with auto-search off does `include` restrict the scan paths,
|
|
28972
|
+
* falling back to `packages/*`.
|
|
28904
28973
|
*
|
|
28905
28974
|
* @param config - resolved packages config
|
|
28906
28975
|
* @returns `null` to auto-search the whole repo, otherwise the patterns to scan
|
|
@@ -28910,9 +28979,8 @@ function scanPatterns(config) {
|
|
|
28910
28979
|
return config.include.length > 0 ? config.include : [...DEFAULT_INCLUDE];
|
|
28911
28980
|
}
|
|
28912
28981
|
/**
|
|
28913
|
-
*
|
|
28914
|
-
*
|
|
28915
|
-
* Empty means keep everything the scan found.
|
|
28982
|
+
* Explicit inclusion patterns, used to add nested paths and promote them to managed packages.
|
|
28983
|
+
* With auto-search disabled, they restrict discovery to the declared paths.
|
|
28916
28984
|
*
|
|
28917
28985
|
* @param config - resolved packages config
|
|
28918
28986
|
* @returns patterns to match a package path against
|
|
@@ -29735,9 +29803,9 @@ var FynpoDepGraph = class {
|
|
|
29735
29803
|
const mms = resolved.map((p) => new Minimatch(p));
|
|
29736
29804
|
groups = groupMM(mms, {});
|
|
29737
29805
|
}
|
|
29738
|
-
const foundInAutoSearch = (path) => {
|
|
29806
|
+
const foundInAutoSearch = (path, partial = false) => {
|
|
29739
29807
|
if (!autoSearch || !pkgConfig.autoSearch.stopOnPackageJsonFound) return false;
|
|
29740
|
-
for (const e of autoSearchFound) if (isPathInside$1(path, e)) return
|
|
29808
|
+
for (const e of autoSearchFound) if (isPathInside$1(path, e)) return !includeMms.some((m) => m.match(posixify$2(path), partial));
|
|
29741
29809
|
return false;
|
|
29742
29810
|
};
|
|
29743
29811
|
const files = [];
|
|
@@ -29757,7 +29825,7 @@ var FynpoDepGraph = class {
|
|
|
29757
29825
|
},
|
|
29758
29826
|
filterDir: (dir, path, extras) => {
|
|
29759
29827
|
if (dir !== "node_modules") {
|
|
29760
|
-
if (foundInAutoSearch(
|
|
29828
|
+
if (foundInAutoSearch(extras.dirFile, true) || isExcluded(path) || skipForAutoSearch(path)) return false;
|
|
29761
29829
|
return prefix === "." && groups[prefix] === null ? !dir.startsWith(".") : Boolean(groups[prefix].find((save) => save.mm.match(extras.dirFile)));
|
|
29762
29830
|
}
|
|
29763
29831
|
return false;
|
|
@@ -29775,7 +29843,7 @@ var FynpoDepGraph = class {
|
|
|
29775
29843
|
const pkgPath = posixify$2(Path.dirname(pkgFile));
|
|
29776
29844
|
const nested = autoSearch && packageRoots.some((root) => isPathInside$1(pkgPath, root));
|
|
29777
29845
|
const included = isIncluded(pkgPath);
|
|
29778
|
-
if (!
|
|
29846
|
+
if (!autoSearch && !included) continue;
|
|
29779
29847
|
const managed = !autoSearch || !nested || includeMms.length > 0 && included;
|
|
29780
29848
|
const pkgStr = await promises.readFile(Path.join(cwd, pkgFile), "utf-8");
|
|
29781
29849
|
const pkgJson = JSON.parse(pkgStr);
|
|
@@ -30667,7 +30735,7 @@ const fyntil = {
|
|
|
30667
30735
|
}
|
|
30668
30736
|
const graph = new FynpoDepGraph({
|
|
30669
30737
|
cwd: fcm.topDir,
|
|
30670
|
-
|
|
30738
|
+
packages: config.packages,
|
|
30671
30739
|
noFynLocal: config.noFynLocal
|
|
30672
30740
|
});
|
|
30673
30741
|
await graph.resolve();
|
|
@@ -91866,6 +91934,7 @@ var hard_link_dir_exports = /* @__PURE__ */ __exportAll({
|
|
|
91866
91934
|
link: () => link$1,
|
|
91867
91935
|
linkFile: () => linkFile,
|
|
91868
91936
|
linkSym1: () => linkSym1,
|
|
91937
|
+
localLinkNeedsRefresh: () => localLinkNeedsRefresh,
|
|
91869
91938
|
unlinkDest: () => unlinkDest
|
|
91870
91939
|
});
|
|
91871
91940
|
var import_lib$4 = /* @__PURE__ */ __toESM(require_lib$36(), 1);
|
|
@@ -92134,10 +92203,15 @@ async function handleSourceMap({ file, destFiles, src, dest, srcFp, destFp, sour
|
|
|
92134
92203
|
* @param {*} dest
|
|
92135
92204
|
* @param {*} sym1
|
|
92136
92205
|
*/
|
|
92137
|
-
async function linkPackTree({ tree, src, dest, sym1, sourceMaps, isRoot = false }) {
|
|
92206
|
+
async function linkPackTree({ tree, src, dest, sym1, sourceMaps, preserveInstall = false, isRoot = false }) {
|
|
92138
92207
|
const files = tree[SYM_FILES];
|
|
92139
92208
|
const destFiles = await prepDestDir(dest);
|
|
92209
|
+
if (isRoot && preserveInstall) {
|
|
92210
|
+
destFiles["package.json"] = true;
|
|
92211
|
+
destFiles["node_modules"] = true;
|
|
92212
|
+
}
|
|
92140
92213
|
for (const file of files) {
|
|
92214
|
+
if (isRoot && preserveInstall && file === "package.json") continue;
|
|
92141
92215
|
if (!import_ci_info.isCI && file.match(/\.(js|mjs)\.map$/)) continue;
|
|
92142
92216
|
destFiles[file] = true;
|
|
92143
92217
|
const srcFp = Path.join(src, file);
|
|
@@ -92161,6 +92235,7 @@ async function linkPackTree({ tree, src, dest, sym1, sourceMaps, isRoot = false
|
|
|
92161
92235
|
}
|
|
92162
92236
|
const dirs = Object.keys(tree).sort();
|
|
92163
92237
|
for (const dir of dirs) {
|
|
92238
|
+
if (isRoot && preserveInstall && dir.split("/")[0] === "node_modules") continue;
|
|
92164
92239
|
destFiles[dir.split("/")[0]] = true;
|
|
92165
92240
|
const srcFp = Path.join(src, dir);
|
|
92166
92241
|
const destFp = Path.join(dest, dir);
|
|
@@ -92175,15 +92250,47 @@ async function linkPackTree({ tree, src, dest, sym1, sourceMaps, isRoot = false
|
|
|
92175
92250
|
logger$1.debug(`linkPackTree src: ${src} dest: ${dest} - destFiles ${JSON.stringify(destFiles)}`);
|
|
92176
92251
|
await cleanExtraDest(dest, destFiles, isRoot);
|
|
92177
92252
|
}
|
|
92178
|
-
async function link$1(src, dest, { sourceMaps = true } = {}) {
|
|
92253
|
+
async function link$1(src, dest, { sourceMaps = true, preserveInstall = false } = {}) {
|
|
92179
92254
|
return await linkPackTree({
|
|
92180
92255
|
tree: await generatePackTree(src),
|
|
92181
92256
|
src,
|
|
92182
92257
|
dest,
|
|
92183
92258
|
sourceMaps,
|
|
92259
|
+
preserveInstall,
|
|
92184
92260
|
isRoot: true
|
|
92185
92261
|
});
|
|
92186
92262
|
}
|
|
92263
|
+
async function localLinkNeedsRefresh(src, dest, installedAt) {
|
|
92264
|
+
const tree = await generatePackTree(src);
|
|
92265
|
+
const copyMode = fyntil.strToBool(process.env.FYN_LOCAL_COPY_MODE);
|
|
92266
|
+
const inspectTree = async (tree, srcDir, destDir) => {
|
|
92267
|
+
for (const file of tree[SYM_FILES]) {
|
|
92268
|
+
const srcFile = Path.join(srcDir, file);
|
|
92269
|
+
const srcStat = await file_ops_default.lstat(srcFile);
|
|
92270
|
+
if (srcDir === src && file === "package.json" || !import_ci_info.isCI && /\.(js|mjs)\.map$/.test(file)) {
|
|
92271
|
+
if (srcStat.mtimeMs > installedAt) return true;
|
|
92272
|
+
continue;
|
|
92273
|
+
}
|
|
92274
|
+
const destFile = Path.join(destDir, file);
|
|
92275
|
+
let destStat;
|
|
92276
|
+
try {
|
|
92277
|
+
destStat = await file_ops_default.lstat(destFile);
|
|
92278
|
+
} catch (err) {
|
|
92279
|
+
if (err.code === "ENOENT" || err.code === "ENOTDIR") return true;
|
|
92280
|
+
throw err;
|
|
92281
|
+
}
|
|
92282
|
+
if (srcStat.isSymbolicLink()) {
|
|
92283
|
+
if (!destStat.isSymbolicLink() || await file_ops_default.readlink(srcFile) !== await file_ops_default.readlink(destFile)) return true;
|
|
92284
|
+
} else if (!destStat.isFile()) return true;
|
|
92285
|
+
else if (copyMode) {
|
|
92286
|
+
if (srcStat.mtimeMs > installedAt) return true;
|
|
92287
|
+
} else if (srcStat.dev !== destStat.dev || srcStat.ino !== destStat.ino) return true;
|
|
92288
|
+
}
|
|
92289
|
+
for (const dir of Object.keys(tree)) if (await inspectTree(tree[dir], Path.join(srcDir, dir), Path.join(destDir, dir))) return true;
|
|
92290
|
+
return false;
|
|
92291
|
+
};
|
|
92292
|
+
return inspectTree(tree, src, dest);
|
|
92293
|
+
}
|
|
92187
92294
|
async function linkSym1(src, dest) {
|
|
92188
92295
|
return await linkPackTree({
|
|
92189
92296
|
tree: await generatePackTree(src),
|
|
@@ -106667,7 +106774,8 @@ var FynCentral = class {
|
|
|
106667
106774
|
//#endregion
|
|
106668
106775
|
//#region lib/util/stat-dir.ts
|
|
106669
106776
|
async function _scanFileStats(dir, ignores, baseDir = "") {
|
|
106670
|
-
const
|
|
106777
|
+
const patterns = ignores.map((pattern) => new Minimatch(pattern, { dot: true }));
|
|
106778
|
+
const ignore = (fullPath) => patterns.find((pattern) => pattern.match(fullPath));
|
|
106671
106779
|
let latestMtimeMs = 0;
|
|
106672
106780
|
let latestFile = "";
|
|
106673
106781
|
const updateLatest = (mtimeMs, file) => {
|
|
@@ -106676,6 +106784,13 @@ async function _scanFileStats(dir, ignores, baseDir = "") {
|
|
|
106676
106784
|
latestFile = file;
|
|
106677
106785
|
}
|
|
106678
106786
|
};
|
|
106787
|
+
const inspectFile = (file) => {
|
|
106788
|
+
try {
|
|
106789
|
+
updateLatest(file_ops_default.statSync(file).mtimeMs, file);
|
|
106790
|
+
} catch (err) {
|
|
106791
|
+
if (err.code !== "ENOENT" && err.code !== "ENOTDIR") throw err;
|
|
106792
|
+
}
|
|
106793
|
+
};
|
|
106679
106794
|
const filter = (file, path, extras) => {
|
|
106680
106795
|
if (ignore(extras.fullFile)) return false;
|
|
106681
106796
|
updateLatest(extras.stat.mtimeMs, extras.fullFile);
|
|
@@ -106683,11 +106798,45 @@ async function _scanFileStats(dir, ignores, baseDir = "") {
|
|
|
106683
106798
|
};
|
|
106684
106799
|
const fullDir = Path.join(baseDir, dir);
|
|
106685
106800
|
updateLatest((await file_ops_default.stat(fullDir)).mtimeMs, fullDir);
|
|
106801
|
+
for (const file of [
|
|
106802
|
+
"package.json",
|
|
106803
|
+
"package-fyn.json",
|
|
106804
|
+
"fyn-lock.yaml",
|
|
106805
|
+
"package-lock.json",
|
|
106806
|
+
"npm-shrinkwrap.json",
|
|
106807
|
+
"yarn.lock",
|
|
106808
|
+
".npmrc",
|
|
106809
|
+
".fynrc",
|
|
106810
|
+
"fynpo.json",
|
|
106811
|
+
"fynpo.config.js",
|
|
106812
|
+
"fynpo.config.json"
|
|
106813
|
+
]) inspectFile(Path.join(fullDir, file));
|
|
106814
|
+
const ruleDirs = [];
|
|
106815
|
+
let ancestor = Path.resolve(fullDir);
|
|
106816
|
+
while (true) {
|
|
106817
|
+
ruleDirs.push(ancestor);
|
|
106818
|
+
if (file_ops_default.existsSync(Path.join(ancestor, ".git"))) break;
|
|
106819
|
+
const parent = Path.dirname(ancestor);
|
|
106820
|
+
if (parent === ancestor) {
|
|
106821
|
+
ruleDirs.length = 1;
|
|
106822
|
+
break;
|
|
106823
|
+
}
|
|
106824
|
+
ancestor = parent;
|
|
106825
|
+
}
|
|
106826
|
+
for (const ruleDir of ruleDirs) {
|
|
106827
|
+
inspectFile(ruleDir);
|
|
106828
|
+
inspectFile(Path.join(ruleDir, ".gitignore"));
|
|
106829
|
+
}
|
|
106686
106830
|
await filterScanDir({
|
|
106687
106831
|
cwd: fullDir,
|
|
106688
106832
|
prependCwd: false,
|
|
106833
|
+
gitignore: (rules) => (0, import_ignore.default)().add(rules),
|
|
106689
106834
|
filter,
|
|
106690
|
-
filterDir:
|
|
106835
|
+
filterDir: (file, path, extras) => {
|
|
106836
|
+
if (!filter(file, path, extras)) return false;
|
|
106837
|
+
inspectFile(Path.join(extras.fullFile, ".gitignore"));
|
|
106838
|
+
return true;
|
|
106839
|
+
},
|
|
106691
106840
|
concurrency: 500,
|
|
106692
106841
|
fullStat: true
|
|
106693
106842
|
});
|
|
@@ -106697,7 +106846,7 @@ async function _scanFileStats(dir, ignores, baseDir = "") {
|
|
|
106697
106846
|
};
|
|
106698
106847
|
}
|
|
106699
106848
|
function scanFileStats(dir, options = {}) {
|
|
106700
|
-
return _scanFileStats(dir, [`**/?(node_modules|_fyn|.vscode|.DS_Store|coverage|.nyc_output|.fynpo|.git|.github|.gitignore)`, "**/*.?(log|md)"].concat(options.ignores || `**/?(docs|docusaurus|packages|tmp|.etmp|samples|dist)`).concat(options.moreIgnores).filter((x) => x), "");
|
|
106849
|
+
return _scanFileStats(dir, [`**/?(node_modules|_fyn|.vscode|.DS_Store|coverage|.nyc_output|.fynpo|.git|.github|.gitignore)`, "**/*.?(log|md)"].concat(options.ignores || `**/?(docs|docusaurus|packages|tmp|.temp|.etmp|samples|dist)`).concat(options.moreIgnores).filter((x) => x), "");
|
|
106701
106850
|
}
|
|
106702
106851
|
|
|
106703
106852
|
//#endregion
|
|
@@ -110331,7 +110480,7 @@ var LocalPkgBuilder = class {
|
|
|
110331
110480
|
}
|
|
110332
110481
|
const checkPkg = await this._fyn.getLocalPkgInstall(item.fullPath);
|
|
110333
110482
|
this._waitItems[item.fullPath] = false;
|
|
110334
|
-
if (!checkPkg.localBuild) {
|
|
110483
|
+
if (!checkPkg.localBuild && !(this._fyn._options.forceInstall && checkPkg.hasScript)) {
|
|
110335
110484
|
logger$1.debug(`local pkg at ${item.fullPath} doesn't need build`, checkPkg);
|
|
110336
110485
|
return;
|
|
110337
110486
|
}
|
|
@@ -110370,7 +110519,8 @@ var LocalPkgBuilder = class {
|
|
|
110370
110519
|
this._fyn._options.registry && `--reg=${this._fyn._options.registry}`,
|
|
110371
110520
|
"-q=d --pg=simple --no-build-local --sl=fyn-debug.log",
|
|
110372
110521
|
!this._fyn._options.sourceMaps && "--no-source-maps",
|
|
110373
|
-
"install --no-audit"
|
|
110522
|
+
"install --no-audit",
|
|
110523
|
+
this._fyn._options.forceInstall && "--force-install"
|
|
110374
110524
|
].filter((x) => x).join(" ");
|
|
110375
110525
|
const displayTitle = `building local pkg at ${dispPath}`;
|
|
110376
110526
|
logger$1.verbose(displayTitle);
|
|
@@ -111175,6 +111325,7 @@ var Fyn = class Fyn {
|
|
|
111175
111325
|
const localPkg = localPkgs[nmDir];
|
|
111176
111326
|
const fullPath = Path.join(this._cwd, localPkg.srcDir);
|
|
111177
111327
|
if ((await this.getLocalPkgInstall(fullPath)).changed) return true;
|
|
111328
|
+
if (await localLinkNeedsRefresh(fullPath, Path.join(this._cwd, nmDir), this._installConfig.time)) return true;
|
|
111178
111329
|
}
|
|
111179
111330
|
if (await localExportsNeedInstall({
|
|
111180
111331
|
cwd: this._cwd,
|
|
@@ -111208,6 +111359,7 @@ var Fyn = class Fyn {
|
|
|
111208
111359
|
time: Date.now() + 5,
|
|
111209
111360
|
centralDir,
|
|
111210
111361
|
production: this.production,
|
|
111362
|
+
fynlocal: Boolean(this.fynlocal),
|
|
111211
111363
|
layout: this._options.layout,
|
|
111212
111364
|
shortPkgDir: this._shortPkgDir,
|
|
111213
111365
|
blockedScripts: this._blockedScripts || this._installConfig.blockedScripts || [],
|
|
@@ -115259,7 +115411,7 @@ var FynCli = class {
|
|
|
115259
115411
|
const auditFile = argv.opts?.auditFile;
|
|
115260
115412
|
return dist_default.try(() => this.fyn._initializePkg()).then(async () => {
|
|
115261
115413
|
checkNewVersion(this.fyn._options);
|
|
115262
|
-
if (!this.fyn._changeProdMode && !this.fyn._options.forceInstall && this.fyn._installConfig.time) {
|
|
115414
|
+
if (!this.fyn._changeProdMode && !this.fyn._options.forceInstall && this.fyn._installConfig.fynlocal === Boolean(this.fyn.fynlocal) && this.fyn._installConfig.time) {
|
|
115263
115415
|
const stats = await scanFileStats(this.fyn.cwd, { moreIgnores: localExportsScanIgnores(this.fyn._pkg) });
|
|
115264
115416
|
const { latestMtimeMs } = stats;
|
|
115265
115417
|
logger$1.debug("time check from install config - last install time", this.fyn._installConfig.time, "latest file time", latestMtimeMs);
|
|
@@ -115353,6 +115505,16 @@ var FynCli = class {
|
|
|
115353
115505
|
dir: this.fyn.cwd
|
|
115354
115506
|
}
|
|
115355
115507
|
});
|
|
115508
|
+
if (scripts.length > 0 || this.fyn._options.autoRun && fynpoNpmScripts.length > 0) {
|
|
115509
|
+
const localPkgLinks = this.fyn._installConfig.localPkgLinks || {};
|
|
115510
|
+
for (const vdir in localPkgLinks) {
|
|
115511
|
+
const localPkg = localPkgLinks[vdir];
|
|
115512
|
+
await link$1(Path.join(this.fyn.cwd, localPkg.srcDir), Path.join(this.fyn.cwd, vdir), {
|
|
115513
|
+
sourceMaps: Boolean(localPkg.sourceMaps),
|
|
115514
|
+
preserveInstall: true
|
|
115515
|
+
});
|
|
115516
|
+
}
|
|
115517
|
+
}
|
|
115356
115518
|
}).then(async () => {
|
|
115357
115519
|
logger$1.removeItem(INSTALL_PACKAGE);
|
|
115358
115520
|
const end = Date.now();
|
|
@@ -124768,6 +124930,20 @@ const pickOptions = async (cmd, checkFynpo = true) => {
|
|
|
124768
124930
|
_fynpo: fynpo
|
|
124769
124931
|
};
|
|
124770
124932
|
};
|
|
124933
|
+
/** Resolve bootstrap's generated report without resolving the package graph or installing. */
|
|
124934
|
+
const getAuditFilePath = async (cwd, { rcfile = true } = {}) => {
|
|
124935
|
+
cwd = Path.resolve(cwd);
|
|
124936
|
+
const manager = new FynpoConfigManager({ cwd });
|
|
124937
|
+
await manager.load();
|
|
124938
|
+
const rc = loadRc(rcfile ? cwd : false, manager.topDir);
|
|
124939
|
+
return new Fyn({
|
|
124940
|
+
opts: {
|
|
124941
|
+
...rc.all || defaultRc,
|
|
124942
|
+
cwd
|
|
124943
|
+
},
|
|
124944
|
+
_fynpo: false
|
|
124945
|
+
}).getFvDir(".fyn-audit.json");
|
|
124946
|
+
};
|
|
124771
124947
|
const makeFynGlobal = async (cmd, extra = {}) => {
|
|
124772
124948
|
const { opts } = await pickOptions(cmd, false);
|
|
124773
124949
|
const tag = cmd.getParent()?.opts?.tag;
|
|
@@ -125473,8 +125649,9 @@ var main_default = {
|
|
|
125473
125649
|
pickEnvOptions,
|
|
125474
125650
|
setLockfile,
|
|
125475
125651
|
hardLinkDir: hard_link_dir_exports,
|
|
125476
|
-
reportFynpoLoadError
|
|
125652
|
+
reportFynpoLoadError,
|
|
125653
|
+
getAuditFilePath
|
|
125477
125654
|
};
|
|
125478
125655
|
|
|
125479
125656
|
//#endregion
|
|
125480
|
-
export { main_default as default, fun, getRunExitCode, hard_link_dir_exports as hardLinkDir, nodeGyp, pickEnvOptions, reportFynpoLoadError, run, setLockfile };
|
|
125657
|
+
export { main_default as default, fun, getAuditFilePath, getRunExitCode, hard_link_dir_exports as hardLinkDir, nodeGyp, pickEnvOptions, reportFynpoLoadError, run, setLockfile };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fyn",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "3.1.
|
|
4
|
+
"version": "3.1.9",
|
|
5
5
|
"description": "fyn is a node.js package manager, and supports fynpo -- a zero setup monorepo tool",
|
|
6
6
|
"main": "./bin/index.mjs",
|
|
7
7
|
"homepage": "https://github.com/jchip/fynjs/tree/main/packages/fyn",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"Walmart GTP.js Team and Contributors"
|
|
83
83
|
],
|
|
84
84
|
"devDependencies": {
|
|
85
|
-
"@fynjs/run": "^1.1.
|
|
85
|
+
"@fynjs/run": "^1.1.6",
|
|
86
86
|
"@fynjs/ts-resolve": "^1.0.3",
|
|
87
87
|
"@types/node": "^26.4.1",
|
|
88
88
|
"@vitest/coverage-v8": "^5.0.0",
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"patch-package": "^8.0.0",
|
|
93
93
|
"prettier": "^3.5.3",
|
|
94
94
|
"rolldown": "^1.2.6",
|
|
95
|
-
"run-verify": "^2.1.
|
|
95
|
+
"run-verify": "^2.1.6",
|
|
96
96
|
"typescript": "^7.0.2",
|
|
97
97
|
"vite": "^8.2.2",
|
|
98
98
|
"vitest": "^5.0.0",
|