@ic-reactor/candid 3.0.14-beta.1 → 3.0.14-beta.2
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 +66 -11
- package/dist/metadata-display-reactor.d.ts.map +1 -1
- package/dist/metadata-display-reactor.js +48 -12
- package/dist/metadata-display-reactor.js.map +1 -1
- package/dist/visitor/arguments/helpers.d.ts +20 -5
- package/dist/visitor/arguments/helpers.d.ts.map +1 -1
- package/dist/visitor/arguments/helpers.js +39 -5
- package/dist/visitor/arguments/helpers.js.map +1 -1
- package/dist/visitor/arguments/index.d.ts.map +1 -1
- package/dist/visitor/arguments/index.js +28 -27
- package/dist/visitor/arguments/index.js.map +1 -1
- package/dist/visitor/arguments/types.d.ts +102 -18
- package/dist/visitor/arguments/types.d.ts.map +1 -1
- package/dist/visitor/arguments/types.js +25 -1
- package/dist/visitor/arguments/types.js.map +1 -1
- package/dist/visitor/returns/index.d.ts.map +1 -1
- package/dist/visitor/returns/index.js +24 -13
- package/dist/visitor/returns/index.js.map +1 -1
- package/dist/visitor/returns/types.d.ts +48 -10
- package/dist/visitor/returns/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/metadata-display-reactor.ts +86 -14
- package/src/visitor/arguments/helpers.ts +48 -6
- package/src/visitor/arguments/index.test.ts +55 -55
- package/src/visitor/arguments/index.ts +36 -27
- package/src/visitor/arguments/types.ts +113 -21
- package/src/visitor/returns/index.test.ts +29 -29
- package/src/visitor/returns/index.ts +52 -21
- package/src/visitor/returns/types.ts +60 -17
|
@@ -289,14 +289,14 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
289
289
|
|
|
290
290
|
expect(field.type).toBe("variant")
|
|
291
291
|
expect(field.label).toBe("status")
|
|
292
|
-
expect(field.
|
|
292
|
+
expect(field.options.map((f) => f.label)).toEqual([
|
|
293
293
|
"Inactive",
|
|
294
294
|
"Active",
|
|
295
295
|
"Pending",
|
|
296
296
|
])
|
|
297
297
|
expect(field.defaultOption).toBe("Inactive")
|
|
298
|
-
expect(field.
|
|
299
|
-
expect(field.
|
|
298
|
+
expect(field.options).toHaveLength(3)
|
|
299
|
+
expect(field.options.some((f) => f.label === "Active")).toBe(true)
|
|
300
300
|
|
|
301
301
|
// Test getOptionDefault helper
|
|
302
302
|
expect(field.getOptionDefault("Active")).toEqual({ _type: "Active" })
|
|
@@ -338,13 +338,13 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
338
338
|
)
|
|
339
339
|
|
|
340
340
|
expect(field.type).toBe("variant")
|
|
341
|
-
expect(field.
|
|
341
|
+
expect(field.options.map((f) => f.label)).toEqual([
|
|
342
342
|
"Approve",
|
|
343
343
|
"Burn",
|
|
344
344
|
"Transfer",
|
|
345
345
|
]) // Sorted order
|
|
346
346
|
|
|
347
|
-
const transferField = field.
|
|
347
|
+
const transferField = field.options.find(
|
|
348
348
|
(f) => f.label === "Transfer"
|
|
349
349
|
) as RecordField
|
|
350
350
|
if (!transferField || transferField.type !== "record") {
|
|
@@ -353,7 +353,7 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
353
353
|
expect(transferField.type).toBe("record")
|
|
354
354
|
expect(transferField.fields).toHaveLength(2)
|
|
355
355
|
|
|
356
|
-
const burnField = field.
|
|
356
|
+
const burnField = field.options.find((f) => f.label === "Burn")
|
|
357
357
|
if (!burnField || burnField.type !== "text") {
|
|
358
358
|
throw new Error("Burn field not found or not text")
|
|
359
359
|
}
|
|
@@ -375,16 +375,16 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
375
375
|
)
|
|
376
376
|
|
|
377
377
|
expect(field.type).toBe("variant")
|
|
378
|
-
expect(field.
|
|
379
|
-
expect(field.
|
|
378
|
+
expect(field.options.some((f) => f.label === "Ok")).toBe(true)
|
|
379
|
+
expect(field.options.some((f) => f.label === "Err")).toBe(true)
|
|
380
380
|
|
|
381
|
-
const okField = field.
|
|
381
|
+
const okField = field.options.find((f) => f.label === "Ok")
|
|
382
382
|
if (!okField || okField.type !== "text") {
|
|
383
383
|
throw new Error("Ok field not found or not text")
|
|
384
384
|
}
|
|
385
385
|
expect(okField.type).toBe("text")
|
|
386
386
|
|
|
387
|
-
const errField = field.
|
|
387
|
+
const errField = field.options.find((f) => f.label === "Err")
|
|
388
388
|
if (!errField || errField.type !== "text") {
|
|
389
389
|
throw new Error("Err field not found or not text")
|
|
390
390
|
}
|
|
@@ -571,8 +571,8 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
571
571
|
throw new Error("Extracted field is not variant")
|
|
572
572
|
}
|
|
573
573
|
expect(extracted.type).toBe("variant")
|
|
574
|
-
expect(extracted.
|
|
575
|
-
expect(extracted.
|
|
574
|
+
expect(extracted.options.some((f) => f.label === "Leaf")).toBe(true)
|
|
575
|
+
expect(extracted.options.some((f) => f.label === "Node")).toBe(true)
|
|
576
576
|
})
|
|
577
577
|
|
|
578
578
|
it("should handle recursive linked list", () => {
|
|
@@ -606,9 +606,9 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
606
606
|
throw new Error("Extracted field is not variant")
|
|
607
607
|
}
|
|
608
608
|
expect(extracted.type).toBe("variant")
|
|
609
|
-
expect(extracted.
|
|
609
|
+
expect(extracted.options.map((f) => f.label)).toEqual(["Nil", "Cons"])
|
|
610
610
|
|
|
611
|
-
const consField = extracted.
|
|
611
|
+
const consField = extracted.options.find(
|
|
612
612
|
(f) => f.label === "Cons"
|
|
613
613
|
) as RecordField
|
|
614
614
|
if (!consField || consField.type !== "record") {
|
|
@@ -630,11 +630,11 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
630
630
|
|
|
631
631
|
expect(meta.functionType).toBe("query")
|
|
632
632
|
expect(meta.functionName).toBe("lookup")
|
|
633
|
-
expect(meta.
|
|
634
|
-
expect(meta.
|
|
635
|
-
expect(meta.
|
|
633
|
+
expect(meta.args).toHaveLength(1)
|
|
634
|
+
expect(meta.args[0].type).toBe("text")
|
|
635
|
+
expect(meta.defaults).toEqual([""])
|
|
636
636
|
expect(meta.argCount).toBe(1)
|
|
637
|
-
expect(meta.
|
|
637
|
+
expect(meta.isEmpty).toBe(false)
|
|
638
638
|
})
|
|
639
639
|
|
|
640
640
|
it("should handle update function", () => {
|
|
@@ -657,10 +657,10 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
657
657
|
|
|
658
658
|
expect(meta.functionType).toBe("update")
|
|
659
659
|
expect(meta.functionName).toBe("transfer")
|
|
660
|
-
expect(meta.
|
|
661
|
-
expect(meta.
|
|
660
|
+
expect(meta.args).toHaveLength(1)
|
|
661
|
+
expect(meta.args[0].type).toBe("record")
|
|
662
662
|
|
|
663
|
-
const recordField = meta.
|
|
663
|
+
const recordField = meta.args[0] as RecordField
|
|
664
664
|
if (recordField.type !== "record") {
|
|
665
665
|
throw new Error("Expected record field")
|
|
666
666
|
}
|
|
@@ -675,10 +675,10 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
675
675
|
)
|
|
676
676
|
const meta = visitor.visitFunc(funcType, "authorize")
|
|
677
677
|
|
|
678
|
-
expect(meta.
|
|
679
|
-
expect(meta.
|
|
680
|
-
expect(meta.
|
|
681
|
-
expect(meta.
|
|
678
|
+
expect(meta.args).toHaveLength(3)
|
|
679
|
+
expect(meta.args[0].type).toBe("principal")
|
|
680
|
+
expect(meta.args[1].type).toBe("text")
|
|
681
|
+
expect(meta.args[2].type).toBe("optional")
|
|
682
682
|
expect(meta.argCount).toBe(3)
|
|
683
683
|
})
|
|
684
684
|
|
|
@@ -687,10 +687,10 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
687
687
|
const meta = visitor.visitFunc(funcType, "getBalance")
|
|
688
688
|
|
|
689
689
|
expect(meta.functionType).toBe("query")
|
|
690
|
-
expect(meta.
|
|
691
|
-
expect(meta.
|
|
690
|
+
expect(meta.args).toHaveLength(0)
|
|
691
|
+
expect(meta.defaults).toEqual([])
|
|
692
692
|
expect(meta.argCount).toBe(0)
|
|
693
|
-
expect(meta.
|
|
693
|
+
expect(meta.isEmpty).toBe(true)
|
|
694
694
|
})
|
|
695
695
|
})
|
|
696
696
|
|
|
@@ -734,20 +734,20 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
734
734
|
// Check get_balance
|
|
735
735
|
const getBalanceMeta = serviceMeta["get_balance"]
|
|
736
736
|
expect(getBalanceMeta.functionType).toBe("query")
|
|
737
|
-
expect(getBalanceMeta.
|
|
738
|
-
expect(getBalanceMeta.
|
|
737
|
+
expect(getBalanceMeta.args).toHaveLength(1)
|
|
738
|
+
expect(getBalanceMeta.args[0].type).toBe("principal")
|
|
739
739
|
|
|
740
740
|
// Check transfer
|
|
741
741
|
const transferMeta = serviceMeta["transfer"]
|
|
742
742
|
expect(transferMeta.functionType).toBe("update")
|
|
743
|
-
expect(transferMeta.
|
|
744
|
-
expect(transferMeta.
|
|
743
|
+
expect(transferMeta.args).toHaveLength(1)
|
|
744
|
+
expect(transferMeta.args[0].type).toBe("record")
|
|
745
745
|
|
|
746
746
|
// Check get_metadata
|
|
747
747
|
const getMetadataMeta = serviceMeta["get_metadata"]
|
|
748
748
|
expect(getMetadataMeta.functionType).toBe("query")
|
|
749
|
-
expect(getMetadataMeta.
|
|
750
|
-
expect(getMetadataMeta.
|
|
749
|
+
expect(getMetadataMeta.args).toHaveLength(0)
|
|
750
|
+
expect(getMetadataMeta.isEmpty).toBe(true)
|
|
751
751
|
})
|
|
752
752
|
})
|
|
753
753
|
|
|
@@ -772,7 +772,7 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
772
772
|
)
|
|
773
773
|
const meta = visitor.visitFunc(funcType, "updateUser")
|
|
774
774
|
|
|
775
|
-
const argRecord = meta.
|
|
775
|
+
const argRecord = meta.args[0] as RecordField
|
|
776
776
|
if (argRecord.type !== "record") {
|
|
777
777
|
throw new Error("Expected record field")
|
|
778
778
|
}
|
|
@@ -803,7 +803,7 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
803
803
|
const funcType = IDL.Func([IDL.Vec(IDL.Text)], [], [])
|
|
804
804
|
const meta = visitor.visitFunc(funcType, "addTags")
|
|
805
805
|
|
|
806
|
-
const vecField = meta.
|
|
806
|
+
const vecField = meta.args[0] as VectorField
|
|
807
807
|
if (vecField.type !== "vector") {
|
|
808
808
|
throw new Error("Expected vector field")
|
|
809
809
|
}
|
|
@@ -923,16 +923,16 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
923
923
|
)
|
|
924
924
|
|
|
925
925
|
expect(field.type).toBe("variant")
|
|
926
|
-
expect(field.
|
|
926
|
+
expect(field.options.some((f) => f.label === "Motion")).toBe(true)
|
|
927
927
|
expect(
|
|
928
|
-
field.
|
|
928
|
+
field.options.some((f) => f.label === "TransferSnsTreasuryFunds")
|
|
929
929
|
).toBe(true)
|
|
930
930
|
expect(
|
|
931
|
-
field.
|
|
931
|
+
field.options.some((f) => f.label === "UpgradeSnsControlledCanister")
|
|
932
932
|
).toBe(true)
|
|
933
933
|
|
|
934
934
|
// Check Motion variant
|
|
935
|
-
const motionField = field.
|
|
935
|
+
const motionField = field.options.find(
|
|
936
936
|
(f) => f.label === "Motion"
|
|
937
937
|
) as RecordField
|
|
938
938
|
if (!motionField || motionField.type !== "record") {
|
|
@@ -942,7 +942,7 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
942
942
|
expect(motionField.fields).toHaveLength(1)
|
|
943
943
|
|
|
944
944
|
// Check TransferSnsTreasuryFunds variant
|
|
945
|
-
const transferField = field.
|
|
945
|
+
const transferField = field.options.find(
|
|
946
946
|
(f) => f.label === "TransferSnsTreasuryFunds"
|
|
947
947
|
) as RecordField
|
|
948
948
|
if (!transferField || transferField.type !== "record") {
|
|
@@ -1011,8 +1011,8 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
1011
1011
|
const funcType = IDL.Func([IDL.Text, IDL.Nat], [], [])
|
|
1012
1012
|
const meta = visitor.visitFunc(funcType, "test")
|
|
1013
1013
|
|
|
1014
|
-
expect(meta.
|
|
1015
|
-
expect(meta.
|
|
1014
|
+
expect(meta.args[0].displayLabel).toBe("Arg 0")
|
|
1015
|
+
expect(meta.args[1].displayLabel).toBe("Arg 1")
|
|
1016
1016
|
})
|
|
1017
1017
|
|
|
1018
1018
|
it("should format tuple index labels correctly", () => {
|
|
@@ -1231,14 +1231,14 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
1231
1231
|
"action"
|
|
1232
1232
|
)
|
|
1233
1233
|
|
|
1234
|
-
const transferField = field.
|
|
1234
|
+
const transferField = field.getOption("Transfer")
|
|
1235
1235
|
expect(transferField.type).toBe("record")
|
|
1236
1236
|
|
|
1237
|
-
const burnField = field.
|
|
1237
|
+
const burnField = field.getOption("Burn")
|
|
1238
1238
|
expect(burnField.type).toBe("text") // nat is rendered as text for large numbers
|
|
1239
1239
|
})
|
|
1240
1240
|
|
|
1241
|
-
it("
|
|
1241
|
+
it("getSelectedKey should return the selected key from a value", () => {
|
|
1242
1242
|
const variantType = IDL.Variant({ A: IDL.Null, B: IDL.Text, C: IDL.Nat })
|
|
1243
1243
|
const field = visitor.visitVariant(
|
|
1244
1244
|
variantType,
|
|
@@ -1250,11 +1250,11 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
1250
1250
|
"choice"
|
|
1251
1251
|
)
|
|
1252
1252
|
|
|
1253
|
-
expect(field.
|
|
1254
|
-
expect(field.
|
|
1255
|
-
expect(field.
|
|
1253
|
+
expect(field.getSelectedKey({ A: null })).toBe("A")
|
|
1254
|
+
expect(field.getSelectedKey({ B: "hello" })).toBe("B")
|
|
1255
|
+
expect(field.getSelectedKey({ C: "100" })).toBe("C")
|
|
1256
1256
|
// Falls back to default option for unknown values
|
|
1257
|
-
expect(field.
|
|
1257
|
+
expect(field.getSelectedKey({})).toBe("A")
|
|
1258
1258
|
})
|
|
1259
1259
|
|
|
1260
1260
|
it("getSelectedField should return the field for the selected option", () => {
|
|
@@ -1271,10 +1271,10 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
1271
1271
|
"result"
|
|
1272
1272
|
)
|
|
1273
1273
|
|
|
1274
|
-
const okField = field.
|
|
1274
|
+
const okField = field.getSelectedOption({ Ok: "100" })
|
|
1275
1275
|
expect(okField.label).toBe("Ok")
|
|
1276
1276
|
|
|
1277
|
-
const errField = field.
|
|
1277
|
+
const errField = field.getSelectedOption({ Err: "error" })
|
|
1278
1278
|
expect(errField.label).toBe("Err")
|
|
1279
1279
|
})
|
|
1280
1280
|
})
|
|
@@ -1312,7 +1312,7 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
1312
1312
|
it("should create item field with correct index in name path", () => {
|
|
1313
1313
|
const funcType = IDL.Func([IDL.Vec(IDL.Text)], [], [])
|
|
1314
1314
|
const meta = visitor.visitFunc(funcType, "addItems")
|
|
1315
|
-
const vecField = meta.
|
|
1315
|
+
const vecField = meta.args[0] as VectorField
|
|
1316
1316
|
|
|
1317
1317
|
const item0 = vecField.createItemField(0)
|
|
1318
1318
|
expect(item0.name).toBe("[0][0]")
|
|
@@ -1328,7 +1328,7 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
1328
1328
|
[]
|
|
1329
1329
|
)
|
|
1330
1330
|
const meta = visitor.visitFunc(funcType, "addItems")
|
|
1331
|
-
const vecField = meta.
|
|
1331
|
+
const vecField = meta.args[0] as VectorField
|
|
1332
1332
|
|
|
1333
1333
|
const item = vecField.createItemField(3, { label: "Person 3" })
|
|
1334
1334
|
expect(item.label).toBe("Person 3")
|
|
@@ -1338,7 +1338,7 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
1338
1338
|
it("should use default label when not provided", () => {
|
|
1339
1339
|
const funcType = IDL.Func([IDL.Vec(IDL.Text)], [], [])
|
|
1340
1340
|
const meta = visitor.visitFunc(funcType, "addTags")
|
|
1341
|
-
const vecField = meta.
|
|
1341
|
+
const vecField = meta.args[0] as VectorField
|
|
1342
1342
|
|
|
1343
1343
|
const item = vecField.createItemField(2)
|
|
1344
1344
|
expect(item.label).toBe("Item 2")
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isQuery } from "../helpers"
|
|
2
2
|
import { checkTextFormat, checkNumberFormat } from "../constants"
|
|
3
|
+
import { MetadataError } from "./types"
|
|
3
4
|
import type {
|
|
4
5
|
FieldNode,
|
|
5
6
|
RecordField,
|
|
@@ -233,13 +234,13 @@ export class FieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
233
234
|
const functionType = isQuery(t) ? "query" : "update"
|
|
234
235
|
const argCount = t.argTypes.length
|
|
235
236
|
|
|
236
|
-
const
|
|
237
|
+
const args = t.argTypes.map((arg, index) => {
|
|
237
238
|
return this.withName(`[${index}]`, () =>
|
|
238
239
|
arg.accept(this, `__arg${index}`)
|
|
239
240
|
) as FieldNode
|
|
240
241
|
})
|
|
241
242
|
|
|
242
|
-
const
|
|
243
|
+
const defaults = args.map((field) => field.defaultValue)
|
|
243
244
|
|
|
244
245
|
// Handle empty args case for schema
|
|
245
246
|
// For no-arg functions, use an empty array schema
|
|
@@ -250,7 +251,7 @@ export class FieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
250
251
|
[z.ZodTypeAny, ...z.ZodTypeAny[]]
|
|
251
252
|
>)
|
|
252
253
|
: z.tuple(
|
|
253
|
-
|
|
254
|
+
args.map((field) => field.schema) as [
|
|
254
255
|
z.ZodTypeAny,
|
|
255
256
|
...z.ZodTypeAny[],
|
|
256
257
|
]
|
|
@@ -259,11 +260,11 @@ export class FieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
259
260
|
return {
|
|
260
261
|
functionType,
|
|
261
262
|
functionName,
|
|
262
|
-
|
|
263
|
-
|
|
263
|
+
args,
|
|
264
|
+
defaults,
|
|
264
265
|
schema,
|
|
265
266
|
argCount,
|
|
266
|
-
|
|
267
|
+
isEmpty: argCount === 0,
|
|
267
268
|
}
|
|
268
269
|
}
|
|
269
270
|
|
|
@@ -313,7 +314,7 @@ export class FieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
313
314
|
label: string
|
|
314
315
|
): VariantField {
|
|
315
316
|
const name = this.currentName()
|
|
316
|
-
const
|
|
317
|
+
const options: FieldNode[] = []
|
|
317
318
|
const variantSchemas: z.ZodTypeAny[] = []
|
|
318
319
|
|
|
319
320
|
for (const [key, type] of fields_) {
|
|
@@ -321,7 +322,7 @@ export class FieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
321
322
|
type.accept(this, key)
|
|
322
323
|
) as FieldNode
|
|
323
324
|
|
|
324
|
-
|
|
325
|
+
options.push(field)
|
|
325
326
|
|
|
326
327
|
if (field.type === "null") {
|
|
327
328
|
variantSchemas.push(z.object({ _type: z.literal(key) }))
|
|
@@ -335,24 +336,28 @@ export class FieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
335
336
|
}
|
|
336
337
|
}
|
|
337
338
|
|
|
338
|
-
const
|
|
339
|
-
const defaultOption =
|
|
339
|
+
const firstOption = options[0]
|
|
340
|
+
const defaultOption = firstOption.label
|
|
340
341
|
|
|
341
342
|
const defaultValue =
|
|
342
|
-
|
|
343
|
+
firstOption.type === "null"
|
|
343
344
|
? { _type: defaultOption }
|
|
344
345
|
: {
|
|
345
346
|
_type: defaultOption,
|
|
346
|
-
[defaultOption]:
|
|
347
|
+
[defaultOption]: firstOption.defaultValue,
|
|
347
348
|
}
|
|
348
349
|
|
|
349
350
|
const schema = z.union(variantSchemas as [z.ZodTypeAny, ...z.ZodTypeAny[]])
|
|
350
351
|
|
|
351
352
|
// Helper to get default value for any option
|
|
352
353
|
const getOptionDefault = (option: string): Record<string, unknown> => {
|
|
353
|
-
const optField =
|
|
354
|
+
const optField = options.find((f) => f.label === option)
|
|
354
355
|
if (!optField) {
|
|
355
|
-
throw new
|
|
356
|
+
throw new MetadataError(
|
|
357
|
+
`Unknown variant option: "${option}". Available: ${options.map((o) => o.label).join(", ")}`,
|
|
358
|
+
name,
|
|
359
|
+
"variant"
|
|
360
|
+
)
|
|
356
361
|
}
|
|
357
362
|
return optField.type === "null"
|
|
358
363
|
? { _type: option }
|
|
@@ -360,29 +365,33 @@ export class FieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
360
365
|
}
|
|
361
366
|
|
|
362
367
|
// Helper to get field for a specific option
|
|
363
|
-
const
|
|
364
|
-
const optField =
|
|
368
|
+
const getOption = (option: string): FieldNode => {
|
|
369
|
+
const optField = options.find((f) => f.label === option)
|
|
365
370
|
if (!optField) {
|
|
366
|
-
throw new
|
|
371
|
+
throw new MetadataError(
|
|
372
|
+
`Unknown variant option: "${option}". Available: ${options.map((o) => o.label).join(", ")}`,
|
|
373
|
+
name,
|
|
374
|
+
"variant"
|
|
375
|
+
)
|
|
367
376
|
}
|
|
368
377
|
return optField
|
|
369
378
|
}
|
|
370
379
|
|
|
371
|
-
// Helper to get currently selected option from a value
|
|
372
|
-
const
|
|
380
|
+
// Helper to get currently selected option key from a value
|
|
381
|
+
const getSelectedKey = (value: Record<string, unknown>): string => {
|
|
373
382
|
if (value._type && typeof value._type === "string") {
|
|
374
383
|
return value._type
|
|
375
384
|
}
|
|
376
385
|
const validKeys = Object.keys(value).filter((k) =>
|
|
377
|
-
|
|
386
|
+
options.some((f) => f.label === k)
|
|
378
387
|
)
|
|
379
388
|
return validKeys[0] ?? defaultOption
|
|
380
389
|
}
|
|
381
390
|
|
|
382
|
-
// Helper to get
|
|
383
|
-
const
|
|
384
|
-
const
|
|
385
|
-
return
|
|
391
|
+
// Helper to get the field for the currently selected option
|
|
392
|
+
const getSelectedOption = (value: Record<string, unknown>): FieldNode => {
|
|
393
|
+
const selectedKey = getSelectedKey(value)
|
|
394
|
+
return getOption(selectedKey)
|
|
386
395
|
}
|
|
387
396
|
|
|
388
397
|
return {
|
|
@@ -392,14 +401,14 @@ export class FieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
392
401
|
name,
|
|
393
402
|
component: "variant-select",
|
|
394
403
|
renderHint: COMPOUND_RENDER_HINT,
|
|
395
|
-
|
|
404
|
+
options,
|
|
396
405
|
defaultOption,
|
|
397
406
|
defaultValue,
|
|
398
407
|
schema,
|
|
399
408
|
getOptionDefault,
|
|
400
|
-
|
|
409
|
+
getOption,
|
|
410
|
+
getSelectedKey,
|
|
401
411
|
getSelectedOption,
|
|
402
|
-
getSelectedField,
|
|
403
412
|
candidType: "variant",
|
|
404
413
|
}
|
|
405
414
|
}
|