@ic-reactor/candid 3.0.11-beta.2 → 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.
Files changed (44) hide show
  1. package/dist/display-reactor.d.ts +1 -2
  2. package/dist/display-reactor.d.ts.map +1 -1
  3. package/dist/display-reactor.js +1 -1
  4. package/dist/display-reactor.js.map +1 -1
  5. package/dist/index.d.ts +0 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/metadata-display-reactor.d.ts +3 -3
  9. package/dist/metadata-display-reactor.d.ts.map +1 -1
  10. package/dist/metadata-display-reactor.js +2 -2
  11. package/dist/metadata-display-reactor.js.map +1 -1
  12. package/dist/visitor/arguments/helpers.d.ts +40 -0
  13. package/dist/visitor/arguments/helpers.d.ts.map +1 -0
  14. package/dist/visitor/arguments/helpers.js +81 -0
  15. package/dist/visitor/arguments/helpers.js.map +1 -0
  16. package/dist/visitor/arguments/index.d.ts +64 -42
  17. package/dist/visitor/arguments/index.d.ts.map +1 -1
  18. package/dist/visitor/arguments/index.js +472 -85
  19. package/dist/visitor/arguments/index.js.map +1 -1
  20. package/dist/visitor/arguments/types.d.ts +481 -46
  21. package/dist/visitor/arguments/types.d.ts.map +1 -1
  22. package/dist/visitor/helpers.d.ts +1 -1
  23. package/dist/visitor/helpers.d.ts.map +1 -1
  24. package/dist/visitor/returns/index.d.ts +1 -2
  25. package/dist/visitor/returns/index.d.ts.map +1 -1
  26. package/dist/visitor/returns/index.js +2 -3
  27. package/dist/visitor/returns/index.js.map +1 -1
  28. package/dist/visitor/types.d.ts +2 -3
  29. package/dist/visitor/types.d.ts.map +1 -1
  30. package/dist/visitor/types.js +1 -2
  31. package/dist/visitor/types.js.map +1 -1
  32. package/package.json +6 -3
  33. package/src/display-reactor.ts +4 -6
  34. package/src/index.ts +0 -1
  35. package/src/metadata-display-reactor.ts +8 -8
  36. package/src/visitor/arguments/helpers.ts +104 -0
  37. package/src/visitor/arguments/index.test.ts +544 -52
  38. package/src/visitor/arguments/index.ts +590 -151
  39. package/src/visitor/arguments/schema.test.ts +215 -0
  40. package/src/visitor/arguments/types.ts +554 -62
  41. package/src/visitor/helpers.ts +1 -1
  42. package/src/visitor/returns/index.test.ts +1 -1
  43. package/src/visitor/returns/index.ts +2 -3
  44. package/src/visitor/types.ts +2 -3
