@nodesecure/tree-walker 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,128 @@
1
+ <p align="center"><h1 align="center">
2
+ @nodesecure/tree-walker
3
+ </h1>
4
+
5
+ <p align="center">
6
+ Fetch and walk the dependency tree of a given manifest
7
+ </p>
8
+
9
+ ## Requirements
10
+ - [Node.js](https://nodejs.org/en/) v20 or higher
11
+
12
+ ## Getting Started
13
+
14
+ This package is available in the Node Package Repository and can be easily installed with [npm](https://docs.npmjs.com/getting-started/what-is-npm) or [yarn](https://yarnpkg.com).
15
+
16
+ ```bash
17
+ $ npm i @nodesecure/tree-walker
18
+ # or
19
+ $ yarn add @nodesecure/tree-walker
20
+ ```
21
+
22
+ ## Usage example
23
+
24
+ ```ts
25
+ import os from "node:os";
26
+
27
+ import pacote from "pacote";
28
+ import { npm } from "@nodesecure/tree-walker";
29
+
30
+ const manifest = await pacote.manifest("some-package@1.0.0", {
31
+ cache: `${os.homedir()}/.npm`
32
+ });
33
+
34
+ const treeWalker = new npm.TreeWalker();
35
+
36
+ for await (const dependency of treeWalker.walk(manifest)) {
37
+ console.log(dependency);
38
+ }
39
+ ```
40
+
41
+ > [!NOTE]
42
+ > This package has been designed to be used by the Scanner package/workspace.
43
+
44
+ ## API
45
+
46
+ ### npm.TreeWalker
47
+
48
+ #### constructor(options?: TreeWalkerOptions)
49
+
50
+ ```ts
51
+ import pacote from "pacote";
52
+ import Arborist from "@npmcli/arborist";
53
+
54
+ interface LocalDependencyTreeLoaderProvider {
55
+ load(
56
+ location: string,
57
+ registry?: string
58
+ ): Promise<Arborist.Node>;
59
+ }
60
+
61
+ interface PacoteProviderApi {
62
+ manifest(
63
+ spec: string,
64
+ opts?: pacote.Options
65
+ ): Promise<pacote.AbbreviatedManifest & pacote.ManifestResult>;
66
+ }
67
+
68
+ interface TreeWalkerOptions {
69
+ registry?: string;
70
+ providers?: {
71
+ pacote?: PacoteProviderApi;
72
+ localTreeLoader?: LocalDependencyTreeLoaderProvider;
73
+ }
74
+ }
75
+ ```
76
+
77
+ #### *walk(manifest: PackageJSON | ManifestVersion, options: WalkOptions): AsyncIterableIterator< DependencyJSON >
78
+
79
+ The `walk` method processes package metadata from a given **package.json file** or a **Manifest** result from the [pacote](https://www.npmjs.com/package/pacote) library.
80
+
81
+ The `options` parameter is described by the following TypeScript interface:
82
+
83
+ ```ts
84
+ interface WalkOptions {
85
+ /**
86
+ * Specifies the maximum depth to traverse for each root dependency.
87
+ * For example, a value of 2 would mean only traversing dependencies and their immediate dependencies.
88
+ *
89
+ * @default Infinity
90
+ */
91
+ maxDepth?: number;
92
+
93
+ /**
94
+ * Includes development dependencies in the walk.
95
+ * Note that enabling this option can significantly increase processing time.
96
+ *
97
+ * @default false
98
+ */
99
+ includeDevDeps?: boolean;
100
+
101
+ /**
102
+ * Enables the use of Arborist for rapidly walking over the dependency tree.
103
+ * When enabled, it triggers different methods based on the presence of `node_modules`:
104
+ * - `loadActual()` if `node_modules` is available.
105
+ * - `loadVirtual()` otherwise.
106
+ *
107
+ * When disabled, it will iterate on all dependencies by using pacote
108
+ */
109
+ packageLock?: {
110
+ /**
111
+ * Fetches all manifests for additional metadata.
112
+ * This option is useful only when `usePackageLock` is enabled.
113
+ *
114
+ * @default false
115
+ */
116
+ fetchManifest?: boolean;
117
+
118
+ /**
119
+ * Specifies the location of the manifest file for Arborist.
120
+ * This is typically the path to the `package.json` file.
121
+ */
122
+ location: string;
123
+ };
124
+ }
125
+ ```
126
+
127
+ ## License
128
+ MIT
@@ -0,0 +1,41 @@
1
+ import * as JSXRay from "@nodesecure/js-x-ray";
2
+ export type NpmSpec = `${string}@${string}`;
3
+ export interface DependencyJSON {
4
+ id: number;
5
+ name: string;
6
+ version: string;
7
+ usedBy: Record<string, string>;
8
+ isDevDependency: boolean;
9
+ existOnRemoteRegistry: boolean;
10
+ flags: string[];
11
+ warnings: JSXRay.Warning<JSXRay.WarningDefault>[];
12
+ alias: Record<string, string>;
13
+ dependencyCount: number;
14
+ gitUrl: string | null;
15
+ }
16
+ export type DependencyOptions = {
17
+ parent?: Dependency;
18
+ } & Partial<Omit<DependencyJSON, "id" | "name" | "version">>;
19
+ export declare class Dependency {
20
+ #private;
21
+ static currentId: number;
22
+ name: string;
23
+ version: string;
24
+ dev: boolean;
25
+ existOnRemoteRegistry: boolean;
26
+ dependencyCount: number;
27
+ gitUrl: null | string;
28
+ warnings: JSXRay.Warning<JSXRay.WarningDefault>[];
29
+ alias: Record<string, string>;
30
+ constructor(name: string, version: string, options?: DependencyOptions);
31
+ addChildren(): void;
32
+ get spec(): NpmSpec;
33
+ get flags(): string[];
34
+ get parent(): {
35
+ [x: string]: string;
36
+ };
37
+ addFlag(flagName: string, predicate?: boolean): void;
38
+ isGit(url?: string): this;
39
+ exportAsPlainObject(customId?: number): DependencyJSON;
40
+ }
41
+ //# sourceMappingURL=Dependency.class.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Dependency.class.d.ts","sourceRoot":"","sources":["../src/Dependency.class.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,sBAAsB,CAAC;AAE/C,MAAM,MAAM,OAAO,GAAG,GAAG,MAAM,IAAI,MAAM,EAAE,CAAC;AAE5C,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,eAAe,EAAE,OAAO,CAAC;IACzB,qBAAqB,EAAE,OAAO,CAAC;IAC/B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;IAClD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;AAE7D,qBAAa,UAAU;;IACrB,MAAM,CAAC,SAAS,SAAK;IAEd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,UAAS;IACZ,qBAAqB,UAAQ;IAC7B,eAAe,SAAK;IACpB,MAAM,EAAE,IAAI,GAAG,MAAM,CAAQ;IAC7B,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAM;IACvD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM;gBAMxC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,iBAAsB;IAcjC,WAAW;IAIX,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,IAAI,KAAK,aAER;IAED,IAAI,MAAM;;MAET;IAED,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,UAAO;IAc1C,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM;IASlB,mBAAmB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,cAAc;CAmBvD"}
@@ -0,0 +1,74 @@
1
+ // Import Third-party Dependencies
2
+ import * as JSXRay from "@nodesecure/js-x-ray";
3
+ export class Dependency {
4
+ static currentId = 1;
5
+ name;
6
+ version;
7
+ dev = false;
8
+ existOnRemoteRegistry = true;
9
+ dependencyCount = 0;
10
+ gitUrl = null;
11
+ warnings = [];
12
+ alias = {};
13
+ #flags = new Set();
14
+ #parent = null;
15
+ constructor(name, version, options = {}) {
16
+ this.name = name;
17
+ this.version = version;
18
+ const { parent = null, ...props } = options;
19
+ if (parent !== null) {
20
+ parent.addChildren();
21
+ }
22
+ this.#parent = parent;
23
+ Object.assign(this, props);
24
+ }
25
+ addChildren() {
26
+ this.dependencyCount += 1;
27
+ }
28
+ get spec() {
29
+ return `${this.name}@${this.version}`;
30
+ }
31
+ get flags() {
32
+ return [...this.#flags];
33
+ }
34
+ get parent() {
35
+ return this.#parent === null ? {} : { [this.#parent.name]: this.#parent.version };
36
+ }
37
+ addFlag(flagName, predicate = true) {
38
+ if (typeof flagName !== "string") {
39
+ throw new TypeError("flagName argument must be typeof string");
40
+ }
41
+ if (predicate) {
42
+ if (flagName === "hasDependencies" && this.#parent !== null) {
43
+ this.#parent.addFlag("hasIndirectDependencies");
44
+ }
45
+ this.#flags.add(flagName);
46
+ }
47
+ }
48
+ isGit(url) {
49
+ this.#flags.add("isGit");
50
+ if (typeof url === "string") {
51
+ this.gitUrl = url;
52
+ }
53
+ return this;
54
+ }
55
+ exportAsPlainObject(customId) {
56
+ if (this.warnings.length > 0) {
57
+ this.addFlag("hasWarnings");
58
+ }
59
+ return {
60
+ id: typeof customId === "number" ? customId : Dependency.currentId++,
61
+ name: this.name,
62
+ version: this.version,
63
+ usedBy: this.parent,
64
+ isDevDependency: this.dev,
65
+ existOnRemoteRegistry: this.existOnRemoteRegistry,
66
+ flags: this.flags,
67
+ warnings: this.warnings,
68
+ dependencyCount: this.dependencyCount,
69
+ gitUrl: this.gitUrl,
70
+ alias: this.alias
71
+ };
72
+ }
73
+ }
74
+ //# sourceMappingURL=Dependency.class.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Dependency.class.js","sourceRoot":"","sources":["../src/Dependency.class.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * as npm from "./npm/walker.js";
2
+ export * from "./Dependency.class.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,iBAAiB,CAAC;AACvC,cAAc,uBAAuB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * as npm from "./npm/walker.js";
2
+ export * from "./Dependency.class.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,iBAAiB,CAAC;AACvC,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import Arborist from "@npmcli/arborist";
2
+ export interface LocalDependencyTreeLoaderProvider {
3
+ load(location: string, registry?: string): Promise<Arborist.Node>;
4
+ }
5
+ export declare class LocalDependencyTreeLoader implements LocalDependencyTreeLoaderProvider {
6
+ load(location: string, registry?: string): Promise<Arborist.Node>;
7
+ }
8
+ //# sourceMappingURL=LocalDependencyTreeLoader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LocalDependencyTreeLoader.d.ts","sourceRoot":"","sources":["../../src/npm/LocalDependencyTreeLoader.ts"],"names":[],"mappings":"AAQA,OAAO,QAAQ,MAAM,kBAAkB,CAAC;AAExC,MAAM,WAAW,iCAAiC;IAChD,IAAI,CACF,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,qBAAa,yBAA0B,YAAW,iCAAiC;IAC3E,IAAI,CACR,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;CAkB1B"}
@@ -0,0 +1,24 @@
1
+ // Import Node.js Dependencies
2
+ import path from "node:path";
3
+ import fs from "node:fs/promises";
4
+ // Import Internal Dependencies
5
+ import * as utils from "../utils/index.js";
6
+ // Import Third-party Dependencies
7
+ import Arborist from "@npmcli/arborist";
8
+ export class LocalDependencyTreeLoader {
9
+ async load(location, registry) {
10
+ const arb = new Arborist({
11
+ ...utils.NPM_TOKEN,
12
+ path: location,
13
+ registry
14
+ });
15
+ try {
16
+ await fs.access(path.join(location, "node_modules"));
17
+ return await arb.loadActual();
18
+ }
19
+ catch {
20
+ return arb.loadVirtual();
21
+ }
22
+ }
23
+ }
24
+ //# sourceMappingURL=LocalDependencyTreeLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LocalDependencyTreeLoader.js","sourceRoot":"","sources":["../../src/npm/LocalDependencyTreeLoader.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAElC,+BAA+B;AAC/B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,kCAAkC;AAClC,OAAO,QAAQ,MAAM,kBAAkB,CAAC;AASxC,MAAM,OAAO,yBAAyB;IACpC,KAAK,CAAC,IAAI,CACR,QAAgB,EAChB,QAAiB;QAEjB,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC;YACvB,GAAG,KAAK,CAAC,SAAS;YAClB,IAAI,EAAE,QAAQ;YACd,QAAQ;SACT,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CACb,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CACpC,CAAC;YAEF,OAAO,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC;QAChC,CAAC;QACD,MAAM,CAAC;YACL,OAAO,GAAG,CAAC,WAAW,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,69 @@
1
+ import pacote from "pacote";
2
+ import type { PackageJSON, ManifestVersion } from "@nodesecure/npm-types";
3
+ import { type LocalDependencyTreeLoaderProvider } from "./LocalDependencyTreeLoader.js";
4
+ import { type DependencyJSON, type NpmSpec } from "../Dependency.class.js";
5
+ export interface PacoteProviderApi {
6
+ manifest(spec: string, opts?: pacote.Options): Promise<pacote.AbbreviatedManifest & pacote.ManifestResult>;
7
+ packument(spec: string, opts?: pacote.Options): Promise<pacote.AbbreviatedPackument & pacote.PackumentResult>;
8
+ }
9
+ export interface TreeWalkerOptions {
10
+ registry?: string;
11
+ providers?: {
12
+ pacote?: PacoteProviderApi;
13
+ localTreeLoader?: LocalDependencyTreeLoaderProvider;
14
+ };
15
+ }
16
+ export interface WalkOptions {
17
+ /**
18
+ * Specifies the maximum depth to traverse for each root dependency.
19
+ * For example, a value of 2 would mean only traversing dependencies and their immediate dependencies.
20
+ *
21
+ * @default Infinity
22
+ */
23
+ maxDepth?: number;
24
+ /**
25
+ * Includes development dependencies in the walk.
26
+ * Note that enabling this option can significantly increase processing time.
27
+ *
28
+ * @default false
29
+ */
30
+ includeDevDeps?: boolean;
31
+ /**
32
+ * Enables the use of Arborist for rapidly walking over the dependency tree.
33
+ * When enabled, it triggers different methods based on the presence of `node_modules`:
34
+ * - `loadActual()` if `node_modules` is available.
35
+ * - `loadVirtual()` otherwise.
36
+ *
37
+ * When disabled, it will iterate on all dependencies by using pacote
38
+ */
39
+ packageLock?: {
40
+ /**
41
+ * Fetches all manifests for additional metadata.
42
+ * This option is useful only when `usePackageLock` is enabled.
43
+ *
44
+ * @default false
45
+ */
46
+ fetchManifest?: boolean;
47
+ /**
48
+ * Specifies the location of the manifest file for Arborist.
49
+ * This is typically the path to the `package.json` file.
50
+ */
51
+ location: string;
52
+ };
53
+ }
54
+ export declare class TreeWalker {
55
+ /**
56
+ * A Map of Children Spec -> Parent Spec (as a unique list)
57
+ */
58
+ relationsMap: Map<NpmSpec, Set<NpmSpec>>;
59
+ registry: string;
60
+ private providers;
61
+ constructor(options?: TreeWalkerOptions);
62
+ private get registryOptions();
63
+ private addTreeRelation;
64
+ private resolveDependencyVersion;
65
+ private walkRemoteDependency;
66
+ private walkLocalDependency;
67
+ walk(manifest: PackageJSON | ManifestVersion, options?: WalkOptions): AsyncIterableIterator<DependencyJSON>;
68
+ }
69
+ //# sourceMappingURL=walker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walker.d.ts","sourceRoot":"","sources":["../../src/npm/walker.ts"],"names":[],"mappings":"AAMA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAK5B,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAI1E,OAAO,EAEL,KAAK,iCAAiC,EACvC,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,OAAO,EACb,MAAM,wBAAwB,CAAC;AAehC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CACN,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,OAAO,GACpB,OAAO,CAAC,MAAM,CAAC,mBAAmB,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;IAC/D,SAAS,CACP,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,OAAO,GACpB,OAAO,CAAC,MAAM,CAAC,oBAAoB,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;CAClE;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE;QACV,MAAM,CAAC,EAAE,iBAAiB,CAAC;QAC3B,eAAe,CAAC,EAAE,iCAAiC,CAAC;KACrD,CAAA;CACF;AAED,MAAM,WAAW,WAAW;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE;QACZ;;;;;WAKG;QACH,aAAa,CAAC,EAAE,OAAO,CAAC;QAExB;;;WAGG;QACH,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,qBAAa,UAAU;IACrB;;OAEG;IACI,YAAY,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAa;IACrD,QAAQ,EAAE,MAAM,CAAC;IAExB,OAAO,CAAC,SAAS,CAGd;gBAGD,OAAO,GAAE,iBAAsB;IAQjC,OAAO,KAAK,eAAe,GAM1B;IAED,OAAO,CAAC,eAAe;YAaT,wBAAwB;YA2BvB,oBAAoB;YAqEpB,mBAAmB;IAqD3B,IAAI,CACT,QAAQ,EAAE,WAAW,GAAG,eAAe,EACvC,OAAO,GAAE,WAAgB,GACxB,qBAAqB,CAAC,cAAc,CAAC;CA8FzC"}
@@ -0,0 +1,211 @@
1
+ // Import Node.js Dependencies
2
+ import os from "node:os";
3
+ // Import Third-party Dependencies
4
+ import * as iter from "itertools";
5
+ import combineAsyncIterators from "combine-async-iterators";
6
+ import pacote from "pacote";
7
+ import Arborist from "@npmcli/arborist";
8
+ // @ts-ignore
9
+ import pickManifest from "npm-pick-manifest";
10
+ import { getNpmRegistryURL } from "@nodesecure/npm-registry-sdk";
11
+ // Import Internal Dependencies
12
+ import * as utils from "../utils/index.js";
13
+ import { LocalDependencyTreeLoader } from "./LocalDependencyTreeLoader.js";
14
+ import { Dependency } from "../Dependency.class.js";
15
+ export class TreeWalker {
16
+ /**
17
+ * A Map of Children Spec -> Parent Spec (as a unique list)
18
+ */
19
+ relationsMap = new Map();
20
+ registry;
21
+ providers = Object.seal({
22
+ pacote,
23
+ localTreeLoader: new LocalDependencyTreeLoader()
24
+ });
25
+ constructor(options = {}) {
26
+ const { providers = {} } = options;
27
+ this.registry = options?.registry ?? getNpmRegistryURL();
28
+ Object.assign(this.providers, providers);
29
+ }
30
+ get registryOptions() {
31
+ return {
32
+ ...utils.NPM_TOKEN,
33
+ registry: this.registry,
34
+ cache: `${os.homedir()}/.npm`
35
+ };
36
+ }
37
+ addTreeRelation(key, value) {
38
+ if (!this.relationsMap.has(key)) {
39
+ return;
40
+ }
41
+ this.relationsMap
42
+ .get(key)
43
+ .add(value);
44
+ }
45
+ async resolveDependencyVersion(dependency) {
46
+ const [dependencyName, range] = dependency;
47
+ try {
48
+ const packument = await this.providers.pacote.packument(dependencyName, this.registryOptions);
49
+ const manifest = pickManifest(packument, range);
50
+ return {
51
+ rangedSpec: `${dependencyName}@${range}`,
52
+ spec: `${dependencyName}@${manifest.version}`,
53
+ isLatest: manifest.version === packument["dist-tags"].latest
54
+ };
55
+ }
56
+ catch {
57
+ return {
58
+ rangedSpec: `${dependencyName}@${range}`,
59
+ spec: `${dependencyName}@${utils.cleanRange(range)}`,
60
+ isLatest: true
61
+ };
62
+ }
63
+ }
64
+ async *walkRemoteDependency(spec, options) {
65
+ const { currDepth = 1, parent, maxDepth, gitURL } = options;
66
+ const { name, version, deprecated, ...pkg } = await this.providers.pacote.manifest(gitURL ?? spec, this.registryOptions);
67
+ const { dependencies, customResolvers, alias } = utils.mergeDependencies(pkg);
68
+ const current = new Dependency(name, version, {
69
+ parent,
70
+ alias: Object.fromEntries(alias)
71
+ });
72
+ if (gitURL !== null) {
73
+ current.isGit(gitURL);
74
+ try {
75
+ await this.providers.pacote.manifest(`${name}@${version}`, this.registryOptions);
76
+ }
77
+ catch {
78
+ current.existOnRemoteRegistry = false;
79
+ }
80
+ }
81
+ current.addFlag("isDeprecated", deprecated === true);
82
+ current.addFlag("hasCustomResolver", customResolvers.size > 0);
83
+ current.addFlag("hasDependencies", dependencies.size > 0);
84
+ if (currDepth < maxDepth) {
85
+ const config = {
86
+ currDepth: currDepth + 1, parent: current, maxDepth
87
+ };
88
+ const gitDependencies = iter.filter(customResolvers.entries(), ([, valueStr]) => utils.isGitDependency(valueStr));
89
+ for (const [depName, gitURL] of gitDependencies) {
90
+ yield* this.walkRemoteDependency(depName, { ...config, gitURL });
91
+ }
92
+ const resolvedDependencies = await Promise.all(iter.map(dependencies.entries(), this.resolveDependencyVersion.bind(this)));
93
+ for (const { rangedSpec, spec, isLatest } of resolvedDependencies) {
94
+ if (!isLatest) {
95
+ current.addFlag("hasOutdatedDependency");
96
+ }
97
+ if (this.relationsMap.has(spec)) {
98
+ current.addChildren();
99
+ this.relationsMap.get(spec).add(current.spec);
100
+ }
101
+ else {
102
+ this.relationsMap.set(spec, new Set([current.spec]));
103
+ yield* this.walkRemoteDependency(rangedSpec, config);
104
+ }
105
+ }
106
+ }
107
+ yield current;
108
+ }
109
+ async *walkLocalDependency(packageName, node, options) {
110
+ const { parent, fetchManifest = false, includeDevDeps = false } = options;
111
+ const { version, integrity = node.integrity } = node.package;
112
+ const updatedVersion = version === "*" || typeof version === "undefined" ?
113
+ "latest" : version;
114
+ const current = new Dependency(packageName, updatedVersion, {
115
+ parent,
116
+ isDevDependency: node.dev
117
+ });
118
+ if (fetchManifest && !includeDevDeps) {
119
+ const { _integrity, ...pkg } = await this.providers.pacote.manifest(`${packageName}@${updatedVersion}`, this.registryOptions);
120
+ const { customResolvers, alias } = utils.mergeDependencies(pkg);
121
+ current.alias = Object.fromEntries(alias);
122
+ current.addFlag("hasValidIntegrity", _integrity === integrity);
123
+ current.addFlag("isDeprecated");
124
+ current.addFlag("hasCustomResolver", customResolvers.size > 0);
125
+ if (node.resolved && utils.isGitDependency(node.resolved)) {
126
+ current.isGit(node.resolved);
127
+ }
128
+ }
129
+ current.addFlag("hasDependencies", node.edgesOut.size > 0);
130
+ for (const [packageName, { to: toNode }] of node.edgesOut) {
131
+ if (toNode === null || (!includeDevDeps && toNode.dev)) {
132
+ continue;
133
+ }
134
+ const spec = `${packageName}@${toNode.package.version}`;
135
+ if (this.relationsMap.has(spec)) {
136
+ current.addChildren();
137
+ this.relationsMap.get(spec).add(current.spec);
138
+ }
139
+ else {
140
+ this.relationsMap.set(spec, new Set([current.spec]));
141
+ yield* this.walkLocalDependency(packageName, toNode, { parent: current });
142
+ }
143
+ }
144
+ yield current;
145
+ }
146
+ async *walk(manifest, options = {}) {
147
+ this.relationsMap.clear();
148
+ const { maxDepth = Infinity, packageLock = null, includeDevDeps = false } = options;
149
+ const { dependencies, customResolvers, alias } = utils.mergeDependencies(manifest);
150
+ const rootDependency = new Dependency(manifest.name, manifest.version, {
151
+ alias: Object.fromEntries(alias)
152
+ });
153
+ try {
154
+ await this.providers.pacote.manifest(`${manifest.name}@${manifest.version}`, this.registryOptions);
155
+ }
156
+ catch {
157
+ rootDependency.existOnRemoteRegistry = false;
158
+ }
159
+ rootDependency.addFlag("hasCustomResolver", customResolvers.size > 0);
160
+ rootDependency.addFlag("hasDependencies", dependencies.size > 0);
161
+ if (packageLock === null) {
162
+ const walkRemoteOptions = { maxDepth, parent: rootDependency };
163
+ const iterators = [
164
+ ...iter
165
+ .filter(customResolvers.entries(), ([, version]) => utils.isGitDependency(version))
166
+ .map(([name, gitURL]) => this.walkRemoteDependency(name, { ...walkRemoteOptions, gitURL })),
167
+ ...iter
168
+ .map(dependencies.entries(), ([name, ver]) => this.walkRemoteDependency(`${name}@${ver}`, walkRemoteOptions))
169
+ ];
170
+ for await (const dep of combineAsyncIterators({}, ...iterators)) {
171
+ yield dep.exportAsPlainObject();
172
+ }
173
+ /**
174
+ * Add root dependencies to the relations Map because the parent is not handled by walkRemoteDependency.
175
+ * If we skip this step, the code will fail to properly re-link dependencies in the subsequent steps.
176
+ */
177
+ const resolvedDependencies = await Promise.all(iter.map(dependencies.entries(), this.resolveDependencyVersion.bind(this)));
178
+ for (const { spec, isLatest } of resolvedDependencies) {
179
+ if (!isLatest) {
180
+ rootDependency.addFlag("hasOutdatedDependency");
181
+ }
182
+ this.addTreeRelation(spec, rootDependency.spec);
183
+ }
184
+ }
185
+ else {
186
+ const { location, ...packageLockOptions } = packageLock;
187
+ const { edgesOut } = await this.providers.localTreeLoader.load(location, this.registry);
188
+ const iterators = [
189
+ ...iter
190
+ .filter(edgesOut.entries(), ([, { to }]) => to !== null && (includeDevDeps ? true : (!to.dev || to.isWorkspace)))
191
+ .map(([packageName, { to }]) => [packageName, to.isWorkspace ? to.target : to])
192
+ .map(([packageName, to]) => this.walkLocalDependency(packageName, to, {
193
+ parent: rootDependency,
194
+ includeDevDeps,
195
+ ...packageLockOptions
196
+ }))
197
+ ];
198
+ for await (const dep of combineAsyncIterators({}, ...iterators)) {
199
+ yield dep.exportAsPlainObject();
200
+ }
201
+ for (const [packageName, { to: toNode }] of edgesOut) {
202
+ if (toNode === null || (!includeDevDeps && toNode.dev)) {
203
+ continue;
204
+ }
205
+ this.addTreeRelation(`${packageName}@${toNode.package.version}`, rootDependency.spec);
206
+ }
207
+ }
208
+ yield rootDependency.exportAsPlainObject(0);
209
+ }
210
+ }
211
+ //# sourceMappingURL=walker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walker.js","sourceRoot":"","sources":["../../src/npm/walker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export declare const NPM_TOKEN: {
2
+ token: string;
3
+ } | {
4
+ token?: undefined;
5
+ };
6
+ export * from "./mergeDependencies.js";
7
+ export * from "./isGitDependency.js";
8
+ export * from "./semver.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,SAAS;;;;CAElB,CAAC;AAEL,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,aAAa,CAAC"}
@@ -0,0 +1,8 @@
1
+ // CONSTANTS
2
+ export const NPM_TOKEN = typeof process.env.NODE_SECURE_TOKEN === "string" ?
3
+ { token: process.env.NODE_SECURE_TOKEN } :
4
+ {};
5
+ export * from "./mergeDependencies.js";
6
+ export * from "./isGitDependency.js";
7
+ export * from "./semver.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,YAAY;AACZ,MAAM,CAAC,MAAM,SAAS,GAAG,OAAO,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,QAAQ,CAAC,CAAC;IAC1E,EAAE,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAC1C,EAAE,CAAC;AAEL,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,aAAa,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @example isGitDependency("github:NodeSecure/scanner") // => true
3
+ * @example isGitDependency("git+ssh://git@github.com:npm/cli#semver:^5.0") // => true
4
+ * @example isGitDependency(">=1.0.2 <2.1.2") // => false
5
+ * @example isGitDependency("http://asdf.com/asdf.tar.gz") // => false
6
+ * @param {string} version
7
+ * @returns {boolean}
8
+ */
9
+ export declare function isGitDependency(version: string): boolean;
10
+ //# sourceMappingURL=isGitDependency.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isGitDependency.d.ts","sourceRoot":"","sources":["../../src/utils/isGitDependency.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAExD"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @example isGitDependency("github:NodeSecure/scanner") // => true
3
+ * @example isGitDependency("git+ssh://git@github.com:npm/cli#semver:^5.0") // => true
4
+ * @example isGitDependency(">=1.0.2 <2.1.2") // => false
5
+ * @example isGitDependency("http://asdf.com/asdf.tar.gz") // => false
6
+ * @param {string} version
7
+ * @returns {boolean}
8
+ */
9
+ export function isGitDependency(version) {
10
+ return /^git(:|\+|hub:)/.test(version);
11
+ }
12
+ //# sourceMappingURL=isGitDependency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isGitDependency.js","sourceRoot":"","sources":["../../src/utils/isGitDependency.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,OAAO,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { PackageJSON } from "@nodesecure/npm-types";
2
+ export type NpmDependency = "dependencies" | "devDependencies" | "optionalDependencies" | "peerDependencies" | "bundleDependencies" | "bundledDependencies";
3
+ export declare function mergeDependencies(manifest: Partial<PackageJSON>, types?: NpmDependency[]): {
4
+ dependencies: Map<string, string>;
5
+ customResolvers: Map<string, string>;
6
+ alias: Map<string, string>;
7
+ };
8
+ //# sourceMappingURL=mergeDependencies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mergeDependencies.d.ts","sourceRoot":"","sources":["../../src/utils/mergeDependencies.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD,MAAM,MAAM,aAAa,GACvB,cAAc,GACd,iBAAiB,GACjB,sBAAsB,GACtB,kBAAkB,GAClB,oBAAoB,GACpB,qBAAqB,CAAC;AAExB,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,OAAO,CAAC,WAAW,CAAC,EAC9B,KAAK,GAAE,aAAa,EAA8B;;;;EA+BnD"}
@@ -0,0 +1,27 @@
1
+ export function mergeDependencies(manifest, types = ["dependencies"]) {
2
+ const dependencies = new Map();
3
+ const customResolvers = new Map();
4
+ const alias = new Map();
5
+ for (const fieldName of types) {
6
+ if (!(fieldName in manifest)) {
7
+ continue;
8
+ }
9
+ const dep = manifest[fieldName];
10
+ for (const [name, version] of Object.entries(dep)) {
11
+ /**
12
+ * Version can be file:, github:, git:, git+, ./...
13
+ * @see https://docs.npmjs.com/cli/v7/configuring-npm/package-json#dependencies
14
+ */
15
+ if (/^([a-zA-Z]+:|git\+|\.\\)/.test(version)) {
16
+ customResolvers.set(name, version);
17
+ if (!version.startsWith("npm:")) {
18
+ continue;
19
+ }
20
+ alias.set(name, version.slice(4));
21
+ }
22
+ dependencies.set(name, version);
23
+ }
24
+ }
25
+ return { dependencies, customResolvers, alias };
26
+ }
27
+ //# sourceMappingURL=mergeDependencies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mergeDependencies.js","sourceRoot":"","sources":["../../src/utils/mergeDependencies.ts"],"names":[],"mappings":"AAWA,MAAM,UAAU,iBAAiB,CAC/B,QAA8B,EAC9B,QAAyB,CAAC,cAAc,CAAU;IAElD,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC/C,MAAM,eAAe,GAAG,IAAI,GAAG,EAAkB,CAAC;IAClD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IAExC,KAAK,MAAM,SAAS,IAAI,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC,CAAC,SAAS,IAAI,QAAQ,CAAC,EAAE,CAAC;YAC7B,SAAS;QACX,CAAC;QAED,MAAM,GAAG,GAAG,QAAQ,CAAC,SAAS,CAA2B,CAAC;QAE1D,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAClD;;;eAGG;YACH,IAAI,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC7C,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;gBACnC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;oBAChC,SAAS;gBACX,CAAC;gBACD,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACpC,CAAC;YAED,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC;AAClD,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @example
3
+ * cleanRange(">=1.5.0"); // 1.5.0
4
+ * cleanRange("^2.0.0"); // 2.0.0
5
+ */
6
+ export declare function cleanRange(version: string): string;
7
+ //# sourceMappingURL=semver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semver.d.ts","sourceRoot":"","sources":["../../src/utils/semver.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,MAAM,GACd,MAAM,CAQR"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @example
3
+ * cleanRange(">=1.5.0"); // 1.5.0
4
+ * cleanRange("^2.0.0"); // 2.0.0
5
+ */
6
+ export function cleanRange(version) {
7
+ // TODO: how do we handle complicated range like pkg-name@1 || 2 or pkg-name@2.1.2 < 3
8
+ const firstChar = version.charAt(0);
9
+ if (firstChar === "^" || firstChar === "<" || firstChar === ">" || firstChar === "=" || firstChar === "~") {
10
+ return version.slice(version.charAt(1) === "=" ? 2 : 1);
11
+ }
12
+ return version;
13
+ }
14
+ //# sourceMappingURL=semver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semver.js","sourceRoot":"","sources":["../../src/utils/semver.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,UAAU,CACxB,OAAe;IAEf,sFAAsF;IACtF,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACpC,IAAI,SAAS,KAAK,GAAG,IAAI,SAAS,KAAK,GAAG,IAAI,SAAS,KAAK,GAAG,IAAI,SAAS,KAAK,GAAG,IAAI,SAAS,KAAK,GAAG,EAAE,CAAC;QAC1G,OAAO,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@nodesecure/tree-walker",
3
+ "version": "1.0.0",
4
+ "description": "NodeSecure tree walker",
5
+ "type": "module",
6
+ "exports": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "scripts": {
9
+ "build": "tsc -b",
10
+ "prepublishOnly": "npm run build",
11
+ "test-only": "glob -c \"tsx --test\" \"./test/**/*.spec.ts\"",
12
+ "test": "c8 -r html npm run test-only"
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "keywords": [
18
+ "NodeSecure",
19
+ "tree",
20
+ "walker"
21
+ ],
22
+ "author": "GENTILHOMME Thomas <gentilhomme.thomas@gmail.com>",
23
+ "license": "MIT",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/NodeSecure/scanner.git"
27
+ },
28
+ "bugs": {
29
+ "url": "https://github.com/NodeSecure/scanner/issues"
30
+ },
31
+ "homepage": "https://github.com/NodeSecure/tree/master/workspaces/tree-walker#readme",
32
+ "dependencies": {
33
+ "@nodesecure/js-x-ray": "^7.3.0",
34
+ "@nodesecure/npm-registry-sdk": "^3.0.0",
35
+ "@nodesecure/npm-types": "^1.1.0",
36
+ "@npmcli/arborist": "^7.5.1",
37
+ "combine-async-iterators": "^3.0.0",
38
+ "itertools": "^2.3.1",
39
+ "npm-pick-manifest": "^9.1.0",
40
+ "pacote": "^18.0.4",
41
+ "semver": "^7.6.0"
42
+ },
43
+ "devDependencies": {
44
+ "@types/npmcli__arborist": "^5.6.9"
45
+ }
46
+ }