@telorun/sdk 0.10.0 → 0.12.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 +2 -2
- package/README.md +0 -10
- package/dist/capabilities/provider.d.ts +2 -2
- package/dist/capabilities/provider.d.ts.map +1 -1
- package/dist/capability-definition.d.ts +8 -0
- package/dist/capability-definition.d.ts.map +1 -0
- package/dist/capability-definition.js +21 -0
- package/dist/cel-environment.d.ts +3 -0
- package/dist/cel-environment.d.ts.map +1 -0
- package/dist/cel-environment.js +13 -0
- package/dist/execution-context.d.ts +13 -0
- package/dist/execution-context.d.ts.map +1 -0
- package/dist/execution-context.js +13 -0
- package/dist/resource-instance.d.ts +2 -1
- package/dist/resource-instance.d.ts.map +1 -1
- package/dist/stream.d.ts +21 -4
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +39 -5
- package/package.json +1 -1
- package/src/capabilities/provider.ts +2 -2
- package/src/resource-instance.ts +3 -1
- package/src/stream.ts +49 -4
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SUSTAINABLE USE LICENSE (Fair-code)
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2026
|
|
3
|
+
Copyright (c) 2026 CodeNet Sp. z o.o.
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to use, copy, modify, and distribute the Software for any purpose—including commercial purposes—subject to the following conditions:
|
|
6
6
|
|
|
@@ -14,4 +14,4 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
|
14
14
|
|
|
15
15
|
5. DISCLAIMER: The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the Software.
|
|
16
16
|
|
|
17
|
-
For commercial licensing, managed hosting exemptions, or enterprise inquiries, please contact
|
|
17
|
+
For commercial licensing, managed hosting exemptions, or enterprise inquiries, please contact <contact@codenet.pl>.
|
package/README.md
CHANGED
|
@@ -8,10 +8,6 @@ The Node.js SDK provides the authoring surface for Telo modules. It defines the
|
|
|
8
8
|
- **Context types** for accessing the kernel, registry, and events.
|
|
9
9
|
- **Shared primitives** used by Telo modules and tooling.
|
|
10
10
|
|
|
11
|
-
## Status
|
|
12
|
-
|
|
13
|
-
Early prototype. APIs and contracts are still evolving. The API surface - including YAML shapes - may change at any time without notice.
|
|
14
|
-
|
|
15
11
|
## When to Use It
|
|
16
12
|
|
|
17
13
|
Use the SDK when building or extending Telo modules. It is not the kernel itself; it is the contract layer that keeps module behavior consistent and predictable.
|
|
@@ -69,9 +65,3 @@ throws:
|
|
|
69
65
|
```
|
|
70
66
|
|
|
71
67
|
`inherit` is driven by the analyzer's dataflow pass over `x-telo-step-context` arrays; future composers opt in by declaring both the annotation and `inherit: true`. See [modules/run/docs/structured-errors.md](../../modules/run/docs/structured-errors.md) for the end-to-end flow.
|
|
72
|
-
|
|
73
|
-
## Related Docs
|
|
74
|
-
|
|
75
|
-
- Kernel overview: [kernel/README.md](../../kernel/README.md)
|
|
76
|
-
- Built‑in modules: [modules/](../../modules/)
|
|
77
|
-
- SDKs index: [sdk/README.md](../README.md)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/capabilities/provider.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/capabilities/provider.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ,CAAC,OAAO,GAAG,OAAO;IACzC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7B"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CapabilityDefinition } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Factory that wires the declarative `expand` config on a CapabilityDefinition
|
|
4
|
+
* into the `onManifest` and `onInvoke` lifecycle hooks. The kernel only ever
|
|
5
|
+
* calls these hooks — it has no knowledge of the `expand` config.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createCapability(def: CapabilityDefinition): CapabilityDefinition;
|
|
8
|
+
//# sourceMappingURL=capability-definition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-definition.d.ts","sourceRoot":"","sources":["../src/capability-definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGvD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,oBAAoB,GAAG,oBAAoB,CAwBhF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory that wires the declarative `expand` config on a CapabilityDefinition
|
|
3
|
+
* into the `onManifest` and `onInvoke` lifecycle hooks. The kernel only ever
|
|
4
|
+
* calls these hooks — it has no knowledge of the `expand` config.
|
|
5
|
+
*/
|
|
6
|
+
export function createCapability(def) {
|
|
7
|
+
const compile = def.expand?.compile ?? [];
|
|
8
|
+
const runtime = def.expand?.runtime ?? [];
|
|
9
|
+
return {
|
|
10
|
+
...def,
|
|
11
|
+
onManifest: compile.length
|
|
12
|
+
? (manifest, ctx) => ctx.expandPaths(manifest, compile, runtime)
|
|
13
|
+
: def.onManifest,
|
|
14
|
+
onInvoke: runtime.length
|
|
15
|
+
? async (instance, inputs, ctx) => {
|
|
16
|
+
const expanded = ctx.moduleContext.expandPaths(inputs, runtime);
|
|
17
|
+
return instance.invoke(expanded);
|
|
18
|
+
}
|
|
19
|
+
: def.onInvoke,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cel-environment.d.ts","sourceRoot":"","sources":["../src/cel-environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,eAAO,MAAM,cAAc,aAWvB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Environment } from "@marcbachmann/cel-js";
|
|
2
|
+
export const celEnvironment = new Environment({ unlistedVariablesAreDyn: true })
|
|
3
|
+
.registerFunction("join(list, string): string", (list, sep) => list.map(String).join(sep))
|
|
4
|
+
.registerFunction("keys(map): list", (map) => {
|
|
5
|
+
if (map instanceof Map)
|
|
6
|
+
return [...map.keys()];
|
|
7
|
+
return Object.keys(map);
|
|
8
|
+
})
|
|
9
|
+
.registerFunction("values(map): list", (map) => {
|
|
10
|
+
if (map instanceof Map)
|
|
11
|
+
return [...map.values()];
|
|
12
|
+
return Object.values(map);
|
|
13
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { EvaluationContext } from "./evaluation-context.js";
|
|
2
|
+
import { ModuleContext } from "./module-context.js";
|
|
3
|
+
/**
|
|
4
|
+
* The ephemeral, per-trigger context layer. Merges a ModuleContext with
|
|
5
|
+
* arbitrary execution-time properties (e.g. { request, inputs } for HTTP;
|
|
6
|
+
* any shape is valid — determined by the trigger type).
|
|
7
|
+
*
|
|
8
|
+
* Execution props overlay the module namespaces on key conflict.
|
|
9
|
+
*/
|
|
10
|
+
export declare class ExecutionContext extends EvaluationContext {
|
|
11
|
+
constructor(moduleCtx: ModuleContext, execProps: Record<string, unknown>);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=execution-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution-context.d.ts","sourceRoot":"","sources":["../src/execution-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD;;;;;;GAMG;AACH,qBAAa,gBAAiB,SAAQ,iBAAiB;gBACzC,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CASzE"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { EvaluationContext } from "./evaluation-context.js";
|
|
2
|
+
/**
|
|
3
|
+
* The ephemeral, per-trigger context layer. Merges a ModuleContext with
|
|
4
|
+
* arbitrary execution-time properties (e.g. { request, inputs } for HTTP;
|
|
5
|
+
* any shape is valid — determined by the trigger type).
|
|
6
|
+
*
|
|
7
|
+
* Execution props overlay the module namespaces on key conflict.
|
|
8
|
+
*/
|
|
9
|
+
export class ExecutionContext extends EvaluationContext {
|
|
10
|
+
constructor(moduleCtx, execProps) {
|
|
11
|
+
super(moduleCtx.source, Object.assign(Object.create(null), moduleCtx.context, execProps), moduleCtx.createInstance, moduleCtx.secretValues, moduleCtx.emit);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Invocable } from "./capabilities/invokable.js";
|
|
2
|
+
import type { Provider } from "./capabilities/provider.js";
|
|
2
3
|
import type { Runnable } from "./capabilities/runnable.js";
|
|
3
4
|
import type { ResourceContext } from "./resource-context.js";
|
|
4
|
-
export type ResourceInstance<TInput = Record<string, any>, TOutput = any> = Partial<Invocable<TInput, TOutput>> & Partial<Runnable> & {
|
|
5
|
+
export type ResourceInstance<TInput = Record<string, any>, TOutput = any> = Partial<Invocable<TInput, TOutput>> & Partial<Runnable> & Partial<Provider<TOutput>> & {
|
|
5
6
|
init?(ctx?: ResourceContext): Promise<void>;
|
|
6
7
|
teardown?(): void | Promise<void>;
|
|
7
8
|
snapshot?(): Record<string, any> | Promise<Record<string, any>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource-instance.d.ts","sourceRoot":"","sources":["../src/resource-instance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,MAAM,gBAAgB,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,GAAG,GAAG,IAAI,OAAO,CACjF,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAC3B,GACC,OAAO,CAAC,QAAQ,CAAC,GAAG;
|
|
1
|
+
{"version":3,"file":"resource-instance.d.ts","sourceRoot":"","sources":["../src/resource-instance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,MAAM,gBAAgB,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,GAAG,GAAG,IAAI,OAAO,CACjF,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAC3B,GACC,OAAO,CAAC,QAAQ,CAAC,GACjB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,GAAG;IAC3B,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,QAAQ,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,QAAQ,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;CACjE,CAAC"}
|
package/dist/stream.d.ts
CHANGED
|
@@ -11,6 +11,18 @@
|
|
|
11
11
|
* resulting value a real-class constructor that cel-js can register and
|
|
12
12
|
* recognize, so `${{ steps.X.result.output }}` evaluations pass through cleanly.
|
|
13
13
|
*
|
|
14
|
+
* Singleton across sdk copies: cel-js identifies registered types by
|
|
15
|
+
* constructor identity (`v.constructor === RegisteredCtor`). The kernel and
|
|
16
|
+
* any npm-loaded controller can — and routinely do — resolve `@telorun/sdk`
|
|
17
|
+
* to different installs (workspace vs `.telo/npm/<hash>/...`), so two `Stream`
|
|
18
|
+
* classes with the same shape but different identity would silently break
|
|
19
|
+
* stream-typed CEL evaluations with "Unsupported type: Stream". The first
|
|
20
|
+
* `@telorun/sdk` copy to load registers its `Stream` class on `globalThis`
|
|
21
|
+
* under a stable `Symbol.for("@telorun/sdk:Stream")` key; later copies discard
|
|
22
|
+
* their local declaration at export time and re-export the registered one.
|
|
23
|
+
* Every Stream value in the process shares one constructor regardless of
|
|
24
|
+
* install topology — no build artifact or `file:` symlink required.
|
|
25
|
+
*
|
|
14
26
|
* The companion analyzer registers `Stream` as a CEL object type with no
|
|
15
27
|
* fields — terminal access (passing the value through) succeeds, member access
|
|
16
28
|
* (`result.output.text`, `result.output[0]`) raises a CEL error at runtime,
|
|
@@ -24,9 +36,14 @@
|
|
|
24
36
|
* patterns work without unwrapping. Internally it forwards `Symbol.asyncIterator`
|
|
25
37
|
* to the underlying iterable.
|
|
26
38
|
*/
|
|
27
|
-
|
|
28
|
-
private readonly source;
|
|
29
|
-
constructor(source: AsyncIterable<T>);
|
|
30
|
-
[Symbol.asyncIterator](): AsyncIterator<T>;
|
|
39
|
+
interface Stream<T = unknown> extends AsyncIterable<T> {
|
|
31
40
|
}
|
|
41
|
+
declare const LocalStream: {
|
|
42
|
+
new <T = unknown>(source: AsyncIterable<T>): {
|
|
43
|
+
"__#private@#source": AsyncIterable<T>;
|
|
44
|
+
[Symbol.asyncIterator](): AsyncIterator<T>;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
declare const Stream: typeof LocalStream;
|
|
48
|
+
export { Stream };
|
|
32
49
|
//# sourceMappingURL=stream.d.ts.map
|
package/dist/stream.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAIH,UAAU,MAAM,CAAC,CAAC,GAAG,OAAO,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC;CAAG;AAOzD,QAAA,MAAM,WAAW;SAAgB,CAAC,oBAMZ,aAAa,CAAC,CAAC,CAAC;8BAF3B,aAAa,CAAC,CAAC,CAAC;kCAMC,aAAa,CAAC,CAAC,CAAC;;CAG3C,CAAC;AAUF,QAAA,MAAM,MAAM,EAAE,OAAO,WAA0D,CAAC;AAMhF,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
package/dist/stream.js
CHANGED
|
@@ -11,6 +11,18 @@
|
|
|
11
11
|
* resulting value a real-class constructor that cel-js can register and
|
|
12
12
|
* recognize, so `${{ steps.X.result.output }}` evaluations pass through cleanly.
|
|
13
13
|
*
|
|
14
|
+
* Singleton across sdk copies: cel-js identifies registered types by
|
|
15
|
+
* constructor identity (`v.constructor === RegisteredCtor`). The kernel and
|
|
16
|
+
* any npm-loaded controller can — and routinely do — resolve `@telorun/sdk`
|
|
17
|
+
* to different installs (workspace vs `.telo/npm/<hash>/...`), so two `Stream`
|
|
18
|
+
* classes with the same shape but different identity would silently break
|
|
19
|
+
* stream-typed CEL evaluations with "Unsupported type: Stream". The first
|
|
20
|
+
* `@telorun/sdk` copy to load registers its `Stream` class on `globalThis`
|
|
21
|
+
* under a stable `Symbol.for("@telorun/sdk:Stream")` key; later copies discard
|
|
22
|
+
* their local declaration at export time and re-export the registered one.
|
|
23
|
+
* Every Stream value in the process shares one constructor regardless of
|
|
24
|
+
* install topology — no build artifact or `file:` symlink required.
|
|
25
|
+
*
|
|
14
26
|
* The companion analyzer registers `Stream` as a CEL object type with no
|
|
15
27
|
* fields — terminal access (passing the value through) succeeds, member access
|
|
16
28
|
* (`result.output.text`, `result.output[0]`) raises a CEL error at runtime,
|
|
@@ -24,12 +36,34 @@
|
|
|
24
36
|
* patterns work without unwrapping. Internally it forwards `Symbol.asyncIterator`
|
|
25
37
|
* to the underlying iterable.
|
|
26
38
|
*/
|
|
27
|
-
|
|
28
|
-
|
|
39
|
+
// Value binding (private): the class declaration that supplies the runtime
|
|
40
|
+
// implementation. Written as a named class expression so `.name === "Stream"`
|
|
41
|
+
// — debuggers, stack traces, and `Object.prototype.toString` all see "Stream",
|
|
42
|
+
// not the const name. The inner `Stream` identifier is only visible inside
|
|
43
|
+
// the class body (for self-reference); it does not shadow the outer interface.
|
|
44
|
+
const LocalStream = class Stream {
|
|
45
|
+
// ECMAScript private field rather than TS `private readonly` — the latter
|
|
46
|
+
// shows up in the inferred type signature, which TS then refuses to export
|
|
47
|
+
// through an anonymous class expression (TS4094).
|
|
48
|
+
#source;
|
|
29
49
|
constructor(source) {
|
|
30
|
-
this
|
|
50
|
+
this.#source = source;
|
|
31
51
|
}
|
|
32
52
|
[Symbol.asyncIterator]() {
|
|
33
|
-
return this
|
|
53
|
+
return this.#source[Symbol.asyncIterator]();
|
|
34
54
|
}
|
|
35
|
-
}
|
|
55
|
+
};
|
|
56
|
+
const STREAM_KEY = Symbol.for("@telorun/sdk:Stream");
|
|
57
|
+
const globalSlot = globalThis;
|
|
58
|
+
if (!(STREAM_KEY in globalSlot))
|
|
59
|
+
globalSlot[STREAM_KEY] = LocalStream;
|
|
60
|
+
// The exported value: whichever Stream class won the globalThis race (first
|
|
61
|
+
// sdk copy to import this module). Later copies discard their `LocalStream`
|
|
62
|
+
// at export time and route through the winner — keeping constructor identity
|
|
63
|
+
// stable across the kernel/controller realm boundary.
|
|
64
|
+
const Stream = globalSlot[STREAM_KEY];
|
|
65
|
+
// `export { Stream }` re-exports the value binding (the const above) and the
|
|
66
|
+
// type binding (the interface above) under the same name — TypeScript treats
|
|
67
|
+
// value/type as separate namespaces, so a consumer's `import { Stream }`
|
|
68
|
+
// receives both `new Stream(...)` and `Stream<T>`.
|
|
69
|
+
export { Stream };
|
package/package.json
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export interface Provider {
|
|
2
|
-
|
|
1
|
+
export interface Provider<TOutput = unknown> {
|
|
2
|
+
provide(): Promise<TOutput>;
|
|
3
3
|
}
|
package/src/resource-instance.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { Invocable } from "./capabilities/invokable.js";
|
|
2
|
+
import type { Provider } from "./capabilities/provider.js";
|
|
2
3
|
import type { Runnable } from "./capabilities/runnable.js";
|
|
3
4
|
import type { ResourceContext } from "./resource-context.js";
|
|
4
5
|
|
|
5
6
|
export type ResourceInstance<TInput = Record<string, any>, TOutput = any> = Partial<
|
|
6
7
|
Invocable<TInput, TOutput>
|
|
7
8
|
> &
|
|
8
|
-
Partial<Runnable> &
|
|
9
|
+
Partial<Runnable> &
|
|
10
|
+
Partial<Provider<TOutput>> & {
|
|
9
11
|
init?(ctx?: ResourceContext): Promise<void>;
|
|
10
12
|
teardown?(): void | Promise<void>;
|
|
11
13
|
snapshot?(): Record<string, any> | Promise<Record<string, any>>;
|
package/src/stream.ts
CHANGED
|
@@ -11,6 +11,18 @@
|
|
|
11
11
|
* resulting value a real-class constructor that cel-js can register and
|
|
12
12
|
* recognize, so `${{ steps.X.result.output }}` evaluations pass through cleanly.
|
|
13
13
|
*
|
|
14
|
+
* Singleton across sdk copies: cel-js identifies registered types by
|
|
15
|
+
* constructor identity (`v.constructor === RegisteredCtor`). The kernel and
|
|
16
|
+
* any npm-loaded controller can — and routinely do — resolve `@telorun/sdk`
|
|
17
|
+
* to different installs (workspace vs `.telo/npm/<hash>/...`), so two `Stream`
|
|
18
|
+
* classes with the same shape but different identity would silently break
|
|
19
|
+
* stream-typed CEL evaluations with "Unsupported type: Stream". The first
|
|
20
|
+
* `@telorun/sdk` copy to load registers its `Stream` class on `globalThis`
|
|
21
|
+
* under a stable `Symbol.for("@telorun/sdk:Stream")` key; later copies discard
|
|
22
|
+
* their local declaration at export time and re-export the registered one.
|
|
23
|
+
* Every Stream value in the process shares one constructor regardless of
|
|
24
|
+
* install topology — no build artifact or `file:` symlink required.
|
|
25
|
+
*
|
|
14
26
|
* The companion analyzer registers `Stream` as a CEL object type with no
|
|
15
27
|
* fields — terminal access (passing the value through) succeeds, member access
|
|
16
28
|
* (`result.output.text`, `result.output[0]`) raises a CEL error at runtime,
|
|
@@ -24,10 +36,43 @@
|
|
|
24
36
|
* patterns work without unwrapping. Internally it forwards `Symbol.asyncIterator`
|
|
25
37
|
* to the underlying iterable.
|
|
26
38
|
*/
|
|
27
|
-
|
|
28
|
-
|
|
39
|
+
|
|
40
|
+
// Type binding: `Stream<T>` as written by consumers (`let s: Stream<number>`)
|
|
41
|
+
// resolves to this interface. The class below also conforms to it.
|
|
42
|
+
interface Stream<T = unknown> extends AsyncIterable<T> {}
|
|
43
|
+
|
|
44
|
+
// Value binding (private): the class declaration that supplies the runtime
|
|
45
|
+
// implementation. Written as a named class expression so `.name === "Stream"`
|
|
46
|
+
// — debuggers, stack traces, and `Object.prototype.toString` all see "Stream",
|
|
47
|
+
// not the const name. The inner `Stream` identifier is only visible inside
|
|
48
|
+
// the class body (for self-reference); it does not shadow the outer interface.
|
|
49
|
+
const LocalStream = class Stream<T = unknown> implements AsyncIterable<T> {
|
|
50
|
+
// ECMAScript private field rather than TS `private readonly` — the latter
|
|
51
|
+
// shows up in the inferred type signature, which TS then refuses to export
|
|
52
|
+
// through an anonymous class expression (TS4094).
|
|
53
|
+
#source: AsyncIterable<T>;
|
|
54
|
+
|
|
55
|
+
constructor(source: AsyncIterable<T>) {
|
|
56
|
+
this.#source = source;
|
|
57
|
+
}
|
|
29
58
|
|
|
30
59
|
[Symbol.asyncIterator](): AsyncIterator<T> {
|
|
31
|
-
return this
|
|
60
|
+
return this.#source[Symbol.asyncIterator]();
|
|
32
61
|
}
|
|
33
|
-
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const STREAM_KEY = Symbol.for("@telorun/sdk:Stream");
|
|
65
|
+
const globalSlot = globalThis as Record<symbol, unknown>;
|
|
66
|
+
if (!(STREAM_KEY in globalSlot)) globalSlot[STREAM_KEY] = LocalStream;
|
|
67
|
+
|
|
68
|
+
// The exported value: whichever Stream class won the globalThis race (first
|
|
69
|
+
// sdk copy to import this module). Later copies discard their `LocalStream`
|
|
70
|
+
// at export time and route through the winner — keeping constructor identity
|
|
71
|
+
// stable across the kernel/controller realm boundary.
|
|
72
|
+
const Stream: typeof LocalStream = globalSlot[STREAM_KEY] as typeof LocalStream;
|
|
73
|
+
|
|
74
|
+
// `export { Stream }` re-exports the value binding (the const above) and the
|
|
75
|
+
// type binding (the interface above) under the same name — TypeScript treats
|
|
76
|
+
// value/type as separate namespaces, so a consumer's `import { Stream }`
|
|
77
|
+
// receives both `new Stream(...)` and `Stream<T>`.
|
|
78
|
+
export { Stream };
|