@ic-reactor/candid 3.0.8-beta.2 → 3.0.10-beta.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.
@@ -1,16 +1,15 @@
1
1
  import type {
2
2
  BaseActor,
3
3
  FunctionName,
4
- DisplayOf,
5
4
  FunctionType,
6
5
  ActorMethodReturnType,
7
6
  } from "@ic-reactor/core"
8
7
 
9
8
  // ════════════════════════════════════════════════════════════════════════════
10
- // Field Type Union
9
+ // Core Types & Formats
11
10
  // ════════════════════════════════════════════════════════════════════════════
12
11
 
13
- export type ResultFieldType =
12
+ export type NodeType =
14
13
  | "record"
15
14
  | "variant"
16
15
  | "tuple"
@@ -25,35 +24,20 @@ export type ResultFieldType =
25
24
  | "null"
26
25
  | "unknown"
27
26
 
28
- // ════════════════════════════════════════════════════════════════════════════
29
- // Display Type (what it becomes after transformation)
30
- // ════════════════════════════════════════════════════════════════════════════
31
-
32
27
  export type DisplayType =
33
- | "string" // Principal, nat, int, nat64, int64, blob, text
34
- | "number" // float32, float64, nat8-nat32, int8-int32
35
- | "boolean" // bool
36
- | "null" // null
37
- | "object" // record
38
- | "array" // vec, tuple
39
- | "variant" // variant (not Result)
40
- | "result" // variant { Ok, Err } - unwrapped to Ok value
41
- | "nullable" // opt T → T | null
42
- | "recursive" // rec types
43
- | "unknown" // fallback
44
-
45
- // ════════════════════════════════════════════════════════════════════════════
46
- // Format Hints
47
- // ════════════════════════════════════════════════════════════════════════════
28
+ | "string"
29
+ | "number"
30
+ | "boolean"
31
+ | "null"
32
+ | "object"
33
+ | "array"
34
+ | "variant"
35
+ | "result"
36
+ | "nullable"
37
+ | "recursive"
38
+ | "unknown"
48
39
 
49
- /**
50
- * Number-specific formatting hints derived from field names.
51
- */
52
40
  export type NumberFormat = "timestamp" | "cycle" | "value" | "token" | "normal"
53
-
54
- /**
55
- * Text-specific formatting hints derived from field names.
56
- */
57
41
  export type TextFormat =
58
42
  | "plain"
59
43
  | "timestamp"
@@ -66,207 +50,119 @@ export type TextFormat =
66
50
  | "account-id"
67
51
  | "principal"
68
52
 
69
- /**
70
- * Display hints for UI rendering.
71
- */
72
- export type DisplayHint =
73
- | "copyable" // Show copy button
74
- | "linkable" // Can be linked
75
- | "truncate" // Truncate long values
76
- | "hex" // Display as hex
77
- | "code" // Display as code/monospace
78
- | "none" // No special formatting
79
-
80
53
  // ════════════════════════════════════════════════════════════════════════════
81
- // Base Field Interface
54
+ // Unified Result Node - Single Structure for Schema & Resolved Data
82
55
  // ════════════════════════════════════════════════════════════════════════════
83
56
 
