assign-gingerly 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -84,14 +84,14 @@ class YourEnhancement extends ElementEnhancement(EventTarget){
84
84
  }
85
85
 
86
86
  class BaseRegistry{
87
- define(IBaseRegistryItem | IBaseRegistryItem[]){
87
+ push(IBaseRegistryItem | IBaseRegistryItem[]){
88
88
  ...
89
89
  }
90
90
  }
91
91
 
92
92
  //Here's where the dependency injection mapping takes place
93
93
  const baseRegistry = new BaseRegistry;
94
- baseRegistry.define([
94
+ baseRegistry.push([
95
95
  {
96
96
  map: {
97
97
  [isHappy]: 'isHappy'
@@ -120,12 +120,25 @@ const asyncResult = await assignGingerly({}, {
120
120
  asyncResult.set[isMellow] = false;
121
121
  ```
122
122
 
123
- The assignGingerly searches the registry for any items that has a mapping with a matching symbol of isHappy and isMellow, and if found, sees it already has an instance of the spawn class associated with the first passed in parameter. If no such instance is found, it instantiates one, associates the instance with the first parameter, then sets the property value.
123
+ The assignGingerly searches the registry for any items that has a mapping with a matching symbol of isHappy and isMellow, and if found, sees if it already has an instance of the spawn class associated with the first passed in parameter. If no such instance is found, it instantiates one, associates the instance with the first parameter, then sets the property value.
124
124
 
125
125
  It also adds a lazy property to the first passed in parameter, "set", which returns a proxy, and that proxy watches for symbol references passed in a value, and sets the value from that spawned instance. Again, if the spawned instance is not found, it respawns it.
126
126
 
127
127
  The suggestion to use Symbol.for with a guid, as opposed to just Symbol(), is based on some negative experiences I've had with multiple versions of the same library being referenced, but is not required. Regular symbols could also be used when that risk can be avoided.
128
128
 
129
- Note the first time we mention async. This is only necessary if you wish to work directly with the merged object. This allows for lazy loading of the spawning class, which can be useful for large applications that don't need to download all the classes at once. If you are just "depositing" values into the object, no need to await for anything. Also, the assignGingerly should first do all the class instantiations that are already loaded (where the class constructor is specified in spawn), and then does all the lazy loaded ones.
129
+ Note that the example above is the first time we mention async. This is only necessary if you wish to work directly with the merged object. This allows for lazy loading of the spawning class, which can be useful for large applications that don't need to download all the classes at once. If you are just "depositing" values into the object, no need to await for anything. Also, the assignGingerly should first do all the class instantiations that are already loaded (where the class constructor is specified in spawn), and then does all the lazy loaded ones.
130
+
131
+ ## Support for JSON assignment with Symbol.for symbols
132
+
133
+ ```JavaScript
134
+ const asyncResult = await assignGingerly({}, {
135
+ "[Symbol.for('TFWsx0YH5E6eSfhE7zfLxA')]": true,
136
+ "[Symbol.for('BqnnTPWRHkWdVGWcGQoAiw')]": true,
137
+ '?.style.height': '40px',
138
+ '?.enhancements?.mellowYellow?.madAboutFourteen': true
139
+ }, {
140
+ registry: BaseRegistry
141
+ });
142
+ ```
130
143
 
131
144
 
package/index.d.ts CHANGED
@@ -18,7 +18,7 @@ export interface IAssignGingerlyOptions {
18
18
  */
19
19
  export declare class BaseRegistry {
20
20
  private items;
21
- define(items: IBaseRegistryItem | IBaseRegistryItem[]): void;
21
+ push(items: IBaseRegistryItem | IBaseRegistryItem[]): void;
22
22
  getItems(): IBaseRegistryItem[];
23
23
  findBySymbol(symbol: symbol | string): IBaseRegistryItem | undefined;
24
24
  }
package/index.js CHANGED
@@ -7,7 +7,7 @@ const instanceMap = new WeakMap();
7
7
  */
8
8
  export class BaseRegistry {
9
9
  items = [];
10
- define(items) {
10
+ push(items) {
11
11
  if (Array.isArray(items)) {
12
12
  this.items.push(...items);
13
13
  }
@@ -30,6 +30,22 @@ export class BaseRegistry {
30
30
  });
31
31
  }
32
32
  }
33
+ /**
34
+ * Helper function to check if a string key represents a Symbol.for expression
35
+ */
36
+ function isSymbolForKey(key) {
37
+ return key.startsWith('[Symbol.for(') && key.endsWith(')]');
38
+ }
39
+ /**
40
+ * Helper function to extract the symbol key from a Symbol.for string
41
+ */
42
+ function parseSymbolForKey(key) {
43
+ const match = key.match(/^\[Symbol\.for\(['"](.+)['"]\)\]$/);
44
+ if (match && match[1]) {
45
+ return Symbol.for(match[1]);
46
+ }
47
+ return null;
48
+ }
33
49
  /**
34
50
  * Helper function to parse a path string with ?. notation
35
51
  */
@@ -72,9 +88,30 @@ export async function assignGingerly(target, source, options) {
72
88
  : undefined;
73
89
  // Track promises for async spawning
74
90
  const asyncSpawns = [];
75
- // First pass: handle all non-symbol keys and sync operations
91
+ // Convert Symbol.for string keys to actual symbols
92
+ const processedSource = {};
76
93
  for (const key of Object.keys(source)) {
77
- const value = source[key];
94
+ if (isSymbolForKey(key)) {
95
+ const symbol = parseSymbolForKey(key);
96
+ if (symbol) {
97
+ processedSource[symbol] = source[key];
98
+ }
99
+ else {
100
+ // Invalid Symbol.for format - treat as regular string key
101
+ processedSource[key] = source[key];
102
+ }
103
+ }
104
+ else {
105
+ processedSource[key] = source[key];
106
+ }
107
+ }
108
+ // Copy over actual symbol keys
109
+ for (const sym of Object.getOwnPropertySymbols(source)) {
110
+ processedSource[sym] = source[sym];
111
+ }
112
+ // First pass: handle all non-symbol keys and sync operations
113
+ for (const key of Object.keys(processedSource)) {
114
+ const value = processedSource[key];
78
115
  if (isNestedPath(key)) {
79
116
  const pathParts = parsePath(key);
80
117
  const lastKey = pathParts[pathParts.length - 1];
@@ -104,9 +141,9 @@ export async function assignGingerly(target, source, options) {
104
141
  }
105
142
  }
106
143
  // Second pass: handle symbol keys for dependency injection
107
- const symbols = Object.getOwnPropertySymbols(source);
144
+ const symbols = Object.getOwnPropertySymbols(processedSource);
108
145
  for (const sym of symbols) {
109
- const value = source[sym];
146
+ const value = processedSource[sym];
110
147
  if (registry) {
111
148
  const registryItem = registry.findBySymbol(sym);
112
149
  if (registryItem) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "assign-gingerly",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
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": {
@@ -33,9 +33,9 @@
33
33
  "update": "ncu -u && npm install"
34
34
  },
35
35
  "devDependencies": {
36
- "@playwright/test": "^1.57.0",
37
- "spa-ssi": "0.0.25",
38
- "@types/node": "^24.10.2",
36
+ "@playwright/test": "^1.58.0",
37
+ "spa-ssi": "0.0.26",
38
+ "@types/node": "^25.0.10",
39
39
  "typescript": "^5.9.3"
40
40
  }
41
41
  }