assign-gingerly 0.0.74 → 0.0.76

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 (62) hide show
  1. package/DX/installForwarding.js +1 -1
  2. package/DX/installForwarding.ts +1 -1
  3. package/README.md +2 -0
  4. package/assignFrom.js +18 -17
  5. package/assignFrom.ts +23 -23
  6. package/assignFromAsync.js +14 -13
  7. package/assignFromAsync.ts +15 -15
  8. package/assignGingerly.js +46 -42
  9. package/assignGingerly.ts +131 -124
  10. package/assignPermissions/PermissionProcessor.js +166 -0
  11. package/assignPermissions/PermissionProcessor.ts +210 -0
  12. package/assignPermissions/isAllowedImportPath.js +2 -6
  13. package/assignPermissions/isAllowedImportPath.ts +3 -5
  14. package/assignPermissions/isAllowedUrl.js +18 -0
  15. package/assignPermissions/isAllowedUrl.ts +15 -0
  16. package/assignTentatively.js +9 -11
  17. package/assignTentatively.ts +11 -13
  18. package/beVigilant.js +1 -1
  19. package/beVigilant.ts +1 -1
  20. package/buildCSSQuery.js +1 -1
  21. package/buildCSSQuery.ts +1 -1
  22. package/eachTime.js +5 -6
  23. package/eachTime.ts +12 -15
  24. package/enhanceAll.js +3 -3
  25. package/enhanceAll.ts +4 -4
  26. package/evaluatePathWithAsyncMethods.js +12 -8
  27. package/evaluatePathWithAsyncMethods.ts +129 -117
  28. package/handlers/addEventListener.js +11 -11
  29. package/handlers/addEventListener.ts +12 -13
  30. package/handlers/lazyLoad.ts +7 -7
  31. package/handlers/lazyLoadSwitch.ts +3 -3
  32. package/handlers/manageTemplateList.js +10 -10
  33. package/handlers/manageTemplateList.ts +12 -12
  34. package/handlers/rangeSelector.ts +3 -3
  35. package/index.js +2 -3
  36. package/index.ts +2 -3
  37. package/inferencer/types/assign-gingerly/types.d.ts +37 -23
  38. package/inferencer/types/el-maker/types.d.ts +33 -0
  39. package/inferencer/types/scratch-box/types.d.ts +3 -0
  40. package/inferencer/types/truth-sourcer/types.d.ts +4 -0
  41. package/package.json +25 -23
  42. package/parseWithAttrs.js +1 -1
  43. package/parseWithAttrs.ts +1 -1
  44. package/processHandlerCommands.js +5 -7
  45. package/processHandlerCommands.ts +12 -15
  46. package/{getValues.js → resolve/getValues.js} +19 -8
  47. package/{getValues.ts → resolve/getValues.ts} +331 -314
  48. package/{resolveIdRef.js → resolve/resolveIdRef.js} +1 -1
  49. package/{resolveIdRef.ts → resolve/resolveIdRef.ts} +1 -1
  50. package/{resolveValues.ts → resolve/resolveValues.ts} +1 -1
  51. package/types/assign-gingerly/types.d.ts +37 -8
  52. package/utils/findClassPrototypeInPath.js +57 -0
  53. package/utils/findClassPrototypeInPath.ts +62 -0
  54. package/utils/isAsyncSpawn.js +20 -0
  55. package/utils/isAsyncSpawn.ts +17 -0
  56. package/assignPermissions/restrictedProps.js +0 -43
  57. package/assignPermissions/restrictedProps.ts +0 -53
  58. package/resolveAndAssignFeatures.js +0 -36
  59. package/resolveAndAssignFeatures.ts +0 -43
  60. /package/{resolveTemplate.js → resolve/resolveTemplate.js} +0 -0
  61. /package/{resolveTemplate.ts → resolve/resolveTemplate.ts} +0 -0
  62. /package/{resolveValues.js → resolve/resolveValues.js} +0 -0
@@ -20,7 +20,7 @@
20
20
  * installForwarding(ClubMember);