84
- export interface ResultFieldBase {
57
+ /**
58
+ * Base properties shared by all result nodes.
59
+ */
60
+ interface ResultNodeBase<T extends NodeType = NodeType> {
85
61
  /** The Candid type category */
86
- type: ResultFieldType
87
- /** Human-readable label from Candid */
62
+ type: T
63
+ /** Human-readable label */
88
64
  label: string
89
65
  /** Original Candid type name */
90
66
  candidType: string
91
67
  /** What it becomes after display transformation */
92
68
  displayType: DisplayType
93
- /**
94
- * Combine metadata with value to create a render-ready tree.
95
- * This allows "zipping" the static schema with dynamic runtime data.
96
- */
97
- resolve(value: unknown): ResultFieldWithValue
98
- }
99
-
100
- // ════════════════════════════════════════════════════════════════════════════
101
- // Compound Types
102
- // ════════════════════════════════════════════════════════════════════════════
103
-
104
- export interface RecordResultField extends ResultFieldBase {
105
- type: "record"
106
- displayType: "object"
107
- fields: ResultField[]
108
- }
109
-
110
- export interface VariantResultField extends ResultFieldBase {
111
- type: "variant"
112
- displayType: "variant" | "result"
113
- options: string[]
114
- optionFields: ResultField[]
115
- }
116
-
117
- export interface TupleResultField extends ResultFieldBase {
118
- type: "tuple"
119
- displayType: "array"
120
- fields: ResultField[]
121
- }
122
-
123
- export interface OptionalResultField extends ResultFieldBase {
124
- type: "optional"
125
- displayType: "nullable"
126
- innerField: ResultField
127
- }
69
+ /** Original raw value before transformation (present after resolution) */
70
+ raw?: unknown
71
+ }
72
+
73
+ // ════════════════════════════════════════════════════════════════════════════
74
+ // Type-Specific Extras (embedded directly in node)
75
+ // For compound types, children are stored directly in their respective fields
76
+ // ════════════════════════════════════════════════════════════════════════════
77
+
78
+ type NodeTypeExtras<T extends NodeType> = T extends "record"
79
+ ? { fields: Record<string, ResultNode> }
80
+ : T extends "variant"
81
+ ? { selectedOption: ResultNode; selected?: string }
82
+ : T extends "tuple" | "vector"
83
+ ? { items: ResultNode[] }
84
+ : T extends "optional"
85
+ ? { value: ResultNode | null }
86
+ : T extends "recursive"
87
+ ? { inner: ResultNode }
88
+ : T extends "blob"
89
+ ? { value: string }
90
+ : T extends "number"
91
+ ? { format: NumberFormat; value: string | number }
92
+ : T extends "text" | "principal"
93
+ ? { format: TextFormat; value: string }
94
+ : T extends "boolean"
95
+ ? { value: boolean }
96
+ : T extends "null"
97
+ ? { value: null }
98
+ : { value: unknown } // unknown
128
99
 
129
- export interface VectorResultField extends ResultFieldBase {
130
- type: "vector"
131
- displayType: "array"
132
- itemField: ResultField
133
- }
134
-
135
- export interface BlobResultField extends ResultFieldBase {
136
- type: "blob"
137
- displayType: "string"
138
- displayHint: "hex"
139
- }
140
-
141
- export interface RecursiveResultField extends ResultFieldBase {
142
- type: "recursive"
143
- displayType: "recursive"
144
- typeName: string
145
- /** Lazily extract the inner field to prevent infinite loops */
146
- extract: () => ResultField
147
- }
148
-
149
- // ════════════════════════════════════════════════════════════════════════════
150
- // Primitive Types
151
- // ════════════════════════════════════════════════════════════════════════════
152
-
153
- export interface PrincipalResultField extends ResultFieldBase {
154
- type: "principal"
155
- displayType: "string"
156
- textFormat: TextFormat
157
- }
158
-
159
- export interface NumberResultField extends ResultFieldBase {
160
- type: "number"
161
- displayType: "string" | "number"
162
- numberFormat: NumberFormat
163
- }
164
-
165
- export interface TextResultField extends ResultFieldBase {
166
- type: "text"
167
- displayType: "string"
168
- textFormat: TextFormat
169
- }
170
-
171
- export interface BooleanResultField extends ResultFieldBase {
172
- type: "boolean"
173
- displayType: "boolean"
174
- }
175
-
176
- export interface NullResultField extends ResultFieldBase {
177
- type: "null"
178
- displayType: "null"
179
- }
100
+ /**
101
+ * A unified result node that contains both schema and resolved value.
102
+ * When used as schema only, `raw` is undefined.
103
+ * When resolved, `raw` contains the original data.
104
+ *
105
+ * Compound types (record, variant, tuple, optional, vector) store
106
+ * resolved children directly in their structure fields.
107
+ * Primitive types store the display value in `value`.
108
+ */
109
+ export type ResultNode<T extends NodeType = NodeType> = ResultNodeBase<T> &
110
+ NodeTypeExtras<T> & {
111
+ /** Resolve this node with a value, returning a new resolved node */
112
+ resolve(data: unknown): ResolvedNode<T>
113
+ value?: unknown
114
+ }
180
115
 
