@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.
- package/dist/display-reactor.d.ts +1 -2
- package/dist/display-reactor.d.ts.map +1 -1
- package/dist/display-reactor.js +1 -1
- package/dist/display-reactor.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/metadata-display-reactor.d.ts +3 -3
- 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 +64 -42
- package/dist/visitor/arguments/index.d.ts.map +1 -1
- package/dist/visitor/arguments/index.js +472 -85
- package/dist/visitor/arguments/index.js.map +1 -1
- package/dist/visitor/arguments/types.d.ts +481 -46
- package/dist/visitor/arguments/types.d.ts.map +1 -1
- package/dist/visitor/helpers.d.ts +1 -1
- package/dist/visitor/helpers.d.ts.map +1 -1
- package/dist/visitor/returns/index.d.ts +1 -2
- package/dist/visitor/returns/index.d.ts.map +1 -1
- package/dist/visitor/returns/index.js +2 -3
- package/dist/visitor/returns/index.js.map +1 -1
- package/dist/visitor/types.d.ts +2 -3
- package/dist/visitor/types.d.ts.map +1 -1
- package/dist/visitor/types.js +1 -2
- package/dist/visitor/types.js.map +1 -1
- package/package.json +6 -3
- package/src/display-reactor.ts +4 -6
- package/src/index.ts +0 -1
- package/src/metadata-display-reactor.ts +8 -8
- package/src/visitor/arguments/helpers.ts +104 -0
- package/src/visitor/arguments/index.test.ts +544 -52
- package/src/visitor/arguments/index.ts +590 -151
- package/src/visitor/arguments/schema.test.ts +215 -0
- package/src/visitor/arguments/types.ts +554 -62
- package/src/visitor/helpers.ts +1 -1
- package/src/visitor/returns/index.test.ts +1 -1
- package/src/visitor/returns/index.ts +2 -3
- 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
|
+
})
|