@verdaccio/package-filter 14.0.0-next-9.55 → 14.0.0-next-9.56

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 CHANGED
@@ -69,18 +69,20 @@ When both `minAgeDays` and `dateThreshold` are set, the **earlier** cutoff wins
69
69
 
70
70
  ### Block by Scope
71
71
 
72
- Block all packages under a scope.
72
+ Block all packages under a scope. Scope values can be exact names or glob patterns.
73
+ Scope globs are matched against only the extracted scope name, for example `@babel`, so use patterns like `@babel*` or `@my-org-*` instead of `@babel/*`.
73
74
 
74
75
  ```yaml
75
76
  filters:
76
77
  '@verdaccio/package-filter':
77
78
  block:
78
79
  - scope: '@evilscope'
80
+ - scope: '@my-org-*'
79
81
  ```
80
82
 
81
83
  ### Block by Package Name
82
84
 
83
- Block all versions of a specific package.
85
+ Block all versions of a specific package. Package values can be exact names or glob patterns.
84
86
 
85
87
  ```yaml
86
88
  filters:
@@ -88,11 +90,13 @@ filters:
88
90
  block:
89
91
  - package: 'malicious-pkg'
90
92
  - package: '@coolauthor/stolen'
93
+ - package: 'react-*'
94
+ - package: '@legacy/*'
91
95
  ```
92
96
 
93
97
  ### Block by Version Range
94
98
 
95
- Block specific semver ranges of a package. Uses [semver](https://www.npmjs.com/package/semver) syntax.
99
+ Block specific semver ranges of a package. Package values can be exact names or glob patterns. Version ranges use [semver](https://www.npmjs.com/package/semver) syntax.
96
100
 
97
101
  ```yaml
98
102
  filters:
@@ -100,6 +104,8 @@ filters:
100
104
  block:
101
105
  - package: '@coolauthor/stolen'
102
106
  versions: '>2.0.1'
107
+ - package: '@legacy/*'
108
+ versions: '>=3.0.0'
103
109
  ```
104
110
 
105
111
  Multiple version ranges for the same package are merged:
@@ -161,11 +167,11 @@ filters:
161
167
 
162
168
  Allow rules are checked before block rules. The granularity levels:
163
169
 
164
- | Allow rule | Effect |
165
- | ------------------------------------ | ----------------------------------- |
166
- | `scope: '@x'` | Entire scope bypasses all rules |
167
- | `package: 'x'` | Entire package bypasses all rules |
168
- | `package: 'x'` + `versions: '1.0.0'` | Only matching versions are exempted |
170
+ | Allow rule | Effect |
171
+ | ------------------------------------ | ------------------------------------------ |
172
+ | `scope: '@x'` or `scope: '@x-*'` | Entire matching scope bypasses all rules |
173
+ | `package: 'x'` or `package: 'x-*'` | Entire matching package bypasses all rules |
174
+ | `package: 'x'` + `versions: '1.0.0'` | Only matching versions are exempted |
169
175
 
170
176
  ### Full Example
171
177
 
@@ -1,4 +1,5 @@
1
1
  const require_runtime = require("../_virtual/_rolldown/runtime.js");
2
+ const require_matcher = require("../filtering/matcher.js");
2
3
  let debug = require("debug");
3
4
  debug = require_runtime.__toESM(debug);
4
5
  let semver = require("semver");
@@ -28,6 +29,7 @@ function parseConfigRules(configRules) {
28
29
  }
29
30
  throw new TypeError(`Could not parse rule ${JSON.stringify(rule, null, 4)}`);
30
31
  }
32
+ require_matcher.prepareRules(ruleMap);
31
33
  return ruleMap;
32
34
  }
