@oscarpalmer/atoms 0.197.0 → 0.199.0

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.
@@ -1,35 +1,24 @@
1
1
  import { isArrayOrPlainObject, isTypedArray } from "../internal/is.mjs";
2
- import { getSelfHandlers } from "../internal/value/handlers.mjs";
2
+ import { createSelfHandlers } from "../internal/value/handlers.mjs";
3
3
  //#region src/value/clone.ts
4
4
  const CLONE_NAME = "clone";
5
5
  function clone(value, options) {
6
+ return cloneAny(value, { copy: false }, 0, options);
7
+ }
8
+ function cloneAny(value, parameters, depth, options) {
6
9
  switch (true) {
7
- case value === null:
8
- case value === void 0:
9
- case typeof value === "bigint":
10
- case typeof value === "boolean":
11
- case typeof value === "number":
12
- case typeof value === "string": return value;
10
+ case value === null || CLONE_PRIMITIVES[typeof value]: return value;
13
11
  case value instanceof Date: return new Date(value.getTime());
14
- default: return cloneAny(value, getCloneParameters(options), 0);
12
+ case typeof value === "function":
13
+ parameters.options ??= createCloneOptions(options);
14
+ return parameters.options.copyFunctions ? value : void 0;
15
+ case typeof value === "symbol":
16
+ parameters.options ??= createCloneOptions(options);
17
+ return parameters.options.copySymbols ? value : Symbol(value.description);
15
18
  }
16
- }
17
- clone.handlers = getSelfHandlers(clone, {
18
- callback: tryStructuredClone,
19
- method: CLONE_NAME
20
- });
21
- clone.deregister = deregisterCloner;
22
- clone.register = registerCloner;
23
- function cloneAny(value, parameters, depth) {
19
+ parameters.options ??= createCloneOptions(options);
20
+ parameters.references ??= /* @__PURE__ */ new WeakMap();
24
21
  switch (true) {
25
- case value == null:
26
- case typeof value === "bigint":
27
- case typeof value === "boolean":
28
- case typeof value === "number":
29
- case typeof value === "string": return value;
30
- case value instanceof Date: return new Date(value.getTime());
31
- case typeof value === "function": return parameters.options?.copyFunctions ? value : void 0;
32
- case typeof value === "symbol": return parameters.options?.copySymbols ? value : Symbol(value.description);
33
22
  case parameters.references.has(value): return parameters.references.get(value);
34
23
  case value instanceof ArrayBuffer: return cloneArrayBuffer(value, parameters, depth);
35
24
  case value instanceof DataView: return cloneDataView(value, parameters, depth);
@@ -39,18 +28,18 @@ function cloneAny(value, parameters, depth) {
39
28
  case value instanceof Set: return cloneSet(value, parameters, depth);
40
29
  case isArrayOrPlainObject(value): return cloneObject(value, parameters, depth);
41
30
  case isTypedArray(value): return cloneTypedArray(value, parameters, depth);
42
- default: return clone.handlers.handle(value, parameters, depth);
31
+ default: return parameters.copy ? value : clone.handlers.handle(value, parameters, depth);
43
32
  }
44
33
  }
45
34
  function cloneArrayBuffer(value, parameters, depth) {
46
- if (depth >= CLONE_MAX_DEPTH) return value;
35
+ if (parameters.copy || depth >= CLONE_MAX_DEPTH) return value;
47
36
  const cloned = new ArrayBuffer(value.byteLength);
48
37
  new Uint8Array(cloned).set(new Uint8Array(value));
49
38
  parameters.references.set(value, cloned);
50
39
  return cloned;
51
40
  }
52
41
  function cloneDataView(value, parameters, depth) {
53
- if (depth >= CLONE_MAX_DEPTH) return value;
42
+ if (parameters.copy || depth >= CLONE_MAX_DEPTH) return value;
54
43
  const buffer = cloneArrayBuffer(value.buffer, parameters, depth);
55
44
  const cloned = new DataView(buffer, value.byteOffset, value.byteLength);
56
45
  parameters.references.set(value, cloned);
@@ -58,22 +47,22 @@ function cloneDataView(value, parameters, depth) {
58
47
  }
59
48
  function cloneMap(map, parameters, depth) {
60
49
  if (depth >= CLONE_MAX_DEPTH) return map;
61
- const flat = parameters.options?.flat;
50
+ if (parameters.copy) return new Map(map);
62
51
  const cloned = /* @__PURE__ */ new Map();
63
- const entries = map.entries();
64
- for (const entry of entries) cloned.set(flat ? entry[0] : cloneAny(entry[0], parameters, depth + 1), flat ? entry[1] : cloneAny(entry[1], parameters, depth + 1));
52
+ for (const [key, value] of map.entries()) cloned.set(cloneAny(key, parameters, depth + 1), cloneAny(value, parameters, depth + 1));
65
53
  parameters.references.set(map, cloned);
66
54
  return cloned;
67
55
  }
68
56
  function cloneNode(node, parameters, depth) {
69
- if (depth >= CLONE_MAX_DEPTH) return node;
57
+ if (parameters.copy || depth >= CLONE_MAX_DEPTH) return node;
70
58
  const cloned = node.cloneNode(true);
71
59
  parameters.references.set(node, cloned);
72
60
  return cloned;
73
61
  }
74
62
  function cloneObject(value, parameters, depth) {
63
+ if (depth >= CLONE_MAX_DEPTH) return value;
75
64
  const isArray = Array.isArray(value);
76
- if (parameters.options?.flat || depth >= CLONE_MAX_DEPTH) return isArray ? value.slice() : { ...value };
65
+ if (parameters.copy) return isArray ? value.slice() : { ...value };
77
66
  const cloned = isArray ? [] : {};
78
67
  const keys = isArray ? void 0 : Object.keys(value);
79
68
  const { length } = keys ?? value;
@@ -85,7 +74,7 @@ function cloneObject(value, parameters, depth) {
85
74
  return cloned;
86
75
  }
87
76
  function cloneRegularExpression(value, parameters, depth) {
88
- if (depth >= CLONE_MAX_DEPTH) return value;
77
+ if (parameters.copy || depth >= CLONE_MAX_DEPTH) return value;
89
78
  const cloned = new RegExp(value.source, value.flags);
90
79
  cloned.lastIndex = value.lastIndex;
91
80
  parameters.references.set(value, cloned);
@@ -93,30 +82,31 @@ function cloneRegularExpression(value, parameters, depth) {
93
82
  }
94
83
  function cloneSet(set, parameters, depth) {
95
84
  if (depth >= CLONE_MAX_DEPTH) return set;
85
+ if (parameters.copy) return new Set(set);
96
86
  const cloned = /* @__PURE__ */ new Set();
97
- const values = [...set.values()];
98
- const { length } = values;
99
- for (let index = 0; index < length; index += 1) cloned.add(parameters.options?.flat ? values[index] : cloneAny(values[index], parameters, depth + 1));
87
+ for (const value of set.values()) cloned.add(cloneAny(value, parameters, depth + 1));
100
88
  parameters.references.set(set, cloned);
101
89
  return cloned;
102
90
  }
103
91
  function cloneTypedArray(value, parameters, depth) {
104
- if (depth >= CLONE_MAX_DEPTH) return value;
92
+ if (parameters.copy || depth >= CLONE_MAX_DEPTH) return value;
105
93
  const cloned = new value.constructor(value);
106
94
  parameters.references.set(value, cloned);
107
95
  return cloned;
108
96
  }
109
- /**
110
- * Copy any kind of value
111
- *
112
- * - Clones the value shallowly, without cloning nested values
113
- * - To copy a value deeply, use `clone` instead
114
- *
115
- * @param value Value to copy
116
- * @returns Copied value
117
- */
118
97
  function copy(value) {
119
- return clone(value, CLONE_COPY_OPTIONS);
98
+ return cloneAny(value, {
99
+ copy: true,
100
+ options: CLONE_COPY_OPTIONS,
101
+ references: void 0
102
+ }, 0);
103
+ }
104
+ function createCloneOptions(input) {
105
+ if (typeof input !== "object" || input === null) return CLONE_DEFAULT_OPTIONS;
106
+ return {
107
+ copyFunctions: input.copyFunctions === true,
108
+ copySymbols: input.copySymbols === true
109
+ };
120
110
  }
121
111
  /**
122
112
  * Deregister a clone handler for a specific class
@@ -128,24 +118,29 @@ function copy(value) {
128
118
  function deregisterCloner(constructor) {
129
119
  clone.handlers.deregister(constructor);
130
120
  }
131
- function getCloneOptions(input) {
132
- if (typeof input === "boolean") return {
133
- copyFunctions: false,
134
- copySymbols: false,
135
- flat: input === true
136
- };
137
- if (typeof input !== "object" || input === null) return CLONE_DEFAULT_OPTIONS;
138
- return {
139
- copyFunctions: input.copyFunctions === true,
140
- copySymbols: input.copySymbols === true,
141
- flat: input.flat === true
142
- };
143
- }
144
- function getCloneParameters(input) {
145
- return {
146
- options: getCloneOptions(input),
147
- references: /* @__PURE__ */ new WeakMap()
148
- };
121
+ /**
122
+ * Create a cloner with predefined options
123
+ *
124
+ * _Available as `initializeCloner` and `clone.initialize`_
125
+ *
126
+ * @param options Clone options
127
+ * @returns Cloner function
128
+ */
129
+ function initializeCloner(options) {
130
+ const opts = createCloneOptions(options);
131
+ function cloner(value) {
132
+ return cloneAny(value, {
133
+ copy: false,
134
+ options: opts
135
+ }, 0);
136
+ }
137
+ cloner.deregister = deregisterCloner;
138
+ cloner.register = registerCloner;
139
+ Object.defineProperties(cloner, {
140
+ deregister: { value: deregisterCloner },
141
+ register: { value: registerCloner }
142
+ });
143
+ return cloner;
149
144
  }
150
145
  /**
151
146
  * Register a clone handler for a specific class
@@ -162,23 +157,45 @@ function tryStructuredClone(value, parameters, depth) {
162
157
  if (depth >= CLONE_MAX_DEPTH) return value;
163
158
  try {
164
159
  const cloned = structuredClone(value);
165
- parameters.references?.set(value, cloned);
160
+ parameters.references.set(value, cloned);
166
161
  return cloned;
167
162
  } catch {
168
- parameters.references?.set(value, value);
163
+ parameters.references.set(value, value);
169
164
  return value;
170
165
  }
171
166
  }
172
167
  const CLONE_COPY_OPTIONS = {
173
168
  copyFunctions: true,
174
- copySymbols: true,
175
- flat: true
169
+ copySymbols: true
176
170
  };
177
171
  const CLONE_DEFAULT_OPTIONS = {
178
172
  copyFunctions: false,
179
- copySymbols: false,
180
- flat: false
173
+ copySymbols: false
181
174
  };
182
175
  const CLONE_MAX_DEPTH = 100;
176
+ const cloneHandlers = createSelfHandlers(clone, {
177
+ callback: tryStructuredClone,
178
+ method: CLONE_NAME
179
+ });
180
+ const CLONE_PRIMITIVES = {
181
+ bigint: true,
182
+ boolean: true,
183
+ function: false,
184
+ number: true,
185
+ object: false,
186
+ string: true,
187
+ symbol: false,
188
+ undefined: true
189
+ };
190
+ clone.deregister = deregisterCloner;
191
+ clone.handlers = cloneHandlers;
192
+ clone.initialize = initializeCloner;
193
+ clone.register = registerCloner;
194
+ Object.defineProperties(clone, {
195
+ deregister: { value: deregisterCloner },
196
+ handlers: { value: cloneHandlers },
197
+ initialize: { value: initializeCloner },
198
+ register: { value: registerCloner }
199
+ });
183
200
  //#endregion
184
- export { clone, copy, deregisterCloner, registerCloner };
201
+ export { clone, copy, deregisterCloner, initializeCloner, registerCloner };
@@ -9,11 +9,11 @@ import { isArrayOrPlainObject } from "../internal/is.mjs";
9
9
  * @returns Assigned value
10
10
  */
11
11
  function assign(to, from, options) {
12
- const actual = getMergeOptions(options);
12
+ const actual = createMergeOptions(options);
13
13
  actual.assignValues = true;
14
14
  return mergeValues([to, ...from], actual);
15
15
  }
16
- function getMergeOptions(options) {
16
+ function createMergeOptions(options) {
17
17
  const actual = {
18
18
  assignValues: false,
19
19
  replaceableObjects: void 0,
@@ -40,7 +40,7 @@ function getReplaceableObjects(value) {
40
40
  * @returns Assigner function
41
41
  */
42
42
  function initializeAssigner(options) {
43
- const actual = getMergeOptions(options);
43
+ const actual = createMergeOptions(options);
44
44
  actual.assignValues = true;
45
45
  return ((to, from) => mergeValues([to, ...from], actual));
46
46
  }
@@ -53,7 +53,7 @@ function initializeAssigner(options) {
53
53
  * @returns Merger function
54
54
  */
55
55
  function initializeMerger(options) {
56
- const actual = getMergeOptions(options);
56
+ const actual = createMergeOptions(options);
57
57
  return ((values) => mergeValues(values, actual));
58
58
  }
59
59
  /**
@@ -64,7 +64,7 @@ function initializeMerger(options) {
64
64
  * @returns Merged value
65
65
  */
66
66
  function merge(values, options) {
67
- return mergeValues(values, getMergeOptions(options));
67
+ return mergeValues(values, createMergeOptions(options));
68
68
  }
69
69
  function mergeObjects(values, options, destination, prefix) {
70
70
  const { length } = values;
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@oscarpalmer/atoms",
3
- "version": "0.197.0",
3
+ "version": "0.199.0",
4
4
  "description": "Atomic utilities for making your JavaScript better.",
5
5
  "keywords": [
6
6
  "array",
7
+ "clone",
7
8
  "color",
8
9
  "helper",
9
10
  "observable",
@@ -282,7 +283,7 @@
282
283
  "@vitest/coverage-istanbul": "^4.1",
283
284
  "eslint": "^10.9",
284
285
  "jsdom": "^30",
285
- "tsdown": "^0.22",
286
+ "tsdown": "^0.23",
286
287
  "typescript": "^6",
287
288
  "vite": "npm:@voidzero-dev/vite-plus-core@latest",
288
289
  "vite-plus": "latest",