workspace-tools 0.20.0 → 0.21.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/CHANGELOG.json +16 -1
- package/CHANGELOG.md +10 -2
- package/lib/__tests__/graph.test.d.ts +1 -0
- package/lib/__tests__/graph.test.js +117 -0
- package/lib/createDependencyMap.d.ts +9 -0
- package/lib/createDependencyMap.js +25 -0
- package/lib/dependencies.d.ts +7 -0
- package/lib/dependencies.js +7 -2
- package/lib/graph.d.ts +8 -6
- package/lib/graph.js +55 -21
- package/lib/types/PackageGraph.d.ts +14 -0
- package/lib/types/PackageGraph.js +3 -0
- package/package.json +2 -1
package/CHANGELOG.json
CHANGED
|
@@ -2,7 +2,22 @@
|
|
|
2
2
|
"name": "workspace-tools",
|
|
3
3
|
"entries": [
|
|
4
4
|
{
|
|
5
|
-
"date": "
|
|
5
|
+
"date": "Fri, 01 Jul 2022 14:55:58 GMT",
|
|
6
|
+
"tag": "workspace-tools_v0.21.0",
|
|
7
|
+
"version": "0.21.0",
|
|
8
|
+
"comments": {
|
|
9
|
+
"minor": [
|
|
10
|
+
{
|
|
11
|
+
"author": "ken@gizzar.com",
|
|
12
|
+
"package": "workspace-tools",
|
|
13
|
+
"comment": "adds a package graph implementation",
|
|
14
|
+
"commit": "28ba85b087e3e3bb8715ea637563793fbb97b069"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"date": "Thu, 23 Jun 2022 20:24:15 GMT",
|
|
6
21
|
"tag": "workspace-tools_v0.20.0",
|
|
7
22
|
"version": "0.20.0",
|
|
8
23
|
"comments": {
|
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
# Change Log - workspace-tools
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Fri, 01 Jul 2022 14:55:58 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## 0.21.0
|
|
8
|
+
|
|
9
|
+
Fri, 01 Jul 2022 14:55:58 GMT
|
|
10
|
+
|
|
11
|
+
### Minor changes
|
|
12
|
+
|
|
13
|
+
- adds a package graph implementation (ken@gizzar.com)
|
|
14
|
+
|
|
7
15
|
## 0.20.0
|
|
8
16
|
|
|
9
|
-
Thu, 23 Jun 2022 20:24:
|
|
17
|
+
Thu, 23 Jun 2022 20:24:15 GMT
|
|
10
18
|
|
|
11
19
|
### Minor changes
|
|
12
20
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const graph_1 = require("../graph");
|
|
4
|
+
describe("createPackageGraph", () => {
|
|
5
|
+
it("can get linear dependencies", () => {
|
|
6
|
+
const allPackages = {
|
|
7
|
+
a: stubPackage("a", ["b"]),
|
|
8
|
+
b: stubPackage("b", ["c"]),
|
|
9
|
+
c: stubPackage("c"),
|
|
10
|
+
};
|
|
11
|
+
const actual = (0, graph_1.createPackageGraph)(allPackages, { namePatterns: ["a"], includeDependencies: true });
|
|
12
|
+
expect(actual).toMatchInlineSnapshot(`
|
|
13
|
+
Object {
|
|
14
|
+
"dependencies": Array [
|
|
15
|
+
Object {
|
|
16
|
+
"dependency": "b",
|
|
17
|
+
"name": "a",
|
|
18
|
+
},
|
|
19
|
+
Object {
|
|
20
|
+
"dependency": "c",
|
|
21
|
+
"name": "b",
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
"packages": Array [
|
|
25
|
+
"a",
|
|
26
|
+
"b",
|
|
27
|
+
"c",
|
|
28
|
+
],
|
|
29
|
+
}
|
|
30
|
+
`);
|
|
31
|
+
});
|
|
32
|
+
it("can represent a graph with some nodes with no edges", () => {
|
|
33
|
+
const allPackages = {
|
|
34
|
+
a: stubPackage("a"),
|
|
35
|
+
b: stubPackage("b"),
|
|
36
|
+
c: stubPackage("c"),
|
|
37
|
+
};
|
|
38
|
+
const actual = (0, graph_1.createPackageGraph)(allPackages);
|
|
39
|
+
expect(actual).toMatchInlineSnapshot(`
|
|
40
|
+
Object {
|
|
41
|
+
"dependencies": Array [],
|
|
42
|
+
"packages": Array [
|
|
43
|
+
"c",
|
|
44
|
+
"b",
|
|
45
|
+
"a",
|
|
46
|
+
],
|
|
47
|
+
}
|
|
48
|
+
`);
|
|
49
|
+
});
|
|
50
|
+
it("can get linear dependents", () => {
|
|
51
|
+
const allPackages = {
|
|
52
|
+
a: stubPackage("a", ["b"]),
|
|
53
|
+
b: stubPackage("b", ["c"]),
|
|
54
|
+
c: stubPackage("c"),
|
|
55
|
+
};
|
|
56
|
+
const actual = (0, graph_1.createPackageGraph)(allPackages, { namePatterns: ["c"], includeDependents: true });
|
|
57
|
+
expect(actual).toMatchInlineSnapshot(`
|
|
58
|
+
Object {
|
|
59
|
+
"dependencies": Array [
|
|
60
|
+
Object {
|
|
61
|
+
"dependency": "c",
|
|
62
|
+
"name": "b",
|
|
63
|
+
},
|
|
64
|
+
Object {
|
|
65
|
+
"dependency": "b",
|
|
66
|
+
"name": "a",
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
"packages": Array [
|
|
70
|
+
"c",
|
|
71
|
+
"b",
|
|
72
|
+
"a",
|
|
73
|
+
],
|
|
74
|
+
}
|
|
75
|
+
`);
|
|
76
|
+
});
|
|
77
|
+
it("will handle circular dependencies", () => {
|
|
78
|
+
const allPackages = {
|
|
79
|
+
a: stubPackage("a", ["b"]),
|
|
80
|
+
b: stubPackage("b", ["c"]),
|
|
81
|
+
c: stubPackage("c", ["a"]),
|
|
82
|
+
};
|
|
83
|
+
const actual = (0, graph_1.createPackageGraph)(allPackages, { namePatterns: ["a"], includeDependencies: true });
|
|
84
|
+
expect(actual).toMatchInlineSnapshot(`
|
|
85
|
+
Object {
|
|
86
|
+
"dependencies": Array [
|
|
87
|
+
Object {
|
|
88
|
+
"dependency": "b",
|
|
89
|
+
"name": "a",
|
|
90
|
+
},
|
|
91
|
+
Object {
|
|
92
|
+
"dependency": "c",
|
|
93
|
+
"name": "b",
|
|
94
|
+
},
|
|
95
|
+
Object {
|
|
96
|
+
"dependency": "a",
|
|
97
|
+
"name": "c",
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
"packages": Array [
|
|
101
|
+
"a",
|
|
102
|
+
"b",
|
|
103
|
+
"c",
|
|
104
|
+
],
|
|
105
|
+
}
|
|
106
|
+
`);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
function stubPackage(name, deps = []) {
|
|
110
|
+
return {
|
|
111
|
+
name,
|
|
112
|
+
packageJsonPath: `packages/${name}`,
|
|
113
|
+
version: "1.0",
|
|
114
|
+
dependencies: deps.reduce((depMap, dep) => (Object.assign(Object.assign({}, depMap), { [dep]: "*" })), {}),
|
|
115
|
+
devDependencies: {},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { PackageInfos } from "./types/PackageInfo";
|
|
2
|
+
export interface DependencyMap {
|
|
3
|
+
dependencies: Map<string, Set<string>>;
|
|
4
|
+
dependents: Map<string, Set<string>>;
|
|
5
|
+
}
|
|
6
|
+
export declare function createDependencyMap(packages: PackageInfos): {
|
|
7
|
+
dependencies: Map<string, Set<string>>;
|
|
8
|
+
dependents: Map<string, Set<string>>;
|
|
9
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createDependencyMap = void 0;
|
|
4
|
+
// @internal
|
|
5
|
+
function createDependencyMap(packages) {
|
|
6
|
+
const map = {
|
|
7
|
+
dependencies: new Map(),
|
|
8
|
+
dependents: new Map(),
|
|
9
|
+
};
|
|
10
|
+
for (const [pkg, info] of Object.entries(packages)) {
|
|
11
|
+
const deps = Object.keys(Object.assign(Object.assign({}, info.dependencies), info.devDependencies));
|
|
12
|
+
for (const dep of deps) {
|
|
13
|
+
if (!map.dependencies.has(pkg)) {
|
|
14
|
+
map.dependencies.set(pkg, new Set());
|
|
15
|
+
}
|
|
16
|
+
map.dependencies.get(pkg).add(dep);
|
|
17
|
+
if (!map.dependents.has(dep)) {
|
|
18
|
+
map.dependents.set(dep, new Set());
|
|
19
|
+
}
|
|
20
|
+
map.dependents.get(dep).add(pkg);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return map;
|
|
24
|
+
}
|
|
25
|
+
exports.createDependencyMap = createDependencyMap;
|
package/lib/dependencies.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { PackageInfo, PackageInfos } from "./types/PackageInfo";
|
|
2
2
|
export declare function getDependentMap(packages: PackageInfos): Map<string, Set<string>>;
|
|
3
3
|
/**
|
|
4
|
+
* @deprecated Do not use
|
|
5
|
+
*
|
|
4
6
|
* for a package graph of a->b->c (where b depends on a), transitive consumers of a are b & c and their consumers (or what are the consequences of a)
|
|
5
7
|
* @param targets
|
|
6
8
|
* @param packages
|
|
@@ -8,11 +10,16 @@ export declare function getDependentMap(packages: PackageInfos): Map<string, Set
|
|
|
8
10
|
*/
|
|
9
11
|
export declare function getTransitiveConsumers(targets: string[], packages: PackageInfos, scope?: string[]): string[];
|
|
10
12
|
/**
|
|
13
|
+
* @deprecated Do not use
|
|
14
|
+
*
|
|
11
15
|
* for a package graph of a->b->c (where b depends on a), transitive providers of c are a & b and their providers (or what is needed to satisfy c)
|
|
12
16
|
* @param targets
|
|
13
17
|
* @param packages
|
|
14
18
|
*/
|
|
15
19
|
export declare function getTransitiveProviders(targets: string[], packages: PackageInfos): string[];
|
|
20
|
+
/** @deprecated Do not use */
|
|
16
21
|
export declare const getTransitiveDependencies: typeof getTransitiveProviders;
|
|
22
|
+
/** @deprecated Do not use */
|
|
17
23
|
export declare const getTransitiveDependents: typeof getTransitiveConsumers;
|
|
24
|
+
/** @deprecated Do not use */
|
|
18
25
|
export declare function getInternalDeps(info: PackageInfo, packages: PackageInfos): string[];
|
package/lib/dependencies.js
CHANGED
|
@@ -49,6 +49,8 @@ function getDependentMap(packages) {
|
|
|
49
49
|
}
|
|
50
50
|
exports.getDependentMap = getDependentMap;
|
|
51
51
|
/**
|
|
52
|
+
* @deprecated Do not use
|
|
53
|
+
*
|
|
52
54
|
* for a package graph of a->b->c (where b depends on a), transitive consumers of a are b & c and their consumers (or what are the consequences of a)
|
|
53
55
|
* @param targets
|
|
54
56
|
* @param packages
|
|
@@ -73,6 +75,8 @@ function getTransitiveConsumers(targets, packages, scope = []) {
|
|
|
73
75
|
}
|
|
74
76
|
exports.getTransitiveConsumers = getTransitiveConsumers;
|
|
75
77
|
/**
|
|
78
|
+
* @deprecated Do not use
|
|
79
|
+
*
|
|
76
80
|
* for a package graph of a->b->c (where b depends on a), transitive providers of c are a & b and their providers (or what is needed to satisfy c)
|
|
77
81
|
* @param targets
|
|
78
82
|
* @param packages
|
|
@@ -95,10 +99,11 @@ function getTransitiveProviders(targets, packages) {
|
|
|
95
99
|
return [...visited].filter((pkg) => !targets.includes(pkg));
|
|
96
100
|
}
|
|
97
101
|
exports.getTransitiveProviders = getTransitiveProviders;
|
|
98
|
-
|
|
102
|
+
/** @deprecated Do not use */
|
|
99
103
|
exports.getTransitiveDependencies = getTransitiveProviders;
|
|
100
|
-
|
|
104
|
+
/** @deprecated Do not use */
|
|
101
105
|
exports.getTransitiveDependents = getTransitiveConsumers;
|
|
106
|
+
/** @deprecated Do not use */
|
|
102
107
|
function getInternalDeps(info, packages) {
|
|
103
108
|
const deps = Object.keys(Object.assign(Object.assign({}, info.dependencies), info.devDependencies));
|
|
104
109
|
return Object.keys(packages).filter((pkg) => deps.includes(pkg));
|
package/lib/graph.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { PackageInfos } from "./types/PackageInfo";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import type { PackageInfos } from "./types/PackageInfo";
|
|
2
|
+
import type { PackageGraph } from "./types/PackageGraph";
|
|
3
|
+
export interface PackageGraphScope {
|
|
4
|
+
namePatterns?: string[];
|
|
5
|
+
includeDependencies?: boolean;
|
|
6
|
+
includeDependents?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function createPackageGraph(packages: PackageInfos, scope?: PackageGraphScope): PackageGraph;
|
package/lib/graph.js
CHANGED
|
@@ -1,27 +1,61 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
function
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
6
|
+
exports.createPackageGraph = void 0;
|
|
7
|
+
const createDependencyMap_1 = require("./createDependencyMap");
|
|
8
|
+
const multimatch_1 = __importDefault(require("multimatch"));
|
|
9
|
+
function createPackageGraph(packages, scope = {}) {
|
|
10
|
+
const dependencyMap = (0, createDependencyMap_1.createDependencyMap)(packages);
|
|
11
|
+
const packageSet = new Set();
|
|
10
12
|
const edges = [];
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
const visitor = (pkg, dependencies, dependents) => {
|
|
14
|
+
packageSet.add(pkg);
|
|
15
|
+
if (scope.includeDependencies && dependencies) {
|
|
16
|
+
for (const dep of dependencies) {
|
|
17
|
+
edges.push({ name: pkg, dependency: dep });
|
|
18
|
+
packageSet.add(dep);
|
|
19
|
+
}
|
|
15
20
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
if (scope.includeDependents && dependents) {
|
|
22
|
+
for (const dep of dependents) {
|
|
23
|
+
edges.push({ name: dep, dependency: pkg });
|
|
24
|
+
packageSet.add(dep);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
visitPackageGraph(packages, dependencyMap, visitor, scope);
|
|
29
|
+
return { packages: [...packageSet], dependencies: edges };
|
|
19
30
|
}
|
|
20
|
-
exports.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
31
|
+
exports.createPackageGraph = createPackageGraph;
|
|
32
|
+
function visitPackageGraph(packages, dependencyMap, visitor, scope) {
|
|
33
|
+
var _a, _b;
|
|
34
|
+
const visited = new Set();
|
|
35
|
+
const packageNames = Object.keys(packages);
|
|
36
|
+
const stack = scope && scope.namePatterns ? (0, multimatch_1.default)(packageNames, scope.namePatterns) : packageNames;
|
|
37
|
+
while (stack.length > 0) {
|
|
38
|
+
const pkg = stack.pop();
|
|
39
|
+
if (visited.has(pkg)) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const nextPkgs = [];
|
|
43
|
+
let dependencies = [];
|
|
44
|
+
let dependents = [];
|
|
45
|
+
if (scope === null || scope === void 0 ? void 0 : scope.includeDependencies) {
|
|
46
|
+
dependencies = [...(_a = dependencyMap.dependencies.get(pkg)) !== null && _a !== void 0 ? _a : []];
|
|
47
|
+
nextPkgs.push(...dependencies);
|
|
48
|
+
}
|
|
49
|
+
if (scope === null || scope === void 0 ? void 0 : scope.includeDependents) {
|
|
50
|
+
dependents = [...(_b = dependencyMap.dependents.get(pkg)) !== null && _b !== void 0 ? _b : []];
|
|
51
|
+
nextPkgs.push(...dependents);
|
|
52
|
+
}
|
|
53
|
+
visitor(pkg, dependencies, dependents);
|
|
54
|
+
visited.add(pkg);
|
|
55
|
+
if (nextPkgs.length > 0) {
|
|
56
|
+
for (const nextPkg of nextPkgs) {
|
|
57
|
+
stack.push(nextPkg);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
26
61
|
}
|
|
27
|
-
exports._resetGraphCache = _resetGraphCache;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** A package graph edge that defines a single package name and one of its dependency */
|
|
2
|
+
export interface PackageDependency {
|
|
3
|
+
name: string;
|
|
4
|
+
dependency: string;
|
|
5
|
+
}
|
|
6
|
+
/** The graph is defined by as a list of package names as nodes, and a list of PackageDependency as edges*/
|
|
7
|
+
export interface PackageGraph {
|
|
8
|
+
packages: string[];
|
|
9
|
+
dependencies: PackageDependency[];
|
|
10
|
+
}
|
|
11
|
+
/** Package graph visitor is called as it visits every package in dependency order */
|
|
12
|
+
export interface PackageGraphVisitor {
|
|
13
|
+
(pkg: string, dependencies: string[], dependents: string[]): void;
|
|
14
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "workspace-tools",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"@types/yarnpkg__lockfile": "^1.1.3",
|
|
39
39
|
"beachball": "^2.17.0",
|
|
40
40
|
"jest": "^25.0.0",
|
|
41
|
+
"prettier": "^2.7.1",
|
|
41
42
|
"tmp": "^0.2.1",
|
|
42
43
|
"ts-jest": "^25.5.1",
|
|
43
44
|
"typedoc": "^0.22.15",
|