@verdaccio/package-filter 14.0.0-next-9.30
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/LICENSE +21 -0
- package/README.md +277 -0
- package/build/_virtual/_rolldown/runtime.js +23 -0
- package/build/config/parser.d.ts +2 -0
- package/build/config/parser.js +56 -0
- package/build/config/parser.js.map +1 -0
- package/build/config/parser.mjs +54 -0
- package/build/config/parser.mjs.map +1 -0
- package/build/config/types.d.ts +39 -0
- package/build/filtering/matcher.d.ts +8 -0
- package/build/filtering/matcher.js +71 -0
- package/build/filtering/matcher.js.map +1 -0
- package/build/filtering/matcher.mjs +69 -0
- package/build/filtering/matcher.mjs.map +1 -0
- package/build/filtering/packageVersion.d.ts +20 -0
- package/build/filtering/packageVersion.js +129 -0
- package/build/filtering/packageVersion.js.map +1 -0
- package/build/filtering/packageVersion.mjs +127 -0
- package/build/filtering/packageVersion.mjs.map +1 -0
- package/build/filtering/publishDate.d.ts +6 -0
- package/build/filtering/publishDate.js +33 -0
- package/build/filtering/publishDate.js.map +1 -0
- package/build/filtering/publishDate.mjs +31 -0
- package/build/filtering/publishDate.mjs.map +1 -0
- package/build/filtering/types.d.ts +24 -0
- package/build/filtering/types.js +11 -0
- package/build/filtering/types.js.map +1 -0
- package/build/filtering/types.mjs +11 -0
- package/build/filtering/types.mjs.map +1 -0
- package/build/index.d.ts +3 -0
- package/build/index.js +12 -0
- package/build/index.js.map +1 -0
- package/build/index.mjs +7 -0
- package/build/index.mjs.map +1 -0
- package/build/packageFilter.d.ts +10 -0
- package/build/packageFilter.js +80 -0
- package/build/packageFilter.js.map +1 -0
- package/build/packageFilter.mjs +78 -0
- package/build/packageFilter.mjs.map +1 -0
- package/build/utils/jsonUtils.d.ts +1 -0
- package/build/utils/jsonUtils.js +12 -0
- package/build/utils/jsonUtils.js.map +1 -0
- package/build/utils/jsonUtils.mjs +11 -0
- package/build/utils/jsonUtils.mjs.map +1 -0
- package/build/utils/manifestUtils.d.ts +36 -0
- package/build/utils/manifestUtils.js +115 -0
- package/build/utils/manifestUtils.js.map +1 -0
- package/build/utils/manifestUtils.mjs +107 -0
- package/build/utils/manifestUtils.mjs.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matcher.mjs","names":[],"sources":["../../src/filtering/matcher.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { satisfies } from 'semver';\n\nimport type { Manifest } from '@verdaccio/types';\n\nimport type { ParsedRule } from '../config/types';\nimport type { MatchResult } from './types';\nimport { MatchType } from './types';\n\nconst debug = buildDebug('verdaccio:plugin:package-filter:filter');\n\n/**\n * Split a package name into name itself and scope.\n */\nfunction splitName(name: string): { name: string; scope?: string } {\n if (!name) {\n return { name: '' };\n }\n\n const parts = name.split('/');\n\n if (parts.length > 1) {\n return {\n scope: parts[0],\n name: parts[1],\n };\n } else {\n return {\n name: parts[0],\n };\n }\n}\n\n/**\n * Try to find a rule that matches the package.\n * If found, returns the rule and the matched package versions from the manifest.\n */\nexport function matchRules(\n manifest: Manifest,\n rules: Map<string, ParsedRule>\n): MatchResult | undefined {\n const { scope } = splitName(manifest.name);\n if (scope) {\n const rule = rules.get(scope);\n if (rule === 'scope') {\n debug('scope match: %s matched rule for %s', manifest.name, scope);\n return {\n type: MatchType.SCOPE,\n rule,\n scope,\n versions: Object.keys(manifest.versions),\n };\n }\n }\n\n const rule = rules.get(manifest.name);\n if (!rule) {\n // No match\n return undefined;\n }\n\n if (rule === 'package') {\n debug('package match: %s', manifest.name);\n return {\n type: MatchType.PACKAGE,\n rule,\n package: manifest.name,\n versions: Object.keys(manifest.versions),\n };\n }\n\n if (rule === 'scope') {\n throw new Error('Unexpected case - rule for package should never be \"scope\"');\n }\n\n const versionRanges = rule.versions;\n if (versionRanges.length === 0) {\n // No match\n return undefined;\n }\n\n const matchedVersions: string[] = [];\n Object.keys(manifest.versions).forEach((version) => {\n versionRanges.forEach((versionRange) => {\n if (\n satisfies(version, versionRange, {\n includePrerelease: true,\n loose: true,\n })\n ) {\n matchedVersions.push(version);\n }\n });\n });\n\n if (matchedVersions.length > 0) {\n debug(\n 'version match: %s matched %d versions: %o',\n manifest.name,\n matchedVersions.length,\n matchedVersions\n );\n }\n\n return {\n type: MatchType.VERSIONS,\n rule,\n versions: matchedVersions,\n };\n}\n"],"mappings":";;;;AASA,IAAM,QAAQ,WAAW,yCAAyC;;;;AAKlE,SAAS,UAAU,MAAgD;AACjE,KAAI,CAAC,KACH,QAAO,EAAE,MAAM,IAAI;CAGrB,MAAM,QAAQ,KAAK,MAAM,IAAI;AAE7B,KAAI,MAAM,SAAS,EACjB,QAAO;EACL,OAAO,MAAM;EACb,MAAM,MAAM;EACb;KAED,QAAO,EACL,MAAM,MAAM,IACb;;;;;;AAQL,SAAgB,WACd,UACA,OACyB;CACzB,MAAM,EAAE,UAAU,UAAU,SAAS,KAAK;AAC1C,KAAI,OAAO;EACT,MAAM,OAAO,MAAM,IAAI,MAAM;AAC7B,MAAI,SAAS,SAAS;AACpB,SAAM,uCAAuC,SAAS,MAAM,MAAM;AAClE,UAAO;IACL,MAAM,UAAU;IAChB;IACA;IACA,UAAU,OAAO,KAAK,SAAS,SAAS;IACzC;;;CAIL,MAAM,OAAO,MAAM,IAAI,SAAS,KAAK;AACrC,KAAI,CAAC,KAEH;AAGF,KAAI,SAAS,WAAW;AACtB,QAAM,qBAAqB,SAAS,KAAK;AACzC,SAAO;GACL,MAAM,UAAU;GAChB;GACA,SAAS,SAAS;GAClB,UAAU,OAAO,KAAK,SAAS,SAAS;GACzC;;AAGH,KAAI,SAAS,QACX,OAAM,IAAI,MAAM,+DAA6D;CAG/E,MAAM,gBAAgB,KAAK;AAC3B,KAAI,cAAc,WAAW,EAE3B;CAGF,MAAM,kBAA4B,EAAE;AACpC,QAAO,KAAK,SAAS,SAAS,CAAC,SAAS,YAAY;AAClD,gBAAc,SAAS,iBAAiB;AACtC,OACE,UAAU,SAAS,cAAc;IAC/B,mBAAmB;IACnB,OAAO;IACR,CAAC,CAEF,iBAAgB,KAAK,QAAQ;IAE/B;GACF;AAEF,KAAI,gBAAgB,SAAS,EAC3B,OACE,6CACA,SAAS,MACT,gBAAgB,QAChB,gBACD;AAGH,QAAO;EACL,MAAM,UAAU;EAChB;EACA,UAAU;EACX"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Logger, Manifest } from '@verdaccio/types';
|
|
2
|
+
import { ParsedRule } from '../config/types';
|
|
3
|
+
/**
|
|
4
|
+
* Filter out all blocked package versions.
|
|
5
|
+
* If package or scope is blocked, then block all versions.
|
|
6
|
+
*
|
|
7
|
+
* TODO: consider adding a `prerelease` filter option to block/allow
|
|
8
|
+
* prerelease versions independently. Currently prereleases are matched by
|
|
9
|
+
* semver ranges with `includePrerelease: true`, but there's no dedicated toggle.
|
|
10
|
+
*
|
|
11
|
+
* Example config (not yet implemented):
|
|
12
|
+
* block:
|
|
13
|
+
* - package: 'foo'
|
|
14
|
+
* prerelease: true # block 1.0.0-beta.1, 2.0.0-rc.1, keep 1.0.0, 2.0.0
|
|
15
|
+
* - package: 'bar'
|
|
16
|
+
* prerelease: false # block 1.0.0, 2.0.0, keep 1.0.0-beta.1
|
|
17
|
+
*
|
|
18
|
+
* Today the only workaround is using awkward ranges like ">=1.0.0-0 <1.0.0".
|
|
19
|
+
*/
|
|
20
|
+
export declare function filterBlockedVersions(manifest: Manifest, blockRules: Map<string, ParsedRule>, allowRules: Map<string, ParsedRule>, logger: Logger): Manifest;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.js");
|
|
2
|
+
const require_types = require("./types.js");
|
|
3
|
+
const require_matcher = require("./matcher.js");
|
|
4
|
+
let debug = require("debug");
|
|
5
|
+
debug = require_runtime.__toESM(debug);
|
|
6
|
+
let semver = require("semver");
|
|
7
|
+
//#region src/filtering/packageVersion.ts
|
|
8
|
+
var debug$1 = (0, debug.default)("verdaccio:plugin:package-filter:filter");
|
|
9
|
+
/**
|
|
10
|
+
* Filter out all blocked package versions.
|
|
11
|
+
* If package or scope is blocked, then block all versions.
|
|
12
|
+
*
|
|
13
|
+
* TODO: consider adding a `prerelease` filter option to block/allow
|
|
14
|
+
* prerelease versions independently. Currently prereleases are matched by
|
|
15
|
+
* semver ranges with `includePrerelease: true`, but there's no dedicated toggle.
|
|
16
|
+
*
|
|
17
|
+
* Example config (not yet implemented):
|
|
18
|
+
* block:
|
|
19
|
+
* - package: 'foo'
|
|
20
|
+
* prerelease: true # block 1.0.0-beta.1, 2.0.0-rc.1, keep 1.0.0, 2.0.0
|
|
21
|
+
* - package: 'bar'
|
|
22
|
+
* prerelease: false # block 1.0.0, 2.0.0, keep 1.0.0-beta.1
|
|
23
|
+
*
|
|
24
|
+
* Today the only workaround is using awkward ranges like ">=1.0.0-0 <1.0.0".
|
|
25
|
+
*/
|
|
26
|
+
function filterBlockedVersions(manifest, blockRules, allowRules, logger) {
|
|
27
|
+
const allowMatch = require_matcher.matchRules(manifest, allowRules);
|
|
28
|
+
if (allowMatch && (allowMatch.type === require_types.MatchType.SCOPE || allowMatch.type === require_types.MatchType.PACKAGE)) {
|
|
29
|
+
logger.trace({ name: manifest.name }, "package @{name} is allow-listed, skipping block rules");
|
|
30
|
+
return manifest;
|
|
31
|
+
}
|
|
32
|
+
const blockMatch = require_matcher.matchRules(manifest, blockRules);
|
|
33
|
+
if (!blockMatch) return manifest;
|
|
34
|
+
logger.trace({
|
|
35
|
+
name: manifest.name,
|
|
36
|
+
type: blockMatch.type
|
|
37
|
+
}, "block rule matched for @{name} (type: @{type})");
|
|
38
|
+
const whitelistedVersions = allowMatch ? allowMatch.versions : [];
|
|
39
|
+
let blockRule = {
|
|
40
|
+
versions: [new semver.Range("*")],
|
|
41
|
+
strategy: "block"
|
|
42
|
+
};
|
|
43
|
+
if (blockMatch.type === require_types.MatchType.SCOPE) {
|
|
44
|
+
if (whitelistedVersions.length === 0) {
|
|
45
|
+
debug$1("blocking all versions of %s (scope %s blocked)", manifest.name, blockMatch.scope);
|
|
46
|
+
logger.trace({
|
|
47
|
+
name: manifest.name,
|
|
48
|
+
scope: blockMatch.scope
|
|
49
|
+
}, "all versions of @{name} blocked (scope @{scope})");
|
|
50
|
+
return {
|
|
51
|
+
...manifest,
|
|
52
|
+
versions: {},
|
|
53
|
+
readme: `All packages in scope ${blockMatch.scope} are blocked by rule`
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
} else if (blockMatch.type === require_types.MatchType.PACKAGE) {
|
|
57
|
+
if (whitelistedVersions.length === 0) {
|
|
58
|
+
debug$1("blocking all versions of %s (package blocked)", manifest.name);
|
|
59
|
+
logger.trace({ name: manifest.name }, "all versions of @{name} blocked (package rule)");
|
|
60
|
+
return {
|
|
61
|
+
...manifest,
|
|
62
|
+
versions: {},
|
|
63
|
+
readme: `All package versions are blocked by rule`
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
} else blockRule = {
|
|
67
|
+
...blockRule,
|
|
68
|
+
...blockMatch.rule
|
|
69
|
+
};
|
|
70
|
+
const versionRanges = blockRule.versions;
|
|
71
|
+
if (blockRule.strategy === "block") {
|
|
72
|
+
const blockedVersions = blockMatch.versions.filter((v) => !whitelistedVersions.includes(v));
|
|
73
|
+
for (const version of blockedVersions) delete manifest.versions[version];
|
|
74
|
+
if (blockedVersions.length > 0) {
|
|
75
|
+
debug$1("blocked %d versions of %s: %o", blockedVersions.length, manifest.name, blockedVersions);
|
|
76
|
+
logger.trace({
|
|
77
|
+
name: manifest.name,
|
|
78
|
+
count: blockedVersions.length,
|
|
79
|
+
versions: blockedVersions.join(", ")
|
|
80
|
+
}, "@{count} versions of @{name} blocked: @{versions}");
|
|
81
|
+
manifest.readme = (manifest.readme || "") + `\nSome versions(${blockedVersions.length}) of package are blocked by rules: ${versionRanges.map((range) => range.raw)}`;
|
|
82
|
+
}
|
|
83
|
+
return manifest;
|
|
84
|
+
}
|
|
85
|
+
const nonBlockedVersions = { ...manifest.versions };
|
|
86
|
+
const newVersionsMapping = {};
|
|
87
|
+
versionRanges.forEach((versionRange) => {
|
|
88
|
+
const allVersions = Object.keys(nonBlockedVersions);
|
|
89
|
+
let lastNonBlockedVersion = null;
|
|
90
|
+
allVersions.forEach((version) => {
|
|
91
|
+
if (!whitelistedVersions.includes(version) && (0, semver.satisfies)(version, versionRange, {
|
|
92
|
+
includePrerelease: true,
|
|
93
|
+
loose: true
|
|
94
|
+
})) {
|
|
95
|
+
delete nonBlockedVersions[version];
|
|
96
|
+
newVersionsMapping[version] = lastNonBlockedVersion;
|
|
97
|
+
} else lastNonBlockedVersion = version;
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
debug$1("replacing versions for %s: %o", manifest.name, newVersionsMapping);
|
|
101
|
+
const removedVersions = Object.entries(newVersionsMapping).filter(([_, replace]) => replace === null);
|
|
102
|
+
const replacedVersions = Object.entries(newVersionsMapping).filter(([_, replace]) => replace !== null);
|
|
103
|
+
removedVersions.forEach(([version]) => {
|
|
104
|
+
debug$1("no version to replace %s in %s", version, manifest.name);
|
|
105
|
+
logger.trace({
|
|
106
|
+
name: manifest.name,
|
|
107
|
+
version
|
|
108
|
+
}, "version @{version} of @{name} removed (no replacement available)");
|
|
109
|
+
delete manifest.versions[version];
|
|
110
|
+
});
|
|
111
|
+
replacedVersions.forEach(([version, replaceVersion]) => {
|
|
112
|
+
logger.trace({
|
|
113
|
+
name: manifest.name,
|
|
114
|
+
version,
|
|
115
|
+
replaceVersion
|
|
116
|
+
}, "version @{version} of @{name} replaced with @{replaceVersion}");
|
|
117
|
+
manifest.versions[version] = {
|
|
118
|
+
...manifest.versions[replaceVersion],
|
|
119
|
+
version
|
|
120
|
+
};
|
|
121
|
+
});
|
|
122
|
+
if (removedVersions.length > 0) manifest.readme += `\nSome versions of package could not be replaced and thus are fully blocked (${removedVersions.length}): ${removedVersions.map((a) => a[0])}`;
|
|
123
|
+
if (replacedVersions.length > 0) manifest.readme += `\nSome versions of package are replaced by other(${replacedVersions.length}): ${replacedVersions.map((a) => `${a[0]} => ${a[1]}`)}`;
|
|
124
|
+
return manifest;
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
127
|
+
exports.filterBlockedVersions = filterBlockedVersions;
|
|
128
|
+
|
|
129
|
+
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packageVersion.js","names":[],"sources":["../../src/filtering/packageVersion.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { Range, satisfies } from 'semver';\n\nimport type { Logger, Manifest } from '@verdaccio/types';\n\nimport type { ParsedConfigRule, ParsedRule } from '../config/types';\nimport { matchRules } from './matcher';\nimport { MatchType } from './types';\n\nconst debug = buildDebug('verdaccio:plugin:package-filter:filter');\n\n/**\n * Filter out all blocked package versions.\n * If package or scope is blocked, then block all versions.\n *\n * TODO: consider adding a `prerelease` filter option to block/allow\n * prerelease versions independently. Currently prereleases are matched by\n * semver ranges with `includePrerelease: true`, but there's no dedicated toggle.\n *\n * Example config (not yet implemented):\n * block:\n * - package: 'foo'\n * prerelease: true # block 1.0.0-beta.1, 2.0.0-rc.1, keep 1.0.0, 2.0.0\n * - package: 'bar'\n * prerelease: false # block 1.0.0, 2.0.0, keep 1.0.0-beta.1\n *\n * Today the only workaround is using awkward ranges like \">=1.0.0-0 <1.0.0\".\n */\nexport function filterBlockedVersions(\n manifest: Manifest,\n blockRules: Map<string, ParsedRule>,\n allowRules: Map<string, ParsedRule>,\n logger: Logger\n): Manifest {\n const allowMatch = matchRules(manifest, allowRules);\n if (\n allowMatch &&\n (allowMatch.type === MatchType.SCOPE || allowMatch.type === MatchType.PACKAGE)\n ) {\n // An entire scope or package is whitelisted\n logger.trace({ name: manifest.name }, 'package @{name} is allow-listed, skipping block rules');\n return manifest;\n }\n\n const blockMatch = matchRules(manifest, blockRules);\n if (!blockMatch) {\n // No rule is blocking this package\n return manifest;\n }\n\n logger.trace(\n { name: manifest.name, type: blockMatch.type },\n 'block rule matched for @{name} (type: @{type})'\n );\n\n const whitelistedVersions: string[] = allowMatch ? allowMatch.versions : [];\n let blockRule: ParsedConfigRule = {\n versions: [new Range('*')],\n strategy: 'block',\n };\n\n if (blockMatch.type === MatchType.SCOPE) {\n if (whitelistedVersions.length === 0) {\n debug('blocking all versions of %s (scope %s blocked)', manifest.name, blockMatch.scope);\n logger.trace(\n { name: manifest.name, scope: blockMatch.scope },\n 'all versions of @{name} blocked (scope @{scope})'\n );\n return {\n ...manifest,\n versions: {},\n readme: `All packages in scope ${blockMatch.scope} are blocked by rule`,\n };\n }\n } else if (blockMatch.type === MatchType.PACKAGE) {\n if (whitelistedVersions.length === 0) {\n debug('blocking all versions of %s (package blocked)', manifest.name);\n logger.trace({ name: manifest.name }, 'all versions of @{name} blocked (package rule)');\n return {\n ...manifest,\n versions: {},\n readme: `All package versions are blocked by rule`,\n };\n }\n } else {\n blockRule = { ...blockRule, ...blockMatch.rule };\n }\n\n const versionRanges = blockRule.versions;\n\n if (blockRule.strategy === 'block') {\n const blockedVersions = blockMatch.versions.filter((v) => !whitelistedVersions.includes(v));\n for (const version of blockedVersions) {\n delete manifest.versions[version];\n }\n\n if (blockedVersions.length > 0) {\n debug(\n 'blocked %d versions of %s: %o',\n blockedVersions.length,\n manifest.name,\n blockedVersions\n );\n logger.trace(\n {\n name: manifest.name,\n count: blockedVersions.length,\n versions: blockedVersions.join(', '),\n },\n '@{count} versions of @{name} blocked: @{versions}'\n );\n // Add debug info for devs\n manifest.readme =\n (manifest.readme || '') +\n `\\nSome versions(${blockedVersions.length}) of package are blocked by rules: ${versionRanges.map(\n (range) => range.raw\n )}`;\n }\n\n return manifest;\n }\n\n // Process block rule strategy 'replace'.\n // We assume that the order of versions is already sorted.\n const nonBlockedVersions = { ...manifest.versions };\n const newVersionsMapping: Record<string, string | null> = {};\n\n versionRanges.forEach((versionRange) => {\n const allVersions = Object.keys(nonBlockedVersions);\n\n let lastNonBlockedVersion: string | null = null;\n\n allVersions.forEach((version) => {\n if (\n !whitelistedVersions.includes(version) &&\n satisfies(version, versionRange, {\n includePrerelease: true,\n loose: true,\n })\n ) {\n delete nonBlockedVersions[version];\n newVersionsMapping[version] = lastNonBlockedVersion;\n } else {\n lastNonBlockedVersion = version;\n }\n });\n });\n\n debug('replacing versions for %s: %o', manifest.name, newVersionsMapping);\n\n const removedVersions = Object.entries(newVersionsMapping).filter(\n ([_, replace]) => replace === null\n ) as [string, null][];\n const replacedVersions = Object.entries(newVersionsMapping).filter(\n ([_, replace]) => replace !== null\n ) as [string, string][];\n\n removedVersions.forEach(([version]) => {\n debug('no version to replace %s in %s', version, manifest.name);\n logger.trace(\n { name: manifest.name, version },\n 'version @{version} of @{name} removed (no replacement available)'\n );\n delete manifest.versions[version];\n });\n\n replacedVersions.forEach(([version, replaceVersion]) => {\n logger.trace(\n { name: manifest.name, version, replaceVersion },\n 'version @{version} of @{name} replaced with @{replaceVersion}'\n );\n manifest.versions[version] = {\n ...manifest.versions[replaceVersion],\n version,\n };\n });\n\n if (removedVersions.length > 0) {\n manifest.readme +=\n `\\nSome versions of package could not be replaced and thus are fully blocked (${removedVersions.length}):` +\n ` ${removedVersions.map((a) => a[0])}`;\n }\n\n if (replacedVersions.length > 0) {\n manifest.readme +=\n `\\nSome versions of package are replaced by other(${replacedVersions.length}):` +\n ` ${replacedVersions.map((a) => `${a[0]} => ${a[1]}`)}`;\n }\n\n return manifest;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { MatchType } from "./types.mjs";
|
|
2
|
+
import { matchRules } from "./matcher.mjs";
|
|
3
|
+
import buildDebug from "debug";
|
|
4
|
+
import { Range, satisfies } from "semver";
|
|
5
|
+
//#region src/filtering/packageVersion.ts
|
|
6
|
+
var debug = buildDebug("verdaccio:plugin:package-filter:filter");
|
|
7
|
+
/**
|
|
8
|
+
* Filter out all blocked package versions.
|
|
9
|
+
* If package or scope is blocked, then block all versions.
|
|
10
|
+
*
|
|
11
|
+
* TODO: consider adding a `prerelease` filter option to block/allow
|
|
12
|
+
* prerelease versions independently. Currently prereleases are matched by
|
|
13
|
+
* semver ranges with `includePrerelease: true`, but there's no dedicated toggle.
|
|
14
|
+
*
|
|
15
|
+
* Example config (not yet implemented):
|
|
16
|
+
* block:
|
|
17
|
+
* - package: 'foo'
|
|
18
|
+
* prerelease: true # block 1.0.0-beta.1, 2.0.0-rc.1, keep 1.0.0, 2.0.0
|
|
19
|
+
* - package: 'bar'
|
|
20
|
+
* prerelease: false # block 1.0.0, 2.0.0, keep 1.0.0-beta.1
|
|
21
|
+
*
|
|
22
|
+
* Today the only workaround is using awkward ranges like ">=1.0.0-0 <1.0.0".
|
|
23
|
+
*/
|
|
24
|
+
function filterBlockedVersions(manifest, blockRules, allowRules, logger) {
|
|
25
|
+
const allowMatch = matchRules(manifest, allowRules);
|
|
26
|
+
if (allowMatch && (allowMatch.type === MatchType.SCOPE || allowMatch.type === MatchType.PACKAGE)) {
|
|
27
|
+
logger.trace({ name: manifest.name }, "package @{name} is allow-listed, skipping block rules");
|
|
28
|
+
return manifest;
|
|
29
|
+
}
|
|
30
|
+
const blockMatch = matchRules(manifest, blockRules);
|
|
31
|
+
if (!blockMatch) return manifest;
|
|
32
|
+
logger.trace({
|
|
33
|
+
name: manifest.name,
|
|
34
|
+
type: blockMatch.type
|
|
35
|
+
}, "block rule matched for @{name} (type: @{type})");
|
|
36
|
+
const whitelistedVersions = allowMatch ? allowMatch.versions : [];
|
|
37
|
+
let blockRule = {
|
|
38
|
+
versions: [new Range("*")],
|
|
39
|
+
strategy: "block"
|
|
40
|
+
};
|
|
41
|
+
if (blockMatch.type === MatchType.SCOPE) {
|
|
42
|
+
if (whitelistedVersions.length === 0) {
|
|
43
|
+
debug("blocking all versions of %s (scope %s blocked)", manifest.name, blockMatch.scope);
|
|
44
|
+
logger.trace({
|
|
45
|
+
name: manifest.name,
|
|
46
|
+
scope: blockMatch.scope
|
|
47
|
+
}, "all versions of @{name} blocked (scope @{scope})");
|
|
48
|
+
return {
|
|
49
|
+
...manifest,
|
|
50
|
+
versions: {},
|
|
51
|
+
readme: `All packages in scope ${blockMatch.scope} are blocked by rule`
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
} else if (blockMatch.type === MatchType.PACKAGE) {
|
|
55
|
+
if (whitelistedVersions.length === 0) {
|
|
56
|
+
debug("blocking all versions of %s (package blocked)", manifest.name);
|
|
57
|
+
logger.trace({ name: manifest.name }, "all versions of @{name} blocked (package rule)");
|
|
58
|
+
return {
|
|
59
|
+
...manifest,
|
|
60
|
+
versions: {},
|
|
61
|
+
readme: `All package versions are blocked by rule`
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
} else blockRule = {
|
|
65
|
+
...blockRule,
|
|
66
|
+
...blockMatch.rule
|
|
67
|
+
};
|
|
68
|
+
const versionRanges = blockRule.versions;
|
|
69
|
+
if (blockRule.strategy === "block") {
|
|
70
|
+
const blockedVersions = blockMatch.versions.filter((v) => !whitelistedVersions.includes(v));
|
|
71
|
+
for (const version of blockedVersions) delete manifest.versions[version];
|
|
72
|
+
if (blockedVersions.length > 0) {
|
|
73
|
+
debug("blocked %d versions of %s: %o", blockedVersions.length, manifest.name, blockedVersions);
|
|
74
|
+
logger.trace({
|
|
75
|
+
name: manifest.name,
|
|
76
|
+
count: blockedVersions.length,
|
|
77
|
+
versions: blockedVersions.join(", ")
|
|
78
|
+
}, "@{count} versions of @{name} blocked: @{versions}");
|
|
79
|
+
manifest.readme = (manifest.readme || "") + `\nSome versions(${blockedVersions.length}) of package are blocked by rules: ${versionRanges.map((range) => range.raw)}`;
|
|
80
|
+
}
|
|
81
|
+
return manifest;
|
|
82
|
+
}
|
|
83
|
+
const nonBlockedVersions = { ...manifest.versions };
|
|
84
|
+
const newVersionsMapping = {};
|
|
85
|
+
versionRanges.forEach((versionRange) => {
|
|
86
|
+
const allVersions = Object.keys(nonBlockedVersions);
|
|
87
|
+
let lastNonBlockedVersion = null;
|
|
88
|
+
allVersions.forEach((version) => {
|
|
89
|
+
if (!whitelistedVersions.includes(version) && satisfies(version, versionRange, {
|
|
90
|
+
includePrerelease: true,
|
|
91
|
+
loose: true
|
|
92
|
+
})) {
|
|
93
|
+
delete nonBlockedVersions[version];
|
|
94
|
+
newVersionsMapping[version] = lastNonBlockedVersion;
|
|
95
|
+
} else lastNonBlockedVersion = version;
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
debug("replacing versions for %s: %o", manifest.name, newVersionsMapping);
|
|
99
|
+
const removedVersions = Object.entries(newVersionsMapping).filter(([_, replace]) => replace === null);
|
|
100
|
+
const replacedVersions = Object.entries(newVersionsMapping).filter(([_, replace]) => replace !== null);
|
|
101
|
+
removedVersions.forEach(([version]) => {
|
|
102
|
+
debug("no version to replace %s in %s", version, manifest.name);
|
|
103
|
+
logger.trace({
|
|
104
|
+
name: manifest.name,
|
|
105
|
+
version
|
|
106
|
+
}, "version @{version} of @{name} removed (no replacement available)");
|
|
107
|
+
delete manifest.versions[version];
|
|
108
|
+
});
|
|
109
|
+
replacedVersions.forEach(([version, replaceVersion]) => {
|
|
110
|
+
logger.trace({
|
|
111
|
+
name: manifest.name,
|
|
112
|
+
version,
|
|
113
|
+
replaceVersion
|
|
114
|
+
}, "version @{version} of @{name} replaced with @{replaceVersion}");
|
|
115
|
+
manifest.versions[version] = {
|
|
116
|
+
...manifest.versions[replaceVersion],
|
|
117
|
+
version
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
if (removedVersions.length > 0) manifest.readme += `\nSome versions of package could not be replaced and thus are fully blocked (${removedVersions.length}): ${removedVersions.map((a) => a[0])}`;
|
|
121
|
+
if (replacedVersions.length > 0) manifest.readme += `\nSome versions of package are replaced by other(${replacedVersions.length}): ${replacedVersions.map((a) => `${a[0]} => ${a[1]}`)}`;
|
|
122
|
+
return manifest;
|
|
123
|
+
}
|
|
124
|
+
//#endregion
|
|
125
|
+
export { filterBlockedVersions };
|
|
126
|
+
|
|
127
|
+
//# sourceMappingURL=packageVersion.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packageVersion.mjs","names":[],"sources":["../../src/filtering/packageVersion.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { Range, satisfies } from 'semver';\n\nimport type { Logger, Manifest } from '@verdaccio/types';\n\nimport type { ParsedConfigRule, ParsedRule } from '../config/types';\nimport { matchRules } from './matcher';\nimport { MatchType } from './types';\n\nconst debug = buildDebug('verdaccio:plugin:package-filter:filter');\n\n/**\n * Filter out all blocked package versions.\n * If package or scope is blocked, then block all versions.\n *\n * TODO: consider adding a `prerelease` filter option to block/allow\n * prerelease versions independently. Currently prereleases are matched by\n * semver ranges with `includePrerelease: true`, but there's no dedicated toggle.\n *\n * Example config (not yet implemented):\n * block:\n * - package: 'foo'\n * prerelease: true # block 1.0.0-beta.1, 2.0.0-rc.1, keep 1.0.0, 2.0.0\n * - package: 'bar'\n * prerelease: false # block 1.0.0, 2.0.0, keep 1.0.0-beta.1\n *\n * Today the only workaround is using awkward ranges like \">=1.0.0-0 <1.0.0\".\n */\nexport function filterBlockedVersions(\n manifest: Manifest,\n blockRules: Map<string, ParsedRule>,\n allowRules: Map<string, ParsedRule>,\n logger: Logger\n): Manifest {\n const allowMatch = matchRules(manifest, allowRules);\n if (\n allowMatch &&\n (allowMatch.type === MatchType.SCOPE || allowMatch.type === MatchType.PACKAGE)\n ) {\n // An entire scope or package is whitelisted\n logger.trace({ name: manifest.name }, 'package @{name} is allow-listed, skipping block rules');\n return manifest;\n }\n\n const blockMatch = matchRules(manifest, blockRules);\n if (!blockMatch) {\n // No rule is blocking this package\n return manifest;\n }\n\n logger.trace(\n { name: manifest.name, type: blockMatch.type },\n 'block rule matched for @{name} (type: @{type})'\n );\n\n const whitelistedVersions: string[] = allowMatch ? allowMatch.versions : [];\n let blockRule: ParsedConfigRule = {\n versions: [new Range('*')],\n strategy: 'block',\n };\n\n if (blockMatch.type === MatchType.SCOPE) {\n if (whitelistedVersions.length === 0) {\n debug('blocking all versions of %s (scope %s blocked)', manifest.name, blockMatch.scope);\n logger.trace(\n { name: manifest.name, scope: blockMatch.scope },\n 'all versions of @{name} blocked (scope @{scope})'\n );\n return {\n ...manifest,\n versions: {},\n readme: `All packages in scope ${blockMatch.scope} are blocked by rule`,\n };\n }\n } else if (blockMatch.type === MatchType.PACKAGE) {\n if (whitelistedVersions.length === 0) {\n debug('blocking all versions of %s (package blocked)', manifest.name);\n logger.trace({ name: manifest.name }, 'all versions of @{name} blocked (package rule)');\n return {\n ...manifest,\n versions: {},\n readme: `All package versions are blocked by rule`,\n };\n }\n } else {\n blockRule = { ...blockRule, ...blockMatch.rule };\n }\n\n const versionRanges = blockRule.versions;\n\n if (blockRule.strategy === 'block') {\n const blockedVersions = blockMatch.versions.filter((v) => !whitelistedVersions.includes(v));\n for (const version of blockedVersions) {\n delete manifest.versions[version];\n }\n\n if (blockedVersions.length > 0) {\n debug(\n 'blocked %d versions of %s: %o',\n blockedVersions.length,\n manifest.name,\n blockedVersions\n );\n logger.trace(\n {\n name: manifest.name,\n count: blockedVersions.length,\n versions: blockedVersions.join(', '),\n },\n '@{count} versions of @{name} blocked: @{versions}'\n );\n // Add debug info for devs\n manifest.readme =\n (manifest.readme || '') +\n `\\nSome versions(${blockedVersions.length}) of package are blocked by rules: ${versionRanges.map(\n (range) => range.raw\n )}`;\n }\n\n return manifest;\n }\n\n // Process block rule strategy 'replace'.\n // We assume that the order of versions is already sorted.\n const nonBlockedVersions = { ...manifest.versions };\n const newVersionsMapping: Record<string, string | null> = {};\n\n versionRanges.forEach((versionRange) => {\n const allVersions = Object.keys(nonBlockedVersions);\n\n let lastNonBlockedVersion: string | null = null;\n\n allVersions.forEach((version) => {\n if (\n !whitelistedVersions.includes(version) &&\n satisfies(version, versionRange, {\n includePrerelease: true,\n loose: true,\n })\n ) {\n delete nonBlockedVersions[version];\n newVersionsMapping[version] = lastNonBlockedVersion;\n } else {\n lastNonBlockedVersion = version;\n }\n });\n });\n\n debug('replacing versions for %s: %o', manifest.name, newVersionsMapping);\n\n const removedVersions = Object.entries(newVersionsMapping).filter(\n ([_, replace]) => replace === null\n ) as [string, null][];\n const replacedVersions = Object.entries(newVersionsMapping).filter(\n ([_, replace]) => replace !== null\n ) as [string, string][];\n\n removedVersions.forEach(([version]) => {\n debug('no version to replace %s in %s', version, manifest.name);\n logger.trace(\n { name: manifest.name, version },\n 'version @{version} of @{name} removed (no replacement available)'\n );\n delete manifest.versions[version];\n });\n\n replacedVersions.forEach(([version, replaceVersion]) => {\n logger.trace(\n { name: manifest.name, version, replaceVersion },\n 'version @{version} of @{name} replaced with @{replaceVersion}'\n );\n manifest.versions[version] = {\n ...manifest.versions[replaceVersion],\n version,\n };\n });\n\n if (removedVersions.length > 0) {\n manifest.readme +=\n `\\nSome versions of package could not be replaced and thus are fully blocked (${removedVersions.length}):` +\n ` ${removedVersions.map((a) => a[0])}`;\n }\n\n if (replacedVersions.length > 0) {\n manifest.readme +=\n `\\nSome versions of package are replaced by other(${replacedVersions.length}):` +\n ` ${replacedVersions.map((a) => `${a[0]} => ${a[1]}`)}`;\n }\n\n return manifest;\n}\n"],"mappings":";;;;;AASA,IAAM,QAAQ,WAAW,yCAAyC;;;;;;;;;;;;;;;;;;AAmBlE,SAAgB,sBACd,UACA,YACA,YACA,QACU;CACV,MAAM,aAAa,WAAW,UAAU,WAAW;AACnD,KACE,eACC,WAAW,SAAS,UAAU,SAAS,WAAW,SAAS,UAAU,UACtE;AAEA,SAAO,MAAM,EAAE,MAAM,SAAS,MAAM,EAAE,wDAAwD;AAC9F,SAAO;;CAGT,MAAM,aAAa,WAAW,UAAU,WAAW;AACnD,KAAI,CAAC,WAEH,QAAO;AAGT,QAAO,MACL;EAAE,MAAM,SAAS;EAAM,MAAM,WAAW;EAAM,EAC9C,iDACD;CAED,MAAM,sBAAgC,aAAa,WAAW,WAAW,EAAE;CAC3E,IAAI,YAA8B;EAChC,UAAU,CAAC,IAAI,MAAM,IAAI,CAAC;EAC1B,UAAU;EACX;AAED,KAAI,WAAW,SAAS,UAAU;MAC5B,oBAAoB,WAAW,GAAG;AACpC,SAAM,kDAAkD,SAAS,MAAM,WAAW,MAAM;AACxF,UAAO,MACL;IAAE,MAAM,SAAS;IAAM,OAAO,WAAW;IAAO,EAChD,mDACD;AACD,UAAO;IACL,GAAG;IACH,UAAU,EAAE;IACZ,QAAQ,yBAAyB,WAAW,MAAM;IACnD;;YAEM,WAAW,SAAS,UAAU;MACnC,oBAAoB,WAAW,GAAG;AACpC,SAAM,iDAAiD,SAAS,KAAK;AACrE,UAAO,MAAM,EAAE,MAAM,SAAS,MAAM,EAAE,iDAAiD;AACvF,UAAO;IACL,GAAG;IACH,UAAU,EAAE;IACZ,QAAQ;IACT;;OAGH,aAAY;EAAE,GAAG;EAAW,GAAG,WAAW;EAAM;CAGlD,MAAM,gBAAgB,UAAU;AAEhC,KAAI,UAAU,aAAa,SAAS;EAClC,MAAM,kBAAkB,WAAW,SAAS,QAAQ,MAAM,CAAC,oBAAoB,SAAS,EAAE,CAAC;AAC3F,OAAK,MAAM,WAAW,gBACpB,QAAO,SAAS,SAAS;AAG3B,MAAI,gBAAgB,SAAS,GAAG;AAC9B,SACE,iCACA,gBAAgB,QAChB,SAAS,MACT,gBACD;AACD,UAAO,MACL;IACE,MAAM,SAAS;IACf,OAAO,gBAAgB;IACvB,UAAU,gBAAgB,KAAK,KAAK;IACrC,EACD,oDACD;AAED,YAAS,UACN,SAAS,UAAU,MACpB,mBAAmB,gBAAgB,OAAO,qCAAqC,cAAc,KAC1F,UAAU,MAAM,IAClB;;AAGL,SAAO;;CAKT,MAAM,qBAAqB,EAAE,GAAG,SAAS,UAAU;CACnD,MAAM,qBAAoD,EAAE;AAE5D,eAAc,SAAS,iBAAiB;EACtC,MAAM,cAAc,OAAO,KAAK,mBAAmB;EAEnD,IAAI,wBAAuC;AAE3C,cAAY,SAAS,YAAY;AAC/B,OACE,CAAC,oBAAoB,SAAS,QAAQ,IACtC,UAAU,SAAS,cAAc;IAC/B,mBAAmB;IACnB,OAAO;IACR,CAAC,EACF;AACA,WAAO,mBAAmB;AAC1B,uBAAmB,WAAW;SAE9B,yBAAwB;IAE1B;GACF;AAEF,OAAM,iCAAiC,SAAS,MAAM,mBAAmB;CAEzE,MAAM,kBAAkB,OAAO,QAAQ,mBAAmB,CAAC,QACxD,CAAC,GAAG,aAAa,YAAY,KAC/B;CACD,MAAM,mBAAmB,OAAO,QAAQ,mBAAmB,CAAC,QACzD,CAAC,GAAG,aAAa,YAAY,KAC/B;AAED,iBAAgB,SAAS,CAAC,aAAa;AACrC,QAAM,kCAAkC,SAAS,SAAS,KAAK;AAC/D,SAAO,MACL;GAAE,MAAM,SAAS;GAAM;GAAS,EAChC,mEACD;AACD,SAAO,SAAS,SAAS;GACzB;AAEF,kBAAiB,SAAS,CAAC,SAAS,oBAAoB;AACtD,SAAO,MACL;GAAE,MAAM,SAAS;GAAM;GAAS;GAAgB,EAChD,gEACD;AACD,WAAS,SAAS,WAAW;GAC3B,GAAG,SAAS,SAAS;GACrB;GACD;GACD;AAEF,KAAI,gBAAgB,SAAS,EAC3B,UAAS,UACP,gFAAgF,gBAAgB,OAAO,KACnG,gBAAgB,KAAK,MAAM,EAAE,GAAG;AAGxC,KAAI,iBAAiB,SAAS,EAC5B,UAAS,UACP,oDAAoD,iBAAiB,OAAO,KACxE,iBAAiB,KAAK,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,KAAK;AAGzD,QAAO"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Manifest } from '@verdaccio/types';
|
|
2
|
+
import { ParsedRule } from '../config/types';
|
|
3
|
+
/**
|
|
4
|
+
* Filter out all package versions that were published after dateThreshold.
|
|
5
|
+
*/
|
|
6
|
+
export declare function filterVersionsByPublishDate(manifest: Manifest, dateThreshold: Date, allowRules: Map<string, ParsedRule>): Manifest;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.js");
|
|
2
|
+
const require_types = require("./types.js");
|
|
3
|
+
const require_matcher = require("./matcher.js");
|
|
4
|
+
let debug = require("debug");
|
|
5
|
+
debug = require_runtime.__toESM(debug);
|
|
6
|
+
//#region src/filtering/publishDate.ts
|
|
7
|
+
var debug$1 = (0, debug.default)("verdaccio:plugin:package-filter:filter");
|
|
8
|
+
/**
|
|
9
|
+
* Filter out all package versions that were published after dateThreshold.
|
|
10
|
+
*/
|
|
11
|
+
function filterVersionsByPublishDate(manifest, dateThreshold, allowRules) {
|
|
12
|
+
const allowMatch = require_matcher.matchRules(manifest, allowRules);
|
|
13
|
+
if (allowMatch && (allowMatch.type === require_types.MatchType.SCOPE || allowMatch.type === require_types.MatchType.PACKAGE)) return manifest;
|
|
14
|
+
const { versions, time, name } = manifest;
|
|
15
|
+
if (!time) throw new TypeError(`Time of publication was not provided for package ${name}`);
|
|
16
|
+
const whitelistedVersions = allowMatch ? allowMatch.versions : [];
|
|
17
|
+
const clearVersions = [];
|
|
18
|
+
Object.keys(versions).forEach((version) => {
|
|
19
|
+
if (whitelistedVersions.includes(version)) return;
|
|
20
|
+
const publishTime = time[version];
|
|
21
|
+
if (!publishTime) throw new TypeError(`Time of publication was not provided for package ${name}, version ${version}`);
|
|
22
|
+
if (new Date(publishTime) > dateThreshold) clearVersions.push(version);
|
|
23
|
+
});
|
|
24
|
+
clearVersions.forEach((version) => {
|
|
25
|
+
delete manifest.versions[version];
|
|
26
|
+
});
|
|
27
|
+
if (clearVersions.length > 0) debug$1("date filter removed %d versions from %s: %o", clearVersions.length, manifest.name, clearVersions);
|
|
28
|
+
return manifest;
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
exports.filterVersionsByPublishDate = filterVersionsByPublishDate;
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=publishDate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publishDate.js","names":[],"sources":["../../src/filtering/publishDate.ts"],"sourcesContent":["import buildDebug from 'debug';\n\nimport type { Manifest } from '@verdaccio/types';\n\nimport type { ParsedRule } from '../config/types';\nimport { matchRules } from './matcher';\nimport { MatchType } from './types';\n\nconst debug = buildDebug('verdaccio:plugin:package-filter:filter');\n\n/**\n * Filter out all package versions that were published after dateThreshold.\n */\nexport function filterVersionsByPublishDate(\n manifest: Manifest,\n dateThreshold: Date,\n allowRules: Map<string, ParsedRule>\n): Manifest {\n const allowMatch = matchRules(manifest, allowRules);\n if (\n allowMatch &&\n (allowMatch.type === MatchType.SCOPE || allowMatch.type === MatchType.PACKAGE)\n ) {\n // An entire scope or package is whitelisted\n return manifest;\n }\n\n const { versions, time, name } = manifest;\n\n if (!time) {\n throw new TypeError(`Time of publication was not provided for package ${name}`);\n }\n\n const whitelistedVersions: string[] = allowMatch ? allowMatch.versions : [];\n const clearVersions: string[] = [];\n\n Object.keys(versions).forEach((version) => {\n if (whitelistedVersions.includes(version)) {\n return;\n }\n\n const publishTime = time[version];\n\n if (!publishTime) {\n throw new TypeError(\n `Time of publication was not provided for package ${name}, version ${version}`\n );\n }\n\n if (new Date(publishTime) > dateThreshold) {\n // clear untrusted version\n clearVersions.push(version);\n }\n });\n\n // delete version from versions\n clearVersions.forEach((version) => {\n delete manifest.versions[version];\n });\n\n if (clearVersions.length > 0) {\n debug(\n 'date filter removed %d versions from %s: %o',\n clearVersions.length,\n manifest.name,\n clearVersions\n );\n }\n\n return manifest;\n}\n"],"mappings":";;;;;;AAQA,IAAM,WAAA,GAAA,MAAA,SAAmB,yCAAyC;;;;AAKlE,SAAgB,4BACd,UACA,eACA,YACU;CACV,MAAM,aAAa,gBAAA,WAAW,UAAU,WAAW;AACnD,KACE,eACC,WAAW,SAAS,cAAA,UAAU,SAAS,WAAW,SAAS,cAAA,UAAU,SAGtE,QAAO;CAGT,MAAM,EAAE,UAAU,MAAM,SAAS;AAEjC,KAAI,CAAC,KACH,OAAM,IAAI,UAAU,oDAAoD,OAAO;CAGjF,MAAM,sBAAgC,aAAa,WAAW,WAAW,EAAE;CAC3E,MAAM,gBAA0B,EAAE;AAElC,QAAO,KAAK,SAAS,CAAC,SAAS,YAAY;AACzC,MAAI,oBAAoB,SAAS,QAAQ,CACvC;EAGF,MAAM,cAAc,KAAK;AAEzB,MAAI,CAAC,YACH,OAAM,IAAI,UACR,oDAAoD,KAAK,YAAY,UACtE;AAGH,MAAI,IAAI,KAAK,YAAY,GAAG,cAE1B,eAAc,KAAK,QAAQ;GAE7B;AAGF,eAAc,SAAS,YAAY;AACjC,SAAO,SAAS,SAAS;GACzB;AAEF,KAAI,cAAc,SAAS,EACzB,SACE,+CACA,cAAc,QACd,SAAS,MACT,cACD;AAGH,QAAO"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { MatchType } from "./types.mjs";
|
|
2
|
+
import { matchRules } from "./matcher.mjs";
|
|
3
|
+
import buildDebug from "debug";
|
|
4
|
+
//#region src/filtering/publishDate.ts
|
|
5
|
+
var debug = buildDebug("verdaccio:plugin:package-filter:filter");
|
|
6
|
+
/**
|
|
7
|
+
* Filter out all package versions that were published after dateThreshold.
|
|
8
|
+
*/
|
|
9
|
+
function filterVersionsByPublishDate(manifest, dateThreshold, allowRules) {
|
|
10
|
+
const allowMatch = matchRules(manifest, allowRules);
|
|
11
|
+
if (allowMatch && (allowMatch.type === MatchType.SCOPE || allowMatch.type === MatchType.PACKAGE)) return manifest;
|
|
12
|
+
const { versions, time, name } = manifest;
|
|
13
|
+
if (!time) throw new TypeError(`Time of publication was not provided for package ${name}`);
|
|
14
|
+
const whitelistedVersions = allowMatch ? allowMatch.versions : [];
|
|
15
|
+
const clearVersions = [];
|
|
16
|
+
Object.keys(versions).forEach((version) => {
|
|
17
|
+
if (whitelistedVersions.includes(version)) return;
|
|
18
|
+
const publishTime = time[version];
|
|
19
|
+
if (!publishTime) throw new TypeError(`Time of publication was not provided for package ${name}, version ${version}`);
|
|
20
|
+
if (new Date(publishTime) > dateThreshold) clearVersions.push(version);
|
|
21
|
+
});
|
|
22
|
+
clearVersions.forEach((version) => {
|
|
23
|
+
delete manifest.versions[version];
|
|
24
|
+
});
|
|
25
|
+
if (clearVersions.length > 0) debug("date filter removed %d versions from %s: %o", clearVersions.length, manifest.name, clearVersions);
|
|
26
|
+
return manifest;
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { filterVersionsByPublishDate };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=publishDate.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publishDate.mjs","names":[],"sources":["../../src/filtering/publishDate.ts"],"sourcesContent":["import buildDebug from 'debug';\n\nimport type { Manifest } from '@verdaccio/types';\n\nimport type { ParsedRule } from '../config/types';\nimport { matchRules } from './matcher';\nimport { MatchType } from './types';\n\nconst debug = buildDebug('verdaccio:plugin:package-filter:filter');\n\n/**\n * Filter out all package versions that were published after dateThreshold.\n */\nexport function filterVersionsByPublishDate(\n manifest: Manifest,\n dateThreshold: Date,\n allowRules: Map<string, ParsedRule>\n): Manifest {\n const allowMatch = matchRules(manifest, allowRules);\n if (\n allowMatch &&\n (allowMatch.type === MatchType.SCOPE || allowMatch.type === MatchType.PACKAGE)\n ) {\n // An entire scope or package is whitelisted\n return manifest;\n }\n\n const { versions, time, name } = manifest;\n\n if (!time) {\n throw new TypeError(`Time of publication was not provided for package ${name}`);\n }\n\n const whitelistedVersions: string[] = allowMatch ? allowMatch.versions : [];\n const clearVersions: string[] = [];\n\n Object.keys(versions).forEach((version) => {\n if (whitelistedVersions.includes(version)) {\n return;\n }\n\n const publishTime = time[version];\n\n if (!publishTime) {\n throw new TypeError(\n `Time of publication was not provided for package ${name}, version ${version}`\n );\n }\n\n if (new Date(publishTime) > dateThreshold) {\n // clear untrusted version\n clearVersions.push(version);\n }\n });\n\n // delete version from versions\n clearVersions.forEach((version) => {\n delete manifest.versions[version];\n });\n\n if (clearVersions.length > 0) {\n debug(\n 'date filter removed %d versions from %s: %o',\n clearVersions.length,\n manifest.name,\n clearVersions\n );\n }\n\n return manifest;\n}\n"],"mappings":";;;;AAQA,IAAM,QAAQ,WAAW,yCAAyC;;;;AAKlE,SAAgB,4BACd,UACA,eACA,YACU;CACV,MAAM,aAAa,WAAW,UAAU,WAAW;AACnD,KACE,eACC,WAAW,SAAS,UAAU,SAAS,WAAW,SAAS,UAAU,SAGtE,QAAO;CAGT,MAAM,EAAE,UAAU,MAAM,SAAS;AAEjC,KAAI,CAAC,KACH,OAAM,IAAI,UAAU,oDAAoD,OAAO;CAGjF,MAAM,sBAAgC,aAAa,WAAW,WAAW,EAAE;CAC3E,MAAM,gBAA0B,EAAE;AAElC,QAAO,KAAK,SAAS,CAAC,SAAS,YAAY;AACzC,MAAI,oBAAoB,SAAS,QAAQ,CACvC;EAGF,MAAM,cAAc,KAAK;AAEzB,MAAI,CAAC,YACH,OAAM,IAAI,UACR,oDAAoD,KAAK,YAAY,UACtE;AAGH,MAAI,IAAI,KAAK,YAAY,GAAG,cAE1B,eAAc,KAAK,QAAQ;GAE7B;AAGF,eAAc,SAAS,YAAY;AACjC,SAAO,SAAS,SAAS;GACzB;AAEF,KAAI,cAAc,SAAS,EACzB,OACE,+CACA,cAAc,QACd,SAAS,MACT,cACD;AAGH,QAAO"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { PackageScopeLevel, ParsedConfigRule } from '../config/types';
|
|
2
|
+
export declare enum MatchType {
|
|
3
|
+
SCOPE = "scope",
|
|
4
|
+
PACKAGE = "package",
|
|
5
|
+
VERSIONS = "versions"
|
|
6
|
+
}
|
|
7
|
+
export interface MatchResultVersions {
|
|
8
|
+
versions: string[];
|
|
9
|
+
}
|
|
10
|
+
export interface MatchScopeResult extends MatchResultVersions {
|
|
11
|
+
type: MatchType.SCOPE;
|
|
12
|
+
rule: PackageScopeLevel;
|
|
13
|
+
scope: string;
|
|
14
|
+
}
|
|
15
|
+
export interface MatchPackageResult extends MatchResultVersions {
|
|
16
|
+
type: MatchType.PACKAGE;
|
|
17
|
+
rule: PackageScopeLevel;
|
|
18
|
+
package: string;
|
|
19
|
+
}
|
|
20
|
+
export interface MatchVersionsResult extends MatchResultVersions {
|
|
21
|
+
type: MatchType.VERSIONS;
|
|
22
|
+
rule: ParsedConfigRule;
|
|
23
|
+
}
|
|
24
|
+
export type MatchResult = MatchScopeResult | MatchPackageResult | MatchVersionsResult;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/filtering/types.ts
|
|
2
|
+
var MatchType = /* @__PURE__ */ function(MatchType) {
|
|
3
|
+
MatchType["SCOPE"] = "scope";
|
|
4
|
+
MatchType["PACKAGE"] = "package";
|
|
5
|
+
MatchType["VERSIONS"] = "versions";
|
|
6
|
+
return MatchType;
|
|
7
|
+
}({});
|
|
8
|
+
//#endregion
|
|
9
|
+
exports.MatchType = MatchType;
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":["../../src/filtering/types.ts"],"sourcesContent":["import { PackageScopeLevel, ParsedConfigRule } from '../config/types';\n\nexport enum MatchType {\n SCOPE = 'scope',\n PACKAGE = 'package',\n VERSIONS = 'versions',\n}\n\nexport interface MatchResultVersions {\n versions: string[];\n}\n\nexport interface MatchScopeResult extends MatchResultVersions {\n type: MatchType.SCOPE;\n rule: PackageScopeLevel;\n scope: string;\n}\n\nexport interface MatchPackageResult extends MatchResultVersions {\n type: MatchType.PACKAGE;\n rule: PackageScopeLevel;\n package: string;\n}\n\nexport interface MatchVersionsResult extends MatchResultVersions {\n type: MatchType.VERSIONS;\n rule: ParsedConfigRule;\n}\n\nexport type MatchResult = MatchScopeResult | MatchPackageResult | MatchVersionsResult;\n"],"mappings":";AAEA,IAAY,YAAL,yBAAA,WAAA;AACL,WAAA,WAAA;AACA,WAAA,aAAA;AACA,WAAA,cAAA;;KACD"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/filtering/types.ts
|
|
2
|
+
var MatchType = /* @__PURE__ */ function(MatchType) {
|
|
3
|
+
MatchType["SCOPE"] = "scope";
|
|
4
|
+
MatchType["PACKAGE"] = "package";
|
|
5
|
+
MatchType["VERSIONS"] = "versions";
|
|
6
|
+
return MatchType;
|
|
7
|
+
}({});
|
|
8
|
+
//#endregion
|
|
9
|
+
export { MatchType };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=types.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.mjs","names":[],"sources":["../../src/filtering/types.ts"],"sourcesContent":["import { PackageScopeLevel, ParsedConfigRule } from '../config/types';\n\nexport enum MatchType {\n SCOPE = 'scope',\n PACKAGE = 'package',\n VERSIONS = 'versions',\n}\n\nexport interface MatchResultVersions {\n versions: string[];\n}\n\nexport interface MatchScopeResult extends MatchResultVersions {\n type: MatchType.SCOPE;\n rule: PackageScopeLevel;\n scope: string;\n}\n\nexport interface MatchPackageResult extends MatchResultVersions {\n type: MatchType.PACKAGE;\n rule: PackageScopeLevel;\n package: string;\n}\n\nexport interface MatchVersionsResult extends MatchResultVersions {\n type: MatchType.VERSIONS;\n rule: ParsedConfigRule;\n}\n\nexport type MatchResult = MatchScopeResult | MatchPackageResult | MatchVersionsResult;\n"],"mappings":";AAEA,IAAY,YAAL,yBAAA,WAAA;AACL,WAAA,WAAA;AACA,WAAA,aAAA;AACA,WAAA,cAAA;;KACD"}
|
package/build/index.d.ts
ADDED
package/build/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Object.defineProperties(exports, {
|
|
2
|
+
__esModule: { value: true },
|
|
3
|
+
[Symbol.toStringTag]: { value: "Module" }
|
|
4
|
+
});
|
|
5
|
+
const require_packageFilter = require("./packageFilter.js");
|
|
6
|
+
//#region src/index.ts
|
|
7
|
+
var src_default = require_packageFilter.PackageFilterPlugin;
|
|
8
|
+
//#endregion
|
|
9
|
+
exports.PackageFilterPlugin = require_packageFilter.PackageFilterPlugin;
|
|
10
|
+
exports.default = src_default;
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { PackageFilterPlugin } from './packageFilter';\n\nexport { PackageFilterPlugin };\nexport default PackageFilterPlugin;\n"],"mappings":";;;;;;AAGA,IAAA,cAAe,sBAAA"}
|
package/build/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { PackageFilterPlugin } from './packageFilter';\n\nexport { PackageFilterPlugin };\nexport default PackageFilterPlugin;\n"],"mappings":";;AAGA,IAAA,cAAe"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { pluginUtils } from '@verdaccio/core';
|
|
2
|
+
import { Logger, Manifest } from '@verdaccio/types';
|
|
3
|
+
import { PluginConfig } from './config/types';
|
|
4
|
+
export declare class PackageFilterPlugin extends pluginUtils.Plugin<PluginConfig> implements pluginUtils.ManifestFilter<PluginConfig> {
|
|
5
|
+
readonly config: PluginConfig;
|
|
6
|
+
private readonly parsedConfig;
|
|
7
|
+
protected readonly logger: Logger;
|
|
8
|
+
constructor(config: PluginConfig, options: pluginUtils.PluginOptions);
|
|
9
|
+
filter_metadata(manifest: Readonly<Manifest>): Promise<Manifest>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const require_runtime = require("./_virtual/_rolldown/runtime.js");
|
|
2
|
+
const require_parser = require("./config/parser.js");
|
|
3
|
+
const require_packageVersion = require("./filtering/packageVersion.js");
|
|
4
|
+
const require_publishDate = require("./filtering/publishDate.js");
|
|
5
|
+
const require_jsonUtils = require("./utils/jsonUtils.js");
|
|
6
|
+
const require_manifestUtils = require("./utils/manifestUtils.js");
|
|
7
|
+
let debug = require("debug");
|
|
8
|
+
debug = require_runtime.__toESM(debug);
|
|
9
|
+
let _verdaccio_core = require("@verdaccio/core");
|
|
10
|
+
//#region src/packageFilter.ts
|
|
11
|
+
var debug$1 = (0, debug.default)("verdaccio:plugin:package-filter");
|
|
12
|
+
var PackageFilterPlugin = class extends _verdaccio_core.pluginUtils.Plugin {
|
|
13
|
+
config;
|
|
14
|
+
parsedConfig;
|
|
15
|
+
logger;
|
|
16
|
+
constructor(config, options) {
|
|
17
|
+
super(config, options);
|
|
18
|
+
this.config = config ?? {};
|
|
19
|
+
this.logger = options.logger;
|
|
20
|
+
this.parsedConfig = require_parser.parseConfig(this.config);
|
|
21
|
+
debug$1("plugin loaded: block rules: %d, allow rules: %d", this.parsedConfig.blockRules.size, this.parsedConfig.allowRules.size);
|
|
22
|
+
this.logger.debug({ config: JSON.stringify(this.parsedConfig, require_jsonUtils.jsonLogReplacer) }, "package-filter loaded with config: @{config}");
|
|
23
|
+
this.logger.trace({
|
|
24
|
+
blockRules: this.parsedConfig.blockRules.size,
|
|
25
|
+
allowRules: this.parsedConfig.allowRules.size
|
|
26
|
+
}, "package-filter plugin initialized: @{blockRules} block rules, @{allowRules} allow rules");
|
|
27
|
+
if (this.parsedConfig.dateThreshold) {
|
|
28
|
+
debug$1("date threshold: %s", this.parsedConfig.dateThreshold.toISOString());
|
|
29
|
+
this.logger.trace({ dateThreshold: this.parsedConfig.dateThreshold.toISOString() }, "package-filter date threshold: @{dateThreshold}");
|
|
30
|
+
}
|
|
31
|
+
if (this.parsedConfig.minAgeMs) {
|
|
32
|
+
const minAgeDays = this.parsedConfig.minAgeMs / (1440 * 60 * 1e3);
|
|
33
|
+
debug$1("min age: %d days", minAgeDays);
|
|
34
|
+
this.logger.trace({ minAgeDays }, "package-filter min age: @{minAgeDays} days");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async filter_metadata(manifest) {
|
|
38
|
+
const { dateThreshold, minAgeMs, blockRules, allowRules } = this.parsedConfig;
|
|
39
|
+
const versionCount = Object.keys(manifest.versions ?? {}).length;
|
|
40
|
+
debug$1("filtering manifest for %s (%d versions)", manifest.name, versionCount);
|
|
41
|
+
this.logger.trace({
|
|
42
|
+
name: manifest.name,
|
|
43
|
+
versionCount
|
|
44
|
+
}, "package-filter processing @{name} (@{versionCount} versions)");
|
|
45
|
+
let newManifest = require_manifestUtils.getManifestClone(manifest);
|
|
46
|
+
if (blockRules.size > 0) newManifest = require_packageVersion.filterBlockedVersions(newManifest, blockRules, allowRules, this.logger);
|
|
47
|
+
let earliestDateThreshold = null;
|
|
48
|
+
if (minAgeMs) earliestDateThreshold = new Date(Date.now() - minAgeMs);
|
|
49
|
+
if (dateThreshold && (!earliestDateThreshold || dateThreshold < earliestDateThreshold)) earliestDateThreshold = dateThreshold;
|
|
50
|
+
if (earliestDateThreshold) {
|
|
51
|
+
debug$1("applying date filter for %s, threshold: %s", manifest.name, earliestDateThreshold.toISOString());
|
|
52
|
+
this.logger.trace({
|
|
53
|
+
name: manifest.name,
|
|
54
|
+
threshold: earliestDateThreshold.toISOString()
|
|
55
|
+
}, "applying date filter for @{name}, cutoff: @{threshold}");
|
|
56
|
+
newManifest = require_publishDate.filterVersionsByPublishDate(newManifest, earliestDateThreshold, allowRules);
|
|
57
|
+
}
|
|
58
|
+
require_manifestUtils.cleanupTags(newManifest);
|
|
59
|
+
require_manifestUtils.setupLatestTag(newManifest);
|
|
60
|
+
require_manifestUtils.cleanupTime(newManifest);
|
|
61
|
+
require_manifestUtils.setupCreatedAndModified(newManifest);
|
|
62
|
+
require_manifestUtils.cleanupDistFiles(newManifest);
|
|
63
|
+
const filteredCount = Object.keys(newManifest.versions).length;
|
|
64
|
+
const removedCount = versionCount - filteredCount;
|
|
65
|
+
if (filteredCount !== versionCount) {
|
|
66
|
+
debug$1("filtered %s: %d -> %d versions (%d removed)", manifest.name, versionCount, filteredCount, removedCount);
|
|
67
|
+
this.logger.trace({
|
|
68
|
+
name: manifest.name,
|
|
69
|
+
before: versionCount,
|
|
70
|
+
after: filteredCount,
|
|
71
|
+
removed: removedCount
|
|
72
|
+
}, "package-filter @{name}: @{before} -> @{after} versions (@{removed} removed)");
|
|
73
|
+
} else debug$1("no versions filtered for %s", manifest.name);
|
|
74
|
+
return newManifest;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
//#endregion
|
|
78
|
+
exports.PackageFilterPlugin = PackageFilterPlugin;
|
|
79
|
+
|
|
80
|
+
//# sourceMappingURL=packageFilter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packageFilter.js","names":[],"sources":["../src/packageFilter.ts"],"sourcesContent":["import buildDebug from 'debug';\n\nimport { pluginUtils } from '@verdaccio/core';\nimport type { Logger, Manifest } from '@verdaccio/types';\n\nimport { parseConfig } from './config/parser';\nimport type { ParsedConfig, PluginConfig } from './config/types';\nimport { filterBlockedVersions } from './filtering/packageVersion';\nimport { filterVersionsByPublishDate } from './filtering/publishDate';\nimport { jsonLogReplacer } from './utils/jsonUtils';\nimport {\n cleanupDistFiles,\n cleanupTags,\n cleanupTime,\n getManifestClone,\n setupCreatedAndModified,\n setupLatestTag,\n} from './utils/manifestUtils';\n\nconst debug = buildDebug('verdaccio:plugin:package-filter');\n\nexport class PackageFilterPlugin\n extends pluginUtils.Plugin<PluginConfig>\n implements pluginUtils.ManifestFilter<PluginConfig>\n{\n public readonly config: PluginConfig;\n private readonly parsedConfig: ParsedConfig;\n protected readonly logger: Logger;\n\n public constructor(config: PluginConfig, options: pluginUtils.PluginOptions) {\n super(config, options);\n this.config = config ?? {};\n this.logger = options.logger;\n this.parsedConfig = parseConfig(this.config);\n\n debug(\n 'plugin loaded: block rules: %d, allow rules: %d',\n this.parsedConfig.blockRules.size,\n this.parsedConfig.allowRules.size\n );\n this.logger.debug(\n { config: JSON.stringify(this.parsedConfig, jsonLogReplacer) },\n 'package-filter loaded with config: @{config}'\n );\n this.logger.trace(\n {\n blockRules: this.parsedConfig.blockRules.size,\n allowRules: this.parsedConfig.allowRules.size,\n },\n 'package-filter plugin initialized: @{blockRules} block rules, @{allowRules} allow rules'\n );\n if (this.parsedConfig.dateThreshold) {\n debug('date threshold: %s', this.parsedConfig.dateThreshold.toISOString());\n this.logger.trace(\n { dateThreshold: this.parsedConfig.dateThreshold.toISOString() },\n 'package-filter date threshold: @{dateThreshold}'\n );\n }\n if (this.parsedConfig.minAgeMs) {\n const minAgeDays = this.parsedConfig.minAgeMs / (24 * 60 * 60 * 1000);\n debug('min age: %d days', minAgeDays);\n this.logger.trace({ minAgeDays }, 'package-filter min age: @{minAgeDays} days');\n }\n }\n\n public async filter_metadata(manifest: Readonly<Manifest>): Promise<Manifest> {\n const { dateThreshold, minAgeMs, blockRules, allowRules } = this.parsedConfig;\n const versionCount = Object.keys(manifest.versions ?? {}).length;\n debug('filtering manifest for %s (%d versions)', manifest.name, versionCount);\n this.logger.trace(\n { name: manifest.name, versionCount },\n 'package-filter processing @{name} (@{versionCount} versions)'\n );\n\n let newManifest = getManifestClone(manifest);\n if (blockRules.size > 0) {\n newManifest = filterBlockedVersions(newManifest, blockRules, allowRules, this.logger);\n }\n\n let earliestDateThreshold: Date | null = null;\n if (minAgeMs) {\n earliestDateThreshold = new Date(Date.now() - minAgeMs);\n }\n\n if (dateThreshold && (!earliestDateThreshold || dateThreshold < earliestDateThreshold)) {\n earliestDateThreshold = dateThreshold;\n }\n\n if (earliestDateThreshold) {\n debug(\n 'applying date filter for %s, threshold: %s',\n manifest.name,\n earliestDateThreshold.toISOString()\n );\n this.logger.trace(\n { name: manifest.name, threshold: earliestDateThreshold.toISOString() },\n 'applying date filter for @{name}, cutoff: @{threshold}'\n );\n newManifest = filterVersionsByPublishDate(newManifest, earliestDateThreshold, allowRules);\n }\n\n cleanupTags(newManifest);\n setupLatestTag(newManifest);\n cleanupTime(newManifest);\n setupCreatedAndModified(newManifest);\n cleanupDistFiles(newManifest);\n\n const filteredCount = Object.keys(newManifest.versions).length;\n const removedCount = versionCount - filteredCount;\n if (filteredCount !== versionCount) {\n debug(\n 'filtered %s: %d -> %d versions (%d removed)',\n manifest.name,\n versionCount,\n filteredCount,\n removedCount\n );\n this.logger.trace(\n { name: manifest.name, before: versionCount, after: filteredCount, removed: removedCount },\n 'package-filter @{name}: @{before} -> @{after} versions (@{removed} removed)'\n );\n } else {\n debug('no versions filtered for %s', manifest.name);\n }\n\n return newManifest;\n }\n}\n"],"mappings":";;;;;;;;;;AAmBA,IAAM,WAAA,GAAA,MAAA,SAAmB,kCAAkC;AAE3D,IAAa,sBAAb,cACU,gBAAA,YAAY,OAEtB;CACE;CACA;CACA;CAEA,YAAmB,QAAsB,SAAoC;AAC3E,QAAM,QAAQ,QAAQ;AACtB,OAAK,SAAS,UAAU,EAAE;AAC1B,OAAK,SAAS,QAAQ;AACtB,OAAK,eAAe,eAAA,YAAY,KAAK,OAAO;AAE5C,UACE,mDACA,KAAK,aAAa,WAAW,MAC7B,KAAK,aAAa,WAAW,KAC9B;AACD,OAAK,OAAO,MACV,EAAE,QAAQ,KAAK,UAAU,KAAK,cAAc,kBAAA,gBAAgB,EAAE,EAC9D,+CACD;AACD,OAAK,OAAO,MACV;GACE,YAAY,KAAK,aAAa,WAAW;GACzC,YAAY,KAAK,aAAa,WAAW;GAC1C,EACD,0FACD;AACD,MAAI,KAAK,aAAa,eAAe;AACnC,WAAM,sBAAsB,KAAK,aAAa,cAAc,aAAa,CAAC;AAC1E,QAAK,OAAO,MACV,EAAE,eAAe,KAAK,aAAa,cAAc,aAAa,EAAE,EAChE,kDACD;;AAEH,MAAI,KAAK,aAAa,UAAU;GAC9B,MAAM,aAAa,KAAK,aAAa,YAAY,OAAU,KAAK;AAChE,WAAM,oBAAoB,WAAW;AACrC,QAAK,OAAO,MAAM,EAAE,YAAY,EAAE,6CAA6C;;;CAInF,MAAa,gBAAgB,UAAiD;EAC5E,MAAM,EAAE,eAAe,UAAU,YAAY,eAAe,KAAK;EACjE,MAAM,eAAe,OAAO,KAAK,SAAS,YAAY,EAAE,CAAC,CAAC;AAC1D,UAAM,2CAA2C,SAAS,MAAM,aAAa;AAC7E,OAAK,OAAO,MACV;GAAE,MAAM,SAAS;GAAM;GAAc,EACrC,+DACD;EAED,IAAI,cAAc,sBAAA,iBAAiB,SAAS;AAC5C,MAAI,WAAW,OAAO,EACpB,eAAc,uBAAA,sBAAsB,aAAa,YAAY,YAAY,KAAK,OAAO;EAGvF,IAAI,wBAAqC;AACzC,MAAI,SACF,yBAAwB,IAAI,KAAK,KAAK,KAAK,GAAG,SAAS;AAGzD,MAAI,kBAAkB,CAAC,yBAAyB,gBAAgB,uBAC9D,yBAAwB;AAG1B,MAAI,uBAAuB;AACzB,WACE,8CACA,SAAS,MACT,sBAAsB,aAAa,CACpC;AACD,QAAK,OAAO,MACV;IAAE,MAAM,SAAS;IAAM,WAAW,sBAAsB,aAAa;IAAE,EACvE,yDACD;AACD,iBAAc,oBAAA,4BAA4B,aAAa,uBAAuB,WAAW;;AAG3F,wBAAA,YAAY,YAAY;AACxB,wBAAA,eAAe,YAAY;AAC3B,wBAAA,YAAY,YAAY;AACxB,wBAAA,wBAAwB,YAAY;AACpC,wBAAA,iBAAiB,YAAY;EAE7B,MAAM,gBAAgB,OAAO,KAAK,YAAY,SAAS,CAAC;EACxD,MAAM,eAAe,eAAe;AACpC,MAAI,kBAAkB,cAAc;AAClC,WACE,+CACA,SAAS,MACT,cACA,eACA,aACD;AACD,QAAK,OAAO,MACV;IAAE,MAAM,SAAS;IAAM,QAAQ;IAAc,OAAO;IAAe,SAAS;IAAc,EAC1F,8EACD;QAED,SAAM,+BAA+B,SAAS,KAAK;AAGrD,SAAO"}
|