@ic-reactor/candid 3.0.9-beta.0 → 3.0.10-beta.1

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.
@@ -6,10 +6,10 @@ import type {
6
6
  } from "@ic-reactor/core"
7
7
 
8
8
  // ════════════════════════════════════════════════════════════════════════════
9
- // Field Type Union
9
+ // Core Types & Formats
10
10
  // ════════════════════════════════════════════════════════════════════════════
11
11
 
12
- export type ResultFieldType =
12
+ export type NodeType =
13
13
  | "record"
14
14
  | "variant"
15
15
  | "tuple"
@@ -24,35 +24,20 @@ export type ResultFieldType =
24
24
  | "null"
25
25
  | "unknown"
26
26
 
27
- // ════════════════════════════════════════════════════════════════════════════
28
- // Display Type (what it becomes after transformation)
29
- // ════════════════════════════════════════════════════════════════════════════
30
-
31
27
  export type DisplayType =
32
- | "string" // Principal, nat, int, nat64, int64, blob, text
33
- | "number" // float32, float64, nat8-nat32, int8-int32
34
- | "boolean" // bool
35
- | "null" // null
36
- | "object" // record
37
- | "array" // vec, tuple
38
- | "variant" // variant (not Result)
39
- | "result" // variant { Ok, Err } - unwrapped to Ok value
40
- | "nullable" // opt T → T | null
41
- | "recursive" // rec types
42
- | "unknown" // fallback
43
-
44
- // ════════════════════════════════════════════════════════════════════════════
45
- // Format Hints
46
- // ════════════════════════════════════════════════════════════════════════════
28
+ | "string"
29
+ | "number"
30
+ | "boolean"
31
+ | "null"
32
+ | "object"
33
+ | "array"
34
+ | "variant"
35
+ | "result"
36
+ | "nullable"
37
+ | "recursive"
38
+ | "unknown"
47
39
 
48
- /**
49
- * Number-specific formatting hints derived from field names.
50
- */
51
40
  export type NumberFormat = "timestamp" | "cycle" | "value" | "token" | "normal"
52
-
53
- /**
54
- * Text-specific formatting hints derived from field names.
55
- */
56
41
  export type TextFormat =
57
42
  | "plain"
58
43
  | "timestamp"
@@ -65,305 +50,119 @@ export type TextFormat =
65
50
  | "account-id"
66
51
  | "principal"
67
52
 
68
- /**
69
- * Display hints for UI rendering.
70
- */
71
- export type DisplayHint =
72
- | "copyable" // Show copy button
73
- | "linkable" // Can be linked
74
- | "truncate" // Truncate long values
75
- | "hex" // Display as hex
76
- | "code" // Display as code/monospace
77
- | "none" // No special formatting
78
-
79
53
  // ════════════════════════════════════════════════════════════════════════════
80
- // Base Field Interface
54
+ // Unified Result Node - Single Structure for Schema & Resolved Data
81
55
  // ════════════════════════════════════════════════════════════════════════════
82
56
 