33
35
  function parseConfig(config) {
@@ -1 +1 @@
1
- {"version":3,"file":"parser.js","names":[],"sources":["../../src/config/parser.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { Range } from 'semver';\n\nimport type { ConfigRule, ParsedConfig, ParsedRule, PluginConfig } from './types';\n\nconst debug = buildDebug('verdaccio:plugin:package-filter:config');\n\nfunction parseConfigRules(configRules: ConfigRule[]): Map<string, ParsedRule> {\n const ruleMap = new Map<string, ParsedRule>();\n for (const rule of configRules) {\n if ('scope' in rule && typeof rule.scope === 'string') {\n if (!rule.scope.startsWith('@')) {\n throw new TypeError(`Scope value must start with @, found: ${rule.scope}`);\n }\n\n ruleMap.set(rule.scope, 'scope');\n continue;\n }\n\n if ('package' in rule && !('versions' in rule)) {\n ruleMap.set(rule.package, 'package');\n continue;\n }\n\n if ('package' in rule && 'versions' in rule) {\n const previousConfig = ruleMap.get(rule.package) || { versions: [] };\n\n if (typeof previousConfig === 'string') {\n throw new Error(\n `Package ${rule.package} is already specified by another strict rule ${previousConfig}`\n );\n }\n\n // Merge version ranges of the rules for the same package\n const range = new Range(rule.versions);\n ruleMap.set(rule.package, {\n versions: [...previousConfig.versions, range],\n strategy: rule.strategy ?? 'block',\n });\n\n continue;\n }\n\n throw new TypeError(`Could not parse rule ${JSON.stringify(rule, null, 4)}`);\n }\n\n return ruleMap;\n}\n\nexport function parseConfig(config: PluginConfig): ParsedConfig {\n debug('parsing config: %o', config);\n const blockMap = parseConfigRules(config.block ?? []);\n const allowMap = parseConfigRules(config.allow ?? []);\n debug('parsed %d block rules, %d allow rules', blockMap.size, allowMap.size);\n const dateThreshold = config.dateThreshold ? new Date(config.dateThreshold) : null;\n if (dateThreshold && isNaN(dateThreshold.getTime())) {\n throw new TypeError(`Invalid date ${config.dateThreshold} was provided for dateThreshold`);\n }\n\n const minAgeDays = config.minAgeDays ? Number(config.minAgeDays) : null;\n let minAgeMs: number | null = null;\n if (minAgeDays !== null) {\n if (isNaN(minAgeDays) || minAgeDays < 0) {\n throw new TypeError(`Invalid number ${config.minAgeDays} was provided for minAgeDays`);\n }\n\n minAgeMs = minAgeDays * 24 * 60 * 60 * 1000;\n }\n\n const excludeDeprecated = config.excludeDeprecated === true;\n\n return {\n dateThreshold,\n minAgeMs,\n excludeDeprecated,\n blockRules: blockMap,\n allowRules: allowMap,\n };\n}\n"],"mappings":";;;;;AAKA,IAAM,WAAA,GAAQ,MAAA,QAAA,CAAW,wCAAwC;AAEjE,SAAS,iBAAiB,aAAoD;CAC5E,MAAM,0BAAU,IAAI,IAAwB;CAC5C,KAAK,MAAM,QAAQ,aAAa;EAC9B,IAAI,WAAW,QAAQ,OAAO,KAAK,UAAU,UAAU;GACrD,IAAI,CAAC,KAAK,MAAM,WAAW,GAAG,GAC5B,MAAM,IAAI,UAAU,yCAAyC,KAAK,OAAO;GAG3E,QAAQ,IAAI,KAAK,OAAO,OAAO;GAC/B;EACF;EAEA,IAAI,aAAa,QAAQ,EAAE,cAAc,OAAO;GAC9C,QAAQ,IAAI,KAAK,SAAS,SAAS;GACnC;EACF;EAEA,IAAI,aAAa,QAAQ,cAAc,MAAM;GAC3C,MAAM,iBAAiB,QAAQ,IAAI,KAAK,OAAO,KAAK,EAAE,UAAU,CAAC,EAAE;GAEnE,IAAI,OAAO,mBAAmB,UAC5B,MAAM,IAAI,MACR,WAAW,KAAK,QAAQ,+CAA+C,gBACzE;GAIF,MAAM,QAAQ,IAAI,OAAA,MAAM,KAAK,QAAQ;GACrC,QAAQ,IAAI,KAAK,SAAS;IACxB,UAAU,CAAC,GAAG,eAAe,UAAU,KAAK;IAC5C,UAAU,KAAK,YAAY;GAC7B,CAAC;GAED;EACF;EAEA,MAAM,IAAI,UAAU,wBAAwB,KAAK,UAAU,MAAM,MAAM,CAAC,GAAG;CAC7E;CAEA,OAAO;AACT;AAEA,SAAgB,YAAY,QAAoC;CAC9D,QAAM,sBAAsB,MAAM;CAClC,MAAM,WAAW,iBAAiB,OAAO,SAAS,CAAC,CAAC;CACpD,MAAM,WAAW,iBAAiB,OAAO,SAAS,CAAC,CAAC;CACpD,QAAM,yCAAyC,SAAS,MAAM,SAAS,IAAI;CAC3E,MAAM,gBAAgB,OAAO,gBAAgB,IAAI,KAAK,OAAO,aAAa,IAAI;CAC9E,IAAI,iBAAiB,MAAM,cAAc,QAAQ,CAAC,GAChD,MAAM,IAAI,UAAU,gBAAgB,OAAO,cAAc,gCAAgC;CAG3F,MAAM,aAAa,OAAO,aAAa,OAAO,OAAO,UAAU,IAAI;CACnE,IAAI,WAA0B;CAC9B,IAAI,eAAe,MAAM;EACvB,IAAI,MAAM,UAAU,KAAK,aAAa,GACpC,MAAM,IAAI,UAAU,kBAAkB,OAAO,WAAW,6BAA6B;EAGvF,WAAW,aAAa,KAAK,KAAK,KAAK;CACzC;CAEA,MAAM,oBAAoB,OAAO,sBAAsB;CAEvD,OAAO;EACL;EACA;EACA;EACA,YAAY;EACZ,YAAY;CACd;AACF"}
1
+ {"version":3,"file":"parser.js","names":[],"sources":["../../src/config/parser.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { Range } from 'semver';\n\nimport { prepareRules } from '../filtering/matcher';\nimport type { ConfigRule, ParsedConfig, ParsedRule, PluginConfig } from './types';\n\nconst debug = buildDebug('verdaccio:plugin:package-filter:config');\n\nfunction parseConfigRules(configRules: ConfigRule[]): Map<string, ParsedRule> {\n const ruleMap = new Map<string, ParsedRule>();\n for (const rule of configRules) {\n if ('scope' in rule && typeof rule.scope === 'string') {\n if (!rule.scope.startsWith('@')) {\n throw new TypeError(`Scope value must start with @, found: ${rule.scope}`);\n }\n\n ruleMap.set(rule.scope, 'scope');\n continue;\n }\n\n if ('package' in rule && !('versions' in rule)) {\n ruleMap.set(rule.package, 'package');\n continue;\n }\n\n if ('package' in rule && 'versions' in rule) {\n const previousConfig = ruleMap.get(rule.package) || { versions: [] };\n\n if (typeof previousConfig === 'string') {\n throw new Error(\n `Package ${rule.package} is already specified by another strict rule ${previousConfig}`\n );\n }\n\n // Merge version ranges of the rules for the same package\n const range = new Range(rule.versions);\n ruleMap.set(rule.package, {\n versions: [...previousConfig.versions, range],\n strategy: rule.strategy ?? 'block',\n });\n\n continue;\n }\n\n throw new TypeError(`Could not parse rule ${JSON.stringify(rule, null, 4)}`);\n }\n\n prepareRules(ruleMap);\n return ruleMap;\n}\n\nexport function parseConfig(config: PluginConfig): ParsedConfig {\n debug('parsing config: %o', config);\n const blockMap = parseConfigRules(config.block ?? []);\n const allowMap = parseConfigRules(config.allow ?? []);\n debug('parsed %d block rules, %d allow rules', blockMap.size, allowMap.size);\n const dateThreshold = config.dateThreshold ? new Date(config.dateThreshold) : null;\n if (dateThreshold && isNaN(dateThreshold.getTime())) {\n throw new TypeError(`Invalid date ${config.dateThreshold} was provided for dateThreshold`);\n }\n\n const minAgeDays = config.minAgeDays ? Number(config.minAgeDays) : null;\n let minAgeMs: number | null = null;\n if (minAgeDays !== null) {\n if (isNaN(minAgeDays) || minAgeDays < 0) {\n throw new TypeError(`Invalid number ${config.minAgeDays} was provided for minAgeDays`);\n }\n\n minAgeMs = minAgeDays * 24 * 60 * 60 * 1000;\n }\n\n const excludeDeprecated = config.excludeDeprecated === true;\n\n return {\n dateThreshold,\n minAgeMs,\n excludeDeprecated,\n blockRules: blockMap,\n allowRules: allowMap,\n };\n}\n"],"mappings":";;;;;;AAMA,IAAM,WAAA,GAAQ,MAAA,QAAA,CAAW,wCAAwC;AAEjE,SAAS,iBAAiB,aAAoD;CAC5E,MAAM,0BAAU,IAAI,IAAwB;CAC5C,KAAK,MAAM,QAAQ,aAAa;EAC9B,IAAI,WAAW,QAAQ,OAAO,KAAK,UAAU,UAAU;GACrD,IAAI,CAAC,KAAK,MAAM,WAAW,GAAG,GAC5B,MAAM,IAAI,UAAU,yCAAyC,KAAK,OAAO;GAG3E,QAAQ,IAAI,KAAK,OAAO,OAAO;GAC/B;EACF;EAEA,IAAI,aAAa,QAAQ,EAAE,cAAc,OAAO;GAC9C,QAAQ,IAAI,KAAK,SAAS,SAAS;GACnC;EACF;EAEA,IAAI,aAAa,QAAQ,cAAc,MAAM;GAC3C,MAAM,iBAAiB,QAAQ,IAAI,KAAK,OAAO,KAAK,EAAE,UAAU,CAAC,EAAE;GAEnE,IAAI,OAAO,mBAAmB,UAC5B,MAAM,IAAI,MACR,WAAW,KAAK,QAAQ,+CAA+C,gBACzE;GAIF,MAAM,QAAQ,IAAI,OAAA,MAAM,KAAK,QAAQ;GACrC,QAAQ,IAAI,KAAK,SAAS;IACxB,UAAU,CAAC,GAAG,eAAe,UAAU,KAAK;IAC5C,UAAU,KAAK,YAAY;GAC7B,CAAC;GAED;EACF;EAEA,MAAM,IAAI,UAAU,wBAAwB,KAAK,UAAU,MAAM,MAAM,CAAC,GAAG;CAC7E;CAEA,gBAAA,aAAa,OAAO;CACpB,OAAO;AACT;AAEA,SAAgB,YAAY,QAAoC;CAC9D,QAAM,sBAAsB,MAAM;CAClC,MAAM,WAAW,iBAAiB,OAAO,SAAS,CAAC,CAAC;CACpD,MAAM,WAAW,iBAAiB,OAAO,SAAS,CAAC,CAAC;CACpD,QAAM,yCAAyC,SAAS,MAAM,SAAS,IAAI;CAC3E,MAAM,gBAAgB,OAAO,gBAAgB,IAAI,KAAK,OAAO,aAAa,IAAI;CAC9E,IAAI,iBAAiB,MAAM,cAAc,QAAQ,CAAC,GAChD,MAAM,IAAI,UAAU,gBAAgB,OAAO,cAAc,gCAAgC;CAG3F,MAAM,aAAa,OAAO,aAAa,OAAO,OAAO,UAAU,IAAI;CACnE,IAAI,WAA0B;CAC9B,IAAI,eAAe,MAAM;EACvB,IAAI,MAAM,UAAU,KAAK,aAAa,GACpC,MAAM,IAAI,UAAU,kBAAkB,OAAO,WAAW,6BAA6B;EAGvF,WAAW,aAAa,KAAK,KAAK,KAAK;CACzC;CAEA,MAAM,oBAAoB,OAAO,sBAAsB;CAEvD,OAAO;EACL;EACA;EACA;EACA,YAAY;EACZ,YAAY;CACd;AACF"}
@@ -1,3 +1,4 @@
1
+ import { prepareRules } from "../filtering/matcher.mjs";
1
2
  import buildDebug from "debug";
2
3
  import { Range } from "semver";
3
4
  //#region src/config/parser.ts
@@ -26,6 +27,7 @@ function parseConfigRules(configRules) {
26
27
  }
27
28
  throw new TypeError(`Could not parse rule ${JSON.stringify(rule, null, 4)}`);
28
29
  }
