@venn-lang/runtime 0.1.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/LICENSE +21 -0
- package/README.md +158 -0
- package/dist/index.d.ts +453 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3314 -0
- package/dist/index.js.map +1 -0
- package/package.json +56 -0
- package/src/check/check-calls.ts +82 -0
- package/src/check/check-deco-body.ts +77 -0
- package/src/check/check-document.ts +106 -0
- package/src/check/check-env.ts +96 -0
- package/src/check/check-fragment-call.ts +27 -0
- package/src/check/check-imports.ts +82 -0
- package/src/check/check-interpolation.ts +58 -0
- package/src/check/check-options.ts +18 -0
- package/src/check/check-uncalled.ts +42 -0
- package/src/check/check.types.ts +30 -0
- package/src/check/index.ts +4 -0
- package/src/context/action-context.ts +20 -0
- package/src/context/index.ts +1 -0
- package/src/decorators/builtin-decorators.ts +87 -0
- package/src/decorators/create-decorator-source.ts +25 -0
- package/src/decorators/index.ts +2 -0
- package/src/emit/create-emitter.ts +16 -0
- package/src/emit/emitter.types.ts +6 -0
- package/src/emit/index.ts +3 -0
- package/src/emit/run-id.ts +11 -0
- package/src/eventsink/event-sink.port.ts +13 -0
- package/src/eventsink/event-sink.types.ts +11 -0
- package/src/eventsink/index.ts +4 -0
- package/src/eventsink/memory-sink.ts +17 -0
- package/src/eventsink/ndjson-sink.ts +14 -0
- package/src/index.ts +14 -0
- package/src/ports/create-port-resolver.ts +39 -0
- package/src/ports/index.ts +2 -0
- package/src/ports/port-resolver.types.ts +12 -0
- package/src/registry/build-registry.ts +76 -0
- package/src/registry/index.ts +2 -0
- package/src/registry/registry.types.ts +24 -0
- package/src/run/create-runner.ts +103 -0
- package/src/run/index.ts +4 -0
- package/src/run/resolve-imports.ts +166 -0
- package/src/run/runner.types.ts +67 -0
- package/src/scheduler/absorb-exit.ts +19 -0
- package/src/scheduler/aliases.ts +44 -0
- package/src/scheduler/annotations.ts +48 -0
- package/src/scheduler/base-scope.ts +25 -0
- package/src/scheduler/bind-globals.ts +55 -0
- package/src/scheduler/bind-imports.ts +130 -0
- package/src/scheduler/bind-namespaces.ts +61 -0
- package/src/scheduler/bind-prelude.ts +11 -0
- package/src/scheduler/block-plan.ts +66 -0
- package/src/scheduler/branch-engine.ts +13 -0
- package/src/scheduler/call-params.ts +140 -0
- package/src/scheduler/cleanup.types.ts +18 -0
- package/src/scheduler/collect.ts +60 -0
- package/src/scheduler/concurrency.ts +16 -0
- package/src/scheduler/create-cleanup-list.ts +17 -0
- package/src/scheduler/declared-arity.ts +13 -0
- package/src/scheduler/engine.types.ts +50 -0
- package/src/scheduler/filter.ts +5 -0
- package/src/scheduler/filter.types.ts +9 -0
- package/src/scheduler/flaky.ts +32 -0
- package/src/scheduler/flaky.types.ts +7 -0
- package/src/scheduler/index.ts +16 -0
- package/src/scheduler/invocation.ts +103 -0
- package/src/scheduler/local-call.ts +28 -0
- package/src/scheduler/node-span.ts +29 -0
- package/src/scheduler/opts-text.ts +10 -0
- package/src/scheduler/opts.ts +14 -0
- package/src/scheduler/pending.types.ts +9 -0
- package/src/scheduler/run-action.ts +163 -0
- package/src/scheduler/run-around.ts +23 -0
- package/src/scheduler/run-attempts.ts +105 -0
- package/src/scheduler/run-bindings.ts +67 -0
- package/src/scheduler/run-block.ts +65 -0
- package/src/scheduler/run-document.ts +181 -0
- package/src/scheduler/run-expect.ts +48 -0
- package/src/scheduler/run-flow.ts +69 -0
- package/src/scheduler/run-foreach.ts +148 -0
- package/src/scheduler/run-group.ts +9 -0
- package/src/scheduler/run-if.ts +21 -0
- package/src/scheduler/run-lifecycle.ts +86 -0
- package/src/scheduler/run-matcher.ts +99 -0
- package/src/scheduler/run-parallel.ts +68 -0
- package/src/scheduler/run-prologue.ts +59 -0
- package/src/scheduler/run-race.ts +20 -0
- package/src/scheduler/run-repeat.ts +54 -0
- package/src/scheduler/run-run.ts +41 -0
- package/src/scheduler/run-script.ts +48 -0
- package/src/scheduler/run-statements.ts +107 -0
- package/src/scheduler/run-step.ts +76 -0
- package/src/scheduler/run-try.ts +34 -0
- package/src/scheduler/run-while.ts +50 -0
- package/src/scheduler/script-lifecycle.ts +47 -0
- package/src/scheduler/settled.ts +20 -0
- package/src/scheduler/signals.ts +33 -0
- package/src/scheduler/target.ts +30 -0
- package/src/scheduler/unknown-option.ts +87 -0
- package/src/scope/create-scope.ts +67 -0
- package/src/scope/index.ts +2 -0
- package/src/scope/scope.types.ts +12 -0
- package/src/types/create-type-catalog.ts +70 -0
- package/src/types/index.ts +1 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vinicius Borges
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# @venn-lang/runtime
|
|
2
|
+
|
|
3
|
+
> Executes a parsed Venn document: the scheduler, the plugin registry, the event stream.
|
|
4
|
+
|
|
5
|
+
`@venn-lang/core` turns source into an AST. This package walks it. It builds the registry of verbs the
|
|
6
|
+
loaded plugins contribute, expands decorators, opens the scopes, runs flows and steps in the order
|
|
7
|
+
the language says, and emits one ordered stream of envelopes describing what happened.
|
|
8
|
+
|
|
9
|
+
It performs no I/O of its own. Every effect leaves through a port the host bound at startup, so the
|
|
10
|
+
package never imports `node:*` and runs unchanged in a Web Worker. The CLI and the language server
|
|
11
|
+
are both built on it.
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { createTestHost } from "@venn-lang/contracts";
|
|
17
|
+
import { parse } from "@venn-lang/core";
|
|
18
|
+
import { defineAction, definePlugin } from "@venn-lang/sdk";
|
|
19
|
+
import { createMemorySink, createRunner } from "@venn-lang/runtime";
|
|
20
|
+
|
|
21
|
+
const echo = definePlugin({
|
|
22
|
+
name: "@test/echo",
|
|
23
|
+
version: "0.0.0",
|
|
24
|
+
namespace: "test",
|
|
25
|
+
actions: [defineAction({ name: "echo", run: (_ctx, input) => ({ status: input.args[0] }) })],
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const source = `flow "F" {
|
|
29
|
+
step "S" {
|
|
30
|
+
let res = test.echo 200
|
|
31
|
+
expect res.status == 200
|
|
32
|
+
}
|
|
33
|
+
}`;
|
|
34
|
+
|
|
35
|
+
const sink = createMemorySink();
|
|
36
|
+
const runner = createRunner({ host: createTestHost(), plugins: [echo], sink });
|
|
37
|
+
|
|
38
|
+
const result = await runner.run(parse(source).ast);
|
|
39
|
+
result.passed; // 1
|
|
40
|
+
sink.envelopes.map((envelope) => envelope.kind); // run.started … run.finished
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`createRunner` negotiates plugins and wires ports once; the returned `Runner` is reused per run.
|
|
44
|
+
|
|
45
|
+
## API
|
|
46
|
+
|
|
47
|
+
### Running
|
|
48
|
+
|
|
49
|
+
| Export | What it does |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| `createRunner(args)` | Builds the registry, the port resolver and the decorator source, and returns a `Runner`. Throws `VN2010` when a plugin needs a capability the host does not offer. |
|
|
52
|
+
| `Runner` | `run(document)` runs every `flow` (test mode); `script(document)` executes the top-level statements top to bottom (script mode). Both return a `RunResult`. |
|
|
53
|
+
| `RunnerArgs` | `host`, `plugins`, `sink`, plus optional `ports`, `uri`, `filter`, `bail`, `env`, `cleanup`, and the import-graph fields `modules`, `moduleFragments`, `moduleDecos`. |
|
|
54
|
+
| `RunResult` | `run` (the run id), `passed`, `failed`, `problems` (what decorators refused before anything ran) and `exitCode` when the program called `exit`. |
|
|
55
|
+
| `resolveImports(args)` | Walks the import graph from one document, parsing each `.vn` file it reaches. Returns the exported fragments and decos, every `use`d package, the loaded npm modules and the parsed modules themselves. Cycles are skipped, not looped. |
|
|
56
|
+
| `collectUses(document, into)` | Adds the packages a document `use`s to a set. |
|
|
57
|
+
| `ModuleIo`, `NpmModules`, `ResolvedImports` | How a host reads source (`read`, `resolve`), how it loads an installed package, and what the walk produced. |
|
|
58
|
+
|
|
59
|
+
### Plugins and types
|
|
60
|
+
|
|
61
|
+
| Export | What it does |
|
|
62
|
+
| --- | --- |
|
|
63
|
+
| `buildRegistry({ plugins, caps })` | Checks every plugin's `requires` against the host capabilities, then indexes its actions, matchers and namespace. |
|
|
64
|
+
| `Registry` | Resolves `namespace.action`, a matcher by name, whether a namespace exists, the namespace a package contributes, and the full action list. |
|
|
65
|
+
| `ResolvedAction`, `ResolvedMatcher` | An action or matcher paired with the plugin that owns it. |
|
|
66
|
+
| `builtinDecorators` | The decorators the language ships with: `@skip`, `@only`, `@serial`, `@tags`, `@timeout`, `@retry`, `@lock`, `@flaky`. |
|
|
67
|
+
| `createDecoratorSource(plugins)` | The built-ins plus every plugin decorator. A plugin's decorator of the same name wins on purpose. |
|
|
68
|
+
| `createTypeCatalog(plugins)` | Turns what plugins publish (`typeDefs`, action `signature`s) into the `TypeCatalog` the checker asks. Names are qualified once here: a plugin says `Request`, a flow writes `http.Request`. |
|
|
69
|
+
|
|
70
|
+
### Events
|
|
71
|
+
|
|
72
|
+
| Export | What it does |
|
|
73
|
+
| --- | --- |
|
|
74
|
+
| `EventSink` | One method, `emit(envelope)`. The destination of the stream. |
|
|
75
|
+
| `createMemorySink()` | The test double: keeps every envelope on `.envelopes`. |
|
|
76
|
+
| `createNdjsonSink({ write })` | One JSON envelope per line. `write` is injected, so the sink stays neutral. |
|
|
77
|
+
| `EventSinkPort` | The port descriptor, `venn.port.event-sink`, version 1. |
|
|
78
|
+
| `createEmitter({ sink, run, clock })` | The single place `seq` increments and `ts` is stamped. |
|
|
79
|
+
| `newRunId({ clock, random })` | Mints a run id from the host clock and random source. |
|
|
80
|
+
|
|
81
|
+
### Ports, scopes and cleanup
|
|
82
|
+
|
|
83
|
+
| Export | What it does |
|
|
84
|
+
| --- | --- |
|
|
85
|
+
| `createPortResolver({ bindings, caps })` | Resolves a `Port<T>` to the bound implementation, running capability and shape negotiation. Throws `VN7002` when nothing is bound. |
|
|
86
|
+
| `PortBinding` | A port paired with the implementation a host chose. |
|
|
87
|
+
| `createScope(parent?)` | A lexical scope. `lookup` falls back to the parent, `set` writes locally, `child()` nests. Bindings live in cells, so a compiled function addresses a free name once. |
|
|
88
|
+
| `createCleanupList()` | The runtime's own `CleanupSink` for a host that does not bring one. `close()` runs the entries newest first and survives one that throws. |
|
|
89
|
+
| `Cleanup`, `CleanupList`, `CleanupSink` | What a run registers on the way out, and who owns running it. |
|
|
90
|
+
| `collectFragments(document)` | The document's `fragment` declarations, by name. |
|
|
91
|
+
| `matchesTitle(title, needle)` | Case-insensitive containment. Absent needle matches everything. |
|
|
92
|
+
| `RunFilter` | `tags`, `flow`, `step`: which flows and steps a run includes. |
|
|
93
|
+
|
|
94
|
+
### Static checks
|
|
95
|
+
|
|
96
|
+
| Export | What it does |
|
|
97
|
+
| --- | --- |
|
|
98
|
+
| `checkDocument(args)` | Resolves every action, matcher, fragment and `env` read in a parsed document, returning `Problem`s with source spans instead of failures mid-run. |
|
|
99
|
+
| `checkImports({ document, uri, graph })` | Every imported name checked against what the named file published, with `VN2009` and a note saying whether it is private or absent. |
|
|
100
|
+
| `checkFragmentCall(call, ctx)` | Reports a `fragment` invoked for a value (`VN3013`), suggesting `run name(…)`. Used inside `checkDocument`. |
|
|
101
|
+
| `CheckArgs` | `document`, `registry`, `fragments`, plus optional `uri` and the `env` names `venn.toml` declares. |
|
|
102
|
+
|
|
103
|
+
The codes `checkDocument` raises: `VN2003` unknown action, `VN2004` unknown matcher, `VN2005`
|
|
104
|
+
unknown fragment, `VN2006` undeclared `env` variable, `VN2007` namespace used without `use`,
|
|
105
|
+
`VN2008` a verb named but never called, `VN3013` a fragment called for a value, plus unknown option
|
|
106
|
+
keys from the action's own parameter schema.
|
|
107
|
+
|
|
108
|
+
## What the scheduler runs
|
|
109
|
+
|
|
110
|
+
Test mode walks the document: suite `setup`, then one full pass per `matrix` variant, then
|
|
111
|
+
`teardown`. Each pass binds `env` and the variant, runs the top-level statements, then the flows with
|
|
112
|
+
`beforeEach` and `afterEach` around each one. Script mode runs the same top-level statements as the
|
|
113
|
+
program itself, top to bottom, and hands `teardown` and `defer` to the host's cleanup sink, because a
|
|
114
|
+
program that serves outlives its last line.
|
|
115
|
+
|
|
116
|
+
Inside a flow the scheduler handles steps and groups, `if`/`else`, `forEach`, `repeat`, `while`,
|
|
117
|
+
`try`/`catch`/`finally`, `run <fragment>(…)`, `defer`, `on failure`/`on success`, and the prelude
|
|
118
|
+
verbs `print`, `log`, `wait`, `skip`, `fail`, `exit`.
|
|
119
|
+
|
|
120
|
+
```ruby
|
|
121
|
+
@tags(smoke)
|
|
122
|
+
@retry(2, { backoff: 500ms, factor: 2 })
|
|
123
|
+
flow "checkout" {
|
|
124
|
+
parallel { concurrency: 2 } {
|
|
125
|
+
step "cart" { expect true }
|
|
126
|
+
step "stock" { expect true }
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`parallel` takes `concurrency` (a worker pool) and `onError: "collect"`, which lets every branch
|
|
132
|
+
finish instead of cancelling the siblings at the first failure. `race` runs its branches until the
|
|
133
|
+
first settles and aborts the rest; a cancelled branch stops at its next statement boundary, and an
|
|
134
|
+
action that wants to be interrupted sooner listens to `ctx.signal`.
|
|
135
|
+
|
|
136
|
+
Decorators run before the scheduler sees anything: what it walks is the tree expansion left, not the
|
|
137
|
+
one the parser produced. `@timeout` and `@retry` wrap a flow or step body, `@lock("name")` and
|
|
138
|
+
`@serial` take a named mutex from the host lock provider, `@skip` and `@only` gate what runs, and
|
|
139
|
+
`@flaky(ratio)` is settled once at the end of the run so the verdict does not depend on the order
|
|
140
|
+
iterations happened to fail in.
|
|
141
|
+
|
|
142
|
+
## The event stream
|
|
143
|
+
|
|
144
|
+
Everything a reporter or a UI shows derives from the envelope stream: `seq` is monotonic per run,
|
|
145
|
+
`ts` comes from the host clock, and the kinds are `run.started`, `run.finished`, `flow.started`,
|
|
146
|
+
`flow.finished`, `flow.retrying`, `step.started`, `step.finished`, `action.started`,
|
|
147
|
+
`action.finished`, `expect.passed`, `expect.failed` and `log`. A failed expectation carries a whole
|
|
148
|
+
`Problem`, code and span included, never a flattened string.
|
|
149
|
+
|
|
150
|
+
`EventSink` is a port: `createMemorySink` and `createNdjsonSink` are its two implementations, and
|
|
151
|
+
both run the same conformance suite, which pins that envelopes arrive in `seq` order.
|
|
152
|
+
|
|
153
|
+
## See also
|
|
154
|
+
|
|
155
|
+
- [`@venn-lang/core`](../core) parses and checks; it produces the document this package runs.
|
|
156
|
+
- [`@venn-lang/sdk`](../sdk) defines the plugins, actions and matchers the registry ingests.
|
|
157
|
+
- [`@venn-lang/contracts`](../contracts) supplies the `Host`, the ports and the capability negotiation.
|
|
158
|
+
- [`@venn-lang/cli`](../cli) assembles a Node host and drives the runner.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
import { Call, CellEnv, DecoratorDefinition, DecoratorSource, Document, Envelope, EventData, EventKind, FragmentDecl, ImportedDeco, NodePath, Problem, RunId, TypeCatalog } from "@venn-lang/core";
|
|
2
|
+
import { AnyPort, Clock, Host, HostCapability, Port, Random } from "@venn-lang/contracts";
|
|
3
|
+
import { ActionDefinition, MatcherDefinition, PluginDefinition } from "@venn-lang/sdk";
|
|
4
|
+
//#region src/registry/registry.types.d.ts
|
|
5
|
+
/** An action together with the plugin that owns it. */
|
|
6
|
+
interface ResolvedAction {
|
|
7
|
+
plugin: PluginDefinition;
|
|
8
|
+
action: ActionDefinition;
|
|
9
|
+
}
|
|
10
|
+
/** A matcher together with the plugin that owns it. */
|
|
11
|
+
interface ResolvedMatcher {
|
|
12
|
+
plugin: PluginDefinition;
|
|
13
|
+
matcher: MatcherDefinition;
|
|
14
|
+
}
|
|
15
|
+
/** Resolves `namespace.action`, matchers, and namespaces from ingested plugins. */
|
|
16
|
+
interface Registry {
|
|
17
|
+
action(args: {
|
|
18
|
+
namespace: string;
|
|
19
|
+
name: string;
|
|
20
|
+
}): ResolvedAction | undefined;
|
|
21
|
+
matcher(name: string): ResolvedMatcher | undefined;
|
|
22
|
+
hasNamespace(namespace: string): boolean;
|
|
23
|
+
/** The namespace a package contributes, for `use "venn/http" as h`. */
|
|
24
|
+
namespaceOf(pkg: string): string | undefined;
|
|
25
|
+
/** Every action, for binding namespaces as values in the evaluator scope. */
|
|
26
|
+
actions(): readonly {
|
|
27
|
+
namespace: string;
|
|
28
|
+
name: string;
|
|
29
|
+
action: ActionDefinition;
|
|
30
|
+
}[];
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/registry/build-registry.d.ts
|
|
34
|
+
/**
|
|
35
|
+
* Ingest plugins after negotiating each plugin's capabilities against the host.
|
|
36
|
+
*
|
|
37
|
+
* @param args.plugins The plugins to index, in load order; later ones win a clash.
|
|
38
|
+
* @param args.caps The capabilities this host offers.
|
|
39
|
+
* @returns A registry resolving actions, matchers and namespaces.
|
|
40
|
+
* @throws VennError `VN2010` when a plugin requires a capability the host lacks.
|
|
41
|
+
*/
|
|
42
|
+
declare function buildRegistry(args: {
|
|
43
|
+
plugins: readonly PluginDefinition[];
|
|
44
|
+
caps: readonly HostCapability[];
|
|
45
|
+
}): Registry;
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region src/check/check.types.d.ts
|
|
48
|
+
/** Inputs to a static name-resolution pass over a parsed document. */
|
|
49
|
+
interface CheckArgs {
|
|
50
|
+
document: Document;
|
|
51
|
+
registry: Registry;
|
|
52
|
+
fragments: ReadonlySet<string>;
|
|
53
|
+
uri?: string;
|
|
54
|
+
/**
|
|
55
|
+
* The variables `venn.toml` declares. Omit it when they are unknown: an
|
|
56
|
+
* undeclared-variable error is only worth raising when the declaration list is
|
|
57
|
+
* trustworthy.
|
|
58
|
+
*/
|
|
59
|
+
env?: readonly string[];
|
|
60
|
+
}
|
|
61
|
+
/** Everything a per-node check needs, resolved once per document. */
|
|
62
|
+
interface CheckContext {
|
|
63
|
+
registry: Registry;
|
|
64
|
+
fragments: ReadonlySet<string>;
|
|
65
|
+
aliases: ReadonlyMap<string, string>;
|
|
66
|
+
/** Namespaces this file actually brought in with `use`. */
|
|
67
|
+
imported: ReadonlySet<string>;
|
|
68
|
+
/** Names this file binds: callable, but their methods cannot be verified. */
|
|
69
|
+
bound: ReadonlySet<string>;
|
|
70
|
+
/** Declared `env` variables, or undefined when the manifest could not be read. */
|
|
71
|
+
env?: ReadonlySet<string>;
|
|
72
|
+
uri: string;
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region src/check/check-document.d.ts
|
|
76
|
+
/**
|
|
77
|
+
* Statically resolve every action, matcher and fragment reference in a parsed
|
|
78
|
+
* document. The errors the runner would otherwise raise mid-run are surfaced all
|
|
79
|
+
* at once, each with its source span.
|
|
80
|
+
*
|
|
81
|
+
* @param args Document, registry, known fragments and the declared `env` names.
|
|
82
|
+
* @returns One `Problem` per unresolved reference; empty when the document is clean.
|
|
83
|
+
*/
|
|
84
|
+
declare function checkDocument(args: CheckArgs): Problem[];
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region src/check/check-fragment-call.d.ts
|
|
87
|
+
/**
|
|
88
|
+
* Refuse a fragment called as though it were a function.
|
|
89
|
+
*
|
|
90
|
+
* The two look alike where they are written but are different kinds of thing: a
|
|
91
|
+
* `fn` gives back a value, a `fragment` gives back steps, and steps are recorded
|
|
92
|
+
* in the report, can fail and belong to a flow. So a fragment is invoked with
|
|
93
|
+
* `run`. `run entrar(…)` never reaches here: its target is a name, not an
|
|
94
|
+
* expression.
|
|
95
|
+
*
|
|
96
|
+
* @param call The call expression to inspect.
|
|
97
|
+
* @param ctx The document's resolved check context.
|
|
98
|
+
* @returns A `VN3013` problem, or `undefined` when the callee is not a fragment.
|
|
99
|
+
*/
|
|
100
|
+
declare function checkFragmentCall(call: Call, ctx: CheckContext): Problem | undefined;
|
|
101
|
+
//#endregion
|
|
102
|
+
//#region src/eventsink/event-sink.types.d.ts
|
|
103
|
+
/** The destination of the event stream. Everything the UI shows derives from it. */
|
|
104
|
+
interface EventSink {
|
|
105
|
+
emit(envelope: Envelope): void;
|
|
106
|
+
}
|
|
107
|
+
/** An EventSink that also retains every envelope (the test double). */
|
|
108
|
+
interface MemorySink extends EventSink {
|
|
109
|
+
readonly envelopes: readonly Envelope[];
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
112
|
+
//#region src/eventsink/event-sink.port.d.ts
|
|
113
|
+
/**
|
|
114
|
+
* The port every run event is written to. Bound at startup by whoever assembles
|
|
115
|
+
* the host: the CLI binds NDJSON on stdout, tests bind the memory double.
|
|
116
|
+
*/
|
|
117
|
+
declare const EventSinkPort: Port<EventSink>;
|
|
118
|
+
//#endregion
|
|
119
|
+
//#region src/eventsink/memory-sink.d.ts
|
|
120
|
+
/**
|
|
121
|
+
* In-memory sink (the test double): keeps every envelope for assertions.
|
|
122
|
+
*
|
|
123
|
+
* @returns A sink whose `envelopes` array grows in emission order.
|
|
124
|
+
*/
|
|
125
|
+
declare function createMemorySink(): MemorySink;
|
|
126
|
+
//#endregion
|
|
127
|
+
//#region src/eventsink/ndjson-sink.d.ts
|
|
128
|
+
/**
|
|
129
|
+
* NDJSON sink: one JSON envelope per line. The `write` sink is injected (the CLI
|
|
130
|
+
* passes stdout) so this file stays neutral and needs no `node:*`.
|
|
131
|
+
*
|
|
132
|
+
* @param args.write Receives each line, newline included.
|
|
133
|
+
* @returns A sink that serialises every envelope it is given.
|
|
134
|
+
*/
|
|
135
|
+
declare function createNdjsonSink(args: {
|
|
136
|
+
write: (line: string) => void;
|
|
137
|
+
}): EventSink;
|
|
138
|
+
//#endregion
|
|
139
|
+
//#region src/emit/emitter.types.d.ts
|
|
140
|
+
/** The single place `seq` increments and `ts` is stamped. Handlers emit only here. */
|
|
141
|
+
interface Emitter {
|
|
142
|
+
emit<K extends EventKind>(args: {
|
|
143
|
+
kind: K;
|
|
144
|
+
data: EventData[K];
|
|
145
|
+
node?: NodePath;
|
|
146
|
+
}): void;
|
|
147
|
+
}
|
|
148
|
+
//#endregion
|
|
149
|
+
//#region src/emit/create-emitter.d.ts
|
|
150
|
+
/** Build the sole emitter: it owns `seq` and stamps `ts` from the runner's clock. */
|
|
151
|
+
declare function createEmitter(args: {
|
|
152
|
+
sink: EventSink;
|
|
153
|
+
run: RunId;
|
|
154
|
+
clock: Clock;
|
|
155
|
+
}): Emitter;
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region src/emit/run-id.d.ts
|
|
158
|
+
/**
|
|
159
|
+
* Mint a run id from the host clock and random source, so a seeded run is
|
|
160
|
+
* reproducible. Real ULID minting comes later.
|
|
161
|
+
*/
|
|
162
|
+
declare function newRunId(args: {
|
|
163
|
+
clock: Clock;
|
|
164
|
+
random: Random;
|
|
165
|
+
}): RunId;
|
|
166
|
+
//#endregion
|
|
167
|
+
//#region src/scope/scope.types.d.ts
|
|
168
|
+
/**
|
|
169
|
+
* A lexical scope: the evaluator's env plus mutation and nesting.
|
|
170
|
+
*
|
|
171
|
+
* A `CellEnv`, so a closure defined here can address its free names once and
|
|
172
|
+
* read them by index afterwards instead of walking the chain per call.
|
|
173
|
+
*/
|
|
174
|
+
interface Scope extends CellEnv {
|
|
175
|
+
set(name: string, value: unknown): void;
|
|
176
|
+
child(): Scope;
|
|
177
|
+
}
|
|
178
|
+
//#endregion
|
|
179
|
+
//#region src/scope/create-scope.d.ts
|
|
180
|
+
/**
|
|
181
|
+
* Create a scope; `lookup` falls back to the parent, `set` writes locally.
|
|
182
|
+
*
|
|
183
|
+
* @param parent The enclosing scope, or nothing for a root scope.
|
|
184
|
+
*/
|
|
185
|
+
declare function createScope(parent?: Scope): Scope;
|
|
186
|
+
//#endregion
|
|
187
|
+
//#region src/scheduler/bind-imports.d.ts
|
|
188
|
+
/** The files an import graph reached, and how one file names another. */
|
|
189
|
+
interface ImportGraph {
|
|
190
|
+
modules: ReadonlyMap<string, Document>;
|
|
191
|
+
resolve: (from: string, spec: string) => string;
|
|
192
|
+
/** What each npm specifier loaded to, already a value. */
|
|
193
|
+
npm?: ReadonlyMap<string, Record<string, unknown>>;
|
|
194
|
+
}
|
|
195
|
+
//#endregion
|
|
196
|
+
//#region src/scheduler/cleanup.types.d.ts
|
|
197
|
+
/** Something a run opened, and how to give it back. */
|
|
198
|
+
type Cleanup = () => Promise<void>;
|
|
199
|
+
/**
|
|
200
|
+
* Where a run registers what it opened, for whoever owns the process.
|
|
201
|
+
*
|
|
202
|
+
* The runtime does not decide when a program ends: a served program ends when
|
|
203
|
+
* the machine says so, and only the host hears that. So the run says what has to
|
|
204
|
+
* happen on the way out, and the host says when.
|
|
205
|
+
*/
|
|
206
|
+
interface CleanupSink {
|
|
207
|
+
add(cleanup: Cleanup): unknown;
|
|
208
|
+
}
|
|
209
|
+
/** A sink that also runs what it collected, newest first. */
|
|
210
|
+
interface CleanupList extends CleanupSink {
|
|
211
|
+
close(): Promise<void>;
|
|
212
|
+
}
|
|
213
|
+
//#endregion
|
|
214
|
+
//#region src/scheduler/filter.types.d.ts
|
|
215
|
+
/** Which flows and steps a run includes. Absent fields mean "no restriction". */
|
|
216
|
+
interface RunFilter {
|
|
217
|
+
/** Keep flows carrying at least one of these `@tags`. */
|
|
218
|
+
tags?: readonly string[];
|
|
219
|
+
/** Keep flows whose title contains this text, case-insensitively. */
|
|
220
|
+
flow?: string;
|
|
221
|
+
/** Keep steps whose title contains this text, case-insensitively. */
|
|
222
|
+
step?: string;
|
|
223
|
+
}
|
|
224
|
+
//#endregion
|
|
225
|
+
//#region src/scheduler/collect.d.ts
|
|
226
|
+
/** Index the document's fragments by name for `run`. */
|
|
227
|
+
declare function collectFragments(doc: Document): Map<string, FragmentDecl>;
|
|
228
|
+
//#endregion
|
|
229
|
+
//#region src/scheduler/create-cleanup-list.d.ts
|
|
230
|
+
/**
|
|
231
|
+
* The runtime's own sink, for a host that does not bring one.
|
|
232
|
+
*
|
|
233
|
+
* Closing runs newest first and survives a cleanup that throws: a program on its
|
|
234
|
+
* way out still has to hand back everything else it was holding.
|
|
235
|
+
*/
|
|
236
|
+
declare function createCleanupList(): CleanupList;
|
|
237
|
+
//#endregion
|
|
238
|
+
//#region src/scheduler/filter.d.ts
|
|
239
|
+
/** A title matches when the needle is absent, or contained case-insensitively. */
|
|
240
|
+
declare function matchesTitle(title: string, needle: string | undefined): boolean;
|
|
241
|
+
//#endregion
|
|
242
|
+
//#region src/check/check-imports.d.ts
|
|
243
|
+
/**
|
|
244
|
+
* Check every name a file imports against what the file it names publishes.
|
|
245
|
+
* Otherwise a misspelt import stays quietly `undefined` until something calls
|
|
246
|
+
* it, and the run blames the call site rather than the import.
|
|
247
|
+
*
|
|
248
|
+
* @param args The importing document, its URI, and the resolved import graph.
|
|
249
|
+
* @returns One `VN2009` problem per name the target does not publish.
|
|
250
|
+
*/
|
|
251
|
+
declare function checkImports(args: {
|
|
252
|
+
document: Document;
|
|
253
|
+
uri: string;
|
|
254
|
+
graph: ImportGraph;
|
|
255
|
+
}): Problem[];
|
|
256
|
+
//#endregion
|
|
257
|
+
//#region src/decorators/builtin-decorators.d.ts
|
|
258
|
+
/**
|
|
259
|
+
* The decorators the language ships with, written the same way anyone else's
|
|
260
|
+
* are. They go through the same expansion as a plugin decorator and leave
|
|
261
|
+
* metadata on the node, because `@retry(2)` says something the grammar has no
|
|
262
|
+
* other word for. Keeping them here rather than as special cases in the
|
|
263
|
+
* scheduler is what makes the built-ins a stdlib instead of reserved words.
|
|
264
|
+
*/
|
|
265
|
+
declare const builtinDecorators: readonly DecoratorDefinition[];
|
|
266
|
+
//#endregion
|
|
267
|
+
//#region src/decorators/create-decorator-source.d.ts
|
|
268
|
+
/**
|
|
269
|
+
* Every decorator this run understands: the ones the language ships with, plus
|
|
270
|
+
* whatever the loaded plugins contribute.
|
|
271
|
+
*
|
|
272
|
+
* A plugin's decorator overrides a built-in of the same name on purpose. The
|
|
273
|
+
* built-ins are a stdlib, not a reserved word list, and a project that wants its
|
|
274
|
+
* own `@retry` is entitled to it.
|
|
275
|
+
*
|
|
276
|
+
* @param plugins The plugins loaded for this run, in load order.
|
|
277
|
+
* @returns A source that looks a decorator up by name.
|
|
278
|
+
*/
|
|
279
|
+
declare function createDecoratorSource(plugins: readonly PluginDefinition[]): DecoratorSource;
|
|
280
|
+
//#endregion
|
|
281
|
+
//#region src/ports/port-resolver.types.d.ts
|
|
282
|
+
/** A port paired with the implementation a host/CLI chose to bind. */
|
|
283
|
+
interface PortBinding {
|
|
284
|
+
port: AnyPort;
|
|
285
|
+
impl: unknown;
|
|
286
|
+
}
|
|
287
|
+
/** Resolves a port descriptor to its bound, negotiated implementation. */
|
|
288
|
+
interface PortResolver {
|
|
289
|
+
resolve<T>(port: Port<T>): T;
|
|
290
|
+
}
|
|
291
|
+
//#endregion
|
|
292
|
+
//#region src/ports/create-port-resolver.d.ts
|
|
293
|
+
/**
|
|
294
|
+
* Resolve ports from a set of bindings, running capability and shape negotiation
|
|
295
|
+
* at the moment of resolution.
|
|
296
|
+
*
|
|
297
|
+
* @param args.bindings Every port the host chose to bind, with its implementation.
|
|
298
|
+
* @param args.caps What this host offers, checked against each port's `requires`.
|
|
299
|
+
* @returns A resolver whose `resolve` throws `VN7002` when the port is unbound,
|
|
300
|
+
* and whatever `bindPort` raises when the capability or shape check fails.
|
|
301
|
+
*/
|
|
302
|
+
declare function createPortResolver(args: {
|
|
303
|
+
bindings: readonly PortBinding[];
|
|
304
|
+
caps: readonly HostCapability[];
|
|
305
|
+
}): PortResolver;
|
|
306
|
+
//#endregion
|
|
307
|
+
//#region src/run/runner.types.d.ts
|
|
308
|
+
/** What one run reports back to the host that asked for it. */
|
|
309
|
+
interface RunResult {
|
|
310
|
+
run: RunId;
|
|
311
|
+
/** What the decorators refused before a statement ran. */
|
|
312
|
+
problems?: Problem[];
|
|
313
|
+
passed: number;
|
|
314
|
+
failed: number;
|
|
315
|
+
/**
|
|
316
|
+
* What `exit` asked the host to end with, absent if nothing called it. It
|
|
317
|
+
* overrides the tally on purpose: `exit 0` is a clean ending, `exit 3` is a
|
|
318
|
+
* failure the program named itself.
|
|
319
|
+
*/
|
|
320
|
+
exitCode?: number;
|
|
321
|
+
}
|
|
322
|
+
/** The level-2 embedding API (§18): a host owns the process and drives runs. */
|
|
323
|
+
interface Runner {
|
|
324
|
+
/** Test mode: collect and run every `flow`, reporting each. */
|
|
325
|
+
run(document: Document): Promise<RunResult>;
|
|
326
|
+
/** Script mode: execute the file's top-level statements, top to bottom. */
|
|
327
|
+
script(document: Document): Promise<RunResult>;
|
|
328
|
+
}
|
|
329
|
+
/** Everything {@link Runner} needs, settled once and reused for every run. */
|
|
330
|
+
interface RunnerArgs {
|
|
331
|
+
host: Host;
|
|
332
|
+
plugins: readonly PluginDefinition[];
|
|
333
|
+
sink: EventSink;
|
|
334
|
+
ports?: readonly PortBinding[];
|
|
335
|
+
uri?: string;
|
|
336
|
+
/** Which flows and steps to include (`--tags`, `--flow`, `--step`). */
|
|
337
|
+
filter?: RunFilter;
|
|
338
|
+
/** Stop after the first flow that fails. */
|
|
339
|
+
bail?: boolean;
|
|
340
|
+
env?: Record<string, unknown>;
|
|
341
|
+
moduleFragments?: Map<string, FragmentDecl>;
|
|
342
|
+
/**
|
|
343
|
+
* The files the import graph reached, so a `pub fn` can be called with the
|
|
344
|
+
* module it was written in around it. Without this the name resolves and the
|
|
345
|
+
* call fails on its first line.
|
|
346
|
+
*/
|
|
347
|
+
modules?: ImportGraph;
|
|
348
|
+
/** The `pub deco`s the imported files exported, so `@name` resolves across a file. */
|
|
349
|
+
moduleDecos?: Map<string, ImportedDeco>;
|
|
350
|
+
/**
|
|
351
|
+
* Where a script-mode program registers what it opened. The host owns when a
|
|
352
|
+
* program ends, so the host owns this list; without one the run keeps its own
|
|
353
|
+
* and nothing closes until the process does.
|
|
354
|
+
*/
|
|
355
|
+
cleanup?: CleanupSink;
|
|
356
|
+
}
|
|
357
|
+
//#endregion
|
|
358
|
+
//#region src/run/create-runner.d.ts
|
|
359
|
+
/**
|
|
360
|
+
* Build a runner: negotiate plugins and wire ports once, then reuse them for
|
|
361
|
+
* every run.
|
|
362
|
+
*
|
|
363
|
+
* @param args The host, the plugins, the event sink and the per-run options.
|
|
364
|
+
* @returns A runner exposing test mode (`run`) and script mode (`script`).
|
|
365
|
+
* @throws VennError `VN2010` when a plugin requires a capability the host lacks.
|
|
366
|
+
*/
|
|
367
|
+
declare function createRunner(args: RunnerArgs): Runner;
|
|
368
|
+
//#endregion
|
|
369
|
+
//#region src/run/resolve-imports.d.ts
|
|
370
|
+
/** Read source by URI and resolve a specifier relative to a base URI. */
|
|
371
|
+
interface ModuleIo {
|
|
372
|
+
read: (uri: string) => Promise<string>;
|
|
373
|
+
resolve: (base: string, spec: string) => string;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Loading a package that was installed rather than written here.
|
|
377
|
+
*
|
|
378
|
+
* Kept apart from {@link ModuleIo} because the two answer different questions:
|
|
379
|
+
* one reads `.vn` source to be parsed, the other hands back a module that is
|
|
380
|
+
* already a value. A host without one simply has no packages, which is the state
|
|
381
|
+
* of every run in a Web Worker and not an error.
|
|
382
|
+
*/
|
|
383
|
+
interface NpmModules {
|
|
384
|
+
load(spec: string): Promise<Record<string, unknown> | undefined>;
|
|
385
|
+
}
|
|
386
|
+
/** What a run needs from the files it reaches: their fragments, decos and plugins. */
|
|
387
|
+
interface ResolvedImports {
|
|
388
|
+
fragments: Map<string, FragmentDecl>;
|
|
389
|
+
/** The `pub deco`s reachable through the import graph, with the file each came from. */
|
|
390
|
+
decos: Map<string, ImportedDeco>;
|
|
391
|
+
/** Every package `use`d anywhere in the graph, so only those need loading. */
|
|
392
|
+
packages: Set<string>;
|
|
393
|
+
/**
|
|
394
|
+
* What each npm specifier loaded to, by the name that was written.
|
|
395
|
+
*
|
|
396
|
+
* Loaded here, before anything runs, because binding a scope cannot wait: by
|
|
397
|
+
* the time a name is looked up the module has to already be a value.
|
|
398
|
+
*/
|
|
399
|
+
npm: Map<string, Record<string, unknown>>;
|
|
400
|
+
/**
|
|
401
|
+
* Every module reached, parsed, keyed by its resolved URI.
|
|
402
|
+
*
|
|
403
|
+
* Carried whole rather than reduced to a list of exported names, because a
|
|
404
|
+
* `pub fn` is a closure over the file it was written in: it calls that file's
|
|
405
|
+
* private helpers and reads that file's globals. Handing over the function
|
|
406
|
+
* without the place it came from produces something that resolves and then
|
|
407
|
+
* fails on its first line.
|
|
408
|
+
*/
|
|
409
|
+
modules: Map<string, Document>;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Walk the import graph from one document, parsing every `.vn` file it reaches
|
|
413
|
+
* and loading every package it names. A file already seen is skipped, so a cycle
|
|
414
|
+
* ends rather than loops. A file that cannot be read is skipped in silence:
|
|
415
|
+
* whoever tried to read it reports the failure.
|
|
416
|
+
*
|
|
417
|
+
* @param args The entry document, its URI, the source reader and the optional
|
|
418
|
+
* package loader.
|
|
419
|
+
* @returns The exported fragments and decos, the packages, the loaded npm
|
|
420
|
+
* modules and every parsed document, keyed by resolved URI.
|
|
421
|
+
*/
|
|
422
|
+
declare function resolveImports(args: {
|
|
423
|
+
document: Document;
|
|
424
|
+
uri: string;
|
|
425
|
+
io: ModuleIo;
|
|
426
|
+
/** Absent when the host has no way to load one: a Worker, most tests. */
|
|
427
|
+
npm?: NpmModules;
|
|
428
|
+
}): Promise<ResolvedImports>;
|
|
429
|
+
/**
|
|
430
|
+
* Add the packages a file declares with `use` to `into`. Collected across the
|
|
431
|
+
* whole graph: a fragment imported from elsewhere calls the verbs *its* file
|
|
432
|
+
* asked for.
|
|
433
|
+
*
|
|
434
|
+
* @param document The file to read `use` declarations from.
|
|
435
|
+
* @param into The accumulating set of package specifiers, mutated in place.
|
|
436
|
+
*/
|
|
437
|
+
declare function collectUses(document: Document, into: Set<string>): void;
|
|
438
|
+
//#endregion
|
|
439
|
+
//#region src/types/create-type-catalog.d.ts
|
|
440
|
+
/**
|
|
441
|
+
* Turn what the loaded plugins publish into what the checker can ask.
|
|
442
|
+
*
|
|
443
|
+
* This is the seam the core deliberately does not cross: `@venn-lang/core` knows
|
|
444
|
+
* nothing about plugins and gets told. Names are qualified here, once: a plugin
|
|
445
|
+
* says `Request` and a flow writes `http.Request`.
|
|
446
|
+
*
|
|
447
|
+
* @param plugins The plugins loaded for this run.
|
|
448
|
+
* @returns A catalog answering a type name or an action's signature.
|
|
449
|
+
*/
|
|
450
|
+
declare function createTypeCatalog(plugins: readonly PluginDefinition[]): TypeCatalog;
|
|
451
|
+
//#endregion
|
|
452
|
+
export { type CheckArgs, type Cleanup, type CleanupList, type CleanupSink, type Emitter, type EventSink, EventSinkPort, type MemorySink, type ModuleIo, type NpmModules, type PortBinding, type PortResolver, type Registry, type ResolvedAction, type ResolvedImports, type ResolvedMatcher, type RunFilter, type RunResult, type Runner, type RunnerArgs, type Scope, buildRegistry, builtinDecorators, checkDocument, checkFragmentCall, checkImports, collectFragments, collectUses, createCleanupList, createDecoratorSource, createEmitter, createMemorySink, createNdjsonSink, createPortResolver, createRunner, createScope, createTypeCatalog, matchesTitle, newRunId, resolveImports };
|
|
453
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/registry/registry.types.ts","../src/registry/build-registry.ts","../src/check/check.types.ts","../src/check/check-document.ts","../src/check/check-fragment-call.ts","../src/eventsink/event-sink.types.ts","../src/eventsink/event-sink.port.ts","../src/eventsink/memory-sink.ts","../src/eventsink/ndjson-sink.ts","../src/emit/emitter.types.ts","../src/emit/create-emitter.ts","../src/emit/run-id.ts","../src/scope/scope.types.ts","../src/scope/create-scope.ts","../src/scheduler/bind-imports.ts","../src/scheduler/cleanup.types.ts","../src/scheduler/filter.types.ts","../src/scheduler/collect.ts","../src/scheduler/create-cleanup-list.ts","../src/scheduler/filter.ts","../src/check/check-imports.ts","../src/decorators/builtin-decorators.ts","../src/decorators/create-decorator-source.ts","../src/ports/port-resolver.types.ts","../src/ports/create-port-resolver.ts","../src/run/runner.types.ts","../src/run/create-runner.ts","../src/run/resolve-imports.ts","../src/types/create-type-catalog.ts"],"mappings":";;;;;UAGiB;EACf,QAAQ;EACR,QAAQ;;;UAIO;EACf,QAAQ;EACR,SAAS;;;UAIM;EACf,OAAO;IAAQ;IAAmB;MAAiB;EACnD,QAAQ,eAAe;EACvB,aAAa;;EAEb,YAAY;;EAEZ;IAAsB;IAAmB;IAAc,QAAQ;;;;;;;;;;;;;iBCVjD,cAAc;EAC5B,kBAAkB;EAClB,eAAe;IACb;;;;UCXa;EACf,UAAU;EACV,UAAU;EACV,WAAW;EACX;;;;;;EAMA;;;UAIe;EACf,UAAU;EACV,WAAW;EACX,SAAS;;EAET,UAAU;;EAEV,OAAO;;EAEP,MAAM;EACN;;;;;;;;;;;;iBCSc,cAAc,MAAM,YAAY;;;;;;;;;;;;;;;;iBCpBhC,kBAAkB,MAAM,MAAM,KAAK,eAAe;;;;UCdjD;EACf,KAAK,UAAU;;;UAIA,mBAAmB;WACzB,oBAAoB;;;;;;;;cCFlB,eAAe,KAAK;;;;;;;;iBCCjB,oBAAoB;;;;;;;;;;iBCCpB,iBAAiB;EAAQ,QAAQ;IAA0B;;;;UCN1D;EACf,KAAK,UAAU,WAAW;IAAQ,MAAM;IAAG,MAAM,UAAU;IAAI,OAAO;;;;;;iBCExD,cAAc;EAAQ,MAAM;EAAW,KAAK;EAAO,OAAO;IAAU;;;;;;;iBCCpE,SAAS;EAAQ,OAAO;EAAO,QAAQ;IAAW;;;;;;;;;UCCjD,cAAc;EAC7B,IAAI,cAAc;EAClB,SAAS;;;;;;;;;iBCsDK,YAAY,SAAS,QAAQ;;;;UCrD5B;EACf,SAAS,oBAAoB;EAC7B,UAAU,cAAc;;EAExB,MAAM,oBAAoB;;;;;KCdhB,gBAAgB;;;;;;;;UASX;EACf,IAAI,SAAS;;;UAIE,oBAAoB;EACnC,SAAS;;;;;UCfM;;EAEf;;EAEA;;EAEA;;;;;iBCac,iBAAiB,KAAK,WAAW,YAAY;;;;;;;;;iBCZ7C,qBAAqB;;;;iBCPrB,aAAa,eAAe;;;;;;;;;;;iBCqB5B,aAAa;EAC3B,UAAU;EACV;EACA,OAAO;IACL;;;;;;;;;;cCbS,4BAA4B;;;;;;;;;;;;;;iBCEzB,sBAAsB,kBAAkB,qBAAqB;;;;UCZ5D;EACf,MAAM;EACN;;;UAIe;EACf,QAAQ,GAAG,MAAM,KAAK,KAAK;;;;;;;;;;;;;iBCEb,mBAAmB;EACjC,mBAAmB;EACnB,eAAe;IACb;;;;UCNa;EACf,KAAK;;EAEL,WAAW;EACX;EACA;;;;;;EAMA;;;UAIe;;EAEf,IAAI,UAAU,WAAW,QAAQ;;EAEjC,OAAO,UAAU,WAAW,QAAQ;;;UAIrB;EACf,MAAM;EACN,kBAAkB;EAClB,MAAM;EACN,iBAAiB;EACjB;;EAEA,SAAS;;EAET;EACA,MAAM;EACN,kBAAkB,YAAY;;;;;;EAM9B,UAAU;;EAEV,cAAc,YAAY;;;;;;EAM1B,UAAU;;;;;;;;;;;;iBCzBI,aAAa,MAAM,aAAa;;;;UCnB/B;EACf,OAAO,gBAAgB;EACvB,UAAU,cAAc;;;;;;;;;;UAWT;EACf,KAAK,eAAe,QAAQ;;;UAIb;EACf,WAAW,YAAY;;EAEvB,OAAO,YAAY;;EAEnB,UAAU;;;;;;;EAOV,KAAK,YAAY;;;;;;;;;;EAUjB,SAAS,YAAY;;;;;;;;;;;;;iBAcD,eAAe;EACnC,UAAU;EACV;EACA,IAAI;;EAEJ,MAAM;IACJ,QAAQ;;;;;;;;;iBA4BI,YAAY,UAAU,UAAU,MAAM;;;;;;;;;;;;;iBCjFtC,kBAAkB,kBAAkB,qBAAqB"}
|