83
- export interface ResultFieldBase<
84
- Type extends ResultFieldType = ResultFieldType,
85
- > {
57
+ /**
58
+ * Base properties shared by all result nodes.
59
+ */
60
+ interface ResultNodeBase<T extends NodeType = NodeType> {
86
61
  /** The Candid type category */
87
- type: Type
88
- /** Human-readable label from Candid */
62
+ type: T
63
+ /** Human-readable label */
89
64
  label: string
90
65
  /** Original Candid type name */
91
66
  candidType: string
92
67
  /** What it becomes after display transformation */
93
68
  displayType: DisplayType
94
- /**
95
- * Combine metadata with value to create a render-ready tree.
96
- * This allows "zipping" the static schema with dynamic runtime data.
97
- */
98
- resolve(value: unknown): ResultFieldWithValue<Type>
99
- }
100
-
101
- // ════════════════════════════════════════════════════════════════════════════
102
- // Compound Types
103
- // ════════════════════════════════════════════════════════════════════════════
104
-
105
- export interface RecordResultField extends ResultFieldBase<"record"> {
106
- type: "record"
107
- displayType: "object"
108
- fields: ResultField[]
109
- }
110
-
111
- export interface VariantResultField extends ResultFieldBase<"variant"> {
112
- type: "variant"
113
- displayType: "variant" | "result"
114
- options: string[]
115
- optionFields: ResultField[]
116
- }
117
-
118
- export interface TupleResultField extends ResultFieldBase<"tuple"> {
119
- type: "tuple"
120
- displayType: "array"
121
- fields: ResultField[]
122
- }
123
-
124
- export interface OptionalResultField extends ResultFieldBase<"optional"> {
125
- type: "optional"
126
- displayType: "nullable"
127
- innerField: ResultField
128
- }
129
-
130
- export interface VectorResultField extends ResultFieldBase<"vector"> {
131
- type: "vector"
132
- displayType: "array"
133
- itemField: ResultField
134
- }
135
-
136
- export interface BlobResultField extends ResultFieldBase<"blob"> {
137
- type: "blob"
138
- displayType: "string"
139
- displayHint: "hex"
140
- }
141
-
142
- export interface RecursiveResultField extends ResultFieldBase {
143
- type: "recursive"
144
- displayType: "recursive"
145
- typeName: string
146
- /** Lazily extract the inner field to prevent infinite loops */
147
- extract: () => ResultField
148
- }
149
-
150
- // ════════════════════════════════════════════════════════════════════════════
151
- // Primitive Types
152
- // ════════════════════════════════════════════════════════════════════════════
153
-
154
- export interface PrincipalResultField extends ResultFieldBase<"principal"> {
155
- type: "principal"
156
- displayType: "string"
157
- textFormat: TextFormat
158
- }
159
-
160
- export interface NumberResultField extends ResultFieldBase<"number"> {
161
- type: "number"
162
- displayType: "string" | "number"
163
- numberFormat: NumberFormat
164
- }
165
-
166
- export interface TextResultField extends ResultFieldBase<"text"> {
167
- type: "text"
168
- displayType: "string"
169
- textFormat: TextFormat
170
- }
171
-
172
- export interface BooleanResultField extends ResultFieldBase<"boolean"> {
173
- type: "boolean"
174
- displayType: "boolean"
175
- }
176
-
177
- export interface NullResultField extends ResultFieldBase<"null"> {
178
- type: "null"
179
- displayType: "null"
180
- }
181
-
182
- export interface UnknownResultField extends ResultFieldBase<"unknown"> {
183
- type: "unknown"
184
- displayType: "unknown"
185
- }
186
-
187
- // ════════════════════════════════════════════════════════════════════════════
188
- // Union Type
189
- // ════════════════════════════════════════════════════════════════════════════
190
-
191
- export type ResultField =
192
- | RecordResultField
193
- | VariantResultField
194
- | TupleResultField
195
- | OptionalResultField
196
- | VectorResultField
197
- | BlobResultField
198
- | RecursiveResultField
199
- | PrincipalResultField
200
- | NumberResultField
201
- | TextResultField
202
- | BooleanResultField
203
- | NullResultField
204
- | UnknownResultField
205
-
206
- // ════════════════════════════════════════════════════════════════════════════
207
- // Result Field With Value Interfaces
208
- // ════════════════════════════════════════════════════════════════════════════
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
209
99
 
210
- export interface RecordResultWithValue<V = unknown> {
211
- field: RecordResultField
212
- value: Record<string, ResultFieldWithValue>
213
- raw: V
214
- }
215
-
216
- export interface VariantResultWithValue<V = unknown> {
217
- field: VariantResultField
218
- value: { option: string; value: ResultFieldWithValue }
219
- raw: V
220
- }
221
-
222
- export interface TupleResultWithValue<V = unknown> {
223
- field: TupleResultField
224
- value: ResultFieldWithValue[]
225
- raw: V
226
- }
227
-
228
- export interface OptionalResultWithValue<V = unknown> {
229
- field: OptionalResultField
230
- value: ResultFieldWithValue | null
231
- raw: V
232
- }
233
-
234
- export interface VectorResultWithValue<V = unknown> {
235
- field: VectorResultField
236
- value: ResultFieldWithValue[]
237
- raw: V
238
- }
239
-
240
- export interface BlobResultWithValue<V = unknown> {
241
- field: BlobResultField
242
- value: string
243
- raw: V
244
- }
245
-
246
- export interface RecursiveResultWithValue<V = unknown> {
247
- field: RecursiveResultField
248
- // Resolves to the specific inner type which is also a ResultFieldWithValue
249
- value: ResultFieldWithValue
250
- raw: V
251
- }
252
-
253
- export interface PrincipalResultWithValue<V = unknown> {
254
- field: PrincipalResultField
255
- value: string
256
- raw: V
257
- }
258
-
259
- export interface NumberResultWithValue<V = unknown> {
260
- field: NumberResultField
261
- value: string | number
262
- raw: V
263
- }
264
-
265
- export interface TextResultWithValue<V = unknown> {
266
- field: TextResultField
267
- value: string
268
- raw: V
269
- }
270
-
271
- export interface BooleanResultWithValue<V = unknown> {
272
- field: BooleanResultField
273
- value: boolean
274
- raw: V
275
- }
276
-
277
- export interface NullResultWithValue<V = unknown> {
278
- field: NullResultField
279
- value: null
280
- raw: V
281
- }
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
+ }
282
115
 
