@intentius/chant 0.124.45 → 0.124.46
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/capabilities/aws.paths +148 -0
- package/dist/capabilities/base-mappings.json +122 -0
- package/dist/capabilities/catalog.d.ts +89 -0
- package/dist/capabilities/catalog.d.ts.map +1 -0
- package/dist/capabilities/catalog.js +204 -0
- package/dist/capabilities/language.d.ts +103 -0
- package/dist/capabilities/language.d.ts.map +1 -0
- package/dist/capabilities/language.js +335 -0
- package/dist/capabilities/matcher.d.ts +65 -0
- package/dist/capabilities/matcher.d.ts.map +1 -0
- package/dist/capabilities/matcher.js +299 -0
- package/dist/capabilities/view.d.ts +207 -0
- package/dist/capabilities/view.d.ts.map +1 -0
- package/dist/capabilities/view.js +484 -0
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/lint.js +1 -0
- package/dist/cli/handlers/declared-graph.d.ts +44 -0
- package/dist/cli/handlers/declared-graph.d.ts.map +1 -0
- package/dist/cli/handlers/declared-graph.js +87 -0
- package/dist/cli/handlers/graph.d.ts +25 -0
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/graph.js +93 -87
- package/dist/cli/handlers/pr-env.d.ts.map +1 -1
- package/dist/cli/handlers/pr-env.js +2 -1
- package/dist/cli/handlers/search-count.d.ts +89 -0
- package/dist/cli/handlers/search-count.d.ts.map +1 -0
- package/dist/cli/handlers/search-count.js +132 -0
- package/dist/cli/handlers/search.d.ts +358 -6
- package/dist/cli/handlers/search.d.ts.map +1 -1
- package/dist/cli/handlers/search.js +1065 -155
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +23 -3
- package/dist/cli/mcp/server.d.ts.map +1 -1
- package/dist/cli/mcp/server.js +3 -0
- package/dist/cli/mcp/tools/capabilities.d.ts +7 -0
- package/dist/cli/mcp/tools/capabilities.d.ts.map +1 -0
- package/dist/cli/mcp/tools/capabilities.js +27 -0
- package/dist/cli/mcp/workspace-tools.d.ts +3 -1
- package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
- package/dist/cli/mcp/workspace-tools.js +47 -2
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +64 -17
- package/dist/cli/registry.d.ts +22 -0
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/components/pr-env-ports.d.ts +29 -0
- package/dist/components/pr-env-ports.d.ts.map +1 -0
- package/dist/components/pr-env-ports.js +77 -0
- package/dist/components/pr-env-run.d.ts +5 -21
- package/dist/components/pr-env-run.d.ts.map +1 -1
- package/dist/components/pr-env-run.js +6 -70
- package/dist/components/pr-environment.d.ts +2 -1
- package/dist/components/pr-environment.d.ts.map +1 -1
- package/dist/components/pr-environment.js +1 -1
- package/dist/config-environments.d.ts +92 -0
- package/dist/config-environments.d.ts.map +1 -0
- package/dist/config-environments.js +102 -0
- package/dist/config.d.ts +24 -84
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +9 -96
- package/dist/graph-detail.d.ts.map +1 -1
- package/dist/graph-detail.js +15 -3
- package/dist/graph-effective.d.ts +33 -2
- package/dist/graph-effective.d.ts.map +1 -1
- package/dist/graph-effective.js +215 -68
- package/dist/graph-ir.d.ts +23 -0
- package/dist/graph-ir.d.ts.map +1 -1
- package/dist/graph-ir.js +130 -0
- package/dist/graph-sub-template.d.ts +11 -0
- package/dist/graph-sub-template.d.ts.map +1 -0
- package/dist/graph-sub-template.js +19 -0
- package/dist/lexicon.d.ts +9 -0
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/observe.d.ts +28 -0
- package/dist/lifecycle/observe.d.ts.map +1 -1
- package/dist/lifecycle/observe.js +23 -1
- package/dist/lint/rule.d.ts +6 -0
- package/dist/lint/rule.d.ts.map +1 -1
- package/dist/live-endpoint.d.ts +1 -1
- package/dist/live-endpoint.d.ts.map +1 -1
- package/dist/live-endpoint.js +1 -1
- package/dist/observation.d.ts +48 -1
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +21 -5
- package/dist/op/activities/activity-contracts.d.ts +4 -4
- package/dist/wave-runtime.mjs +250 -249
- package/dist/workspace/capabilities-contract.d.ts +66 -0
- package/dist/workspace/capabilities-contract.d.ts.map +1 -0
- package/dist/workspace/capabilities-contract.js +107 -0
- package/dist/workspace/capabilities.schema.json +229 -0
- package/dist/workspace/compose-graph.d.ts +9 -0
- package/dist/workspace/compose-graph.d.ts.map +1 -1
- package/dist/workspace/compose-graph.js +3 -1
- package/dist/workspace/conformance/index.d.ts +1 -1
- package/dist/workspace/conformance/index.d.ts.map +1 -1
- package/dist/workspace/conformance/index.js +39 -2
- package/dist/workspace/graph-cache.d.ts +8 -0
- package/dist/workspace/graph-cache.d.ts.map +1 -1
- package/dist/workspace/graph-cache.js +27 -3
- package/dist/workspace/graph-cli.d.ts +39 -2
- package/dist/workspace/graph-cli.d.ts.map +1 -1
- package/dist/workspace/graph-cli.js +66 -24
- package/dist/workspace/graph.schema.json +148 -0
- package/dist/workspace/kind-readers.d.ts +3 -0
- package/dist/workspace/kind-readers.d.ts.map +1 -1
- package/dist/workspace/kind-readers.js +7 -1
- package/dist/workspace/member-commands.d.ts +10 -1
- package/dist/workspace/member-commands.d.ts.map +1 -1
- package/dist/workspace/member-commands.js +17 -1
- package/dist/workspace/nested-graph.d.ts +2 -0
- package/dist/workspace/nested-graph.d.ts.map +1 -1
- package/dist/workspace/nested-graph.js +32 -1
- package/dist/workspace/reason-codes.d.ts +10 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +12 -0
- package/dist/workspace/search-cli.d.ts +204 -0
- package/dist/workspace/search-cli.d.ts.map +1 -0
- package/dist/workspace/search-cli.js +466 -0
- package/dist/workspace/search-contract.d.ts +56 -0
- package/dist/workspace/search-contract.d.ts.map +1 -0
- package/dist/workspace/search-contract.js +70 -0
- package/dist/workspace/search.schema.json +822 -0
- package/package.json +1 -1
- package/src/__snapshots__/okf.test.ts.snap +10 -0
- package/src/capabilities/aws.paths +148 -0
- package/src/capabilities/base-mappings.json +122 -0
- package/src/capabilities/catalog.ts +230 -0
- package/src/capabilities/language.test.ts +191 -0
- package/src/capabilities/language.ts +373 -0
- package/src/capabilities/matcher.ts +315 -0
- package/src/capabilities/view-compose.test.ts +76 -0
- package/src/capabilities/view.ts +631 -0
- package/src/cli/commands/lint.ts +1 -0
- package/src/cli/handlers/declared-graph.ts +99 -0
- package/src/cli/handlers/graph.test.ts +94 -3
- package/src/cli/handlers/graph.ts +123 -96
- package/src/cli/handlers/pr-env.ts +1 -2
- package/src/cli/handlers/search-build-roots.test.ts +144 -0
- package/src/cli/handlers/search-count.test.ts +191 -0
- package/src/cli/handlers/search-count.ts +165 -0
- package/src/cli/handlers/search-json.test.ts +333 -0
- package/src/cli/handlers/search-live.test.ts +387 -0
- package/src/cli/handlers/search-paths.test.ts +235 -0
- package/src/cli/handlers/search.ts +1312 -166
- package/src/cli/main.test.ts +28 -3
- package/src/cli/main.ts +23 -3
- package/src/cli/mcp/server.test.ts +3 -3
- package/src/cli/mcp/server.ts +3 -0
- package/src/cli/mcp/tools/capabilities.ts +32 -0
- package/src/cli/mcp/workspace-tools.e2e.test.ts +21 -1
- package/src/cli/mcp/workspace-tools.ts +47 -2
- package/src/cli/parse-args.ts +52 -13
- package/src/cli/registry.ts +22 -0
- package/src/components/pr-env-ports.ts +89 -0
- package/src/components/pr-env-run-bundle.test.ts +54 -0
- package/src/components/pr-env-run.ts +5 -76
- package/src/components/pr-environment.ts +2 -1
- package/src/config-environments.ts +133 -0
- package/src/config.ts +37 -124
- package/src/graph-detail.ts +15 -3
- package/src/graph-effective.ts +226 -75
- package/src/graph-ir.test.ts +163 -0
- package/src/graph-ir.ts +147 -0
- package/src/graph-sub-template.ts +22 -0
- package/src/lexicon.ts +10 -0
- package/src/lifecycle/observe.test.ts +27 -1
- package/src/lifecycle/observe.ts +43 -1
- package/src/lint/rule.ts +6 -0
- package/src/live-endpoint.ts +1 -1
- package/src/observation.test.ts +25 -0
- package/src/observation.ts +69 -5
- package/src/workspace/capabilities-contract.test.ts +88 -0
- package/src/workspace/capabilities-contract.ts +132 -0
- package/src/workspace/capabilities.schema.json +229 -0
- package/src/workspace/compose-graph.ts +10 -1
- package/src/workspace/conformance/conformance.e2e.test.ts +14 -1
- package/src/workspace/conformance/index.ts +31 -2
- package/src/workspace/graph-cache.ts +27 -3
- package/src/workspace/graph-cli.ts +96 -24
- package/src/workspace/graph.schema.json +148 -0
- package/src/workspace/kind-readers.e2e.test.ts +28 -0
- package/src/workspace/kind-readers.test.ts +1 -1
- package/src/workspace/kind-readers.ts +7 -1
- package/src/workspace/member-commands.ts +22 -1
- package/src/workspace/nested-graph.ts +32 -1
- package/src/workspace/reason-codes.test.ts +7 -0
- package/src/workspace/reason-codes.ts +12 -0
- package/src/workspace/search-cli.e2e.test.ts +305 -0
- package/src/workspace/search-cli.ts +591 -0
- package/src/workspace/search-contract.ts +95 -0
- package/src/workspace/search.schema.json +822 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language.d.ts","sourceRoot":"","sources":["../../src/capabilities/language.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAEvD,kFAAkF;AAClF,MAAM,MAAM,KAAK,GAAG;IAAE,GAAG,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzD,MAAM,MAAM,IAAI,GACZ;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,SAAS,CAAC;IAAC,MAAM,EAAE,KAAK,EAAE,CAAA;CAAE,GACpI;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,KAAK,EAAE,CAAA;CAAE,CAAC;AAElE,MAAM,WAAW,QAAQ;IACvB,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AAED,MAAM,WAAW,IAAI;IACnB,GAAG,EAAE,KAAK,GAAG,IAAI,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,2DAA2D;IAC3D,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,KAAK,EAAE,CAAA;KAAE,EAAE,CAAC;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,IAAI,EAAE,WAAW,EAAE,CAAC;IACpB,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;CACd;AAED,sEAAsE;AACtE,qBAAa,eAAgB,SAAQ,KAAK;IAGtC,QAAQ,CAAC,IAAI,EAAE,MAAM;IAFvB,YACE,OAAO,EAAE,MAAM,EACN,IAAI,EAAE,MAAM,EAGtB;CACF;AAkBD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,CA0D/C;AA2LD,kFAAkF;AAClF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,CAaxD"}
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The capability rule language (#4375, ruled on #4361).
|
|
3
|
+
*
|
|
4
|
+
* A capability is a named path pattern over the lexicon-neutral view
|
|
5
|
+
* (`./view.ts`). Its steps are #4359's edge terms: an arrow, an optional
|
|
6
|
+
* depth, then what the edge is. A rule file is data, read at run time:
|
|
7
|
+
*
|
|
8
|
+
* # a comment
|
|
9
|
+
* ## meaning: what the capability says, in one line (catalog metadata)
|
|
10
|
+
* in-sg(x, g) := x ->{0,1}template ->sg g:SecurityGroup
|
|
11
|
+
* open-ingress(c; port?, proto?)
|
|
12
|
+
* := c ->in-sg ->ingress :IngressRule[cidrs in ("0.0.0.0/0"), from <= $port]
|
|
13
|
+
* internet-reachable(c; port?)
|
|
14
|
+
* := c[@internet-facing, @open-ingress($port)]
|
|
15
|
+
* | c:Function <-function :FunctionUrl[authType = "NONE"]
|
|
16
|
+
*
|
|
17
|
+
* One variable makes a node set, used as `[@name]`. Two make a named edge,
|
|
18
|
+
* followed as `->name` or `<-name`, which carries the hops that proved it.
|
|
19
|
+
* Parameters come after `;`; a `?` makes one optional, and a test that names
|
|
20
|
+
* an absent parameter is left out. Lines starting `|` add an alternative.
|
|
21
|
+
*
|
|
22
|
+
* A step is `->` or `<-`, an optional depth (`?`, `*`, `+`, `{n}`, `{m,n}`,
|
|
23
|
+
* `{m,}`; a rule may start at 0, which #4359's query grammar refuses), an
|
|
24
|
+
* edge name or `(a|b)`, and an optional node: `var:Label|Label[tests]`.
|
|
25
|
+
* `!->name node` and `!<-name node` are negated steps: the walk stays where
|
|
26
|
+
* it is and goes on only when no such edge leads to such a node.
|
|
27
|
+
*
|
|
28
|
+
* A node test is `attr = v`, `attr != v`, `attr in (v, ...)`, `attr ~ "glob"`,
|
|
29
|
+
* `attr < n` (and `<=`, `>`, `>=`), a bare `attr` (present and not false),
|
|
30
|
+
* or `@cap` / `@cap(args)`. Any test takes a leading `!`. Against a list
|
|
31
|
+
* attribute, a test holds when it holds for any element.
|
|
32
|
+
*/
|
|
33
|
+
/** A rule file the parser cannot read, with the line it failed on. */
|
|
34
|
+
export class RuleSyntaxError extends Error {
|
|
35
|
+
constructor(message, line) {
|
|
36
|
+
super(`line ${line}: ${message}`);
|
|
37
|
+
this.line = line;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// An identifier may hold `-` (`can-assume`), but not one that starts an arrow.
|
|
41
|
+
const TOKEN = /\s*(!->|!<-|->|<-|:=|<=|>=|!=|\{\d*(?:,\d*)?\}|"(?:[^"\\]|\\.)*"|-?\d+(?:\.\d+)?(?![\w-])|[$]?[A-Za-z_](?:\w|-(?!>))*|[()[\],|?*+@:=~<>!;])/y;
|
|
42
|
+
function tokenize(text, line) {
|
|
43
|
+
const out = [];
|
|
44
|
+
TOKEN.lastIndex = 0;
|
|
45
|
+
const end = text.trimEnd().length;
|
|
46
|
+
while (TOKEN.lastIndex < end) {
|
|
47
|
+
const at = TOKEN.lastIndex;
|
|
48
|
+
const m = TOKEN.exec(text);
|
|
49
|
+
if (!m)
|
|
50
|
+
throw new RuleSyntaxError(`cannot read "${text.slice(at).trim()}"`, line);
|
|
51
|
+
out.push(m[1]);
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Parse a rule file. Rules may span lines: a line that starts with `|`
|
|
57
|
+
* continues the rule above it, and so does an indented line when the rule's
|
|
58
|
+
* `:=` has nothing after it yet.
|
|
59
|
+
*/
|
|
60
|
+
export function parseRules(text) {
|
|
61
|
+
const rules = [];
|
|
62
|
+
let meta = {};
|
|
63
|
+
let pending;
|
|
64
|
+
const lines = text.split("\n");
|
|
65
|
+
const flush = () => {
|
|
66
|
+
if (!pending)
|
|
67
|
+
return;
|
|
68
|
+
const { text: body, line } = pending;
|
|
69
|
+
const toks = tokenize(body, line);
|
|
70
|
+
const p = new Parser(toks, line);
|
|
71
|
+
if (pending.rule) {
|
|
72
|
+
p.eat("|");
|
|
73
|
+
pending.rule.alts.push(p.alternative());
|
|
74
|
+
pending.rule.text += `\n${body.trim()}`;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
const rule = p.header(meta, body.trim());
|
|
78
|
+
meta = {};
|
|
79
|
+
rule.alts.push(p.alternative());
|
|
80
|
+
rules.push(rule);
|
|
81
|
+
}
|
|
82
|
+
p.done();
|
|
83
|
+
pending = undefined;
|
|
84
|
+
};
|
|
85
|
+
lines.forEach((raw, i) => {
|
|
86
|
+
const line = i + 1;
|
|
87
|
+
const docMatch = /^\s*##\s*([\w-]+)\s*:\s*(.*)$/.exec(raw);
|
|
88
|
+
if (docMatch) {
|
|
89
|
+
flush();
|
|
90
|
+
const [, key, value] = docMatch;
|
|
91
|
+
meta[key] = meta[key] ? `${meta[key]}\n${value.trim()}` : value.trim();
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const code = raw.replace(/(^|\s)#.*$/, "");
|
|
95
|
+
if (!code.trim())
|
|
96
|
+
return;
|
|
97
|
+
if (/^\s*\|/.test(code)) {
|
|
98
|
+
flush();
|
|
99
|
+
const rule = rules.at(-1);
|
|
100
|
+
if (!rule)
|
|
101
|
+
throw new RuleSyntaxError("an alternative needs a rule above it", line);
|
|
102
|
+
pending = { text: code, line, rule };
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (/^\s/.test(code) && pending) {
|
|
106
|
+
pending.text += ` ${code.trim()}`;
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
flush();
|
|
110
|
+
pending = { text: code, line };
|
|
111
|
+
});
|
|
112
|
+
flush();
|
|
113
|
+
const seen = new Set();
|
|
114
|
+
for (const r of rules) {
|
|
115
|
+
if (seen.has(r.name))
|
|
116
|
+
throw new RuleSyntaxError(`"${r.name}" is defined twice`, r.line);
|
|
117
|
+
seen.add(r.name);
|
|
118
|
+
}
|
|
119
|
+
return rules;
|
|
120
|
+
}
|
|
121
|
+
const LIT = (tok) => {
|
|
122
|
+
if (tok === "null")
|
|
123
|
+
return null;
|
|
124
|
+
if (tok === "true")
|
|
125
|
+
return true;
|
|
126
|
+
if (tok === "false")
|
|
127
|
+
return false;
|
|
128
|
+
if (tok.startsWith('"'))
|
|
129
|
+
return JSON.parse(tok);
|
|
130
|
+
if (/^-?\d/.test(tok))
|
|
131
|
+
return Number(tok);
|
|
132
|
+
return tok;
|
|
133
|
+
};
|
|
134
|
+
const NAME = /^[A-Za-z_][\w-]*$/;
|
|
135
|
+
class Parser {
|
|
136
|
+
constructor(t, line) {
|
|
137
|
+
this.t = t;
|
|
138
|
+
this.line = line;
|
|
139
|
+
this.i = 0;
|
|
140
|
+
}
|
|
141
|
+
peek(k = 0) {
|
|
142
|
+
return this.t[this.i + k];
|
|
143
|
+
}
|
|
144
|
+
next() {
|
|
145
|
+
const tok = this.t[this.i++];
|
|
146
|
+
if (tok === undefined)
|
|
147
|
+
throw new RuleSyntaxError("the rule ends too early", this.line);
|
|
148
|
+
return tok;
|
|
149
|
+
}
|
|
150
|
+
eat(x) {
|
|
151
|
+
if (this.t[this.i] !== x) {
|
|
152
|
+
throw new RuleSyntaxError(`expected "${x}" at "${this.t.slice(this.i).join(" ") || "end of rule"}"`, this.line);
|
|
153
|
+
}
|
|
154
|
+
this.i++;
|
|
155
|
+
}
|
|
156
|
+
done() {
|
|
157
|
+
if (this.i !== this.t.length)
|
|
158
|
+
throw new RuleSyntaxError(`cannot read "${this.t.slice(this.i).join(" ")}"`, this.line);
|
|
159
|
+
}
|
|
160
|
+
name(what) {
|
|
161
|
+
const tok = this.next();
|
|
162
|
+
if (!NAME.test(tok))
|
|
163
|
+
throw new RuleSyntaxError(`expected ${what}, found "${tok}"`, this.line);
|
|
164
|
+
return tok;
|
|
165
|
+
}
|
|
166
|
+
header(meta, text) {
|
|
167
|
+
const name = this.name("a capability name");
|
|
168
|
+
this.eat("(");
|
|
169
|
+
const vars = [this.name("a variable")];
|
|
170
|
+
if (this.peek() === ",") {
|
|
171
|
+
this.next();
|
|
172
|
+
vars.push(this.name("a variable"));
|
|
173
|
+
}
|
|
174
|
+
const params = [];
|
|
175
|
+
if (this.peek() === ";") {
|
|
176
|
+
this.next();
|
|
177
|
+
for (;;) {
|
|
178
|
+
const p = this.name("a parameter");
|
|
179
|
+
const optional = this.peek() === "?";
|
|
180
|
+
if (optional)
|
|
181
|
+
this.next();
|
|
182
|
+
params.push({ name: p, optional });
|
|
183
|
+
if (this.peek() !== ",")
|
|
184
|
+
break;
|
|
185
|
+
this.next();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
this.eat(")");
|
|
189
|
+
this.eat(":=");
|
|
190
|
+
return { name, vars, params, alts: [], meta, line: this.line, text };
|
|
191
|
+
}
|
|
192
|
+
alternative() {
|
|
193
|
+
const head = this.node();
|
|
194
|
+
const steps = [];
|
|
195
|
+
while (this.peek() && /^!?(->|<-)$/.test(this.peek()))
|
|
196
|
+
steps.push(this.step());
|
|
197
|
+
return { head, steps, line: this.line };
|
|
198
|
+
}
|
|
199
|
+
step() {
|
|
200
|
+
const arrow = this.next();
|
|
201
|
+
const negated = arrow.startsWith("!");
|
|
202
|
+
const dir = arrow.endsWith("->") ? "out" : "in";
|
|
203
|
+
let min = 1;
|
|
204
|
+
let max = 1;
|
|
205
|
+
const q = this.peek();
|
|
206
|
+
if (q === "?") {
|
|
207
|
+
this.next();
|
|
208
|
+
min = 0;
|
|
209
|
+
}
|
|
210
|
+
else if (q === "*") {
|
|
211
|
+
this.next();
|
|
212
|
+
max = Infinity;
|
|
213
|
+
}
|
|
214
|
+
else if (q === "+") {
|
|
215
|
+
this.next();
|
|
216
|
+
max = Infinity;
|
|
217
|
+
}
|
|
218
|
+
else if (q && q.startsWith("{")) {
|
|
219
|
+
this.next();
|
|
220
|
+
const m = /^\{(\d*)(,(\d*))?\}$/.exec(q);
|
|
221
|
+
min = m[1] === "" ? 0 : Number(m[1]);
|
|
222
|
+
max = m[2] === undefined ? min : m[3] === "" ? Infinity : Number(m[3]);
|
|
223
|
+
if (max < min)
|
|
224
|
+
throw new RuleSyntaxError(`depth ${q} has its maximum below its minimum`, this.line);
|
|
225
|
+
}
|
|
226
|
+
if (negated && (min !== 1 || max !== 1))
|
|
227
|
+
throw new RuleSyntaxError("a negated step takes no depth", this.line);
|
|
228
|
+
const names = [];
|
|
229
|
+
if (this.peek() === "(") {
|
|
230
|
+
this.next();
|
|
231
|
+
for (;;) {
|
|
232
|
+
names.push(this.edgeName());
|
|
233
|
+
if (this.peek() !== "|")
|
|
234
|
+
break;
|
|
235
|
+
this.next();
|
|
236
|
+
}
|
|
237
|
+
this.eat(")");
|
|
238
|
+
}
|
|
239
|
+
else
|
|
240
|
+
names.push(this.edgeName());
|
|
241
|
+
return { dir, negated, names, min, max, node: this.node() };
|
|
242
|
+
}
|
|
243
|
+
edgeName() {
|
|
244
|
+
const name = this.name("an edge name");
|
|
245
|
+
// `->grants($action)`: arguments must touch the name, so a following
|
|
246
|
+
// `(a|b)` step is not read as arguments.
|
|
247
|
+
return { name, args: this.peek() === "(" ? this.args() : [] };
|
|
248
|
+
}
|
|
249
|
+
args() {
|
|
250
|
+
this.eat("(");
|
|
251
|
+
const out = [];
|
|
252
|
+
while (this.peek() !== ")") {
|
|
253
|
+
out.push(this.value());
|
|
254
|
+
if (this.peek() === ",")
|
|
255
|
+
this.next();
|
|
256
|
+
}
|
|
257
|
+
this.eat(")");
|
|
258
|
+
return out;
|
|
259
|
+
}
|
|
260
|
+
value() {
|
|
261
|
+
const tok = this.next();
|
|
262
|
+
if (tok.startsWith("$"))
|
|
263
|
+
return { param: tok.slice(1) };
|
|
264
|
+
return { lit: LIT(tok) };
|
|
265
|
+
}
|
|
266
|
+
node() {
|
|
267
|
+
const spec = { tests: [] };
|
|
268
|
+
const p = this.peek();
|
|
269
|
+
if (p && NAME.test(p) && /^[a-z_]/.test(p) && this.peek(1) !== "(") {
|
|
270
|
+
spec.v = this.next();
|
|
271
|
+
}
|
|
272
|
+
if (this.peek() === ":") {
|
|
273
|
+
this.next();
|
|
274
|
+
spec.labels = [this.name("a label")];
|
|
275
|
+
while (this.peek() === "|" && /^[A-Z]/.test(this.peek(1) ?? "")) {
|
|
276
|
+
this.next();
|
|
277
|
+
spec.labels.push(this.name("a label"));
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
if (this.peek() === "[") {
|
|
281
|
+
this.next();
|
|
282
|
+
while (this.peek() !== "]") {
|
|
283
|
+
spec.tests.push(this.test());
|
|
284
|
+
if (this.peek() === ",")
|
|
285
|
+
this.next();
|
|
286
|
+
else if (this.peek() !== "]")
|
|
287
|
+
throw new RuleSyntaxError(`expected "," or "]" at "${this.peek() ?? "end of rule"}"`, this.line);
|
|
288
|
+
}
|
|
289
|
+
this.eat("]");
|
|
290
|
+
}
|
|
291
|
+
return spec;
|
|
292
|
+
}
|
|
293
|
+
test() {
|
|
294
|
+
let negated = false;
|
|
295
|
+
if (this.peek() === "!") {
|
|
296
|
+
this.next();
|
|
297
|
+
negated = true;
|
|
298
|
+
}
|
|
299
|
+
if (this.peek() === "@") {
|
|
300
|
+
this.next();
|
|
301
|
+
const cap = this.name("a capability name");
|
|
302
|
+
return { kind: "cap", negated, cap, args: this.peek() === "(" ? this.args() : [] };
|
|
303
|
+
}
|
|
304
|
+
const attr = this.name("an attribute");
|
|
305
|
+
const op = this.peek();
|
|
306
|
+
if (op === "," || op === "]")
|
|
307
|
+
return { kind: "attr", negated, attr, op: "present", values: [] };
|
|
308
|
+
this.next();
|
|
309
|
+
if (op === "in") {
|
|
310
|
+
return { kind: "attr", negated, attr, op: "in", values: this.args() };
|
|
311
|
+
}
|
|
312
|
+
if (op === "=" || op === "!=" || op === "~" || op === "<" || op === "<=" || op === ">" || op === ">=") {
|
|
313
|
+
return { kind: "attr", negated, attr, op, values: [this.value()] };
|
|
314
|
+
}
|
|
315
|
+
throw new RuleSyntaxError(`"${op}" is not a test operator`, this.line);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
/** The capabilities a rule refers to, by name: in `[@cap]` tests and in steps. */
|
|
319
|
+
export function ruleDependencies(rule) {
|
|
320
|
+
const out = new Set();
|
|
321
|
+
const node = (n) => {
|
|
322
|
+
for (const t of n.tests)
|
|
323
|
+
if (t.kind === "cap")
|
|
324
|
+
out.add(t.cap);
|
|
325
|
+
};
|
|
326
|
+
for (const a of rule.alts) {
|
|
327
|
+
node(a.head);
|
|
328
|
+
for (const s of a.steps) {
|
|
329
|
+
for (const n of s.names)
|
|
330
|
+
out.add(n.name);
|
|
331
|
+
node(s.node);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return out;
|
|
335
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The matcher for capability rules (#4375): evaluates `./language.ts` rules
|
|
3
|
+
* over a `./view.ts` view, lazily, keeping the path that proved each fact.
|
|
4
|
+
*
|
|
5
|
+
* A capability is computed the first time something asks for it, over the
|
|
6
|
+
* whole view, and kept. One that refers to another asks for it first, so
|
|
7
|
+
* negation is stratified by construction: `[!@cap]` reads a set that is
|
|
8
|
+
* already complete. Two capabilities that need each other are refused.
|
|
9
|
+
*/
|
|
10
|
+
import type { Literal, Rule } from "./language.js";
|
|
11
|
+
import type { View, ViewHop } from "./view.js";
|
|
12
|
+
/** Why a node is in a set, or a pair in an edge: the hops walked, and the sets it relied on. */
|
|
13
|
+
export interface Evidence {
|
|
14
|
+
/** IR hops in walk order. Each keeps the edge's own direction. */
|
|
15
|
+
hops: ViewHop[];
|
|
16
|
+
/** The `[@cap]` tests the match relied on, each with its own evidence. */
|
|
17
|
+
because: {
|
|
18
|
+
capability: string;
|
|
19
|
+
id: string;
|
|
20
|
+
evidence: Evidence;
|
|
21
|
+
}[];
|
|
22
|
+
}
|
|
23
|
+
export type Args = Record<string, Literal | undefined>;
|
|
24
|
+
/** An edge capability: each source's targets, with evidence. */
|
|
25
|
+
export interface Relation {
|
|
26
|
+
out: Map<string, Map<string, Evidence>>;
|
|
27
|
+
in: Map<string, Map<string, Evidence>>;
|
|
28
|
+
}
|
|
29
|
+
export declare class CapabilityError extends Error {
|
|
30
|
+
}
|
|
31
|
+
export declare class CapabilityEngine {
|
|
32
|
+
readonly view: View;
|
|
33
|
+
private readonly rules;
|
|
34
|
+
private readonly sets;
|
|
35
|
+
private readonly relations;
|
|
36
|
+
private readonly busy;
|
|
37
|
+
private readonly out;
|
|
38
|
+
private readonly in;
|
|
39
|
+
private readonly byLabel;
|
|
40
|
+
constructor(view: View, rules: Rule[]);
|
|
41
|
+
private index;
|
|
42
|
+
/** Refuse a rule that names a capability that doesn't exist, or uses one in the wrong shape. */
|
|
43
|
+
private check;
|
|
44
|
+
has(name: string): boolean;
|
|
45
|
+
/** The capabilities the catalog lists: rules that carry a `## meaning`. */
|
|
46
|
+
publicNames(): string[];
|
|
47
|
+
rule(name: string): Rule | undefined;
|
|
48
|
+
/** Bind positional arguments to a rule's parameters. */
|
|
49
|
+
bind(name: string, positional: (Literal | undefined)[]): Args;
|
|
50
|
+
private key;
|
|
51
|
+
/** The nodes in a set capability, with evidence. */
|
|
52
|
+
set(name: string, args?: Args): Map<string, Evidence>;
|
|
53
|
+
/** The pairs in an edge capability, with evidence. */
|
|
54
|
+
relation(name: string, args?: Args): Relation;
|
|
55
|
+
private enter;
|
|
56
|
+
private starts;
|
|
57
|
+
private resolve;
|
|
58
|
+
private test;
|
|
59
|
+
private ok;
|
|
60
|
+
private hop;
|
|
61
|
+
/** Every node within the step's depth range, by its shortest walk. */
|
|
62
|
+
private walk;
|
|
63
|
+
private match;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=matcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matcher.d.ts","sourceRoot":"","sources":["../../src/capabilities/matcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAe,OAAO,EAAY,IAAI,EAAqB,MAAM,YAAY,CAAC;AAC1F,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAE5C,gGAAgG;AAChG,MAAM,WAAW,QAAQ;IACvB,kEAAkE;IAClE,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,0EAA0E;IAC1E,OAAO,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,QAAQ,CAAA;KAAE,EAAE,CAAC;CACnE;AAED,MAAM,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC,CAAC;AAEvD,gEAAgE;AAChE,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IACxC,EAAE,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;CACxC;AAED,qBAAa,eAAgB,SAAQ,KAAK;CAAG;AAkB7C,qBAAa,gBAAgB;IAUzB,QAAQ,CAAC,IAAI,EAAE,IAAI;IATrB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2B;IACjD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA4C;IACjE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+B;IACzD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAqB;IAC1C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAqE;IACzF,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAqE;IACxF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;IAEvD,YACW,IAAI,EAAE,IAAI,EACnB,KAAK,EAAE,IAAI,EAAE,EAYd;IAED,OAAO,CAAC,KAAK;IAQb,gGAAgG;IAChG,OAAO,CAAC,KAAK;IAuBb,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzB;IAED,2EAA2E;IAC3E,WAAW,IAAI,MAAM,EAAE,CAEtB;IAED,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAEnC;IAED,wDAAwD;IACxD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,OAAO,GAAG,SAAS,CAAC,EAAE,GAAG,IAAI,CAa5D;IAED,OAAO,CAAC,GAAG;IAIX,oDAAoD;IACpD,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,IAAS,GAAG,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAoBxD;IAED,sDAAsD;IACtD,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,IAAS,GAAG,QAAQ,CA4BhD;IAED,OAAO,CAAC,KAAK;IAOb,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,IAAI;IAqCZ,OAAO,CAAC,EAAE;IAQV,OAAO,CAAC,GAAG;IAcX,sEAAsE;IACtE,OAAO,CAAC,IAAI;IAuBZ,OAAO,CAAC,KAAK;CAyBd"}
|