@stackframe/stack-shared 2.7.20 → 2.7.22
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/CHANGELOG.md +12 -0
- package/dist/crud.js +76 -0
- package/dist/hooks/use-strict-memo.js +75 -0
- package/dist/interface/serverInterface.d.ts +1 -1
- package/dist/interface/serverInterface.js +1 -1
- package/dist/known-errors.js +1 -1
- package/dist/utils/arrays.js +75 -1
- package/dist/utils/caches.js +33 -0
- package/dist/utils/compile-time.js +3 -0
- package/dist/utils/dates.js +4 -4
- package/dist/utils/functions.js +15 -0
- package/dist/utils/html.js +28 -0
- package/dist/utils/http.js +29 -0
- package/dist/utils/ips.js +29 -0
- package/dist/utils/json.js +135 -0
- package/dist/utils/maps.js +145 -0
- package/dist/utils/objects.js +69 -0
- package/dist/utils/promises.js +205 -3
- package/dist/utils/proxies.js +72 -0
- package/dist/utils/react.js +82 -0
- package/dist/utils/results.d.ts +5 -3
- package/dist/utils/results.js +220 -6
- package/dist/utils/strings.js +223 -2
- package/dist/utils/unicode.js +13 -0
- package/dist/utils/urls.js +115 -0
- package/dist/utils/uuids.js +30 -0
- package/package.json +1 -1
package/dist/utils/json.js
CHANGED
|
@@ -18,9 +18,144 @@ export function isJson(value) {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
+
import.meta.vitest?.test("isJson", ({ expect }) => {
|
|
22
|
+
// Test primitive values
|
|
23
|
+
expect(isJson(null)).toBe(true);
|
|
24
|
+
expect(isJson(true)).toBe(true);
|
|
25
|
+
expect(isJson(false)).toBe(true);
|
|
26
|
+
expect(isJson(123)).toBe(true);
|
|
27
|
+
expect(isJson("string")).toBe(true);
|
|
28
|
+
// Test arrays
|
|
29
|
+
expect(isJson([])).toBe(true);
|
|
30
|
+
expect(isJson([1, 2, 3])).toBe(true);
|
|
31
|
+
expect(isJson(["a", "b", "c"])).toBe(true);
|
|
32
|
+
expect(isJson([1, "a", true, null])).toBe(true);
|
|
33
|
+
expect(isJson([1, [2, 3], { a: "b" }])).toBe(true);
|
|
34
|
+
// Test objects
|
|
35
|
+
expect(isJson({})).toBe(true);
|
|
36
|
+
expect(isJson({ a: 1, b: 2 })).toBe(true);
|
|
37
|
+
expect(isJson({ a: "string", b: true, c: null })).toBe(true);
|
|
38
|
+
expect(isJson({ a: [1, 2, 3], b: { c: "d" } })).toBe(true);
|
|
39
|
+
// Test invalid JSON values
|
|
40
|
+
expect(isJson(undefined)).toBe(false);
|
|
41
|
+
expect(isJson(() => { })).toBe(false);
|
|
42
|
+
expect(isJson(Symbol())).toBe(false);
|
|
43
|
+
expect(isJson(BigInt(123))).toBe(false);
|
|
44
|
+
// Test arrays with invalid JSON values
|
|
45
|
+
expect(isJson([1, undefined, 3])).toBe(false);
|
|
46
|
+
expect(isJson([1, () => { }, 3])).toBe(false);
|
|
47
|
+
// Test objects with invalid JSON values
|
|
48
|
+
expect(isJson({ a: 1, b: undefined })).toBe(false);
|
|
49
|
+
expect(isJson({ a: 1, b: () => { } })).toBe(false);
|
|
50
|
+
});
|
|
21
51
|
export function parseJson(json) {
|
|
22
52
|
return Result.fromThrowing(() => JSON.parse(json));
|
|
23
53
|
}
|
|
54
|
+
import.meta.vitest?.test("parseJson", ({ expect }) => {
|
|
55
|
+
// Test valid JSON strings
|
|
56
|
+
const nullResult = parseJson("null");
|
|
57
|
+
expect(nullResult.status).toBe("ok");
|
|
58
|
+
if (nullResult.status === "ok") {
|
|
59
|
+
expect(nullResult.data).toBe(null);
|
|
60
|
+
}
|
|
61
|
+
const trueResult = parseJson("true");
|
|
62
|
+
expect(trueResult.status).toBe("ok");
|
|
63
|
+
if (trueResult.status === "ok") {
|
|
64
|
+
expect(trueResult.data).toBe(true);
|
|
65
|
+
}
|
|
66
|
+
const numberResult = parseJson("123");
|
|
67
|
+
expect(numberResult.status).toBe("ok");
|
|
68
|
+
if (numberResult.status === "ok") {
|
|
69
|
+
expect(numberResult.data).toBe(123);
|
|
70
|
+
}
|
|
71
|
+
const stringResult = parseJson('"string"');
|
|
72
|
+
expect(stringResult.status).toBe("ok");
|
|
73
|
+
if (stringResult.status === "ok") {
|
|
74
|
+
expect(stringResult.data).toBe("string");
|
|
75
|
+
}
|
|
76
|
+
const emptyArrayResult = parseJson("[]");
|
|
77
|
+
expect(emptyArrayResult.status).toBe("ok");
|
|
78
|
+
if (emptyArrayResult.status === "ok") {
|
|
79
|
+
expect(emptyArrayResult.data).toEqual([]);
|
|
80
|
+
}
|
|
81
|
+
const arrayResult = parseJson("[1,2,3]");
|
|
82
|
+
expect(arrayResult.status).toBe("ok");
|
|
83
|
+
if (arrayResult.status === "ok") {
|
|
84
|
+
expect(arrayResult.data).toEqual([1, 2, 3]);
|
|
85
|
+
}
|
|
86
|
+
const emptyObjectResult = parseJson("{}");
|
|
87
|
+
expect(emptyObjectResult.status).toBe("ok");
|
|
88
|
+
if (emptyObjectResult.status === "ok") {
|
|
89
|
+
expect(emptyObjectResult.data).toEqual({});
|
|
90
|
+
}
|
|
91
|
+
const objectResult = parseJson('{"a":1,"b":"string"}');
|
|
92
|
+
expect(objectResult.status).toBe("ok");
|
|
93
|
+
if (objectResult.status === "ok") {
|
|
94
|
+
expect(objectResult.data).toEqual({ a: 1, b: "string" });
|
|
95
|
+
}
|
|
96
|
+
// Test invalid JSON strings
|
|
97
|
+
expect(parseJson("").status).toBe("error");
|
|
98
|
+
expect(parseJson("undefined").status).toBe("error");
|
|
99
|
+
expect(parseJson("{").status).toBe("error");
|
|
100
|
+
expect(parseJson('{"a":1,}').status).toBe("error");
|
|
101
|
+
expect(parseJson("function(){}").status).toBe("error");
|
|
102
|
+
});
|
|
24
103
|
export function stringifyJson(json) {
|
|
25
104
|
return Result.fromThrowing(() => JSON.stringify(json));
|
|
26
105
|
}
|
|
106
|
+
import.meta.vitest?.test("stringifyJson", ({ expect }) => {
|
|
107
|
+
// Test primitive values
|
|
108
|
+
const nullResult = stringifyJson(null);
|
|
109
|
+
expect(nullResult.status).toBe("ok");
|
|
110
|
+
if (nullResult.status === "ok") {
|
|
111
|
+
expect(nullResult.data).toBe("null");
|
|
112
|
+
}
|
|
113
|
+
const trueResult = stringifyJson(true);
|
|
114
|
+
expect(trueResult.status).toBe("ok");
|
|
115
|
+
if (trueResult.status === "ok") {
|
|
116
|
+
expect(trueResult.data).toBe("true");
|
|
117
|
+
}
|
|
118
|
+
const numberResult = stringifyJson(123);
|
|
119
|
+
expect(numberResult.status).toBe("ok");
|
|
120
|
+
if (numberResult.status === "ok") {
|
|
121
|
+
expect(numberResult.data).toBe("123");
|
|
122
|
+
}
|
|
123
|
+
const stringResult = stringifyJson("string");
|
|
124
|
+
expect(stringResult.status).toBe("ok");
|
|
125
|
+
if (stringResult.status === "ok") {
|
|
126
|
+
expect(stringResult.data).toBe('"string"');
|
|
127
|
+
}
|
|
128
|
+
// Test arrays
|
|
129
|
+
const emptyArrayResult = stringifyJson([]);
|
|
130
|
+
expect(emptyArrayResult.status).toBe("ok");
|
|
131
|
+
if (emptyArrayResult.status === "ok") {
|
|
132
|
+
expect(emptyArrayResult.data).toBe("[]");
|
|
133
|
+
}
|
|
134
|
+
const arrayResult = stringifyJson([1, 2, 3]);
|
|
135
|
+
expect(arrayResult.status).toBe("ok");
|
|
136
|
+
if (arrayResult.status === "ok") {
|
|
137
|
+
expect(arrayResult.data).toBe("[1,2,3]");
|
|
138
|
+
}
|
|
139
|
+
// Test objects
|
|
140
|
+
const emptyObjectResult = stringifyJson({});
|
|
141
|
+
expect(emptyObjectResult.status).toBe("ok");
|
|
142
|
+
if (emptyObjectResult.status === "ok") {
|
|
143
|
+
expect(emptyObjectResult.data).toBe("{}");
|
|
144
|
+
}
|
|
145
|
+
const objectResult = stringifyJson({ a: 1, b: "string" });
|
|
146
|
+
expect(objectResult.status).toBe("ok");
|
|
147
|
+
if (objectResult.status === "ok") {
|
|
148
|
+
expect(objectResult.data).toBe('{"a":1,"b":"string"}');
|
|
149
|
+
}
|
|
150
|
+
// Test nested structures
|
|
151
|
+
const nested = { a: [1, 2, 3], b: { c: "d" } };
|
|
152
|
+
const nestedResult = stringifyJson(nested);
|
|
153
|
+
expect(nestedResult.status).toBe("ok");
|
|
154
|
+
if (nestedResult.status === "ok") {
|
|
155
|
+
expect(nestedResult.data).toBe('{"a":[1,2,3],"b":{"c":"d"}}');
|
|
156
|
+
}
|
|
157
|
+
// Test circular references (should error)
|
|
158
|
+
const circular = { a: 1 };
|
|
159
|
+
circular.self = circular;
|
|
160
|
+
expect(stringifyJson(circular).status).toBe("error");
|
|
161
|
+
});
|
package/dist/utils/maps.js
CHANGED
|
@@ -13,6 +13,20 @@ export class WeakRefIfAvailable {
|
|
|
13
13
|
return this._ref.deref();
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
|
+
import.meta.vitest?.test("WeakRefIfAvailable", ({ expect }) => {
|
|
17
|
+
// Test with an object
|
|
18
|
+
const obj = { id: 1, name: "test" };
|
|
19
|
+
const weakRef = new WeakRefIfAvailable(obj);
|
|
20
|
+
// Test deref returns the original object
|
|
21
|
+
expect(weakRef.deref()).toBe(obj);
|
|
22
|
+
// Test with a different object
|
|
23
|
+
const obj2 = { id: 2, name: "test2" };
|
|
24
|
+
const weakRef2 = new WeakRefIfAvailable(obj2);
|
|
25
|
+
expect(weakRef2.deref()).toBe(obj2);
|
|
26
|
+
expect(weakRef2.deref()).not.toBe(obj);
|
|
27
|
+
// We can't easily test garbage collection in this environment,
|
|
28
|
+
// but we can verify the basic functionality works
|
|
29
|
+
});
|
|
16
30
|
/**
|
|
17
31
|
* A WeakMap-like object that can be iterated over.
|
|
18
32
|
*
|
|
@@ -62,6 +76,56 @@ export class IterableWeakMap {
|
|
|
62
76
|
}
|
|
63
77
|
}
|
|
64
78
|
_a = Symbol.toStringTag;
|
|
79
|
+
import.meta.vitest?.test("IterableWeakMap", ({ expect }) => {
|
|
80
|
+
// Test basic functionality
|
|
81
|
+
const map = new IterableWeakMap();
|
|
82
|
+
// Create object keys
|
|
83
|
+
const obj1 = { id: 1 };
|
|
84
|
+
const obj2 = { id: 2 };
|
|
85
|
+
// Test set and get
|
|
86
|
+
map.set(obj1, "value1");
|
|
87
|
+
expect(map.get(obj1)).toBe("value1");
|
|
88
|
+
// Test has
|
|
89
|
+
expect(map.has(obj1)).toBe(true);
|
|
90
|
+
expect(map.has(obj2)).toBe(false);
|
|
91
|
+
expect(map.has({ id: 1 })).toBe(false); // Different object with same content
|
|
92
|
+
// Test with multiple keys
|
|
93
|
+
map.set(obj2, "value2");
|
|
94
|
+
expect(map.get(obj2)).toBe("value2");
|
|
95
|
+
expect(map.get(obj1)).toBe("value1"); // Original still exists
|
|
96
|
+
// Test delete
|
|
97
|
+
expect(map.delete(obj1)).toBe(true);
|
|
98
|
+
expect(map.has(obj1)).toBe(false);
|
|
99
|
+
expect(map.get(obj1)).toBeUndefined();
|
|
100
|
+
expect(map.has(obj2)).toBe(true); // Other key still exists
|
|
101
|
+
// Test delete non-existent key
|
|
102
|
+
expect(map.delete({ id: 3 })).toBe(false);
|
|
103
|
+
// Test iteration
|
|
104
|
+
const iterMap = new IterableWeakMap();
|
|
105
|
+
const iterObj1 = { id: 1 };
|
|
106
|
+
const iterObj2 = { id: 2 };
|
|
107
|
+
const iterObj3 = { id: 3 };
|
|
108
|
+
iterMap.set(iterObj1, 1);
|
|
109
|
+
iterMap.set(iterObj2, 2);
|
|
110
|
+
iterMap.set(iterObj3, 3);
|
|
111
|
+
const entries = Array.from(iterMap);
|
|
112
|
+
expect(entries.length).toBe(3);
|
|
113
|
+
// Find entries by their values since we can't directly compare objects in the array
|
|
114
|
+
const values = entries.map(entry => entry[1]);
|
|
115
|
+
expect(values).toContain(1);
|
|
116
|
+
expect(values).toContain(2);
|
|
117
|
+
expect(values).toContain(3);
|
|
118
|
+
// Test constructor with entries
|
|
119
|
+
const initialEntries = [
|
|
120
|
+
[{ id: 4 }, "initial1"],
|
|
121
|
+
[{ id: 5 }, "initial2"]
|
|
122
|
+
];
|
|
123
|
+
const mapWithEntries = new IterableWeakMap(initialEntries);
|
|
124
|
+
// We can't directly access the initial entries since they're different object references
|
|
125
|
+
// But we can verify the map has the correct number of entries
|
|
126
|
+
const entriesFromConstructor = Array.from(mapWithEntries);
|
|
127
|
+
expect(entriesFromConstructor.length).toBe(2);
|
|
128
|
+
});
|
|
65
129
|
/**
|
|
66
130
|
* A map that is a IterableWeakMap for object keys and a regular Map for primitive keys. Also provides iteration over both
|
|
67
131
|
* object and primitive keys.
|
|
@@ -117,6 +181,45 @@ export class MaybeWeakMap {
|
|
|
117
181
|
}
|
|
118
182
|
}
|
|
119
183
|
_b = Symbol.toStringTag;
|
|
184
|
+
import.meta.vitest?.test("MaybeWeakMap", ({ expect }) => {
|
|
185
|
+
// Test with primitive keys
|
|
186
|
+
const map = new MaybeWeakMap();
|
|
187
|
+
// Test with string keys
|
|
188
|
+
map.set("key1", 1);
|
|
189
|
+
map.set("key2", 2);
|
|
190
|
+
expect(map.get("key1")).toBe(1);
|
|
191
|
+
expect(map.get("key2")).toBe(2);
|
|
192
|
+
expect(map.has("key1")).toBe(true);
|
|
193
|
+
expect(map.has("nonexistent")).toBe(false);
|
|
194
|
+
// Test with object keys
|
|
195
|
+
const obj1 = { id: 1 };
|
|
196
|
+
const obj2 = { id: 2 };
|
|
197
|
+
map.set(obj1, 3);
|
|
198
|
+
map.set(obj2, 4);
|
|
199
|
+
expect(map.get(obj1)).toBe(3);
|
|
200
|
+
expect(map.get(obj2)).toBe(4);
|
|
201
|
+
expect(map.has(obj1)).toBe(true);
|
|
202
|
+
// Test delete with primitive key
|
|
203
|
+
expect(map.delete("key1")).toBe(true);
|
|
204
|
+
expect(map.has("key1")).toBe(false);
|
|
205
|
+
expect(map.delete("nonexistent")).toBe(false);
|
|
206
|
+
// Test delete with object key
|
|
207
|
+
expect(map.delete(obj1)).toBe(true);
|
|
208
|
+
expect(map.has(obj1)).toBe(false);
|
|
209
|
+
// Test iteration
|
|
210
|
+
const entries = Array.from(map);
|
|
211
|
+
expect(entries.length).toBe(2);
|
|
212
|
+
expect(entries).toContainEqual(["key2", 2]);
|
|
213
|
+
expect(entries).toContainEqual([obj2, 4]);
|
|
214
|
+
// Test constructor with entries
|
|
215
|
+
const initialEntries = [
|
|
216
|
+
["initial1", 10],
|
|
217
|
+
[{ id: 3 }, 20]
|
|
218
|
+
];
|
|
219
|
+
const mapWithEntries = new MaybeWeakMap(initialEntries);
|
|
220
|
+
expect(mapWithEntries.get("initial1")).toBe(10);
|
|
221
|
+
expect(mapWithEntries.get(initialEntries[1][0])).toBe(20);
|
|
222
|
+
});
|
|
120
223
|
/**
|
|
121
224
|
* A map that stores values indexed by an array of keys. If the keys are objects and the environment supports WeakRefs,
|
|
122
225
|
* they are stored in a WeakMap.
|
|
@@ -198,3 +301,45 @@ export class DependenciesMap {
|
|
|
198
301
|
}
|
|
199
302
|
}
|
|
200
303
|
_c = Symbol.toStringTag;
|
|
304
|
+
import.meta.vitest?.test("DependenciesMap", ({ expect }) => {
|
|
305
|
+
// Test basic functionality
|
|
306
|
+
const map = new DependenciesMap();
|
|
307
|
+
// Test set and get
|
|
308
|
+
map.set(["key", 1], "value1");
|
|
309
|
+
expect(map.get(["key", 1])).toBe("value1");
|
|
310
|
+
// Test has
|
|
311
|
+
expect(map.has(["key", 1])).toBe(true);
|
|
312
|
+
expect(map.has(["key", 2])).toBe(false);
|
|
313
|
+
// Test with different dependencies
|
|
314
|
+
map.set(["key", 2], "value2");
|
|
315
|
+
expect(map.get(["key", 2])).toBe("value2");
|
|
316
|
+
expect(map.get(["key", 1])).toBe("value1"); // Original still exists
|
|
317
|
+
// Test delete
|
|
318
|
+
expect(map.delete(["key", 1])).toBe(true);
|
|
319
|
+
expect(map.has(["key", 1])).toBe(false);
|
|
320
|
+
expect(map.get(["key", 1])).toBeUndefined();
|
|
321
|
+
expect(map.has(["key", 2])).toBe(true); // Other key still exists
|
|
322
|
+
// Test delete non-existent key
|
|
323
|
+
expect(map.delete(["nonexistent", 1])).toBe(false);
|
|
324
|
+
// Test clear
|
|
325
|
+
map.clear();
|
|
326
|
+
expect(map.has(["key", 2])).toBe(false);
|
|
327
|
+
// Test with object keys
|
|
328
|
+
const objMap = new DependenciesMap();
|
|
329
|
+
const obj1 = { id: 1 };
|
|
330
|
+
const obj2 = { id: 2 };
|
|
331
|
+
objMap.set([obj1, 1], "object1");
|
|
332
|
+
objMap.set([obj2, 2], "object2");
|
|
333
|
+
expect(objMap.get([obj1, 1])).toBe("object1");
|
|
334
|
+
expect(objMap.get([obj2, 2])).toBe("object2");
|
|
335
|
+
// Test iteration
|
|
336
|
+
const iterMap = new DependenciesMap();
|
|
337
|
+
iterMap.set(["a"], 1);
|
|
338
|
+
iterMap.set(["b"], 2);
|
|
339
|
+
iterMap.set(["c"], 3);
|
|
340
|
+
const entries = Array.from(iterMap);
|
|
341
|
+
expect(entries.length).toBe(3);
|
|
342
|
+
expect(entries).toContainEqual([["a"], 1]);
|
|
343
|
+
expect(entries).toContainEqual([["b"], 2]);
|
|
344
|
+
expect(entries).toContainEqual([["c"], 3]);
|
|
345
|
+
});
|
package/dist/utils/objects.js
CHANGED
|
@@ -119,18 +119,87 @@ import.meta.vitest?.test("deepPlainClone", ({ expect }) => {
|
|
|
119
119
|
export function typedEntries(obj) {
|
|
120
120
|
return Object.entries(obj);
|
|
121
121
|
}
|
|
122
|
+
import.meta.vitest?.test("typedEntries", ({ expect }) => {
|
|
123
|
+
expect(typedEntries({})).toEqual([]);
|
|
124
|
+
expect(typedEntries({ a: 1, b: 2 })).toEqual([["a", 1], ["b", 2]]);
|
|
125
|
+
expect(typedEntries({ a: "hello", b: true, c: null })).toEqual([["a", "hello"], ["b", true], ["c", null]]);
|
|
126
|
+
// Test with object containing methods
|
|
127
|
+
const objWithMethod = { a: 1, b: () => "test" };
|
|
128
|
+
const entries = typedEntries(objWithMethod);
|
|
129
|
+
expect(entries.length).toBe(2);
|
|
130
|
+
expect(entries[0][0]).toBe("a");
|
|
131
|
+
expect(entries[0][1]).toBe(1);
|
|
132
|
+
expect(entries[1][0]).toBe("b");
|
|
133
|
+
expect(typeof entries[1][1]).toBe("function");
|
|
134
|
+
});
|
|
122
135
|
export function typedFromEntries(entries) {
|
|
123
136
|
return Object.fromEntries(entries);
|
|
124
137
|
}
|
|
138
|
+
import.meta.vitest?.test("typedFromEntries", ({ expect }) => {
|
|
139
|
+
expect(typedFromEntries([])).toEqual({});
|
|
140
|
+
expect(typedFromEntries([["a", 1], ["b", 2]])).toEqual({ a: 1, b: 2 });
|
|
141
|
+
// Test with mixed types (using type assertion)
|
|
142
|
+
const mixedEntries = [["a", "hello"], ["b", true], ["c", null]];
|
|
143
|
+
const mixedObj = typedFromEntries(mixedEntries);
|
|
144
|
+
expect(mixedObj).toEqual({ a: "hello", b: true, c: null });
|
|
145
|
+
// Test with function values
|
|
146
|
+
const fn = () => "test";
|
|
147
|
+
const fnEntries = [["a", 1], ["b", fn]];
|
|
148
|
+
const obj = typedFromEntries(fnEntries);
|
|
149
|
+
expect(obj.a).toBe(1);
|
|
150
|
+
expect(typeof obj.b).toBe("function");
|
|
151
|
+
// Type assertion needed for the function call
|
|
152
|
+
expect(obj.b()).toBe("test");
|
|
153
|
+
});
|
|
125
154
|
export function typedKeys(obj) {
|
|
126
155
|
return Object.keys(obj);
|
|
127
156
|
}
|
|
157
|
+
import.meta.vitest?.test("typedKeys", ({ expect }) => {
|
|
158
|
+
expect(typedKeys({})).toEqual([]);
|
|
159
|
+
expect(typedKeys({ a: 1, b: 2 })).toEqual(["a", "b"]);
|
|
160
|
+
expect(typedKeys({ a: "hello", b: true, c: null })).toEqual(["a", "b", "c"]);
|
|
161
|
+
// Test with object containing methods
|
|
162
|
+
const objWithMethod = { a: 1, b: () => "test" };
|
|
163
|
+
expect(typedKeys(objWithMethod)).toEqual(["a", "b"]);
|
|
164
|
+
});
|
|
128
165
|
export function typedValues(obj) {
|
|
129
166
|
return Object.values(obj);
|
|
130
167
|
}
|
|
168
|
+
import.meta.vitest?.test("typedValues", ({ expect }) => {
|
|
169
|
+
expect(typedValues({})).toEqual([]);
|
|
170
|
+
expect(typedValues({ a: 1, b: 2 })).toEqual([1, 2]);
|
|
171
|
+
const mixedObj = { a: "hello", b: true, c: null };
|
|
172
|
+
expect(typedValues(mixedObj)).toEqual(["hello", true, null]);
|
|
173
|
+
const fn = () => "test";
|
|
174
|
+
const objWithMethod = { a: 1, b: fn };
|
|
175
|
+
const values = typedValues(objWithMethod);
|
|
176
|
+
expect(values.length).toBe(2);
|
|
177
|
+
expect(values[0]).toBe(1);
|
|
178
|
+
expect(typeof values[1]).toBe("function");
|
|
179
|
+
// Need to cast to the correct type
|
|
180
|
+
const fnValue = values[1];
|
|
181
|
+
expect(fnValue()).toBe("test");
|
|
182
|
+
});
|
|
131
183
|
export function typedAssign(target, source) {
|
|
132
184
|
return Object.assign(target, source);
|
|
133
185
|
}
|
|
186
|
+
import.meta.vitest?.test("typedAssign", ({ expect }) => {
|
|
187
|
+
// Test with empty objects
|
|
188
|
+
const emptyTarget = {};
|
|
189
|
+
const emptyResult = typedAssign(emptyTarget, { a: 1 });
|
|
190
|
+
expect(emptyResult).toEqual({ a: 1 });
|
|
191
|
+
expect(emptyResult).toBe(emptyTarget); // Same reference
|
|
192
|
+
// Test with non-empty target
|
|
193
|
+
const target = { a: 1, b: 2 };
|
|
194
|
+
const result = typedAssign(target, { c: 3, d: 4 });
|
|
195
|
+
expect(result).toEqual({ a: 1, b: 2, c: 3, d: 4 });
|
|
196
|
+
expect(result).toBe(target); // Same reference
|
|
197
|
+
// Test with overlapping properties
|
|
198
|
+
const targetWithOverlap = { a: 1, b: 2 };
|
|
199
|
+
const resultWithOverlap = typedAssign(targetWithOverlap, { b: 3, c: 4 });
|
|
200
|
+
expect(resultWithOverlap).toEqual({ a: 1, b: 3, c: 4 });
|
|
201
|
+
expect(resultWithOverlap).toBe(targetWithOverlap); // Same reference
|
|
202
|
+
});
|
|
134
203
|
/**
|
|
135
204
|
* Returns a new object with all undefined values removed. Useful when spreading optional parameters on an object, as
|
|
136
205
|
* TypeScript's `Partial<XYZ>` type allows `undefined` values.
|