21
21
  * // Now el.command delegates to el.behaviors.commandBehavior.command
22
22
  */
23
- import { resolveValue } from '../resolveValues.js';
23
+ import { resolveValue } from '../resolve/resolveValues.js';
24
24
  import assignGingerly from '../assignGingerly.js';
25
25
  /**
26
26
  * Installs property forwarding on a class prototype based on `static propLinks`.
@@ -21,7 +21,7 @@
21
21
  * // Now el.command delegates to el.behaviors.commandBehavior.command
22
22
  */
23
23
 
24
- import { resolveValue} from '../resolveValues.js';
24
+ import { resolveValue} from '../resolve/resolveValues.js';
25
25
  import {ResolveValuesOptions, IAssignGingerlyOptions} from '../types/assign-gingerly/types.js';
26
26
  import assignGingerly, { } from '../assignGingerly.js';
27
27
 
package/README.md CHANGED
@@ -54,6 +54,8 @@ So in our view this package helps fill the void left by not supporting the "is"
54
54
 
55
55
  Anyway, let's start out detailing the more innocent features of this package / polyfill.
56
56
 
57
+ Because the same declarative input can come from sources that aren't fully trusted — HTML attributes, user JSON, remote config — the package also provides an **opt-in permission layer** to block or redirect dangerous property assignments. See [docs/assign-permissions.md](docs/assign-permissions.md) for how to construct and pass a `PermissionProcessor`.
58
+
57
59
  The three utility functions are:
58
60
 
59
61
  ## assignGingerly
package/assignFrom.js CHANGED
@@ -8,9 +8,9 @@
8
8
  *
9
9
  * Handler commands (` =>`) are fire-and-forget (kicked off asynchronously, not awaited).
10
10
  */
11
- import { getValues, getValue } from './getValues.js';
11
+ import { getValues, getValue } from './resolve/getValues.js';
12
12
  import assignGingerly from './assignGingerly.js';
13
- import { resolveIdVariable, parseIdRef } from './resolveIdRef.js';
13
+ import { resolveIdVariable, parseIdRef } from './resolve/resolveIdRef.js';
14
14
  import { processInferredAssignments } from './inferredAssignments.js';
15
15
  /**
16
16
  * Supported substitution variables and their option keys.
@@ -377,7 +377,7 @@ function getEffectiveIds(options) {
377
377
  /**
378
378
  * Process #[x] normal keys synchronously.
379
379
  */
