@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.
@@ -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
+ });
@@ -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
+ });
@@ -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.