@matter/tools 0.12.4-alpha.0-20250211-56b2c53a0 → 0.12.4-alpha.0-20250213-1187f81eb
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/cjs/building/builder.js +2 -2
- package/dist/cjs/building/builder.js.map +1 -1
- package/dist/cjs/building/cli.d.ts.map +1 -1
- package/dist/cjs/building/cli.js +88 -10
- package/dist/cjs/building/cli.js.map +2 -2
- package/dist/cjs/building/cycles.d.ts +9 -0
- package/dist/cjs/building/cycles.d.ts.map +1 -0
- package/dist/cjs/building/cycles.js +124 -0
- package/dist/cjs/building/cycles.js.map +6 -0
- package/dist/cjs/building/graph.js +1 -1
- package/dist/cjs/building/graph.js.map +1 -1
- package/dist/cjs/building/project-builder.js +2 -2
- package/dist/cjs/building/project-builder.js.map +1 -1
- package/dist/cjs/util/bootstrap.mjs +8 -1
- package/dist/cjs/util/import-aliases.d.ts +14 -0
- package/dist/cjs/util/import-aliases.d.ts.map +1 -0
- package/dist/cjs/util/import-aliases.js +82 -0
- package/dist/cjs/util/import-aliases.js.map +6 -0
- package/dist/cjs/util/package.d.ts +2 -1
- package/dist/cjs/util/package.d.ts.map +1 -1
- package/dist/cjs/util/package.js +15 -10
- package/dist/cjs/util/package.js.map +1 -1
- package/dist/cjs/util/progress.d.ts +2 -1
- package/dist/cjs/util/progress.d.ts.map +1 -1
- package/dist/cjs/util/progress.js +4 -1
- package/dist/cjs/util/progress.js.map +1 -1
- package/dist/cjs/versioning/cli.js +1 -1
- package/dist/cjs/versioning/cli.js.map +1 -1
- package/dist/esm/building/builder.js +3 -3
- package/dist/esm/building/builder.js.map +1 -1
- package/dist/esm/building/cli.d.ts.map +1 -1
- package/dist/esm/building/cli.js +89 -11
- package/dist/esm/building/cli.js.map +2 -2
- package/dist/esm/building/cycles.d.ts +9 -0
- package/dist/esm/building/cycles.d.ts.map +1 -0
- package/dist/esm/building/cycles.js +94 -0
- package/dist/esm/building/cycles.js.map +6 -0
- package/dist/esm/building/graph.js +2 -2
- package/dist/esm/building/graph.js.map +1 -1
- package/dist/esm/building/project-builder.js +3 -3
- package/dist/esm/building/project-builder.js.map +1 -1
- package/dist/esm/util/bootstrap.mjs +8 -1
- package/dist/esm/util/import-aliases.d.ts +14 -0
- package/dist/esm/util/import-aliases.d.ts.map +1 -0
- package/dist/esm/util/import-aliases.js +62 -0
- package/dist/esm/util/import-aliases.js.map +6 -0
- package/dist/esm/util/package.d.ts +2 -1
- package/dist/esm/util/package.d.ts.map +1 -1
- package/dist/esm/util/package.js +16 -11
- package/dist/esm/util/package.js.map +1 -1
- package/dist/esm/util/progress.d.ts +2 -1
- package/dist/esm/util/progress.d.ts.map +1 -1
- package/dist/esm/util/progress.js +5 -2
- package/dist/esm/util/progress.js.map +1 -1
- package/dist/esm/versioning/cli.js +2 -2
- package/dist/esm/versioning/cli.js.map +1 -1
- package/package.json +6 -4
- package/src/building/builder.ts +2 -2
- package/src/building/cli.ts +25 -1
- package/src/building/cycles.ts +108 -0
- package/src/building/graph.ts +1 -1
- package/src/building/project-builder.ts +2 -2
- package/src/util/bootstrap.mjs +8 -1
- package/src/util/import-aliases.ts +79 -0
- package/src/util/package.ts +15 -10
- package/src/util/progress.ts +5 -1
- package/src/versioning/cli.ts +1 -1
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Project CHIP Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { readFile } from "fs/promises";
|
|
8
|
+
import { Package } from "../util/package.js";
|
|
9
|
+
import { Progress } from "../util/progress.js";
|
|
10
|
+
|
|
11
|
+
// @ts-expect-error we don't have types for detective-typescript
|
|
12
|
+
import detective from "detective-typescript";
|
|
13
|
+
import { dirname, relative, resolve } from "path";
|
|
14
|
+
import { std } from "../ansi-text/std.js";
|
|
15
|
+
import { ansi } from "../ansi-text/text-builder.js";
|
|
16
|
+
|
|
17
|
+
export async function reportCycles(pkg: Package, progress: Progress) {
|
|
18
|
+
const cycles = await progress.run(pkg.name, () => identifyCycles(pkg, progress));
|
|
19
|
+
if (cycles) {
|
|
20
|
+
printCycles(pkg, cycles);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function identifyCycles(pkg: Package, progress: Progress) {
|
|
25
|
+
const deps = {} as Record<string, string[]>;
|
|
26
|
+
for (const filename of await pkg.glob("{src,test}/**/*.ts")) {
|
|
27
|
+
const contents = await readFile(filename, "utf-8");
|
|
28
|
+
const fileDeps = detective(contents, {
|
|
29
|
+
skipTypeImports: true,
|
|
30
|
+
skipAsyncImports: true,
|
|
31
|
+
});
|
|
32
|
+
deps[filename] = resolveDeps(pkg, filename, fileDeps);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const cycles = [] as string[][];
|
|
36
|
+
for (const filename in deps) {
|
|
37
|
+
visit(filename, []);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function visit(filename: string, breadcrumb: string[]) {
|
|
41
|
+
progress.refresh();
|
|
42
|
+
const fileDeps = deps[filename] ?? deps[filename.replace(/\.js$/, ".ts")];
|
|
43
|
+
if (fileDeps === undefined) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const previousIndex = breadcrumb.indexOf(filename);
|
|
48
|
+
if (previousIndex !== -1) {
|
|
49
|
+
const newCycle = breadcrumb.slice(previousIndex);
|
|
50
|
+
for (const cycle of cycles) {
|
|
51
|
+
const filenameOffset = cycle.indexOf(filename);
|
|
52
|
+
if (cycle.length !== newCycle.length) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (filenameOffset === -1) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let i = 0;
|
|
60
|
+
for (i = 0; i < newCycle.length; i++) {
|
|
61
|
+
if (newCycle[i] !== cycle[(filenameOffset + i) % newCycle.length]) {
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (i === newCycle.length) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
cycles.push(newCycle);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
breadcrumb = [...breadcrumb, filename];
|
|
75
|
+
for (const dep of fileDeps) {
|
|
76
|
+
visit(dep, breadcrumb);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return cycles.length ? cycles : undefined;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function printCycles(pkg: Package, cycles: string[][]) {
|
|
84
|
+
std.out(ansi.red("Cycles detected:"), "\n");
|
|
85
|
+
const src = pkg.resolve("src");
|
|
86
|
+
for (const cycle of cycles) {
|
|
87
|
+
std.out(" ", cycle.map(name => ansi.bright.blue(relative(src, name))).join(" → "), " ↩\n");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function resolveDeps(pkg: Package, sourceFilename: string, deps: string[]) {
|
|
92
|
+
const dir = dirname(sourceFilename);
|
|
93
|
+
const aliases = pkg.importAliases;
|
|
94
|
+
const resolved = Array<string>();
|
|
95
|
+
|
|
96
|
+
for (let dep of deps) {
|
|
97
|
+
let base = dir;
|
|
98
|
+
if (dep.startsWith("#")) {
|
|
99
|
+
dep = aliases.rewrite(dep);
|
|
100
|
+
base = pkg.path;
|
|
101
|
+
}
|
|
102
|
+
if (dep.startsWith("./")) {
|
|
103
|
+
resolved.push(resolve(base, dep));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return resolved;
|
|
108
|
+
}
|
package/src/building/graph.ts
CHANGED
|
@@ -134,7 +134,7 @@ export class Graph {
|
|
|
134
134
|
progress.info("built", formatTime(node.info.timestamp ?? 0));
|
|
135
135
|
progress.info("dirty", node.isDirty ? colors.dim.red("yes") : colors.dim.green("no"));
|
|
136
136
|
progress.info("dependencies", node.dependencies.map(formatDep).join(", "));
|
|
137
|
-
progress.
|
|
137
|
+
progress.close();
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
|
|
@@ -67,12 +67,12 @@ export class ProjectBuilder {
|
|
|
67
67
|
try {
|
|
68
68
|
await this.#doBuild(project, progress);
|
|
69
69
|
} catch (e: any) {
|
|
70
|
-
progress.
|
|
70
|
+
progress.close();
|
|
71
71
|
process.stderr.write(`${e.stack ?? e.message}\n\n`);
|
|
72
72
|
process.exit(1);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
progress.
|
|
75
|
+
progress.close();
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
async #doBuild(project: Project, progress: Progress) {
|
package/src/util/bootstrap.mjs
CHANGED
|
@@ -73,7 +73,14 @@ async function bootstrap() {
|
|
|
73
73
|
await new Promise(resolve => {
|
|
74
74
|
const proc = spawn(
|
|
75
75
|
esbuild,
|
|
76
|
-
[
|
|
76
|
+
[
|
|
77
|
+
"src/**/*.ts",
|
|
78
|
+
"--outdir=dist/esm",
|
|
79
|
+
"--format=esm",
|
|
80
|
+
"--log-level=warning",
|
|
81
|
+
"--sourcemap=inline",
|
|
82
|
+
"--target=es2022",
|
|
83
|
+
],
|
|
77
84
|
options,
|
|
78
85
|
);
|
|
79
86
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Project CHIP Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Parses package.json "imports" fields and rewrites local imports according to the import definitions.
|
|
9
|
+
*/
|
|
10
|
+
export class ImportAliases {
|
|
11
|
+
#parent?: ImportAliases;
|
|
12
|
+
#direct: Record<string, string> = {};
|
|
13
|
+
#wildcard = Array<WildcardAlias>();
|
|
14
|
+
|
|
15
|
+
constructor(localAliases?: Record<string, string>, parent?: ImportAliases) {
|
|
16
|
+
for (const path in localAliases) {
|
|
17
|
+
const resolvesTo = localAliases[path];
|
|
18
|
+
|
|
19
|
+
let wildcardAt = path.indexOf("*");
|
|
20
|
+
if (wildcardAt === -1) {
|
|
21
|
+
this.#direct[path] = resolvesTo;
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const inputPrefix = path.substring(0, wildcardAt);
|
|
26
|
+
const inputSuffix = path.substring(wildcardAt + 1);
|
|
27
|
+
|
|
28
|
+
wildcardAt = resolvesTo.indexOf("*");
|
|
29
|
+
if (wildcardAt === -1) {
|
|
30
|
+
this.#wildcard.push({
|
|
31
|
+
inputPrefix,
|
|
32
|
+
inputSuffix,
|
|
33
|
+
includeGlob: false,
|
|
34
|
+
outputPrefix: resolvesTo,
|
|
35
|
+
outputSuffix: "",
|
|
36
|
+
});
|
|
37
|
+
} else {
|
|
38
|
+
this.#wildcard.push({
|
|
39
|
+
inputPrefix,
|
|
40
|
+
inputSuffix,
|
|
41
|
+
includeGlob: true,
|
|
42
|
+
outputPrefix: resolvesTo.substring(0, wildcardAt),
|
|
43
|
+
outputSuffix: resolvesTo.substring(wildcardAt + 1),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
this.#parent = parent;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
rewrite(path: string): string {
|
|
51
|
+
if (path.startsWith("#")) {
|
|
52
|
+
const direct = this.#direct[path];
|
|
53
|
+
if (direct) {
|
|
54
|
+
return direct;
|
|
55
|
+
}
|
|
56
|
+
for (const alias of this.#wildcard) {
|
|
57
|
+
if (path.startsWith(alias.inputPrefix) && path.endsWith(alias.inputSuffix)) {
|
|
58
|
+
if (alias.includeGlob) {
|
|
59
|
+
return (
|
|
60
|
+
alias.outputPrefix +
|
|
61
|
+
path.substring(alias.inputPrefix.length, path.length - alias.inputSuffix.length) +
|
|
62
|
+
alias.outputSuffix
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
return alias.outputPrefix;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return this.#parent?.rewrite(path) ?? path;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface WildcardAlias {
|
|
74
|
+
inputPrefix: string;
|
|
75
|
+
inputSuffix: string;
|
|
76
|
+
includeGlob: boolean;
|
|
77
|
+
outputPrefix: string;
|
|
78
|
+
outputSuffix: string;
|
|
79
|
+
}
|
package/src/util/package.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { dirname, join, relative, resolve } from "path";
|
|
|
10
10
|
import { ignoreError, ignoreErrorSync } from "./errors.js";
|
|
11
11
|
import { isFile, maybeReadJsonSync, maybeStatSync } from "./file.js";
|
|
12
12
|
import { globSync } from "./glob.js";
|
|
13
|
+
import { ImportAliases } from "./import-aliases.js";
|
|
13
14
|
import { Progress } from "./progress.js";
|
|
14
15
|
import { toolsPath } from "./tools-path.cjs";
|
|
15
16
|
|
|
@@ -53,7 +54,7 @@ export class Package {
|
|
|
53
54
|
hasTests: boolean;
|
|
54
55
|
hasConfig: boolean;
|
|
55
56
|
isLibrary: boolean;
|
|
56
|
-
#
|
|
57
|
+
#importAliases?: ImportAliases;
|
|
57
58
|
|
|
58
59
|
constructor({
|
|
59
60
|
path = ".",
|
|
@@ -314,7 +315,11 @@ export class Package {
|
|
|
314
315
|
if (existsSync(join(path, "package.json"))) {
|
|
315
316
|
result = new Package({ path });
|
|
316
317
|
} else {
|
|
317
|
-
|
|
318
|
+
const parentDir = dirname(path);
|
|
319
|
+
if (parentDir === path) {
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
result = find(parentDir);
|
|
318
323
|
}
|
|
319
324
|
packageForPath[path] = result;
|
|
320
325
|
}
|
|
@@ -334,17 +339,17 @@ export class Package {
|
|
|
334
339
|
throw new Error(`Cannot find package.json for "${path}"`);
|
|
335
340
|
}
|
|
336
341
|
|
|
337
|
-
get
|
|
338
|
-
if (this.#
|
|
339
|
-
return this.#
|
|
342
|
+
get importAliases(): ImportAliases {
|
|
343
|
+
if (this.#importAliases !== undefined) {
|
|
344
|
+
return this.#importAliases;
|
|
340
345
|
}
|
|
341
346
|
|
|
342
|
-
this.#
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
347
|
+
this.#importAliases = new ImportAliases(
|
|
348
|
+
this.json.imports,
|
|
349
|
+
Package.maybeForPath(dirname(this.path))?.importAliases,
|
|
350
|
+
);
|
|
346
351
|
|
|
347
|
-
return this.#
|
|
352
|
+
return this.#importAliases;
|
|
348
353
|
}
|
|
349
354
|
|
|
350
355
|
get modules() {
|
package/src/util/progress.ts
CHANGED
|
@@ -155,7 +155,7 @@ export class Progress {
|
|
|
155
155
|
std.out.write(` ${ansi.yellow("Warning:")} ${text}\n`);
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
|
|
158
|
+
close() {
|
|
159
159
|
if (this.#refreshInterval) {
|
|
160
160
|
clearInterval(this.#refreshInterval);
|
|
161
161
|
this.#refreshInterval = undefined;
|
|
@@ -163,6 +163,10 @@ export class Progress {
|
|
|
163
163
|
writeStatus("");
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
+
[Symbol.dispose]() {
|
|
167
|
+
this.close();
|
|
168
|
+
}
|
|
169
|
+
|
|
166
170
|
refresh() {
|
|
167
171
|
if (this.#updateSpinner()) {
|
|
168
172
|
this.#writeOngoing();
|
package/src/versioning/cli.ts
CHANGED