380
- function processIdRefNormalKeys(idRefNormalKeys, expandedPattern, target, options, permissions) {
380
+ function processIdRefNormalKeys(idRefNormalKeys, expandedPattern, target, options, permissionProcessor) {
381
381
  const ids = getEffectiveIds(options);
382
382
  if (!ids)
383
383
  return;
@@ -391,13 +391,13 @@ function processIdRefNormalKeys(idRefNormalKeys, expandedPattern, target, option
391
391
  continue;
392
392
  const value = expandedPattern[key];
393
393
  if (parsed.remainingPath) {
394
- const resolvedValue = getValues({ __v: value }, from, { withMethods, aka, akaMethods, protocols, root: target });
395
- assignGingerly(el, { [parsed.remainingPath]: resolvedValue.__v }, options, permissions);
394
+ const resolvedValue = getValues({ __v: value }, from, { withMethods, aka, akaMethods, protocols, root: target, permissionProcessor });
395
+ assignGingerly(el, { [parsed.remainingPath]: resolvedValue.__v }, options, permissionProcessor);
396
396
  }
397
397
  else {
398
- const resolvedValue = getValues(typeof value === 'object' && value !== null ? value : { __v: value }, from, { withMethods, aka, akaMethods, protocols, root: target });
398
+ const resolvedValue = getValues(typeof value === 'object' && value !== null ? value : { __v: value }, from, { withMethods, aka, akaMethods, protocols, root: target, permissionProcessor });
399
399
  if (!('__v' in resolvedValue)) {
400
- assignGingerly(el, resolvedValue, options, permissions);
400
+ assignGingerly(el, resolvedValue, options, permissionProcessor);
401
401
  }
402
402
  }
403
403
  }
@@ -411,15 +411,15 @@ function processIdRefNormalKeys(idRefNormalKeys, expandedPattern, target, option
411
411
  * @param target - Object to merge resolved values into
412
412
  * @param pattern - Object whose RHS values may contain `?.` path strings
413
413
  * @param options - Options including `from` (source object)
414
- * @param permissions - Optional security permissions
414
+ * @param permissionProcessor - Optional security permissionProcessor
415
415
  * @returns The target object after merging
416
416
  */
417
- export function assignFrom(target, pattern, options, permissions) {
417
+ export function assignFrom(target, pattern, options, permissionProcessor) {
418
418
  // Expand looped substitution variables
419
419
  const expandedPattern = expandSubstitutions(pattern, options);
420
420
  // Categorize keys
421
421
  const { handlerKeys, normalPattern, idRefNormalKeys, idRefHandlerKeys, ternaryKeys } = categorizeKeys(expandedPattern);
422
- const resolveOptions = { ...options, root: target };
422
+ const resolveOptions = { ...options, root: target, permissionProcessor };
423
423
  // Process ?= ternary keys (sync)
424
424
  if (ternaryKeys.length > 0) {
425
425
  const ternaryResolved = {};
@@ -436,7 +436,7 @@ export function assignFrom(target, pattern, options, permissions) {
436
436
  }
437
437
  }
438
438
  if (Object.keys(ternaryResolved).length > 0) {
439
- assignGingerly(target, ternaryResolved, options, permissions);
439
+ assignGingerly(target, ternaryResolved, options, permissionProcessor);
440
440
  }
441
441
  }
442
442
  // Process normal keys via getValues (sync) + assignGingerly
@@ -459,7 +459,8 @@ export function assignFrom(target, pattern, options, permissions) {
459
459
  aka: options.aka,
460
460
  akaMethods: options.akaMethods,
461
461
  protocols: options.protocols,
462
- root: target
462
+ root: target,
463
+ permissionProcessor
463
464
  });
464
465
  }
465
466
  else {
@@ -472,16 +473,16 @@ export function assignFrom(target, pattern, options, permissions) {
472
473
  }
473
474
  const resolved = getValues(normalPattern, options.from, resolveOptions);
474
475
  handleSpreads(resolved);
475
- assignGingerly(target, resolved, options, permissions);
476
+ assignGingerly(target, resolved, options, permissionProcessor);
476
477
  }
477
478
  // Process #[x] normal keys (sync)
478
479
  if (idRefNormalKeys.length > 0) {
479
- processIdRefNormalKeys(idRefNormalKeys, expandedPattern, target, options, permissions);
480
+ processIdRefNormalKeys(idRefNormalKeys, expandedPattern, target, options, permissionProcessor);
480
481
  }
481
482
  // Process handler commands — fire-and-forget (async)
482
483
  if (handlerKeys.length > 0) {
483
484
  import('./processHandlerCommands.js').then(({ processHandlerCommands }) => {
484
- processHandlerCommands(target, handlerKeys, expandedPattern, options, permissions);
485
+ processHandlerCommands(target, handlerKeys, expandedPattern, options, permissionProcessor);
485
486
  });
486
487
  }
487
488
  // Process #[x] handler keys — fire-and-forget (async)
@@ -497,7 +498,7 @@ export function assignFrom(target, pattern, options, permissions) {
497
498
  continue;
498
499
  const syntheticKey = parsed.remainingPath ? `${parsed.remainingPath} =>` : ' =>';
499
500
  const syntheticPattern = { [syntheticKey]: expandedPattern[key] };
500
- processHandlerCommands(el, [syntheticKey], syntheticPattern, options, permissions);
501
+ processHandlerCommands(el, [syntheticKey], syntheticPattern, options, permissionProcessor);
501
502
  }
502
503
  });
