@vltpkg/query 0.0.0-8 → 1.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/README.md +38 -249
  2. package/dist/esm/attribute.d.ts +1 -1
  3. package/dist/esm/attribute.d.ts.map +1 -1
  4. package/dist/esm/attribute.js +5 -12
  5. package/dist/esm/attribute.js.map +1 -1
  6. package/dist/esm/combinator.d.ts.map +1 -1
  7. package/dist/esm/combinator.js +1 -1
  8. package/dist/esm/combinator.js.map +1 -1
  9. package/dist/esm/id.d.ts.map +1 -1
  10. package/dist/esm/id.js +23 -7
  11. package/dist/esm/id.js.map +1 -1
  12. package/dist/esm/index.d.ts +29 -7
  13. package/dist/esm/index.d.ts.map +1 -1
  14. package/dist/esm/index.js +247 -21
  15. package/dist/esm/index.js.map +1 -1
  16. package/dist/esm/parser.d.ts +15 -0
  17. package/dist/esm/parser.d.ts.map +1 -0
  18. package/dist/esm/parser.js +93 -0
  19. package/dist/esm/parser.js.map +1 -0
  20. package/dist/esm/pseudo/attr.d.ts +2 -1
  21. package/dist/esm/pseudo/attr.d.ts.map +1 -1
  22. package/dist/esm/pseudo/attr.js +10 -2
  23. package/dist/esm/pseudo/attr.js.map +1 -1
  24. package/dist/esm/pseudo/built.d.ts +8 -0
  25. package/dist/esm/pseudo/built.d.ts.map +1 -0
  26. package/dist/esm/pseudo/built.js +16 -0
  27. package/dist/esm/pseudo/built.js.map +1 -0
  28. package/dist/esm/pseudo/confused.d.ts +4 -2
  29. package/dist/esm/pseudo/confused.d.ts.map +1 -1
  30. package/dist/esm/pseudo/confused.js +15 -2
  31. package/dist/esm/pseudo/confused.js.map +1 -1
  32. package/dist/esm/pseudo/cve.d.ts +2 -1
  33. package/dist/esm/pseudo/cve.d.ts.map +1 -1
  34. package/dist/esm/pseudo/cve.js +2 -2
  35. package/dist/esm/pseudo/cve.js.map +1 -1
  36. package/dist/esm/pseudo/cwe.d.ts +2 -1
  37. package/dist/esm/pseudo/cwe.d.ts.map +1 -1
  38. package/dist/esm/pseudo/cwe.js +2 -2
  39. package/dist/esm/pseudo/cwe.js.map +1 -1
  40. package/dist/esm/pseudo/dev.d.ts +6 -0
  41. package/dist/esm/pseudo/dev.d.ts.map +1 -0
  42. package/dist/esm/pseudo/dev.js +15 -0
  43. package/dist/esm/pseudo/dev.js.map +1 -0
  44. package/dist/esm/pseudo/empty.d.ts +7 -0
  45. package/dist/esm/pseudo/empty.d.ts.map +1 -0
  46. package/dist/esm/pseudo/empty.js +14 -0
  47. package/dist/esm/pseudo/empty.js.map +1 -0
  48. package/dist/esm/pseudo/helpers.d.ts +13 -1
  49. package/dist/esm/pseudo/helpers.d.ts.map +1 -1
  50. package/dist/esm/pseudo/helpers.js +27 -0
  51. package/dist/esm/pseudo/helpers.js.map +1 -1
  52. package/dist/esm/pseudo/host.d.ts +20 -0
  53. package/dist/esm/pseudo/host.d.ts.map +1 -0
  54. package/dist/esm/pseudo/host.js +80 -0
  55. package/dist/esm/pseudo/host.js.map +1 -0
  56. package/dist/esm/pseudo/license.d.ts +2 -1
  57. package/dist/esm/pseudo/license.d.ts.map +1 -1
  58. package/dist/esm/pseudo/license.js +19 -2
  59. package/dist/esm/pseudo/license.js.map +1 -1
  60. package/dist/esm/pseudo/link.d.ts +9 -0
  61. package/dist/esm/pseudo/link.d.ts.map +1 -0
  62. package/dist/esm/pseudo/link.js +25 -0
  63. package/dist/esm/pseudo/link.js.map +1 -0
  64. package/dist/esm/pseudo/malware.d.ts +13 -1
  65. package/dist/esm/pseudo/malware.d.ts.map +1 -1
  66. package/dist/esm/pseudo/malware.js +140 -10
  67. package/dist/esm/pseudo/malware.js.map +1 -1
  68. package/dist/esm/pseudo/missing.d.ts +8 -0
  69. package/dist/esm/pseudo/missing.d.ts.map +1 -0
  70. package/dist/esm/pseudo/missing.js +15 -0
  71. package/dist/esm/pseudo/missing.js.map +1 -0
  72. package/dist/esm/pseudo/optional.d.ts +6 -0
  73. package/dist/esm/pseudo/optional.d.ts.map +1 -0
  74. package/dist/esm/pseudo/optional.js +15 -0
  75. package/dist/esm/pseudo/optional.js.map +1 -0
  76. package/dist/esm/pseudo/outdated.d.ts +4 -4
  77. package/dist/esm/pseudo/outdated.d.ts.map +1 -1
  78. package/dist/esm/pseudo/outdated.js +44 -33
  79. package/dist/esm/pseudo/outdated.js.map +1 -1
  80. package/dist/esm/pseudo/overridden.d.ts +8 -0
  81. package/dist/esm/pseudo/overridden.d.ts.map +1 -0
  82. package/dist/esm/pseudo/overridden.js +17 -0
  83. package/dist/esm/pseudo/overridden.js.map +1 -0
  84. package/dist/esm/pseudo/path.d.ts +19 -0
  85. package/dist/esm/pseudo/path.d.ts.map +1 -0
  86. package/dist/esm/pseudo/path.js +113 -0
  87. package/dist/esm/pseudo/path.js.map +1 -0
  88. package/dist/esm/pseudo/peer.d.ts +6 -0
  89. package/dist/esm/pseudo/peer.d.ts.map +1 -0
  90. package/dist/esm/pseudo/peer.js +15 -0
  91. package/dist/esm/pseudo/peer.js.map +1 -0
  92. package/dist/esm/pseudo/prerelease.d.ts +18 -0
  93. package/dist/esm/pseudo/prerelease.d.ts.map +1 -0
  94. package/dist/esm/pseudo/prerelease.js +41 -0
  95. package/dist/esm/pseudo/prerelease.js.map +1 -0
  96. package/dist/esm/pseudo/private.d.ts +7 -0
  97. package/dist/esm/pseudo/private.d.ts.map +1 -0
  98. package/dist/esm/pseudo/private.js +16 -0
  99. package/dist/esm/pseudo/private.js.map +1 -0
  100. package/dist/esm/pseudo/prod.d.ts +6 -0
  101. package/dist/esm/pseudo/prod.d.ts.map +1 -0
  102. package/dist/esm/pseudo/prod.js +15 -0
  103. package/dist/esm/pseudo/prod.js.map +1 -0
  104. package/dist/esm/pseudo/published.d.ts +40 -0
  105. package/dist/esm/pseudo/published.d.ts.map +1 -0
  106. package/dist/esm/pseudo/published.js +180 -0
  107. package/dist/esm/pseudo/published.js.map +1 -0
  108. package/dist/esm/pseudo/root.d.ts +7 -0
  109. package/dist/esm/pseudo/root.d.ts.map +1 -0
  110. package/dist/esm/pseudo/root.js +18 -0
  111. package/dist/esm/pseudo/root.js.map +1 -0
  112. package/dist/esm/pseudo/scanned.d.ts +4 -2
  113. package/dist/esm/pseudo/scanned.d.ts.map +1 -1
  114. package/dist/esm/pseudo/scanned.js +10 -5
  115. package/dist/esm/pseudo/scanned.js.map +1 -1
  116. package/dist/esm/pseudo/score.d.ts +16 -0
  117. package/dist/esm/pseudo/score.d.ts.map +1 -0
  118. package/dist/esm/pseudo/score.js +133 -0
  119. package/dist/esm/pseudo/score.js.map +1 -0
  120. package/dist/esm/pseudo/scripts.d.ts +7 -4
  121. package/dist/esm/pseudo/scripts.d.ts.map +1 -1
  122. package/dist/esm/pseudo/scripts.js +41 -3
  123. package/dist/esm/pseudo/scripts.js.map +1 -1
  124. package/dist/esm/pseudo/semver.d.ts +2 -1
  125. package/dist/esm/pseudo/semver.d.ts.map +1 -1
  126. package/dist/esm/pseudo/semver.js +11 -24
  127. package/dist/esm/pseudo/semver.js.map +1 -1
  128. package/dist/esm/pseudo/severity.d.ts +4 -1
  129. package/dist/esm/pseudo/severity.d.ts.map +1 -1
  130. package/dist/esm/pseudo/severity.js +111 -8
  131. package/dist/esm/pseudo/severity.js.map +1 -1
  132. package/dist/esm/pseudo/spec.d.ts +17 -0
  133. package/dist/esm/pseudo/spec.d.ts.map +1 -0
  134. package/dist/esm/pseudo/spec.js +102 -0
  135. package/dist/esm/pseudo/spec.js.map +1 -0
  136. package/dist/esm/pseudo/squat.d.ts +4 -1
  137. package/dist/esm/pseudo/squat.d.ts.map +1 -1
  138. package/dist/esm/pseudo/squat.js +127 -9
  139. package/dist/esm/pseudo/squat.js.map +1 -1
  140. package/dist/esm/pseudo/type.d.ts +8 -0
  141. package/dist/esm/pseudo/type.d.ts.map +1 -0
  142. package/dist/esm/pseudo/type.js +22 -0
  143. package/dist/esm/pseudo/type.js.map +1 -0
  144. package/dist/esm/pseudo/workspace.d.ts +6 -0
  145. package/dist/esm/pseudo/workspace.d.ts.map +1 -0
  146. package/dist/esm/pseudo/workspace.js +20 -0
  147. package/dist/esm/pseudo/workspace.js.map +1 -0
  148. package/dist/esm/pseudo.d.ts.map +1 -1
  149. package/dist/esm/pseudo.js +81 -105
  150. package/dist/esm/pseudo.js.map +1 -1
  151. package/dist/esm/types.d.ts +97 -27
  152. package/dist/esm/types.d.ts.map +1 -1
  153. package/dist/esm/types.js +1 -106
  154. package/dist/esm/types.js.map +1 -1
  155. package/package.json +20 -16
  156. package/dist/esm/class.d.ts +0 -6
  157. package/dist/esm/class.d.ts.map +0 -1
  158. package/dist/esm/class.js +0 -131
  159. package/dist/esm/class.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../src/pseudo/link.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAG9C;;;;;GAKG;AACH,eAAO,MAAM,IAAI,UAAiB,WAAW,yBAmB5C,CAAA"}