30
+ prepareRules(ruleMap);
29
31
  return ruleMap;
30
32
  }
31
33
  function parseConfig(config) {
@@ -1 +1 @@
1
- {"version":3,"file":"parser.mjs","names":[],"sources":["../../src/config/parser.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { Range } from 'semver';\n\nimport type { ConfigRule, ParsedConfig, ParsedRule, PluginConfig } from './types';\n\nconst debug = buildDebug('verdaccio:plugin:package-filter:config');\n\nfunction parseConfigRules(configRules: ConfigRule[]): Map<string, ParsedRule> {\n const ruleMap = new Map<string, ParsedRule>();\n for (const rule of configRules) {\n if ('scope' in rule && typeof rule.scope === 'string') {\n if (!rule.scope.startsWith('@')) {\n throw new TypeError(`Scope value must start with @, found: ${rule.scope}`);\n }\n\n ruleMap.set(rule.scope, 'scope');\n continue;\n }\n\n if ('package' in rule && !('versions' in rule)) {\n ruleMap.set(rule.package, 'package');\n continue;\n }\n\n if ('package' in rule && 'versions' in rule) {\n const previousConfig = ruleMap.get(rule.package) || { versions: [] };\n\n if (typeof previousConfig === 'string') {\n throw new Error(\n `Package ${rule.package} is already specified by another strict rule ${previousConfig}`\n );\n }\n\n // Merge version ranges of the rules for the same package\n const range = new Range(rule.versions);\n ruleMap.set(rule.package, {\n versions: [...previousConfig.versions, range],\n strategy: rule.strategy ?? 'block',\n });\n\n continue;\n }\n\n throw new TypeError(`Could not parse rule ${JSON.stringify(rule, null, 4)}`);\n }\n\n return ruleMap;\n}\n\nexport function parseConfig(config: PluginConfig): ParsedConfig {\n debug('parsing config: %o', config);\n const blockMap = parseConfigRules(config.block ?? []);\n const allowMap = parseConfigRules(config.allow ?? []);\n debug('parsed %d block rules, %d allow rules', blockMap.size, allowMap.size);\n const dateThreshold = config.dateThreshold ? new Date(config.dateThreshold) : null;\n if (dateThreshold && isNaN(dateThreshold.getTime())) {\n throw new TypeError(`Invalid date ${config.dateThreshold} was provided for dateThreshold`);\n }\n\n const minAgeDays = config.minAgeDays ? Number(config.minAgeDays) : null;\n let minAgeMs: number | null = null;\n if (minAgeDays !== null) {\n if (isNaN(minAgeDays) || minAgeDays < 0) {\n throw new TypeError(`Invalid number ${config.minAgeDays} was provided for minAgeDays`);\n }\n\n minAgeMs = minAgeDays * 24 * 60 * 60 * 1000;\n }\n\n const excludeDeprecated = config.excludeDeprecated === true;\n\n return {\n dateThreshold,\n minAgeMs,\n excludeDeprecated,\n blockRules: blockMap,\n allowRules: allowMap,\n };\n}\n"],"mappings":";;;AAKA,IAAM,QAAQ,WAAW,wCAAwC;AAEjE,SAAS,iBAAiB,aAAoD;CAC5E,MAAM,0BAAU,IAAI,IAAwB;CAC5C,KAAK,MAAM,QAAQ,aAAa;EAC9B,IAAI,WAAW,QAAQ,OAAO,KAAK,UAAU,UAAU;GACrD,IAAI,CAAC,KAAK,MAAM,WAAW,GAAG,GAC5B,MAAM,IAAI,UAAU,yCAAyC,KAAK,OAAO;GAG3E,QAAQ,IAAI,KAAK,OAAO,OAAO;GAC/B;EACF;EAEA,IAAI,aAAa,QAAQ,EAAE,cAAc,OAAO;GAC9C,QAAQ,IAAI,KAAK,SAAS,SAAS;GACnC;EACF;EAEA,IAAI,aAAa,QAAQ,cAAc,MAAM;GAC3C,MAAM,iBAAiB,QAAQ,IAAI,KAAK,OAAO,KAAK,EAAE,UAAU,CAAC,EAAE;GAEnE,IAAI,OAAO,mBAAmB,UAC5B,MAAM,IAAI,MACR,WAAW,KAAK,QAAQ,+CAA+C,gBACzE;GAIF,MAAM,QAAQ,IAAI,MAAM,KAAK,QAAQ;GACrC,QAAQ,IAAI,KAAK,SAAS;IACxB,UAAU,CAAC,GAAG,eAAe,UAAU,KAAK;IAC5C,UAAU,KAAK,YAAY;GAC7B,CAAC;GAED;EACF;EAEA,MAAM,IAAI,UAAU,wBAAwB,KAAK,UAAU,MAAM,MAAM,CAAC,GAAG;CAC7E;CAEA,OAAO;AACT;AAEA,SAAgB,YAAY,QAAoC;CAC9D,MAAM,sBAAsB,MAAM;CAClC,MAAM,WAAW,iBAAiB,OAAO,SAAS,CAAC,CAAC;CACpD,MAAM,WAAW,iBAAiB,OAAO,SAAS,CAAC,CAAC;CACpD,MAAM,yCAAyC,SAAS,MAAM,SAAS,IAAI;CAC3E,MAAM,gBAAgB,OAAO,gBAAgB,IAAI,KAAK,OAAO,aAAa,IAAI;CAC9E,IAAI,iBAAiB,MAAM,cAAc,QAAQ,CAAC,GAChD,MAAM,IAAI,UAAU,gBAAgB,OAAO,cAAc,gCAAgC;CAG3F,MAAM,aAAa,OAAO,aAAa,OAAO,OAAO,UAAU,IAAI;CACnE,IAAI,WAA0B;CAC9B,IAAI,eAAe,MAAM;EACvB,IAAI,MAAM,UAAU,KAAK,aAAa,GACpC,MAAM,IAAI,UAAU,kBAAkB,OAAO,WAAW,6BAA6B;EAGvF,WAAW,aAAa,KAAK,KAAK,KAAK;CACzC;CAEA,MAAM,oBAAoB,OAAO,sBAAsB;CAEvD,OAAO;EACL;EACA;EACA;EACA,YAAY;EACZ,YAAY;CACd;AACF"}
1
+ {"version":3,"file":"parser.mjs","names":[],"sources":["../../src/config/parser.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { Range } from 'semver';\n\nimport { prepareRules } from '../filtering/matcher';\nimport type { ConfigRule, ParsedConfig, ParsedRule, PluginConfig } from './types';\n\nconst debug = buildDebug('verdaccio:plugin:package-filter:config');\n\nfunction parseConfigRules(configRules: ConfigRule[]): Map<string, ParsedRule> {\n const ruleMap = new Map<string, ParsedRule>();\n for (const rule of configRules) {\n if ('scope' in rule && typeof rule.scope === 'string') {\n if (!rule.scope.startsWith('@')) {\n throw new TypeError(`Scope value must start with @, found: ${rule.scope}`);\n }\n\n ruleMap.set(rule.scope, 'scope');\n continue;\n }\n\n if ('package' in rule && !('versions' in rule)) {\n ruleMap.set(rule.package, 'package');\n continue;\n }\n\n if ('package' in rule && 'versions' in rule) {\n const previousConfig = ruleMap.get(rule.package) || { versions: [] };\n\n if (typeof previousConfig === 'string') {\n throw new Error(\n `Package ${rule.package} is already specified by another strict rule ${previousConfig}`\n );\n }\n\n // Merge version ranges of the rules for the same package\n const range = new Range(rule.versions);\n ruleMap.set(rule.package, {\n versions: [...previousConfig.versions, range],\n strategy: rule.strategy ?? 'block',\n });\n\n continue;\n }\n\n throw new TypeError(`Could not parse rule ${JSON.stringify(rule, null, 4)}`);\n }\n\n prepareRules(ruleMap);\n return ruleMap;\n}\n\nexport function parseConfig(config: PluginConfig): ParsedConfig {\n debug('parsing config: %o', config);\n const blockMap = parseConfigRules(config.block ?? []);\n const allowMap = parseConfigRules(config.allow ?? []);\n debug('parsed %d block rules, %d allow rules', blockMap.size, allowMap.size);\n const dateThreshold = config.dateThreshold ? new Date(config.dateThreshold) : null;\n if (dateThreshold && isNaN(dateThreshold.getTime())) {\n throw new TypeError(`Invalid date ${config.dateThreshold} was provided for dateThreshold`);\n }\n\n const minAgeDays = config.minAgeDays ? Number(config.minAgeDays) : null;\n let minAgeMs: number | null = null;\n if (minAgeDays !== null) {\n if (isNaN(minAgeDays) || minAgeDays < 0) {\n throw new TypeError(`Invalid number ${config.minAgeDays} was provided for minAgeDays`);\n }\n\n minAgeMs = minAgeDays * 24 * 60 * 60 * 1000;\n }\n\n const excludeDeprecated = config.excludeDeprecated === true;\n\n return {\n dateThreshold,\n minAgeMs,\n excludeDeprecated,\n blockRules: blockMap,\n allowRules: allowMap,\n };\n}\n"],"mappings":";;;;AAMA,IAAM,QAAQ,WAAW,wCAAwC;AAEjE,SAAS,iBAAiB,aAAoD;CAC5E,MAAM,0BAAU,IAAI,IAAwB;CAC5C,KAAK,MAAM,QAAQ,aAAa;EAC9B,IAAI,WAAW,QAAQ,OAAO,KAAK,UAAU,UAAU;GACrD,IAAI,CAAC,KAAK,MAAM,WAAW,GAAG,GAC5B,MAAM,IAAI,UAAU,yCAAyC,KAAK,OAAO;GAG3E,QAAQ,IAAI,KAAK,OAAO,OAAO;GAC/B;EACF;EAEA,IAAI,aAAa,QAAQ,EAAE,cAAc,OAAO;GAC9C,QAAQ,IAAI,KAAK,SAAS,SAAS;GACnC;EACF;EAEA,IAAI,aAAa,QAAQ,cAAc,MAAM;GAC3C,MAAM,iBAAiB,QAAQ,IAAI,KAAK,OAAO,KAAK,EAAE,UAAU,CAAC,EAAE;GAEnE,IAAI,OAAO,mBAAmB,UAC5B,MAAM,IAAI,MACR,WAAW,KAAK,QAAQ,+CAA+C,gBACzE;GAIF,MAAM,QAAQ,IAAI,MAAM,KAAK,QAAQ;GACrC,QAAQ,IAAI,KAAK,SAAS;IACxB,UAAU,CAAC,GAAG,eAAe,UAAU,KAAK;IAC5C,UAAU,KAAK,YAAY;GAC7B,CAAC;GAED;EACF;EAEA,MAAM,IAAI,UAAU,wBAAwB,KAAK,UAAU,MAAM,MAAM,CAAC,GAAG;CAC7E;CAEA,aAAa,OAAO;CACpB,OAAO;AACT;AAEA,SAAgB,YAAY,QAAoC;CAC9D,MAAM,sBAAsB,MAAM;CAClC,MAAM,WAAW,iBAAiB,OAAO,SAAS,CAAC,CAAC;CACpD,MAAM,WAAW,iBAAiB,OAAO,SAAS,CAAC,CAAC;CACpD,MAAM,yCAAyC,SAAS,MAAM,SAAS,IAAI;CAC3E,MAAM,gBAAgB,OAAO,gBAAgB,IAAI,KAAK,OAAO,aAAa,IAAI;CAC9E,IAAI,iBAAiB,MAAM,cAAc,QAAQ,CAAC,GAChD,MAAM,IAAI,UAAU,gBAAgB,OAAO,cAAc,gCAAgC;CAG3F,MAAM,aAAa,OAAO,aAAa,OAAO,OAAO,UAAU,IAAI;CACnE,IAAI,WAA0B;CAC9B,IAAI,eAAe,MAAM;EACvB,IAAI,MAAM,UAAU,KAAK,aAAa,GACpC,MAAM,IAAI,UAAU,kBAAkB,OAAO,WAAW,6BAA6B;EAGvF,WAAW,aAAa,KAAK,KAAK,KAAK;CACzC;CAEA,MAAM,oBAAoB,OAAO,sBAAsB;CAEvD,OAAO;EACL;EACA;EACA;EACA,YAAY;EACZ,YAAY;CACd;AACF"}
@@ -34,7 +34,7 @@ export interface ParsedConfigRule {
34
34
  versions: Range[];
35
35
  strategy?: BlockStrategy;
36
36
  }
37
- export type PackageScopeLevel = 'scope' | 'package' | undefined;
37
+ export type PackageScopeLevel = 'scope' | 'package';
38
38
  export type ParsedRule = ParsedConfigRule | PackageScopeLevel;
39
39
  export interface ParsedConfig {
40
40
  dateThreshold: Date | null;
@@ -1,9 +1,14 @@
1
1
  import type { Manifest } from '@verdaccio/types';
2
2
  import type { ParsedRule } from '../config/types';
3
3
  import type { MatchResult } from './types';
4
+ /**
5
+ * Cache the compiled glob rules for a rule map. Call again after changing the map.
6
+ */
7
+ export declare function prepareRules(rules: Map<string, ParsedRule>): void;
4
8
  /**
5
9
  * Try to find a rule that matches the package.
6
10
  * If found, returns the rule and the matched package versions from the manifest.
11
+ * Rule maps are cached; call prepareRules after modifying them.
7
12
  */
8
13
  export declare function matchRules(manifest: Manifest, rules: Map<string, ParsedRule>): MatchResult | undefined;
9
14
  /**
@@ -3,8 +3,71 @@ const require_types = require("./types.js");
3
3
  let debug = require("debug");
4
4
  debug = require_runtime.__toESM(debug);
5
5
  let semver = require("semver");
6
+ let minimatch = require("minimatch");
6
7
  //#region src/filtering/matcher.ts
7
8
  var debug$1 = (0, debug.default)("verdaccio:plugin:package-filter:filter");
9
+ var compiledGlobRules = /* @__PURE__ */ new WeakMap();
10
+ var globMagic = /[\\*?[\]{}!]|[+@]\(/;
11
+ /**
12
+ * Compile patterns requiring glob or escape handling, grouped by rule type.
13
+ */
14
+ function compileGlobRules(rules) {
15
+ const compiled = {
16
+ packages: [],
17
+ scopes: []
18
+ };
19
+ for (const [pattern, rule] of rules) {
20
+ if (!globMagic.test(pattern)) continue;
21
+ const compiledRule = {
22
+ pattern,
23
+ matcher: new minimatch.Minimatch(pattern),
24
+ rule
25
+ };
26
+ if (rule === "scope") compiled.scopes.push(compiledRule);
27
+ else compiled.packages.push(compiledRule);
28
+ }
29
+ return compiled;
30
+ }
31
+ /**
32
+ * Cache the compiled glob rules for a rule map. Call again after changing the map.
33
+ */
34
+ function prepareRules(rules) {
35
+ compiledGlobRules.set(rules, compileGlobRules(rules));
36
+ }
37
+ /**
38
+ * Return cached glob rules, compiling and caching unprepared maps on first use.
39
+ */
40
+ function getCompiledGlobRules(rules) {
41
+ let compiled = compiledGlobRules.get(rules);
42
+ if (!compiled) {
43
+ compiled = compileGlobRules(rules);
44
+ compiledGlobRules.set(rules, compiled);
45
+ }
46
+ return compiled;
47
+ }
48
+ function findScopeRule(scope, rules) {
49
+ if (!scope) return;
50
+ const exactRule = rules.get(scope);
51
+ if (exactRule === "scope") return {
52
+ scope,
53
+ rule: exactRule
54
+ };
55
+ for (const { pattern, matcher } of getCompiledGlobRules(rules).scopes) if (matcher.match(scope)) return {
56
+ scope: pattern,
57
+ rule: "scope"
58
+ };
59
+ }
60
+ function findPackageRule(packageName, rules) {
61
+ const exactRule = rules.get(packageName);
62
+ if (exactRule) return {
63
+ pattern: packageName,
64
+ rule: exactRule
65
+ };
66
+ for (const { pattern, matcher, rule } of getCompiledGlobRules(rules).packages) if (matcher.match(packageName)) return {
67
+ pattern,
68
+ rule
69
+ };
70
+ }
8
71
  /**
9
72
  * Split a package name into name itself and scope.
10
73
  */
@@ -20,29 +83,31 @@ function splitName(name) {
20
83
  /**
21
84
  * Try to find a rule that matches the package.
22
85
  * If found, returns the rule and the matched package versions from the manifest.
86
+ * Rule maps are cached; call prepareRules after modifying them.
23
87
  */
24
88
  function matchRules(manifest, rules) {
25
- const { scope } = splitName(manifest.name);
26
- if (scope) {
27
- const rule = rules.get(scope);
28
- if (rule === "scope") {
29
- debug$1("scope match: %s matched rule for %s", manifest.name, scope);
30
- return {
31
- type: require_types.MatchType.SCOPE,
32
- rule,
33
- scope,
34
- versions: Object.keys(manifest.versions)
35
- };
36
- }
89
+ const packageName = manifest.name;
90
+ if (!packageName) return;
91
+ const { scope } = splitName(packageName);
92
+ const scopeMatch = findScopeRule(scope, rules);
93
+ if (scopeMatch) {
94
+ debug$1("scope match: %s matched rule for %s", packageName, scopeMatch.scope);
95
+ return {
96
+ type: require_types.MatchType.SCOPE,
97
+ rule: scopeMatch.rule,
98
+ scope: scopeMatch.scope,
99
+ versions: Object.keys(manifest.versions)
100
+ };
37
101
  }
38
- const rule = rules.get(manifest.name);
39
- if (!rule) return;
102
+ const packageMatch = findPackageRule(packageName, rules);
103
+ if (!packageMatch) return;
104
+ const { rule } = packageMatch;
40
105
  if (rule === "package") {
41
- debug$1("package match: %s", manifest.name);
106
+ debug$1("package match: %s matched rule for %s", packageName, packageMatch.pattern);
42
107
  return {
43
108
  type: require_types.MatchType.PACKAGE,
44
109
  rule,
45
- package: manifest.name,
110
+ package: packageMatch.pattern,
46
111
  versions: Object.keys(manifest.versions)
47
112
  };
48
113
  }
@@ -78,6 +143,7 @@ function resolveAllowList(allowMatch) {
78
143
  }
79
144
  //#endregion
80
145
  exports.matchRules = matchRules;
146
+ exports.prepareRules = prepareRules;
81
147
  exports.resolveAllowList = resolveAllowList;
82
148
 
83
149
  //# sourceMappingURL=matcher.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"matcher.js","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\n/**\n * Derive the allow-list outcome from a precomputed allow-rule match:\n * whether the whole package/scope is allow-listed, and which versions\n * (if any) are individually whitelisted.\n */\nexport function resolveAllowList(allowMatch: MatchResult | undefined): {\n allowAll: boolean;\n whitelistedVersions: string[];\n} {\n const allowAll =\n !!allowMatch && (allowMatch.type === MatchType.SCOPE || allowMatch.type === MatchType.PACKAGE);\n return { allowAll, whitelistedVersions: allowMatch?.versions ?? [] };\n}\n"],"mappings":";;;;;;AASA,IAAM,WAAA,GAAQ,MAAA,QAAA,CAAW,wCAAwC;;;;AAKjE,SAAS,UAAU,MAAgD;CACjE,IAAI,CAAC,MACH,OAAO,EAAE,MAAM,GAAG;CAGpB,MAAM,QAAQ,KAAK,MAAM,GAAG;CAE5B,IAAI,MAAM,SAAS,GACjB,OAAO;EACL,OAAO,MAAM;EACb,MAAM,MAAM;CACd;MAEA,OAAO,EACL,MAAM,MAAM,GACd;AAEJ;;;;;AAMA,SAAgB,WACd,UACA,OACyB;CACzB,MAAM,EAAE,UAAU,UAAU,SAAS,IAAI;CACzC,IAAI,OAAO;EACT,MAAM,OAAO,MAAM,IAAI,KAAK;EAC5B,IAAI,SAAS,SAAS;GACpB,QAAM,uCAAuC,SAAS,MAAM,KAAK;GACjE,OAAO;IACL,MAAM,cAAA,UAAU;IAChB;IACA;IACA,UAAU,OAAO,KAAK,SAAS,QAAQ;GACzC;EACF;CACF;CAEA,MAAM,OAAO,MAAM,IAAI,SAAS,IAAI;CACpC,IAAI,CAAC,MAEH;CAGF,IAAI,SAAS,WAAW;EACtB,QAAM,qBAAqB,SAAS,IAAI;EACxC,OAAO;GACL,MAAM,cAAA,UAAU;GAChB;GACA,SAAS,SAAS;GAClB,UAAU,OAAO,KAAK,SAAS,QAAQ;EACzC;CACF;CAEA,IAAI,SAAS,SACX,MAAM,IAAI,MAAM,8DAA4D;CAG9E,MAAM,gBAAgB,KAAK;CAC3B,IAAI,cAAc,WAAW,GAE3B;CAGF,MAAM,kBAA4B,CAAC;CACnC,OAAO,KAAK,SAAS,QAAQ,CAAC,CAAC,SAAS,YAAY;EAClD,cAAc,SAAS,iBAAiB;GACtC,KAAA,GACE,OAAA,UAAA,CAAU,SAAS,cAAc;IAC/B,mBAAmB;IACnB,OAAO;GACT,CAAC,GAED,gBAAgB,KAAK,OAAO;EAEhC,CAAC;CACH,CAAC;CAED,IAAI,gBAAgB,SAAS,GAC3B,QACE,6CACA,SAAS,MACT,gBAAgB,QAChB,eACF;CAGF,OAAO;EACL,MAAM,cAAA,UAAU;EAChB;EACA,UAAU;CACZ;AACF;;;;;;AAOA,SAAgB,iBAAiB,YAG/B;CAGA,OAAO;EAAE,UADP,CAAC,CAAC,eAAe,WAAW,SAAS,cAAA,UAAU,SAAS,WAAW,SAAS,cAAA,UAAU;EACrE,qBAAqB,YAAY,YAAY,CAAC;CAAE;AACrE"}
1
+ {"version":3,"file":"matcher.js","names":[],"sources":["../../src/filtering/matcher.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { Minimatch } from 'minimatch';\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\ninterface CompiledGlobRule {\n pattern: string;\n matcher: Minimatch;\n rule: ParsedRule;\n}\n\ninterface CompiledGlobRules {\n packages: CompiledGlobRule[];\n scopes: CompiledGlobRule[];\n}\n\nconst compiledGlobRules = new WeakMap<Map<string, ParsedRule>, CompiledGlobRules>();\nconst globMagic = /[\\\\*?[\\]{}!]|[+@]\\(/;\n\n/**\n * Compile patterns requiring glob or escape handling, grouped by rule type.\n */\nfunction compileGlobRules(rules: Map<string, ParsedRule>): CompiledGlobRules {\n const compiled: CompiledGlobRules = { packages: [], scopes: [] };\n\n for (const [pattern, rule] of rules) {\n if (!globMagic.test(pattern)) {\n continue;\n }\n\n const matcher = new Minimatch(pattern);\n const compiledRule = { pattern, matcher, rule };\n if (rule === 'scope') {\n compiled.scopes.push(compiledRule);\n } else {\n compiled.packages.push(compiledRule);\n }\n }\n\n return compiled;\n}\n\n/**\n * Cache the compiled glob rules for a rule map. Call again after changing the map.\n */\nexport function prepareRules(rules: Map<string, ParsedRule>): void {\n compiledGlobRules.set(rules, compileGlobRules(rules));\n}\n\n/**\n * Return cached glob rules, compiling and caching unprepared maps on first use.\n */\nfunction getCompiledGlobRules(rules: Map<string, ParsedRule>): CompiledGlobRules {\n let compiled = compiledGlobRules.get(rules);\n if (!compiled) {\n compiled = compileGlobRules(rules);\n compiledGlobRules.set(rules, compiled);\n }\n\n return compiled;\n}\n\nfunction findScopeRule(\n scope: string | undefined,\n rules: Map<string, ParsedRule>\n): { scope: string; rule: 'scope' } | undefined {\n if (!scope) {\n return undefined;\n }\n\n const exactRule = rules.get(scope);\n if (exactRule === 'scope') {\n return { scope, rule: exactRule };\n }\n\n for (const { pattern, matcher } of getCompiledGlobRules(rules).scopes) {\n if (matcher.match(scope)) {\n return { scope: pattern, rule: 'scope' };\n }\n }\n\n return undefined;\n}\n\nfunction findPackageRule(\n packageName: string,\n rules: Map<string, ParsedRule>\n): { pattern: string; rule: ParsedRule } | undefined {\n const exactRule = rules.get(packageName);\n if (exactRule) {\n return { pattern: packageName, rule: exactRule };\n }\n\n for (const { pattern, matcher, rule } of getCompiledGlobRules(rules).packages) {\n if (matcher.match(packageName)) {\n return { pattern, rule };\n }\n }\n\n return undefined;\n}\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 * Rule maps are cached; call prepareRules after modifying them.\n */\nexport function matchRules(\n manifest: Manifest,\n rules: Map<string, ParsedRule>\n): MatchResult | undefined {\n const packageName = manifest.name;\n if (!packageName) {\n return undefined;\n }\n\n const { scope } = splitName(packageName);\n const scopeMatch = findScopeRule(scope, rules);\n if (scopeMatch) {\n debug('scope match: %s matched rule for %s', packageName, scopeMatch.scope);\n return {\n type: MatchType.SCOPE,\n rule: scopeMatch.rule,\n scope: scopeMatch.scope,\n versions: Object.keys(manifest.versions),\n };\n }\n\n const packageMatch = findPackageRule(packageName, rules);\n if (!packageMatch) {\n // No match\n return undefined;\n }\n const { rule } = packageMatch;\n\n if (rule === 'package') {\n debug('package match: %s matched rule for %s', packageName, packageMatch.pattern);\n return {\n type: MatchType.PACKAGE,\n rule,\n package: packageMatch.pattern,\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\n/**\n * Derive the allow-list outcome from a precomputed allow-rule match:\n * whether the whole package/scope is allow-listed, and which versions\n * (if any) are individually whitelisted.\n */\nexport function resolveAllowList(allowMatch: MatchResult | undefined): {\n allowAll: boolean;\n whitelistedVersions: string[];\n} {\n const allowAll =\n !!allowMatch && (allowMatch.type === MatchType.SCOPE || allowMatch.type === MatchType.PACKAGE);\n return { allowAll, whitelistedVersions: allowMatch?.versions ?? [] };\n}\n"],"mappings":"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"}
@@ -1,8 +1,71 @@
1
1
  import { MatchType } from "./types.mjs";
2
2
  import buildDebug from "debug";
3
3
  import { satisfies } from "semver";
4
+ import { Minimatch } from "minimatch";
4
5
  //#region src/filtering/matcher.ts
5
6
  var debug = buildDebug("verdaccio:plugin:package-filter:filter");
7
+ var compiledGlobRules = /* @__PURE__ */ new WeakMap();
8
+ var globMagic = /[\\*?[\]{}!]|[+@]\(/;
9
+ /**
10
+ * Compile patterns requiring glob or escape handling, grouped by rule type.
11
+ */
12
+ function compileGlobRules(rules) {
13
+ const compiled = {
14
+ packages: [],
15
+ scopes: []
16
+ };
17
+ for (const [pattern, rule] of rules) {
18
+ if (!globMagic.test(pattern)) continue;
19
+ const compiledRule = {
20
+ pattern,
21
+ matcher: new Minimatch(pattern),
22
+ rule
23
+ };
24
+ if (rule === "scope") compiled.scopes.push(compiledRule);
25
+ else compiled.packages.push(compiledRule);
26
+ }
27
+ return compiled;
28
+ }
29
+ /**
30
+ * Cache the compiled glob rules for a rule map. Call again after changing the map.
31
+ */
32
+ function prepareRules(rules) {
33
+ compiledGlobRules.set(rules, compileGlobRules(rules));
34
+ }
35
+ /**
36
+ * Return cached glob rules, compiling and caching unprepared maps on first use.
37
+ */
38
+ function getCompiledGlobRules(rules) {
39
+ let compiled = compiledGlobRules.get(rules);
40
+ if (!compiled) {
41
+ compiled = compileGlobRules(rules);
42
+ compiledGlobRules.set(rules, compiled);
43
+ }
44
+ return compiled;
45
+ }
46
+ function findScopeRule(scope, rules) {
47
+ if (!scope) return;
48
+ const exactRule = rules.get(scope);
49
+ if (exactRule === "scope") return {
50
+ scope,
51
+ rule: exactRule
52
+ };
53
+ for (const { pattern, matcher } of getCompiledGlobRules(rules).scopes) if (matcher.match(scope)) return {
54
+ scope: pattern,
55
+ rule: "scope"
56
+ };
57
+ }
58
+ function findPackageRule(packageName, rules) {
59
+ const exactRule = rules.get(packageName);
60
+ if (exactRule) return {
61
+ pattern: packageName,
62
+ rule: exactRule
63
+ };
64
+ for (const { pattern, matcher, rule } of getCompiledGlobRules(rules).packages) if (matcher.match(packageName)) return {
65
+ pattern,
66
+ rule
67
+ };
68
+ }
6
69
  /**
7
70
  * Split a package name into name itself and scope.
8
71
  */
@@ -18,29 +81,31 @@ function splitName(name) {
18
81
  /**
19
82
  * Try to find a rule that matches the package.
20
83
  * If found, returns the rule and the matched package versions from the manifest.
84
+ * Rule maps are cached; call prepareRules after modifying them.
21
85
  */
22
86
  function matchRules(manifest, rules) {
23
- const { scope } = splitName(manifest.name);
24
- if (scope) {
25
- const rule = rules.get(scope);
26
- if (rule === "scope") {
27
- debug("scope match: %s matched rule for %s", manifest.name, scope);
28
- return {
29
- type: MatchType.SCOPE,
30
- rule,
31
- scope,
32
- versions: Object.keys(manifest.versions)
33
- };
34
- }
87
+ const packageName = manifest.name;
88
+ if (!packageName) return;
89
+ const { scope } = splitName(packageName);
90
+ const scopeMatch = findScopeRule(scope, rules);
91
+ if (scopeMatch) {
92
+ debug("scope match: %s matched rule for %s", packageName, scopeMatch.scope);
93
+ return {
94
+ type: MatchType.SCOPE,
95
+ rule: scopeMatch.rule,
96
+ scope: scopeMatch.scope,
97
+ versions: Object.keys(manifest.versions)
98
+ };
35
99
  }
36
- const rule = rules.get(manifest.name);
37
- if (!rule) return;
100
+ const packageMatch = findPackageRule(packageName, rules);
101
+ if (!packageMatch) return;
102
+ const { rule } = packageMatch;
38
103
  if (rule === "package") {
39
- debug("package match: %s", manifest.name);
104
+ debug("package match: %s matched rule for %s", packageName, packageMatch.pattern);
40
105
  return {
41
106
  type: MatchType.PACKAGE,
42
107
  rule,
43
- package: manifest.name,
108
+ package: packageMatch.pattern,
44
109
  versions: Object.keys(manifest.versions)
45
110
  };
46
111
  }
@@ -75,6 +140,6 @@ function resolveAllowList(allowMatch) {
75
140
  };
76
141
  }
77
142
  //#endregion
78
- export { matchRules, resolveAllowList };
143
+ export { matchRules, prepareRules, resolveAllowList };
79
144
 
80
145
  //# sourceMappingURL=matcher.mjs.map
@@ -1 +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\n/**\n * Derive the allow-list outcome from a precomputed allow-rule match:\n * whether the whole package/scope is allow-listed, and which versions\n * (if any) are individually whitelisted.\n */\nexport function resolveAllowList(allowMatch: MatchResult | undefined): {\n allowAll: boolean;\n whitelistedVersions: string[];\n} {\n const allowAll =\n !!allowMatch && (allowMatch.type === MatchType.SCOPE || allowMatch.type === MatchType.PACKAGE);\n return { allowAll, whitelistedVersions: allowMatch?.versions ?? [] };\n}\n"],"mappings":";;;;AASA,IAAM,QAAQ,WAAW,wCAAwC;;;;AAKjE,SAAS,UAAU,MAAgD;CACjE,IAAI,CAAC,MACH,OAAO,EAAE,MAAM,GAAG;CAGpB,MAAM,QAAQ,KAAK,MAAM,GAAG;CAE5B,IAAI,MAAM,SAAS,GACjB,OAAO;EACL,OAAO,MAAM;EACb,MAAM,MAAM;CACd;MAEA,OAAO,EACL,MAAM,MAAM,GACd;AAEJ;;;;;AAMA,SAAgB,WACd,UACA,OACyB;CACzB,MAAM,EAAE,UAAU,UAAU,SAAS,IAAI;CACzC,IAAI,OAAO;EACT,MAAM,OAAO,MAAM,IAAI,KAAK;EAC5B,IAAI,SAAS,SAAS;GACpB,MAAM,uCAAuC,SAAS,MAAM,KAAK;GACjE,OAAO;IACL,MAAM,UAAU;IAChB;IACA;IACA,UAAU,OAAO,KAAK,SAAS,QAAQ;GACzC;EACF;CACF;CAEA,MAAM,OAAO,MAAM,IAAI,SAAS,IAAI;CACpC,IAAI,CAAC,MAEH;CAGF,IAAI,SAAS,WAAW;EACtB,MAAM,qBAAqB,SAAS,IAAI;EACxC,OAAO;GACL,MAAM,UAAU;GAChB;GACA,SAAS,SAAS;GAClB,UAAU,OAAO,KAAK,SAAS,QAAQ;EACzC;CACF;CAEA,IAAI,SAAS,SACX,MAAM,IAAI,MAAM,8DAA4D;CAG9E,MAAM,gBAAgB,KAAK;CAC3B,IAAI,cAAc,WAAW,GAE3B;CAGF,MAAM,kBAA4B,CAAC;CACnC,OAAO,KAAK,SAAS,QAAQ,CAAC,CAAC,SAAS,YAAY;EAClD,cAAc,SAAS,iBAAiB;GACtC,IACE,UAAU,SAAS,cAAc;IAC/B,mBAAmB;IACnB,OAAO;GACT,CAAC,GAED,gBAAgB,KAAK,OAAO;EAEhC,CAAC;CACH,CAAC;CAED,IAAI,gBAAgB,SAAS,GAC3B,MACE,6CACA,SAAS,MACT,gBAAgB,QAChB,eACF;CAGF,OAAO;EACL,MAAM,UAAU;EAChB;EACA,UAAU;CACZ;AACF;;;;;;AAOA,SAAgB,iBAAiB,YAG/B;CAGA,OAAO;EAAE,UADP,CAAC,CAAC,eAAe,WAAW,SAAS,UAAU,SAAS,WAAW,SAAS,UAAU;EACrE,qBAAqB,YAAY,YAAY,CAAC;CAAE;AACrE"}
1
+ {"version":3,"file":"matcher.mjs","names":[],"sources":["../../src/filtering/matcher.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { Minimatch } from 'minimatch';\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\ninterface CompiledGlobRule {\n pattern: string;\n matcher: Minimatch;\n rule: ParsedRule;\n}\n\ninterface CompiledGlobRules {\n packages: CompiledGlobRule[];\n scopes: CompiledGlobRule[];\n}\n\nconst compiledGlobRules = new WeakMap<Map<string, ParsedRule>, CompiledGlobRules>();\nconst globMagic = /[\\\\*?[\\]{}!]|[+@]\\(/;\n\n/**\n * Compile patterns requiring glob or escape handling, grouped by rule type.\n */\nfunction compileGlobRules(rules: Map<string, ParsedRule>): CompiledGlobRules {\n const compiled: CompiledGlobRules = { packages: [], scopes: [] };\n\n for (const [pattern, rule] of rules) {\n if (!globMagic.test(pattern)) {\n continue;\n }\n\n const matcher = new Minimatch(pattern);\n const compiledRule = { pattern, matcher, rule };\n if (rule === 'scope') {\n compiled.scopes.push(compiledRule);\n } else {\n compiled.packages.push(compiledRule);\n }\n }\n\n return compiled;\n}\n\n/**\n * Cache the compiled glob rules for a rule map. Call again after changing the map.\n */\nexport function prepareRules(rules: Map<string, ParsedRule>): void {\n compiledGlobRules.set(rules, compileGlobRules(rules));\n}\n\n/**\n * Return cached glob rules, compiling and caching unprepared maps on first use.\n */\nfunction getCompiledGlobRules(rules: Map<string, ParsedRule>): CompiledGlobRules {\n let compiled = compiledGlobRules.get(rules);\n if (!compiled) {\n compiled = compileGlobRules(rules);\n compiledGlobRules.set(rules, compiled);\n }\n\n return compiled;\n}\n\nfunction findScopeRule(\n scope: string | undefined,\n rules: Map<string, ParsedRule>\n): { scope: string; rule: 'scope' } | undefined {\n if (!scope) {\n return undefined;\n }\n\n const exactRule = rules.get(scope);\n if (exactRule === 'scope') {\n return { scope, rule: exactRule };\n }\n\n for (const { pattern, matcher } of getCompiledGlobRules(rules).scopes) {\n if (matcher.match(scope)) {\n return { scope: pattern, rule: 'scope' };\n }\n }\n\n return undefined;\n}\n\nfunction findPackageRule(\n packageName: string,\n rules: Map<string, ParsedRule>\n): { pattern: string; rule: ParsedRule } | undefined {\n const exactRule = rules.get(packageName);\n if (exactRule) {\n return { pattern: packageName, rule: exactRule };\n }\n\n for (const { pattern, matcher, rule } of getCompiledGlobRules(rules).packages) {\n if (matcher.match(packageName)) {\n return { pattern, rule };\n }\n }\n\n return undefined;\n}\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 * Rule maps are cached; call prepareRules after modifying them.\n */\nexport function matchRules(\n manifest: Manifest,\n rules: Map<string, ParsedRule>\n): MatchResult | undefined {\n const packageName = manifest.name;\n if (!packageName) {\n return undefined;\n }\n\n const { scope } = splitName(packageName);\n const scopeMatch = findScopeRule(scope, rules);\n if (scopeMatch) {\n debug('scope match: %s matched rule for %s', packageName, scopeMatch.scope);\n return {\n type: MatchType.SCOPE,\n rule: scopeMatch.rule,\n scope: scopeMatch.scope,\n versions: Object.keys(manifest.versions),\n };\n }\n\n const packageMatch = findPackageRule(packageName, rules);\n if (!packageMatch) {\n // No match\n return undefined;\n }\n const { rule } = packageMatch;\n\n if (rule === 'package') {\n debug('package match: %s matched rule for %s', packageName, packageMatch.pattern);\n return {\n type: MatchType.PACKAGE,\n rule,\n package: packageMatch.pattern,\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\n/**\n * Derive the allow-list outcome from a precomputed allow-rule match:\n * whether the whole package/scope is allow-listed, and which versions\n * (if any) are individually whitelisted.\n */\nexport function resolveAllowList(allowMatch: MatchResult | undefined): {\n allowAll: boolean;\n whitelistedVersions: string[];\n} {\n const allowAll =\n !!allowMatch && (allowMatch.type === MatchType.SCOPE || allowMatch.type === MatchType.PACKAGE);\n return { allowAll, whitelistedVersions: allowMatch?.versions ?? [] };\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  const require_runtime = require("./_virtual/_rolldown/runtime.js");
2
- const require_parser = require("./config/parser.js");
3
2
  const require_matcher = require("./filtering/matcher.js");
3
+ const require_parser = require("./config/parser.js");
4
4
  const require_deprecated = require("./filtering/deprecated.js");
5
5
  const require_packageVersion = require("./filtering/packageVersion.js");
6
6
  const require_publishDate = require("./filtering/publishDate.js");
@@ -1,5 +1,5 @@
1
- import { parseConfig } from "./config/parser.mjs";
2
1
  import { matchRules } from "./filtering/matcher.mjs";
2
+ import { parseConfig } from "./config/parser.mjs";
3
3
  import { filterDeprecatedVersions } from "./filtering/deprecated.mjs";
4
4
  import { filterBlockedVersions } from "./filtering/packageVersion.mjs";
5
5
  import { filterVersionsByPublishDate } from "./filtering/publishDate.mjs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@verdaccio/package-filter",
3
- "version": "14.0.0-next-9.55",
3
+ "version": "14.0.0-next-9.56",
4
4
  "description": "Package filter plugin for Verdaccio that allows blocking packages by name, scope, version or date",
5
5
  "keywords": [
6
6
  "private",
@@ -35,19 +35,20 @@
35
35
  "node": ">=24"
36
36
  },
37
37
  "dependencies": {
38
- "@verdaccio/core": "9.0.0-next-9.31",
38
+ "@verdaccio/core": "9.0.0-next-9.32",
39
39
  "debug": "4.4.3",
40
+ "minimatch": "10.2.6",
40
41
  "semver": "7.8.5"
41
42
  },
42
43
  "devDependencies": {
43
44
  "@types/debug": "4.1.13",
44
- "@verdaccio/config": "9.0.0-next-9.31",
45
- "@verdaccio/logger": "9.0.0-next-9.31",
46
- "@verdaccio/plugin-verifier": "1.0.0-next-9.27",
47
- "@verdaccio/types": "14.0.0-next-9.14",
45
+ "@verdaccio/config": "9.0.0-next-9.32",
46
+ "@verdaccio/logger": "9.0.0-next-9.32",
47
+ "@verdaccio/plugin-verifier": "1.0.0-next-9.28",
48
+ "@verdaccio/types": "14.0.0-next-9.15",
48
49
  "rimraf": "6.1.3",
49
50
  "vite": "8.2.2",
50
- "vitest": "4.1.10"
51
+ "vitest": "4.1.11"
51
52
  },
52
53
  "funding": {
53
54
  "type": "opencollective",