503
504
  }
@@ -517,7 +518,7 @@ export function assignFrom(target, pattern, options, permissions) {
517
518
  // Process bulk enhancements — fire-and-forget (async)
518
519
  if (options.enhance && options.enhance.length > 0) {
519
520
  import('./enhanceAll.js').then(({ enhanceAll }) => {
520
- enhanceAll(target, options.enhance, permissions);
521
+ enhanceAll(target, options.enhance, permissionProcessor);
521
522
  });
522
523
  }
523
524
  return target;
package/assignFrom.ts CHANGED
@@ -9,12 +9,11 @@
9
9
  * Handler commands (` =>`) are fire-and-forget (kicked off asynchronously, not awaited).
10
10
  */
11
11
 
12
- import { getValues, getValue } from './getValues.js';
12
+ import { getValues, getValue } from './resolve/getValues.js';
13
13
  import assignGingerly from './assignGingerly.js';
14
- import { resolveIdVariable, parseIdRef } from './resolveIdRef.js';
14
+ import { resolveIdVariable, parseIdRef } from './resolve/resolveIdRef.js';
15
15
  import { processInferredAssignments } from './inferredAssignments.js';
16
- import type { AssignPermissions } from './types/assign-gingerly/types.js';
17
- import type { AssignFromOptions, AssignFromHandler, AssignFromHandlerConstructor } from './types/assign-gingerly/types.js';
16
+ import type { PermissionProcessor, AssignFromOptions, AssignFromHandler, AssignFromHandlerConstructor } from './types/assign-gingerly/types.js';
18
17
 
19
18
  // Re-export types for consumers
20
19
  export type { AssignFromOptions, AssignFromHandler, AssignFromHandlerConstructor };
@@ -387,11 +386,11 @@ function getEffectiveIds(options: AssignFromOptions): Record<string, any> | unde
387
386
  * Process #[x] normal keys synchronously.
388
387
  */
389
388
  function processIdRefNormalKeys(
390
- idRefNormalKeys: string[],
391
- expandedPattern: Record<string, any>,
392
- target: any,
393
- options: AssignFromOptions,
394
- permissions?: AssignPermissions
389
+ idRefNormalKeys: string[],
390
+ expandedPattern: Record<string, any>,
391
+ target: any,
392
+ options: AssignFromOptions,
393
+ permissionProcessor?: PermissionProcessor
395
394
  ): void {
396
395
  const ids = getEffectiveIds(options);
397
396
  if (!ids) return;
@@ -408,17 +407,17 @@ function processIdRefNormalKeys(
408
407
  if (parsed.remainingPath) {
409
408
  const resolvedValue = getValues(
410
409
  { __v: value }, from,
411
- { withMethods, aka, akaMethods, protocols, root: target }
410
+ { withMethods, aka, akaMethods, protocols, root: target, permissionProcessor }
412
411
  );
413
- assignGingerly(el, { [parsed.remainingPath]: resolvedValue.__v }, options, permissions);
412
+ assignGingerly(el, { [parsed.remainingPath]: resolvedValue.__v }, options, permissionProcessor);
414
413
  } else {
415
414
  const resolvedValue = getValues(
416
415
  typeof value === 'object' && value !== null ? value : { __v: value },
417
416
  from,
418
- { withMethods, aka, akaMethods, protocols, root: target }
417
+ { withMethods, aka, akaMethods, protocols, root: target, permissionProcessor }
419
418
  );
420
419
  if (!('__v' in resolvedValue)) {
421
- assignGingerly(el, resolvedValue, options, permissions);
420
+ assignGingerly(el, resolvedValue, options, permissionProcessor);
422
421
  }
423
422
  }
424
423
  }
@@ -433,14 +432,14 @@ function processIdRefNormalKeys(
433
432
  * @param target - Object to merge resolved values into
434
433
  * @param pattern - Object whose RHS values may contain `?.` path strings
435
434
  * @param options - Options including `from` (source object)
436
- * @param permissions - Optional security permissions
435
+ * @param permissionProcessor - Optional security permissionProcessor
437
436
  * @returns The target object after merging
438
437
  */
439
438
  export function assignFrom(
440
439
  target: any,
441
440
  pattern: Record<string, any>,
442
441
  options: AssignFromOptions,
443
- permissions?: AssignPermissions
442
+ permissionProcessor?: PermissionProcessor
444
443
  ): any {
445
444
  // Expand looped substitution variables
446
445
  const expandedPattern = expandSubstitutions(pattern, options);
@@ -448,7 +447,7 @@ export function assignFrom(
448
447
  // Categorize keys
449
448
  const { handlerKeys, normalPattern, idRefNormalKeys, idRefHandlerKeys, ternaryKeys } = categorizeKeys(expandedPattern);
450
449
 
451
- const resolveOptions = { ...options, root: target } as any;
450
+ const resolveOptions = { ...options, root: target, permissionProcessor } as any;
452
451
 
453
452
  // Process ?= ternary keys (sync)
454
453
  if (ternaryKeys.length > 0) {
@@ -464,7 +463,7 @@ export function assignFrom(
464
463
  }
465
464
  }
466
465
  if (Object.keys(ternaryResolved).length > 0) {
467
- assignGingerly(target, ternaryResolved, options, permissions);
466
+ assignGingerly(target, ternaryResolved, options, permissionProcessor);
468
467
  }
469
468
  }
470
469
 
@@ -488,7 +487,8 @@ export function assignFrom(
488
487
  aka: options.aka,
489
488
  akaMethods: options.akaMethods,
490
489
  protocols: options.protocols,
491
- root: target
490
+ root: target,
491
+ permissionProcessor
492
492
  });
493
493
  } else {
494
494
  normalPattern[key] = el.id; // bare #[x] → ID string
@@ -502,18 +502,18 @@ export function assignFrom(
502
502
  const resolved = getValues(normalPattern, options.from, resolveOptions);
503
503
 
504
504
  handleSpreads(resolved);
505
- assignGingerly(target, resolved, options, permissions);
505
+ assignGingerly(target, resolved, options, permissionProcessor);
506
506
  }
507
507
 
508
508
  // Process #[x] normal keys (sync)
509
509
  if (idRefNormalKeys.length > 0) {
510
- processIdRefNormalKeys(idRefNormalKeys, expandedPattern, target, options, permissions);
510
+ processIdRefNormalKeys(idRefNormalKeys, expandedPattern, target, options, permissionProcessor);
511
511
  }
512
512
 
513
513
  // Process handler commands — fire-and-forget (async)
514
514
  if (handlerKeys.length > 0) {
515
515
  import('./processHandlerCommands.js').then(({ processHandlerCommands }) => {
516
- processHandlerCommands(target, handlerKeys, expandedPattern, options, permissions);
516
+ processHandlerCommands(target, handlerKeys, expandedPattern, options, permissionProcessor);
517
517
  });
518
518
  }
519
519
 
@@ -528,7 +528,7 @@ export function assignFrom(
528
528
  if (!el) continue;
529
529
  const syntheticKey = parsed.remainingPath ? `${parsed.remainingPath} =>` : ' =>';
530
530
  const syntheticPattern = { [syntheticKey]: expandedPattern[key] };
531
- processHandlerCommands(el, [syntheticKey], syntheticPattern, options, permissions);
531
+ processHandlerCommands(el, [syntheticKey], syntheticPattern, options, permissionProcessor);
532
532
  }
533
533
  });
534
534
  }
