@levr-one/cli 0.12.2 → 0.12.4
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/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { COMPLETION_SHELLS } from "./completionHandler-O2G_WZLf.js";
|
|
3
|
-
import { gatesInspectCommand } from "./inspect-
|
|
3
|
+
import { gatesInspectCommand } from "./inspect-BbL7kDe-.js";
|
|
4
4
|
import { buildApplication, buildCommand, buildRouteMap, proposeCompletions, run, text_en } from "@stricli/core";
|
|
5
5
|
import chalk from "chalk";
|
|
6
6
|
import { existsSync, readFileSync } from "node:fs";
|
|
@@ -718,7 +718,7 @@ Examples:
|
|
|
718
718
|
}
|
|
719
719
|
},
|
|
720
720
|
loader: async () => {
|
|
721
|
-
const { gatesRunHandler } = await import("./runHandler-
|
|
721
|
+
const { gatesRunHandler } = await import("./runHandler-IyPhhiGs.js");
|
|
722
722
|
return gatesRunHandler;
|
|
723
723
|
}
|
|
724
724
|
});
|
|
@@ -914,7 +914,7 @@ Examples:
|
|
|
914
914
|
|
|
915
915
|
//#endregion
|
|
916
916
|
//#region package.json
|
|
917
|
-
var version = "0.12.
|
|
917
|
+
var version = "0.12.4";
|
|
918
918
|
|
|
919
919
|
//#endregion
|
|
920
920
|
//#region src/app.ts
|
|
@@ -3,6 +3,103 @@ import { z } from "zod";
|
|
|
3
3
|
import * as fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
|
|
6
|
+
//#region ../shared/dist/runs/gate-pattern.js
|
|
7
|
+
/**
|
|
8
|
+
* POSIX ERE → JS `RegExp` translation for gate patterns (ENG-7246).
|
|
9
|
+
*
|
|
10
|
+
* Moved from the CLI's `gates inspect` builtins so the server and the seed
|
|
11
|
+
* specs read a pattern with the same parser the CLI runs: a pattern the CLI
|
|
12
|
+
* refuses is caught before it ships, not when a gate is verified.
|
|
13
|
+
*/
|
|
14
|
+
const POSIX_CLASSES = {
|
|
15
|
+
alpha: "A-Za-z",
|
|
16
|
+
digit: "0-9",
|
|
17
|
+
alnum: "A-Za-z0-9",
|
|
18
|
+
upper: "A-Z",
|
|
19
|
+
lower: "a-z",
|
|
20
|
+
space: " \\t\\n\\r\\f\\v",
|
|
21
|
+
blank: " \\t",
|
|
22
|
+
punct: "!-\\/:-@\\[-`{-~",
|
|
23
|
+
xdigit: "0-9A-Fa-f",
|
|
24
|
+
cntrl: "\\x00-\\x1f\\x7f",
|
|
25
|
+
print: "\\x20-\\x7e",
|
|
26
|
+
graph: "\\x21-\\x7e",
|
|
27
|
+
word: "A-Za-z0-9_"
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Translate a POSIX ERE (what `grep -E` read) into a JS `RegExp` source.
|
|
31
|
+
*
|
|
32
|
+
* Bracket classes become their JS ranges. Syntax that `grep` and JS read
|
|
33
|
+
* differently, and that has no faithful translation, is refused with a
|
|
34
|
+
* reason: GNU word anchors `\<` `\>`, buffer anchors, collating and
|
|
35
|
+
* equivalence classes, a backslash inside a bracket expression (literal to
|
|
36
|
+
* grep, an escape to JS), and a back-reference to a group that does not
|
|
37
|
+
* exist (an octal escape to JS). Refusing is the point: a `not_contains`
|
|
38
|
+
* whose pattern silently stopped matching is a false pass.
|
|
39
|
+
*/
|
|
40
|
+
function translatePosixEre(pattern) {
|
|
41
|
+
let out = "";
|
|
42
|
+
let groups = 0;
|
|
43
|
+
for (let i = 0; i < pattern.length; i++) if (pattern[i] === "\\") i += 1;
|
|
44
|
+
else if (pattern[i] === "(" && pattern[i + 1] !== "?") groups += 1;
|
|
45
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
46
|
+
const ch = pattern[i] ?? "";
|
|
47
|
+
if (ch === "\\") {
|
|
48
|
+
const next = pattern[i + 1];
|
|
49
|
+
if (next === void 0) return { error: "pattern ends with a backslash" };
|
|
50
|
+
if (next === "<" || next === ">") return { error: `\\${next} is a GNU word anchor with no JS equivalent; use \\b` };
|
|
51
|
+
if (next === "`" || next === "'") return { error: `\\${next} is a GNU buffer anchor; use ^ or $` };
|
|
52
|
+
if (/[1-9]/.test(next) && Number(next) > groups) return { error: `back-reference \\${next} names a group the pattern does not have` };
|
|
53
|
+
out += ch + next;
|
|
54
|
+
i += 1;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (ch !== "[") {
|
|
58
|
+
out += ch;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
let j = i + 1;
|
|
62
|
+
let body = "";
|
|
63
|
+
if (pattern[j] === "^") {
|
|
64
|
+
body += "^";
|
|
65
|
+
j += 1;
|
|
66
|
+
}
|
|
67
|
+
if (pattern[j] === "]") {
|
|
68
|
+
body += "\\]";
|
|
69
|
+
j += 1;
|
|
70
|
+
}
|
|
71
|
+
let closed = false;
|
|
72
|
+
while (j < pattern.length) {
|
|
73
|
+
const c = pattern[j] ?? "";
|
|
74
|
+
if (c === "]") {
|
|
75
|
+
closed = true;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
if (c === "[" && (pattern[j + 1] === ":" || pattern[j + 1] === "=" || pattern[j + 1] === ".")) {
|
|
79
|
+
const kind = pattern[j + 1];
|
|
80
|
+
const end = pattern.indexOf(`${kind}]`, j + 2);
|
|
81
|
+
if (end === -1) return { error: `unterminated [${kind} in a bracket expression` };
|
|
82
|
+
const name = pattern.slice(j + 2, end);
|
|
83
|
+
if (kind !== ":") return { error: `[${kind}${name}${kind}] has no JS equivalent` };
|
|
84
|
+
const range = POSIX_CLASSES[name];
|
|
85
|
+
if (range === void 0) return { error: `unknown class [:${name}:]` };
|
|
86
|
+
body += range;
|
|
87
|
+
j = end + 2;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (c === "\\") return { error: "a backslash inside [...] is literal to grep and an escape to JS; use a POSIX class or move it outside the brackets" };
|
|
91
|
+
if (c === "[") body += "\\[";
|
|
92
|
+
else body += c;
|
|
93
|
+
j += 1;
|
|
94
|
+
}
|
|
95
|
+
if (!closed) return { error: "unterminated bracket expression" };
|
|
96
|
+
out += `[${body}]`;
|
|
97
|
+
i = j;
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
//#endregion
|
|
6
103
|
//#region ../shared/dist/runs/gate-op.js
|
|
7
104
|
const GATE_OP_CONTRACT_VERSION = 1;
|
|
8
105
|
const REPO_RELATIVE = "path must be repo-relative and must not contain ..";
|
|
@@ -778,93 +875,6 @@ function readText(root, rel) {
|
|
|
778
875
|
function escapeRegExp(value) {
|
|
779
876
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
780
877
|
}
|
|
781
|
-
const POSIX_CLASSES = {
|
|
782
|
-
alpha: "A-Za-z",
|
|
783
|
-
digit: "0-9",
|
|
784
|
-
alnum: "A-Za-z0-9",
|
|
785
|
-
upper: "A-Z",
|
|
786
|
-
lower: "a-z",
|
|
787
|
-
space: " \\t\\n\\r\\f\\v",
|
|
788
|
-
blank: " \\t",
|
|
789
|
-
punct: "!-\\/:-@\\[-`{-~",
|
|
790
|
-
xdigit: "0-9A-Fa-f",
|
|
791
|
-
cntrl: "\\x00-\\x1f\\x7f",
|
|
792
|
-
print: "\\x20-\\x7e",
|
|
793
|
-
graph: "\\x21-\\x7e",
|
|
794
|
-
word: "A-Za-z0-9_"
|
|
795
|
-
};
|
|
796
|
-
/**
|
|
797
|
-
* Translate a POSIX ERE (what `grep -E` read) into a JS `RegExp` source.
|
|
798
|
-
*
|
|
799
|
-
* Bracket classes become their JS ranges. Syntax that `grep` and JS read
|
|
800
|
-
* differently, and that has no faithful translation, is refused with a
|
|
801
|
-
* reason: GNU word anchors `\<` `\>`, buffer anchors, collating and
|
|
802
|
-
* equivalence classes, a backslash inside a bracket expression (literal to
|
|
803
|
-
* grep, an escape to JS), and a back-reference to a group that does not
|
|
804
|
-
* exist (an octal escape to JS). Refusing is the point: a `not_contains`
|
|
805
|
-
* whose pattern silently stopped matching is a false pass.
|
|
806
|
-
*/
|
|
807
|
-
function translatePosixEre(pattern) {
|
|
808
|
-
let out = "";
|
|
809
|
-
let groups = 0;
|
|
810
|
-
for (let i = 0; i < pattern.length; i++) if (pattern[i] === "\\") i += 1;
|
|
811
|
-
else if (pattern[i] === "(" && pattern[i + 1] !== "?") groups += 1;
|
|
812
|
-
for (let i = 0; i < pattern.length; i++) {
|
|
813
|
-
const ch = pattern[i] ?? "";
|
|
814
|
-
if (ch === "\\") {
|
|
815
|
-
const next = pattern[i + 1];
|
|
816
|
-
if (next === void 0) return { error: "pattern ends with a backslash" };
|
|
817
|
-
if (next === "<" || next === ">") return { error: `\\${next} is a GNU word anchor with no JS equivalent; use \\b` };
|
|
818
|
-
if (next === "`" || next === "'") return { error: `\\${next} is a GNU buffer anchor; use ^ or $` };
|
|
819
|
-
if (/[1-9]/.test(next) && Number(next) > groups) return { error: `back-reference \\${next} names a group the pattern does not have` };
|
|
820
|
-
out += ch + next;
|
|
821
|
-
i += 1;
|
|
822
|
-
continue;
|
|
823
|
-
}
|
|
824
|
-
if (ch !== "[") {
|
|
825
|
-
out += ch;
|
|
826
|
-
continue;
|
|
827
|
-
}
|
|
828
|
-
let j = i + 1;
|
|
829
|
-
let body = "";
|
|
830
|
-
if (pattern[j] === "^") {
|
|
831
|
-
body += "^";
|
|
832
|
-
j += 1;
|
|
833
|
-
}
|
|
834
|
-
if (pattern[j] === "]") {
|
|
835
|
-
body += "\\]";
|
|
836
|
-
j += 1;
|
|
837
|
-
}
|
|
838
|
-
let closed = false;
|
|
839
|
-
while (j < pattern.length) {
|
|
840
|
-
const c = pattern[j] ?? "";
|
|
841
|
-
if (c === "]") {
|
|
842
|
-
closed = true;
|
|
843
|
-
break;
|
|
844
|
-
}
|
|
845
|
-
if (c === "[" && (pattern[j + 1] === ":" || pattern[j + 1] === "=" || pattern[j + 1] === ".")) {
|
|
846
|
-
const kind = pattern[j + 1];
|
|
847
|
-
const end = pattern.indexOf(`${kind}]`, j + 2);
|
|
848
|
-
if (end === -1) return { error: `unterminated [${kind} in a bracket expression` };
|
|
849
|
-
const name = pattern.slice(j + 2, end);
|
|
850
|
-
if (kind !== ":") return { error: `[${kind}${name}${kind}] has no JS equivalent` };
|
|
851
|
-
const range = POSIX_CLASSES[name];
|
|
852
|
-
if (range === void 0) return { error: `unknown class [:${name}:]` };
|
|
853
|
-
body += range;
|
|
854
|
-
j = end + 2;
|
|
855
|
-
continue;
|
|
856
|
-
}
|
|
857
|
-
if (c === "\\") return { error: "a backslash inside [...] is literal to grep and an escape to JS; use a POSIX class or move it outside the brackets" };
|
|
858
|
-
if (c === "[") body += "\\[";
|
|
859
|
-
else body += c;
|
|
860
|
-
j += 1;
|
|
861
|
-
}
|
|
862
|
-
if (!closed) return { error: "unterminated bracket expression" };
|
|
863
|
-
out += `[${body}]`;
|
|
864
|
-
i = j;
|
|
865
|
-
}
|
|
866
|
-
return out;
|
|
867
|
-
}
|
|
868
878
|
function compilePattern(source, flags) {
|
|
869
879
|
const translated = translatePosixEre(source);
|
|
870
880
|
if (typeof translated !== "string") return finish(2, `ERROR: unsupported pattern: ${translated.error}`);
|
|
@@ -884,9 +894,17 @@ function matcherFor(params, insensitive) {
|
|
|
884
894
|
}
|
|
885
895
|
return finish(1, "ERROR: pattern or keywords is required");
|
|
886
896
|
}
|
|
897
|
+
/**
|
|
898
|
+
* Lines as `grep -c` counts them (ENG-7271): a final newline ENDS the last
|
|
899
|
+
* line, it does not start an empty one. `split('\n')` yields that phantom
|
|
900
|
+
* empty element, which a `^$`-style pattern matched, so the CLI counted one
|
|
901
|
+
* more than grep on every newline-terminated file.
|
|
902
|
+
*/
|
|
887
903
|
function countLines(text, re) {
|
|
904
|
+
const lines = text.split("\n");
|
|
905
|
+
if (lines[lines.length - 1] === "") lines.pop();
|
|
888
906
|
let count = 0;
|
|
889
|
-
for (const line of
|
|
907
|
+
for (const line of lines) if (re.test(line)) count += 1;
|
|
890
908
|
return count;
|
|
891
909
|
}
|
|
892
910
|
const MAX_WALK_FILES = 1e5;
|
|
@@ -1113,7 +1131,7 @@ Examples:
|
|
|
1113
1131
|
flags: {}
|
|
1114
1132
|
},
|
|
1115
1133
|
loader: async () => {
|
|
1116
|
-
const { gatesInspectHandler: handler } = await import("./inspect-
|
|
1134
|
+
const { gatesInspectHandler: handler } = await import("./inspect-EGW-cgVD.js");
|
|
1117
1135
|
return handler;
|
|
1118
1136
|
}
|
|
1119
1137
|
});
|