@telorun/sdk 0.58.0 → 0.59.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/dist/dispatch-invoke-ref.d.ts +11 -1
- package/dist/dispatch-invoke-ref.d.ts.map +1 -1
- package/dist/dispatch-invoke-ref.js +11 -3
- package/dist/resolve-ref-instance.d.ts +10 -0
- package/dist/resolve-ref-instance.d.ts.map +1 -1
- package/dist/resolve-ref-instance.js +1 -1
- package/package.json +1 -1
- package/src/dispatch-invoke-ref.ts +22 -5
- package/src/resolve-ref-instance.ts +11 -1
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import type { InvokeContext } from "./cancellation.js";
|
|
2
2
|
import type { ModuleContext } from "./module-context.js";
|
|
3
|
+
import type { KindRef } from "./ref.js";
|
|
4
|
+
import { type RefResolveContext } from "./resolve-ref-instance.js";
|
|
3
5
|
import { type ResourceInstance } from "./resource-instance.js";
|
|
4
6
|
/** The context a decorator kind composes to dispatch its wrapped target. */
|
|
5
|
-
export interface DispatchContext {
|
|
7
|
+
export interface DispatchContext extends RefResolveContext {
|
|
6
8
|
invokeResolved<TInputs>(kind: string, name: string, instance: ResourceInstance, inputs: TInputs, ctx?: InvokeContext): Promise<unknown>;
|
|
7
9
|
readonly moduleContext: ModuleContext;
|
|
10
|
+
/**
|
|
11
|
+
* Normalize a slot value to a {@link KindRef}: a `!ref` sentinel, an inline
|
|
12
|
+
* definition, or an already-normalized ref. Optional only so a caller holding
|
|
13
|
+
* a hand-built context still satisfies the interface — supply it whenever the
|
|
14
|
+
* slot can hold a value Phase 2.5 did not rewrite, which is every slot inside
|
|
15
|
+
* an `x-telo-scope` array.
|
|
16
|
+
*/
|
|
17
|
+
ensureKindRef?(value: unknown): KindRef;
|
|
8
18
|
}
|
|
9
19
|
/**
|
|
10
20
|
* Resolve a decorator's `invoke:` field to a live invocable and return a thunk
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatch-invoke-ref.d.ts","sourceRoot":"","sources":["../src/dispatch-invoke-ref.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"dispatch-invoke-ref.d.ts","sourceRoot":"","sources":["../src/dispatch-invoke-ref.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAsB,KAAK,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACvF,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/E,4EAA4E;AAC5E,MAAM,WAAW,eAAgB,SAAQ,iBAAiB;IACxD,cAAc,CAAC,OAAO,EACpB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,gBAAgB,EAC1B,MAAM,EAAE,OAAO,EACf,GAAG,CAAC,EAAE,aAAa,GAClB,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC;;;;;;OAMG;IACH,aAAa,CAAC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;CACzC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,eAAe,EACpB,QAAQ,EAAE,MAAM,MAAM,GACrB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,CAyBlF"}
|
|
@@ -12,10 +12,18 @@ import { getRefIdentity } from "./resource-instance.js";
|
|
|
12
12
|
* invocation context applies unchanged.
|
|
13
13
|
*/
|
|
14
14
|
export function resolveInvocableDispatcher(field, ctx, describe) {
|
|
15
|
-
|
|
15
|
+
// A `!ref` inside an `x-telo-scope` array is never rewritten by Phase 2.5, so it
|
|
16
|
+
// arrives as the raw sentinel — which has no `name` and would otherwise fail with
|
|
17
|
+
// a message pointing nowhere. `ensureKindRef` is the same rescue `ctx.resolveRef`
|
|
18
|
+
// performs; both resolution paths have to normalize, or a slot works only
|
|
19
|
+
// depending on which one its kind happens to use.
|
|
20
|
+
const normalized = ctx.ensureKindRef && field !== null && typeof field === "object" && !isInvocableInstance(field)
|
|
21
|
+
? ctx.ensureKindRef(field)
|
|
22
|
+
: field;
|
|
23
|
+
const target = resolveRefInstance(normalized, ctx, isInvocableInstance, () => `${describe()}: 'invoke'`, "Telo.Invocable");
|
|
16
24
|
// Dispatch through the traced chokepoint needs the target's kind+name: from
|
|
17
|
-
// the `!ref` identity the kernel stamped at injection, else from the
|
|
18
|
-
const id = getRefIdentity(target) ??
|
|
25
|
+
// the `!ref` identity the kernel stamped at injection, else from the ref.
|
|
26
|
+
const id = getRefIdentity(target) ?? normalized;
|
|
19
27
|
if (!id || typeof id.kind !== "string" || typeof id.name !== "string") {
|
|
20
28
|
return (inputs, invokeCtx) => target.invoke(inputs, invokeCtx);
|
|
21
29
|
}
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import type { ModuleContext } from "./module-context.js";
|
|
2
|
+
import type { ResourceInstance } from "./resource-instance.js";
|
|
2
3
|
/** The slice of `ResourceContext` needed to resolve a reference. */
|
|
3
4
|
export interface RefResolveContext {
|
|
4
5
|
readonly moduleContext: ModuleContext;
|
|
6
|
+
/**
|
|
7
|
+
* Resolve a bare name with the caller's own precedence — scope-local first,
|
|
8
|
+
* enclosing module as the fallback. Optional: a caller holding only a
|
|
9
|
+
* `{ moduleContext }` slice has no scope to prefer, and falls back to the
|
|
10
|
+
* module. Supplying it is what lets a `with:`-scoped resource reference a
|
|
11
|
+
* scoped sibling, and keeps `!ref` agreeing with the CEL `resources` layering
|
|
12
|
+
* about what a name means inside a scope.
|
|
13
|
+
*/
|
|
14
|
+
resolveLocalInstance?(name: string): ResourceInstance | undefined;
|
|
5
15
|
}
|
|
6
16
|
/**
|
|
7
17
|
* Resolve a `!ref` config field to a live instance of `T`. Controllers reach
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-ref-instance.d.ts","sourceRoot":"","sources":["../src/resolve-ref-instance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"resolve-ref-instance.d.ts","sourceRoot":"","sources":["../src/resolve-ref-instance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG/D,oEAAoE;AACpE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC;;;;;;;OAOG;IACH,oBAAoB,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAAC;CACnE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,iBAAiB,EACtB,KAAK,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,SAAS,IAAI,CAAC,EAC7C,QAAQ,EAAE,MAAM,MAAM,EACtB,OAAO,CAAC,EAAE,MAAM,GACf,CAAC,CAiCH"}
|
|
@@ -47,7 +47,7 @@ export function resolveRefInstance(value, ctx, guard, describe, expects) {
|
|
|
47
47
|
// it is an alias that crosses no import boundary.
|
|
48
48
|
const instance = ref.alias && ref.alias !== "Self"
|
|
49
49
|
? ctx.moduleContext.resolveImportedInstance(ref.alias, ref.name)
|
|
50
|
-
: ctx.moduleContext.getInstance(ref.name);
|
|
50
|
+
: (ctx.resolveLocalInstance?.(ref.name) ?? ctx.moduleContext.getInstance(ref.name));
|
|
51
51
|
if (!guard(instance)) {
|
|
52
52
|
const label = ref.alias ? `${ref.alias}.${ref.name}` : ref.name;
|
|
53
53
|
throw new RuntimeError("ERR_REF_UNRESOLVED", `${describe()} reference '${label}' did not resolve to a ${target}` +
|
package/package.json
CHANGED
|
@@ -2,11 +2,11 @@ import type { InvokeContext } from "./cancellation.js";
|
|
|
2
2
|
import type { Invocable } from "./capabilities/invokable.js";
|
|
3
3
|
import type { ModuleContext } from "./module-context.js";
|
|
4
4
|
import type { KindRef } from "./ref.js";
|
|
5
|
-
import { resolveRefInstance } from "./resolve-ref-instance.js";
|
|
5
|
+
import { resolveRefInstance, type RefResolveContext } from "./resolve-ref-instance.js";
|
|
6
6
|
import { getRefIdentity, type ResourceInstance } from "./resource-instance.js";
|
|
7
7
|
|
|
8
8
|
/** The context a decorator kind composes to dispatch its wrapped target. */
|
|
9
|
-
export interface DispatchContext {
|
|
9
|
+
export interface DispatchContext extends RefResolveContext {
|
|
10
10
|
invokeResolved<TInputs>(
|
|
11
11
|
kind: string,
|
|
12
12
|
name: string,
|
|
@@ -15,6 +15,14 @@ export interface DispatchContext {
|
|
|
15
15
|
ctx?: InvokeContext,
|
|
16
16
|
): Promise<unknown>;
|
|
17
17
|
readonly moduleContext: ModuleContext;
|
|
18
|
+
/**
|
|
19
|
+
* Normalize a slot value to a {@link KindRef}: a `!ref` sentinel, an inline
|
|
20
|
+
* definition, or an already-normalized ref. Optional only so a caller holding
|
|
21
|
+
* a hand-built context still satisfies the interface — supply it whenever the
|
|
22
|
+
* slot can hold a value Phase 2.5 did not rewrite, which is every slot inside
|
|
23
|
+
* an `x-telo-scope` array.
|
|
24
|
+
*/
|
|
25
|
+
ensureKindRef?(value: unknown): KindRef;
|
|
18
26
|
}
|
|
19
27
|
|
|
20
28
|
/**
|
|
@@ -33,16 +41,25 @@ export function resolveInvocableDispatcher(
|
|
|
33
41
|
ctx: DispatchContext,
|
|
34
42
|
describe: () => string,
|
|
35
43
|
): (inputs: Record<string, unknown>, invokeCtx?: InvokeContext) => Promise<unknown> {
|
|
44
|
+
// A `!ref` inside an `x-telo-scope` array is never rewritten by Phase 2.5, so it
|
|
45
|
+
// arrives as the raw sentinel — which has no `name` and would otherwise fail with
|
|
46
|
+
// a message pointing nowhere. `ensureKindRef` is the same rescue `ctx.resolveRef`
|
|
47
|
+
// performs; both resolution paths have to normalize, or a slot works only
|
|
48
|
+
// depending on which one its kind happens to use.
|
|
49
|
+
const normalized =
|
|
50
|
+
ctx.ensureKindRef && field !== null && typeof field === "object" && !isInvocableInstance(field)
|
|
51
|
+
? ctx.ensureKindRef(field)
|
|
52
|
+
: field;
|
|
36
53
|
const target = resolveRefInstance(
|
|
37
|
-
|
|
54
|
+
normalized,
|
|
38
55
|
ctx,
|
|
39
56
|
isInvocableInstance,
|
|
40
57
|
() => `${describe()}: 'invoke'`,
|
|
41
58
|
"Telo.Invocable",
|
|
42
59
|
);
|
|
43
60
|
// Dispatch through the traced chokepoint needs the target's kind+name: from
|
|
44
|
-
// the `!ref` identity the kernel stamped at injection, else from the
|
|
45
|
-
const id = getRefIdentity(target as object) ?? (
|
|
61
|
+
// the `!ref` identity the kernel stamped at injection, else from the ref.
|
|
62
|
+
const id = getRefIdentity(target as object) ?? (normalized as Partial<KindRef> | undefined);
|
|
46
63
|
if (!id || typeof id.kind !== "string" || typeof id.name !== "string") {
|
|
47
64
|
return (inputs, invokeCtx) => target.invoke(inputs, invokeCtx);
|
|
48
65
|
}
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import type { ModuleContext } from "./module-context.js";
|
|
2
2
|
import type { KindRef } from "./ref.js";
|
|
3
|
+
import type { ResourceInstance } from "./resource-instance.js";
|
|
3
4
|
import { RuntimeError } from "./types.js";
|
|
4
5
|
|
|
5
6
|
/** The slice of `ResourceContext` needed to resolve a reference. */
|
|
6
7
|
export interface RefResolveContext {
|
|
7
8
|
readonly moduleContext: ModuleContext;
|
|
9
|
+
/**
|
|
10
|
+
* Resolve a bare name with the caller's own precedence — scope-local first,
|
|
11
|
+
* enclosing module as the fallback. Optional: a caller holding only a
|
|
12
|
+
* `{ moduleContext }` slice has no scope to prefer, and falls back to the
|
|
13
|
+
* module. Supplying it is what lets a `with:`-scoped resource reference a
|
|
14
|
+
* scoped sibling, and keeps `!ref` agreeing with the CEL `resources` layering
|
|
15
|
+
* about what a name means inside a scope.
|
|
16
|
+
*/
|
|
17
|
+
resolveLocalInstance?(name: string): ResourceInstance | undefined;
|
|
8
18
|
}
|
|
9
19
|
|
|
10
20
|
/**
|
|
@@ -67,7 +77,7 @@ export function resolveRefInstance<T>(
|
|
|
67
77
|
const instance =
|
|
68
78
|
ref.alias && ref.alias !== "Self"
|
|
69
79
|
? ctx.moduleContext.resolveImportedInstance(ref.alias, ref.name)
|
|
70
|
-
: ctx.moduleContext.getInstance(ref.name);
|
|
80
|
+
: (ctx.resolveLocalInstance?.(ref.name) ?? ctx.moduleContext.getInstance(ref.name));
|
|
71
81
|
|
|
72
82
|
if (!guard(instance)) {
|
|
73
83
|
const label = ref.alias ? `${ref.alias}.${ref.name}` : ref.name;
|