fyn 3.1.7 → 3.1.8
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/dist/fyn.mjs +129 -27
- package/package.json +1 -1
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/dist/fyn.mjs
CHANGED
|
@@ -26965,6 +26965,65 @@ const join2 = (sep, a, b) => {
|
|
|
26965
26965
|
else return a + sep + b;
|
|
26966
26966
|
};
|
|
26967
26967
|
|
|
26968
|
+
//#endregion
|
|
26969
|
+
//#region node_modules/filter-scan-dir/dist/gitignore.js
|
|
26970
|
+
function ancestorDirs(dir) {
|
|
26971
|
+
const dirs = [dir];
|
|
26972
|
+
for (let current = dir;;) {
|
|
26973
|
+
if (fs.existsSync(Path.join(current, ".git"))) return dirs.reverse();
|
|
26974
|
+
const parent = Path.dirname(current);
|
|
26975
|
+
if (parent === current) return [dir];
|
|
26976
|
+
dirs.push(parent);
|
|
26977
|
+
current = parent;
|
|
26978
|
+
}
|
|
26979
|
+
}
|
|
26980
|
+
var GitignoreRules = class GitignoreRules {
|
|
26981
|
+
constructor(rules = []) {
|
|
26982
|
+
this.rules = rules;
|
|
26983
|
+
}
|
|
26984
|
+
ignores(file, directory) {
|
|
26985
|
+
let ignored = false;
|
|
26986
|
+
for (const { dir, matcher } of this.rules) {
|
|
26987
|
+
const relative = Path.relative(dir, file).split(Path.sep).join("/");
|
|
26988
|
+
if (!relative) continue;
|
|
26989
|
+
const result = matcher.test(relative + (directory ? "/" : ""));
|
|
26990
|
+
if (result.ignored) ignored = true;
|
|
26991
|
+
else if (result.unignored) ignored = false;
|
|
26992
|
+
}
|
|
26993
|
+
return ignored;
|
|
26994
|
+
}
|
|
26995
|
+
add(dir, source, parse) {
|
|
26996
|
+
return new GitignoreRules([...this.rules, {
|
|
26997
|
+
dir,
|
|
26998
|
+
matcher: parse(source)
|
|
26999
|
+
}]);
|
|
27000
|
+
}
|
|
27001
|
+
static loadSync(dir, parse, parent) {
|
|
27002
|
+
let rules = parent || new GitignoreRules();
|
|
27003
|
+
for (const base of parent ? [dir] : ancestorDirs(dir)) {
|
|
27004
|
+
if (!parent && rules.ignores(base, true)) rules = new GitignoreRules();
|
|
27005
|
+
try {
|
|
27006
|
+
rules = rules.add(base, fs.readFileSync(Path.join(base, ".gitignore"), "utf8"), parse);
|
|
27007
|
+
} catch (error) {
|
|
27008
|
+
if (error.code !== "ENOENT" && error.code !== "ENOTDIR") throw error;
|
|
27009
|
+
}
|
|
27010
|
+
}
|
|
27011
|
+
return rules;
|
|
27012
|
+
}
|
|
27013
|
+
static async load(dir, parse, parent) {
|
|
27014
|
+
let rules = parent || new GitignoreRules();
|
|
27015
|
+
for (const base of parent ? [dir] : ancestorDirs(dir)) {
|
|
27016
|
+
if (!parent && rules.ignores(base, true)) rules = new GitignoreRules();
|
|
27017
|
+
try {
|
|
27018
|
+
rules = rules.add(base, await fs.promises.readFile(Path.join(base, ".gitignore"), "utf8"), parse);
|
|
27019
|
+
} catch (error) {
|
|
27020
|
+
if (error.code !== "ENOENT" && error.code !== "ENOTDIR") throw error;
|
|
27021
|
+
}
|
|
27022
|
+
}
|
|
27023
|
+
return rules;
|
|
27024
|
+
}
|
|
27025
|
+
};
|
|
27026
|
+
|
|
26968
27027
|
//#endregion
|
|
26969
27028
|
//#region node_modules/filter-scan-dir/dist/index.js
|
|
26970
27029
|
/**
|
|
@@ -27051,9 +27110,10 @@ function processFile(options, extras) {
|
|
|
27051
27110
|
}
|
|
27052
27111
|
return false;
|
|
27053
27112
|
}
|
|
27054
|
-
function acceptEntry(options, entry, path) {
|
|
27113
|
+
function acceptEntry(options, entry, path, gitignore) {
|
|
27055
27114
|
const isDirectory = entry.isDirectory();
|
|
27056
27115
|
if (isDirectory && options._ignoreDirs.has(entry.name)) return false;
|
|
27116
|
+
if (gitignore === null || gitignore === void 0 ? void 0 : gitignore.ignores(Path.resolve(options.dir, path, entry.name), isDirectory)) return false;
|
|
27057
27117
|
if (options.prefilter && !options.prefilter(entry.name, path, entry)) return false;
|
|
27058
27118
|
if (isDirectory) return true;
|
|
27059
27119
|
if (options.ignoreExt.length || options.filterExt.length) {
|
|
@@ -27096,7 +27156,7 @@ function releaseDirectory(options) {
|
|
|
27096
27156
|
* @param level
|
|
27097
27157
|
* @returns
|
|
27098
27158
|
*/
|
|
27099
|
-
async function walk(path, options, level = 0) {
|
|
27159
|
+
async function walk(path, options, level = 0, parentRules) {
|
|
27100
27160
|
let promises = [];
|
|
27101
27161
|
let hasSlot = false;
|
|
27102
27162
|
try {
|
|
@@ -27107,6 +27167,7 @@ async function walk(path, options, level = 0) {
|
|
|
27107
27167
|
}
|
|
27108
27168
|
if (options._stopped) return void 0;
|
|
27109
27169
|
const dir = Path.join(options.dir, path);
|
|
27170
|
+
const gitignore = options.gitignore ? await GitignoreRules.load(Path.resolve(dir), options.gitignore, parentRules) : void 0;
|
|
27110
27171
|
let files = await asyncReaddir(dir, options.readdirOpts);
|
|
27111
27172
|
if (options.sortFiles) {
|
|
27112
27173
|
if (!options.readdirOpts) files = files.sort();
|
|
@@ -27116,7 +27177,7 @@ async function walk(path, options, level = 0) {
|
|
|
27116
27177
|
const extrasFiles = options.fullStat && options._earlyFilter && (options.filter || options.filterDir) ? files.map((entry) => entry.name) : files;
|
|
27117
27178
|
for (let ix = 0; !options._stopped && ix < files.length; ix++) {
|
|
27118
27179
|
const file = files[ix];
|
|
27119
|
-
if (options._earlyFilter && !acceptEntry(options, file, path)) continue;
|
|
27180
|
+
if (options._earlyFilter && !acceptEntry(options, file, path, gitignore)) continue;
|
|
27120
27181
|
let extras;
|
|
27121
27182
|
if (options.fullStat) {
|
|
27122
27183
|
const name = options._earlyFilter ? file.name : file;
|
|
@@ -27143,7 +27204,7 @@ async function walk(path, options, level = 0) {
|
|
|
27143
27204
|
break;
|
|
27144
27205
|
}
|
|
27145
27206
|
if (!flags.skip && level < options.maxLevel) {
|
|
27146
|
-
const walkP = walk(extras.dirFile, options, level + 1);
|
|
27207
|
+
const walkP = walk(extras.dirFile, options, level + 1, gitignore);
|
|
27147
27208
|
if (options.concurrency > 1) {
|
|
27148
27209
|
promises.push(walkP);
|
|
27149
27210
|
if (promises.length >= options.concurrency) {
|
|
@@ -27207,7 +27268,7 @@ function makeOptions(opts) {
|
|
|
27207
27268
|
_earlyFilter: false,
|
|
27208
27269
|
_ignoreDirs: new Set([].concat(options.ignoreDirs || []))
|
|
27209
27270
|
});
|
|
27210
|
-
opts2._earlyFilter = !!opts2.prefilter || opts2._ignoreDirs.size > 0 || opts2.ignoreExt.length > 0 || opts2.filterExt.length > 0;
|
|
27271
|
+
opts2._earlyFilter = !!opts2.gitignore || !!opts2.prefilter || opts2._ignoreDirs.size > 0 || opts2.ignoreExt.length > 0 || opts2.filterExt.length > 0;
|
|
27211
27272
|
if (!opts2.fullStat || opts2._earlyFilter) opts2.readdirOpts = { withFileTypes: true };
|
|
27212
27273
|
return opts2;
|
|
27213
27274
|
}
|
|
@@ -28836,20 +28897,20 @@ const resolveAutoSearch = (val) => {
|
|
|
28836
28897
|
if (val === false) return {
|
|
28837
28898
|
enable: false,
|
|
28838
28899
|
respectGitignore: false,
|
|
28839
|
-
stopOnPackageJsonFound:
|
|
28900
|
+
stopOnPackageJsonFound: true
|
|
28840
28901
|
};
|
|
28841
28902
|
if (val && typeof val === "object") {
|
|
28842
28903
|
const obj = val;
|
|
28843
28904
|
return {
|
|
28844
28905
|
enable: obj.enable !== false,
|
|
28845
28906
|
respectGitignore: obj.respectGitignore === true,
|
|
28846
|
-
stopOnPackageJsonFound: obj.stopOnPackageJsonFound
|
|
28907
|
+
stopOnPackageJsonFound: obj.stopOnPackageJsonFound !== false
|
|
28847
28908
|
};
|
|
28848
28909
|
}
|
|
28849
28910
|
return {
|
|
28850
28911
|
enable: true,
|
|
28851
28912
|
respectGitignore: false,
|
|
28852
|
-
stopOnPackageJsonFound:
|
|
28913
|
+
stopOnPackageJsonFound: true
|
|
28853
28914
|
};
|
|
28854
28915
|
};
|
|
28855
28916
|
/**
|
|
@@ -28857,12 +28918,12 @@ const resolveAutoSearch = (val) => {
|
|
|
28857
28918
|
*
|
|
28858
28919
|
* Accepts both shapes:
|
|
28859
28920
|
*
|
|
28860
|
-
* - **array** - the historical form. Treated as `publishInclude`,
|
|
28861
|
-
* `respectGitignore` off. It no longer narrows discovery.
|
|
28921
|
+
* - **array** - the historical form. Treated as additive `include` and `publishInclude`,
|
|
28922
|
+
* with auto-search on and `respectGitignore` off. It no longer narrows discovery.
|
|
28862
28923
|
* - **object** - `{ autoSearch, include, exclude, publishInclude, publishExclude }`.
|
|
28863
28924
|
*
|
|
28864
|
-
* Defaults: `autoSearch` on, `respectGitignore` off. With auto-search
|
|
28865
|
-
* `include` falls back to `["packages/*"]`.
|
|
28925
|
+
* Defaults: `autoSearch` on, `respectGitignore` off, stop at package.json. With auto-search
|
|
28926
|
+
* off and no `include`, `include` falls back to `["packages/*"]`.
|
|
28866
28927
|
*
|
|
28867
28928
|
* @param packages - the raw `packages` value from fynpo.json / fynpo.config.js
|
|
28868
28929
|
* @returns the resolved config, every field populated
|
|
@@ -28874,7 +28935,7 @@ function resolvePackagesConfig(packages) {
|
|
|
28874
28935
|
autoSearch: {
|
|
28875
28936
|
enable: true,
|
|
28876
28937
|
respectGitignore: false,
|
|
28877
|
-
stopOnPackageJsonFound:
|
|
28938
|
+
stopOnPackageJsonFound: true
|
|
28878
28939
|
},
|
|
28879
28940
|
include: list,
|
|
28880
28941
|
exclude: [],
|
|
@@ -28898,9 +28959,9 @@ function resolvePackagesConfig(packages) {
|
|
|
28898
28959
|
* Decide how to scan for packages.
|
|
28899
28960
|
*
|
|
28900
28961
|
* `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
|
-
*
|
|
28962
|
+
* still decides *how the tree is walked*. `include` adds explicit paths below package
|
|
28963
|
+
* boundaries. Only with auto-search off does `include` restrict the scan paths,
|
|
28964
|
+
* falling back to `packages/*`.
|
|
28904
28965
|
*
|
|
28905
28966
|
* @param config - resolved packages config
|
|
28906
28967
|
* @returns `null` to auto-search the whole repo, otherwise the patterns to scan
|
|
@@ -28910,9 +28971,8 @@ function scanPatterns(config) {
|
|
|
28910
28971
|
return config.include.length > 0 ? config.include : [...DEFAULT_INCLUDE];
|
|
28911
28972
|
}
|
|
28912
28973
|
/**
|
|
28913
|
-
*
|
|
28914
|
-
*
|
|
28915
|
-
* Empty means keep everything the scan found.
|
|
28974
|
+
* Explicit inclusion patterns, used to add nested paths and promote them to managed packages.
|
|
28975
|
+
* With auto-search disabled, they restrict discovery to the declared paths.
|
|
28916
28976
|
*
|
|
28917
28977
|
* @param config - resolved packages config
|
|
28918
28978
|
* @returns patterns to match a package path against
|
|
@@ -29735,9 +29795,9 @@ var FynpoDepGraph = class {
|
|
|
29735
29795
|
const mms = resolved.map((p) => new Minimatch(p));
|
|
29736
29796
|
groups = groupMM(mms, {});
|
|
29737
29797
|
}
|
|
29738
|
-
const foundInAutoSearch = (path) => {
|
|
29798
|
+
const foundInAutoSearch = (path, partial = false) => {
|
|
29739
29799
|
if (!autoSearch || !pkgConfig.autoSearch.stopOnPackageJsonFound) return false;
|
|
29740
|
-
for (const e of autoSearchFound) if (isPathInside$1(path, e)) return
|
|
29800
|
+
for (const e of autoSearchFound) if (isPathInside$1(path, e)) return !includeMms.some((m) => m.match(posixify$2(path), partial));
|
|
29741
29801
|
return false;
|
|
29742
29802
|
};
|
|
29743
29803
|
const files = [];
|
|
@@ -29757,7 +29817,7 @@ var FynpoDepGraph = class {
|
|
|
29757
29817
|
},
|
|
29758
29818
|
filterDir: (dir, path, extras) => {
|
|
29759
29819
|
if (dir !== "node_modules") {
|
|
29760
|
-
if (foundInAutoSearch(
|
|
29820
|
+
if (foundInAutoSearch(extras.dirFile, true) || isExcluded(path) || skipForAutoSearch(path)) return false;
|
|
29761
29821
|
return prefix === "." && groups[prefix] === null ? !dir.startsWith(".") : Boolean(groups[prefix].find((save) => save.mm.match(extras.dirFile)));
|
|
29762
29822
|
}
|
|
29763
29823
|
return false;
|
|
@@ -29775,7 +29835,7 @@ var FynpoDepGraph = class {
|
|
|
29775
29835
|
const pkgPath = posixify$2(Path.dirname(pkgFile));
|
|
29776
29836
|
const nested = autoSearch && packageRoots.some((root) => isPathInside$1(pkgPath, root));
|
|
29777
29837
|
const included = isIncluded(pkgPath);
|
|
29778
|
-
if (!
|
|
29838
|
+
if (!autoSearch && !included) continue;
|
|
29779
29839
|
const managed = !autoSearch || !nested || includeMms.length > 0 && included;
|
|
29780
29840
|
const pkgStr = await promises.readFile(Path.join(cwd, pkgFile), "utf-8");
|
|
29781
29841
|
const pkgJson = JSON.parse(pkgStr);
|
|
@@ -30667,7 +30727,7 @@ const fyntil = {
|
|
|
30667
30727
|
}
|
|
30668
30728
|
const graph = new FynpoDepGraph({
|
|
30669
30729
|
cwd: fcm.topDir,
|
|
30670
|
-
|
|
30730
|
+
packages: config.packages,
|
|
30671
30731
|
noFynLocal: config.noFynLocal
|
|
30672
30732
|
});
|
|
30673
30733
|
await graph.resolve();
|
|
@@ -106667,7 +106727,8 @@ var FynCentral = class {
|
|
|
106667
106727
|
//#endregion
|
|
106668
106728
|
//#region lib/util/stat-dir.ts
|
|
106669
106729
|
async function _scanFileStats(dir, ignores, baseDir = "") {
|
|
106670
|
-
const
|
|
106730
|
+
const patterns = ignores.map((pattern) => new Minimatch(pattern, { dot: true }));
|
|
106731
|
+
const ignore = (fullPath) => patterns.find((pattern) => pattern.match(fullPath));
|
|
106671
106732
|
let latestMtimeMs = 0;
|
|
106672
106733
|
let latestFile = "";
|
|
106673
106734
|
const updateLatest = (mtimeMs, file) => {
|
|
@@ -106676,6 +106737,13 @@ async function _scanFileStats(dir, ignores, baseDir = "") {
|
|
|
106676
106737
|
latestFile = file;
|
|
106677
106738
|
}
|
|
106678
106739
|
};
|
|
106740
|
+
const inspectFile = (file) => {
|
|
106741
|
+
try {
|
|
106742
|
+
updateLatest(file_ops_default.statSync(file).mtimeMs, file);
|
|
106743
|
+
} catch (err) {
|
|
106744
|
+
if (err.code !== "ENOENT" && err.code !== "ENOTDIR") throw err;
|
|
106745
|
+
}
|
|
106746
|
+
};
|
|
106679
106747
|
const filter = (file, path, extras) => {
|
|
106680
106748
|
if (ignore(extras.fullFile)) return false;
|
|
106681
106749
|
updateLatest(extras.stat.mtimeMs, extras.fullFile);
|
|
@@ -106683,11 +106751,45 @@ async function _scanFileStats(dir, ignores, baseDir = "") {
|
|
|
106683
106751
|
};
|
|
106684
106752
|
const fullDir = Path.join(baseDir, dir);
|
|
106685
106753
|
updateLatest((await file_ops_default.stat(fullDir)).mtimeMs, fullDir);
|
|
106754
|
+
for (const file of [
|
|
106755
|
+
"package.json",
|
|
106756
|
+
"package-fyn.json",
|
|
106757
|
+
"fyn-lock.yaml",
|
|
106758
|
+
"package-lock.json",
|
|
106759
|
+
"npm-shrinkwrap.json",
|
|
106760
|
+
"yarn.lock",
|
|
106761
|
+
".npmrc",
|
|
106762
|
+
".fynrc",
|
|
106763
|
+
"fynpo.json",
|
|
106764
|
+
"fynpo.config.js",
|
|
106765
|
+
"fynpo.config.json"
|
|
106766
|
+
]) inspectFile(Path.join(fullDir, file));
|
|
106767
|
+
const ruleDirs = [];
|
|
106768
|
+
let ancestor = Path.resolve(fullDir);
|
|
106769
|
+
while (true) {
|
|
106770
|
+
ruleDirs.push(ancestor);
|
|
106771
|
+
if (file_ops_default.existsSync(Path.join(ancestor, ".git"))) break;
|
|
106772
|
+
const parent = Path.dirname(ancestor);
|
|
106773
|
+
if (parent === ancestor) {
|
|
106774
|
+
ruleDirs.length = 1;
|
|
106775
|
+
break;
|
|
106776
|
+
}
|
|
106777
|
+
ancestor = parent;
|
|
106778
|
+
}
|
|
106779
|
+
for (const ruleDir of ruleDirs) {
|
|
106780
|
+
inspectFile(ruleDir);
|
|
106781
|
+
inspectFile(Path.join(ruleDir, ".gitignore"));
|
|
106782
|
+
}
|
|
106686
106783
|
await filterScanDir({
|
|
106687
106784
|
cwd: fullDir,
|
|
106688
106785
|
prependCwd: false,
|
|
106786
|
+
gitignore: (rules) => (0, import_ignore.default)().add(rules),
|
|
106689
106787
|
filter,
|
|
106690
|
-
filterDir:
|
|
106788
|
+
filterDir: (file, path, extras) => {
|
|
106789
|
+
if (!filter(file, path, extras)) return false;
|
|
106790
|
+
inspectFile(Path.join(extras.fullFile, ".gitignore"));
|
|
106791
|
+
return true;
|
|
106792
|
+
},
|
|
106691
106793
|
concurrency: 500,
|
|
106692
106794
|
fullStat: true
|
|
106693
106795
|
});
|
|
@@ -106697,7 +106799,7 @@ async function _scanFileStats(dir, ignores, baseDir = "") {
|
|
|
106697
106799
|
};
|
|
106698
106800
|
}
|
|
106699
106801
|
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), "");
|
|
106802
|
+
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
106803
|
}
|
|
106702
106804
|
|
|
106703
106805
|
//#endregion
|
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.8",
|
|
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",
|