@vltpkg/query 1.0.0-rc.22 → 1.0.0-rc.24
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/dist/attribute.d.ts +14 -0
- package/dist/attribute.js +132 -0
- package/dist/combinator.d.ts +5 -0
- package/dist/combinator.js +111 -0
- package/dist/id.d.ts +5 -0
- package/dist/id.js +35 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.js +410 -0
- package/dist/parser.d.ts +14 -0
- package/dist/parser.js +92 -0
- package/dist/pseudo/abandoned.d.ts +6 -0
- package/dist/pseudo/abandoned.js +5 -0
- package/dist/pseudo/attr.d.ts +18 -0
- package/dist/pseudo/attr.js +57 -0
- package/dist/pseudo/built.d.ts +7 -0
- package/dist/pseudo/built.js +15 -0
- package/dist/pseudo/confused.d.ts +8 -0
- package/dist/pseudo/confused.js +18 -0
- package/dist/pseudo/cve.d.ts +12 -0
- package/dist/pseudo/cve.js +43 -0
- package/dist/pseudo/cwe.d.ts +12 -0
- package/dist/pseudo/cwe.js +42 -0
- package/dist/pseudo/debug.d.ts +6 -0
- package/dist/pseudo/debug.js +5 -0
- package/dist/pseudo/deprecated.d.ts +6 -0
- package/dist/pseudo/deprecated.js +5 -0
- package/dist/pseudo/dev.d.ts +5 -0
- package/dist/pseudo/dev.js +14 -0
- package/dist/pseudo/diff.d.ts +26 -0
- package/dist/pseudo/diff.js +75 -0
- package/dist/pseudo/dynamic.d.ts +6 -0
- package/dist/pseudo/dynamic.js +5 -0
- package/dist/pseudo/empty.d.ts +6 -0
- package/dist/pseudo/empty.js +13 -0
- package/dist/pseudo/entropic.d.ts +6 -0
- package/dist/pseudo/entropic.js +5 -0
- package/dist/pseudo/env.d.ts +6 -0
- package/dist/pseudo/env.js +5 -0
- package/dist/pseudo/eval.d.ts +6 -0
- package/dist/pseudo/eval.js +5 -0
- package/dist/pseudo/fs.d.ts +6 -0
- package/dist/pseudo/fs.js +5 -0
- package/dist/pseudo/helpers.d.ts +38 -0
- package/dist/pseudo/helpers.js +79 -0
- package/dist/pseudo/host.d.ts +19 -0
- package/dist/pseudo/host.js +79 -0
- package/dist/pseudo/hostname.d.ts +11 -0
- package/dist/pseudo/hostname.js +138 -0
- package/dist/pseudo/license.d.ts +12 -0
- package/dist/pseudo/license.js +74 -0
- package/dist/pseudo/link.d.ts +8 -0
- package/dist/pseudo/link.js +24 -0
- package/dist/pseudo/malware.d.ts +23 -0
- package/dist/pseudo/malware.js +186 -0
- package/dist/pseudo/minified.d.ts +6 -0
- package/dist/pseudo/minified.js +5 -0
- package/dist/pseudo/missing.d.ts +7 -0
- package/dist/pseudo/missing.js +14 -0
- package/dist/pseudo/native.d.ts +6 -0
- package/dist/pseudo/native.js +5 -0
- package/dist/pseudo/network.d.ts +6 -0
- package/dist/pseudo/network.js +5 -0
- package/dist/pseudo/obfuscated.d.ts +6 -0
- package/dist/pseudo/obfuscated.js +5 -0
- package/dist/pseudo/optional.d.ts +5 -0
- package/dist/pseudo/optional.js +14 -0
- package/dist/pseudo/outdated.d.ts +53 -0
- package/dist/pseudo/outdated.js +211 -0
- package/dist/pseudo/overridden.d.ts +7 -0
- package/dist/pseudo/overridden.js +16 -0
- package/dist/pseudo/path.d.ts +18 -0
- package/dist/pseudo/path.js +110 -0
- package/dist/pseudo/peer.d.ts +5 -0
- package/dist/pseudo/peer.js +14 -0
- package/dist/pseudo/prerelease.d.ts +17 -0
- package/dist/pseudo/prerelease.js +40 -0
- package/dist/pseudo/private.d.ts +6 -0
- package/dist/pseudo/private.js +15 -0
- package/dist/pseudo/prod.d.ts +5 -0
- package/dist/pseudo/prod.js +14 -0
- package/dist/pseudo/published.d.ts +39 -0
- package/dist/pseudo/published.js +179 -0
- package/dist/pseudo/registry.d.ts +10 -0
- package/dist/pseudo/registry.js +24 -0
- package/dist/pseudo/root.d.ts +6 -0
- package/dist/pseudo/root.js +17 -0
- package/dist/pseudo/scanned.d.ts +8 -0
- package/dist/pseudo/scanned.js +16 -0
- package/dist/pseudo/score.d.ts +15 -0
- package/dist/pseudo/score.js +132 -0
- package/dist/pseudo/scripts.d.ts +9 -0
- package/dist/pseudo/scripts.js +43 -0
- package/dist/pseudo/semver.d.ts +16 -0
- package/dist/pseudo/semver.js +166 -0
- package/dist/pseudo/severity.d.ts +14 -0
- package/dist/pseudo/severity.js +159 -0
- package/dist/pseudo/shell.d.ts +6 -0
- package/dist/pseudo/shell.js +5 -0
- package/dist/pseudo/shrinkwrap.d.ts +6 -0
- package/dist/pseudo/shrinkwrap.js +5 -0
- package/dist/pseudo/spec.d.ts +16 -0
- package/dist/pseudo/spec.js +101 -0
- package/dist/pseudo/squat.d.ts +14 -0
- package/dist/pseudo/squat.js +171 -0
- package/dist/pseudo/suspicious.d.ts +6 -0
- package/dist/pseudo/suspicious.js +5 -0
- package/dist/pseudo/tracker.d.ts +6 -0
- package/dist/pseudo/tracker.js +5 -0
- package/dist/pseudo/trivial.d.ts +6 -0
- package/dist/pseudo/trivial.js +5 -0
- package/dist/pseudo/type.d.ts +7 -0
- package/dist/pseudo/type.js +21 -0
- package/dist/pseudo/undesirable.d.ts +6 -0
- package/dist/pseudo/undesirable.js +5 -0
- package/dist/pseudo/unknown.d.ts +6 -0
- package/dist/pseudo/unknown.js +5 -0
- package/dist/pseudo/unmaintained.d.ts +6 -0
- package/dist/pseudo/unmaintained.js +5 -0
- package/dist/pseudo/unpopular.d.ts +6 -0
- package/dist/pseudo/unpopular.js +5 -0
- package/dist/pseudo/unstable.d.ts +6 -0
- package/dist/pseudo/unstable.js +5 -0
- package/dist/pseudo/workspace.d.ts +5 -0
- package/dist/pseudo/workspace.js +19 -0
- package/dist/pseudo.d.ts +5 -0
- package/dist/pseudo.js +366 -0
- package/dist/types.d.ts +124 -0
- package/dist/types.js +1 -0
- package/package.json +10 -10
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { error } from '@vltpkg/error-cause';
|
|
2
|
+
import { asPostcssNodeWithChildren, asStringNode, asTagNode, isStringNode, isTagNode, } from '@vltpkg/dss-parser';
|
|
3
|
+
import { assertSecurityArchive, removeDanglingEdges, removeNode, removeQuotes, } from "./helpers.js";
|
|
4
|
+
export const parseInternals = (nodes) => {
|
|
5
|
+
let cveId = '';
|
|
6
|
+
if (isStringNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])) {
|
|
7
|
+
cveId = removeQuotes(asStringNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])
|
|
8
|
+
.value);
|
|
9
|
+
}
|
|
10
|
+
else if (isTagNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])) {
|
|
11
|
+
cveId = asTagNode(asPostcssNodeWithChildren(nodes[0]).nodes[0]).value;
|
|
12
|
+
}
|
|
13
|
+
if (!cveId) {
|
|
14
|
+
throw error('Expected a CVE ID', {
|
|
15
|
+
found: asPostcssNodeWithChildren(nodes[0]).nodes[0],
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
return { cveId };
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Filters out any node that does not have a CVE alert with the specified CVE ID.
|
|
22
|
+
*/
|
|
23
|
+
export const cve = async (state) => {
|
|
24
|
+
assertSecurityArchive(state, 'cve');
|
|
25
|
+
let internals;
|
|
26
|
+
try {
|
|
27
|
+
internals = parseInternals(asPostcssNodeWithChildren(state.current).nodes);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
throw error('Failed to parse :cve selector', { cause: err });
|
|
31
|
+
}
|
|
32
|
+
const { cveId } = internals;
|
|
33
|
+
for (const node of state.partial.nodes) {
|
|
34
|
+
const report = state.securityArchive.get(node.id);
|
|
35
|
+
const exclude = !report?.alerts.some(alert => alert.props?.cveId?.trim().toLowerCase() ===
|
|
36
|
+
cveId.trim().toLowerCase());
|
|
37
|
+
if (exclude) {
|
|
38
|
+
removeNode(state, node);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
removeDanglingEdges(state);
|
|
42
|
+
return state;
|
|
43
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ParserState } from '../types.ts';
|
|
2
|
+
import type { PostcssNode } from '@vltpkg/dss-parser';
|
|
3
|
+
export type CweInternals = {
|
|
4
|
+
cweId: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const parseInternals: (nodes: PostcssNode[]) => CweInternals;
|
|
7
|
+
/**
|
|
8
|
+
* Filters out any node that does not have a CWE alert with the specified CWE ID.
|
|
9
|
+
*/
|
|
10
|
+
export declare const cwe: (state: ParserState) => Promise<ParserState & {
|
|
11
|
+
securityArchive: NonNullable<ParserState["securityArchive"]>;
|
|
12
|
+
}>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { error } from '@vltpkg/error-cause';
|
|
2
|
+
import { asPostcssNodeWithChildren, asStringNode, asTagNode, isStringNode, isTagNode, } from '@vltpkg/dss-parser';
|
|
3
|
+
import { assertSecurityArchive, removeDanglingEdges, removeNode, removeQuotes, } from "./helpers.js";
|
|
4
|
+
export const parseInternals = (nodes) => {
|
|
5
|
+
let cweId = '';
|
|
6
|
+
if (isStringNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])) {
|
|
7
|
+
cweId = removeQuotes(asStringNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])
|
|
8
|
+
.value);
|
|
9
|
+
}
|
|
10
|
+
else if (isTagNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])) {
|
|
11
|
+
cweId = asTagNode(asPostcssNodeWithChildren(nodes[0]).nodes[0]).value;
|
|
12
|
+
}
|
|
13
|
+
if (!cweId) {
|
|
14
|
+
throw error('Expected a CWE ID', {
|
|
15
|
+
found: asPostcssNodeWithChildren(nodes[0]).nodes[0],
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
return { cweId };
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Filters out any node that does not have a CWE alert with the specified CWE ID.
|
|
22
|
+
*/
|
|
23
|
+
export const cwe = async (state) => {
|
|
24
|
+
assertSecurityArchive(state, 'cwe');
|
|
25
|
+
let internals;
|
|
26
|
+
try {
|
|
27
|
+
internals = parseInternals(asPostcssNodeWithChildren(state.current).nodes);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
throw error('Failed to parse :cwe selector', { cause: err });
|
|
31
|
+
}
|
|
32
|
+
const { cweId } = internals;
|
|
33
|
+
for (const node of state.partial.nodes) {
|
|
34
|
+
const report = state.securityArchive.get(node.id);
|
|
35
|
+
const exclude = !report?.alerts.some(alert => alert.props?.cwes?.some(cwe => cwe.id.trim().toLowerCase() === cweId.trim().toLowerCase()));
|
|
36
|
+
if (exclude) {
|
|
37
|
+
removeNode(state, node);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
removeDanglingEdges(state);
|
|
41
|
+
return state;
|
|
42
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filters out any node that does not have a **debugAccess** report alert.
|
|
3
|
+
*/
|
|
4
|
+
export declare const debug: (state: import("../types.ts").ParserState) => Promise<import("../types.ts").ParserState & {
|
|
5
|
+
securityArchive: NonNullable<import("../types.ts").ParserState["securityArchive"]>;
|
|
6
|
+
}>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filters out any node that does not have a **deprecated** report alert.
|
|
3
|
+
*/
|
|
4
|
+
export declare const deprecated: (state: import("../types.ts").ParserState) => Promise<import("../types.ts").ParserState & {
|
|
5
|
+
securityArchive: NonNullable<import("../types.ts").ParserState["securityArchive"]>;
|
|
6
|
+
}>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { removeEdge, removeUnlinkedNodes } from "./helpers.js";
|
|
2
|
+
/**
|
|
3
|
+
* :dev Pseudo-Selector will only match devDependencies.
|
|
4
|
+
*/
|
|
5
|
+
export const dev = async (state) => {
|
|
6
|
+
// filter edges that don't have type 'dev'
|
|
7
|
+
for (const edge of state.partial.edges) {
|
|
8
|
+
if (edge.type !== 'dev') {
|
|
9
|
+
removeEdge(state, edge);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
removeUnlinkedNodes(state);
|
|
13
|
+
return state;
|
|
14
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ParserState } from '../types.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Given a set of changed file paths and a package location
|
|
4
|
+
* (relative to the project root), returns true if any changed
|
|
5
|
+
* file belongs to that package.
|
|
6
|
+
*/
|
|
7
|
+
export declare const packageHasChanges: (changedFiles: Set<string>, packageLocation: string) => boolean;
|
|
8
|
+
/**
|
|
9
|
+
* :diff(<commitish>) Pseudo-Selector, matches only nodes
|
|
10
|
+
* whose files have changed between the current state and
|
|
11
|
+
* the specified commitish reference.
|
|
12
|
+
*
|
|
13
|
+
* Requires a `diffFiles` provider to be set on the
|
|
14
|
+
* {@link ParserState}. The provider is a callback that
|
|
15
|
+
* takes a commitish string and returns a Set of changed
|
|
16
|
+
* file paths relative to the project root.
|
|
17
|
+
*
|
|
18
|
+
* When called with no argument, defaults to HEAD (uncommitted changes).
|
|
19
|
+
*
|
|
20
|
+
* Examples:
|
|
21
|
+
* - :diff() — packages with uncommitted changes (defaults to HEAD)
|
|
22
|
+
* - :diff(main) — packages changed since main branch
|
|
23
|
+
* - :diff(HEAD~1) — packages changed since last commit
|
|
24
|
+
* - :diff("v1.0.0") — packages changed since tag v1.0.0
|
|
25
|
+
*/
|
|
26
|
+
export declare const diff: (state: ParserState) => Promise<ParserState>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { error } from '@vltpkg/error-cause';
|
|
2
|
+
import { asPostcssNodeWithChildren } from '@vltpkg/dss-parser';
|
|
3
|
+
import { removeDanglingEdges, removeNode } from "./helpers.js";
|
|
4
|
+
import { parseInternals } from "./spec.js";
|
|
5
|
+
/**
|
|
6
|
+
* Given a set of changed file paths and a package location
|
|
7
|
+
* (relative to the project root), returns true if any changed
|
|
8
|
+
* file belongs to that package.
|
|
9
|
+
*/
|
|
10
|
+
export const packageHasChanges = (changedFiles, packageLocation) => {
|
|
11
|
+
// Normalize the package location — remove leading './'
|
|
12
|
+
const normalized = packageLocation.startsWith('./') ?
|
|
13
|
+
packageLocation.slice(2)
|
|
14
|
+
: packageLocation;
|
|
15
|
+
// Root package — check if any file at root level changed
|
|
16
|
+
// (not inside a subdirectory that is another package)
|
|
17
|
+
if (!normalized || normalized === '.') {
|
|
18
|
+
// Any changed file means the root package changed
|
|
19
|
+
return changedFiles.size > 0;
|
|
20
|
+
}
|
|
21
|
+
// Check if any changed file starts with the package path
|
|
22
|
+
for (const file of changedFiles) {
|
|
23
|
+
if (file === normalized || file.startsWith(normalized + '/')) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return false;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* :diff(<commitish>) Pseudo-Selector, matches only nodes
|
|
31
|
+
* whose files have changed between the current state and
|
|
32
|
+
* the specified commitish reference.
|
|
33
|
+
*
|
|
34
|
+
* Requires a `diffFiles` provider to be set on the
|
|
35
|
+
* {@link ParserState}. The provider is a callback that
|
|
36
|
+
* takes a commitish string and returns a Set of changed
|
|
37
|
+
* file paths relative to the project root.
|
|
38
|
+
*
|
|
39
|
+
* When called with no argument, defaults to HEAD (uncommitted changes).
|
|
40
|
+
*
|
|
41
|
+
* Examples:
|
|
42
|
+
* - :diff() — packages with uncommitted changes (defaults to HEAD)
|
|
43
|
+
* - :diff(main) — packages changed since main branch
|
|
44
|
+
* - :diff(HEAD~1) — packages changed since last commit
|
|
45
|
+
* - :diff("v1.0.0") — packages changed since tag v1.0.0
|
|
46
|
+
*/
|
|
47
|
+
export const diff = async (state) => {
|
|
48
|
+
const currentNodes = asPostcssNodeWithChildren(state.current).nodes;
|
|
49
|
+
const hasArg = currentNodes.length > 0 &&
|
|
50
|
+
asPostcssNodeWithChildren(currentNodes[0]).nodes.length > 0;
|
|
51
|
+
let commitish = 'HEAD';
|
|
52
|
+
if (hasArg) {
|
|
53
|
+
try {
|
|
54
|
+
commitish = parseInternals(currentNodes).specValue;
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
throw error('Failed to parse :diff selector', {
|
|
58
|
+
cause: err,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (!state.diffFiles) {
|
|
63
|
+
throw error('The :diff() selector requires a diffFiles provider');
|
|
64
|
+
}
|
|
65
|
+
const changedFiles = state.diffFiles(commitish);
|
|
66
|
+
for (const node of state.partial.nodes) {
|
|
67
|
+
/* c8 ignore next -- location is always set on real nodes */
|
|
68
|
+
const location = node.location ?? '';
|
|
69
|
+
if (!packageHasChanges(changedFiles, location)) {
|
|
70
|
+
removeNode(state, node);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
removeDanglingEdges(state);
|
|
74
|
+
return state;
|
|
75
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filters out any node that does not have a **dynamicRequire** report alert.
|
|
3
|
+
*/
|
|
4
|
+
export declare const dynamic: (state: import("../types.ts").ParserState) => Promise<import("../types.ts").ParserState & {
|
|
5
|
+
securityArchive: NonNullable<import("../types.ts").ParserState["securityArchive"]>;
|
|
6
|
+
}>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ParserState } from '../types.ts';
|
|
2
|
+
/**
|
|
3
|
+
* :empty Pseudo-Selector, matches only nodes that have no children.
|
|
4
|
+
* It filters out any node that has edges out, i.e., has dependencies.
|
|
5
|
+
*/
|
|
6
|
+
export declare const empty: (state: ParserState) => Promise<ParserState>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { removeNode } from "./helpers.js";
|
|
2
|
+
/**
|
|
3
|
+
* :empty Pseudo-Selector, matches only nodes that have no children.
|
|
4
|
+
* It filters out any node that has edges out, i.e., has dependencies.
|
|
5
|
+
*/
|
|
6
|
+
export const empty = async (state) => {
|
|
7
|
+
for (const node of state.partial.nodes) {
|
|
8
|
+
if (node.edgesOut.size > 0) {
|
|
9
|
+
removeNode(state, node);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return state;
|
|
13
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filters out any node that does not have a **highEntropyStrings** report alert.
|
|
3
|
+
*/
|
|
4
|
+
export declare const entropic: (state: import("../types.ts").ParserState) => Promise<import("../types.ts").ParserState & {
|
|
5
|
+
securityArchive: NonNullable<import("../types.ts").ParserState["securityArchive"]>;
|
|
6
|
+
}>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filters out any node that does not have a **envVars** report alert.
|
|
3
|
+
*/
|
|
4
|
+
export declare const env: (state: import("../types.ts").ParserState) => Promise<import("../types.ts").ParserState & {
|
|
5
|
+
securityArchive: NonNullable<import("../types.ts").ParserState["securityArchive"]>;
|
|
6
|
+
}>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filters out any node that does not have a **usesEval** report alert.
|
|
3
|
+
*/
|
|
4
|
+
export declare const evalParser: (state: import("../types.ts").ParserState) => Promise<import("../types.ts").ParserState & {
|
|
5
|
+
securityArchive: NonNullable<import("../types.ts").ParserState["securityArchive"]>;
|
|
6
|
+
}>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filters out any node that does not have a **filesystemAccess** report alert.
|
|
3
|
+
*/
|
|
4
|
+
export declare const fs: (state: import("../types.ts").ParserState) => Promise<import("../types.ts").ParserState & {
|
|
5
|
+
securityArchive: NonNullable<import("../types.ts").ParserState["securityArchive"]>;
|
|
6
|
+
}>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { EdgeLike, NodeLike } from '@vltpkg/types';
|
|
2
|
+
import type { ParserState } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Removes a node and its incoming edges from the results.
|
|
5
|
+
*/
|
|
6
|
+
export declare const removeNode: (state: ParserState, node: NodeLike) => void;
|
|
7
|
+
/**
|
|
8
|
+
* Removes an edge and its outgoing node from the results.
|
|
9
|
+
*/
|
|
10
|
+
export declare const removeEdge: (state: ParserState, edge: EdgeLike) => void;
|
|
11
|
+
/**
|
|
12
|
+
* Removes any edges that have no destination node from the results.
|
|
13
|
+
*/
|
|
14
|
+
export declare const removeDanglingEdges: (state: ParserState) => void;
|
|
15
|
+
/**
|
|
16
|
+
* Removes any nodes that have no incoming edges from the results.
|
|
17
|
+
*/
|
|
18
|
+
export declare const removeUnlinkedNodes: (state: ParserState) => void;
|
|
19
|
+
/**
|
|
20
|
+
* Removes quotes from a string value.
|
|
21
|
+
*/
|
|
22
|
+
export declare const removeQuotes: (value: string) => string;
|
|
23
|
+
/**
|
|
24
|
+
* Asserts that the security archive is present.
|
|
25
|
+
*/
|
|
26
|
+
export declare const assertSecurityArchive: (state: ParserState, name: string) => asserts state is ParserState & {
|
|
27
|
+
securityArchive: NonNullable<ParserState['securityArchive']>;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Clears all nodes and edges from the results.
|
|
31
|
+
*/
|
|
32
|
+
export declare const clear: (state: ParserState) => ParserState;
|
|
33
|
+
/**
|
|
34
|
+
* Reusable security selector alert filter.
|
|
35
|
+
*/
|
|
36
|
+
export declare const createSecuritySelectorFilter: (name: string, type: string) => (state: ParserState) => Promise<ParserState & {
|
|
37
|
+
securityArchive: NonNullable<ParserState["securityArchive"]>;
|
|
38
|
+
}>;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { error } from '@vltpkg/error-cause';
|
|
2
|
+
/**
|
|
3
|
+
* Removes a node and its incoming edges from the results.
|
|
4
|
+
*/
|
|
5
|
+
export const removeNode = (state, node) => {
|
|
6
|
+
for (const edge of node.edgesIn) {
|
|
7
|
+
state.partial.edges.delete(edge);
|
|
8
|
+
}
|
|
9
|
+
state.partial.nodes.delete(node);
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Removes an edge and its outgoing node from the results.
|
|
13
|
+
*/
|
|
14
|
+
export const removeEdge = (state, edge) => {
|
|
15
|
+
state.partial.edges.delete(edge);
|
|
16
|
+
if (edge.to?.edgesIn.size === 1) {
|
|
17
|
+
state.partial.nodes.delete(edge.to);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Removes any edges that have no destination node from the results.
|
|
22
|
+
*/
|
|
23
|
+
export const removeDanglingEdges = (state) => {
|
|
24
|
+
for (const edge of state.partial.edges) {
|
|
25
|
+
if (!edge.to || !state.partial.nodes.has(edge.to)) {
|
|
26
|
+
state.partial.edges.delete(edge);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Removes any nodes that have no incoming edges from the results.
|
|
32
|
+
*/
|
|
33
|
+
export const removeUnlinkedNodes = (state) => {
|
|
34
|
+
nodeLoop: for (const node of state.partial.nodes) {
|
|
35
|
+
for (const edge of state.partial.edges) {
|
|
36
|
+
if (edge.to === node) {
|
|
37
|
+
continue nodeLoop;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
state.partial.nodes.delete(node);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Removes quotes from a string value.
|
|
45
|
+
*/
|
|
46
|
+
export const removeQuotes = (value) => value.replace(/^"(.*?)"$/, '$1');
|
|
47
|
+
/**
|
|
48
|
+
* Asserts that the security archive is present.
|
|
49
|
+
*/
|
|
50
|
+
export const assertSecurityArchive = (state, name) => {
|
|
51
|
+
if (!state.securityArchive) {
|
|
52
|
+
throw error(`Missing security archive while trying to parse the :${name} selector`, { found: state });
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Clears all nodes and edges from the results.
|
|
57
|
+
*/
|
|
58
|
+
export const clear = (state) => {
|
|
59
|
+
state.partial.nodes.clear();
|
|
60
|
+
state.partial.edges.clear();
|
|
61
|
+
return state;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Reusable security selector alert filter.
|
|
65
|
+
*/
|
|
66
|
+
export const createSecuritySelectorFilter = (name, type) => {
|
|
67
|
+
return async (state) => {
|
|
68
|
+
assertSecurityArchive(state, name);
|
|
69
|
+
for (const node of state.partial.nodes) {
|
|
70
|
+
const report = state.securityArchive.get(node.id);
|
|
71
|
+
const exclude = !report?.alerts.some(alert => alert.type === type);
|
|
72
|
+
if (exclude) {
|
|
73
|
+
removeNode(state, node);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
removeDanglingEdges(state);
|
|
77
|
+
return state;
|
|
78
|
+
};
|
|
79
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ParserState } from '../types.ts';
|
|
2
|
+
import type { PostcssNode } from '@vltpkg/dss-parser';
|
|
3
|
+
/**
|
|
4
|
+
* Parses the internal parameters of the :host() pseudo selector.
|
|
5
|
+
* Returns the context key that should be used to look up the host context function.
|
|
6
|
+
*/
|
|
7
|
+
export declare const parseInternals: (nodes: PostcssNode[]) => string;
|
|
8
|
+
/**
|
|
9
|
+
* :host Pseudo-Selector, switches the current graph context to a new
|
|
10
|
+
* set of graphs loaded from a specific host context.
|
|
11
|
+
*
|
|
12
|
+
* This selector accepts a single parameter that specifies which host context
|
|
13
|
+
* to use. The host context must be defined in the hostContexts map provided
|
|
14
|
+
* to the Query constructor.
|
|
15
|
+
*
|
|
16
|
+
* Example:
|
|
17
|
+
* - :host(local) - Switches to graphs loaded from the local context
|
|
18
|
+
*/
|
|
19
|
+
export declare const hostContext: (state: ParserState) => Promise<ParserState>;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { error } from '@vltpkg/error-cause';
|
|
2
|
+
import { asPostcssNodeWithChildren, asStringNode, asTagNode, isStringNode, isTagNode, } from '@vltpkg/dss-parser';
|
|
3
|
+
import { removeQuotes } from "./helpers.js";
|
|
4
|
+
/**
|
|
5
|
+
* Parses the internal parameters of the :host() pseudo selector.
|
|
6
|
+
* Returns the context key that should be used to look up the host context function.
|
|
7
|
+
*/
|
|
8
|
+
export const parseInternals = (nodes) => {
|
|
9
|
+
let contextKey = '';
|
|
10
|
+
if (isStringNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])) {
|
|
11
|
+
contextKey = removeQuotes(asStringNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])
|
|
12
|
+
.value);
|
|
13
|
+
}
|
|
14
|
+
else if (isTagNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])) {
|
|
15
|
+
const tagNode = asTagNode(asPostcssNodeWithChildren(nodes[0]).nodes[0]);
|
|
16
|
+
contextKey = tagNode.value;
|
|
17
|
+
}
|
|
18
|
+
if (!contextKey) {
|
|
19
|
+
throw error('Expected a context key parameter for :host selector');
|
|
20
|
+
}
|
|
21
|
+
return contextKey;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* :host Pseudo-Selector, switches the current graph context to a new
|
|
25
|
+
* set of graphs loaded from a specific host context.
|
|
26
|
+
*
|
|
27
|
+
* This selector accepts a single parameter that specifies which host context
|
|
28
|
+
* to use. The host context must be defined in the hostContexts map provided
|
|
29
|
+
* to the Query constructor.
|
|
30
|
+
*
|
|
31
|
+
* Example:
|
|
32
|
+
* - :host(local) - Switches to graphs loaded from the local context
|
|
33
|
+
*/
|
|
34
|
+
export const hostContext = async (state) => {
|
|
35
|
+
if (!state.hostContexts) {
|
|
36
|
+
throw error('No host contexts available for :host selector');
|
|
37
|
+
}
|
|
38
|
+
let contextKey;
|
|
39
|
+
try {
|
|
40
|
+
contextKey = parseInternals(asPostcssNodeWithChildren(state.current).nodes);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
throw error('Failed to parse :host selector', {
|
|
44
|
+
cause: err,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
const contextFunction = state.hostContexts.get(contextKey);
|
|
48
|
+
if (!contextFunction) {
|
|
49
|
+
throw error(`Unknown host context: ${contextKey}`, {
|
|
50
|
+
validOptions: Array.from(state.hostContexts.keys()),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
// Get the graphs from the host context function
|
|
54
|
+
const { initialEdges, initialNodes, edges, nodes, securityArchive, } = await contextFunction();
|
|
55
|
+
// Clear current nodes and edges
|
|
56
|
+
state.securityArchive = securityArchive;
|
|
57
|
+
state.initial.nodes.clear();
|
|
58
|
+
state.initial.edges.clear();
|
|
59
|
+
state.partial.nodes.clear();
|
|
60
|
+
state.partial.edges.clear();
|
|
61
|
+
state.importers.clear();
|
|
62
|
+
// Reset the initial state
|
|
63
|
+
for (const node of initialNodes) {
|
|
64
|
+
state.initial.nodes.add(node);
|
|
65
|
+
}
|
|
66
|
+
for (const edge of initialEdges) {
|
|
67
|
+
state.initial.edges.add(edge);
|
|
68
|
+
}
|
|
69
|
+
// Populate with nodes and edges from all returned graphs
|
|
70
|
+
for (const node of nodes) {
|
|
71
|
+
state.partial.nodes.add(node);
|
|
72
|
+
// use the current selected nodes by the context function as importers
|
|
73
|
+
state.importers.add(node);
|
|
74
|
+
}
|
|
75
|
+
for (const edge of edges) {
|
|
76
|
+
state.partial.edges.add(edge);
|
|
77
|
+
}
|
|
78
|
+
return state;
|
|
79
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ParserState } from '../types.ts';
|
|
2
|
+
/**
|
|
3
|
+
* :hostname(str) Pseudo-Selector, matches only nodes whose
|
|
4
|
+
* upstream hostname matches the provided domain string.
|
|
5
|
+
*
|
|
6
|
+
* Examples:
|
|
7
|
+
* - :hostname("registry.npmjs.org") — default npm registry deps
|
|
8
|
+
* - :hostname("github.com") — github git deps
|
|
9
|
+
* - :hostname("example.com") — custom registry deps
|
|
10
|
+
*/
|
|
11
|
+
export declare const hostname: (state: ParserState) => Promise<ParserState>;
|