@sundaeswap/sprinkles 0.5.0 → 0.6.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.
Files changed (112) hide show
  1. package/dist/cjs/Sprinkle/__tests__/encryption.test.js +3 -1
  2. package/dist/cjs/Sprinkle/__tests__/encryption.test.js.map +1 -1
  3. package/dist/cjs/Sprinkle/__tests__/enhancements.test.js +3 -37
  4. package/dist/cjs/Sprinkle/__tests__/enhancements.test.js.map +1 -1
  5. package/dist/cjs/Sprinkle/__tests__/field-utils.test.js +170 -0
  6. package/dist/cjs/Sprinkle/__tests__/field-utils.test.js.map +1 -0
  7. package/dist/cjs/Sprinkle/__tests__/fill-in-struct.test.js +377 -84
  8. package/dist/cjs/Sprinkle/__tests__/fill-in-struct.test.js.map +1 -1
  9. package/dist/cjs/Sprinkle/__tests__/formatting.test.js +97 -0
  10. package/dist/cjs/Sprinkle/__tests__/formatting.test.js.map +1 -0
  11. package/dist/cjs/Sprinkle/__tests__/show-menu.test.js +9 -5
  12. package/dist/cjs/Sprinkle/__tests__/show-menu.test.js.map +1 -1
  13. package/dist/cjs/Sprinkle/__tests__/tx-dialog.test.js +9 -0
  14. package/dist/cjs/Sprinkle/__tests__/tx-dialog.test.js.map +1 -1
  15. package/dist/cjs/Sprinkle/index.js +174 -94
  16. package/dist/cjs/Sprinkle/index.js.map +1 -1
  17. package/dist/cjs/Sprinkle/menus/array-menu.js +195 -0
  18. package/dist/cjs/Sprinkle/menus/array-menu.js.map +1 -0
  19. package/dist/cjs/Sprinkle/menus/field-menu.js +161 -0
  20. package/dist/cjs/Sprinkle/menus/field-menu.js.map +1 -0
  21. package/dist/cjs/Sprinkle/menus/index.js +33 -0
  22. package/dist/cjs/Sprinkle/menus/index.js.map +1 -0
  23. package/dist/cjs/Sprinkle/menus/object-menu.js +324 -0
  24. package/dist/cjs/Sprinkle/menus/object-menu.js.map +1 -0
  25. package/dist/cjs/Sprinkle/prompts.js +68 -2
  26. package/dist/cjs/Sprinkle/prompts.js.map +1 -1
  27. package/dist/cjs/Sprinkle/type-guards.js +48 -1
  28. package/dist/cjs/Sprinkle/type-guards.js.map +1 -1
  29. package/dist/cjs/Sprinkle/types.js +24 -0
  30. package/dist/cjs/Sprinkle/types.js.map +1 -1
  31. package/dist/cjs/Sprinkle/utils/field-utils.js +154 -0
  32. package/dist/cjs/Sprinkle/utils/field-utils.js.map +1 -0
  33. package/dist/cjs/Sprinkle/utils/formatting.js +126 -0
  34. package/dist/cjs/Sprinkle/utils/formatting.js.map +1 -0
  35. package/dist/cjs/Sprinkle/utils/index.js +56 -0
  36. package/dist/cjs/Sprinkle/utils/index.js.map +1 -0
  37. package/dist/esm/Sprinkle/__tests__/encryption.test.js +3 -1
  38. package/dist/esm/Sprinkle/__tests__/encryption.test.js.map +1 -1
  39. package/dist/esm/Sprinkle/__tests__/enhancements.test.js +3 -37
  40. package/dist/esm/Sprinkle/__tests__/enhancements.test.js.map +1 -1
  41. package/dist/esm/Sprinkle/__tests__/field-utils.test.js +168 -0
  42. package/dist/esm/Sprinkle/__tests__/field-utils.test.js.map +1 -0
  43. package/dist/esm/Sprinkle/__tests__/fill-in-struct.test.js +378 -85
  44. package/dist/esm/Sprinkle/__tests__/fill-in-struct.test.js.map +1 -1
  45. package/dist/esm/Sprinkle/__tests__/formatting.test.js +95 -0
  46. package/dist/esm/Sprinkle/__tests__/formatting.test.js.map +1 -0
  47. package/dist/esm/Sprinkle/__tests__/show-menu.test.js +9 -5
  48. package/dist/esm/Sprinkle/__tests__/show-menu.test.js.map +1 -1
  49. package/dist/esm/Sprinkle/__tests__/tx-dialog.test.js +9 -0
  50. package/dist/esm/Sprinkle/__tests__/tx-dialog.test.js.map +1 -1
  51. package/dist/esm/Sprinkle/index.js +141 -96
  52. package/dist/esm/Sprinkle/index.js.map +1 -1
  53. package/dist/esm/Sprinkle/menus/array-menu.js +190 -0
  54. package/dist/esm/Sprinkle/menus/array-menu.js.map +1 -0
  55. package/dist/esm/Sprinkle/menus/field-menu.js +155 -0
  56. package/dist/esm/Sprinkle/menus/field-menu.js.map +1 -0
  57. package/dist/esm/Sprinkle/menus/index.js +8 -0
  58. package/dist/esm/Sprinkle/menus/index.js.map +1 -0
  59. package/dist/esm/Sprinkle/menus/object-menu.js +318 -0
  60. package/dist/esm/Sprinkle/menus/object-menu.js.map +1 -0
  61. package/dist/esm/Sprinkle/prompts.js +59 -1
  62. package/dist/esm/Sprinkle/prompts.js.map +1 -1
  63. package/dist/esm/Sprinkle/type-guards.js +42 -0
  64. package/dist/esm/Sprinkle/type-guards.js.map +1 -1
  65. package/dist/esm/Sprinkle/types.js +24 -0
  66. package/dist/esm/Sprinkle/types.js.map +1 -1
  67. package/dist/esm/Sprinkle/utils/field-utils.js +145 -0
  68. package/dist/esm/Sprinkle/utils/field-utils.js.map +1 -0
  69. package/dist/esm/Sprinkle/utils/formatting.js +118 -0
  70. package/dist/esm/Sprinkle/utils/formatting.js.map +1 -0
  71. package/dist/esm/Sprinkle/utils/index.js +7 -0
  72. package/dist/esm/Sprinkle/utils/index.js.map +1 -0
  73. package/dist/types/Sprinkle/index.d.ts +9 -3
  74. package/dist/types/Sprinkle/index.d.ts.map +1 -1
  75. package/dist/types/Sprinkle/menus/array-menu.d.ts +31 -0
  76. package/dist/types/Sprinkle/menus/array-menu.d.ts.map +1 -0
  77. package/dist/types/Sprinkle/menus/field-menu.d.ts +34 -0
  78. package/dist/types/Sprinkle/menus/field-menu.d.ts.map +1 -0
  79. package/dist/types/Sprinkle/menus/index.d.ts +10 -0
  80. package/dist/types/Sprinkle/menus/index.d.ts.map +1 -0
  81. package/dist/types/Sprinkle/menus/object-menu.d.ts +34 -0
  82. package/dist/types/Sprinkle/menus/object-menu.d.ts.map +1 -0
  83. package/dist/types/Sprinkle/prompts.d.ts +25 -0
  84. package/dist/types/Sprinkle/prompts.d.ts.map +1 -1
  85. package/dist/types/Sprinkle/type-guards.d.ts +24 -1
  86. package/dist/types/Sprinkle/type-guards.d.ts.map +1 -1
  87. package/dist/types/Sprinkle/types.d.ts +53 -0
  88. package/dist/types/Sprinkle/types.d.ts.map +1 -1
  89. package/dist/types/Sprinkle/utils/field-utils.d.ts +47 -0
  90. package/dist/types/Sprinkle/utils/field-utils.d.ts.map +1 -0
  91. package/dist/types/Sprinkle/utils/formatting.d.ts +30 -0
  92. package/dist/types/Sprinkle/utils/formatting.d.ts.map +1 -0
  93. package/dist/types/tsconfig.build.tsbuildinfo +1 -1
  94. package/package.json +1 -1
  95. package/src/Sprinkle/__tests__/encryption.test.ts +2 -0
  96. package/src/Sprinkle/__tests__/enhancements.test.ts +3 -42
  97. package/src/Sprinkle/__tests__/field-utils.test.ts +191 -0
  98. package/src/Sprinkle/__tests__/fill-in-struct.test.ts +393 -100
  99. package/src/Sprinkle/__tests__/formatting.test.ts +115 -0
  100. package/src/Sprinkle/__tests__/show-menu.test.ts +14 -8
  101. package/src/Sprinkle/__tests__/tx-dialog.test.ts +9 -0
  102. package/src/Sprinkle/index.ts +175 -122
  103. package/src/Sprinkle/menus/array-menu.ts +191 -0
  104. package/src/Sprinkle/menus/field-menu.ts +145 -0
  105. package/src/Sprinkle/menus/index.ts +12 -0
  106. package/src/Sprinkle/menus/object-menu.ts +336 -0
  107. package/src/Sprinkle/prompts.ts +71 -1
  108. package/src/Sprinkle/type-guards.ts +42 -0
  109. package/src/Sprinkle/types.ts +43 -0
  110. package/src/Sprinkle/utils/field-utils.ts +158 -0
  111. package/src/Sprinkle/utils/formatting.ts +127 -0
  112. package/src/Sprinkle/utils/index.ts +17 -0
