assign-gingerly 0.0.79 → 0.0.80

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/DX/paths.js CHANGED
@@ -27,6 +27,9 @@
27
27
  * The sp tag function uses this to auto-extract path strings from proxies.
28
28
  */
29
29
  const PATH_SYMBOL = Symbol('assign-gingerly-path');
30
+ function isPathProxy(value) {
31
+ return !!value && (typeof value === 'object' || typeof value === 'function') && PATH_SYMBOL in value;
32
+ }
30
33
  /**
31
34
  * Create a proxy for id-ref paths (#[varName]).
32
35
  * After the initial #[varName], further property access chains with ?. from the resolved element.
@@ -34,6 +37,7 @@ const PATH_SYMBOL = Symbol('assign-gingerly-path');
34
37
  */
35
38
  function createIdRefProxy(idRef, options) {
36
39
  function handler() { }
40
+ Object.defineProperty(handler, PATH_SYMBOL, { value: idRef });
37
41
  return new Proxy(handler, {
38
42
  get(_, prop) {
39
43
  if (prop === 'path' || prop === PATH_SYMBOL) {
@@ -53,7 +57,7 @@ function createIdRefProxy(idRef, options) {
53
57
  argStr = 'true';
54
58
  else if (arg === false)
55
59
  argStr = 'false';
56
- else if (arg && typeof arg === 'object' && PATH_SYMBOL in arg) {
60
+ else if (isPathProxy(arg)) {
57
61
  const fullPath = arg[PATH_SYMBOL];
58
62
  argStr = fullPath.startsWith('?.') ? fullPath.substring(2) : fullPath;
59
63
  }
@@ -77,6 +81,7 @@ function createPathProxy(prefix, options) {
77
81
  const aliasMap = options?.aka;
78
82
  // Use a function as the target to enable the apply trap
79
83
  function handler() { }
84
+ Object.defineProperty(handler, PATH_SYMBOL, { value: prefix.length > 0 ? `?.${prefix}` : '?.' });
80
85
  return new Proxy(handler, {
81
86
  get(_, prop) {
82
87
  if (prop === 'path' || prop === PATH_SYMBOL) {
@@ -114,7 +119,7 @@ function createPathProxy(prefix, options) {
114
119
  argStr = 'true';
115
120
  else if (arg === false)
116
121
  argStr = 'false';
117
- else if (arg && typeof arg === 'object' && PATH_SYMBOL in arg) {
122
+ else if (isPathProxy(arg)) {
118
123
  // Proxy arg — extract path without '?.' prefix
119
124
  const fullPath = arg[PATH_SYMBOL];
120
125
  argStr = fullPath.startsWith('?.') ? fullPath.substring(2) : fullPath;
@@ -167,12 +172,12 @@ export function paths(options) {
167
172
  * }
168
173
  */
169
174
  export function set(lhs) {
170
- const lhsStr = lhs && typeof lhs === 'object' && PATH_SYMBOL in lhs
175
+ const lhsStr = isPathProxy(lhs)
171
176
  ? lhs[PATH_SYMBOL]
172
177
  : String(lhs);
173
178
  return {
174
179
  to(rhs) {
175
- const rhsStr = rhs && typeof rhs === 'object' && PATH_SYMBOL in rhs
180
+ const rhsStr = isPathProxy(rhs)
176
181
  ? rhs[PATH_SYMBOL]
177
182
  : rhs;
178
183
  return { [lhsStr]: rhsStr };
@@ -198,7 +203,7 @@ export function set(lhs) {
198
203
  * // { assign: { incrementButton: '?.clone?.q?..increment', ... } }
199
204
  */
200
205
  export function smoothOver(value) {
201
- if (value && typeof value === 'object' && PATH_SYMBOL in value) {
206
+ if (isPathProxy(value)) {
202
207
  return value[PATH_SYMBOL];
203
208
  }
204
209
  if (Array.isArray(value)) {
@@ -294,13 +299,13 @@ export function sp(strings, ...values) {
294
299
  result.push(strings[i]);
295
300
  if (i < values.length) {
296
301
  const v = values[i];
297
- if (v && typeof v === 'object' && PATH_SYMBOL in v) {
302
+ if (isPathProxy(v)) {
298
303
  // Auto-extract path from proxy object
299
304
  result.push(v[PATH_SYMBOL]);
300
305
  }
301
306
  else if (Array.isArray(v)) {
302
307
  // Nested array — recursively extract paths from proxy elements
303
- result.push(v.map(el => el && typeof el === 'object' && PATH_SYMBOL in el ? el[PATH_SYMBOL] : el));
308
+ result.push(v.map(el => isPathProxy(el) ? el[PATH_SYMBOL] : el));
304
309
  }
305
310
  else {
306
311
  result.push(v);
@@ -349,7 +354,7 @@ export function md(strings, ...values) {
349
354
  result.push(strings[i]);
350
355
  if (i < values.length) {
351
356
  const v = values[i];
352
- if (v && typeof v === 'object' && PATH_SYMBOL in v) {
357
+ if (isPathProxy(v)) {
353
358
  // Proxy object → {prop, val}
354
359
  const pathStr = v[PATH_SYMBOL];
355
360
  result.push({ prop: extractPropName(pathStr), val: pathStr });
@@ -357,7 +362,7 @@ export function md(strings, ...values) {
357
362
  else if (Array.isArray(v)) {
358
363
  // Nested array — recursively convert proxy elements to {prop, val}
359
364
  result.push(v.map(el => {
360
- if (el && typeof el === 'object' && PATH_SYMBOL in el) {
365
+ if (isPathProxy(el)) {
361
366
  const pathStr = el[PATH_SYMBOL];
362
367
  return { prop: extractPropName(pathStr), val: pathStr };
363
368
  }
@@ -367,7 +372,7 @@ export function md(strings, ...values) {
367
372
  else if (v && typeof v === 'object' && 'prop' in v) {
368
373
  // Developer override object — extract val from proxy if present
369
374
  const processed = { ...v };
370
- if (processed.val && typeof processed.val === 'object' && PATH_SYMBOL in processed.val) {
375
+ if (isPathProxy(processed.val)) {
371
376
  processed.val = processed.val[PATH_SYMBOL];
372
377
  }
373
378
  result.push(processed);
package/DX/paths.ts CHANGED
@@ -27,7 +27,11 @@
27
27
  * Symbol used internally to detect path proxy objects.
28
28
  * The sp tag function uses this to auto-extract path strings from proxies.
29
29
  */
30
- const PATH_SYMBOL = Symbol('assign-gingerly-path');
30
+ const PATH_SYMBOL = Symbol('assign-gingerly-path');
31
+
32
+ function isPathProxy(value: unknown): value is { [PATH_SYMBOL]: string } {
33
+ return !!value && (typeof value === 'object' || typeof value === 'function') && PATH_SYMBOL in value;
34
+ }
31
35
 
32
36
  /**
33
37
  * Type that maps an object type to a proxy where every property access
@@ -58,13 +62,14 @@ export interface PathsOptions {
58
62
  * After the initial #[varName], further property access chains with ?. from the resolved element.
59
63
  * .path returns the #[varName] prefix (optionally with further ?. path).
60
64
  */
61
- function createIdRefProxy(idRef: string, options?: PathsOptions): any {
62
- function handler() {}
63
- return new Proxy(handler, {
64
- get(_, prop: string | symbol) {
65
- if (prop === 'path' || prop === PATH_SYMBOL) {
66
- return idRef;
67
- }
65
+ function createIdRefProxy(idRef: string, options?: PathsOptions): any {
66
+ function handler() {}
67
+ Object.defineProperty(handler, PATH_SYMBOL, { value: idRef });
68
+ return new Proxy(handler, {
69
+ get(_, prop: string | symbol) {
70
+ if (prop === 'path' || prop === PATH_SYMBOL) {
71
+ return idRef;
72
+ }
68
73
  if (typeof prop === 'symbol') return undefined;
69
74
 
70
75
  // Chain further path segments after the id ref
@@ -73,15 +78,15 @@ function createIdRefProxy(idRef: string, options?: PathsOptions): any {
73
78
  },
74
79
  apply(_, __, args) {
75
80
  if (args.length > 0) {
76
- const arg = args[0];
77
- let argStr: string;
78
- if (arg === true) argStr = 'true';
79
- else if (arg === false) argStr = 'false';
80
- else if (arg && typeof arg === 'object' && PATH_SYMBOL in arg) {
81
- const fullPath = arg[PATH_SYMBOL] as string;
82
- argStr = fullPath.startsWith('?.') ? fullPath.substring(2) : fullPath;
83
- }
84
- else argStr = String(arg);
81
+ const arg = args[0];
82
+ let argStr: string;
83
+ if (arg === true) argStr = 'true';
84
+ else if (arg === false) argStr = 'false';
85
+ else if (isPathProxy(arg)) {
86
+ const fullPath = arg[PATH_SYMBOL] as string;
87
+ argStr = fullPath.startsWith('?.') ? fullPath.substring(2) : fullPath;
88
+ }
89
+ else argStr = String(arg);
85
90
 
86
91
  const chained = `${idRef}?.${argStr}`;
87
92
  return createIdRefProxy(chained, options);
@@ -98,16 +103,17 @@ function createIdRefProxy(idRef: string, options?: PathsOptions): any {
98
103
  * When `aka` is provided, property names that match an alias *value* are output
99
104
  * using the alias *key* instead (reverse alias).
100
105
  */
101
- function createPathProxy(prefix: string, options?: PathsOptions): any {
102
- const aliasMap = options?.aka;
103
-
104
- // Use a function as the target to enable the apply trap
105
- function handler() {}
106
-
107
- return new Proxy(handler, {
108
- get(_, prop: string | symbol) {
109
- if (prop === 'path' || prop === PATH_SYMBOL) {
110
- return prefix.length > 0 ? `?.${prefix}` : '?.';
106
+ function createPathProxy(prefix: string, options?: PathsOptions): any {
107
+ const aliasMap = options?.aka;
108
+
109
+ // Use a function as the target to enable the apply trap
110
+ function handler() {}
111
+ Object.defineProperty(handler, PATH_SYMBOL, { value: prefix.length > 0 ? `?.${prefix}` : '?.' });
112
+
113
+ return new Proxy(handler, {
114
+ get(_, prop: string | symbol) {
115
+ if (prop === 'path' || prop === PATH_SYMBOL) {
116
+ return prefix.length > 0 ? `?.${prefix}` : '?.';
111
117
  }
112
118
  // Ignore symbol access (Symbol.iterator, Symbol.toPrimitive, etc.)
113
119
  if (typeof prop === 'symbol') return undefined;
@@ -135,16 +141,16 @@ function createPathProxy(prefix: string, options?: PathsOptions): any {
135
141
  apply(_, __, args) {
136
142
  // Method call syntax: $.querySelector('.username') → extends path with the argument
137
143
  if (args.length > 0) {
138
- const arg = args[0];
139
- let argStr: string;
140
- if (arg === true) argStr = 'true';
141
- else if (arg === false) argStr = 'false';
142
- else if (arg && typeof arg === 'object' && PATH_SYMBOL in arg) {
143
- // Proxy arg — extract path without '?.' prefix
144
- const fullPath = arg[PATH_SYMBOL] as string;
145
- argStr = fullPath.startsWith('?.') ? fullPath.substring(2) : fullPath;
146
- }
147
- else argStr = String(arg);
144
+ const arg = args[0];
145
+ let argStr: string;
146
+ if (arg === true) argStr = 'true';
147
+ else if (arg === false) argStr = 'false';
148
+ else if (isPathProxy(arg)) {
149
+ // Proxy arg — extract path without '?.' prefix
150
+ const fullPath = arg[PATH_SYMBOL] as string;
151
+ argStr = fullPath.startsWith('?.') ? fullPath.substring(2) : fullPath;
152
+ }
153
+ else argStr = String(arg);
148
154
 
149
155
  const newPath = prefix ? `${prefix}?.${argStr}` : argStr;
150
156
  return createPathProxy(newPath, options);
@@ -193,18 +199,18 @@ export function paths<T>(options?: PathsOptions): PathProxy<T> {
193
199
  * count: 1
194
200
  * }
195
201
  */
196
- export function set(lhs: any): { to: (rhs: any) => Record<string, any> } {
197
- const lhsStr = lhs && typeof lhs === 'object' && PATH_SYMBOL in lhs
198
- ? lhs[PATH_SYMBOL]
199
- : String(lhs);
200
- return {
201
- to(rhs: any): Record<string, any> {
202
- const rhsStr = rhs && typeof rhs === 'object' && PATH_SYMBOL in rhs
203
- ? rhs[PATH_SYMBOL]
204
- : rhs;
205
- return { [lhsStr]: rhsStr };
206
- }
207
- };
202
+ export function set(lhs: any): { to: (rhs: any) => Record<string, any> } {
203
+ const lhsStr = isPathProxy(lhs)
204
+ ? lhs[PATH_SYMBOL]
205
+ : String(lhs);
206
+ return {
207
+ to(rhs: any): Record<string, any> {
208
+ const rhsStr = isPathProxy(rhs)
209
+ ? rhs[PATH_SYMBOL]
210
+ : rhs;
211
+ return { [lhsStr]: rhsStr };
212
+ }
213
+ };
208
214
  }
209
215
 
210
216
  /**
@@ -225,19 +231,19 @@ export function set(lhs: any): { to: (rhs: any) => Record<string, any> } {
225
231
  * });
226
232
  * // { assign: { incrementButton: '?.clone?.q?..increment', ... } }
227
233
  */
228
- export function smoothOver(value: any): any {
229
- if (value && typeof value === 'object' && PATH_SYMBOL in value) {
230
- return value[PATH_SYMBOL];
231
- }
234
+ export function smoothOver(value: any): any {
235
+ if (isPathProxy(value)) {
236
+ return value[PATH_SYMBOL];
237
+ }
232
238
  if (Array.isArray(value)) {
233
239
  return value.map(smoothOver);
234
240
  }
235
241
  if (value && typeof value === 'object') {
236
242
  const proto = Object.getPrototypeOf(value);
237
243
  if (proto === Object.prototype || proto === null) {
238
- const result: Record<string, any> = {};
239
- for (const [k, v] of Object.entries(value)) {
240
- result[k] = smoothOver(v);
244
+ const result: Record<string, any> = {};
245
+ for (const [k, v] of Object.entries(value)) {
246
+ result[k] = smoothOver(v);
241
247
  }
242
248
  return result;
243
249
  }
@@ -322,23 +328,23 @@ export function forEachKeyIn<T>(
322
328
  * sp`${$.lastName}${[', ', $.middleName]}, ${$.firstName}`
323
329
  * // ['?.lastName', [', ', '?.middleName'], ', ', '?.firstName']
324
330
  */
325
- export function sp(strings: TemplateStringsArray, ...values: any[]): any[] {
331
+ export function sp(strings: TemplateStringsArray, ...values: any[]): any[] {
326
332
  const result: any[] = [];
327
333
  for (let i = 0; i < strings.length; i++) {
328
334
  if (strings[i]) result.push(strings[i]);
329
335
  if (i < values.length) {
330
- const v = values[i];
331
- if (v && typeof v === 'object' && PATH_SYMBOL in v) {
332
- // Auto-extract path from proxy object
333
- result.push(v[PATH_SYMBOL]);
334
- } else if (Array.isArray(v)) {
335
- // Nested array — recursively extract paths from proxy elements
336
- result.push(v.map(el =>
337
- el && typeof el === 'object' && PATH_SYMBOL in el ? el[PATH_SYMBOL] : el
338
- ));
339
- } else {
340
- result.push(v);
341
- }
336
+ const v = values[i];
337
+ if (isPathProxy(v)) {
338
+ // Auto-extract path from proxy object
339
+ result.push(v[PATH_SYMBOL]);
340
+ } else if (Array.isArray(v)) {
341
+ // Nested array — recursively extract paths from proxy elements
342
+ result.push(v.map(el =>
343
+ isPathProxy(el) ? el[PATH_SYMBOL] : el
344
+ ));
345
+ } else {
346
+ result.push(v);
347
+ }
342
348
  }
343
349
  }
344
350
  return result;
@@ -383,27 +389,27 @@ export function md(strings: TemplateStringsArray, ...values: any[]): any[] {
383
389
  for (let i = 0; i < strings.length; i++) {
384
390
  if (strings[i]) result.push(strings[i]);
385
391
  if (i < values.length) {
386
- const v = values[i];
387
- if (v && typeof v === 'object' && PATH_SYMBOL in v) {
388
- // Proxy object → {prop, val}
389
- const pathStr = v[PATH_SYMBOL] as string;
390
- result.push({ prop: extractPropName(pathStr), val: pathStr });
391
- } else if (Array.isArray(v)) {
392
- // Nested array — recursively convert proxy elements to {prop, val}
393
- result.push(v.map(el => {
394
- if (el && typeof el === 'object' && PATH_SYMBOL in el) {
395
- const pathStr = el[PATH_SYMBOL] as string;
396
- return { prop: extractPropName(pathStr), val: pathStr };
397
- }
398
- return el;
399
- }));
400
- } else if (v && typeof v === 'object' && 'prop' in v) {
401
- // Developer override object — extract val from proxy if present
402
- const processed = { ...v };
403
- if (processed.val && typeof processed.val === 'object' && PATH_SYMBOL in processed.val) {
404
- processed.val = processed.val[PATH_SYMBOL];
405
- }
406
- result.push(processed);
392
+ const v = values[i];
393
+ if (isPathProxy(v)) {
394
+ // Proxy object → {prop, val}
395
+ const pathStr = v[PATH_SYMBOL] as string;
396
+ result.push({ prop: extractPropName(pathStr), val: pathStr });
397
+ } else if (Array.isArray(v)) {
398
+ // Nested array — recursively convert proxy elements to {prop, val}
399
+ result.push(v.map(el => {
400
+ if (isPathProxy(el)) {
401
+ const pathStr = el[PATH_SYMBOL] as string;
402
+ return { prop: extractPropName(pathStr), val: pathStr };
403
+ }
404
+ return el;
405
+ }));
406
+ } else if (v && typeof v === 'object' && 'prop' in v) {
407
+ // Developer override object — extract val from proxy if present
408
+ const processed = { ...v };
409
+ if (isPathProxy(processed.val)) {
410
+ processed.val = processed.val[PATH_SYMBOL];
411
+ }
412
+ result.push(processed);
407
413
  } else {
408
414
  result.push(v);
409
415
  }
package/assignGingerly.js CHANGED
@@ -420,6 +420,7 @@ export function isAllowedMethod(methodName, withMethods, permissionProcessor) {
420
420
  export function evaluatePathWithMethods(target, pathParts, value, withMethods, permissionProcessor) {
421
421
  let current = target;
422
422
  let i = 0;
423
+ let lastSegmentConsumed = false;
423
424
  // Process all segments except the last one
424
425
  while (i < pathParts.length - 1) {
425
426
  const part = pathParts[i];
@@ -442,6 +443,9 @@ export function evaluatePathWithMethods(target, pathParts, value, withMethods, p
442
443
  // Only current is method - call with next part as string arg
443
444
  current = method.call(current, nextPart, ...appendArgs);
444
445
  i++; // Skip next part since we consumed it as argument
446
+ if (i === pathParts.length - 1) {
447
+ lastSegmentConsumed = true;
448
+ }
445
449
  }
446
450
  }
447
451
  else {
@@ -470,7 +474,8 @@ export function evaluatePathWithMethods(target, pathParts, value, withMethods, p
470
474
  target: current,
471
475
  lastKey,
472
476
  isMethod: isAllowedMethod(lastKey, withMethods, permissionProcessor),
473
- isZeroArg
477
+ isZeroArg,
478
+ lastSegmentConsumed
474
479
  };
475
480
  }
476
481
  /**
@@ -623,6 +628,95 @@ function applyToEach(iterable, remainingPath, value, withMethods, aliasMap, opti
623
628
  }
624
629
  }
625
630
  }
631
+ /**
632
+ * Resolve the RHS of a toggle (=!) command to the value that should be negated.
633
+ * Supports:
634
+ * - '?.path' nested path strings resolved against target (returns the resolved value, or true if missing)
635
+ * - plain key strings looked up on target (returns the value, or true if missing)
636
+ * - resolved literal values (e.g., booleans from assignFrom) returned as-is
637
+ */
638
+ function resolveValueToNegate(rhsPath, target) {
639
+ if (typeof rhsPath === 'string' && isNestedPath(rhsPath)) {
640
+ const rhsPathParts = parsePath(rhsPath);
641
+ let current = target;
642
+ let exists = true;
643
+ for (const part of rhsPathParts) {
644
+ if (current && typeof current === 'object' && part in current) {
645
+ current = current[part];
646
+ }
647
+ else {
648
+ exists = false;
649
+ break;
650
+ }
651
+ }
652
+ return exists ? current : true;
653
+ }
654
+ if (typeof rhsPath === 'string') {
655
+ return (rhsPath in target) ? target[rhsPath] : true;
656
+ }
657
+ // Non-string resolved value (e.g., boolean, number, null from assignFrom)
658
+ return rhsPath;
659
+ }
660
+ /**
661
+ * Navigate a path that leads to an iterable, returning the iterable value or undefined.
662
+ * Handles withMethods and the evaluatePathWithMethods semantics.
663
+ */
664
+ function getIterableAtPath(target, pathParts, value, withMethods, permissionProcessor) {
665
+ let current = target;
666
+ if (pathParts.length > 0) {
667
+ if (withMethods && withMethods.size > 0) {
668
+ const result = evaluatePathWithMethods(target, pathParts, value, withMethods, permissionProcessor);
669
+ // evaluatePathWithMethods returns the container object + last key by default.
670
+ // If the last segment was consumed as a method argument, or the last segment
671
+ // is a zero-arg method marked with |, result.target is already the value.
672
+ if (result.lastSegmentConsumed) {
673
+ current = result.target;
674
+ }
675
+ else if (result.isMethod) {
676
+ const method = result.target[result.lastKey];
677
+ if (typeof method === 'function') {
678
+ const appendArgs = permissionProcessor?.getMethodAppendArgs(result.lastKey) ?? [];
679
+ current = method.call(result.target, ...appendArgs);
680
+ }
681
+ else {
682
+ current = method;
683
+ }
684
+ }
685
+ else {
686
+ current = result.target[result.lastKey];
687
+ }
688
+ }
689
+ else {
690
+ for (const part of pathParts) {
691
+ current = current[part];
692
+ }
693
+ }
694
+ }
695
+ return isIterable(current) ? current : undefined;
696
+ }
697
+ /**
698
+ * Apply an operator command (+=, =!, -=, Y=) to each item in an iterable.
699
+ * Detects @each in the path, navigates to the iterable, then builds a synthetic
700
+ * command key for the remaining path and delegates to assignGingerly per item.
701
+ * Nested @each is handled recursively through assignGingerly.
702
+ */
703
+ function applyCommandToEach(target, pathParts, commandSuffix, value, withMethods, aliasMap, options, permissionProcessor) {
704
+ const forEachIndex = pathParts.findIndex(part => isForEachSymbol(part, aliasMap));
705
+ if (forEachIndex === -1)
706
+ return;
707
+ const pathToForEach = pathParts.slice(0, forEachIndex);
708
+ const pathAfterForEach = pathParts.slice(forEachIndex + 1);
709
+ const iterable = getIterableAtPath(target, pathToForEach, value, withMethods, permissionProcessor);
710
+ if (!iterable)
711
+ return;
712
+ const items = Array.isArray(iterable) ? iterable : Array.from(iterable);
713
+ const syntheticKey = pathAfterForEach.length > 0
714
+ ? `?.${pathAfterForEach.join('?.')}${commandSuffix}`
715
+ : commandSuffix;
716
+ for (const item of items) {
717
+ assignGingerly(item, { [syntheticKey]: value }, options, permissionProcessor);
718
+ }
719
+ }
626
720
  /**
627
721
  * Apply alias substitutions to a key string.
628
722
  * Replaces complete tokens between `?.` delimiters with their aliased values.
@@ -727,6 +821,11 @@ export function assignGingerly(target, source, options, permissionProcessor) {
727
821
  if (path) {
728
822
  if (isNestedPath(path)) {
729
823
  const pathParts = parsePath(path);
824
+ // Check for @each in path
825
+ if (pathParts.some(part => isForEachSymbol(part, aliasMap))) {
826
+ applyCommandToEach(target, pathParts, ' +=', value, withMethodsSet, aliasMap, options, permissionProcessor);
827
+ continue;
828
+ }
730
829
  // Check for withMethods path evaluation
731
830
  let lhsValue;
732
831
  let lhsParent;
@@ -795,54 +894,47 @@ export function assignGingerly(target, source, options, permissionProcessor) {
795
894
  const lhsPath = parseToggleCommand(key);
796
895
  if (lhsPath) {
797
896
  const rhsPath = value;
798
- // Resolve LHS
799
- let lhsParent;
800
- let lhsLastKey;
801
897
  if (isNestedPath(lhsPath)) {
802
898
  const lhsPathParts = parsePath(lhsPath);
803
- lhsLastKey = lhsPathParts[lhsPathParts.length - 1];
804
- lhsParent = ensureNestedPath(target, lhsPathParts);
805
- }
806
- else {
807
- lhsLastKey = lhsPath;
808
- lhsParent = target;
809
- }
810
- // Determine what to negate
811
- let valueToNegate;
812
- if (rhsPath === '.') {
813
- // Self-reference: negate the LHS value itself (if it exists)
814
- if (lhsLastKey in lhsParent) {
815
- valueToNegate = lhsParent[lhsLastKey];
899
+ // Check for @each in the LHS path
900
+ if (lhsPathParts.some(part => isForEachSymbol(part, aliasMap))) {
901
+ // Resolve non-self-referencing RHS paths against the original target
902
+ // before iterating, so each item negates the same root value.
903
+ const resolvedValue = (rhsPath === '.' || typeof rhsPath !== 'string')
904
+ ? rhsPath
905
+ : resolveValueToNegate(rhsPath, target);
906
+ applyCommandToEach(target, lhsPathParts, ' =!', resolvedValue, withMethodsSet, aliasMap, options, permissionProcessor);
907
+ continue;
908
+ }
909
+ // No @each in path - standard toggle
910
+ const lhsLastKey = lhsPathParts[lhsPathParts.length - 1];
911
+ const lhsParent = ensureNestedPath(target, lhsPathParts);
912
+ // Determine what to negate
913
+ let valueToNegate;
914
+ if (rhsPath === '.') {
915
+ valueToNegate = (lhsLastKey in lhsParent) ? lhsParent[lhsLastKey] : undefined;
816
916
  }
817
917
  else {
818
- valueToNegate = undefined;
918
+ valueToNegate = resolveValueToNegate(rhsPath, target);
919
+ }
920
+ if (!permissionProcessor?.checkRestrictedProp(lhsLastKey)) {
921
+ lhsParent[lhsLastKey] = !valueToNegate;
819
922
  }
820
923
  }
821
924
  else {
822
- // RHS path: navigate to get the value (don't create paths)
823
- if (isNestedPath(rhsPath)) {
824
- const rhsPathParts = parsePath(rhsPath);
825
- let current = target;
826
- let exists = true;
827
- for (const part of rhsPathParts) {
828
- if (current && typeof current === 'object' && part in current) {
829
- current = current[part];
830
- }
831
- else {
832
- exists = false;
833
- break;
834
- }
835
- }
836
- valueToNegate = exists ? current : true;
925
+ // Plain key LHS
926
+ const lhsLastKey = lhsPath;
927
+ const lhsParent = target;
928
+ let valueToNegate;
929
+ if (rhsPath === '.') {
930
+ valueToNegate = (lhsLastKey in lhsParent) ? lhsParent[lhsLastKey] : undefined;
837
931
  }
838
932
  else {
839
- // Plain key RHS
840
- valueToNegate = (rhsPath in target) ? target[rhsPath] : true;
933
+ valueToNegate = resolveValueToNegate(rhsPath, target);
934
+ }
935
+ if (!permissionProcessor?.checkRestrictedProp(lhsLastKey)) {
936
+ lhsParent[lhsLastKey] = !valueToNegate;
841
937
  }
842
- }
843
- // Apply negation to LHS — check restriction first
844
- if (!permissionProcessor?.checkRestrictedProp(lhsLastKey)) {
845
- lhsParent[lhsLastKey] = !valueToNegate;
846
938
  }
847
939
  }
848
940
  continue;
@@ -856,6 +948,11 @@ export function assignGingerly(target, source, options, permissionProcessor) {
856
948
  let canDelete = true;
857
949
  if (isNestedPath(path)) {
858
950
  const pathParts = parsePath(path);
951
+ // Check for @each in path
952
+ if (pathParts.some(part => isForEachSymbol(part, aliasMap))) {
953
+ applyCommandToEach(target, pathParts, ' -=', value, withMethodsSet, aliasMap, options, permissionProcessor);
954
+ continue;
955
+ }
859
956
  if (pathParts.length === 0) {
860
957
  parent = target;
861
958
  }
@@ -901,6 +998,11 @@ export function assignGingerly(target, source, options, permissionProcessor) {
901
998
  if (permissionProcessor?.checkRestrictedProp(lastKey)) {
902
999
  continue;
903
1000
  }
1001
+ // Check for @each in path
1002
+ if (isNestedPath(path) && pathParts.some(part => isForEachSymbol(part, aliasMap))) {
1003
+ applyCommandToEach(target, pathParts, ' Y=', value, withMethodsSet, aliasMap, options, permissionProcessor);
1004
+ continue;
1005
+ }
904
1006
  // Navigate to the target sub-object
905
1007
  let mergeTarget;
906
1008
  if (isNestedPath(path)) {
@@ -956,22 +1058,9 @@ export function assignGingerly(target, source, options, permissionProcessor) {
956
1058
  const pathToForEach = pathParts.slice(0, forEachIndex);
957
1059
  const pathAfterForEach = pathParts.slice(forEachIndex + 1);
958
1060
  // Navigate to the iterable
959
- let current = target;
960
- if (pathToForEach.length > 0) {
961
- if (withMethodsSet) {
962
- const result = evaluatePathWithMethods(target, pathToForEach, value, withMethodsSet, permissionProcessor);
963
- // The result.target is the current position after evaluating the path
964
- // This is already the iterable we want
965
- current = result.target;
966
- }
967
- else {
968
- for (const part of pathToForEach) {
969
- current = current[part];
970
- }
971
- }
972
- }
1061
+ const current = getIterableAtPath(target, pathToForEach, value, withMethodsSet, permissionProcessor);
973
1062
  // Apply to each item in the iterable
974
- if (isIterable(current)) {
1063
+ if (current) {
975
1064
  applyToEach(current, pathAfterForEach, value, withMethodsSet || new Set(), aliasMap, options, permissionProcessor);
976
1065
  }
977
1066
  // If not iterable, let JavaScript throw error naturally when trying to iterate
package/assignGingerly.ts CHANGED
@@ -506,9 +506,10 @@ export function evaluatePathWithMethods(
506
506
  value: any,
507
507
  withMethods: Set<string>,
508
508
  permissionProcessor?: PermissionProcessor
509
- ): { target: any; lastKey: string; isMethod: boolean; isZeroArg: boolean } {
509
+ ): { target: any; lastKey: string; isMethod: boolean; isZeroArg: boolean; lastSegmentConsumed: boolean } {
510
510
  let current = target;
511
511
  let i = 0;
512
+ let lastSegmentConsumed = false;
512
513
 
513
514
  // Process all segments except the last one
514
515
  while (i < pathParts.length - 1) {
@@ -533,6 +534,9 @@ export function evaluatePathWithMethods(
533
534
  // Only current is method - call with next part as string arg
534
535
  current = method.call(current, nextPart, ...appendArgs);
535
536
  i++; // Skip next part since we consumed it as argument
537
+ if (i === pathParts.length - 1) {
538
+ lastSegmentConsumed = true;
539
+ }
536
540
  }
537
541
  } else {
538
542
  // Not a function - just access property (create if needed)
@@ -561,7 +565,8 @@ export function evaluatePathWithMethods(
561
565
  target: current,
562
566
  lastKey,
563
567
  isMethod: isAllowedMethod(lastKey, withMethods, permissionProcessor),
564
- isZeroArg
568
+ isZeroArg,
569
+ lastSegmentConsumed
565
570
  };
566
571
  }
567
572
 
@@ -724,6 +729,110 @@ function applyToEach(
724
729
  }
725
730
  }
726
731
 
732
+ /**
733
+ * Resolve the RHS of a toggle (=!) command to the value that should be negated.
734
+ * Supports:
735
+ * - '?.path' nested path strings resolved against target (returns the resolved value, or true if missing)
736
+ * - plain key strings looked up on target (returns the value, or true if missing)
737
+ * - resolved literal values (e.g., booleans from assignFrom) returned as-is
738
+ */
739
+ function resolveValueToNegate(rhsPath: any, target: any): any {
740
+ if (typeof rhsPath === 'string' && isNestedPath(rhsPath)) {
741
+ const rhsPathParts = parsePath(rhsPath);
742
+ let current = target;
743
+ let exists = true;
744
+ for (const part of rhsPathParts) {
745
+ if (current && typeof current === 'object' && part in current) {
746
+ current = current[part];
747
+ } else {
748
+ exists = false;
749
+ break;
750
+ }
751
+ }
752
+ return exists ? current : true;
753
+ }
754
+ if (typeof rhsPath === 'string') {
755
+ return (rhsPath in target) ? target[rhsPath] : true;
756
+ }
757
+ // Non-string resolved value (e.g., boolean, number, null from assignFrom)
758
+ return rhsPath;
759
+ }
760
+
761
+ /**
762
+ * Navigate a path that leads to an iterable, returning the iterable value or undefined.
763
+ * Handles withMethods and the evaluatePathWithMethods semantics.
764
+ */
765
+ function getIterableAtPath(
766
+ target: any,
767
+ pathParts: string[],
768
+ value: any,
769
+ withMethods: Set<string> | undefined,
770
+ permissionProcessor?: PermissionProcessor
771
+ ): any {
772
+ let current = target;
773
+ if (pathParts.length > 0) {
774
+ if (withMethods && withMethods.size > 0) {
775
+ const result = evaluatePathWithMethods(target, pathParts, value, withMethods, permissionProcessor);
776
+ // evaluatePathWithMethods returns the container object + last key by default.
777
+ // If the last segment was consumed as a method argument, or the last segment
778
+ // is a zero-arg method marked with |, result.target is already the value.
779
+ if (result.lastSegmentConsumed) {
780
+ current = result.target;
781
+ } else if (result.isMethod) {
782
+ const method = result.target[result.lastKey];
783
+ if (typeof method === 'function') {
784
+ const appendArgs = permissionProcessor?.getMethodAppendArgs(result.lastKey) ?? [];
785
+ current = method.call(result.target, ...appendArgs);
786
+ } else {
787
+ current = method;
788
+ }
789
+ } else {
790
+ current = result.target[result.lastKey];
791
+ }
792
+ } else {
793
+ for (const part of pathParts) {
794
+ current = current[part];
795
+ }
796
+ }
797
+ }
798
+ return isIterable(current) ? current : undefined;
799
+ }
800
+
801
+ /**
802
+ * Apply an operator command (+=, =!, -=, Y=) to each item in an iterable.
803
+ * Detects @each in the path, navigates to the iterable, then builds a synthetic
804
+ * command key for the remaining path and delegates to assignGingerly per item.
805
+ * Nested @each is handled recursively through assignGingerly.
806
+ */
807
+ function applyCommandToEach(
808
+ target: any,
809
+ pathParts: string[],
810
+ commandSuffix: string,
811
+ value: any,
812
+ withMethods: Set<string> | undefined,
813
+ aliasMap: Map<string, string>,
814
+ options?: IAssignGingerlyOptions,
815
+ permissionProcessor?: PermissionProcessor
816
+ ): void {
817
+ const forEachIndex = pathParts.findIndex(part => isForEachSymbol(part, aliasMap));
818
+ if (forEachIndex === -1) return;
819
+
820
+ const pathToForEach = pathParts.slice(0, forEachIndex);
821
+ const pathAfterForEach = pathParts.slice(forEachIndex + 1);
822
+
823
+ const iterable = getIterableAtPath(target, pathToForEach, value, withMethods, permissionProcessor);
824
+ if (!iterable) return;
825
+
826
+ const items = Array.isArray(iterable) ? iterable : Array.from(iterable);
827
+ const syntheticKey = pathAfterForEach.length > 0
828
+ ? `?.${pathAfterForEach.join('?.')}${commandSuffix}`
829
+ : commandSuffix;
830
+
831
+ for (const item of items) {
832
+ assignGingerly(item, { [syntheticKey]: value }, options, permissionProcessor);
833
+ }
834
+ }
835
+
727
836
  /**
728
837
  * Apply alias substitutions to a key string.
729
838
  * Replaces complete tokens between `?.` delimiters with their aliased values.
@@ -845,6 +954,12 @@ export function assignGingerly(
845
954
  if (isNestedPath(path)) {
846
955
  const pathParts = parsePath(path);
847
956
 
957
+ // Check for @each in path
958
+ if (pathParts.some(part => isForEachSymbol(part, aliasMap))) {
959
+ applyCommandToEach(target, pathParts, ' +=', value, withMethodsSet, aliasMap, options, permissionProcessor);
960
+ continue;
961
+ }
962
+
848
963
  // Check for withMethods path evaluation
849
964
  let lhsValue: any;
850
965
  let lhsParent: any;
@@ -915,52 +1030,51 @@ export function assignGingerly(
915
1030
  const lhsPath = parseToggleCommand(key);
916
1031
  if (lhsPath) {
917
1032
  const rhsPath = value;
918
-
919
- // Resolve LHS
920
- let lhsParent: any;
921
- let lhsLastKey: string;
1033
+
922
1034
  if (isNestedPath(lhsPath)) {
923
1035
  const lhsPathParts = parsePath(lhsPath);
924
- lhsLastKey = lhsPathParts[lhsPathParts.length - 1];
925
- lhsParent = ensureNestedPath(target, lhsPathParts);
926
- } else {
927
- lhsLastKey = lhsPath;
928
- lhsParent = target;
929
- }
930
1036
 
931
- // Determine what to negate
932
- let valueToNegate;
933
- if (rhsPath === '.') {
934
- // Self-reference: negate the LHS value itself (if it exists)
935
- if (lhsLastKey in lhsParent) {
936
- valueToNegate = lhsParent[lhsLastKey];
1037
+ // Check for @each in the LHS path
1038
+ if (lhsPathParts.some(part => isForEachSymbol(part, aliasMap))) {
1039
+ // Resolve non-self-referencing RHS paths against the original target
1040
+ // before iterating, so each item negates the same root value.
1041
+ const resolvedValue = (rhsPath === '.' || typeof rhsPath !== 'string')
1042
+ ? rhsPath
1043
+ : resolveValueToNegate(rhsPath, target);
1044
+ applyCommandToEach(target, lhsPathParts, ' =!', resolvedValue, withMethodsSet, aliasMap, options, permissionProcessor);
1045
+ continue;
1046
+ }
1047
+
1048
+ // No @each in path - standard toggle
1049
+ const lhsLastKey = lhsPathParts[lhsPathParts.length - 1];
1050
+ const lhsParent = ensureNestedPath(target, lhsPathParts);
1051
+
1052
+ // Determine what to negate
1053
+ let valueToNegate: any;
1054
+ if (rhsPath === '.') {
1055
+ valueToNegate = (lhsLastKey in lhsParent) ? lhsParent[lhsLastKey] : undefined;
937
1056
  } else {
938
- valueToNegate = undefined;
1057
+ valueToNegate = resolveValueToNegate(rhsPath, target);
1058
+ }
1059
+
1060
+ if (!permissionProcessor?.checkRestrictedProp(lhsLastKey)) {
1061
+ lhsParent[lhsLastKey] = !valueToNegate;
939
1062
  }
940
1063
  } else {
941
- // RHS path: navigate to get the value (don't create paths)
942
- if (isNestedPath(rhsPath)) {
943
- const rhsPathParts = parsePath(rhsPath);
944
- let current = target;
945
- let exists = true;
946
- for (const part of rhsPathParts) {
947
- if (current && typeof current === 'object' && part in current) {
948
- current = current[part];
949
- } else {
950
- exists = false;
951
- break;
952
- }
953
- }
954
- valueToNegate = exists ? current : true;
1064
+ // Plain key LHS
1065
+ const lhsLastKey = lhsPath;
1066
+ const lhsParent = target;
1067
+
1068
+ let valueToNegate: any;
1069
+ if (rhsPath === '.') {
1070
+ valueToNegate = (lhsLastKey in lhsParent) ? lhsParent[lhsLastKey] : undefined;
955
1071
  } else {
956
- // Plain key RHS
957
- valueToNegate = (rhsPath in target) ? target[rhsPath] : true;
1072
+ valueToNegate = resolveValueToNegate(rhsPath, target);
1073
+ }
1074
+
1075
+ if (!permissionProcessor?.checkRestrictedProp(lhsLastKey)) {
1076
+ lhsParent[lhsLastKey] = !valueToNegate;
958
1077
  }
959
- }
960
-
961
- // Apply negation to LHS — check restriction first
962
- if (!permissionProcessor?.checkRestrictedProp(lhsLastKey)) {
963
- lhsParent[lhsLastKey] = !valueToNegate;
964
1078
  }
965
1079
  }
966
1080
  continue;
@@ -976,6 +1090,13 @@ export function assignGingerly(
976
1090
 
977
1091
  if (isNestedPath(path)) {
978
1092
  const pathParts = parsePath(path);
1093
+
1094
+ // Check for @each in path
1095
+ if (pathParts.some(part => isForEachSymbol(part, aliasMap))) {
1096
+ applyCommandToEach(target, pathParts, ' -=', value, withMethodsSet, aliasMap, options, permissionProcessor);
1097
+ continue;
1098
+ }
1099
+
979
1100
  if (pathParts.length === 0) {
980
1101
  parent = target;
981
1102
  } else {
@@ -1019,6 +1140,13 @@ export function assignGingerly(
1019
1140
  if (permissionProcessor?.checkRestrictedProp(lastKey)) {
1020
1141
  continue;
1021
1142
  }
1143
+
1144
+ // Check for @each in path
1145
+ if (isNestedPath(path) && pathParts.some(part => isForEachSymbol(part, aliasMap))) {
1146
+ applyCommandToEach(target, pathParts, ' Y=', value, withMethodsSet, aliasMap, options, permissionProcessor);
1147
+ continue;
1148
+ }
1149
+
1022
1150
  // Navigate to the target sub-object
1023
1151
  let mergeTarget: any;
1024
1152
  if (isNestedPath(path)) {
@@ -1086,24 +1214,12 @@ export function assignGingerly(
1086
1214
  // Static forEach (@each) - existing logic
1087
1215
  const pathToForEach = pathParts.slice(0, forEachIndex);
1088
1216
  const pathAfterForEach = pathParts.slice(forEachIndex + 1);
1089
-
1217
+
1090
1218
  // Navigate to the iterable
1091
- let current = target;
1092
- if (pathToForEach.length > 0) {
1093
- if (withMethodsSet) {
1094
- const result = evaluatePathWithMethods(target, pathToForEach, value, withMethodsSet, permissionProcessor);
1095
- // The result.target is the current position after evaluating the path
1096
- // This is already the iterable we want
1097
- current = result.target;
1098
- } else {
1099
- for (const part of pathToForEach) {
1100
- current = current[part];
1101
- }
1102
- }
1103
- }
1104
-
1219
+ const current = getIterableAtPath(target, pathToForEach, value, withMethodsSet, permissionProcessor);
1220
+
1105
1221
  // Apply to each item in the iterable
1106
- if (isIterable(current)) {
1222
+ if (current) {
1107
1223
  applyToEach(current, pathAfterForEach, value, withMethodsSet || new Set(), aliasMap, options, permissionProcessor);
1108
1224
  }
1109
1225
  // If not iterable, let JavaScript throw error naturally when trying to iterate
@@ -47,7 +47,7 @@ async function defineIshProperty(element, managerName, options, assignGingerlyFn
47
47
  let config = registry.get(managerName);
48
48
  // If not registered, wait for registration
49
49
  if (!config) {
50
- const { waitForEvent } = await import('./waitForEvent.js');
50
+ const { waitForEvent } = await import('./utils/waitForEvent.js');
51
51
  await waitForEvent(registry, managerName);
52
52
  config = registry.get(managerName);
53
53
  if (!config) {
@@ -66,7 +66,7 @@ async function defineIshProperty(
66
66
 
67
67
  // If not registered, wait for registration
68
68
  if (!config) {
69
- const { waitForEvent } = await import('./waitForEvent.js');
69
+ const { waitForEvent } = await import('./utils/waitForEvent.js');
70
70
  await waitForEvent(registry, managerName);
71
71
  config = registry.get(managerName);
72
72
 
@@ -224,7 +224,7 @@ export class ManageTemplateListHandler {
224
224
  if (fragment.childNodes.length > 0) {
225
225
  const waitOpt = resolvedParams.waitForSettled;
226
226
  if (waitOpt) {
227
- const { waitForSettled } = await import('../waitForSettled.js');
227
+ const { waitForSettled } = await import('../utils/waitForSettled.js');
228
228
  const idleMs = typeof waitOpt === 'object' ? waitOpt.idleMs : 100;
229
229
  const timeout = typeof waitOpt === 'object' ? waitOpt.timeout : undefined;
230
230
  try {
@@ -263,7 +263,7 @@ export class ManageTemplateListHandler implements AssignFromHandler {
263
263
  if (fragment.childNodes.length > 0) {
264
264
  const waitOpt = resolvedParams.waitForSettled;
265
265
  if (waitOpt) {
266
- const { waitForSettled } = await import('../waitForSettled.js');
266
+ const { waitForSettled } = await import('../utils/waitForSettled.js');
267
267
  const idleMs = typeof waitOpt === 'object' ? waitOpt.idleMs : 100;
268
268
  const timeout = typeof waitOpt === 'object' ? waitOpt.timeout : undefined;
269
269
  try {
package/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export { assignGingerly } from './assignGingerly.js';
2
2
  export { assignTentatively } from './assignTentatively.js';
3
3
  export { EnhancementRegistry, ItemscopeRegistry, EnhancementRegisteredEvent } from './assignGingerly.js';
4
- export { waitForEvent } from './waitForEvent.js';
4
+ export { waitForEvent } from './utils/waitForEvent.js';
5
5
  export { ParserRegistry, globalParserRegistry } from './parserRegistry.js';
6
6
  export { parseWithAttrs } from './parseWithAttrs.js';
7
7
  export { buildCSSQuery } from './buildCSSQuery.js';
package/index.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export {assignGingerly} from './assignGingerly.js';
2
2
  export {assignTentatively} from './assignTentatively.js';
3
3
  export {EnhancementRegistry, ItemscopeRegistry, EnhancementRegisteredEvent} from './assignGingerly.js';
4
- export {waitForEvent} from './waitForEvent.js';
4
+ export {waitForEvent} from './utils/waitForEvent.js';
5
5
  export {ParserRegistry, globalParserRegistry} from './parserRegistry.js';
6
6
  export {parseWithAttrs} from './parseWithAttrs.js';
7
7
  export {buildCSSQuery} from './buildCSSQuery.js';
@@ -53,6 +53,7 @@ export type Compacts<TProps = any, TActions = TProps, TEvents extends string = s
53
53
  | Partial<{[key in `when_${keyof TProps & string}_changes_dispatch`]: string}>
54
54
  | Partial<{[key in `on_${TEvents}_of_${keyof TProps & string}_inc_${keyof TProps & string}_by`]: number}>
55
55
  | Partial<{[key in `on_${TEvents}_of_${keyof TProps & string}_set_${keyof TProps & string}_to`]: any}>
56
+ | Partial<{[key in `on_${TEvents}_of_${keyof TProps & string}_assign`]: Record<string, any>}>
56
57
  ;
57
58
 
58
59
  export type Hitches<TProps = any, TActions = TProps> =
@@ -250,7 +250,7 @@ class ElementEnhancementContainer {
250
250
  throw new Error('Instance must be an EventTarget to use whenResolved');
251
251
  }
252
252
  // Lazy load waitForEvent
253
- const { waitForEvent } = await import('./waitForEvent.js');
253
+ const { waitForEvent } = await import('./utils/waitForEvent.js');
254
254
  // Wait for the resolved event (use resolvedKey as event name)
255
255
  // Note: When symbols are supported as event names, this will work with symbol keys too
256
256
  await waitForEvent(spawnedInstance, resolvedKey);
@@ -359,7 +359,7 @@ class ElementEnhancementContainer {
359
359
  }
360
360
 
361
361
  // Lazy load waitForEvent
362
- const { waitForEvent } = await import('./waitForEvent.js');
362
+ const { waitForEvent } = await import('./utils/waitForEvent.js');
363
363
 
364
364
  // Wait for the resolved event (use resolvedKey as event name)
365
365
  // Note: When symbols are supported as event names, this will work with symbol keys too
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "assign-gingerly",
3
- "version": "0.0.79",
3
+ "version": "0.0.80",
4
4
  "description": "This package provides a utility function for carefully merging one object into another.",
5
5
  "homepage": "https://github.com/bahrus/assign-gingerly#readme",
6
6
  "bugs": {
@@ -159,9 +159,9 @@
159
159
  "default": "./markerUtils.js",
160
160
  "types": "./markerUtils.ts"
161
161
  },
162
- "./waitForSettled.js": {
163
- "default": "./waitForSettled.js",
164
- "types": "./waitForSettled.ts"
162
+ "./utils/waitForSettled.js": {
163
+ "default": "./utils/waitForSettled.js",
164
+ "types": "./utils/waitForSettled.ts"
165
165
  },
166
166
  "./inferredAssignments.js": {
167
167
  "default": "./inferredAssignments.js",
@@ -199,8 +199,9 @@
199
199
  "default": "./evaluatePathWithAsyncMethods.js",
200
200
  "types": "./evaluatePathWithAsyncMethods.ts"
201
201
  },
202
- "./waitForEvent.js": {
203
- "default": "./waitForEvent.js"
202
+ "./utils/waitForEvent.js": {
203
+ "default": "./utils/waitForEvent.js",
204
+ "types": "./utils/waitForEvent.ts"
204
205
  }
205
206
  },
206
207
  "main": "index.js",
File without changes
File without changes
File without changes
File without changes