@@ -0,0 +1,215 @@
1
+ import { describe, it, expect } from "vitest"
2
+ import { IDL } from "@icp-sdk/core/candid"
3
+ import { Principal } from "@icp-sdk/core/principal"
4
+ import { FieldVisitor } from "./index"
5
+ import * as z from "zod"
6
+
7
+ describe("FieldVisitor Schema Generation", () => {
8
+ const visitor = new FieldVisitor()
9
+
10
+ // ════════════════════════════════════════════════════════════════════════
11
+ // Primitive Types
12
+ // ════════════════════════════════════════════════════════════════════════
13
+
14
+ describe("Primitive Types", () => {
15
+ it("should generate string schema for text", () => {
16
+ const field = visitor.visitText(IDL.Text, "username")
17
+ const schema = field.schema
18
+
19
+ expect(schema).toBeDefined()
20
+ expect(schema.parse("hello")).toBe("hello")
21
+ expect(() => schema.parse(123)).toThrow()
22
+ })
23
+
24
+ it("should generate boolean schema for bool", () => {
25
+ const field = visitor.visitBool(IDL.Bool, "isActive")
26
+ const schema = field.schema
27
+
28
+ expect(schema.parse(true)).toBe(true)
29
+ expect(schema.parse(false)).toBe(false)
30
+ expect(() => schema.parse("true")).toThrow()
31
+ })
32
+
33
+ it("should generate null schema for null", () => {
34
+ const field = visitor.visitNull(IDL.Null, "void")
35
+ const schema = field.schema
36
+
37
+ expect(schema.parse(null)).toBe(null)
38
+ expect(() => schema.parse(undefined)).toThrow()
39
+ })
40
+
41
+ it("should generate string schema for numbers (form input matching)", () => {
42
+ // The visitor currently generates string schemas for numbers to match form inputs
43
+ const natField = visitor.visitNat(IDL.Nat, "amount")
44
+ expect(natField.schema.parse("100")).toBe("100")
45
+
46
+ const intField = visitor.visitInt(IDL.Int, "balance")
47
+ expect(intField.schema.parse("-50")).toBe("-50")
48
+ })
49
+
50
+ it("should generate principal schema", () => {
51
+ const field = visitor.visitPrincipal(IDL.Principal, "owner")
52
+ const schema = field.schema
53
+
54
+ const p = Principal.fromText("2vxsx-fae")
55
+ // Should accept Principal instance
56
+ expect(schema.parse(p)).toEqual(p)
57
+ // Should accept valid string representation
58
+ expect(schema.parse("2vxsx-fae")).toBe("2vxsx-fae")
59
+
60
+ // Should reject invalid
61
+ expect(() => schema.parse("invalid-principal")).toThrow()
62
+ })
63
+ })
64
+
65
+ // ════════════════════════════════════════════════════════════════════════
66
+ // Compound Types
67
+ // ════════════════════════════════════════════════════════════════════════
68
+
69
+ describe("Record Types", () => {
70
+ it("should generate object schema for record", () => {
71
+ const recordType = IDL.Record({
72
+ name: IDL.Text,
73
+ age: IDL.Nat,
74
+ })
75
+ const field = visitor.visitRecord(
76
+ recordType,
77
+ [
78
+ ["name", IDL.Text],
79
+ ["age", IDL.Nat],
80
+ ],
81
+ "person"
82
+ )
83
+ const schema = field.schema as z.ZodObject<any>
84
+
85
+ const validData = { name: "John", age: "30" }
86
+ expect(schema.parse(validData)).toEqual(validData)
87
+
88
+ expect(() => schema.parse({ name: "John" })).toThrow() // missing age
89
+ expect(() => schema.parse({ name: 123, age: "30" })).toThrow() // invalid type
90
+ })
91
+ })
92
+
93
+ describe("Variant Types", () => {
94
+ it("should generate union schema for variant", () => {
95
+ const variantType = IDL.Variant({
96
+ Ok: IDL.Text,
97
+ Err: IDL.Text,
98
+ })
99
+ const field = visitor.visitVariant(
100
+ variantType,
101
+ [
102
+ ["Ok", IDL.Text],
103
+ ["Err", IDL.Text],
104
+ ],
105
+ "result"
106
+ )
107
+ const schema = field.schema as z.ZodUnion<any>
108
+
109
+ expect(schema.parse({ Ok: "Success" })).toEqual({ Ok: "Success" })
110
+ expect(schema.parse({ Err: "Error" })).toEqual({ Err: "Error" })
111
+
112
+ expect(() => schema.parse({ Other: "value" })).toThrow()
113
+ })
114
+ })
115
+
116
+ describe("Tuple Types", () => {
117
+ it("should generate tuple schema", () => {
118
+ const tupleType = IDL.Tuple(IDL.Text, IDL.Nat)
119
+ const field = visitor.visitTuple(tupleType, [IDL.Text, IDL.Nat], "pair")
120
+ const schema = field.schema as z.ZodTuple<any>
121
+
122
+ expect(schema.parse(["key", "100"])).toEqual(["key", "100"])
123
+ expect(() => schema.parse(["key"])).toThrow()
124
+ })
125
+ })
126
+
127
+ describe("Optional Types", () => {
128
+ it("should generate nullable/optional schema", () => {
129
+ const optType = IDL.Opt(IDL.Text)
130
+ const field = visitor.visitOpt(optType, IDL.Text, "maybe")
131
+ const schema = field.schema
132
+
133
+ expect(schema.parse("value")).toBe("value")
134
+ expect(schema.parse(null)).toBe(null)
135
+ expect(schema.parse(undefined)).toBe(null) // nullish() allows undefined -> null
136
+ })
137
+ })
138
+
139
+ describe("Vector Types", () => {
140
+ it("should generate array schema", () => {
141
+ const vecType = IDL.Vec(IDL.Text)
142
+ const field = visitor.visitVec(vecType, IDL.Text, "tags")
143
+ const schema = field.schema
144
+
145
+ expect(schema.parse(["a", "b"])).toEqual(["a", "b"])
146
+ expect(schema.parse([])).toEqual([])
147
+ expect(() => schema.parse("not array")).toThrow()
148
+ })
149
+
150
+ it("should generate special schema for blob", () => {
151
+ const blobType = IDL.Vec(IDL.Nat8)
152
+ const field = visitor.visitVec(blobType, IDL.Nat8, "data")
153
+ const schema = field.schema
154
+
155
+ // Blob accepts string (hex) or array of numbers
156
+ expect(schema.parse("deadbeef")).toBe("deadbeef")
157
+ expect(schema.parse([1, 2, 3])).toEqual([1, 2, 3])
158
+ expect(() => schema.parse(123)).toThrow()
159
+ })
160
+ })
161
+
162
+ // ════════════════════════════════════════════════════════════════════════
163
+ // Recursive Types
164
+ // ════════════════════════════════════════════════════════════════════════
165
+
166
+ describe("Recursive Types", () => {
167
+ it("should handle recursive schemas", () => {
168
+ const List = IDL.Rec()
169
+ const ListVariant = IDL.Variant({
170
+ Nil: IDL.Null,
171
+ Cons: IDL.Record({
172
+ head: IDL.Nat,
173
+ tail: List,
174
+ }),
175
+ })
176
+ List.fill(ListVariant)
177
+
178
+ const field = visitor.visitRec(List, ListVariant, "list")
179
+ const schema = field.schema
180
+
181
+ const validList = {
182
+ Cons: {
183
+ head: "1",
184
+ tail: {
185
+ Cons: {
186
+ head: "2",
187
+ tail: { Nil: null },
188
+ },
189
+ },
190
+ },
191
+ }
192
+
193
+ expect(schema.parse(validList)).toEqual(validList)
194
+ })
195
+ })
196
+
197
+ // ════════════════════════════════════════════════════════════════════════
198
+ // Method Schema
199
+ // ════════════════════════════════════════════════════════════════════════
200
+
201
+ describe("Method Schema", () => {
202
+ it("should generate tuple schema for function arguments", () => {
203
+ const funcType = IDL.Func([IDL.Text, IDL.Nat], [], [])
204
+ const meta = visitor.visitFunc(funcType, "myMethod")
205
+
206
+ const schema = meta.schema
207
+ expect(schema).toBeDefined()
208
+
209
+ const validArgs = ["hello", "123"]
210
+ expect(schema.parse(validArgs)).toEqual(validArgs)
211
+
212
+ expect(() => schema.parse(["hello"])).toThrow()
213
+ })
214
+ })
215
+ })