@ic-reactor/candid 3.0.12-beta.0 → 3.0.13-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.
- package/dist/metadata-display-reactor.d.ts.map +1 -1
- package/dist/metadata-display-reactor.js +2 -2
- package/dist/metadata-display-reactor.js.map +1 -1
- package/dist/visitor/arguments/helpers.d.ts +40 -0
- package/dist/visitor/arguments/helpers.d.ts.map +1 -0
- package/dist/visitor/arguments/helpers.js +81 -0
- package/dist/visitor/arguments/helpers.js.map +1 -0
- package/dist/visitor/arguments/index.d.ts +8 -5
- package/dist/visitor/arguments/index.d.ts.map +1 -1
- package/dist/visitor/arguments/index.js +212 -17
- package/dist/visitor/arguments/index.js.map +1 -1
- package/dist/visitor/arguments/types.d.ts +282 -30
- package/dist/visitor/arguments/types.d.ts.map +1 -1
- package/dist/visitor/arguments/types.js +1 -40
- package/dist/visitor/arguments/types.js.map +1 -1
- package/package.json +2 -2
- package/src/metadata-display-reactor.ts +2 -2
- package/src/visitor/arguments/helpers.ts +104 -0
- package/src/visitor/arguments/index.test.ts +401 -2
- package/src/visitor/arguments/index.ts +251 -17
- package/src/visitor/arguments/schema.test.ts +3 -3
- package/src/visitor/arguments/types.ts +318 -52
- package/src/visitor/arguments/README.md +0 -230
|
@@ -16,17 +16,115 @@ import type {
|
|
|
16
16
|
UnknownField,
|
|
17
17
|
ArgumentsMeta,
|
|
18
18
|
ArgumentsServiceMeta,
|
|
19
|
+
RenderHint,
|
|
20
|
+
PrimitiveInputProps,
|
|
21
|
+
BlobLimits,
|
|
22
|
+
BlobValidationResult,
|
|
19
23
|
} from "./types"
|
|
20
24
|
|
|
21
25
|
import { IDL } from "@icp-sdk/core/candid"
|
|
22
26
|
import { Principal } from "@icp-sdk/core/principal"
|
|
23
27
|
import { BaseActor, FunctionName } from "@ic-reactor/core"
|
|
24
28
|
import * as z from "zod"
|
|
29
|
+
import { formatLabel } from "./helpers"
|
|
25
30
|
|
|
26
31
|
export * from "./types"
|
|
27
32
|
|
|
33
|
+
// ════════════════════════════════════════════════════════════════════════════
|
|
34
|
+
// Render Hint Helpers
|
|
35
|
+
// ════════════════════════════════════════════════════════════════════════════
|
|
36
|
+
|
|
37
|
+
const COMPOUND_RENDER_HINT: RenderHint = {
|
|
38
|
+
isCompound: true,
|
|
39
|
+
isPrimitive: false,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const TEXT_RENDER_HINT: RenderHint = {
|
|
43
|
+
isCompound: false,
|
|
44
|
+
isPrimitive: true,
|
|
45
|
+
inputType: "text",
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const NUMBER_RENDER_HINT: RenderHint = {
|
|
49
|
+
isCompound: false,
|
|
50
|
+
isPrimitive: true,
|
|
51
|
+
inputType: "number",
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const CHECKBOX_RENDER_HINT: RenderHint = {
|
|
55
|
+
isCompound: false,
|
|
56
|
+
isPrimitive: true,
|
|
57
|
+
inputType: "checkbox",
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const FILE_RENDER_HINT: RenderHint = {
|
|
61
|
+
isCompound: false,
|
|
62
|
+
isPrimitive: true,
|
|
63
|
+
inputType: "file",
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ════════════════════════════════════════════════════════════════════════════
|
|
67
|
+
// Blob Field Helpers
|
|
68
|
+
// ════════════════════════════════════════════════════════════════════════════
|
|
69
|
+
|
|
70
|
+
const DEFAULT_BLOB_LIMITS: BlobLimits = {
|
|
71
|
+
maxHexBytes: 512,
|
|
72
|
+
maxFileBytes: 2 * 1024 * 1024, // 2MB
|
|
73
|
+
maxHexDisplayLength: 128,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function normalizeHex(input: string): string {
|
|
77
|
+
// Remove 0x prefix and convert to lowercase
|
|
78
|
+
let hex = input.toLowerCase()
|
|
79
|
+
if (hex.startsWith("0x")) {
|
|
80
|
+
hex = hex.slice(2)
|
|
81
|
+
}
|
|
82
|
+
// Remove any whitespace
|
|
83
|
+
hex = hex.replace(/\s/g, "")
|
|
84
|
+
return hex
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function validateBlobInput(
|
|
88
|
+
value: string | Uint8Array,
|
|
89
|
+
limits: BlobLimits
|
|
90
|
+
): BlobValidationResult {
|
|
91
|
+
if (value instanceof Uint8Array) {
|
|
92
|
+
if (value.length > limits.maxFileBytes) {
|
|
93
|
+
return {
|
|
94
|
+
valid: false,
|
|
95
|
+
error: `File size exceeds maximum of ${limits.maxFileBytes} bytes`,
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return { valid: true }
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// String input (hex)
|
|
102
|
+
const normalized = normalizeHex(value)
|
|
103
|
+
if (normalized.length === 0) {
|
|
104
|
+
return { valid: true } // Empty is valid
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!/^[0-9a-f]*$/.test(normalized)) {
|
|
108
|
+
return { valid: false, error: "Invalid hex characters" }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (normalized.length % 2 !== 0) {
|
|
112
|
+
return { valid: false, error: "Hex string must have even length" }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const byteLength = normalized.length / 2
|
|
116
|
+
if (byteLength > limits.maxHexBytes) {
|
|
117
|
+
return {
|
|
118
|
+
valid: false,
|
|
119
|
+
error: `Hex input exceeds maximum of ${limits.maxHexBytes} bytes`,
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return { valid: true }
|
|
124
|
+
}
|
|
125
|
+
|
|
28
126
|
/**
|
|
29
|
-
*
|
|
127
|
+
* FieldVisitor generates metadata for form input fields from Candid IDL types.
|
|
30
128
|
*
|
|
31
129
|
* ## Design Principles
|
|
32
130
|
*
|
|
@@ -40,8 +138,11 @@ export * from "./types"
|
|
|
40
138
|
*
|
|
41
139
|
* Each field has:
|
|
42
140
|
* - `type`: The field type (record, variant, text, number, etc.)
|
|
43
|
-
* - `label`:
|
|
141
|
+
* - `label`: Raw label from Candid
|
|
142
|
+
* - `displayLabel`: Human-readable formatted label
|
|
44
143
|
* - `name`: TanStack Form compatible path (e.g., "[0]", "[0].owner", "tags[1]")
|
|
144
|
+
* - `component`: Suggested component type for rendering
|
|
145
|
+
* - `renderHint`: Hints for UI rendering strategy
|
|
45
146
|
* - `defaultValue`: Initial value for the form
|
|
46
147
|
* - `schema`: Zod schema for validation
|
|
47
148
|
* - Type-specific properties (options for variant, fields for record, etc.)
|
|
@@ -52,9 +153,9 @@ export * from "./types"
|
|
|
52
153
|
* @example
|
|
53
154
|
* ```typescript
|
|
54
155
|
* import { useForm } from '@tanstack/react-form'
|
|
55
|
-
* import {
|
|
156
|
+
* import { FieldVisitor } from '@ic-reactor/candid'
|
|
56
157
|
*
|
|
57
|
-
* const visitor = new
|
|
158
|
+
* const visitor = new FieldVisitor()
|
|
58
159
|
* const serviceMeta = service.accept(visitor, null)
|
|
59
160
|
* const methodMeta = serviceMeta["icrc1_transfer"]
|
|
60
161
|
*
|
|
@@ -74,7 +175,7 @@ export * from "./types"
|
|
|
74
175
|
* ))
|
|
75
176
|
* ```
|
|
76
177
|
*/
|
|
77
|
-
export class
|
|
178
|
+
export class FieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
78
179
|
string,
|
|
79
180
|
Field | ArgumentsMeta<A> | ArgumentsServiceMeta<A>
|
|
80
181
|
> {
|
|
@@ -192,7 +293,10 @@ export class ArgumentFieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
192
293
|
return {
|
|
193
294
|
type: "record",
|
|
194
295
|
label,
|
|
296
|
+
displayLabel: formatLabel(label),
|
|
195
297
|
name,
|
|
298
|
+
component: "record-container",
|
|
299
|
+
renderHint: COMPOUND_RENDER_HINT,
|
|
196
300
|
fields,
|
|
197
301
|
fieldMap,
|
|
198
302
|
defaultValue,
|
|
@@ -240,10 +344,34 @@ export class ArgumentFieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
240
344
|
return { [option]: optField.defaultValue }
|
|
241
345
|
}
|
|
242
346
|
|
|
347
|
+
// Helper to get field for a specific option
|
|
348
|
+
const getField = (option: string): Field => {
|
|
349
|
+
const optField = optionMap.get(option)
|
|
350
|
+
if (!optField) {
|
|
351
|
+
throw new Error(`Unknown variant option: ${option}`)
|
|
352
|
+
}
|
|
353
|
+
return optField
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Helper to get currently selected option from a value
|
|
357
|
+
const getSelectedOption = (value: Record<string, unknown>): string => {
|
|
358
|
+
const validKeys = Object.keys(value).filter((k) => options.includes(k))
|
|
359
|
+
return validKeys[0] ?? defaultOption
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Helper to get selected field from a value
|
|
363
|
+
const getSelectedField = (value: Record<string, unknown>): Field => {
|
|
364
|
+
const selectedOption = getSelectedOption(value)
|
|
365
|
+
return getField(selectedOption)
|
|
366
|
+
}
|
|
367
|
+
|
|
243
368
|
return {
|
|
244
369
|
type: "variant",
|
|
245
370
|
label,
|
|
371
|
+
displayLabel: formatLabel(label),
|
|
246
372
|
name,
|
|
373
|
+
component: "variant-select",
|
|
374
|
+
renderHint: COMPOUND_RENDER_HINT,
|
|
247
375
|
fields,
|
|
248
376
|
options,
|
|
249
377
|
defaultOption,
|
|
@@ -251,6 +379,9 @@ export class ArgumentFieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
251
379
|
defaultValue,
|
|
252
380
|
schema,
|
|
253
381
|
getOptionDefault,
|
|
382
|
+
getField,
|
|
383
|
+
getSelectedOption,
|
|
384
|
+
getSelectedField,
|
|
254
385
|
candidType: "variant",
|
|
255
386
|
}
|
|
256
387
|
}
|
|
@@ -281,7 +412,10 @@ export class ArgumentFieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
281
412
|
return {
|
|
282
413
|
type: "tuple",
|
|
283
414
|
label,
|
|
415
|
+
displayLabel: formatLabel(label),
|
|
284
416
|
name,
|
|
417
|
+
component: "tuple-container",
|
|
418
|
+
renderHint: COMPOUND_RENDER_HINT,
|
|
285
419
|
fields,
|
|
286
420
|
defaultValue,
|
|
287
421
|
schema,
|
|
@@ -310,14 +444,23 @@ export class ArgumentFieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
310
444
|
// Helper to get the inner default when enabling the optional
|
|
311
445
|
const getInnerDefault = (): unknown => innerField.defaultValue
|
|
312
446
|
|
|
447
|
+
// Helper to check if a value represents an enabled optional
|
|
448
|
+
const isEnabled = (value: unknown): boolean => {
|
|
449
|
+
return value !== null && typeof value !== "undefined"
|
|
450
|
+
}
|
|
451
|
+
|
|
313
452
|
return {
|
|
314
453
|
type: "optional",
|
|
315
454
|
label,
|
|
455
|
+
displayLabel: formatLabel(label),
|
|
316
456
|
name,
|
|
457
|
+
component: "optional-toggle",
|
|
458
|
+
renderHint: COMPOUND_RENDER_HINT,
|
|
317
459
|
innerField,
|
|
318
460
|
defaultValue: null,
|
|
319
461
|
schema,
|
|
320
462
|
getInnerDefault,
|
|
463
|
+
isEnabled,
|
|
321
464
|
candidType: "opt",
|
|
322
465
|
}
|
|
323
466
|
}
|
|
@@ -343,14 +486,24 @@ export class ArgumentFieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
343
486
|
z.array(z.number()),
|
|
344
487
|
z.instanceof(Uint8Array),
|
|
345
488
|
])
|
|
489
|
+
|
|
490
|
+
const limits = { ...DEFAULT_BLOB_LIMITS }
|
|
491
|
+
|
|
346
492
|
return {
|
|
347
493
|
type: "blob",
|
|
348
494
|
label,
|
|
495
|
+
displayLabel: formatLabel(label),
|
|
349
496
|
name,
|
|
497
|
+
component: "blob-upload",
|
|
498
|
+
renderHint: FILE_RENDER_HINT,
|
|
350
499
|
itemField,
|
|
351
500
|
defaultValue: "",
|
|
352
501
|
schema,
|
|
353
502
|
acceptedFormats: ["hex", "base64", "file"],
|
|
503
|
+
limits,
|
|
504
|
+
normalizeHex,
|
|
505
|
+
validateInput: (value: string | Uint8Array) =>
|
|
506
|
+
validateBlobInput(value, limits),
|
|
354
507
|
candidType: "blob",
|
|
355
508
|
}
|
|
356
509
|
}
|
|
@@ -360,14 +513,35 @@ export class ArgumentFieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
360
513
|
// Helper to get a new item with default values
|
|
361
514
|
const getItemDefault = (): unknown => itemField.defaultValue
|
|
362
515
|
|
|
516
|
+
// Helper to create an item field for a specific index
|
|
517
|
+
const createItemField = (
|
|
518
|
+
index: number,
|
|
519
|
+
overrides?: { label?: string }
|
|
520
|
+
): Field => {
|
|
521
|
+
// Replace [0] in template with actual index
|
|
522
|
+
const itemName = name ? `${name}[${index}]` : `[${index}]`
|
|
523
|
+
const itemLabel = overrides?.label ?? `Item ${index}`
|
|
524
|
+
|
|
525
|
+
return {
|
|
526
|
+
...itemField,
|
|
527
|
+
name: itemName,
|
|
528
|
+
label: itemLabel,
|
|
529
|
+
displayLabel: formatLabel(itemLabel),
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
363
533
|
return {
|
|
364
534
|
type: "vector",
|
|
365
535
|
label,
|
|
536
|
+
displayLabel: formatLabel(label),
|
|
366
537
|
name,
|
|
538
|
+
component: "vector-list",
|
|
539
|
+
renderHint: COMPOUND_RENDER_HINT,
|
|
367
540
|
itemField,
|
|
368
541
|
defaultValue: [],
|
|
369
542
|
schema,
|
|
370
543
|
getItemDefault,
|
|
544
|
+
createItemField,
|
|
371
545
|
candidType: "vec",
|
|
372
546
|
}
|
|
373
547
|
}
|
|
@@ -399,7 +573,10 @@ export class ArgumentFieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
399
573
|
return {
|
|
400
574
|
type: "recursive",
|
|
401
575
|
label,
|
|
576
|
+
displayLabel: formatLabel(label),
|
|
402
577
|
name,
|
|
578
|
+
component: "recursive-lazy",
|
|
579
|
+
renderHint: COMPOUND_RENDER_HINT,
|
|
403
580
|
typeName,
|
|
404
581
|
extract,
|
|
405
582
|
defaultValue: undefined,
|
|
@@ -432,42 +609,67 @@ export class ArgumentFieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
432
609
|
}
|
|
433
610
|
)
|
|
434
611
|
|
|
612
|
+
const inputProps: PrimitiveInputProps = {
|
|
613
|
+
type: "text",
|
|
614
|
+
placeholder: "aaaaa-aa or full principal ID",
|
|
615
|
+
minLength: 7,
|
|
616
|
+
maxLength: 64,
|
|
617
|
+
spellCheck: false,
|
|
618
|
+
autoComplete: "off",
|
|
619
|
+
}
|
|
620
|
+
|
|
435
621
|
return {
|
|
436
622
|
type: "principal",
|
|
437
623
|
label,
|
|
624
|
+
displayLabel: formatLabel(label),
|
|
438
625
|
name: this.currentName(),
|
|
626
|
+
component: "principal-input",
|
|
627
|
+
renderHint: TEXT_RENDER_HINT,
|
|
439
628
|
defaultValue: "",
|
|
440
629
|
maxLength: 64,
|
|
441
630
|
minLength: 7,
|
|
442
631
|
schema,
|
|
632
|
+
inputProps,
|
|
443
633
|
candidType: "principal",
|
|
444
|
-
ui: {
|
|
445
|
-
placeholder: "aaaaa-aa or full principal ID",
|
|
446
|
-
},
|
|
447
634
|
}
|
|
448
635
|
}
|
|
449
636
|
|
|
450
637
|
public visitText(_t: IDL.TextClass, label: string): TextField {
|
|
638
|
+
const inputProps: PrimitiveInputProps = {
|
|
639
|
+
type: "text",
|
|
640
|
+
placeholder: "Enter text...",
|
|
641
|
+
spellCheck: true,
|
|
642
|
+
}
|
|
643
|
+
|
|
451
644
|
return {
|
|
452
645
|
type: "text",
|
|
453
646
|
label,
|
|
647
|
+
displayLabel: formatLabel(label),
|
|
454
648
|
name: this.currentName(),
|
|
649
|
+
component: "text-input",
|
|
650
|
+
renderHint: TEXT_RENDER_HINT,
|
|
455
651
|
defaultValue: "",
|
|
456
652
|
schema: z.string().min(1, "Required"),
|
|
653
|
+
inputProps,
|
|
457
654
|
candidType: "text",
|
|
458
|
-
ui: {
|
|
459
|
-
placeholder: "Enter text...",
|
|
460
|
-
},
|
|
461
655
|
}
|
|
462
656
|
}
|
|
463
657
|
|
|
464
658
|
public visitBool(_t: IDL.BoolClass, label: string): BooleanField {
|
|
659
|
+
const inputProps: PrimitiveInputProps = {
|
|
660
|
+
type: "checkbox",
|
|
661
|
+
}
|
|
662
|
+
|
|
465
663
|
return {
|
|
466
664
|
type: "boolean",
|
|
467
665
|
label,
|
|
666
|
+
displayLabel: formatLabel(label),
|
|
468
667
|
name: this.currentName(),
|
|
668
|
+
component: "boolean-checkbox",
|
|
669
|
+
renderHint: CHECKBOX_RENDER_HINT,
|
|
469
670
|
defaultValue: false,
|
|
470
671
|
schema: z.boolean(),
|
|
672
|
+
inputProps,
|
|
471
673
|
candidType: "bool",
|
|
472
674
|
}
|
|
473
675
|
}
|
|
@@ -476,7 +678,13 @@ export class ArgumentFieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
476
678
|
return {
|
|
477
679
|
type: "null",
|
|
478
680
|
label,
|
|
681
|
+
displayLabel: formatLabel(label),
|
|
479
682
|
name: this.currentName(),
|
|
683
|
+
component: "null-hidden",
|
|
684
|
+
renderHint: {
|
|
685
|
+
isCompound: false,
|
|
686
|
+
isPrimitive: true,
|
|
687
|
+
},
|
|
480
688
|
defaultValue: null,
|
|
481
689
|
schema: z.null(),
|
|
482
690
|
candidType: "null",
|
|
@@ -514,30 +722,50 @@ export class ArgumentFieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
514
722
|
const type = isBigInt ? "text" : "number"
|
|
515
723
|
|
|
516
724
|
if (type === "text") {
|
|
725
|
+
const inputProps: PrimitiveInputProps = {
|
|
726
|
+
type: "text",
|
|
727
|
+
placeholder: options.unsigned ? "e.g. 100000" : "e.g. -100000",
|
|
728
|
+
inputMode: "numeric",
|
|
729
|
+
pattern: options.unsigned ? "\\d+" : "-?\\d+",
|
|
730
|
+
spellCheck: false,
|
|
731
|
+
autoComplete: "off",
|
|
732
|
+
}
|
|
733
|
+
|
|
517
734
|
return {
|
|
518
735
|
type: "text",
|
|
519
736
|
label,
|
|
737
|
+
displayLabel: formatLabel(label),
|
|
520
738
|
name: this.currentName(),
|
|
739
|
+
component: "text-input",
|
|
740
|
+
renderHint: TEXT_RENDER_HINT,
|
|
521
741
|
defaultValue: "",
|
|
522
742
|
candidType,
|
|
523
743
|
schema,
|
|
524
|
-
|
|
525
|
-
placeholder: options.unsigned ? "e.g. 100000" : "e.g. -100000",
|
|
526
|
-
},
|
|
744
|
+
inputProps,
|
|
527
745
|
}
|
|
528
746
|
}
|
|
529
747
|
|
|
748
|
+
const inputProps: PrimitiveInputProps = {
|
|
749
|
+
type: "number",
|
|
750
|
+
placeholder: options.isFloat ? "0.0" : "0",
|
|
751
|
+
inputMode: options.isFloat ? "decimal" : "numeric",
|
|
752
|
+
min: options.min,
|
|
753
|
+
max: options.max,
|
|
754
|
+
step: options.isFloat ? "any" : "1",
|
|
755
|
+
}
|
|
756
|
+
|
|
530
757
|
return {
|
|
531
758
|
type: "number",
|
|
532
759
|
label,
|
|
760
|
+
displayLabel: formatLabel(label),
|
|
533
761
|
name: this.currentName(),
|
|
762
|
+
component: "number-input",
|
|
763
|
+
renderHint: NUMBER_RENDER_HINT,
|
|
534
764
|
defaultValue: "",
|
|
535
765
|
candidType,
|
|
536
766
|
schema: schema,
|
|
767
|
+
inputProps,
|
|
537
768
|
...options,
|
|
538
|
-
ui: {
|
|
539
|
-
placeholder: options.isFloat ? "0.0" : "0",
|
|
540
|
-
},
|
|
541
769
|
}
|
|
542
770
|
}
|
|
543
771
|
|
|
@@ -602,7 +830,13 @@ export class ArgumentFieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
602
830
|
return {
|
|
603
831
|
type: "unknown",
|
|
604
832
|
label,
|
|
833
|
+
displayLabel: formatLabel(label),
|
|
605
834
|
name: this.currentName(),
|
|
835
|
+
component: "unknown-fallback",
|
|
836
|
+
renderHint: {
|
|
837
|
+
isCompound: false,
|
|
838
|
+
isPrimitive: false,
|
|
839
|
+
},
|
|
606
840
|
defaultValue: undefined,
|
|
607
841
|
schema: z.any(),
|
|
608
842
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest"
|
|
2
2
|
import { IDL } from "@icp-sdk/core/candid"
|
|
3
3
|
import { Principal } from "@icp-sdk/core/principal"
|
|
4
|
-
import {
|
|
4
|
+
import { FieldVisitor } from "./index"
|
|
5
5
|
import * as z from "zod"
|
|
6
6
|
|
|
7
|
-
describe("
|
|
8
|
-
const visitor = new
|
|
7
|
+
describe("FieldVisitor Schema Generation", () => {
|
|
8
|
+
const visitor = new FieldVisitor()
|
|
9
9
|
|
|
10
10
|
// ════════════════════════════════════════════════════════════════════════
|
|
11
11
|
// Primitive Types
|