@@ -551,7 +551,7 @@ export function assignFrom(
551
551
  // Process bulk enhancements — fire-and-forget (async)
552
552
  if (options.enhance && options.enhance.length > 0) {
553
553
  import('./enhanceAll.js').then(({ enhanceAll }) => {
554
- enhanceAll(target, options.enhance!, permissions);
554
+ enhanceAll(target, options.enhance!, permissionProcessor);
555
555
  });
556
556
  }
557
557
 
@@ -19,12 +19,12 @@
19
19
  * }, { from: source });
20
20
  * // target is now { color: 'red', text: 'Hello' }
21
21
  */
22
- import { resolveValues } from './resolveValues.js';
22
+ import { resolveValues } from './resolve/resolveValues.js';
23
23
  import assignGingerly from './assignGingerly.js';
24
24
  import { expandSubstitutions, categorizeKeys, handleSpreads } from './assignFrom.js';
25
25
  // Module cache for processHandlerCommands — avoids await on dynamic import after first call
26
26
  let _processHandlerCommands;
27
- export async function assignFromAsync(target, pattern, options, permissions) {
27
+ export async function assignFromAsync(target, pattern, options, permissionProcessor) {
28
28
  // First: expand looped substitution variables (${x}, ${y}, ${z})
29
29
  const expandedPattern = expandSubstitutions(pattern, options);
30
30
  // Categorize keys
@@ -36,16 +36,17 @@ export async function assignFromAsync(target, pattern, options, permissions) {
36
36
  aka: options.aka,
37
37
  akaMethods: options.akaMethods,
38
38
  protocols: options.protocols,
39
- root: target
39
+ root: target,
40
+ permissionProcessor
40
41
  });
41
42
  // Recursively handle "..." spread keys at all nesting levels
42
43
  handleSpreads(resolved);
43
- assignGingerly(target, resolved, options, permissions);
44
+ assignGingerly(target, resolved, options, permissionProcessor);
44
45
  }