@@ -0,0 +1,25 @@
1
+ import { splitDepID } from '@vltpkg/dep-id/browser';
2
+ import { removeNode } from "./helpers.js";
3
+ /**
4
+ * :link Pseudo-Selector, matches only nodes that are file links.
5
+ *
6
+ * It filters out any node that is not of type 'file' or nodes of 'file'
7
+ * type that ends with 'tar.gz' since these are local tarballs.
8
+ */
9
+ export const link = async (state) => {
10
+ for (const node of state.partial.nodes) {
11
+ const [type, path] = splitDepID(node.id);
12
+ if (type !== 'file' || path.endsWith('tar.gz') || path === '.') {
13
+ removeNode(state, node);
14
+ }
15
+ }
16
+ for (const edge of state.partial.edges) {
17
+ if (!edge.spec.file ||
18
+ edge.spec.file.endsWith('tar.gz') ||
19
+ edge.spec.file === '.') {
20
+ state.partial.edges.delete(edge);
21
+ }
22
+ }
23
+ return state;
24
+ };
25
+ //# sourceMappingURL=link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.js","sourceRoot":"","sources":["../../../src/pseudo/link.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAEnD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEzC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,EAAE,KAAkB,EAAE,EAAE;IAC/C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACvC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACxC,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YAC/D,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QACzB,CAAC;IACH,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACvC,IACE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;YACf,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;YACjC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,GAAG,EACtB,CAAC;YACD,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QAClC,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA","sourcesContent":["import { splitDepID } from '@vltpkg/dep-id/browser'\nimport type { ParserState } from '../types.ts'\nimport { removeNode } from './helpers.ts'\n\n/**\n * :link Pseudo-Selector, matches only nodes that are file links.\n *\n * It filters out any node that is not of type 'file' or nodes of 'file'\n * type that ends with 'tar.gz' since these are local tarballs.\n */\nexport const link = async (state: ParserState) => {\n for (const node of state.partial.nodes) {\n const [type, path] = splitDepID(node.id)\n if (type !== 'file' || path.endsWith('tar.gz') || path === '.') {\n removeNode(state, node)\n }\n }\n\n for (const edge of state.partial.edges) {\n if (\n !edge.spec.file ||\n edge.spec.file.endsWith('tar.gz') ||\n edge.spec.file === '.'\n ) {\n state.partial.edges.delete(edge)\n }\n }\n\n return state\n}\n"]}
@@ -1,11 +1,23 @@
1
- import type { ParserState, PostcssNode } from '../types.ts';
1
+ import type { ParserState } from '../types.ts';
2
+ import type { PostcssNode } from '@vltpkg/dss-parser';
2
3
  export type MalwareKinds = '0' | '1' | '2' | '3' | 'critical' | 'high' | 'medium' | 'low' | undefined;
3
4
  export type MalwareAlertTypes = 'malware' | 'gptMalware' | 'gptSecurity' | 'gptAnomaly' | undefined;
5
+ export type MalwareComparator = '>' | '<' | '>=' | '<=' | undefined;
4
6
  export declare const isMalwareKind: (value?: string) => value is MalwareKinds;
5
7
  export declare const asMalwareKind: (value?: string) => MalwareKinds;
6
8
  export declare const parseInternals: (nodes: PostcssNode[]) => {
7
9
  kind: MalwareKinds;
10
+ comparator: MalwareComparator;
8
11
  };