@@ -23,6 +23,11 @@ var _exportNames = {
23
23
  isTuple: true,
24
24
  isUnion: true,
25
25
  isSensitive: true,
26
+ isNull: true,
27
+ isNullable: true,
28
+ unwrapNullable: true,
29
+ hasDefault: true,
30
+ getDefault: true,
26
31
  GetProvider: true,
27
32
  GetWallet: true,
28
33
  GetBlaze: true
@@ -82,6 +87,18 @@ Object.defineProperty(exports, "WalletSettingsSchema", {
82
87
  return _schemas.WalletSettingsSchema;
83
88
  }
84
89
  });
90
+ Object.defineProperty(exports, "getDefault", {
91
+ enumerable: true,
92
+ get: function () {
93
+ return _typeGuards.getDefault;
94
+ }
95
+ });
96
+ Object.defineProperty(exports, "hasDefault", {
97
+ enumerable: true,
98
+ get: function () {
99
+ return _typeGuards.hasDefault;
100
+ }
101
+ });
85
102
  Object.defineProperty(exports, "isArray", {
86
103
  enumerable: true,
87
104
  get: function () {
@@ -106,6 +123,18 @@ Object.defineProperty(exports, "isLiteral", {
106
123
  return _typeGuards.isLiteral;
107
124
  }
108
125
  });
126
+ Object.defineProperty(exports, "isNull", {
127
+ enumerable: true,
128
+ get: function () {
129
+ return _typeGuards.isNull;
130
+ }
131
+ });
132
+ Object.defineProperty(exports, "isNullable", {
133
+ enumerable: true,
134
+ get: function () {
135
+ return _typeGuards.isNullable;
136
+ }
137
+ });
109
138
  Object.defineProperty(exports, "isObject", {
110
139
  enumerable: true,
111
140
  get: function () {
@@ -154,9 +183,16 @@ Object.defineProperty(exports, "isUnion", {
154
183
  return _typeGuards.isUnion;
155
184
  }
156
185
  });
186
+ Object.defineProperty(exports, "unwrapNullable", {
187
+ enumerable: true,
188
+ get: function () {
189
+ return _typeGuards.unwrapNullable;
190
+ }
191
+ });
157
192
  var _sdk = require("@blaze-cardano/sdk");
158
193
  var _core = require("@blaze-cardano/core");
159
194
  var _prompts = require("./prompts.js");
195
+ var _yoctocolorsCjs = _interopRequireDefault(require("yoctocolors-cjs"));
160
196
  var _typebox = require("@sinclair/typebox");
161
197
  Object.keys(_typebox).forEach(function (key) {
162
198
  if (key === "default" || key === "__esModule") return;
@@ -169,6 +205,7 @@ Object.keys(_typebox).forEach(function (key) {
169
205
  }
170
206
  });
171
207
  });
208
+ var _value = require("@sinclair/typebox/value");
172
209
  var fs = _interopRequireWildcard(require("fs"));
173
210
  var path = _interopRequireWildcard(require("path"));
174
211
  var _types = require("./types.js");
@@ -177,6 +214,9 @@ var _typeGuards = require("./type-guards.js");
177
214
  var _wallet = require("./wallet.js");
178
215
  var _encryption = require("./encryption.js");
179
216
  var _txDialog = require("./tx-dialog.js");
217
+ var _index = require("./menus/index.js");
218
+ var _formatting = require("./utils/formatting.js");
219
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
180
220
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
181
221
  function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
182
222
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
@@ -187,6 +227,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
187
227
  // Import and re-export wallet utilities
188
228
  // Import encryption utilities
189
229
  // Import tx-dialog utilities
230
+ // Import menu modules
190
231
  class Sprinkle {
191
232
  constructor(type, storagePath, options) {
192
233
  _defineProperty(this, "storagePath", void 0);
@@ -509,9 +550,13 @@ class Sprinkle {
509
550
  // --- Menu ---
510
551
 
511
552
  async showMenu(menu) {
512
- return this._showMenu(menu, true);
553
+ return this._showMenu(menu, true, [menu.title]);
513
554
  }
514
- async _showMenu(menu, main) {
555
+ async _showMenu(menu, main, path, clearPrevious = false) {
556
+ // Clear previous breadcrumb if coming back from action/submenu
557
+ if (clearPrevious) {
558
+ process.stdout.write("\x1b[1A\x1b[2K\x1b[G");
559
+ }
515
560
  if (menu.beforeShow) {
516
561
  await menu.beforeShow(this);
517
562
  }
@@ -543,11 +588,16 @@ class Sprinkle {
543
588
  value: -1
544
589
  });
545
590
  }
546
- const selectionResult = await (0, _prompts.selectCancellable)({
591
+
592
+ // Show breadcrumb
593
+ const breadcrumb = path.join(" > ");
594
+ console.log(_yoctocolorsCjs.default.dim("🍞 " + breadcrumb));
595
+ const selectionResult = await (0, _prompts.selectWithClear)({
547
596
  message: "Select an option:",
548
597
  choices: choices
549
598
  });
550
599
  // Handle escape (null) as Back
600
+ // Don't clear here - let the caller's clearPrevious handle it
551
601
  if (selectionResult === null) {
552
602
  return;
553
603
  }
@@ -558,13 +608,34 @@ class Sprinkle {
558
608
  items: [{
559
609
  title: "View settings",
560
610
  action: async () => {
561
- console.log(JSON.stringify(this.getDisplaySettings(), _encryption.bigIntReplacer, 2));
611
+ const jsonStr = JSON.stringify(this.getDisplaySettings(), _encryption.bigIntReplacer, 2);
612
+ const jsonLines = jsonStr.split("\n").length;
613
+ console.log(jsonStr);
614
+
615
+ // Wait for user to press Enter
616
+ await (0, _prompts.selectWithClear)({
617
+ message: "Press Enter to continue...",
618
+ choices: [{
619
+ name: "Continue",
620
+ value: "continue"
621
+ }]
622
+ });
623
+
624
+ // Clear the JSON output
625
+ process.stdout.write("\x1b[1A\x1b[2K".repeat(jsonLines) + "\x1b[G");
562
626
  }
563
627
  }, {
564
628
  title: "Edit settings",
565
629
  action: async () => {
566
- this.settings = await this.EditStruct(this.type, this.settings);
567
- this.saveSettings();
630
+ try {
631
+ this.settings = await this.EditStruct(this.type, this.settings);
632
+ this.saveSettings();
633
+ } catch (e) {
634
+ if (e instanceof _types.UserCancelledError) {
635
+ return; // User cancelled, return to menu
636
+ }
637
+ throw e;
638
+ }
568
639
  }
569
640
  }, {
570
641
  title: "Switch profile",
@@ -599,24 +670,28 @@ class Sprinkle {
599
670
  }
600
671
  }]
601
672
  };
602
- await this._showMenu(settingsMenu, false);
603
- await this._showMenu(menu, main);
673
+ await this._showMenu(settingsMenu, false, [...path, "Settings & Profiles"], true);
674
+ await this._showMenu(menu, main, path, true);
604
675
  return;
605
676
  }
606
677
  if (selection === -1) {
678
+ // Don't clear here - let the caller's clearPrevious handle it
607
679
  return;
608
680
  }
609
681
  const selectedItem = menu.items[selection];
610
682
  if ("action" in selectedItem) {
683
+ // Update breadcrumb to show current action
684
+ process.stdout.write("\x1b[1A\x1b[2K\x1b[G");
685
+ console.log(_yoctocolorsCjs.default.dim("🍞 " + [...path, selectedItem.title].join(" > ")));
611
686
  const result = await selectedItem.action(this);
612
687
  if (result instanceof Sprinkle) {
613
688
  this.settings = result.settings;
614
689
  this.saveSettings();
615
690
  }
616
- await this._showMenu(menu, main);
691
+ await this._showMenu(menu, main, path, true);
617
692
  } else {
618
- await this._showMenu(selectedItem, false);
619
- await this._showMenu(menu, main);
693
+ await this._showMenu(selectedItem, false, [...path, selectedItem.title], true);
694
+ await this._showMenu(menu, main, path, true);
620
695
  }
621
696
  return;
622
697
  }
@@ -771,7 +846,7 @@ class Sprinkle {
771
846
  name: "Cancel",
772
847
  value: "cancel"
773
848
  });
774
- const selection = await (0, _prompts.selectCancellable)({
849
+ const selection = await (0, _prompts.selectWithClear)({
775
850
  message: "Select an option:",
776
851
  choices
777
852
  });
@@ -969,46 +1044,18 @@ class Sprinkle {
969
1044
  }
970
1045
  }
971
1046
  }
1047
+
1048
+ /**
1049
+ * Edit an existing struct value using a menu-based interface.
1050
+ * This is now unified with FillInStruct - both use the same menu system.
1051
+ * @param type - The TypeBox schema
1052
+ * @param current - The current value to edit
1053
+ * @returns The edited value
1054
+ */
972
1055
  async EditStruct(type, current) {
973
- return this._editStruct(type, ["root"], current);
974
- }
975
- async _editStruct(type, path, current) {
976
- if ((0, _typeGuards.isObject)(type)) {
977
- const obj = {};
978
- const fields = type["properties"];
979
- const menuItems = [];
980
- const currentRecord = current;
981
- for (const [field, fieldType] of Object.entries(fields)) {
982
- if (current && field in currentRecord) {
983
- obj[field] = currentRecord[field];
984
- }
985
- const menuTitle = Sprinkle.ExtractMessage(fieldType, `Edit ${field} at ${path.join(".")}`);
986
- if ((0, _typeGuards.isOptional)(fieldType) && current && currentRecord[field] !== undefined) {
987
- menuItems.push({
988
- title: `Clear ${field}`,
989
- action: async sprinkle => {
990
- obj[field] = undefined;
991
- return sprinkle;
992
- }
993
- });
994
- }
995
- menuItems.push({
996
- title: menuTitle,
997
- action: async sprinkle => {
998
- const fieldValue = await sprinkle._editStruct(fieldType, path.concat([field]), current && field in currentRecord ? currentRecord[field] : undefined);
999
- obj[field] = fieldValue;
1000
- return sprinkle;
1001
- }
1002
- });
1003
- }
1004
- const editMenu = {
1005
- title: "Test",
1006
- items: menuItems
1007
- };
1008
- await this._showMenu(editMenu, false);
1009
- return obj;
1010
- }
1011
- return this._fillInStruct(type, path, {}, current);
1056
+ // Use FillInStruct with current values as defaults
1057
+ // The menu system will show existing values and allow editing
1058
+ return this.FillInStruct(type, current);
1012
1059
  }
1013
1060
  async FillInStruct(type, def) {
1014
1061
  return this._fillInStruct(type, ["root"], {}, def);
@@ -1026,8 +1073,9 @@ class Sprinkle {
1026
1073
  return this._fillInStruct(resolvedType, path, defs, def);
1027
1074
  }
1028
1075
  if ((0, _typeGuards.isOptional)(type)) {
1029
- const shouldSet = await (0, _prompts.selectCancellable)({
1030
- message: Sprinkle.ExtractMessage(type, `Set value for ${path.join(".")}?`),
1076
+ const pathDisplay = (0, _formatting.formatPath)(path) || "value";
1077
+ const shouldSet = await (0, _prompts.selectWithClear)({
1078
+ message: Sprinkle.ExtractMessage(type, `Set value for ${pathDisplay}?`),
1031
1079
  choices: [{
1032
1080
  name: "Yes",
1033
1081
  value: true
@@ -1051,6 +1099,7 @@ class Sprinkle {
1051
1099
  return this._fillInStruct(innerType, path, defs, def);
1052
1100
  }
1053
1101
  if ((0, _typeGuards.isUnion)(type)) {
1102
+ const pathDisplay = (0, _formatting.formatPath)(path) || "value";
1054
1103
  const choices = [];
1055
1104
  const resolved = this.resolveType(type, path, defs);
1056
1105
  for (const variant of resolved.anyOf) {
@@ -1059,21 +1108,48 @@ class Sprinkle {
1059
1108
  value: variant
1060
1109
  });
1061
1110
  }
1062
- const selectionResult = await (0, _prompts.selectCancellable)({
1063
- message: Sprinkle.ExtractMessage(resolved, `Enter a choice for ${path.join(".")}`),
1064
- choices: choices,
1065
- default: def ? `${def}` : undefined
1111
+ const selectionResult = await (0, _prompts.selectWithClear)({
1112
+ message: Sprinkle.ExtractMessage(resolved, `Enter a choice for ${pathDisplay}`),
1113
+ choices: choices
1066
1114
  });
1067
1115
  if (selectionResult === null) {
1068
1116
  throw new _types.UserCancelledError();
1069
1117
  }
1070
1118
  const selection = selectionResult;
1071
- return this._fillInStruct(selection, path, defs);
1119
+ // Determine if the provided default value matches the selected variant.
1120
+ // For discriminated unions (objects with literal fields like `type`), check
1121
+ // if the literal field values in the selected variant match those in `def`.
1122
+ // For non-discriminated unions, fall back to structural matching with Value.Check.
1123
+ let matchedDef = undefined;
1124
+ if (def !== undefined) {
1125
+ if ((0, _typeGuards.isObject)(selection)) {
1126
+ // Check if all literal fields in the selected variant match def
1127
+ const literalFields = Object.entries(selection.properties ?? {}).filter(([, fieldSchema]) => (0, _typeGuards.isLiteral)(fieldSchema));
1128
+ if (literalFields.length > 0) {
1129
+ const defRecord = def;
1130
+ const allLiteralsMatch = literalFields.every(([fieldName, fieldSchema]) => defRecord[fieldName] === fieldSchema.const);
1131
+ if (allLiteralsMatch) {
1132
+ matchedDef = def;
1133
+ }
1134
+ } else {
1135
+ // No literal discriminators - use structural check
1136
+ if (_value.Value.Check(selection, def)) {
1137
+ matchedDef = def;
1138
+ }
1139
+ }
1140
+ } else {
1141
+ // Non-object variant - use structural check
1142
+ if (_value.Value.Check(selection, def)) {
1143
+ matchedDef = def;
1144
+ }
1145
+ }
1146
+ }
1147
+ return this._fillInStruct(selection, path, defs, matchedDef);
1072
1148
  }
1073
1149
  if ((0, _typeGuards.isString)(type)) {
1074
1150
  // Special handling for hot wallet private key - offer generation option
1075
1151
  if (type.title === "Hot Wallet Private Key") {
1076
- const choice = await (0, _prompts.selectCancellable)({
1152
+ const choice = await (0, _prompts.selectWithClear)({
1077
1153
  message: "Hot wallet setup:",
1078
1154
  choices: [{
1079
1155
  name: "Enter existing private key",
@@ -1090,7 +1166,7 @@ class Sprinkle {
1090
1166
  return Sprinkle.generateWalletFromMnemonic();
1091
1167
  }
1092
1168
  // Fall through to password prompt for "existing" choice
1093
- const answer = await (0, _prompts.passwordCancellable)({
1169
+ const answer = await (0, _prompts.passwordWithClear)({
1094
1170
  message: "Enter your private key:"
1095
1171
  });
1096
1172
  if (answer === null) {
@@ -1098,15 +1174,16 @@ class Sprinkle {
1098
1174
  }
1099
1175
  return answer;
1100
1176
  }
1177
+ const pathDisplay = (0, _formatting.formatPath)(path) || "value";
1101
1178
  const defaultString = def ? def : this.defaults["string"];
1102
- const message = Sprinkle.ExtractMessage(type, `Enter a string for ${path.join(".")}`);
1179
+ const message = Sprinkle.ExtractMessage(type, `Enter a string for ${pathDisplay}`);
1103
1180
  let answer;
1104
1181
  if ((0, _typeGuards.isSensitive)(type)) {
1105
- answer = await (0, _prompts.passwordCancellable)({
1182
+ answer = await (0, _prompts.passwordWithClear)({
1106
1183
  message
1107
1184
  });
1108
1185
  } else {
1109
- answer = await (0, _prompts.inputCancellable)({
1186
+ answer = await (0, _prompts.inputWithClear)({
1110
1187
  message,
1111
1188
  default: defaultString
1112
1189
  });
@@ -1120,8 +1197,9 @@ class Sprinkle {
1120
1197
  return answer;
1121
1198
  }
1122
1199
  if ((0, _typeGuards.isBigInt)(type)) {
1123
- const answer = await (0, _prompts.inputCancellable)({
1124
- message: Sprinkle.ExtractMessage(type, `Enter a bigint for ${path.join(".")}`),
1200
+ const pathDisplay = (0, _formatting.formatPath)(path) || "value";
1201
+ const answer = await (0, _prompts.inputWithClear)({
1202
+ message: Sprinkle.ExtractMessage(type, `Enter a bigint for ${pathDisplay}`),
1125
1203
  default: def ? def.toString() : undefined,
1126
1204
  validate: s => {
1127
1205
  try {
@@ -1141,39 +1219,40 @@ class Sprinkle {
1141
1219
  return type.const;
1142
1220
  }
1143
1221
  if ((0, _typeGuards.isObject)(type)) {
1144
- const obj = {};
1145
- const fields = type["properties"];
1146
- for (const [field, fieldType] of Object.entries(fields)) {
1147
- const fieldValue = await this._fillInStruct(fieldType, path.concat([field]), defs, def ? def[field] : undefined);
1148
- obj[field] = fieldValue;
1222
+ // Use menu-based editing for objects
1223
+ const defaults = def;
1224
+ const sprinkle = this;
1225
+ const result = await (0, _index.promptObject)({
1226
+ type,
1227
+ path,
1228
+ defs,
1229
+ defaults,
1230
+ fillField: async (fieldType, fieldPath, fieldDefs, fieldDef) => {
1231
+ return sprinkle._fillInStruct(fieldType, fieldPath, fieldDefs, fieldDef);
1232
+ }
1233
+ });
1234
+ if (result.action === "cancel") {
1235
+ throw new _types.UserCancelledError();
1149
1236
  }
1150
- return obj;
1237
+ return result.value;
1151
1238
  }
1152
-
1153
- //TODO: support starting with default values for arrays and allow removal of items
1154
1239
  if ((0, _typeGuards.isArray)(type)) {
1155
- const arr = [];
1156
- const itemType = type.items;
1157
- let addMore = true;
1158
- while (addMore) {
1159
- const itemValue = await this._fillInStruct(itemType, path.concat([`[${arr.length}]`]), defs);
1160
- arr.push(itemValue);
1161
- const continueAnswer = await (0, _prompts.selectCancellable)({
1162
- message: `Add another item to ${path.join(".")}?`,
1163
- choices: [{
1164
- name: "Yes",
1165
- value: true
1166
- }, {
1167
- name: "No",
1168
- value: false
1169
- }]
1170
- });
1171
- if (continueAnswer === null) {
1172
- throw new _types.UserCancelledError();
1240
+ // Use menu-based editing for arrays
1241
+ const defaults = def;
1242
+ const sprinkle = this;
1243
+ const result = await (0, _index.promptArray)({
1244
+ type,
1245
+ path,
1246
+ defs,
1247
+ defaults,
1248
+ fillField: async (itemType, itemPath, itemDefs, itemDef) => {
1249
+ return sprinkle._fillInStruct(itemType, itemPath, itemDefs, itemDef);
1173
1250
  }
1174
- addMore = continueAnswer;
1251
+ });
1252
+ if (result.action === "back") {
1253
+ throw new _types.UserCancelledError();
1175
1254
  }
1176
- return arr;
1255
+ return result.value;
1177
1256
  }
1178
1257
  if ((0, _typeGuards.isTuple)(type)) {
1179
1258
  const items = type.items ?? [];
@@ -1185,7 +1264,8 @@ class Sprinkle {
1185
1264
  }
1186
1265
  return result;
1187
1266
  }
1188
- throw new Error(`Unable to fill in struct for type at path ${path.join(".")}`);
1267
+ const pathDisplay = (0, _formatting.formatPath)(path) || "root";
1268
+ throw new Error(`Unable to fill in struct for type at path ${pathDisplay}`);
1189
1269
  }
1190
1270
  resolveType(type, path, defs) {
1191
1271
  if ((0, _typeGuards.isRef)(type) || (0, _typeGuards.isThis)(type) || (0, _typeGuards.isImport)(type)) {