45
46
  // Process #[x] normal keys — resolve element, then apply remaining path + value
46
47
  if (idRefNormalKeys.length > 0 && (options.pin || options.at)) {
47
48
  const ids = { ...options.pin, ...options.at };
48
- const { resolveIdVariable, parseIdRef } = await import('./resolveIdRef.js');
49
+ const { resolveIdVariable, parseIdRef } = await import('./resolve/resolveIdRef.js');
49
50
  const { withMethods, aka, akaMethods, protocols, from } = options;
50
51
  for (const key of idRefNormalKeys) {
51
52
  const parsed = parseIdRef(key);
@@ -57,18 +58,18 @@ export async function assignFromAsync(target, pattern, options, permissions) {
57
58
  const value = expandedPattern[key];
58
59
  if (parsed.remainingPath) {
59
60
  // Resolve the RHS value
60
- const resolvedValue = await resolveValues({ __v: value }, from, { withMethods, aka, akaMethods, protocols, root: el });
61
+ const resolvedValue = await resolveValues({ __v: value }, from, { withMethods, aka, akaMethods, protocols, root: el, permissionProcessor });
61
62
  // Apply remaining path on the resolved element
62
- assignGingerly(el, { [parsed.remainingPath]: resolvedValue.__v }, options, permissions);
63
+ assignGingerly(el, { [parsed.remainingPath]: resolvedValue.__v }, options, permissionProcessor);
63
64
  }
64
65
  else {
65
66
  // No remaining path — resolve and assign directly to the element
66
- const resolvedValue = await resolveValues(typeof value === 'object' && value !== null ? value : { __v: value }, from, { withMethods, aka, akaMethods, protocols, root: el });
67
+ const resolvedValue = await resolveValues(typeof value === 'object' && value !== null ? value : { __v: value }, from, { withMethods, aka, akaMethods, protocols, root: el, permissionProcessor });
67
68
  if ('__v' in resolvedValue) {
68
69
  // Single value — can't assign to element root without a path
69
70
  }
70
71
  else {
71
- assignGingerly(el, resolvedValue, options, permissions);
72
+ assignGingerly(el, resolvedValue, options, permissionProcessor);
72
73
  }
73
74
  }
74
75
  }
@@ -76,12 +77,12 @@ export async function assignFromAsync(target, pattern, options, permissions) {
76
77
  // Process handler commands ( =>) — cached after first load to avoid await overhead
77
78
  if (handlerKeys.length > 0) {
78
79
  _processHandlerCommands ??= (await import('./processHandlerCommands.js')).processHandlerCommands;
79
- await _processHandlerCommands(target, handlerKeys, expandedPattern, options, permissions);
80
+ await _processHandlerCommands(target, handlerKeys, expandedPattern, options, permissionProcessor);
80
81
  }
81
82
  // Process #[x] handler keys — resolve element, then pass to handler processing
82
83
  if (idRefHandlerKeys.length > 0 && (options.pin || options.at)) {
83
84
  const ids = { ...options.pin, ...options.at };
84
- const { resolveIdVariable, parseIdRef } = await import('./resolveIdRef.js');
85
+ const { resolveIdVariable, parseIdRef } = await import('./resolve/resolveIdRef.js');
85
86
  _processHandlerCommands ??= (await import('./processHandlerCommands.js')).processHandlerCommands;
86
87
  for (const key of idRefHandlerKeys) {
87
88
  const parsed = parseIdRef(key);
@@ -98,7 +99,7 @@ export async function assignFromAsync(target, pattern, options, permissions) {
98
99
  const syntheticPattern = {
99
100
  [syntheticKey]: expandedPattern[key]
100
101
  };
101
- await _processHandlerCommands(el, [syntheticKey], syntheticPattern, options, permissions);
102
+ await _processHandlerCommands(el, [syntheticKey], syntheticPattern, options, permissionProcessor);
102
103
  }
103
104
  }
104
105
  // Process inferred assignments — dynamically imported only when option is present
@@ -117,7 +118,7 @@ export async function assignFromAsync(target, pattern, options, permissions) {
117
118
  // Process bulk enhancements — dynamically imported only when option is present
118
119
  if (options.enhance && options.enhance.length > 0) {
119
120
  const { enhanceAll } = await import('./enhanceAll.js');
120
- await enhanceAll(target, options.enhance, permissions);
121
+ await enhanceAll(target, options.enhance, permissionProcessor);
121
122
  }
122
123
  return target;
123
124
  }
@@ -19,11 +19,10 @@
19
19
  * }, { from: source });
20
20
  * // target is now { color: 'red', text: 'Hello' }
21
21
  */
22
- import { resolveValues } from './resolveValues.js';
22
+ import { resolveValues } from './resolve/resolveValues.js';
23
23
  import {IAssignGingerlyOptions} from './types/assign-gingerly/types.js';
24
24
  import assignGingerly from './assignGingerly.js';
25
- import type { AssignPermissions } from './types/assign-gingerly/types.js';
26
- import type { AssignFromHandler, AssignFromHandlerConstructor } from './types/assign-gingerly/types.js';
25
+ import type { PermissionProcessor, AssignFromHandler, AssignFromHandlerConstructor } from './types/assign-gingerly/types.js';
27
26
  import {
28
27
  expandSubstitutions, categorizeKeys, handleSpreads, isHandlerCommand
29
28
  } from './assignFrom.js';
@@ -56,7 +55,7 @@ export async function assignFromAsync(
56
55
  target: any,
57
56
  pattern: Record<string, any>,
58
57
  options: AssignFromOptions,
59
- permissions?: AssignPermissions
58
+ permissionProcessor?: PermissionProcessor
60
59
  ): Promise<any> {
61
60
  // First: expand looped substitution variables (${x}, ${y}, ${z})
62
61
  const expandedPattern = expandSubstitutions(pattern, options);
@@ -71,19 +70,20 @@ export async function assignFromAsync(
71
70
  aka: options.aka,
72
71
  akaMethods: options.akaMethods,
73
72
  protocols: options.protocols,
74
- root: target
73
+ root: target,
74
+ permissionProcessor
75
75
  });
76
76
 
77
77
  // Recursively handle "..." spread keys at all nesting levels
78
78
  handleSpreads(resolved);
79
79
 
80
- assignGingerly(target, resolved, options, permissions);
80
+ assignGingerly(target, resolved, options, permissionProcessor);
81
81
  }
82
82
 
83
83
  // Process #[x] normal keys — resolve element, then apply remaining path + value
84
84
  if (idRefNormalKeys.length > 0 && (options.pin || options.at)) {
85
85
  const ids = { ...options.pin, ...options.at };
86
- const { resolveIdVariable, parseIdRef } = await import('./resolveIdRef.js');
86
+ const { resolveIdVariable, parseIdRef } = await import('./resolve/resolveIdRef.js');
87
87
  const { withMethods, aka, akaMethods, protocols, from } = options;
88
88
  for (const key of idRefNormalKeys) {
89
89
  const parsed = parseIdRef(key);
@@ -97,21 +97,21 @@ export async function assignFromAsync(
97
97
  // Resolve the RHS value
98
98
  const resolvedValue = await resolveValues(
99
99
  { __v: value }, from,
100
- { withMethods, aka, akaMethods, protocols, root: el }
100
+ { withMethods, aka, akaMethods, protocols, root: el, permissionProcessor }
101
101
  );
102
102
  // Apply remaining path on the resolved element
103
- assignGingerly(el, { [parsed.remainingPath]: resolvedValue.__v }, options, permissions);
103
+ assignGingerly(el, { [parsed.remainingPath]: resolvedValue.__v }, options, permissionProcessor);
104
104
  } else {
105
105
  // No remaining path — resolve and assign directly to the element
106
106
  const resolvedValue = await resolveValues(
107
107
  typeof value === 'object' && value !== null ? value : { __v: value },
108
108
  from,
109
- { withMethods, aka, akaMethods, protocols, root: el }
109
+ { withMethods, aka, akaMethods, protocols, root: el, permissionProcessor }
110
110
  );
111
111
  if ('__v' in resolvedValue) {
112
112
  // Single value — can't assign to element root without a path
113
113
  } else {
114
- assignGingerly(el, resolvedValue, options, permissions);
114
+ assignGingerly(el, resolvedValue, options, permissionProcessor);
115
115
  }
116
116
  }
117
117
  }
@@ -120,12 +120,12 @@ export async function assignFromAsync(
120
120
  if (handlerKeys.length > 0) {
121
121
 
122
122
  _processHandlerCommands ??= (await import('./processHandlerCommands.js')).processHandlerCommands;
123
- await _processHandlerCommands(target, handlerKeys, expandedPattern, options, permissions);
123
+ await _processHandlerCommands(target, handlerKeys, expandedPattern, options, permissionProcessor);
124
124
  }
125
125
  // Process #[x] handler keys — resolve element, then pass to handler processing
126
126
  if (idRefHandlerKeys.length > 0 && (options.pin || options.at)) {
127
127
  const ids = { ...options.pin, ...options.at };
128
- const { resolveIdVariable, parseIdRef } = await import('./resolveIdRef.js');
128
+ const { resolveIdVariable, parseIdRef } = await import('./resolve/resolveIdRef.js');
129
129
  _processHandlerCommands ??= (await import('./processHandlerCommands.js')).processHandlerCommands;
130
130
 
131
131
  for (const key of idRefHandlerKeys) {
@@ -145,7 +145,7 @@ export async function assignFromAsync(
145
145
  [syntheticKey]: expandedPattern[key]
146
146
  };
147
147
 
148
- await _processHandlerCommands(el, [syntheticKey], syntheticPattern, options, permissions);
148
+ await _processHandlerCommands(el, [syntheticKey], syntheticPattern, options, permissionProcessor);
149
149
  }
150
150
  }
151
151
 
@@ -167,7 +167,7 @@ export async function assignFromAsync(
167
167
  // Process bulk enhancements — dynamically imported only when option is present
168
168
  if (options.enhance && options.enhance.length > 0) {
169
169
  const { enhanceAll } = await import('./enhanceAll.js');
170
- await enhanceAll(target, options.enhance, permissions);
170
+ await enhanceAll(target, options.enhance, permissionProcessor);
171
171
  }
172
172
 
173
173
  return target;