@lifi/composer-sdk 0.8.1 → 0.9.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 (161) hide show
  1. package/README.md +3 -2
  2. package/dist/_virtual/_rolldown/runtime.cjs +33 -0
  3. package/dist/_virtual/_rolldown/runtime.js +13 -0
  4. package/dist/authoring/FlowBuilderCore.cjs +102 -120
  5. package/dist/authoring/FlowBuilderCore.cjs.map +1 -1
  6. package/dist/authoring/FlowBuilderCore.d.cts +58 -61
  7. package/dist/authoring/FlowBuilderCore.d.ts +58 -61
  8. package/dist/authoring/FlowBuilderCore.js +99 -97
  9. package/dist/authoring/FlowBuilderCore.js.map +1 -1
  10. package/dist/authoring/handles.cjs +25 -40
  11. package/dist/authoring/handles.cjs.map +1 -1
  12. package/dist/authoring/handles.d.cts +33 -34
  13. package/dist/authoring/handles.d.ts +33 -34
  14. package/dist/authoring/handles.js +21 -13
  15. package/dist/authoring/handles.js.map +1 -1
  16. package/dist/authoring/raw.cjs +85 -44
  17. package/dist/authoring/raw.cjs.map +1 -1
  18. package/dist/authoring/raw.d.cts +8 -8
  19. package/dist/authoring/raw.d.ts +8 -8
  20. package/dist/authoring/raw.js +83 -19
  21. package/dist/authoring/raw.js.map +1 -1
  22. package/dist/authoring/signatureArgs.cjs +81 -103
  23. package/dist/authoring/signatureArgs.cjs.map +1 -1
  24. package/dist/authoring/signatureArgs.d.cts +63 -64
  25. package/dist/authoring/signatureArgs.d.ts +63 -64
  26. package/dist/authoring/signatureArgs.js +76 -75
  27. package/dist/authoring/signatureArgs.js.map +1 -1
  28. package/dist/client.cjs +172 -220
  29. package/dist/client.cjs.map +1 -1
  30. package/dist/client.d.cts +131 -131
  31. package/dist/client.d.ts +131 -131
  32. package/dist/client.js +165 -198
  33. package/dist/client.js.map +1 -1
  34. package/dist/discovery.cjs +0 -17
  35. package/dist/discovery.d.cts +57 -56
  36. package/dist/discovery.d.ts +57 -56
  37. package/dist/discovery.js +1 -1
  38. package/dist/errors.cjs +211 -159
  39. package/dist/errors.cjs.map +1 -1
  40. package/dist/errors.d.cts +84 -84
  41. package/dist/errors.d.ts +84 -84
  42. package/dist/errors.js +201 -120
  43. package/dist/errors.js.map +1 -1
  44. package/dist/generated/config.generated.cjs +0 -17
  45. package/dist/generated/config.generated.d.cts +804 -936
  46. package/dist/generated/config.generated.d.ts +804 -936
  47. package/dist/generated/config.generated.js +1 -1
  48. package/dist/generated/guards.generated.cjs +25 -35
  49. package/dist/generated/guards.generated.cjs.map +1 -1
  50. package/dist/generated/guards.generated.d.cts +20 -4
  51. package/dist/generated/guards.generated.d.ts +20 -4
  52. package/dist/generated/guards.generated.js +19 -11
  53. package/dist/generated/guards.generated.js.map +1 -1
  54. package/dist/generated/materialisers.generated.cjs +25 -35
  55. package/dist/generated/materialisers.generated.cjs.map +1 -1
  56. package/dist/generated/materialisers.generated.d.cts +17 -4
  57. package/dist/generated/materialisers.generated.d.ts +17 -4
  58. package/dist/generated/materialisers.generated.js +19 -11
  59. package/dist/generated/materialisers.generated.js.map +1 -1
  60. package/dist/generated/operations.generated.cjs +236 -277
  61. package/dist/generated/operations.generated.cjs.map +1 -1
  62. package/dist/generated/operations.generated.d.cts +719 -708
  63. package/dist/generated/operations.generated.d.ts +719 -708
  64. package/dist/generated/operations.generated.js +235 -256
  65. package/dist/generated/operations.generated.js.map +1 -1
  66. package/dist/generated/preconditions.generated.cjs +25 -35
  67. package/dist/generated/preconditions.generated.cjs.map +1 -1
  68. package/dist/generated/preconditions.generated.d.cts +17 -4
  69. package/dist/generated/preconditions.generated.d.ts +17 -4
  70. package/dist/generated/preconditions.generated.js +19 -11
  71. package/dist/generated/preconditions.generated.js.map +1 -1
  72. package/dist/index.cjs +131 -97
  73. package/dist/index.cjs.map +1 -1
  74. package/dist/index.d.cts +29 -43
  75. package/dist/index.d.ts +29 -43
  76. package/dist/index.js +96 -45
  77. package/dist/index.js.map +1 -1
  78. package/dist/outputs.cjs +11 -32
  79. package/dist/outputs.cjs.map +1 -1
  80. package/dist/outputs.d.cts +5 -5
  81. package/dist/outputs.d.ts +5 -5
  82. package/dist/outputs.js +10 -8
  83. package/dist/outputs.js.map +1 -1
  84. package/dist/raw.cjs +21 -33
  85. package/dist/raw.cjs.map +1 -1
  86. package/dist/raw.d.cts +8 -4
  87. package/dist/raw.d.ts +8 -4
  88. package/dist/raw.js +12 -7
  89. package/dist/raw.js.map +1 -1
  90. package/dist/reachability.cjs +82 -112
  91. package/dist/reachability.cjs.map +1 -1
  92. package/dist/reachability.d.cts +33 -59
  93. package/dist/reachability.d.ts +33 -59
  94. package/dist/reachability.js +81 -88
  95. package/dist/reachability.js.map +1 -1
  96. package/dist/resources.cjs +47 -32
  97. package/dist/resources.cjs.map +1 -1
  98. package/dist/resources.d.cts +50 -3
  99. package/dist/resources.d.ts +50 -3
  100. package/dist/resources.js +42 -9
  101. package/dist/resources.js.map +1 -1
  102. package/dist/responseSchemas.cjs +99 -111
  103. package/dist/responseSchemas.cjs.map +1 -1
  104. package/dist/responseSchemas.d.cts +34 -34
  105. package/dist/responseSchemas.d.ts +34 -34
  106. package/dist/responseSchemas.js +85 -66
  107. package/dist/responseSchemas.js.map +1 -1
  108. package/dist/routeAmount.cjs +61 -31
  109. package/dist/routeAmount.cjs.map +1 -1
  110. package/dist/routeAmount.d.cts +52 -2
  111. package/dist/routeAmount.d.ts +52 -2
  112. package/dist/routeAmount.js +56 -8
  113. package/dist/routeAmount.js.map +1 -1
  114. package/dist/run/inputs.cjs +56 -48
  115. package/dist/run/inputs.cjs.map +1 -1
  116. package/dist/run/inputs.d.cts +70 -74
  117. package/dist/run/inputs.d.ts +70 -74
  118. package/dist/run/inputs.js +54 -23
  119. package/dist/run/inputs.js.map +1 -1
  120. package/dist/run/simulate.cjs +38 -43
  121. package/dist/run/simulate.cjs.map +1 -1
  122. package/dist/run/simulate.d.cts +36 -36
  123. package/dist/run/simulate.d.ts +36 -36
  124. package/dist/run/simulate.js +37 -19
  125. package/dist/run/simulate.js.map +1 -1
  126. package/dist/sdk.cjs +55 -66
  127. package/dist/sdk.cjs.map +1 -1
  128. package/dist/sdk.d.cts +108 -111
  129. package/dist/sdk.d.ts +108 -111
  130. package/dist/sdk.js +52 -44
  131. package/dist/sdk.js.map +1 -1
  132. package/dist/types.cjs +0 -17
  133. package/dist/types.d.cts +22 -22
  134. package/dist/types.d.ts +22 -22
  135. package/dist/types.js +1 -1
  136. package/package.json +4 -4
  137. package/src/client.ts +2 -2
  138. package/src/examples/aaveClaimRewards.ts +2 -1
  139. package/src/examples/emitCustomEvent.ts +1 -2
  140. package/src/examples/run.ts +1 -1
  141. package/src/examples/transferTokens.ts +21 -17
  142. package/src/generated/config.generated.ts +20 -9
  143. package/src/generated/operations.generated.ts +28 -5
  144. package/dist/discovery.cjs.map +0 -1
  145. package/dist/discovery.js.map +0 -1
  146. package/dist/generated/config.generated.cjs.map +0 -1
  147. package/dist/generated/config.generated.js.map +0 -1
  148. package/dist/guards.generated-CDCgYGZo.d.cts +0 -24
  149. package/dist/guards.generated-CdYcs4h0.d.ts +0 -24
  150. package/dist/materialisers.generated-BMkBQgWZ.d.ts +0 -24
  151. package/dist/materialisers.generated-BWq5oePO.d.cts +0 -24
  152. package/dist/preconditions.generated-DblS13Wq.d.cts +0 -24
  153. package/dist/preconditions.generated-U7YpVh30.d.ts +0 -24
  154. package/dist/raw-BvRghN3r.d.ts +0 -20
  155. package/dist/raw-s1rer8X3.d.cts +0 -20
  156. package/dist/resources-BKlFxjo8.d.cts +0 -56
  157. package/dist/resources-CYis1_DS.d.ts +0 -56
  158. package/dist/routeAmount-DdbJYJyM.d.cts +0 -55
  159. package/dist/routeAmount-DdbJYJyM.d.ts +0 -55
  160. package/dist/types.cjs.map +0 -1
  161. package/dist/types.js.map +0 -1