12
+ /**
13
+ * :malware Pseudo-Selector, matches nodes with malware alerts.
14
+ *
15
+ * Usage:
16
+ * - :malware - matches malware with severity >= medium (critical, high, medium but not low)
17
+ * - :malware(critical) - matches specific malware kind
18
+ * - :malware(>1) - matches malware with severity greater than 1
19
+ * - :malware(">=medium") - matches malware with severity >= medium
20
+ */
9
21
  export declare const malware: (state: ParserState) => Promise<ParserState & {
10
22
  securityArchive: NonNullable<ParserState["securityArchive"]>;
11
23
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"malware.d.ts","sourceRoot":"","sources":["../../../src/pseudo/malware.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAQ3D,MAAM,MAAM,YAAY,GACpB,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,UAAU,GACV,MAAM,GACN,QAAQ,GACR,KAAK,GACL,SAAS,CAAA;AAEb,MAAM,MAAM,iBAAiB,GACzB,SAAS,GACT,YAAY,GACZ,aAAa,GACb,YAAY,GACZ,SAAS,CAAA;AAcb,eAAO,MAAM,aAAa,WAChB,MAAM,KACb,KAAK,IAAI,YAAgD,CAAA;AAE5D,eAAO,MAAM,aAAa,WAAY,MAAM,KAAG,YAQ9C,CAAA;AAED,eAAO,MAAM,cAAc,UAClB,WAAW,EAAE,KACnB;IAAE,IAAI,EAAE,YAAY,CAAA;CAmBtB,CAAA;AAED,eAAO,MAAM,OAAO,UAAiB,WAAW;;EA2B/C,CAAA"}
1
+ {"version":3,"file":"malware.d.ts","sourceRoot":"","sources":["../../../src/pseudo/malware.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAErD,MAAM,MAAM,YAAY,GACpB,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,UAAU,GACV,MAAM,GACN,QAAQ,GACR,KAAK,GACL,SAAS,CAAA;AAEb,MAAM,MAAM,iBAAiB,GACzB,SAAS,GACT,YAAY,GACZ,aAAa,GACb,YAAY,GACZ,SAAS,CAAA;AAEb,MAAM,MAAM,iBAAiB,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAA;AA2BnE,eAAO,MAAM,aAAa,WAChB,MAAM,KACb,KAAK,IAAI,YAAgD,CAAA;AAE5D,eAAO,MAAM,aAAa,WAAY,MAAM,KAAG,YAQ9C,CAAA;AAED,eAAO,MAAM,cAAc,UAClB,WAAW,EAAE,KACnB;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,iBAAiB,CAAA;CAyDrD,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,UAAiB,WAAW;;EA0G/C,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { error } from '@vltpkg/error-cause';
2
- import { asPostcssNodeWithChildren, asStringNode, asTagNode, isStringNode, isTagNode, } from "../types.js";
2
+ import { asPostcssNodeWithChildren, asStringNode, asTagNode, isStringNode, isTagNode, } from '@vltpkg/dss-parser';
3
3
  import { assertSecurityArchive, removeDanglingEdges, removeNode, removeQuotes, } from "./helpers.js";
4
4
  const kindsMap = new Map([
5
5
  ['critical', 'malware'],
@@ -11,6 +11,17 @@ const kindsMap = new Map([
11
11
  ['2', 'gptSecurity'],
12
12
  ['3', 'gptAnomaly'],
13
13
  ]);
14
+ // Map numerical values to their respective kinds for comparison operations
15
+ const kindLevelMap = new Map([
16
+ ['critical', 0],
17
+ ['high', 1],
18
+ ['medium', 2],
19
+ ['low', 3],
20
+ ['0', 0],
21
+ ['1', 1],
22
+ ['2', 2],
23
+ ['3', 3],
24
+ ]);
14
25
  const kinds = new Set(kindsMap.keys());
15
26
  export const isMalwareKind = (value) => kinds.has(value);
16
27
  export const asMalwareKind = (value) => {
@@ -23,16 +34,67 @@ export const asMalwareKind = (value) => {
23
34
  return value;
24
35
  };
25
36
  export const parseInternals = (nodes) => {
37
+ // Handle case where no parameters are provided (parameterless :malware)
38
+ if (!nodes[0]) {
39
+ return { kind: undefined, comparator: undefined };
40
+ }
41
+ const selectorNode = asPostcssNodeWithChildren(nodes[0]);
42
+ if (!selectorNode.nodes[0]) {
43
+ return { kind: undefined, comparator: undefined };
44
+ }
45
+ let kindValue = '';
46
+ let comparator = undefined;
26
47
  let kind;
27
- if (isStringNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])) {
28
- kind = asMalwareKind(removeQuotes(asStringNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])
29
- .value));
48
+ // Parse the parameter (kind with optional comparator)
49
+ if (isStringNode(selectorNode.nodes[0])) {
50
+ kindValue = removeQuotes(asStringNode(selectorNode.nodes[0]).value);
51
+ }
52
+ else if (isTagNode(selectorNode.nodes[0])) {
53
+ kindValue = asTagNode(selectorNode.nodes[0]).value;
54
+ }
55
+ // Extract comparator if present
56
+ if (kindValue.startsWith('>=')) {
57
+ comparator = '>=';
58
+ kindValue = kindValue.substring(2);
30
59
  }
31
- else if (isTagNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])) {
32
- kind = asMalwareKind(asTagNode(asPostcssNodeWithChildren(nodes[0]).nodes[0]).value);
60
+ else if (kindValue.startsWith('<=')) {
61
+ comparator = '<=';
62
+ kindValue = kindValue.substring(2);
33
63
  }
34
- return { kind };
64
+ else if (kindValue.startsWith('>')) {
65
+ comparator = '>';
66
+ kindValue = kindValue.substring(1);
67
+ }
68
+ else if (kindValue.startsWith('<')) {
69
+ comparator = '<';
70
+ kindValue = kindValue.substring(1);
71
+ }
72
+ // Validate the kind without comparator
73
+ if (!comparator) {
74
+ kind = asMalwareKind(kindValue);
75
+ }
76
+ else {
77
+ // For comparisons, just make sure it's a valid numeric value or a valid kind
78
+ if (isMalwareKind(kindValue)) {
79
+ kind = kindValue;
80
+ }
81
+ else {
82
+ throw error('Expected a valid malware kind or number between 0-3', {
83
+ found: kindValue,
84
+ });
85
+ }
86
+ }
87
+ return { kind, comparator };
35
88
  };
89
+ /**
90
+ * :malware Pseudo-Selector, matches nodes with malware alerts.
91
+ *
92
+ * Usage:
93
+ * - :malware - matches malware with severity >= medium (critical, high, medium but not low)
94
+ * - :malware(critical) - matches specific malware kind
95
+ * - :malware(>1) - matches malware with severity greater than 1
96
+ * - :malware(">=medium") - matches malware with severity >= medium
97
+ */
36
98
  export const malware = async (state) => {
37
99
  assertSecurityArchive(state, 'malware');
38
100
  let internals;
@@ -42,11 +104,79 @@ export const malware = async (state) => {
42
104
  catch (err) {
43
105
  throw error('Failed to parse :malware selector', { cause: err });
44
106
  }
45
- const { kind } = internals;
46
- const alertName = kindsMap.get(kind);
107
+ const { kind, comparator } = internals;
108
+ const alertName = comparator ? undefined : kindsMap.get(kind);
109
+ for (const node of state.partial.nodes) {
110
+ const report = state.securityArchive.get(node.id);
111
+ // Always exclude nodes that don't have security data or alerts
112
+ if (!report?.alerts || report.alerts.length === 0) {
113
+ removeNode(state, node);
114
+ }
115
+ }
47
116
  for (const node of state.partial.nodes) {
48
117
  const report = state.securityArchive.get(node.id);
49
- const exclude = !report?.alerts.some(alert => alert.type === alertName);
118
+ let exclude = true;
119
+ if (report) {
120
+ if (kind === undefined && comparator === undefined) {
121
+ // Parameterless :malware - match malware alerts with severity >= medium (exclude low/gptAnomaly)
122
+ exclude = !report.alerts.some(alert => alert.type === 'malware' ||
123
+ alert.type === 'gptMalware' ||
124
+ alert.type === 'gptSecurity');
125
+ }
126
+ else if (comparator) {
127
+ // retrieve the value to compare against
128
+ const kindLevel = kindLevelMap.get(kind);
129
+ // the kindLevel value has already been validated at this point
130
+ // and thus can never return an undefined/falsy value but ts doesn't
131
+ // know about that, so we have the extra check here
132
+ /* c8 ignore next - impossible */
133
+ if (kindLevel == null)
134
+ break;
135
+ // Check each alert to find any that match our comparison criteria
136
+ for (const alert of report.alerts) {
137
+ // Get the numerical value of the alert type
138
+ const alertType = alert.type;
139
+ // retrieve a key to the current alert level to be compared against
140
+ const currentAlertLevelKey = [...kindsMap.entries()].find(([_, alertValue]) => alertValue === alertType)?.[0];
141
+ // perform the comparison based on the user-provided kindLevel
142
+ if (currentAlertLevelKey) {
143
+ const currentAlertLevel = kindLevelMap.get(currentAlertLevelKey);
144
+ /* c8 ignore next - impossible but ts doesn't know */
145
+ if (currentAlertLevel == null)
146
+ continue;
147
+ switch (comparator) {
148
+ case '>':
149
+ if (currentAlertLevel > kindLevel) {
150
+ exclude = false;
151
+ }
152
+ break;
153
+ case '<':
154
+ if (currentAlertLevel < kindLevel) {
155
+ exclude = false;
156
+ }
157
+ break;
158
+ case '>=':
159
+ if (currentAlertLevel >= kindLevel) {
160
+ exclude = false;
161
+ }
162
+ break;
163
+ case '<=':
164
+ if (currentAlertLevel <= kindLevel) {
165
+ exclude = false;
166
+ }
167
+ break;
168
+ }
169
+ // If we've found a match, no need to check other alerts
170
+ if (!exclude)
171
+ break;
172
+ }
173
+ }
174
+ }
175
+ else {
176
+ // Original exact match behavior
177
+ exclude = !report.alerts.some(alert => alert.type === alertName);
178
+ }
179
+ }
50
180
  if (exclude) {
51
181
  removeNode(state, node);
52
182
  }
@@ -1 +1 @@
1
- {"version":3,"file":"malware.js","sourceRoot":"","sources":["../../../src/pseudo/malware.ts"],"names":[],"mappings":"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","sourcesContent":["import { error } from '@vltpkg/error-cause'\nimport {\n asPostcssNodeWithChildren,\n asStringNode,\n asTagNode,\n isStringNode,\n isTagNode,\n} from '../types.ts'\nimport type { ParserState, PostcssNode } from '../types.ts'\nimport {\n assertSecurityArchive,\n removeDanglingEdges,\n removeNode,\n removeQuotes,\n} from './helpers.ts'\n\nexport type MalwareKinds =\n | '0'\n | '1'\n | '2'\n | '3'\n | 'critical'\n | 'high'\n | 'medium'\n | 'low'\n | undefined\n\nexport type MalwareAlertTypes =\n | 'malware'\n | 'gptMalware'\n | 'gptSecurity'\n | 'gptAnomaly'\n | undefined\n\nconst kindsMap = new Map<MalwareKinds, MalwareAlertTypes>([\n ['critical', 'malware'],\n ['high', 'gptMalware'],\n ['medium', 'gptSecurity'],\n ['low', 'gptAnomaly'],\n ['0', 'malware'],\n ['1', 'gptMalware'],\n ['2', 'gptSecurity'],\n ['3', 'gptAnomaly'],\n])\nconst kinds = new Set(kindsMap.keys())\n\nexport const isMalwareKind = (\n value?: string,\n): value is MalwareKinds => kinds.has(value as MalwareKinds)\n\nexport const asMalwareKind = (value?: string): MalwareKinds => {\n if (!isMalwareKind(value)) {\n throw error('Expected a valid malware kind', {\n found: value,\n validOptions: Array.from(kinds),\n })\n }\n return value\n}\n\nexport const parseInternals = (\n nodes: PostcssNode[],\n): { kind: MalwareKinds } => {\n let kind: MalwareKinds\n\n if (isStringNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])) {\n kind = asMalwareKind(\n removeQuotes(\n asStringNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])\n .value,\n ),\n )\n } else if (\n isTagNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])\n ) {\n kind = asMalwareKind(\n asTagNode(asPostcssNodeWithChildren(nodes[0]).nodes[0]).value,\n )\n }\n\n return { kind }\n}\n\nexport const malware = async (state: ParserState) => {\n assertSecurityArchive(state, 'malware')\n\n let internals\n try {\n internals = parseInternals(\n asPostcssNodeWithChildren(state.current).nodes,\n )\n } catch (err) {\n throw error('Failed to parse :malware selector', { cause: err })\n }\n\n const { kind } = internals\n const alertName = kindsMap.get(kind)\n for (const node of state.partial.nodes) {\n const report = state.securityArchive.get(node.id)\n const exclude = !report?.alerts.some(\n alert => alert.type === alertName,\n )\n if (exclude) {\n removeNode(state, node)\n }\n }\n\n removeDanglingEdges(state)\n\n return state\n}\n"]}
1
+ {"version":3,"file":"malware.js","sourceRoot":"","sources":["../../../src/pseudo/malware.ts"],"names":[],"mappings":"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","sourcesContent":["import { error } from '@vltpkg/error-cause'\nimport {\n asPostcssNodeWithChildren,\n asStringNode,\n asTagNode,\n isStringNode,\n isTagNode,\n} from '@vltpkg/dss-parser'\nimport {\n assertSecurityArchive,\n removeDanglingEdges,\n removeNode,\n removeQuotes,\n} from './helpers.ts'\nimport type { ParserState } from '../types.ts'\nimport type { PostcssNode } from '@vltpkg/dss-parser'\n\nexport type MalwareKinds =\n | '0'\n | '1'\n | '2'\n | '3'\n | 'critical'\n | 'high'\n | 'medium'\n | 'low'\n | undefined\n\nexport type MalwareAlertTypes =\n | 'malware'\n | 'gptMalware'\n | 'gptSecurity'\n | 'gptAnomaly'\n | undefined\n\nexport type MalwareComparator = '>' | '<' | '>=' | '<=' | undefined\n\nconst kindsMap = new Map<MalwareKinds, MalwareAlertTypes>([\n ['critical', 'malware'],\n ['high', 'gptMalware'],\n ['medium', 'gptSecurity'],\n ['low', 'gptAnomaly'],\n ['0', 'malware'],\n ['1', 'gptMalware'],\n ['2', 'gptSecurity'],\n ['3', 'gptAnomaly'],\n])\n\n// Map numerical values to their respective kinds for comparison operations\nconst kindLevelMap = new Map<MalwareKinds, number>([\n ['critical', 0],\n ['high', 1],\n ['medium', 2],\n ['low', 3],\n ['0', 0],\n ['1', 1],\n ['2', 2],\n ['3', 3],\n])\n\nconst kinds = new Set(kindsMap.keys())\n\nexport const isMalwareKind = (\n value?: string,\n): value is MalwareKinds => kinds.has(value as MalwareKinds)\n\nexport const asMalwareKind = (value?: string): MalwareKinds => {\n if (!isMalwareKind(value)) {\n throw error('Expected a valid malware kind', {\n found: value,\n validOptions: Array.from(kinds),\n })\n }\n return value\n}\n\nexport const parseInternals = (\n nodes: PostcssNode[],\n): { kind: MalwareKinds; comparator: MalwareComparator } => {\n // Handle case where no parameters are provided (parameterless :malware)\n if (!nodes[0]) {\n return { kind: undefined, comparator: undefined }\n }\n\n const selectorNode = asPostcssNodeWithChildren(nodes[0])\n if (!selectorNode.nodes[0]) {\n return { kind: undefined, comparator: undefined }\n }\n\n let kindValue = ''\n let comparator: MalwareComparator = undefined\n let kind: MalwareKinds\n\n // Parse the parameter (kind with optional comparator)\n if (isStringNode(selectorNode.nodes[0])) {\n kindValue = removeQuotes(\n asStringNode(selectorNode.nodes[0]).value,\n )\n } else if (isTagNode(selectorNode.nodes[0])) {\n kindValue = asTagNode(selectorNode.nodes[0]).value\n }\n\n // Extract comparator if present\n if (kindValue.startsWith('>=')) {\n comparator = '>='\n kindValue = kindValue.substring(2)\n } else if (kindValue.startsWith('<=')) {\n comparator = '<='\n kindValue = kindValue.substring(2)\n } else if (kindValue.startsWith('>')) {\n comparator = '>'\n kindValue = kindValue.substring(1)\n } else if (kindValue.startsWith('<')) {\n comparator = '<'\n kindValue = kindValue.substring(1)\n }\n\n // Validate the kind without comparator\n if (!comparator) {\n kind = asMalwareKind(kindValue)\n } else {\n // For comparisons, just make sure it's a valid numeric value or a valid kind\n if (isMalwareKind(kindValue)) {\n kind = kindValue\n } else {\n throw error(\n 'Expected a valid malware kind or number between 0-3',\n {\n found: kindValue,\n },\n )\n }\n }\n\n return { kind, comparator }\n}\n\n/**\n * :malware Pseudo-Selector, matches nodes with malware alerts.\n *\n * Usage:\n * - :malware - matches malware with severity >= medium (critical, high, medium but not low)\n * - :malware(critical) - matches specific malware kind\n * - :malware(>1) - matches malware with severity greater than 1\n * - :malware(\">=medium\") - matches malware with severity >= medium\n */\nexport const malware = async (state: ParserState) => {\n assertSecurityArchive(state, 'malware')\n\n let internals\n try {\n internals = parseInternals(\n asPostcssNodeWithChildren(state.current).nodes,\n )\n } catch (err) {\n throw error('Failed to parse :malware selector', { cause: err })\n }\n\n const { kind, comparator } = internals\n const alertName = comparator ? undefined : kindsMap.get(kind)\n\n for (const node of state.partial.nodes) {\n const report = state.securityArchive.get(node.id)\n // Always exclude nodes that don't have security data or alerts\n if (!report?.alerts || report.alerts.length === 0) {\n removeNode(state, node)\n }\n }\n\n for (const node of state.partial.nodes) {\n const report = state.securityArchive.get(node.id)\n let exclude = true\n\n if (report) {\n if (kind === undefined && comparator === undefined) {\n // Parameterless :malware - match malware alerts with severity >= medium (exclude low/gptAnomaly)\n exclude = !report.alerts.some(\n alert =>\n alert.type === 'malware' ||\n alert.type === 'gptMalware' ||\n alert.type === 'gptSecurity',\n )\n } else if (comparator) {\n // retrieve the value to compare against\n const kindLevel = kindLevelMap.get(kind)\n // the kindLevel value has already been validated at this point\n // and thus can never return an undefined/falsy value but ts doesn't\n // know about that, so we have the extra check here\n /* c8 ignore next - impossible */\n if (kindLevel == null) break\n\n // Check each alert to find any that match our comparison criteria\n for (const alert of report.alerts) {\n // Get the numerical value of the alert type\n const alertType = alert.type\n\n // retrieve a key to the current alert level to be compared against\n const currentAlertLevelKey = [...kindsMap.entries()].find(\n ([_, alertValue]) => alertValue === alertType,\n )?.[0]\n\n // perform the comparison based on the user-provided kindLevel\n if (currentAlertLevelKey) {\n const currentAlertLevel = kindLevelMap.get(\n currentAlertLevelKey,\n )\n /* c8 ignore next - impossible but ts doesn't know */\n if (currentAlertLevel == null) continue\n\n switch (comparator) {\n case '>':\n if (currentAlertLevel > kindLevel) {\n exclude = false\n }\n break\n case '<':\n if (currentAlertLevel < kindLevel) {\n exclude = false\n }\n break\n case '>=':\n if (currentAlertLevel >= kindLevel) {\n exclude = false\n }\n break\n case '<=':\n if (currentAlertLevel <= kindLevel) {\n exclude = false\n }\n break\n }\n\n // If we've found a match, no need to check other alerts\n if (!exclude) break\n }\n }\n } else {\n // Original exact match behavior\n exclude = !report.alerts.some(\n alert => alert.type === alertName,\n )\n }\n }\n\n if (exclude) {\n removeNode(state, node)\n }\n }\n\n removeDanglingEdges(state)\n\n return state\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import type { ParserState } from '../types.ts';
2
+ /**
3
+ * :missing Pseudo-Selector, matches only edges that are not linked to any node.
4
+ * It filters out any edges that have a 'to' property, keeping only dangling edges
5
+ * and clears all nodes from the result.
6
+ */
7
+ export declare const missing: (state: ParserState) => Promise<ParserState>;
8
+ //# sourceMappingURL=missing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing.d.ts","sourceRoot":"","sources":["../../../src/pseudo/missing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C;;;;GAIG;AACH,eAAO,MAAM,OAAO,UAAiB,WAAW,yBAQ/C,CAAA"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * :missing Pseudo-Selector, matches only edges that are not linked to any node.
3
+ * It filters out any edges that have a 'to' property, keeping only dangling edges
4
+ * and clears all nodes from the result.
5
+ */
6
+ export const missing = async (state) => {
7
+ for (const edge of state.partial.edges) {
8
+ if (edge.to) {
9
+ state.partial.edges.delete(edge);
10
+ }
11
+ }
12
+ state.partial.nodes.clear();
13
+ return state;
14
+ };
15
+ //# sourceMappingURL=missing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing.js","sourceRoot":"","sources":["../../../src/pseudo/missing.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,EAAE,KAAkB,EAAE,EAAE;IAClD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACvC,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACZ,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QAClC,CAAC;IACH,CAAC;IACD,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;IAC3B,OAAO,KAAK,CAAA;AACd,CAAC,CAAA","sourcesContent":["import type { ParserState } from '../types.ts'\n\n/**\n * :missing Pseudo-Selector, matches only edges that are not linked to any node.\n * It filters out any edges that have a 'to' property, keeping only dangling edges\n * and clears all nodes from the result.\n */\nexport const missing = async (state: ParserState) => {\n for (const edge of state.partial.edges) {\n if (edge.to) {\n state.partial.edges.delete(edge)\n }\n }\n state.partial.nodes.clear()\n return state\n}\n"]}
@@ -0,0 +1,6 @@
1
+ import type { ParserState } from '../types.ts';
2
+ /**
3
+ * :optional Pseudo-Selector will only match optional dependencies.
4
+ */
5
+ export declare const optional: (state: ParserState) => Promise<ParserState>;
6
+ //# sourceMappingURL=optional.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional.d.ts","sourceRoot":"","sources":["../../../src/pseudo/optional.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAG9C;;GAEG;AACH,eAAO,MAAM,QAAQ,UAAiB,WAAW,yBAWhD,CAAA"}
@@ -0,0 +1,15 @@
1
+ import { removeEdge, removeUnlinkedNodes } from "./helpers.js";
2
+ /**
3
+ * :optional Pseudo-Selector will only match optional dependencies.
4
+ */
5
+ export const optional = async (state) => {
6
+ // filter edges that aren't marked as optional
7
+ for (const edge of state.partial.edges) {
8
+ if (!edge.optional) {
9
+ removeEdge(state, edge);
10
+ }
11
+ }
12
+ removeUnlinkedNodes(state);
13
+ return state;
14
+ };
15
+ //# sourceMappingURL=optional.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional.js","sourceRoot":"","sources":["../../../src/pseudo/optional.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAE9D;;GAEG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,EAAE,KAAkB,EAAE,EAAE;IACnD,8CAA8C;IAC9C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QACzB,CAAC;IACH,CAAC;IAED,mBAAmB,CAAC,KAAK,CAAC,CAAA;IAE1B,OAAO,KAAK,CAAA;AACd,CAAC,CAAA","sourcesContent":["import type { ParserState } from '../types.ts'\nimport { removeEdge, removeUnlinkedNodes } from './helpers.ts'\n\n/**\n * :optional Pseudo-Selector will only match optional dependencies.\n */\nexport const optional = async (state: ParserState) => {\n // filter edges that aren't marked as optional\n for (const edge of state.partial.edges) {\n if (!edge.optional) {\n removeEdge(state, edge)\n }\n }\n\n removeUnlinkedNodes(state)\n\n return state\n}\n"]}
@@ -1,6 +1,6 @@
1
- import type { NodeLike } from '@vltpkg/graph';
2
- import type { SpecOptions } from '@vltpkg/spec/browser';
3
- import type { ParserState, PostcssNode } from '../types.ts';
1
+ import type { NodeLike } from '@vltpkg/types';
2
+ import type { ParserState } from '../types.ts';
3
+ import type { PostcssNode } from '@vltpkg/dss-parser';
4
4
  /**
5
5
  * The possible values accepted by the :outdated() pseudo selector.
6
6
  */
@@ -26,7 +26,7 @@ export declare const asOutdatedKind: (value: string) => OutdatedKinds;
26
26
  /**
27
27
  * Fetches the available versions of a package from the npm registry.
28
28
  */
29
- export declare const retrieveRemoteVersions: (node: NodeLike, specOptions: SpecOptions) => Promise<string[]>;
29
+ export declare const retrieveRemoteVersions: (node: NodeLike, signal?: AbortSignal) => Promise<string[]>;
30
30
  /**
31
31
  * Retrieves what kind of check the :outdated selector should perform.
32
32
  */
@@ -1 +1 @@
1
- {"version":3,"file":"outdated.d.ts","sourceRoot":"","sources":["../../../src/pseudo/outdated.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAiBvD,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAG3D;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,KAAK,GACL,OAAO,GACP,OAAO,GACP,OAAO,GACP,UAAU,GACV,cAAc,CAAA;AAElB;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,aAAa,CAAA;CACpB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,CACjC,OAAO,EAAE,MAAM,KACZ,MAAM,GAAG,SAAS,CAAA;AAWvB;;GAEG;AACH,eAAO,MAAM,cAAc,UAClB,MAAM,KACZ,KAAK,IAAI,aAAkD,CAAA;AAE9D;;GAEG;AACH,eAAO,MAAM,cAAc,UAAW,MAAM,KAAG,aAQ9C,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,sBAAsB,SAC3B,QAAQ,eACD,WAAW,KACvB,OAAO,CAAC,MAAM,EAAE,CAyClB,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,UAClB,WAAW,EAAE,KACnB,iBAmBF,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,SAAS,UACb,WAAW,QACZ,QAAQ,QACR,aAAa,KAClB,OAAO,CAAC,QAAQ,GAAG,SAAS,CAsF9B,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,QAAQ,UAAiB,WAAW,yBAwChD,CAAA"}
1
+ {"version":3,"file":"outdated.d.ts","sourceRoot":"","sources":["../../../src/pseudo/outdated.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,QAAQ,EAAa,MAAM,eAAe,CAAA;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAErD;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,KAAK,GACL,OAAO,GACP,OAAO,GACP,OAAO,GACP,UAAU,GACV,cAAc,CAAA;AAElB;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,aAAa,CAAA;CACpB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,CACjC,OAAO,EAAE,MAAM,KACZ,MAAM,GAAG,SAAS,CAAA;AAWvB;;GAEG;AACH,eAAO,MAAM,cAAc,UAClB,MAAM,KACZ,KAAK,IAAI,aAAkD,CAAA;AAE9D;;GAEG;AACH,eAAO,MAAM,cAAc,UAAW,MAAM,KAAG,aAQ9C,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,sBAAsB,SAC3B,QAAQ,WACL,WAAW,KACnB,OAAO,CAAC,MAAM,EAAE,CA4BlB,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,UAClB,WAAW,EAAE,KACnB,iBAmBF,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,SAAS,UACb,WAAW,QACZ,QAAQ,QACR,aAAa,KAClB,OAAO,CAAC,QAAQ,GAAG,SAAS,CAqG9B,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,QAAQ,UAAiB,WAAW,yBA4ChD,CAAA"}
@@ -1,7 +1,9 @@
1
+ import pRetry, { AbortError } from 'p-retry';
1
2
  import { hydrate, splitDepID } from '@vltpkg/dep-id/browser';
2
3
  import { error } from '@vltpkg/error-cause';
4
+ import { asError } from '@vltpkg/types';
3
5
  import { compare, gt, major, minor, patch, satisfies, } from '@vltpkg/semver';
4
- import { asPostcssNodeWithChildren, asStringNode, asTagNode, isStringNode, isTagNode, } from "../types.js";
6
+ import { asPostcssNodeWithChildren, asStringNode, asTagNode, isStringNode, isTagNode, } from '@vltpkg/dss-parser';
5
7
  import { removeNode, removeQuotes } from "./helpers.js";
6
8
  const kinds = new Set([
7
9
  'any',
@@ -30,42 +32,32 @@ export const asOutdatedKind = (value) => {
30
32
  /**
31
33
  * Fetches the available versions of a package from the npm registry.
32
34
  */
33
- export const retrieveRemoteVersions = async (node, specOptions) => {
34
- const spec = hydrate(node.id, String(node.name), specOptions);
35
+ export const retrieveRemoteVersions = async (node, signal) => {
36
+ const spec = hydrate(node.id, String(node.name), node.options);
35
37
  if (!spec.registry || !node.name) {
36
38
  return [];
37
39
  }
38
40
  const url = new URL(spec.registry);
39
41
  url.pathname = `/${node.name}`;
40
- try {
41
- const response = await fetch(String(url), {
42
- headers: {
43
- Accept: 'application/vnd.npm.install-v1+json',
44
- },
45
- });
46
- if (!response.ok) {
47
- // eslint-disable-next-line no-console
48
- console.warn(error('Failed to fetch packument', {
49
- name: String(node.name),
50
- spec,
51
- response,
52
- }));
53
- return [];
54
- }
55
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
56
- const packument = await response.json();
57
- return Object.keys(packument.versions).sort(compare);
42
+ const response = await fetch(String(url), {
43
+ headers: {
44
+ Accept: 'application/vnd.npm.install-v1+json',
45
+ },
46
+ signal,
47
+ });
48
+ // on missing valid auth or API, it should abort the retry logic
49
+ if (response.status === 404) {
50
+ throw new AbortError('Missing API');
58
51
  }
59
- catch (e) {
60
- const err = e;
61
- // eslint-disable-next-line no-console
62
- console.warn(error('Could not retrieve registry versions', {
63
- name: String(node.name),
52
+ if (!response.ok) {
53
+ throw error('Failed to fetch packument', {
54
+ name: node.name,
64
55
  spec,
65
- cause: err,
66
- }));
67
- return [];
56
+ response,
57
+ });
68
58
  }
59
+ const packument = (await response.json());
60
+ return Object.keys(packument.versions).sort(compare);
69
61
  };
70
62
  /**
71
63
  * Retrieves what kind of check the :outdated selector should perform.
@@ -89,7 +81,21 @@ export const queueNode = async (state, node, kind) => {
89
81
  return node;
90
82
  }
91
83
  const nodeVersion = node.version;
92
- const versions = await retrieveRemoteVersions(node, state.specOptions);
84
+ let versions;
85
+ try {
86
+ versions = await pRetry(() => retrieveRemoteVersions(node, state.signal), {
87
+ retries: state.retries,
88
+ signal: state.signal,
89
+ });
90
+ }
91
+ catch (err) {
92
+ // eslint-disable-next-line no-console
93
+ console.warn(error('Could not retrieve registry versions', {
94
+ name: node.name,
95
+ cause: err,
96
+ }));
97
+ versions = [];
98
+ }
93
99
  const greaterVersions = versions.filter((version) => gt(version, nodeVersion));
94
100
  // if there are no greater versions, then the node is not outdated
95
101
  if (!greaterVersions.length) {
@@ -171,9 +177,14 @@ export const outdated = async (state) => {
171
177
  internals = parseInternals(asPostcssNodeWithChildren(state.current).nodes);
172
178
  }
173
179
  catch (err) {
174
- throw error('Failed to parse :outdated selector', {
175
- cause: err,
176
- });
180
+ if (asError(err).message === 'Expected a query node') {
181
+ internals = { kind: 'any' };
182
+ }
183
+ else {
184
+ throw error('Failed to parse :outdated selector', {
185
+ cause: err,
186
+ });
187
+ }
177
188
  }
178
189
  const { kind } = internals;
179
190
  const queue = [];
@@ -1 +1 @@
1
- {"version":3,"file":"outdated.js","sourceRoot":"","sources":["../../../src/pseudo/outdated.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAG3C,OAAO,EACL,OAAO,EACP,EAAE,EACF,KAAK,EACL,KAAK,EACL,KAAK,EACL,SAAS,GACV,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EACL,yBAAyB,EACzB,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,SAAS,GACV,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AA2BvD,MAAM,KAAK,GAAG,IAAI,GAAG,CAAgB;IACnC,KAAK;IACL,OAAO;IACP,OAAO;IACP,OAAO;IACP,UAAU;IACV,cAAc;CACf,CAAC,CAAA;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,KAAa,EACW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,KAAsB,CAAC,CAAA;AAE9D;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAa,EAAiB,EAAE;IAC7D,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,KAAK,CAAC,gCAAgC,EAAE;YAC5C,KAAK,EAAE,KAAK;YACZ,YAAY,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;SAChC,CAAC,CAAA;IACJ,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,EACzC,IAAc,EACd,WAAwB,EACL,EAAE;IACrB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,CAAA;IAC7D,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACjC,OAAO,EAAE,CAAA;IACX,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAClC,GAAG,CAAC,QAAQ,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAA;IAE9B,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;YACxC,OAAO,EAAE;gBACP,MAAM,EAAE,qCAAqC;aAC9C;SACF,CAAC,CAAA;QACF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,sCAAsC;YACtC,OAAO,CAAC,IAAI,CACV,KAAK,CAAC,2BAA2B,EAAE;gBACjC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;gBACvB,IAAI;gBACJ,QAAQ;aACT,CAAC,CACH,CAAA;YACD,OAAO,EAAE,CAAA;QACX,CAAC;QACD,mEAAmE;QACnE,MAAM,SAAS,GAAc,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;QAClD,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACtD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,GAAG,GAAG,CAAU,CAAA;QACtB,sCAAsC;QACtC,OAAO,CAAC,IAAI,CACV,KAAK,CAAC,sCAAsC,EAAE;YAC5C,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;YACvB,IAAI;YACJ,KAAK,EAAE,GAAG;SACX,CAAC,CACH,CAAA;QACD,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,KAAoB,EACD,EAAE;IACrB,IAAI,IAAI,GAAkB,KAAK,CAAA;IAE/B,IAAI,YAAY,CAAC,yBAAyB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,IAAI,GAAG,cAAc,CACnB,YAAY,CACV,YAAY,CAAC,yBAAyB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;aACvD,KAAK,CACT,CACF,CAAA;IACH,CAAC;SAAM,IACL,SAAS,CAAC,yBAAyB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EACvD,CAAC;QACD,IAAI,GAAG,cAAc,CACnB,SAAS,CAAC,yBAAyB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAC9D,CAAA;IACH,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,CAAA;AACjB,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAC5B,KAAkB,EAClB,IAAc,EACd,IAAmB,EACY,EAAE;IACjC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAChC,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,WAAW,GAAW,IAAI,CAAC,OAAO,CAAA;IACxC,MAAM,QAAQ,GAAG,MAAM,sBAAsB,CAC3C,IAAI,EACJ,KAAK,CAAC,WAAW,CAClB,CAAA;IAED,MAAM,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAe,EAAE,EAAE,CAC1D,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC,CACzB,CAAA;IAED,kEAAkE;IAClE,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,GAAG,CAAsC;QAC7D,CAAC,OAAO,EAAE,KAAK,CAAC;QAChB,CAAC,OAAO,EAAE,KAAK,CAAC;QAChB,CAAC,OAAO,EAAE,KAAK,CAAC;KACjB,CAAC,CAAA;IAEF,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,KAAK;YACR,OAAM;QACR,KAAK,OAAO,CAAC;QACb,KAAK,OAAO,CAAC;QACb,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,OAAO,CACH,eAAe,CAAC,IAAI,CAAC,CAAC,OAAe,EAAE,EAAE;gBACvC,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,CAAA;gBACzC,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAA;gBAC7C,6DAA6D;gBAC7D,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,SAAS;oBAAE,OAAO,KAAK,CAAA;gBACtD,OAAO,EAAE,GAAG,EAAE,CAAA;YAChB,CAAC,CAAC,CACH,CAAC,CAAC;gBACD,SAAS;gBACX,CAAC,CAAC,IAAI,CAAA;QACV,CAAC;QACD,mEAAmE;QACnE,gEAAgE;QAChE,mCAAmC;QACnC,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBAChC,0DAA0D;gBAC1D,oBAAoB;gBACpB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,SAAQ;gBAE5C,IACE,eAAe,CAAC,IAAI,CAClB,OAAO,CAAC,EAAE,CACR,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK;oBACrB,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAC5C,EACD,CAAC;oBACD,OAAM;gBACR,CAAC;YACH,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC;QACD,oEAAoE;QACpE,wEAAwE;QACxE,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBAChC,0DAA0D;gBAC1D,oBAAoB;gBACpB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,SAAQ;gBAE5C,IACE,eAAe,CAAC,IAAI,CAClB,OAAO,CAAC,EAAE,CACR,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK;oBACrB,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAC5C,EACD,CAAC;oBACD,OAAO,IAAI,CAAA;gBACb,CAAC;YACH,CAAC;YACD,OAAM;QACR,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,EAAE,KAAkB,EAAE,EAAE;IACnD,IAAI,SAAS,CAAA;IACb,IAAI,CAAC;QACH,SAAS,GAAG,cAAc,CACxB,yBAAyB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,CAC/C,CAAA;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,KAAK,CAAC,oCAAoC,EAAE;YAChD,KAAK,EAAE,GAAG;SACX,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,GAAG,SAAS,CAAA;IAC1B,MAAM,KAAK,GAAG,EAAE,CAAA;IAEhB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACvC,oEAAoE;QACpE,IACE,IAAI,CAAC,YAAY;YACjB,IAAI,CAAC,QAAQ,EAAE,OAAO;YACtB,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,UAAU,EACrC,CAAC;YACD,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;YACvB,SAAQ;QACV,CAAC;QAED,qDAAqD;QACrD,+CAA+C;QAC/C,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;IAC1C,CAAC;IAED,oDAAoD;IACpD,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IAChD,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;QACnC,IAAI,IAAI,EAAE,CAAC;YACT,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QACzB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA","sourcesContent":["import { hydrate, splitDepID } from '@vltpkg/dep-id/browser'\nimport { error } from '@vltpkg/error-cause'\nimport type { NodeLike } from '@vltpkg/graph'\nimport type { SpecOptions } from '@vltpkg/spec/browser'\nimport {\n compare,\n gt,\n major,\n minor,\n patch,\n satisfies,\n} from '@vltpkg/semver'\nimport type { Packument } from '@vltpkg/types'\nimport {\n asPostcssNodeWithChildren,\n asStringNode,\n asTagNode,\n isStringNode,\n isTagNode,\n} from '../types.ts'\nimport type { ParserState, PostcssNode } from '../types.ts'\nimport { removeNode, removeQuotes } from './helpers.ts'\n\n/**\n * The possible values accepted by the :outdated() pseudo selector.\n */\nexport type OutdatedKinds =\n | 'any'\n | 'major'\n | 'minor'\n | 'patch'\n | 'in-range'\n | 'out-of-range'\n\n/**\n * Result of the internal parsing of the :outdated() pseudo selector.\n */\nexport type OutdatedInternals = {\n kind: OutdatedKinds\n}\n\n/**\n * Extracts a semver type from a version string.\n */\nexport type SemverTypeExtraction = (\n version: string,\n) => number | undefined\n\nconst kinds = new Set<OutdatedKinds>([\n 'any',\n 'major',\n 'minor',\n 'patch',\n 'in-range',\n 'out-of-range',\n])\n\n/**\n * Checks if a string is a valid {@link OutdatedKinds}.\n */\nexport const isOutdatedKind = (\n value: string,\n): value is OutdatedKinds => kinds.has(value as OutdatedKinds)\n\n/**\n * Asserts that a string is a valid {@link OutdatedKinds}.\n */\nexport const asOutdatedKind = (value: string): OutdatedKinds => {\n if (!isOutdatedKind(value)) {\n throw error('Expected a valid outdated kind', {\n found: value,\n validOptions: Array.from(kinds),\n })\n }\n return value\n}\n\n/**\n * Fetches the available versions of a package from the npm registry.\n */\nexport const retrieveRemoteVersions = async (\n node: NodeLike,\n specOptions: SpecOptions,\n): Promise<string[]> => {\n const spec = hydrate(node.id, String(node.name), specOptions)\n if (!spec.registry || !node.name) {\n return []\n }\n\n const url = new URL(spec.registry)\n url.pathname = `/${node.name}`\n\n try {\n const response = await fetch(String(url), {\n headers: {\n Accept: 'application/vnd.npm.install-v1+json',\n },\n })\n if (!response.ok) {\n // eslint-disable-next-line no-console\n console.warn(\n error('Failed to fetch packument', {\n name: String(node.name),\n spec,\n response,\n }),\n )\n return []\n }\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const packument: Packument = await response.json()\n return Object.keys(packument.versions).sort(compare)\n } catch (e) {\n const err = e as Error\n // eslint-disable-next-line no-console\n console.warn(\n error('Could not retrieve registry versions', {\n name: String(node.name),\n spec,\n cause: err,\n }),\n )\n return []\n }\n}\n\n/**\n * Retrieves what kind of check the :outdated selector should perform.\n */\nexport const parseInternals = (\n nodes: PostcssNode[],\n): OutdatedInternals => {\n let kind: OutdatedKinds = 'any'\n\n if (isStringNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])) {\n kind = asOutdatedKind(\n removeQuotes(\n asStringNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])\n .value,\n ),\n )\n } else if (\n isTagNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])\n ) {\n kind = asOutdatedKind(\n asTagNode(asPostcssNodeWithChildren(nodes[0]).nodes[0]).value,\n )\n }\n\n return { kind }\n}\n\n/**\n * Filter nodes by queueing up for removal those that are not outdated.\n */\nexport const queueNode = async (\n state: ParserState,\n node: NodeLike,\n kind: OutdatedKinds,\n): Promise<NodeLike | undefined> => {\n if (!node.name || !node.version) {\n return node\n }\n\n const nodeVersion: string = node.version\n const versions = await retrieveRemoteVersions(\n node,\n state.specOptions,\n )\n\n const greaterVersions = versions.filter((version: string) =>\n gt(version, nodeVersion),\n )\n\n // if there are no greater versions, then the node is not outdated\n if (!greaterVersions.length) {\n return node\n }\n\n const checkKind = new Map<OutdatedKinds, SemverTypeExtraction>([\n ['major', major],\n ['minor', minor],\n ['patch', patch],\n ])\n\n switch (kind) {\n case 'any':\n return\n case 'major':\n case 'minor':\n case 'patch': {\n return (\n greaterVersions.some((version: string) => {\n const va = checkKind.get(kind)?.(version)\n const vb = checkKind.get(kind)?.(nodeVersion)\n /* c8 ignore next - impossible but typescript doesn't know */\n if (va === undefined || vb === undefined) return false\n return va > vb\n })\n ) ?\n undefined\n : node\n }\n // the node should be part of the result as long as it has at least\n // one parent node that has a spec definition that satisfies one\n // of the available remove versions\n case 'in-range': {\n for (const edge of node.edgesIn) {\n // if the edge is not part of the partial results, skip it\n /* c8 ignore next */\n if (!state.partial.edges.has(edge)) continue\n\n if (\n greaterVersions.some(\n version =>\n edge.spec.final.range &&\n satisfies(version, edge.spec.final.range),\n )\n ) {\n return\n }\n }\n return node\n }\n // the node is part of the result as long as none of its parents has\n // a spec definition that satisfies one of the available remote versions\n case 'out-of-range': {\n for (const edge of node.edgesIn) {\n // if the edge is not part of the partial results, skip it\n /* c8 ignore next */\n if (!state.partial.edges.has(edge)) continue\n\n if (\n greaterVersions.some(\n version =>\n edge.spec.final.range &&\n satisfies(version, edge.spec.final.range),\n )\n ) {\n return node\n }\n }\n return\n }\n }\n}\n\n/**\n * Filters out nodes that are not outdated.\n *\n * The :outdated() pseudo selector supports one `type` argument,\n * possible values are the following:\n *\n * - `any`: Selects all nodes that have a greater version available.\n * - `major`: Selects all nodes that have a greater major version available.\n * - `minor`: Selects all nodes that have a greater minor version available.\n * - `patch`: Selects all nodes that have a greater patch version available.\n * - `in-range`: Selects all nodes that have a parent node with a spec definition\n * that satisfies one of the available remote versions.\n * - `out-of-range`: Selects all nodes that have a parent node with a spec definition\n * that does not satisfy any of the available remote versions.\n */\nexport const outdated = async (state: ParserState) => {\n let internals\n try {\n internals = parseInternals(\n asPostcssNodeWithChildren(state.current).nodes,\n )\n } catch (err) {\n throw error('Failed to parse :outdated selector', {\n cause: err,\n })\n }\n\n const { kind } = internals\n const queue = []\n\n for (const node of state.partial.nodes) {\n // filter out nodes that are always ignored by the outdated selector\n if (\n node.mainImporter ||\n node.manifest?.private ||\n splitDepID(node.id)[0] !== 'registry'\n ) {\n removeNode(state, node)\n continue\n }\n\n // fetchs outdated info and performs checks to define\n // whether or not a node should be filtered out\n queue.push(queueNode(state, node, kind))\n }\n\n // nodes queued for removal are then finally removed\n const removeNodeQueue = await Promise.all(queue)\n for (const node of removeNodeQueue) {\n if (node) {\n removeNode(state, node)\n }\n }\n\n return state\n}\n"]}
1
+ {"version":3,"file":"outdated.js","sourceRoot":"","sources":["../../../src/pseudo/outdated.ts"],"names":[],"mappings":"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","sourcesContent":["import pRetry, { AbortError } from 'p-retry'\nimport { hydrate, splitDepID } from '@vltpkg/dep-id/browser'\nimport { error } from '@vltpkg/error-cause'\nimport { asError } from '@vltpkg/types'\nimport {\n compare,\n gt,\n major,\n minor,\n patch,\n satisfies,\n} from '@vltpkg/semver'\nimport {\n asPostcssNodeWithChildren,\n asStringNode,\n asTagNode,\n isStringNode,\n isTagNode,\n} from '@vltpkg/dss-parser'\nimport { removeNode, removeQuotes } from './helpers.ts'\nimport type { NodeLike, Packument } from '@vltpkg/types'\nimport type { ParserState } from '../types.ts'\nimport type { PostcssNode } from '@vltpkg/dss-parser'\n\n/**\n * The possible values accepted by the :outdated() pseudo selector.\n */\nexport type OutdatedKinds =\n | 'any'\n | 'major'\n | 'minor'\n | 'patch'\n | 'in-range'\n | 'out-of-range'\n\n/**\n * Result of the internal parsing of the :outdated() pseudo selector.\n */\nexport type OutdatedInternals = {\n kind: OutdatedKinds\n}\n\n/**\n * Extracts a semver type from a version string.\n */\nexport type SemverTypeExtraction = (\n version: string,\n) => number | undefined\n\nconst kinds = new Set<OutdatedKinds>([\n 'any',\n 'major',\n 'minor',\n 'patch',\n 'in-range',\n 'out-of-range',\n])\n\n/**\n * Checks if a string is a valid {@link OutdatedKinds}.\n */\nexport const isOutdatedKind = (\n value: string,\n): value is OutdatedKinds => kinds.has(value as OutdatedKinds)\n\n/**\n * Asserts that a string is a valid {@link OutdatedKinds}.\n */\nexport const asOutdatedKind = (value: string): OutdatedKinds => {\n if (!isOutdatedKind(value)) {\n throw error('Expected a valid outdated kind', {\n found: value,\n validOptions: Array.from(kinds),\n })\n }\n return value\n}\n\n/**\n * Fetches the available versions of a package from the npm registry.\n */\nexport const retrieveRemoteVersions = async (\n node: NodeLike,\n signal?: AbortSignal,\n): Promise<string[]> => {\n const spec = hydrate(node.id, String(node.name), node.options)\n if (!spec.registry || !node.name) {\n return []\n }\n\n const url = new URL(spec.registry)\n url.pathname = `/${node.name}`\n\n const response = await fetch(String(url), {\n headers: {\n Accept: 'application/vnd.npm.install-v1+json',\n },\n signal,\n })\n // on missing valid auth or API, it should abort the retry logic\n if (response.status === 404) {\n throw new AbortError('Missing API')\n }\n if (!response.ok) {\n throw error('Failed to fetch packument', {\n name: node.name,\n spec,\n response,\n })\n }\n const packument = (await response.json()) as Packument\n return Object.keys(packument.versions).sort(compare)\n}\n\n/**\n * Retrieves what kind of check the :outdated selector should perform.\n */\nexport const parseInternals = (\n nodes: PostcssNode[],\n): OutdatedInternals => {\n let kind: OutdatedKinds = 'any'\n\n if (isStringNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])) {\n kind = asOutdatedKind(\n removeQuotes(\n asStringNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])\n .value,\n ),\n )\n } else if (\n isTagNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])\n ) {\n kind = asOutdatedKind(\n asTagNode(asPostcssNodeWithChildren(nodes[0]).nodes[0]).value,\n )\n }\n\n return { kind }\n}\n\n/**\n * Filter nodes by queueing up for removal those that are not outdated.\n */\nexport const queueNode = async (\n state: ParserState,\n node: NodeLike,\n kind: OutdatedKinds,\n): Promise<NodeLike | undefined> => {\n if (!node.name || !node.version) {\n return node\n }\n\n const nodeVersion: string = node.version\n let versions: string[]\n try {\n versions = await pRetry(\n () => retrieveRemoteVersions(node, state.signal),\n {\n retries: state.retries,\n signal: state.signal,\n },\n )\n } catch (err) {\n // eslint-disable-next-line no-console\n console.warn(\n error('Could not retrieve registry versions', {\n name: node.name,\n cause: err,\n }),\n )\n versions = []\n }\n\n const greaterVersions = versions.filter((version: string) =>\n gt(version, nodeVersion),\n )\n\n // if there are no greater versions, then the node is not outdated\n if (!greaterVersions.length) {\n return node\n }\n\n const checkKind = new Map<OutdatedKinds, SemverTypeExtraction>([\n ['major', major],\n ['minor', minor],\n ['patch', patch],\n ])\n\n switch (kind) {\n case 'any':\n return\n case 'major':\n case 'minor':\n case 'patch': {\n return (\n greaterVersions.some((version: string) => {\n const va = checkKind.get(kind)?.(version)\n const vb = checkKind.get(kind)?.(nodeVersion)\n /* c8 ignore next - impossible but typescript doesn't know */\n if (va === undefined || vb === undefined) return false\n return va > vb\n })\n ) ?\n undefined\n : node\n }\n // the node should be part of the result as long as it has at least\n // one parent node that has a spec definition that satisfies one\n // of the available remove versions\n case 'in-range': {\n for (const edge of node.edgesIn) {\n // if the edge is not part of the partial results, skip it\n /* c8 ignore next */\n if (!state.partial.edges.has(edge)) continue\n\n if (\n greaterVersions.some(\n version =>\n edge.spec.final.range &&\n satisfies(version, edge.spec.final.range),\n )\n ) {\n return\n }\n }\n return node\n }\n // the node is part of the result as long as none of its parents has\n // a spec definition that satisfies one of the available remote versions\n case 'out-of-range': {\n for (const edge of node.edgesIn) {\n // if the edge is not part of the partial results, skip it\n /* c8 ignore next */\n if (!state.partial.edges.has(edge)) continue\n\n if (\n greaterVersions.some(\n version =>\n edge.spec.final.range &&\n satisfies(version, edge.spec.final.range),\n )\n ) {\n return node\n }\n }\n return\n }\n }\n}\n\n/**\n * Filters out nodes that are not outdated.\n *\n * The :outdated() pseudo selector supports one `type` argument,\n * possible values are the following:\n *\n * - `any`: Selects all nodes that have a greater version available.\n * - `major`: Selects all nodes that have a greater major version available.\n * - `minor`: Selects all nodes that have a greater minor version available.\n * - `patch`: Selects all nodes that have a greater patch version available.\n * - `in-range`: Selects all nodes that have a parent node with a spec definition\n * that satisfies one of the available remote versions.\n * - `out-of-range`: Selects all nodes that have a parent node with a spec definition\n * that does not satisfy any of the available remote versions.\n */\nexport const outdated = async (state: ParserState) => {\n let internals\n try {\n internals = parseInternals(\n asPostcssNodeWithChildren(state.current).nodes,\n )\n } catch (err) {\n if (asError(err).message === 'Expected a query node') {\n internals = { kind: 'any' } satisfies OutdatedInternals\n } else {\n throw error('Failed to parse :outdated selector', {\n cause: err,\n })\n }\n }\n\n const { kind } = internals\n const queue = []\n\n for (const node of state.partial.nodes) {\n // filter out nodes that are always ignored by the outdated selector\n if (\n node.mainImporter ||\n node.manifest?.private ||\n splitDepID(node.id)[0] !== 'registry'\n ) {\n removeNode(state, node)\n continue\n }\n\n // fetchs outdated info and performs checks to define\n // whether or not a node should be filtered out\n queue.push(queueNode(state, node, kind))\n }\n\n // nodes queued for removal are then finally removed\n const removeNodeQueue = await Promise.all(queue)\n for (const node of removeNodeQueue) {\n if (node) {\n removeNode(state, node)\n }\n }\n\n return state\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import type { ParserState } from '../types.ts';
2
+ /**
3
+ * :overridden Pseudo-Selector, matches only edges that have a truthy overridden property in their spec.
4
+ * It filters out any edges that don't have edge.spec.overridden set to a truthy value
5
+ * and removes any unlinked nodes from the result.
6
+ */
7
+ export declare const overridden: (state: ParserState) => Promise<ParserState>;
8
+ //# sourceMappingURL=overridden.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overridden.d.ts","sourceRoot":"","sources":["../../../src/pseudo/overridden.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAG9C;;;;GAIG;AACH,eAAO,MAAM,UAAU,UAAiB,WAAW,yBAWlD,CAAA"}
@@ -0,0 +1,17 @@
1
+ import { removeEdge, removeUnlinkedNodes } from "./helpers.js";
2
+ /**
3
+ * :overridden Pseudo-Selector, matches only edges that have a truthy overridden property in their spec.
4
+ * It filters out any edges that don't have edge.spec.overridden set to a truthy value
5
+ * and removes any unlinked nodes from the result.
6
+ */
7
+ export const overridden = async (state) => {
8
+ // filter edges that don't have a truthy overridden property
9
+ for (const edge of state.partial.edges) {
10
+ if (!edge.spec.overridden) {
11
+ removeEdge(state, edge);
12
+ }
13
+ }
14
+ removeUnlinkedNodes(state);
15
+ return state;
16
+ };
17
+ //# sourceMappingURL=overridden.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overridden.js","sourceRoot":"","sources":["../../../src/pseudo/overridden.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAE9D;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,KAAkB,EAAE,EAAE;IACrD,4DAA4D;IAC5D,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YAC1B,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QACzB,CAAC;IACH,CAAC;IAED,mBAAmB,CAAC,KAAK,CAAC,CAAA;IAE1B,OAAO,KAAK,CAAA;AACd,CAAC,CAAA","sourcesContent":["import type { ParserState } from '../types.ts'\nimport { removeEdge, removeUnlinkedNodes } from './helpers.ts'\n\n/**\n * :overridden Pseudo-Selector, matches only edges that have a truthy overridden property in their spec.\n * It filters out any edges that don't have edge.spec.overridden set to a truthy value\n * and removes any unlinked nodes from the result.\n */\nexport const overridden = async (state: ParserState) => {\n // filter edges that don't have a truthy overridden property\n for (const edge of state.partial.edges) {\n if (!edge.spec.overridden) {\n removeEdge(state, edge)\n }\n }\n\n removeUnlinkedNodes(state)\n\n return state\n}\n"]}