assign-gingerly 0.0.52 → 0.0.53

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/assignFrom.js CHANGED
@@ -27,13 +27,30 @@ export async function assignFrom(target, pattern, options) {
27
27
  aka: options.aka,
28
28
  protocols: options.protocols
29
29
  });
30
- // Handle "..." spread key merge resolved value into parent
31
- if ('...' in resolved) {
32
- const spreadValue = resolved['...'];
30
+ // Recursively handle "..." spread keys at all nesting levels
31
+ handleSpreads(resolved);
32
+ return assignGingerly(target, resolved, options);
33
+ }
34
+ /**
35
+ * Recursively walk an object and handle "..." spread keys.
36
+ * When a "..." key is found, its value (which should be an object after protocol resolution)
37
+ * is spread into the parent, replacing the "..." entry.
38
+ */
39
+ function handleSpreads(obj) {
40
+ for (const [key, value] of Object.entries(obj)) {
41
+ if (key !== '...' && typeof value === 'object' && value !== null && !Array.isArray(value)) {
42
+ const proto = Object.getPrototypeOf(value);
43
+ if (proto === Object.prototype || proto === null) {
44
+ obj[key] = handleSpreads(value);
45
+ }
46
+ }
47
+ }
48
+ if ('...' in obj) {
49
+ const spreadValue = obj['...'];
50
+ delete obj['...'];
33
51
  if (spreadValue && typeof spreadValue === 'object') {
34
- Object.assign(resolved, spreadValue);
52
+ Object.assign(obj, spreadValue);
35
53
  }
36
- delete resolved['...'];
37
54
  }
38
- return assignGingerly(target, resolved, options);
55
+ return obj;
39
56
  }
package/assignFrom.ts CHANGED
@@ -38,14 +38,32 @@ export async function assignFrom(
38
38
  protocols: options.protocols
39
39
  });
40
40
 
41
- // Handle "..." spread key merge resolved value into parent
42
- if ('...' in resolved) {
43
- const spreadValue = resolved['...'];
41
+ // Recursively handle "..." spread keys at all nesting levels
42
+ handleSpreads(resolved);
43
+
44
+ return assignGingerly(target, resolved, options);
45
+ }
46
+
47
+ /**
48
+ * Recursively walk an object and handle "..." spread keys.
49
+ * When a "..." key is found, its value (which should be an object after protocol resolution)
50
+ * is spread into the parent, replacing the "..." entry.
51
+ */
52
+ function handleSpreads(obj: Record<string, any>): Record<string, any> {
53
+ for (const [key, value] of Object.entries(obj)) {
54
+ if (key !== '...' && typeof value === 'object' && value !== null && !Array.isArray(value)) {
55
+ const proto = Object.getPrototypeOf(value);
56
+ if (proto === Object.prototype || proto === null) {
57
+ obj[key] = handleSpreads(value);
58
+ }
59
+ }
60
+ }
61
+ if ('...' in obj) {
62
+ const spreadValue = obj['...'];
63
+ delete obj['...'];
44
64
  if (spreadValue && typeof spreadValue === 'object') {
45
- Object.assign(resolved, spreadValue);
65
+ Object.assign(obj, spreadValue);
46
66
  }
47
- delete resolved['...'];
48
67
  }
49
-
50
- return assignGingerly(target, resolved, options);
68
+ return obj;
51
69
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "assign-gingerly",
3
- "version": "0.0.52",
3
+ "version": "0.0.53",
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": {
package/resolveValues.js CHANGED
@@ -160,6 +160,16 @@ export async function resolveValues(pattern, source, options) {
160
160
  // Protocol-prefixed value — resolve asynchronously
161
161
  result[key] = await resolveProtocolValue(value, protocols, options);
162
162
  }
163
+ else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
164
+ // Recursively resolve nested plain objects (e.g., headers: { "...": "globalThis://key" })
165
+ // Only recurse into plain objects — skip DOM elements, class instances, etc.
166
+ const proto = Object.getPrototypeOf(value);
167
+ if (proto === Object.prototype || proto === null) {
168
+ result[key] = await resolveValues(value, source, options);
169
+ } else {
170
+ result[key] = value;
171
+ }
172
+ }
163
173
  else {
164
174
  result[key] = value;
165
175
  }
package/resolveValues.ts CHANGED
@@ -216,6 +216,15 @@ export async function resolveValues(
216
216
  } else if (typeof value === 'string' && protocols && hasProtocol(value)) {
217
217
  // Protocol-prefixed value — resolve asynchronously
218
218
  result[key] = await resolveProtocolValue(value, protocols, options);
219
+ } else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
220
+ // Recursively resolve nested plain objects (e.g., headers: { "...": "globalThis://key" })
221
+ // Only recurse into plain objects — skip DOM elements, class instances, etc.
222
+ const proto = Object.getPrototypeOf(value);
223
+ if (proto === Object.prototype || proto === null) {
224
+ result[key] = await resolveValues(value, source, options);
225
+ } else {
226
+ result[key] = value;
227
+ }
219
228
  } else {
220
229
  result[key] = value;
221
230
  }