@@ -1,17 +1,17 @@
1
- import { Ref, Resource, SolType, BindValue, AppliedGuard, Flow } from '@lifi/compose-spec';
2
- import { TypedRef, TypedLiteral, InputSchema, InputDecl, TypedGuard, OutputKind } from '../types.js';
3
- import { InputHandle, OutputHandle, ResourceInputHandle } from './handles.js';
4
-
1
+ import { InputDecl, InputSchema, OutputKind, TypedGuard, TypedLiteral, TypedRef } from "../types.js";
2
+ import { InputHandle, OutputHandle, ResourceInputHandle } from "./handles.js";
3
+ import { AppliedGuard, BindValue, Flow, Ref, Resource, SolType } from "@lifi/compose-spec";
4
+ //#region src/authoring/FlowBuilderCore.d.ts
5
5
  /**
6
6
  * Arguments for calling an operation node in a flow.
7
7
  */
8
- interface CallArgs {
9
- /** Maps parameter names to input/output handles or raw `$ref` pointers. */
10
- readonly bind: Record<string, AnyBindable>;
11
- /** Optional operation-specific configuration. */
12
- readonly config?: object;
13
- /** Optional guards (e.g. slippage checks) applied to this operation's outputs. */
14
- readonly guards?: readonly TypedGuard[];
8
+ export interface CallArgs {
9
+ /** Maps parameter names to input/output handles or raw `$ref` pointers. */
10
+ readonly bind: Record<string, AnyBindable>;
11
+ /** Optional operation-specific configuration. */
12
+ readonly config?: object;
13
+ /** Optional guards (e.g. slippage checks) applied to this operation's outputs. */
14
+ readonly guards?: readonly TypedGuard[];
15
15
  }
16
16
  /**
17
17
  * Any value that can be bound to an operation parameter: an input handle, an
@@ -28,16 +28,16 @@ interface CallArgs {
28
28
  * Use `raw.ref<T>()` to create a typed ref from a raw path string, and
29
29
  * `raw.literal<T>()` to bake in a constant.
30
30
  */
31
- type AnyBindable = InputHandle | OutputHandle | TypedRef | TypedLiteral | Ref;
31
+ export type AnyBindable = InputHandle | OutputHandle | TypedRef | TypedLiteral | Ref;
32
32
  /**
33
33
  * Provides references to runtime context values available inside a flow.
34
34
  * Access via `builder.context`.
35
35
  */
36
- interface ContextAccessor {
37
- /** A `$ref` pointing to the transaction sender (signer) address. */
38
- readonly sender: TypedRef<'address'>;
39
- /** A `$ref` pointing to the on-chain execution (proxy) address. */
40
- readonly executionAddress: TypedRef<'address'>;
36
+ export interface ContextAccessor {
37
+ /** A `$ref` pointing to the transaction sender (signer) address. */
38
+ readonly sender: TypedRef<"address">;
39
+ /** A `$ref` pointing to the on-chain execution (proxy) address. */
40
+ readonly executionAddress: TypedRef<"address">;
41
41
  }
42
42
  type InputHandleOf<D extends InputDecl> = D extends Resource ? ResourceInputHandle : D extends SolType ? InputHandle<D> : InputHandle;
43
43
  /**
@@ -46,19 +46,17 @@ type InputHandleOf<D extends InputDecl> = D extends Resource ? ResourceInputHand
46
46
  *
47
47
  * @typeParam T - The flow's input schema.
48
48
  */
49
- type InputHandles<T extends InputSchema> = {
50
- readonly [K in keyof T]: InputHandleOf<T[K]>;
51
- };
49
+ export type InputHandles<T extends InputSchema> = { readonly [K in keyof T]: InputHandleOf<T[K]>; };
52
50
  /**
53
51
  * Options for creating a new flow builder.
54
52
  *
55
53
  * @typeParam T - The flow's input schema.
56
54
  */
57
- interface FlowOptions<T extends InputSchema> {
58
- /** Optional human-readable name for the flow. Defaults to a random UUID. */
59
- readonly name?: string;
60
- /** Input declarations mapping names to resource or scalar types. */
61
- readonly inputs: T;
55
+ export interface FlowOptions<T extends InputSchema> {
56
+ /** Optional human-readable name for the flow. Defaults to a random UUID. */
57
+ readonly name?: string;
58
+ /** Input declarations mapping names to resource or scalar types. */
59
+ readonly inputs: T;
62
60
  }
63
61
  /**
64
62
  * A Flow document branded with its input schema for type-safe request building.
@@ -66,8 +64,8 @@ interface FlowOptions<T extends InputSchema> {
66
64
  * The `__inputs` field is a phantom type — it exists only at compile time for
67
65
  * TypeScript inference and is never present at runtime.
68
66
  */
69
- type TypedFlow<T extends InputSchema = InputSchema> = Flow & {
70
- readonly __inputs?: T;
67
+ export type TypedFlow<T extends InputSchema = InputSchema> = Flow & {
68
+ readonly __inputs?: T;
71
69
  };
72
70
  /**
73
71
  * Core flow builder interface providing low-level access to flow construction.
@@ -77,46 +75,44 @@ type TypedFlow<T extends InputSchema = InputSchema> = Flow & {
77
75
  *
78
76
  * @typeParam T - The flow's input schema.
79
77
  */
80
- interface FlowBuilderCore<T extends InputSchema = InputSchema> {
81
- /** Runtime context references (sender address, execution address). */
82
- readonly context: ContextAccessor;
83
- /** Typed handles for each declared flow input, used to bind inputs to operations. */
84
- readonly inputs: InputHandles<T>;
85
- /**
86
- * Appends an untyped operation node to the flow. This is an escape hatch
87
- * for operations not yet covered by the generated methods.
88
- *
89
- * Use `raw.ref<T>()` to reference this node's outputs in subsequent typed
90
- * operations.
91
- *
92
- * @param id - Unique node identifier within the flow.
93
- * @param op - The operation name (e.g. `"custom.vaultQuery"`).
94
- * @param args - Bind map, config, and optional guards for the node.
95
- * @throws Error if a node with the same `id` already exists in the flow.
96
- */
97
- readonly untypedOp: (id: string, op: string, args: {
98
- readonly bind: Record<string, BindValue>;
99
- readonly config: Record<string, unknown>;
100
- readonly guards?: readonly AppliedGuard[];
101
- }) => void;
102
- /** Serialises the builder state into a {@link TypedFlow} document. */
103
- readonly build: () => TypedFlow<T>;
78
+ export interface FlowBuilderCore<T extends InputSchema = InputSchema> {
79
+ /** Runtime context references (sender address, execution address). */
80
+ readonly context: ContextAccessor;
81
+ /** Typed handles for each declared flow input, used to bind inputs to operations. */
82
+ readonly inputs: InputHandles<T>;
83
+ /**
84
+ * Appends an untyped operation node to the flow. This is an escape hatch
85
+ * for operations not yet covered by the generated methods.
86
+ *
87
+ * Use `raw.ref<T>()` to reference this node's outputs in subsequent typed
88
+ * operations.
89
+ *
90
+ * @param id - Unique node identifier within the flow.
91
+ * @param op - The operation name (e.g. `"custom.vaultQuery"`).
92
+ * @param args - Bind map, config, and optional guards for the node.
93
+ * @throws Error if a node with the same `id` already exists in the flow.
94
+ */
95
+ readonly untypedOp: (id: string, op: string, args: {
96
+ readonly bind: Record<string, BindValue>;
97
+ readonly config: Record<string, unknown>;
98
+ readonly guards?: readonly AppliedGuard[];
99
+ }) => void;
100
+ /** Serialises the builder state into a {@link TypedFlow} document. */
101
+ readonly build: () => TypedFlow<T>;
104
102
  }
105
103
  /** Maps output port names to their output kind for compile-time and runtime validation. */
106
- type OutputSpec = Record<string, OutputKind>;
104
+ export type OutputSpec = Record<string, OutputKind>;
107
105
  /**
108
106
  * Maps each output family's port name to the config key that sizes it: an
109
107
  * array (one instance per element) or a non-negative integer count.
110
108
  * A family port is also listed in the {@link OutputSpec}, as `'resource'`.
111
109
  */
112
- type FamilySpec = Readonly<Record<string, string>>;
110
+ export type FamilySpec = Readonly<Record<string, string>>;
113
111
  /** The handles `call` returns for an {@link OutputSpec} and its families. */
114
- type OutputHandles<O extends OutputSpec, F extends FamilySpec> = {
115
- readonly [K in keyof O & string]: K extends keyof F ? readonly OutputHandle<'resource'>[] : OutputHandle<O[K]>;
116
- };
112
+ export type OutputHandles<O extends OutputSpec, F extends FamilySpec> = { readonly [K in keyof O & string]: K extends keyof F ? readonly OutputHandle<"resource">[] : OutputHandle<O[K]>; };
117
113
  /** Internal interface exposed to bindGeneratedOps — not part of the public API. */
118
- interface FlowBuilderInternal<T extends InputSchema = InputSchema> extends FlowBuilderCore<T> {
119
- readonly call: <O extends OutputSpec, F extends FamilySpec = Record<never, string>>(nodeId: string, op: string, args: CallArgs, outputs: O, families?: F) => OutputHandles<O, F>;
114
+ export interface FlowBuilderInternal<T extends InputSchema = InputSchema> extends FlowBuilderCore<T> {
115
+ readonly call: <O extends OutputSpec, F extends FamilySpec = Record<never, string>>(nodeId: string, op: string, args: CallArgs, outputs: O, families?: F) => OutputHandles<O, F>;
120
116
  }
121
117
  /**
122
118
  * Creates a new flow builder targeting the given chain.
@@ -126,6 +122,7 @@ interface FlowBuilderInternal<T extends InputSchema = InputSchema> extends FlowB
126
122
  * @returns A {@link FlowBuilderInternal} instance.
127
123
  * @internal
128
124
  */
129
- declare const createFlowBuilderCore: <T extends InputSchema>(chainId: number, options: FlowOptions<T>) => FlowBuilderInternal<T>;
130
-
131
- export { type AnyBindable, type CallArgs, type ContextAccessor, type FamilySpec, type FlowBuilderCore, type FlowBuilderInternal, type FlowOptions, type InputHandles, type OutputHandles, type OutputSpec, type TypedFlow, createFlowBuilderCore };
125
+ export declare const createFlowBuilderCore: <T extends InputSchema>(chainId: number, options: FlowOptions<T>) => FlowBuilderInternal<T>;
126
+ //#endregion
127
+ export {};
128
+ //# sourceMappingURL=FlowBuilderCore.d.ts.map
@@ -1,103 +1,105 @@
1
- import {
2
- familySize,
3
- instancePortName
4
- } from "@lifi/compose-spec";
5
1
  import { toBindValue } from "./handles.js";
6
2
  import { ref } from "./raw.js";
3
+ import { familySize, instancePortName } from "@lifi/compose-spec";
4
+ //#region src/authoring/FlowBuilderCore.ts
7
5
  const isResource = (decl) => typeof decl === "object" && decl !== null && "kind" in decl;
6
+ /**
7
+ * Creates a new flow builder targeting the given chain.
8
+ *
9
+ * @param chainId - The EVM chain ID (e.g. `1` for Ethereum mainnet).
10
+ * @param options - Flow configuration including input declarations.
11
+ * @returns A {@link FlowBuilderInternal} instance.
12
+ * @internal
13
+ */
8
14
  const createFlowBuilderCore = (chainId, options) => {
9
- const id = options.name ?? crypto.randomUUID();
10
- const flowInputs = [];
11
- const nodes = [];
12
- const nodeIds = /* @__PURE__ */ new Set();
13
- const inputHandles = {};
14
- for (const [name, decl] of Object.entries(options.inputs)) {
15
- if (isResource(decl)) {
16
- if (decl.chainId !== chainId) {
17
- throw new Error(
18
- `Input "${name}" has chainId ${decl.chainId} but flow targets chain ${chainId}`
19
- );
20
- }
21
- flowInputs.push({ name, resource: decl });
22
- inputHandles[name] = { _tag: "input", inputName: name, resource: decl };
23
- } else {
24
- flowInputs.push({ name, type: decl });
25
- inputHandles[name] = { _tag: "input", inputName: name };
26
- }
27
- }
28
- const call = (nodeId, op, args, outputs, families) => {
29
- if (nodeIds.has(nodeId)) throw new Error(`Duplicate node id: "${nodeId}"`);
30
- nodeIds.add(nodeId);
31
- const bind = {};
32
- for (const [key, val] of Object.entries(args.bind)) {
33
- bind[key] = toBindValue(val);
34
- }
35
- const config = args.config ?? {};
36
- const node = {
37
- id: nodeId,
38
- op,
39
- bind,
40
- config,
41
- ...args.guards && args.guards.length > 0 && { guards: args.guards }
42
- };
43
- nodes.push(node);
44
- const outputHandle = (portName) => ({
45
- _tag: "output",
46
- nodeId,
47
- portName
48
- });
49
- return new Proxy({}, {
50
- get: (_target, prop) => {
51
- if (typeof prop !== "string" || prop === "then") return void 0;
52
- if (!Object.hasOwn(outputs, prop)) {
53
- throw new Error(
54
- `Op "${op}" has no output port "${prop}". Valid ports: ${Object.keys(
55
- outputs
56
- ).join(", ")}`
57
- );
58
- }
59
- const countFrom = families?.[prop];
60
- if (countFrom === void 0) return outputHandle(prop);
61
- const size = familySize({ name: prop, countFrom }, config);
62
- return Array.from(
63
- { length: size },
64
- (_, index) => outputHandle(instancePortName(prop, index))
65
- );
66
- }
67
- });
68
- };
69
- const untypedOp = (nodeId, op, args) => {
70
- if (nodeIds.has(nodeId)) throw new Error(`Duplicate node id: "${nodeId}"`);
71
- nodeIds.add(nodeId);
72
- const node = {
73
- id: nodeId,
74
- op,
75
- bind: args.bind,
76
- config: args.config,
77
- ...args.guards && args.guards.length > 0 && { guards: args.guards }
78
- };
79
- nodes.push(node);
80
- };
81
- const build = () => ({
82
- version: 1,
83
- id,
84
- chainId,
85
- inputs: [...flowInputs],
86
- nodes: [...nodes]
87
- });
88
- const context = {
89
- sender: ref("context.sender"),
90
- executionAddress: ref("context.executionAddress")
91
- };
92
- return {
93
- context,
94
- inputs: inputHandles,
95
- call,
96
- untypedOp,
97
- build
98
- };
99
- };
100
- export {
101
- createFlowBuilderCore
15
+ const id = options.name ?? crypto.randomUUID();
16
+ const flowInputs = [];
17
+ const nodes = [];
18
+ const nodeIds = /* @__PURE__ */ new Set();
19
+ const inputHandles = {};
20
+ for (const [name, decl] of Object.entries(options.inputs)) if (isResource(decl)) {
21
+ if (decl.chainId !== chainId) throw new Error(`Input "${name}" has chainId ${decl.chainId} but flow targets chain ${chainId}`);
22
+ flowInputs.push({
23
+ name,
24
+ resource: decl
25
+ });
26
+ inputHandles[name] = {
27
+ _tag: "input",
28
+ inputName: name,
29
+ resource: decl
30
+ };
31
+ } else {
32
+ flowInputs.push({
33
+ name,
34
+ type: decl
35
+ });
36
+ inputHandles[name] = {
37
+ _tag: "input",
38
+ inputName: name
39
+ };
40
+ }
41
+ const call = (nodeId, op, args, outputs, families) => {
42
+ if (nodeIds.has(nodeId)) throw new Error(`Duplicate node id: "${nodeId}"`);
43
+ nodeIds.add(nodeId);
44
+ const bind = {};
45
+ for (const [key, val] of Object.entries(args.bind)) bind[key] = toBindValue(val);
46
+ const config = args.config ?? {};
47
+ const node = {
48
+ id: nodeId,
49
+ op,
50
+ bind,
51
+ config,
52
+ ...args.guards && args.guards.length > 0 && { guards: args.guards }
53
+ };
54
+ nodes.push(node);
55
+ const outputHandle = (portName) => ({
56
+ _tag: "output",
57
+ nodeId,
58
+ portName
59
+ });
60
+ return new Proxy({}, { get: (_target, prop) => {
61
+ if (typeof prop !== "string" || prop === "then") return void 0;
62
+ if (!Object.hasOwn(outputs, prop)) throw new Error(`Op "${op}" has no output port "${prop}". Valid ports: ${Object.keys(outputs).join(", ")}`);
63
+ const countFrom = families?.[prop];
64
+ if (countFrom === void 0) return outputHandle(prop);
65
+ const size = familySize({
66
+ name: prop,
67
+ countFrom
68
+ }, config);
69
+ return Array.from({ length: size }, (_, index) => outputHandle(instancePortName(prop, index)));
70
+ } });
71
+ };
72
+ const untypedOp = (nodeId, op, args) => {
73
+ if (nodeIds.has(nodeId)) throw new Error(`Duplicate node id: "${nodeId}"`);
74
+ nodeIds.add(nodeId);
75
+ const node = {
76
+ id: nodeId,
77
+ op,
78
+ bind: args.bind,
79
+ config: args.config,
80
+ ...args.guards && args.guards.length > 0 && { guards: args.guards }
81
+ };
82
+ nodes.push(node);
83
+ };
84
+ const build = () => ({
85
+ version: 1,
86
+ id,
87
+ chainId,
88
+ inputs: [...flowInputs],
89
+ nodes: [...nodes]
90
+ });
91
+ return {
92
+ context: {
93
+ sender: ref("context.sender"),
94
+ executionAddress: ref("context.executionAddress")
95
+ },
96
+ inputs: inputHandles,
97
+ call,
98
+ untypedOp,
99
+ build
100
+ };
102
101
  };
102
+ //#endregion
103
+ export { createFlowBuilderCore };
104
+
103
105
  //# sourceMappingURL=FlowBuilderCore.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/authoring/FlowBuilderCore.ts"],"sourcesContent":["import {\n type AppliedGuard,\n type BindValue,\n type Call,\n familySize,\n type Flow,\n type FlowInput,\n instancePortName,\n type Ref,\n type Resource,\n type SolType,\n} from '@lifi/compose-spec';\n\nimport type {\n InputDecl,\n InputSchema,\n OutputKind,\n TypedGuard,\n TypedLiteral,\n TypedRef,\n} from '../types.js';\n\nimport type {\n InputHandle,\n OutputHandle,\n ResourceInputHandle,\n} from './handles.js';\nimport { toBindValue } from './handles.js';\nimport { ref } from './raw.js';\n\n/**\n * Arguments for calling an operation node in a flow.\n */\nexport interface CallArgs {\n /** Maps parameter names to input/output handles or raw `$ref` pointers. */\n readonly bind: Record<string, AnyBindable>;\n /** Optional operation-specific configuration. */\n readonly config?: object;\n /** Optional guards (e.g. slippage checks) applied to this operation's outputs. */\n readonly guards?: readonly TypedGuard[];\n}\n\n/**\n * Any value that can be bound to an operation parameter: an input handle, an\n * output handle from a previous operation, a typed `$ref` pointer, a typed\n * literal, or a bare `{ $ref }` pointer.\n *\n * This is the bind type of {@link FlowBuilderInternal.call}, the entry point\n * every generated operation lowers into — not a public authoring surface. A\n * bare `Ref` belongs here because a generated op resolves its own typed binds\n * to wire refs (`toBindRef` in `./signatureArgs.js`) before calling it. Typed\n * operation slots use `Bindable<T>`, which rejects a bare `Ref`; see\n * `RefBindable` in `./handles.js`.\n *\n * Use `raw.ref<T>()` to create a typed ref from a raw path string, and\n * `raw.literal<T>()` to bake in a constant.\n */\nexport type AnyBindable =\n InputHandle | OutputHandle | TypedRef | TypedLiteral | Ref;\n\n/**\n * Provides references to runtime context values available inside a flow.\n * Access via `builder.context`.\n */\nexport interface ContextAccessor {\n /** A `$ref` pointing to the transaction sender (signer) address. */\n readonly sender: TypedRef<'address'>;\n /** A `$ref` pointing to the on-chain execution (proxy) address. */\n readonly executionAddress: TypedRef<'address'>;\n}\n\ntype InputHandleOf<D extends InputDecl> = D extends Resource\n ? ResourceInputHandle\n : D extends SolType\n ? InputHandle<D>\n : InputHandle;\n\n/**\n * A mapped type that converts an input schema into typed handles.\n * Resource inputs produce {@link ResourceInputHandle}; scalar inputs produce {@link InputHandle}.\n *\n * @typeParam T - The flow's input schema.\n */\nexport type InputHandles<T extends InputSchema> = {\n readonly [K in keyof T]: InputHandleOf<T[K]>;\n};\n\n/**\n * Options for creating a new flow builder.\n *\n * @typeParam T - The flow's input schema.\n */\nexport interface FlowOptions<T extends InputSchema> {\n /** Optional human-readable name for the flow. Defaults to a random UUID. */\n readonly name?: string;\n /** Input declarations mapping names to resource or scalar types. */\n readonly inputs: T;\n}\n\n/**\n * A Flow document branded with its input schema for type-safe request building.\n *\n * The `__inputs` field is a phantom type — it exists only at compile time for\n * TypeScript inference and is never present at runtime.\n */\nexport type TypedFlow<T extends InputSchema = InputSchema> = Flow & {\n readonly __inputs?: T;\n};\n\n/**\n * Core flow builder interface providing low-level access to flow construction.\n *\n * For most use cases, prefer the {@link FlowBuilder} type returned by `sdk.flow()`\n * which adds generated operation methods and a `compile` method.\n *\n * @typeParam T - The flow's input schema.\n */\nexport interface FlowBuilderCore<T extends InputSchema = InputSchema> {\n /** Runtime context references (sender address, execution address). */\n readonly context: ContextAccessor;\n /** Typed handles for each declared flow input, used to bind inputs to operations. */\n readonly inputs: InputHandles<T>;\n /**\n * Appends an untyped operation node to the flow. This is an escape hatch\n * for operations not yet covered by the generated methods.\n *\n * Use `raw.ref<T>()` to reference this node's outputs in subsequent typed\n * operations.\n *\n * @param id - Unique node identifier within the flow.\n * @param op - The operation name (e.g. `\"custom.vaultQuery\"`).\n * @param args - Bind map, config, and optional guards for the node.\n * @throws Error if a node with the same `id` already exists in the flow.\n */\n readonly untypedOp: (\n id: string,\n op: string,\n args: {\n readonly bind: Record<string, BindValue>;\n readonly config: Record<string, unknown>;\n readonly guards?: readonly AppliedGuard[];\n },\n ) => void;\n /** Serialises the builder state into a {@link TypedFlow} document. */\n readonly build: () => TypedFlow<T>;\n}\n\n/** Maps output port names to their output kind for compile-time and runtime validation. */\nexport type OutputSpec = Record<string, OutputKind>;\n\n/**\n * Maps each output family's port name to the config key that sizes it: an\n * array (one instance per element) or a non-negative integer count.\n * A family port is also listed in the {@link OutputSpec}, as `'resource'`.\n */\nexport type FamilySpec = Readonly<Record<string, string>>;\n\n/** The handles `call` returns for an {@link OutputSpec} and its families. */\nexport type OutputHandles<O extends OutputSpec, F extends FamilySpec> = {\n readonly [K in keyof O & string]: K extends keyof F\n ? readonly OutputHandle<'resource'>[]\n : OutputHandle<O[K]>;\n};\n\n/** Internal interface exposed to bindGeneratedOps — not part of the public API. */\nexport interface FlowBuilderInternal<\n T extends InputSchema = InputSchema,\n> extends FlowBuilderCore<T> {\n readonly call: <\n O extends OutputSpec,\n F extends FamilySpec = Record<never, string>,\n >(\n nodeId: string,\n op: string,\n args: CallArgs,\n outputs: O,\n families?: F,\n ) => OutputHandles<O, F>;\n}\n\nconst isResource = (decl: InputDecl): decl is Resource =>\n typeof decl === 'object' && decl !== null && 'kind' in decl;\n\n/**\n * Creates a new flow builder targeting the given chain.\n *\n * @param chainId - The EVM chain ID (e.g. `1` for Ethereum mainnet).\n * @param options - Flow configuration including input declarations.\n * @returns A {@link FlowBuilderInternal} instance.\n * @internal\n */\nexport const createFlowBuilderCore = <T extends InputSchema>(\n chainId: number,\n options: FlowOptions<T>,\n): FlowBuilderInternal<T> => {\n const id = options.name ?? crypto.randomUUID();\n const flowInputs: FlowInput[] = [];\n const nodes: Call[] = [];\n const nodeIds = new Set<string>();\n\n const inputHandles = {} as Record<string, InputHandle | ResourceInputHandle>;\n for (const [name, decl] of Object.entries(options.inputs)) {\n if (isResource(decl)) {\n if (decl.chainId !== chainId) {\n throw new Error(\n `Input \"${name}\" has chainId ${decl.chainId} but flow targets chain ${chainId}`,\n );\n }\n flowInputs.push({ name, resource: decl });\n inputHandles[name] = { _tag: 'input', inputName: name, resource: decl };\n } else {\n flowInputs.push({ name, type: decl });\n inputHandles[name] = { _tag: 'input', inputName: name };\n }\n }\n\n const call = <\n O extends OutputSpec,\n F extends FamilySpec = Record<never, string>,\n >(\n nodeId: string,\n op: string,\n args: CallArgs,\n outputs: O,\n families?: F,\n ): OutputHandles<O, F> => {\n if (nodeIds.has(nodeId)) throw new Error(`Duplicate node id: \"${nodeId}\"`);\n nodeIds.add(nodeId);\n\n const bind: Record<string, BindValue> = {};\n for (const [key, val] of Object.entries(args.bind)) {\n bind[key] = toBindValue(val);\n }\n\n const config = (args.config ?? {}) as Record<string, unknown>;\n const node: Call = {\n id: nodeId,\n op,\n bind,\n config,\n ...(args.guards && args.guards.length > 0 && { guards: args.guards }),\n };\n nodes.push(node);\n\n const outputHandle = (portName: string): OutputHandle => ({\n _tag: 'output',\n nodeId,\n portName,\n });\n return new Proxy({} as OutputHandles<O, F>, {\n get: (\n _target,\n prop,\n ): OutputHandle | readonly OutputHandle[] | undefined => {\n if (typeof prop !== 'string' || prop === 'then') return undefined;\n // Own-key only: the trap sees every property a consumer reads, so `in`\n // would answer a handle for `toString` or `constructor` instead of the\n // unknown-port error.\n if (!Object.hasOwn(outputs, prop)) {\n throw new Error(\n `Op \"${op}\" has no output port \"${prop}\". Valid ports: ${Object.keys(\n outputs,\n ).join(', ')}`,\n );\n }\n const countFrom = families?.[prop];\n if (countFrom === undefined) return outputHandle(prop);\n const size = familySize({ name: prop, countFrom }, config);\n return Array.from({ length: size }, (_, index) =>\n outputHandle(instancePortName(prop, index)),\n );\n },\n });\n };\n\n const untypedOp = (\n nodeId: string,\n op: string,\n args: {\n readonly bind: Record<string, BindValue>;\n readonly config: Record<string, unknown>;\n readonly guards?: readonly AppliedGuard[];\n },\n ): void => {\n if (nodeIds.has(nodeId)) throw new Error(`Duplicate node id: \"${nodeId}\"`);\n nodeIds.add(nodeId);\n const node: Call = {\n id: nodeId,\n op,\n bind: args.bind,\n config: args.config,\n ...(args.guards && args.guards.length > 0 && { guards: args.guards }),\n };\n nodes.push(node);\n };\n\n const build = (): TypedFlow<T> => ({\n version: 1,\n id,\n chainId,\n inputs: [...flowInputs],\n nodes: [...nodes],\n });\n\n const context: ContextAccessor = {\n sender: ref<'address'>('context.sender'),\n executionAddress: ref<'address'>('context.executionAddress'),\n };\n\n return {\n context,\n inputs: inputHandles as InputHandles<T>,\n call,\n untypedOp,\n build,\n };\n};\n"],"mappings":"AAAA;AAAA,EAIE;AAAA,EAGA;AAAA,OAIK;AAgBP,SAAS,mBAAmB;AAC5B,SAAS,WAAW;AAwJpB,MAAM,aAAa,CAAC,SAClB,OAAO,SAAS,YAAY,SAAS,QAAQ,UAAU;AAUlD,MAAM,wBAAwB,CACnC,SACA,YAC2B;AAC3B,QAAM,KAAK,QAAQ,QAAQ,OAAO,WAAW;AAC7C,QAAM,aAA0B,CAAC;AACjC,QAAM,QAAgB,CAAC;AACvB,QAAM,UAAU,oBAAI,IAAY;AAEhC,QAAM,eAAe,CAAC;AACtB,aAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,QAAQ,MAAM,GAAG;AACzD,QAAI,WAAW,IAAI,GAAG;AACpB,UAAI,KAAK,YAAY,SAAS;AAC5B,cAAM,IAAI;AAAA,UACR,UAAU,IAAI,iBAAiB,KAAK,OAAO,2BAA2B,OAAO;AAAA,QAC/E;AAAA,MACF;AACA,iBAAW,KAAK,EAAE,MAAM,UAAU,KAAK,CAAC;AACxC,mBAAa,IAAI,IAAI,EAAE,MAAM,SAAS,WAAW,MAAM,UAAU,KAAK;AAAA,IACxE,OAAO;AACL,iBAAW,KAAK,EAAE,MAAM,MAAM,KAAK,CAAC;AACpC,mBAAa,IAAI,IAAI,EAAE,MAAM,SAAS,WAAW,KAAK;AAAA,IACxD;AAAA,EACF;AAEA,QAAM,OAAO,CAIX,QACA,IACA,MACA,SACA,aACwB;AACxB,QAAI,QAAQ,IAAI,MAAM,EAAG,OAAM,IAAI,MAAM,uBAAuB,MAAM,GAAG;AACzE,YAAQ,IAAI,MAAM;AAElB,UAAM,OAAkC,CAAC;AACzC,eAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,KAAK,IAAI,GAAG;AAClD,WAAK,GAAG,IAAI,YAAY,GAAG;AAAA,IAC7B;AAEA,UAAM,SAAU,KAAK,UAAU,CAAC;AAChC,UAAM,OAAa;AAAA,MACjB,IAAI;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAI,KAAK,UAAU,KAAK,OAAO,SAAS,KAAK,EAAE,QAAQ,KAAK,OAAO;AAAA,IACrE;AACA,UAAM,KAAK,IAAI;AAEf,UAAM,eAAe,CAAC,cAAoC;AAAA,MACxD,MAAM;AAAA,MACN;AAAA,MACA;AAAA,IACF;AACA,WAAO,IAAI,MAAM,CAAC,GAA0B;AAAA,MAC1C,KAAK,CACH,SACA,SACuD;AACvD,YAAI,OAAO,SAAS,YAAY,SAAS,OAAQ,QAAO;AAIxD,YAAI,CAAC,OAAO,OAAO,SAAS,IAAI,GAAG;AACjC,gBAAM,IAAI;AAAA,YACR,OAAO,EAAE,yBAAyB,IAAI,mBAAmB,OAAO;AAAA,cAC9D;AAAA,YACF,EAAE,KAAK,IAAI,CAAC;AAAA,UACd;AAAA,QACF;AACA,cAAM,YAAY,WAAW,IAAI;AACjC,YAAI,cAAc,OAAW,QAAO,aAAa,IAAI;AACrD,cAAM,OAAO,WAAW,EAAE,MAAM,MAAM,UAAU,GAAG,MAAM;AACzD,eAAO,MAAM;AAAA,UAAK,EAAE,QAAQ,KAAK;AAAA,UAAG,CAAC,GAAG,UACtC,aAAa,iBAAiB,MAAM,KAAK,CAAC;AAAA,QAC5C;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,YAAY,CAChB,QACA,IACA,SAKS;AACT,QAAI,QAAQ,IAAI,MAAM,EAAG,OAAM,IAAI,MAAM,uBAAuB,MAAM,GAAG;AACzE,YAAQ,IAAI,MAAM;AAClB,UAAM,OAAa;AAAA,MACjB,IAAI;AAAA,MACJ;AAAA,MACA,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK;AAAA,MACb,GAAI,KAAK,UAAU,KAAK,OAAO,SAAS,KAAK,EAAE,QAAQ,KAAK,OAAO;AAAA,IACrE;AACA,UAAM,KAAK,IAAI;AAAA,EACjB;AAEA,QAAM,QAAQ,OAAqB;AAAA,IACjC,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA,QAAQ,CAAC,GAAG,UAAU;AAAA,IACtB,OAAO,CAAC,GAAG,KAAK;AAAA,EAClB;AAEA,QAAM,UAA2B;AAAA,IAC/B,QAAQ,IAAe,gBAAgB;AAAA,IACvC,kBAAkB,IAAe,0BAA0B;AAAA,EAC7D;AAEA,SAAO;AAAA,IACL;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"file":"FlowBuilderCore.js","names":[],"sources":["../../src/authoring/FlowBuilderCore.ts"],"sourcesContent":["import {\n type AppliedGuard,\n type BindValue,\n type Call,\n familySize,\n type Flow,\n type FlowInput,\n instancePortName,\n type Ref,\n type Resource,\n type SolType,\n} from '@lifi/compose-spec';\n\nimport type {\n InputDecl,\n InputSchema,\n OutputKind,\n TypedGuard,\n TypedLiteral,\n TypedRef,\n} from '../types.js';\n\nimport type {\n InputHandle,\n OutputHandle,\n ResourceInputHandle,\n} from './handles.js';\nimport { toBindValue } from './handles.js';\nimport { ref } from './raw.js';\n\n/**\n * Arguments for calling an operation node in a flow.\n */\nexport interface CallArgs {\n /** Maps parameter names to input/output handles or raw `$ref` pointers. */\n readonly bind: Record<string, AnyBindable>;\n /** Optional operation-specific configuration. */\n readonly config?: object;\n /** Optional guards (e.g. slippage checks) applied to this operation's outputs. */\n readonly guards?: readonly TypedGuard[];\n}\n\n/**\n * Any value that can be bound to an operation parameter: an input handle, an\n * output handle from a previous operation, a typed `$ref` pointer, a typed\n * literal, or a bare `{ $ref }` pointer.\n *\n * This is the bind type of {@link FlowBuilderInternal.call}, the entry point\n * every generated operation lowers into — not a public authoring surface. A\n * bare `Ref` belongs here because a generated op resolves its own typed binds\n * to wire refs (`toBindRef` in `./signatureArgs.js`) before calling it. Typed\n * operation slots use `Bindable<T>`, which rejects a bare `Ref`; see\n * `RefBindable` in `./handles.js`.\n *\n * Use `raw.ref<T>()` to create a typed ref from a raw path string, and\n * `raw.literal<T>()` to bake in a constant.\n */\nexport type AnyBindable =\n InputHandle | OutputHandle | TypedRef | TypedLiteral | Ref;\n\n/**\n * Provides references to runtime context values available inside a flow.\n * Access via `builder.context`.\n */\nexport interface ContextAccessor {\n /** A `$ref` pointing to the transaction sender (signer) address. */\n readonly sender: TypedRef<'address'>;\n /** A `$ref` pointing to the on-chain execution (proxy) address. */\n readonly executionAddress: TypedRef<'address'>;\n}\n\ntype InputHandleOf<D extends InputDecl> = D extends Resource\n ? ResourceInputHandle\n : D extends SolType\n ? InputHandle<D>\n : InputHandle;\n\n/**\n * A mapped type that converts an input schema into typed handles.\n * Resource inputs produce {@link ResourceInputHandle}; scalar inputs produce {@link InputHandle}.\n *\n * @typeParam T - The flow's input schema.\n */\nexport type InputHandles<T extends InputSchema> = {\n readonly [K in keyof T]: InputHandleOf<T[K]>;\n};\n\n/**\n * Options for creating a new flow builder.\n *\n * @typeParam T - The flow's input schema.\n */\nexport interface FlowOptions<T extends InputSchema> {\n /** Optional human-readable name for the flow. Defaults to a random UUID. */\n readonly name?: string;\n /** Input declarations mapping names to resource or scalar types. */\n readonly inputs: T;\n}\n\n/**\n * A Flow document branded with its input schema for type-safe request building.\n *\n * The `__inputs` field is a phantom type — it exists only at compile time for\n * TypeScript inference and is never present at runtime.\n */\nexport type TypedFlow<T extends InputSchema = InputSchema> = Flow & {\n readonly __inputs?: T;\n};\n\n/**\n * Core flow builder interface providing low-level access to flow construction.\n *\n * For most use cases, prefer the {@link FlowBuilder} type returned by `sdk.flow()`\n * which adds generated operation methods and a `compile` method.\n *\n * @typeParam T - The flow's input schema.\n */\nexport interface FlowBuilderCore<T extends InputSchema = InputSchema> {\n /** Runtime context references (sender address, execution address). */\n readonly context: ContextAccessor;\n /** Typed handles for each declared flow input, used to bind inputs to operations. */\n readonly inputs: InputHandles<T>;\n /**\n * Appends an untyped operation node to the flow. This is an escape hatch\n * for operations not yet covered by the generated methods.\n *\n * Use `raw.ref<T>()` to reference this node's outputs in subsequent typed\n * operations.\n *\n * @param id - Unique node identifier within the flow.\n * @param op - The operation name (e.g. `\"custom.vaultQuery\"`).\n * @param args - Bind map, config, and optional guards for the node.\n * @throws Error if a node with the same `id` already exists in the flow.\n */\n readonly untypedOp: (\n id: string,\n op: string,\n args: {\n readonly bind: Record<string, BindValue>;\n readonly config: Record<string, unknown>;\n readonly guards?: readonly AppliedGuard[];\n },\n ) => void;\n /** Serialises the builder state into a {@link TypedFlow} document. */\n readonly build: () => TypedFlow<T>;\n}\n\n/** Maps output port names to their output kind for compile-time and runtime validation. */\nexport type OutputSpec = Record<string, OutputKind>;\n\n/**\n * Maps each output family's port name to the config key that sizes it: an\n * array (one instance per element) or a non-negative integer count.\n * A family port is also listed in the {@link OutputSpec}, as `'resource'`.\n */\nexport type FamilySpec = Readonly<Record<string, string>>;\n\n/** The handles `call` returns for an {@link OutputSpec} and its families. */\nexport type OutputHandles<O extends OutputSpec, F extends FamilySpec> = {\n readonly [K in keyof O & string]: K extends keyof F\n ? readonly OutputHandle<'resource'>[]\n : OutputHandle<O[K]>;\n};\n\n/** Internal interface exposed to bindGeneratedOps — not part of the public API. */\nexport interface FlowBuilderInternal<\n T extends InputSchema = InputSchema,\n> extends FlowBuilderCore<T> {\n readonly call: <\n O extends OutputSpec,\n F extends FamilySpec = Record<never, string>,\n >(\n nodeId: string,\n op: string,\n args: CallArgs,\n outputs: O,\n families?: F,\n ) => OutputHandles<O, F>;\n}\n\nconst isResource = (decl: InputDecl): decl is Resource =>\n typeof decl === 'object' && decl !== null && 'kind' in decl;\n\n/**\n * Creates a new flow builder targeting the given chain.\n *\n * @param chainId - The EVM chain ID (e.g. `1` for Ethereum mainnet).\n * @param options - Flow configuration including input declarations.\n * @returns A {@link FlowBuilderInternal} instance.\n * @internal\n */\nexport const createFlowBuilderCore = <T extends InputSchema>(\n chainId: number,\n options: FlowOptions<T>,\n): FlowBuilderInternal<T> => {\n const id = options.name ?? crypto.randomUUID();\n const flowInputs: FlowInput[] = [];\n const nodes: Call[] = [];\n const nodeIds = new Set<string>();\n\n const inputHandles = {} as Record<string, InputHandle | ResourceInputHandle>;\n for (const [name, decl] of Object.entries(options.inputs)) {\n if (isResource(decl)) {\n if (decl.chainId !== chainId) {\n throw new Error(\n `Input \"${name}\" has chainId ${decl.chainId} but flow targets chain ${chainId}`,\n );\n }\n flowInputs.push({ name, resource: decl });\n inputHandles[name] = { _tag: 'input', inputName: name, resource: decl };\n } else {\n flowInputs.push({ name, type: decl });\n inputHandles[name] = { _tag: 'input', inputName: name };\n }\n }\n\n const call = <\n O extends OutputSpec,\n F extends FamilySpec = Record<never, string>,\n >(\n nodeId: string,\n op: string,\n args: CallArgs,\n outputs: O,\n families?: F,\n ): OutputHandles<O, F> => {\n if (nodeIds.has(nodeId)) throw new Error(`Duplicate node id: \"${nodeId}\"`);\n nodeIds.add(nodeId);\n\n const bind: Record<string, BindValue> = {};\n for (const [key, val] of Object.entries(args.bind)) {\n bind[key] = toBindValue(val);\n }\n\n const config = (args.config ?? {}) as Record<string, unknown>;\n const node: Call = {\n id: nodeId,\n op,\n bind,\n config,\n ...(args.guards && args.guards.length > 0 && { guards: args.guards }),\n };\n nodes.push(node);\n\n const outputHandle = (portName: string): OutputHandle => ({\n _tag: 'output',\n nodeId,\n portName,\n });\n return new Proxy({} as OutputHandles<O, F>, {\n get: (\n _target,\n prop,\n ): OutputHandle | readonly OutputHandle[] | undefined => {\n if (typeof prop !== 'string' || prop === 'then') return undefined;\n // Own-key only: the trap sees every property a consumer reads, so `in`\n // would answer a handle for `toString` or `constructor` instead of the\n // unknown-port error.\n if (!Object.hasOwn(outputs, prop)) {\n throw new Error(\n `Op \"${op}\" has no output port \"${prop}\". Valid ports: ${Object.keys(\n outputs,\n ).join(', ')}`,\n );\n }\n const countFrom = families?.[prop];\n if (countFrom === undefined) return outputHandle(prop);\n const size = familySize({ name: prop, countFrom }, config);\n return Array.from({ length: size }, (_, index) =>\n outputHandle(instancePortName(prop, index)),\n );\n },\n });\n };\n\n const untypedOp = (\n nodeId: string,\n op: string,\n args: {\n readonly bind: Record<string, BindValue>;\n readonly config: Record<string, unknown>;\n readonly guards?: readonly AppliedGuard[];\n },\n ): void => {\n if (nodeIds.has(nodeId)) throw new Error(`Duplicate node id: \"${nodeId}\"`);\n nodeIds.add(nodeId);\n const node: Call = {\n id: nodeId,\n op,\n bind: args.bind,\n config: args.config,\n ...(args.guards && args.guards.length > 0 && { guards: args.guards }),\n };\n nodes.push(node);\n };\n\n const build = (): TypedFlow<T> => ({\n version: 1,\n id,\n chainId,\n inputs: [...flowInputs],\n nodes: [...nodes],\n });\n\n const context: ContextAccessor = {\n sender: ref<'address'>('context.sender'),\n executionAddress: ref<'address'>('context.executionAddress'),\n };\n\n return {\n context,\n inputs: inputHandles as InputHandles<T>,\n call,\n untypedOp,\n build,\n };\n};\n"],"mappings":";;;;AAoLA,MAAM,cAAc,SAClB,OAAO,SAAS,YAAY,SAAS,QAAQ,UAAU;;;;;;;;;AAUzD,MAAa,yBACX,SACA,YAC2B;CAC3B,MAAM,KAAK,QAAQ,QAAQ,OAAO,WAAW;CAC7C,MAAM,aAA0B,CAAC;CACjC,MAAM,QAAgB,CAAC;CACvB,MAAM,0BAAU,IAAI,IAAY;CAEhC,MAAM,eAAe,CAAC;CACtB,KAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,QAAQ,MAAM,GACtD,IAAI,WAAW,IAAI,GAAG;EACpB,IAAI,KAAK,YAAY,SACnB,MAAM,IAAI,MACR,UAAU,KAAK,gBAAgB,KAAK,QAAQ,0BAA0B,SACxE;EAEF,WAAW,KAAK;GAAE;GAAM,UAAU;EAAK,CAAC;EACxC,aAAa,QAAQ;GAAE,MAAM;GAAS,WAAW;GAAM,UAAU;EAAK;CACxE,OAAO;EACL,WAAW,KAAK;GAAE;GAAM,MAAM;EAAK,CAAC;EACpC,aAAa,QAAQ;GAAE,MAAM;GAAS,WAAW;EAAK;CACxD;CAGF,MAAM,QAIJ,QACA,IACA,MACA,SACA,aACwB;EACxB,IAAI,QAAQ,IAAI,MAAM,GAAG,MAAM,IAAI,MAAM,uBAAuB,OAAO,EAAE;EACzE,QAAQ,IAAI,MAAM;EAElB,MAAM,OAAkC,CAAC;EACzC,KAAK,MAAM,CAAC,KAAK,QAAQ,OAAO,QAAQ,KAAK,IAAI,GAC/C,KAAK,OAAO,YAAY,GAAG;EAG7B,MAAM,SAAU,KAAK,UAAU,CAAC;EAChC,MAAM,OAAa;GACjB,IAAI;GACJ;GACA;GACA;GACA,GAAI,KAAK,UAAU,KAAK,OAAO,SAAS,KAAK,EAAE,QAAQ,KAAK,OAAO;EACrE;EACA,MAAM,KAAK,IAAI;EAEf,MAAM,gBAAgB,cAAoC;GACxD,MAAM;GACN;GACA;EACF;EACA,OAAO,IAAI,MAAM,CAAC,GAA0B,EAC1C,MACE,SACA,SACuD;GACvD,IAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,OAAO,KAAA;GAIxD,IAAI,CAAC,OAAO,OAAO,SAAS,IAAI,GAC9B,MAAM,IAAI,MACR,OAAO,GAAG,wBAAwB,KAAK,kBAAkB,OAAO,KAC9D,OACF,CAAC,CAAC,KAAK,IAAI,GACb;GAEF,MAAM,YAAY,WAAW;GAC7B,IAAI,cAAc,KAAA,GAAW,OAAO,aAAa,IAAI;GACrD,MAAM,OAAO,WAAW;IAAE,MAAM;IAAM;GAAU,GAAG,MAAM;GACzD,OAAO,MAAM,KAAK,EAAE,QAAQ,KAAK,IAAI,GAAG,UACtC,aAAa,iBAAiB,MAAM,KAAK,CAAC,CAC5C;EACF,EACF,CAAC;CACH;CAEA,MAAM,aACJ,QACA,IACA,SAKS;EACT,IAAI,QAAQ,IAAI,MAAM,GAAG,MAAM,IAAI,MAAM,uBAAuB,OAAO,EAAE;EACzE,QAAQ,IAAI,MAAM;EAClB,MAAM,OAAa;GACjB,IAAI;GACJ;GACA,MAAM,KAAK;GACX,QAAQ,KAAK;GACb,GAAI,KAAK,UAAU,KAAK,OAAO,SAAS,KAAK,EAAE,QAAQ,KAAK,OAAO;EACrE;EACA,MAAM,KAAK,IAAI;CACjB;CAEA,MAAM,eAA6B;EACjC,SAAS;EACT;EACA;EACA,QAAQ,CAAC,GAAG,UAAU;EACtB,OAAO,CAAC,GAAG,KAAK;CAClB;CAOA,OAAO;EACL,SAAA;GALA,QAAQ,IAAe,gBAAgB;GACvC,kBAAkB,IAAe,0BAA0B;EAIrD;EACN,QAAQ;EACR;EACA;EACA;CACF;AACF"}
@@ -1,46 +1,31 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
- var handles_exports = {};
20
- __export(handles_exports, {
21
- handleToRef: () => handleToRef,
22
- isInputHandle: () => isInputHandle,
23
- isOutputHandle: () => isOutputHandle,
24
- toBindValue: () => toBindValue
25
- });
26
- module.exports = __toCommonJS(handles_exports);
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/authoring/handles.ts
3
+ /** Type guard that narrows an {@link AnyHandle} to an {@link InputHandle}. */
27
4
  const isInputHandle = (h) => h._tag === "input";
5
+ /** Type guard that narrows an {@link AnyHandle} to an {@link OutputHandle}. */
28
6
  const isOutputHandle = (h) => h._tag === "output";
7
+ /**
8
+ * Converts a handle to a JSON `$ref` pointer used in the flow document.
9
+ * Input handles become `"input.<name>"`; output handles become `"<nodeId>.<port>"`.
10
+ */
29
11
  const handleToRef = (h) => {
30
- if (h._tag === "input") {
31
- if (!h.inputName) throw new Error("InputHandle has empty inputName");
32
- return { $ref: `input.${h.inputName}` };
33
- }
34
- if (!h.nodeId) throw new Error("OutputHandle has empty nodeId");
35
- if (!h.portName) throw new Error("OutputHandle has empty portName");
36
- return { $ref: `${h.nodeId}.${h.portName}` };
12
+ if (h._tag === "input") {
13
+ if (!h.inputName) throw new Error("InputHandle has empty inputName");
14
+ return { $ref: `input.${h.inputName}` };
15
+ }
16
+ if (!h.nodeId) throw new Error("OutputHandle has empty nodeId");
17
+ if (!h.portName) throw new Error("OutputHandle has empty portName");
18
+ return { $ref: `${h.nodeId}.${h.portName}` };
37
19
  };
20
+ /**
21
+ * Converts a bindable to the wire `bind` value it denotes: handles become
22
+ * `$ref` pointers, refs and literals pass through as-is.
23
+ */
38
24
  const toBindValue = (bindable) => "_tag" in bindable ? handleToRef(bindable) : bindable;
39
- // Annotate the CommonJS export names for ESM import in node:
40
- 0 && (module.exports = {
41
- handleToRef,
42
- isInputHandle,
43
- isOutputHandle,
44
- toBindValue
45
- });
25
+ //#endregion
26
+ exports.handleToRef = handleToRef;
27
+ exports.isInputHandle = isInputHandle;
28
+ exports.isOutputHandle = isOutputHandle;
29
+ exports.toBindValue = toBindValue;
30
+
46
31
  //# sourceMappingURL=handles.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/authoring/handles.ts"],"sourcesContent":["import type {\n BindValue,\n Ref,\n Resource,\n SolType,\n StaticSolType,\n} from '@lifi/compose-spec';\n\nimport type { OutputKind, TypedLiteral, TypedRef } from '../types.js';\n\n/**\n * A handle referencing a flow input declared in the flow's input schema.\n * The phantom `__outputKind` field carries the type parameter through\n * TypeScript's structural type system without affecting runtime shape.\n */\nexport interface InputHandle<T extends OutputKind = OutputKind> {\n readonly _tag: 'input';\n readonly inputName: string;\n readonly __outputKind?: T;\n}\n\n/**\n * An input handle for a resource (token) input, carrying the resource\n * declaration alongside the reference.\n */\nexport interface ResourceInputHandle extends InputHandle<'resource'> {\n readonly resource: Resource;\n}\n\n/**\n * A handle referencing an output port of a previously declared operation node.\n * The phantom `__outputKind` field carries the type parameter through\n * TypeScript's structural type system without affecting runtime shape.\n */\nexport interface OutputHandle<T extends OutputKind = OutputKind> {\n readonly _tag: 'output';\n readonly nodeId: string;\n readonly portName: string;\n readonly __outputKind?: T;\n}\n\n/**\n * What an output family's sizing parameter accepts, given the config field the\n * family counts from: an array of that field's elements, or a number.\n */\nexport type FamilySource<Field> = Field extends readonly (infer E)[]\n ? readonly E[]\n : number;\n\n/** Whether a number literal is a valid family count: a non-negative integer. */\ntype IsCountLiteral<N extends number> = `${N}` extends\n `-${string}` | `${string}.${string}` | `${string}e${string}`\n ? false\n : true;\n\n/**\n * `N` resource handles as a tuple. A non-literal `number`, or a literal that is\n * not a valid count, gives an open array; {@link FamilyCount} rejects the\n * invalid literal at the call site.\n */\ntype HandleTuple<\n N extends number,\n Acc extends readonly OutputHandle<'resource'>[] = readonly [],\n> = number extends N\n ? readonly OutputHandle<'resource'>[]\n : IsCountLiteral<N> extends false\n ? readonly OutputHandle<'resource'>[]\n : Acc['length'] extends N\n ? Acc\n : HandleTuple<N, readonly [...Acc, OutputHandle<'resource'>]>;\n\n/**\n * The handles of an output family: one resource {@link OutputHandle} per\n * element of the config array the family counts from, or as many as the config\n * count. A literal array or count yields a tuple of that length, so indexing\n * past the last instance is a type error.\n */\nexport type OutputFamilyHandles<TCount extends readonly unknown[] | number> =\n TCount extends readonly unknown[]\n ? { readonly [I in keyof TCount]: OutputHandle<'resource'> }\n : TCount extends number\n ? HandleTuple<TCount>\n : never;\n\n/**\n * Holds the config value an output family counts from to the op's own type. A\n * runtime-sized array or count passes as is. A literal tuple must also satisfy\n * `Shape`, so a tuple shorter than the op's `minItems` fails at the call site\n * instead of at the server's bind step. A literal count must be a non-negative\n * integer.\n */\nexport type FamilyCount<\n TCount extends readonly unknown[] | number,\n Shape,\n> = TCount extends readonly unknown[]\n ? number extends TCount['length']\n ? unknown\n : TCount extends Shape\n ? unknown\n : { readonly 'output family config array has too few entries': never }\n : TCount extends number\n ? IsCountLiteral<TCount> extends true\n ? unknown\n : {\n readonly 'output family count must be a non-negative integer': never;\n }\n : unknown;\n\n/** Discriminated union of all handle types that can be bound to operation arguments. */\nexport type AnyHandle = InputHandle | OutputHandle;\n\n/** Type guard that narrows an {@link AnyHandle} to an {@link InputHandle}. */\nexport const isInputHandle = (h: AnyHandle): h is InputHandle =>\n h._tag === 'input';\n\n/** Type guard that narrows an {@link AnyHandle} to an {@link OutputHandle}. */\nexport const isOutputHandle = (h: AnyHandle): h is OutputHandle =>\n h._tag === 'output';\n\n/**\n * Converts a handle to a JSON `$ref` pointer used in the flow document.\n * Input handles become `\"input.<name>\"`; output handles become `\"<nodeId>.<port>\"`.\n */\nexport const handleToRef = (h: AnyHandle): { $ref: string } => {\n if (h._tag === 'input') {\n if (!h.inputName) throw new Error('InputHandle has empty inputName');\n return { $ref: `input.${h.inputName}` };\n }\n if (!h.nodeId) throw new Error('OutputHandle has empty nodeId');\n if (!h.portName) throw new Error('OutputHandle has empty portName');\n return { $ref: `${h.nodeId}.${h.portName}` };\n};\n\n/**\n * For a bind slot expecting type T, widen the set of accepted handle types:\n * - `'bytes32'` is the raw 32-byte word type: accept any static-32-byte handle\n * (`uint256`/`uintN`/`address`/`bool`/`bytes32`) plus `'resource'` (a uint256\n * amount). At the IR1 boundary every value is a type-erased word, so any\n * static-32-byte handle is a sound bind for a `bytes32` payload port.\n * - `'uint256'` keeps its existing widening to also accept `'resource'`-tagged\n * handles (resources are uint256 amounts).\n * - every other type keeps exact-SolType matching.\n */\ntype SlotAssignable<T extends OutputKind> = T extends 'bytes32'\n ? StaticSolType | 'resource'\n : T extends 'uint256'\n ? T | 'resource'\n : T;\n\n/**\n * The values accepted by a typed slot that must resolve to a `$ref`:\n * - `OutputHandle<T>` / `InputHandle<T>` (same type)\n * - For `'uint256'` slots, also `'resource'`-tagged handles\n * - For `'bytes32'` slots, any static-32-byte handle (and `'resource'`)\n * - `TypedRef<T>` (typed context refs, subject to `SlotAssignable`)\n *\n * Plain `{ $ref: '...' }` objects are **not** accepted - use `raw.ref<T>()`\n * to create a typed ref when you need to reference a raw path.\n */\nexport type RefBindable<T extends OutputKind> =\n | OutputHandle<SlotAssignable<T>>\n | InputHandle<SlotAssignable<T>>\n | TypedRef<SlotAssignable<T>>;\n\n/**\n * Any ref-resolving bindable, with no per-slot type constraint.\n */\nexport type AnyRefBindable = InputHandle | OutputHandle | TypedRef;\n\n/**\n * The set of values accepted by a typed operation bind slot: everything\n * {@link RefBindable} accepts, plus a {@link TypedLiteral} constant baked\n * into the flow document. A `'resource'` slot rejects a literal: a token\n * resource is not a scalar constant.\n *\n * Use `raw.literal<T>()` to create one.\n */\nexport type Bindable<T extends OutputKind> =\n RefBindable<T> | LiteralBindable<SlotAssignable<T>>;\n\n// Distributes over the slot's assignable kinds and keeps the scalar ones: a\n// `'resource'` slot has no scalar arm, so its literal arm collapses to\n// `never` and a literal is rejected outright.\ntype LiteralBindable<K extends OutputKind> = K extends SolType\n ? TypedLiteral<K>\n : never;\n\n/**\n * Converts a bindable to the wire `bind` value it denotes: handles become\n * `$ref` pointers, refs and literals pass through as-is.\n */\nexport const toBindValue = (\n bindable: InputHandle | OutputHandle | TypedRef | TypedLiteral | Ref,\n): BindValue => ('_tag' in bindable ? handleToRef(bindable) : bindable);\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgHO,MAAM,gBAAgB,CAAC,MAC5B,EAAE,SAAS;AAGN,MAAM,iBAAiB,CAAC,MAC7B,EAAE,SAAS;AAMN,MAAM,cAAc,CAAC,MAAmC;AAC7D,MAAI,EAAE,SAAS,SAAS;AACtB,QAAI,CAAC,EAAE,UAAW,OAAM,IAAI,MAAM,iCAAiC;AACnE,WAAO,EAAE,MAAM,SAAS,EAAE,SAAS,GAAG;AAAA,EACxC;AACA,MAAI,CAAC,EAAE,OAAQ,OAAM,IAAI,MAAM,+BAA+B;AAC9D,MAAI,CAAC,EAAE,SAAU,OAAM,IAAI,MAAM,iCAAiC;AAClE,SAAO,EAAE,MAAM,GAAG,EAAE,MAAM,IAAI,EAAE,QAAQ,GAAG;AAC7C;AA4DO,MAAM,cAAc,CACzB,aACe,UAAU,WAAW,YAAY,QAAQ,IAAI;","names":[]}
1
+ {"version":3,"file":"handles.cjs","names":[],"sources":["../../src/authoring/handles.ts"],"sourcesContent":["import type {\n BindValue,\n Ref,\n Resource,\n SolType,\n StaticSolType,\n} from '@lifi/compose-spec';\n\nimport type { OutputKind, TypedLiteral, TypedRef } from '../types.js';\n\n/**\n * A handle referencing a flow input declared in the flow's input schema.\n * The phantom `__outputKind` field carries the type parameter through\n * TypeScript's structural type system without affecting runtime shape.\n */\nexport interface InputHandle<T extends OutputKind = OutputKind> {\n readonly _tag: 'input';\n readonly inputName: string;\n readonly __outputKind?: T;\n}\n\n/**\n * An input handle for a resource (token) input, carrying the resource\n * declaration alongside the reference.\n */\nexport interface ResourceInputHandle extends InputHandle<'resource'> {\n readonly resource: Resource;\n}\n\n/**\n * A handle referencing an output port of a previously declared operation node.\n * The phantom `__outputKind` field carries the type parameter through\n * TypeScript's structural type system without affecting runtime shape.\n */\nexport interface OutputHandle<T extends OutputKind = OutputKind> {\n readonly _tag: 'output';\n readonly nodeId: string;\n readonly portName: string;\n readonly __outputKind?: T;\n}\n\n/**\n * What an output family's sizing parameter accepts, given the config field the\n * family counts from: an array of that field's elements, or a number.\n */\nexport type FamilySource<Field> = Field extends readonly (infer E)[]\n ? readonly E[]\n : number;\n\n/** Whether a number literal is a valid family count: a non-negative integer. */\ntype IsCountLiteral<N extends number> = `${N}` extends\n `-${string}` | `${string}.${string}` | `${string}e${string}`\n ? false\n : true;\n\n/**\n * `N` resource handles as a tuple. A non-literal `number`, or a literal that is\n * not a valid count, gives an open array; {@link FamilyCount} rejects the\n * invalid literal at the call site.\n */\ntype HandleTuple<\n N extends number,\n Acc extends readonly OutputHandle<'resource'>[] = readonly [],\n> = number extends N\n ? readonly OutputHandle<'resource'>[]\n : IsCountLiteral<N> extends false\n ? readonly OutputHandle<'resource'>[]\n : Acc['length'] extends N\n ? Acc\n : HandleTuple<N, readonly [...Acc, OutputHandle<'resource'>]>;\n\n/**\n * The handles of an output family: one resource {@link OutputHandle} per\n * element of the config array the family counts from, or as many as the config\n * count. A literal array or count yields a tuple of that length, so indexing\n * past the last instance is a type error.\n */\nexport type OutputFamilyHandles<TCount extends readonly unknown[] | number> =\n TCount extends readonly unknown[]\n ? { readonly [I in keyof TCount]: OutputHandle<'resource'> }\n : TCount extends number\n ? HandleTuple<TCount>\n : never;\n\n/**\n * Holds the config value an output family counts from to the op's own type. A\n * runtime-sized array or count passes as is. A literal tuple must also satisfy\n * `Shape`, so a tuple shorter than the op's `minItems` fails at the call site\n * instead of at the server's bind step. A literal count must be a non-negative\n * integer.\n */\nexport type FamilyCount<\n TCount extends readonly unknown[] | number,\n Shape,\n> = TCount extends readonly unknown[]\n ? number extends TCount['length']\n ? unknown\n : TCount extends Shape\n ? unknown\n : { readonly 'output family config array has too few entries': never }\n : TCount extends number\n ? IsCountLiteral<TCount> extends true\n ? unknown\n : {\n readonly 'output family count must be a non-negative integer': never;\n }\n : unknown;\n\n/** Discriminated union of all handle types that can be bound to operation arguments. */\nexport type AnyHandle = InputHandle | OutputHandle;\n\n/** Type guard that narrows an {@link AnyHandle} to an {@link InputHandle}. */\nexport const isInputHandle = (h: AnyHandle): h is InputHandle =>\n h._tag === 'input';\n\n/** Type guard that narrows an {@link AnyHandle} to an {@link OutputHandle}. */\nexport const isOutputHandle = (h: AnyHandle): h is OutputHandle =>\n h._tag === 'output';\n\n/**\n * Converts a handle to a JSON `$ref` pointer used in the flow document.\n * Input handles become `\"input.<name>\"`; output handles become `\"<nodeId>.<port>\"`.\n */\nexport const handleToRef = (h: AnyHandle): { $ref: string } => {\n if (h._tag === 'input') {\n if (!h.inputName) throw new Error('InputHandle has empty inputName');\n return { $ref: `input.${h.inputName}` };\n }\n if (!h.nodeId) throw new Error('OutputHandle has empty nodeId');\n if (!h.portName) throw new Error('OutputHandle has empty portName');\n return { $ref: `${h.nodeId}.${h.portName}` };\n};\n\n/**\n * For a bind slot expecting type T, widen the set of accepted handle types:\n * - `'bytes32'` is the raw 32-byte word type: accept any static-32-byte handle\n * (`uint256`/`uintN`/`address`/`bool`/`bytes32`) plus `'resource'` (a uint256\n * amount). At the IR1 boundary every value is a type-erased word, so any\n * static-32-byte handle is a sound bind for a `bytes32` payload port.\n * - `'uint256'` keeps its existing widening to also accept `'resource'`-tagged\n * handles (resources are uint256 amounts).\n * - every other type keeps exact-SolType matching.\n */\ntype SlotAssignable<T extends OutputKind> = T extends 'bytes32'\n ? StaticSolType | 'resource'\n : T extends 'uint256'\n ? T | 'resource'\n : T;\n\n/**\n * The values accepted by a typed slot that must resolve to a `$ref`:\n * - `OutputHandle<T>` / `InputHandle<T>` (same type)\n * - For `'uint256'` slots, also `'resource'`-tagged handles\n * - For `'bytes32'` slots, any static-32-byte handle (and `'resource'`)\n * - `TypedRef<T>` (typed context refs, subject to `SlotAssignable`)\n *\n * Plain `{ $ref: '...' }` objects are **not** accepted - use `raw.ref<T>()`\n * to create a typed ref when you need to reference a raw path.\n */\nexport type RefBindable<T extends OutputKind> =\n | OutputHandle<SlotAssignable<T>>\n | InputHandle<SlotAssignable<T>>\n | TypedRef<SlotAssignable<T>>;\n\n/**\n * Any ref-resolving bindable, with no per-slot type constraint.\n */\nexport type AnyRefBindable = InputHandle | OutputHandle | TypedRef;\n\n/**\n * The set of values accepted by a typed operation bind slot: everything\n * {@link RefBindable} accepts, plus a {@link TypedLiteral} constant baked\n * into the flow document. A `'resource'` slot rejects a literal: a token\n * resource is not a scalar constant.\n *\n * Use `raw.literal<T>()` to create one.\n */\nexport type Bindable<T extends OutputKind> =\n RefBindable<T> | LiteralBindable<SlotAssignable<T>>;\n\n// Distributes over the slot's assignable kinds and keeps the scalar ones: a\n// `'resource'` slot has no scalar arm, so its literal arm collapses to\n// `never` and a literal is rejected outright.\ntype LiteralBindable<K extends OutputKind> = K extends SolType\n ? TypedLiteral<K>\n : never;\n\n/**\n * Converts a bindable to the wire `bind` value it denotes: handles become\n * `$ref` pointers, refs and literals pass through as-is.\n */\nexport const toBindValue = (\n bindable: InputHandle | OutputHandle | TypedRef | TypedLiteral | Ref,\n): BindValue => ('_tag' in bindable ? handleToRef(bindable) : bindable);\n"],"mappings":";;;AAgHA,MAAa,iBAAiB,MAC5B,EAAE,SAAS;;AAGb,MAAa,kBAAkB,MAC7B,EAAE,SAAS;;;;;AAMb,MAAa,eAAe,MAAmC;CAC7D,IAAI,EAAE,SAAS,SAAS;EACtB,IAAI,CAAC,EAAE,WAAW,MAAM,IAAI,MAAM,iCAAiC;EACnE,OAAO,EAAE,MAAM,SAAS,EAAE,YAAY;CACxC;CACA,IAAI,CAAC,EAAE,QAAQ,MAAM,IAAI,MAAM,+BAA+B;CAC9D,IAAI,CAAC,EAAE,UAAU,MAAM,IAAI,MAAM,iCAAiC;CAClE,OAAO,EAAE,MAAM,GAAG,EAAE,OAAO,GAAG,EAAE,WAAW;AAC7C;;;;;AA4DA,MAAa,eACX,aACe,UAAU,WAAW,YAAY,QAAQ,IAAI"}