181
- export interface UnknownResultField extends ResultFieldBase {
182
- type: "unknown"
183
- displayType: "unknown"
116
+ /**
117
+ * A resolved node has `raw` populated and children resolved.
118
+ */
119
+ export type ResolvedNode<T extends NodeType = NodeType> = ResultNode<T> & {
120
+ raw: unknown
184
121
  }
185
122
 
186
123
  // ════════════════════════════════════════════════════════════════════════════
187
- // Union Type
188
- // ════════════════════════════════════════════════════════════════════════════
189
-
190
- export type ResultField =
191
- | RecordResultField
192
- | VariantResultField
193
- | TupleResultField
194
- | OptionalResultField
195
- | VectorResultField
196
- | BlobResultField
197
- | RecursiveResultField
198
- | PrincipalResultField
199
- | NumberResultField
200
- | TextResultField
201
- | BooleanResultField
202
- | NullResultField
203
- | UnknownResultField
204
-
205
- // ════════════════════════════════════════════════════════════════════════════
206
- // Helper Types for Rendering
124
+ // Convenience Type Aliases
207
125
  // ════════════════════════════════════════════════════════════════════════════
208
126
 
209
- /**
210
- * A result field paired with its transformed value for rendering.
211
- * Can contain nested resolved fields for compound types.
212
- */
213
- export interface ResultFieldWithValue<T = unknown> {
214
- field: ResultField
215
- value: DisplayOf<T>
216
- raw: T
217
- }
127
+ export type RecordNode = ResultNode<"record">
128
+ export type VariantNode = ResultNode<"variant">
129
+ export type TupleNode = ResultNode<"tuple">
130
+ export type OptionalNode = ResultNode<"optional">
131
+ export type VectorNode = ResultNode<"vector">
132
+ export type BlobNode = ResultNode<"blob">
133
+ export type RecursiveNode = ResultNode<"recursive">
134
+ export type PrincipalNode = ResultNode<"principal">
135
+ export type NumberNode = ResultNode<"number">
136
+ export type TextNode = ResultNode<"text">
137
+ export type BooleanNode = ResultNode<"boolean">
138
+ export type NullNode = ResultNode<"null">
139
+ export type UnknownNode = ResultNode<"unknown">
218
140
 
219
141
  // ════════════════════════════════════════════════════════════════════════════
220
142
  // Method & Service Level
221
143
  // ════════════════════════════════════════════════════════════════════════════
222
144
 
223
- /**
224
- * Resolved method result containing metadata and resolved field values.
225
- * This is the output of `generateMetadata()`.
226
- */
227
- export interface ResolvedMethodResult<A = BaseActor> {
228
- functionType: FunctionType
229
- functionName: FunctionName<A>
230
- results: ResultFieldWithValue[]
231
- raw: ActorMethodReturnType<A[FunctionName<A>]>
232
- }
233
-
234
- export interface MethodResultMeta<
145
+ export interface MethodMeta<
235
146
  A = BaseActor,
236
147
  Name extends FunctionName<A> = FunctionName<A>,
237
148
  > {
238
149
  functionType: FunctionType
239
150
  functionName: Name
240
- resultFields: ResultField[]
151
+ returns: ResultNode[]
241
152
  returnCount: number
242
153
  /**
243
- * Generate metadata by resolving each result field with its corresponding display value.
244
- * This "zips" the static schema with dynamic runtime data for easy rendering.
245
- *
246
- * @param data - Array of display-transformed return values from the canister method call
247
- * @returns Resolved method result with metadata attached to each value
248
- *
249
- * @example
250
- * ```ts
251
- * const result = await reactor.callMethod({ functionName: "myMethod", args: [] })
252
- * const resolved = methodMeta.generateMetadata(result)
253
- * // resolved.results contains fields with their display values for rendering
254
- * ```
154
+ * Resolve the method result schema with actual return data.
255
155
  */
256
- generateMetadata(
257
- data: ActorMethodReturnType<A[Name]>
258
- ): ResolvedMethodResult<A>
156
+ resolve(data: ActorMethodReturnType<A[Name]>): ResolvedMethodResult<A>
259
157
  }
260
158
 
261
- export type ServiceResultMeta<A = BaseActor> = {
262
- [K in FunctionName<A>]: MethodResultMeta<A, K>
159
+ export interface ResolvedMethodResult<A = BaseActor> {
160
+ functionType: FunctionType
161
+ functionName: FunctionName<A>
162
+ results: ResolvedNode[]
163
+ raw: ActorMethodReturnType<A[FunctionName<A>]>
263
164
  }
264
165
 
265
- // ════════════════════════════════════════════════════════════════════════════
266
- // Type Utilities
267
- // ════════════════════════════════════════════════════════════════════════════
268
-
269
- export type ResultFieldByType<T extends ResultFieldType> = Extract<
270
- ResultField,
271
- { type: T }
272
- >
166
+ export type ServiceMeta<A = BaseActor> = {
167
+ [K in FunctionName<A>]: MethodMeta<A, K>
168
+ }