283
- export interface UnknownResultWithValue<V = unknown> {
284
- field: UnknownResultField
285
- value: unknown
286
- raw: V
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
287
121
  }
288
122
 
289
123
  // ════════════════════════════════════════════════════════════════════════════
290
- // Maps and Helper Types
124
+ // Convenience Type Aliases
291
125
  // ════════════════════════════════════════════════════════════════════════════
292
126
 
293
- /**
294
- * Mapping from ResultFieldType string to the corresponding *ResultWithValue interface.
295
- */
296
- export type ResultWithValueMap<V = unknown> = {
297
- record: RecordResultWithValue<V>
298
- variant: VariantResultWithValue<V>
299
- tuple: TupleResultWithValue<V>
300
- optional: OptionalResultWithValue<V>
301
- vector: VectorResultWithValue<V>
302
- blob: BlobResultWithValue<V>
303
- recursive: RecursiveResultWithValue<V>
304
- principal: PrincipalResultWithValue<V>
305
- number: NumberResultWithValue<V>
306
- text: TextResultWithValue<V>
307
- boolean: BooleanResultWithValue<V>
308
- null: NullResultWithValue<V>
309
- unknown: UnknownResultWithValue<V>
310
- }
311
-
312
- /**
313
- * A result field paired with its transformed value for rendering.
314
- * Can contain nested resolved fields for compound types.
315
- *
316
- * It is a discriminated union of all specific result types.
317
- */
318
- export type ResultFieldWithValue<
319
- P = unknown,
320
- V = unknown,
321
- > = P extends ResultFieldType
322
- ? ResultWithValueMap<V>[P]
323
- : ResultWithValueMap<V>[ResultFieldType]
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">
324
140
 
325
141
  // ════════════════════════════════════════════════════════════════════════════
326
142
  // Method & Service Level
327
143
  // ════════════════════════════════════════════════════════════════════════════
328
144
 
329
- /**
330
- * Resolved method result containing metadata and resolved field values.
331
- * This is the output of `generateMetadata()`.
332
- */
333
- export interface ResolvedMethodResult<A = BaseActor> {
334
- functionType: FunctionType
335
- functionName: FunctionName<A>
336
- results: ResultFieldWithValue[]
337
- raw: ActorMethodReturnType<A[FunctionName<A>]>
338
- }
339
-
340
- export interface MethodResultMeta<
145
+ export interface MethodMeta<
341
146
  A = BaseActor,
342
147
  Name extends FunctionName<A> = FunctionName<A>,
343
148
  > {
344
149
  functionType: FunctionType
345
150
  functionName: Name
346
- resultFields: ResultField[]
151
+ returns: ResultNode[]
347
152
  returnCount: number
348
153
  /**
349
- * Generate metadata by resolving each result field with its corresponding display value.
350
- * This "zips" the static schema with dynamic runtime data for easy rendering.
351
- *
352
- * @param data - Array of display-transformed return values from the canister method call
353
- * @returns Resolved method result with metadata attached to each value
354
- *
355
- * @example
356
- * ```ts
357
- * const result = await reactor.callMethod({ functionName: "myMethod", args: [] })
358
- * const resolved = methodMeta.generateMetadata(result)
359
- * // resolved.results contains fields with their display values for rendering
360
- * ```
154
+ * Resolve the method result schema with actual return data.
361
155
  */
362
- generateMetadata(
363
- data: ActorMethodReturnType<A[Name]>
364
- ): ResolvedMethodResult<A>
156
+ resolve(data: ActorMethodReturnType<A[Name]>): ResolvedMethodResult<A>
157
+ }
158
+
159
+ export interface ResolvedMethodResult<A = BaseActor> {
160
+ functionType: FunctionType
161
+ functionName: FunctionName<A>
162
+ results: ResolvedNode[]
163
+ raw: ActorMethodReturnType<A[FunctionName<A>]>
365
164
  }
366
165
 
367
- export type ServiceResultMeta<A = BaseActor> = {
368
- [K in FunctionName<A>]: MethodResultMeta<A, K>
166
+ export type ServiceMeta<A = BaseActor> = {
167
+ [K in FunctionName<A>]: MethodMeta<A, K>
369
168
  }