@effected/cli 0.26.0 → 0.28.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/bin/effected.js +9 -2
- package/ci.js +16 -0
- package/commands/action/build.js +9 -0
- package/commands/action/errors.js +54 -0
- package/commands/action/execute-init.js +44 -0
- package/commands/action/execute.js +47 -0
- package/commands/action/flags.js +19 -0
- package/commands/action/index.js +9 -0
- package/commands/action/init.js +9 -0
- package/commands/package/build.js +9 -0
- package/commands/package/errors.js +38 -0
- package/commands/package/execute.js +52 -0
- package/commands/package/flags.js +12 -0
- package/commands/package/index.js +8 -0
- package/commands/root.js +11 -5
- package/commands/schema/LiveProgress.js +114 -0
- package/commands/schema/build.js +9 -0
- package/commands/schema/check.js +12 -0
- package/commands/schema/errors.js +121 -0
- package/commands/schema/execute.js +141 -0
- package/commands/schema/flags.js +24 -0
- package/commands/schema/index.js +14 -0
- package/commands/schema/validate.js +58 -0
- package/index.d.ts +231 -15
- package/index.js +5 -2
- package/main.d.ts +46 -1
- package/main.js +27 -8
- package/package.json +14 -7
- package/render/ActionDoc.js +66 -0
- package/render/DiffDoc.js +51 -0
- package/render/InitDoc.js +35 -0
- package/render/IssuesDoc.js +73 -0
- package/version.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effected/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "The effected command: the tool's command tree on the kit's front-end runtime",
|
|
6
6
|
"keywords": [
|
|
@@ -43,12 +43,19 @@
|
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@effect/platform-node": "~4.1.2",
|
|
46
|
-
"@effected/cli-kit": "^0.
|
|
47
|
-
"@effected/
|
|
48
|
-
"@effected/
|
|
49
|
-
"@effected/
|
|
50
|
-
"@effected/
|
|
51
|
-
"
|
|
46
|
+
"@effected/cli-kit": "^0.27.1",
|
|
47
|
+
"@effected/engine": "0.14.0",
|
|
48
|
+
"@effected/env": "^0.11.0",
|
|
49
|
+
"@effected/glob": "^0.20.0",
|
|
50
|
+
"@effected/kit": "^0.13.0",
|
|
51
|
+
"@effected/walker": "^0.26.0",
|
|
52
|
+
"effect": "~4.1.2",
|
|
53
|
+
"ink": "^8.0.0",
|
|
54
|
+
"react": "^19.3.0"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"@types/node": "^26.6.0",
|
|
58
|
+
"typescript": "7.1.0-beta || 7.1.1-rc || >=7.1.0 <8"
|
|
52
59
|
},
|
|
53
60
|
"engines": {
|
|
54
61
|
"node": ">=24.11.0"
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Doc } from "@effected/cli-kit";
|
|
2
|
+
|
|
3
|
+
// src/render/ActionDoc.ts
|
|
4
|
+
const formatBytes = (bytes) => {
|
|
5
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
6
|
+
return bytes < 1048576 ? `${(bytes / 1024).toFixed(1)} KB` : `${(bytes / 1048576).toFixed(1)} MB`;
|
|
7
|
+
};
|
|
8
|
+
const issueLine = (issue) => `${issue.code}: ${issue.message}`;
|
|
9
|
+
/** One line for an entry, with only the first line of its error: a failed load's message can carry a require stack. */
|
|
10
|
+
const entryLine = (entry) => {
|
|
11
|
+
if (entry.stats === void 0) return `✗ ${(entry.error ?? "failed").split("\n")[0]}`;
|
|
12
|
+
const { entry: name, size, duration, outputPath } = entry.stats;
|
|
13
|
+
return `✓ ${name}: ${formatBytes(size)} (${duration}ms) → ${outputPath}`;
|
|
14
|
+
};
|
|
15
|
+
const summaryOf = ({ build }) => `built ${build.entries.filter((entry) => entry.success).length} entries in ${build.duration}ms`;
|
|
16
|
+
/** A warning as its first line, indented under the entry it belongs to. */
|
|
17
|
+
const warningLines = (entry) => (entry.warnings ?? []).map((warning) => ` ${warning.trim().split("\n")[0]}`);
|
|
18
|
+
/**
|
|
19
|
+
* An action build for a reader: validation's errors, its warnings, a line per entry, then the total.
|
|
20
|
+
*
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
var ActionDoc = class ActionDoc {
|
|
24
|
+
constructor() {}
|
|
25
|
+
/** The report as plain lines, the total last, for a log. */
|
|
26
|
+
static lines(result) {
|
|
27
|
+
return [
|
|
28
|
+
...result.validation.errors.map(issueLine),
|
|
29
|
+
...result.validation.warnings.map(issueLine),
|
|
30
|
+
...result.build.entries.flatMap((entry) => [entryLine(entry), ...warningLines(entry)]),
|
|
31
|
+
summaryOf(result)
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The report as a `Doc`.
|
|
36
|
+
*
|
|
37
|
+
* @remarks
|
|
38
|
+
* Every line goes in as a `Doc.text` run, which is data: the renderers remove escape and control characters from it,
|
|
39
|
+
* so an error quoting untrusted text cannot repaint the terminal.
|
|
40
|
+
*/
|
|
41
|
+
static render(result) {
|
|
42
|
+
const rows = [
|
|
43
|
+
...result.validation.errors.map((issue) => Doc.text(issueLine(issue), "error")),
|
|
44
|
+
...result.validation.warnings.map((issue) => Doc.text(issueLine(issue), "warning")),
|
|
45
|
+
...result.build.entries.flatMap((entry) => [Doc.text(entryLine(entry), entry.success ? "success" : "error"), ...warningLines(entry).map((line) => Doc.text(line, "warning"))]),
|
|
46
|
+
Doc.text(summaryOf(result), result.build.success ? "success" : "error")
|
|
47
|
+
];
|
|
48
|
+
return Doc.lines(rows, { wrap: false });
|
|
49
|
+
}
|
|
50
|
+
/** The report for a GitHub step summary, in a code block. */
|
|
51
|
+
static markdown(result) {
|
|
52
|
+
const body = ActionDoc.lines(result).join("\n");
|
|
53
|
+
const longest = (body.match(/`+/g) ?? []).reduce((length, run) => Math.max(length, run.length), 2);
|
|
54
|
+
const fence = "`".repeat(longest + 1);
|
|
55
|
+
return [
|
|
56
|
+
"### effected action build",
|
|
57
|
+
"",
|
|
58
|
+
fence,
|
|
59
|
+
body,
|
|
60
|
+
fence,
|
|
61
|
+
""
|
|
62
|
+
].join("\n");
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export { ActionDoc };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Doc } from "@effected/cli-kit";
|
|
2
|
+
|
|
3
|
+
// src/render/DiffDoc.ts
|
|
4
|
+
/**
|
|
5
|
+
* How many diff rows `DiffDoc.render` shows per schema before it cuts the rest with a "… N more lines" tail: a
|
|
6
|
+
* screenful of context that keeps a many-schema report readable.
|
|
7
|
+
*
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULT_MAX_DIFF_LINES = 40;
|
|
11
|
+
const expandTabs = (text) => text.replaceAll(" ", " ");
|
|
12
|
+
/**
|
|
13
|
+
* A schema's line diff as a `Doc`, in git's shape: an `@@ path @@` header, context lines as they are, removes in the
|
|
14
|
+
* `error` token and adds in the `success` token.
|
|
15
|
+
*
|
|
16
|
+
* @remarks
|
|
17
|
+
* Each tab in a line's text is expanded to two spaces, so a tab-indented document keeps its shape. Every line's text
|
|
18
|
+
* goes into the document as a `Doc.text` run, which is data: the renderers remove escape and control characters from it
|
|
19
|
+
* and never read it as markup, so a diff of untrusted text cannot repaint the terminal.
|
|
20
|
+
* A document with more than one hunk separates them with a muted `@@ -a,b +c,d @@` range row. The cap counts every
|
|
21
|
+
* row after the header (diff lines, range rows and `` markers) and the tail names exactly
|
|
22
|
+
* how many were cut. Nothing here loads Ink or React.
|
|
23
|
+
*
|
|
24
|
+
* @public
|
|
25
|
+
*/
|
|
26
|
+
var DiffDoc = class {
|
|
27
|
+
constructor() {}
|
|
28
|
+
/**
|
|
29
|
+
* @param path - the schema file the diff is for, shown in the header
|
|
30
|
+
* @param diff - the diff
|
|
31
|
+
* @param options - `maxLines`, the cap on shown rows
|
|
32
|
+
*/
|
|
33
|
+
static render(path, diff, options) {
|
|
34
|
+
const cap = Math.max(0, Math.floor(options?.maxLines ?? 40));
|
|
35
|
+
const rows = [];
|
|
36
|
+
diff.hunks.forEach((hunk) => {
|
|
37
|
+
if (diff.hunks.length > 1) rows.push(Doc.text(`@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@`, "muted"));
|
|
38
|
+
for (const line of hunk.lines) {
|
|
39
|
+
const text = expandTabs(line.text);
|
|
40
|
+
rows.push(line.kind === "add" ? Doc.text(`+${text}`, "success") : line.kind === "remove" ? Doc.text(`-${text}`, "error") : Doc.text(` ${text}`));
|
|
41
|
+
if (line.noNewline === true) rows.push(Doc.text("\", "muted"));
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
const hidden = rows.length - cap;
|
|
45
|
+
const shown = hidden > 0 ? rows.slice(0, cap) : rows;
|
|
46
|
+
if (hidden > 0) shown.push(Doc.text(`… ${hidden} more ${hidden === 1 ? "line" : "lines"}`, "muted"));
|
|
47
|
+
return Doc.lines([Doc.text(`@@ ${path} @@`, "accent"), ...shown], { wrap: false });
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export { DiffDoc };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Doc } from "@effected/cli-kit";
|
|
2
|
+
|
|
3
|
+
// src/render/InitDoc.ts
|
|
4
|
+
/** What is left to do, as lines: the packages to add, the module type, and the build. */
|
|
5
|
+
const nextSteps = (result) => [
|
|
6
|
+
...result.missingDependencies.length > 0 ? [`add dependencies: ${result.missingDependencies.join(" ")}`] : [],
|
|
7
|
+
...result.missingDevDependencies.length > 0 ? [`add devDependencies: ${result.missingDevDependencies.join(" ")}`] : [],
|
|
8
|
+
...result.typeModule ? [] : ["set \"type\": \"module\" in package.json"],
|
|
9
|
+
"then run: effected action build"
|
|
10
|
+
];
|
|
11
|
+
const fileLine = (result, file) => `${result.overwritten.includes(file) ? "replaced" : "wrote"} ${file}`;
|
|
12
|
+
/**
|
|
13
|
+
* An `action init` for a reader: a line per file written, then what is left to do.
|
|
14
|
+
*
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
var InitDoc = class {
|
|
18
|
+
constructor() {}
|
|
19
|
+
/** The report as plain lines, for a log. */
|
|
20
|
+
static lines(result) {
|
|
21
|
+
return [...result.written.map((file) => fileLine(result, file)), ...nextSteps(result)];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The report as a `Doc`.
|
|
25
|
+
*
|
|
26
|
+
* @remarks
|
|
27
|
+
* Every line goes in as a `Doc.text` run, which is data, so a name echoed back cannot repaint the terminal.
|
|
28
|
+
*/
|
|
29
|
+
static render(result) {
|
|
30
|
+
const rows = [...result.written.map((file) => Doc.text(fileLine(result, file), result.overwritten.includes(file) ? "warning" : "success")), ...nextSteps(result).map((line) => Doc.text(line, "muted"))];
|
|
31
|
+
return Doc.lines(rows, { wrap: false });
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export { InitDoc };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Doc } from "@effected/cli-kit";
|
|
2
|
+
|
|
3
|
+
// src/render/IssuesDoc.ts
|
|
4
|
+
/** `file:line:col code text`, leaving out whichever parts the diagnostic does not have. */
|
|
5
|
+
const lineOf = (diagnostic) => {
|
|
6
|
+
return [
|
|
7
|
+
...diagnostic.file === void 0 ? [] : [[
|
|
8
|
+
diagnostic.file,
|
|
9
|
+
diagnostic.line,
|
|
10
|
+
diagnostic.column
|
|
11
|
+
].filter((part) => part !== void 0).join(":")],
|
|
12
|
+
...diagnostic.code !== void 0 ? [diagnostic.code] : [],
|
|
13
|
+
diagnostic.text
|
|
14
|
+
].join(" ");
|
|
15
|
+
};
|
|
16
|
+
const summaryOf = (issues) => `built ${issues.package}: ${issues.errors.length} errors, ${issues.warnings.length} warnings, ${issues.suppressed.length} suppressed`;
|
|
17
|
+
const summaryToken = (issues) => !issues.buildOk || issues.errors.length > 0 ? "error" : issues.warnings.length > 0 ? "warning" : "success";
|
|
18
|
+
const fenceFor = (text) => {
|
|
19
|
+
const longest = (text.match(/`+/g) ?? []).reduce((length, run) => Math.max(length, run.length), 2);
|
|
20
|
+
return "`".repeat(longest + 1);
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* A build's `issues.json` for a reader: errors, then warnings, then one summary line. Suppressed diagnostics are only
|
|
24
|
+
* counted.
|
|
25
|
+
*
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
var IssuesDoc = class {
|
|
29
|
+
constructor() {}
|
|
30
|
+
/** The report as plain lines, the summary last, for a log. */
|
|
31
|
+
static lines(issues) {
|
|
32
|
+
return [
|
|
33
|
+
...issues.errors.map(lineOf),
|
|
34
|
+
...issues.warnings.map(lineOf),
|
|
35
|
+
summaryOf(issues)
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The report as a `Doc`.
|
|
40
|
+
*
|
|
41
|
+
* @remarks
|
|
42
|
+
* Every line goes in as a `Doc.text` run, which is data: the renderers remove escape and control characters from it,
|
|
43
|
+
* so a diagnostic quoting untrusted text cannot repaint the terminal.
|
|
44
|
+
*/
|
|
45
|
+
static render(issues) {
|
|
46
|
+
const rows = [
|
|
47
|
+
...issues.errors.map((diagnostic) => Doc.text(lineOf(diagnostic), "error")),
|
|
48
|
+
...issues.warnings.map((diagnostic) => Doc.text(lineOf(diagnostic), "warning")),
|
|
49
|
+
Doc.text(summaryOf(issues), summaryToken(issues))
|
|
50
|
+
];
|
|
51
|
+
return Doc.lines(rows, { wrap: false });
|
|
52
|
+
}
|
|
53
|
+
/** The report for a GitHub step summary: the failure, when there is one, and the diagnostics in a code block. */
|
|
54
|
+
static markdown(issues) {
|
|
55
|
+
const diagnostics = [...issues.errors, ...issues.warnings].map(lineOf).join("\n");
|
|
56
|
+
const fence = fenceFor(diagnostics);
|
|
57
|
+
return [
|
|
58
|
+
"### effected package build",
|
|
59
|
+
"",
|
|
60
|
+
summaryOf(issues),
|
|
61
|
+
...issues.failure !== void 0 ? ["", `Failed: ${issues.failure.message}`] : [],
|
|
62
|
+
...diagnostics !== "" ? [
|
|
63
|
+
"",
|
|
64
|
+
fence,
|
|
65
|
+
diagnostics,
|
|
66
|
+
fence
|
|
67
|
+
] : [],
|
|
68
|
+
""
|
|
69
|
+
].join("\n");
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export { IssuesDoc };
|