@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.
Files changed (104) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +158 -0
  3. package/dist/index.d.ts +453 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +3314 -0
  6. package/dist/index.js.map +1 -0
  7. package/package.json +56 -0
  8. package/src/check/check-calls.ts +82 -0
  9. package/src/check/check-deco-body.ts +77 -0
  10. package/src/check/check-document.ts +106 -0
  11. package/src/check/check-env.ts +96 -0
  12. package/src/check/check-fragment-call.ts +27 -0
  13. package/src/check/check-imports.ts +82 -0
  14. package/src/check/check-interpolation.ts +58 -0
  15. package/src/check/check-options.ts +18 -0
  16. package/src/check/check-uncalled.ts +42 -0
  17. package/src/check/check.types.ts +30 -0
  18. package/src/check/index.ts +4 -0
  19. package/src/context/action-context.ts +20 -0
  20. package/src/context/index.ts +1 -0
  21. package/src/decorators/builtin-decorators.ts +87 -0
  22. package/src/decorators/create-decorator-source.ts +25 -0
  23. package/src/decorators/index.ts +2 -0
  24. package/src/emit/create-emitter.ts +16 -0
  25. package/src/emit/emitter.types.ts +6 -0
  26. package/src/emit/index.ts +3 -0
  27. package/src/emit/run-id.ts +11 -0
  28. package/src/eventsink/event-sink.port.ts +13 -0
  29. package/src/eventsink/event-sink.types.ts +11 -0
  30. package/src/eventsink/index.ts +4 -0
  31. package/src/eventsink/memory-sink.ts +17 -0
  32. package/src/eventsink/ndjson-sink.ts +14 -0
  33. package/src/index.ts +14 -0
  34. package/src/ports/create-port-resolver.ts +39 -0
  35. package/src/ports/index.ts +2 -0
  36. package/src/ports/port-resolver.types.ts +12 -0
  37. package/src/registry/build-registry.ts +76 -0
  38. package/src/registry/index.ts +2 -0
  39. package/src/registry/registry.types.ts +24 -0
  40. package/src/run/create-runner.ts +103 -0
  41. package/src/run/index.ts +4 -0
  42. package/src/run/resolve-imports.ts +166 -0
  43. package/src/run/runner.types.ts +67 -0
  44. package/src/scheduler/absorb-exit.ts +19 -0
  45. package/src/scheduler/aliases.ts +44 -0
  46. package/src/scheduler/annotations.ts +48 -0
  47. package/src/scheduler/base-scope.ts +25 -0
  48. package/src/scheduler/bind-globals.ts +55 -0
  49. package/src/scheduler/bind-imports.ts +130 -0
  50. package/src/scheduler/bind-namespaces.ts +61 -0
  51. package/src/scheduler/bind-prelude.ts +11 -0
  52. package/src/scheduler/block-plan.ts +66 -0
  53. package/src/scheduler/branch-engine.ts +13 -0
  54. package/src/scheduler/call-params.ts +140 -0
  55. package/src/scheduler/cleanup.types.ts +18 -0
  56. package/src/scheduler/collect.ts +60 -0
  57. package/src/scheduler/concurrency.ts +16 -0
  58. package/src/scheduler/create-cleanup-list.ts +17 -0
  59. package/src/scheduler/declared-arity.ts +13 -0
  60. package/src/scheduler/engine.types.ts +50 -0
  61. package/src/scheduler/filter.ts +5 -0
  62. package/src/scheduler/filter.types.ts +9 -0
  63. package/src/scheduler/flaky.ts +32 -0
  64. package/src/scheduler/flaky.types.ts +7 -0
  65. package/src/scheduler/index.ts +16 -0
  66. package/src/scheduler/invocation.ts +103 -0
  67. package/src/scheduler/local-call.ts +28 -0
  68. package/src/scheduler/node-span.ts +29 -0
  69. package/src/scheduler/opts-text.ts +10 -0
  70. package/src/scheduler/opts.ts +14 -0
  71. package/src/scheduler/pending.types.ts +9 -0
  72. package/src/scheduler/run-action.ts +163 -0
  73. package/src/scheduler/run-around.ts +23 -0
  74. package/src/scheduler/run-attempts.ts +105 -0
  75. package/src/scheduler/run-bindings.ts +67 -0
  76. package/src/scheduler/run-block.ts +65 -0
  77. package/src/scheduler/run-document.ts +181 -0
  78. package/src/scheduler/run-expect.ts +48 -0
  79. package/src/scheduler/run-flow.ts +69 -0
  80. package/src/scheduler/run-foreach.ts +148 -0
  81. package/src/scheduler/run-group.ts +9 -0
  82. package/src/scheduler/run-if.ts +21 -0
  83. package/src/scheduler/run-lifecycle.ts +86 -0
  84. package/src/scheduler/run-matcher.ts +99 -0
  85. package/src/scheduler/run-parallel.ts +68 -0
  86. package/src/scheduler/run-prologue.ts +59 -0
  87. package/src/scheduler/run-race.ts +20 -0
  88. package/src/scheduler/run-repeat.ts +54 -0
  89. package/src/scheduler/run-run.ts +41 -0
  90. package/src/scheduler/run-script.ts +48 -0
  91. package/src/scheduler/run-statements.ts +107 -0
  92. package/src/scheduler/run-step.ts +76 -0
  93. package/src/scheduler/run-try.ts +34 -0
  94. package/src/scheduler/run-while.ts +50 -0
  95. package/src/scheduler/script-lifecycle.ts +47 -0
  96. package/src/scheduler/settled.ts +20 -0
  97. package/src/scheduler/signals.ts +33 -0
  98. package/src/scheduler/target.ts +30 -0
  99. package/src/scheduler/unknown-option.ts +87 -0
  100. package/src/scope/create-scope.ts +67 -0
  101. package/src/scope/index.ts +2 -0
  102. package/src/scope/scope.types.ts +12 -0
  103. package/src/types/create-type-catalog.ts +70 -0
  104. 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.
@@ -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"}