@themeparks/typelib 1.1.0 → 1.1.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@themeparks/typelib",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -32,8 +32,9 @@
32
32
  },
33
33
  "files": [
34
34
  "dist/**/*",
35
+ "!dist/__tests__",
36
+ "!dist/run_generate_types.*",
35
37
  "typesrc/**/*",
36
- "src/**/*",
37
38
  "README.md"
38
39
  ],
39
40
  "scripts": {
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=hash.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hash.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/hash.test.ts"],"names":[],"mappings":""}
@@ -1,207 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { hashObject } from '../hash.js';
3
- // ── Helper ─────────────────────────────────────────────────────────────────
4
- /** Assert that two values hash the same */
5
- function same(a, b) {
6
- expect(hashObject(a)).toBe(hashObject(b));
7
- }
8
- /** Assert that two values hash differently */
9
- function different(a, b) {
10
- expect(hashObject(a)).not.toBe(hashObject(b));
11
- }
12
- /** Assert that hashObject throws a TypeError with a message matching the pattern */
13
- function throwsTypeError(value, pattern) {
14
- expect(() => hashObject(value)).toThrow(TypeError);
15
- expect(() => hashObject(value)).toThrow(pattern);
16
- }
17
- // ── Output format ──────────────────────────────────────────────────────────
18
- describe('output format', () => {
19
- it('returns a 64-character lowercase hex string', () => {
20
- expect(hashObject({ x: 1 })).toMatch(/^[0-9a-f]{64}$/);
21
- });
22
- it('is deterministic — same input always produces same output', () => {
23
- const obj = { a: 1, b: [2, 3], c: { d: 'hello' } };
24
- expect(hashObject(obj)).toBe(hashObject(obj));
25
- expect(hashObject(obj)).toBe(hashObject({ a: 1, b: [2, 3], c: { d: 'hello' } }));
26
- });
27
- });
28
- // ── Supported types ────────────────────────────────────────────────────────
29
- describe('supported scalar types', () => {
30
- it('hashes null', () => {
31
- const h = hashObject(null);
32
- expect(h).toMatch(/^[0-9a-f]{64}$/);
33
- });
34
- it('hashes strings', () => {
35
- different('hello', 'world');
36
- same('hello', 'hello');
37
- });
38
- it('hashes numbers', () => {
39
- different(1, 2);
40
- same(42, 42);
41
- });
42
- it('hashes booleans', () => {
43
- different(true, false);
44
- same(true, true);
45
- });
46
- it('differentiates between types with similar string forms', () => {
47
- different(null, 'null');
48
- different(0, false);
49
- different(0, '0');
50
- different(false, 'false');
51
- different(1, '1');
52
- different(null, ''); // null is fine; just checking null != ''
53
- });
54
- it('differentiates NaN from null — NaN throws', () => {
55
- expect(() => hashObject(NaN)).toThrow(TypeError);
56
- // null should still work fine
57
- expect(() => hashObject(null)).not.toThrow();
58
- });
59
- });
60
- describe('supported object types', () => {
61
- it('hashes empty object', () => {
62
- const h = hashObject({});
63
- expect(h).toMatch(/^[0-9a-f]{64}$/);
64
- });
65
- it('hashes empty array', () => {
66
- different([], {});
67
- expect(hashObject([])).toMatch(/^[0-9a-f]{64}$/);
68
- });
69
- it('hashes plain objects', () => {
70
- same({ a: 1 }, { a: 1 });
71
- different({ a: 1 }, { a: 2 });
72
- different({ a: 1 }, { b: 1 });
73
- });
74
- it('hashes arrays (order is preserved)', () => {
75
- same([1, 2, 3], [1, 2, 3]);
76
- different([1, 2, 3], [3, 2, 1]);
77
- });
78
- it('hashes nested objects', () => {
79
- same({ a: { b: { c: 42 } } }, { a: { b: { c: 42 } } });
80
- different({ a: { b: 1 } }, { a: { b: 2 } });
81
- });
82
- it('hashes mixed nested structures', () => {
83
- same({ a: [1, { b: 2 }] }, { a: [1, { b: 2 }] });
84
- different({ a: [1, { b: 2 }] }, { a: [1, { b: 3 }] });
85
- });
86
- it('allows the same object reference in sibling array positions', () => {
87
- const shared = { x: 1 };
88
- expect(() => hashObject([shared, shared])).not.toThrow();
89
- same([shared, shared], [{ x: 1 }, { x: 1 }]);
90
- });
91
- });
92
- // ── Key ordering ───────────────────────────────────────────────────────────
93
- describe('key ordering', () => {
94
- it('produces the same hash regardless of key insertion order (top level)', () => {
95
- same({ a: 1, b: 2 }, { b: 2, a: 1 });
96
- });
97
- it('produces the same hash for deeply nested objects with different key order', () => {
98
- same({ x: { c: 3, a: 1, b: 2 } }, { x: { a: 1, b: 2, c: 3 } });
99
- });
100
- it('produces the same hash for objects inside arrays with different key order', () => {
101
- same([{ z: 26, a: 1 }, { m: 13, b: 2 }], [{ a: 1, z: 26 }, { b: 2, m: 13 }]);
102
- });
103
- it('distinguishes objects with the same keys but different values', () => {
104
- different({ a: 1, b: 2 }, { a: 2, b: 1 });
105
- });
106
- });
107
- // ── Unsupported types — must throw TypeError ───────────────────────────────
108
- describe('unsupported types throw TypeError', () => {
109
- it('throws on undefined (top-level)', () => {
110
- throwsTypeError(undefined, /undefined/);
111
- });
112
- it('throws on undefined inside an object value', () => {
113
- throwsTypeError({ a: undefined }, /undefined/);
114
- });
115
- it('throws on undefined inside a nested object', () => {
116
- throwsTypeError({ a: { b: undefined } }, /undefined/);
117
- });
118
- it('throws on undefined inside an array', () => {
119
- throwsTypeError([1, undefined, 3], /undefined/);
120
- });
121
- it('throws on Date', () => {
122
- throwsTypeError(new Date(), /Date/);
123
- });
124
- it('throws on Date inside an object', () => {
125
- throwsTypeError({ created: new Date() }, /Date/);
126
- });
127
- it('throws on Map', () => {
128
- throwsTypeError(new Map([['a', 1]]), /Map/);
129
- });
130
- it('throws on Map inside an object', () => {
131
- throwsTypeError({ data: new Map() }, /Map/);
132
- });
133
- it('throws on Set', () => {
134
- throwsTypeError(new Set([1, 2, 3]), /Set/);
135
- });
136
- it('throws on Set inside an object', () => {
137
- throwsTypeError({ tags: new Set(['a', 'b']) }, /Set/);
138
- });
139
- it('throws on Buffer', () => {
140
- throwsTypeError(Buffer.from('hello'), /TypedArray|Buffer/);
141
- });
142
- it('throws on Uint8Array', () => {
143
- throwsTypeError(new Uint8Array([1, 2, 3]), /TypedArray|Buffer/);
144
- });
145
- it('throws on Int32Array', () => {
146
- throwsTypeError(new Int32Array([1, 2, 3]), /TypedArray|Buffer/);
147
- });
148
- it('throws on Float64Array', () => {
149
- throwsTypeError(new Float64Array([1.0, 2.0]), /TypedArray|Buffer/);
150
- });
151
- it('throws on function', () => {
152
- throwsTypeError(() => 42, /function/);
153
- });
154
- it('throws on function inside an object', () => {
155
- throwsTypeError({ fn: () => { } }, /function/);
156
- });
157
- it('throws on BigInt', () => {
158
- throwsTypeError(BigInt(9007199254740993), /BigInt/);
159
- });
160
- it('throws on BigInt inside an object', () => {
161
- throwsTypeError({ id: BigInt(1) }, /BigInt/);
162
- });
163
- it('throws on Symbol', () => {
164
- throwsTypeError(Symbol('test'), /Symbol/);
165
- });
166
- it('throws on circular reference (object)', () => {
167
- const obj = { a: 1 };
168
- obj.self = obj;
169
- throwsTypeError(obj, /circular/);
170
- });
171
- it('throws on circular reference (array)', () => {
172
- const arr = [1, 2];
173
- arr.push(arr);
174
- throwsTypeError(arr, /circular/);
175
- });
176
- it('throws on circular reference (nested)', () => {
177
- const inner = { x: 1 };
178
- const outer = { a: inner, b: inner }; // shared ref is fine (not circular)
179
- outer.a.parent = outer; // this makes it circular
180
- throwsTypeError(outer, /circular/);
181
- });
182
- it('does NOT throw for shared (non-circular) references', () => {
183
- // The same object appearing in two sibling branches is fine — it is not circular
184
- const shared = { x: 1 };
185
- expect(() => hashObject({ a: shared, b: shared })).not.toThrow();
186
- // And both branches must hash the same
187
- same({ a: shared, b: shared }, { a: { x: 1 }, b: { x: 1 } });
188
- });
189
- it('throws on NaN', () => {
190
- throwsTypeError(NaN, /non-finite/);
191
- });
192
- it('throws on Infinity', () => {
193
- throwsTypeError(Infinity, /non-finite/);
194
- });
195
- it('throws on -Infinity', () => {
196
- throwsTypeError(-Infinity, /non-finite/);
197
- });
198
- it('throws on NaN inside an object', () => {
199
- throwsTypeError({ value: NaN }, /non-finite/);
200
- });
201
- it('throws on Symbol inside an object', () => {
202
- throwsTypeError({ s: Symbol('test') }, /Symbol/);
203
- });
204
- it('throws on Buffer inside an object', () => {
205
- throwsTypeError({ data: Buffer.from('hello') }, /TypedArray|Buffer/);
206
- });
207
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=run_generate_types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"run_generate_types.d.ts","sourceRoot":"","sources":["../src/run_generate_types.ts"],"names":[],"mappings":""}
@@ -1,7 +0,0 @@
1
- import { generateTypes } from './generate_types.js';
2
- import { resolve } from 'path';
3
- await generateTypes({
4
- schemaDirs: [resolve('./typesrc')],
5
- outputDir: './src/types',
6
- typeRegistryImport: '../type_register.js',
7
- });
@@ -1,269 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { hashObject } from '../hash.js';
3
-
4
- // ── Helper ─────────────────────────────────────────────────────────────────
5
-
6
- /** Assert that two values hash the same */
7
- function same(a: unknown, b: unknown): void {
8
- expect(hashObject(a)).toBe(hashObject(b));
9
- }
10
-
11
- /** Assert that two values hash differently */
12
- function different(a: unknown, b: unknown): void {
13
- expect(hashObject(a)).not.toBe(hashObject(b));
14
- }
15
-
16
- /** Assert that hashObject throws a TypeError with a message matching the pattern */
17
- function throwsTypeError(value: unknown, pattern: RegExp): void {
18
- expect(() => hashObject(value)).toThrow(TypeError);
19
- expect(() => hashObject(value)).toThrow(pattern);
20
- }
21
-
22
- // ── Output format ──────────────────────────────────────────────────────────
23
-
24
- describe('output format', () => {
25
- it('returns a 64-character lowercase hex string', () => {
26
- expect(hashObject({ x: 1 })).toMatch(/^[0-9a-f]{64}$/);
27
- });
28
-
29
- it('is deterministic — same input always produces same output', () => {
30
- const obj = { a: 1, b: [2, 3], c: { d: 'hello' } };
31
- expect(hashObject(obj)).toBe(hashObject(obj));
32
- expect(hashObject(obj)).toBe(hashObject({ a: 1, b: [2, 3], c: { d: 'hello' } }));
33
- });
34
- });
35
-
36
- // ── Supported types ────────────────────────────────────────────────────────
37
-
38
- describe('supported scalar types', () => {
39
- it('hashes null', () => {
40
- const h = hashObject(null);
41
- expect(h).toMatch(/^[0-9a-f]{64}$/);
42
- });
43
-
44
- it('hashes strings', () => {
45
- different('hello', 'world');
46
- same('hello', 'hello');
47
- });
48
-
49
- it('hashes numbers', () => {
50
- different(1, 2);
51
- same(42, 42);
52
- });
53
-
54
- it('hashes booleans', () => {
55
- different(true, false);
56
- same(true, true);
57
- });
58
-
59
- it('differentiates between types with similar string forms', () => {
60
- different(null, 'null');
61
- different(0, false);
62
- different(0, '0');
63
- different(false, 'false');
64
- different(1, '1');
65
- different(null, ''); // null is fine; just checking null != ''
66
- });
67
-
68
- it('differentiates NaN from null — NaN throws', () => {
69
- expect(() => hashObject(NaN)).toThrow(TypeError);
70
- // null should still work fine
71
- expect(() => hashObject(null)).not.toThrow();
72
- });
73
- });
74
-
75
- describe('supported object types', () => {
76
- it('hashes empty object', () => {
77
- const h = hashObject({});
78
- expect(h).toMatch(/^[0-9a-f]{64}$/);
79
- });
80
-
81
- it('hashes empty array', () => {
82
- different([], {});
83
- expect(hashObject([])).toMatch(/^[0-9a-f]{64}$/);
84
- });
85
-
86
- it('hashes plain objects', () => {
87
- same({ a: 1 }, { a: 1 });
88
- different({ a: 1 }, { a: 2 });
89
- different({ a: 1 }, { b: 1 });
90
- });
91
-
92
- it('hashes arrays (order is preserved)', () => {
93
- same([1, 2, 3], [1, 2, 3]);
94
- different([1, 2, 3], [3, 2, 1]);
95
- });
96
-
97
- it('hashes nested objects', () => {
98
- same({ a: { b: { c: 42 } } }, { a: { b: { c: 42 } } });
99
- different({ a: { b: 1 } }, { a: { b: 2 } });
100
- });
101
-
102
- it('hashes mixed nested structures', () => {
103
- same({ a: [1, { b: 2 }] }, { a: [1, { b: 2 }] });
104
- different({ a: [1, { b: 2 }] }, { a: [1, { b: 3 }] });
105
- });
106
-
107
- it('allows the same object reference in sibling array positions', () => {
108
- const shared = { x: 1 };
109
- expect(() => hashObject([shared, shared])).not.toThrow();
110
- same([shared, shared], [{ x: 1 }, { x: 1 }]);
111
- });
112
- });
113
-
114
- // ── Key ordering ───────────────────────────────────────────────────────────
115
-
116
- describe('key ordering', () => {
117
- it('produces the same hash regardless of key insertion order (top level)', () => {
118
- same({ a: 1, b: 2 }, { b: 2, a: 1 });
119
- });
120
-
121
- it('produces the same hash for deeply nested objects with different key order', () => {
122
- same(
123
- { x: { c: 3, a: 1, b: 2 } },
124
- { x: { a: 1, b: 2, c: 3 } },
125
- );
126
- });
127
-
128
- it('produces the same hash for objects inside arrays with different key order', () => {
129
- same(
130
- [{ z: 26, a: 1 }, { m: 13, b: 2 }],
131
- [{ a: 1, z: 26 }, { b: 2, m: 13 }],
132
- );
133
- });
134
-
135
- it('distinguishes objects with the same keys but different values', () => {
136
- different({ a: 1, b: 2 }, { a: 2, b: 1 });
137
- });
138
- });
139
-
140
- // ── Unsupported types — must throw TypeError ───────────────────────────────
141
-
142
- describe('unsupported types throw TypeError', () => {
143
- it('throws on undefined (top-level)', () => {
144
- throwsTypeError(undefined, /undefined/);
145
- });
146
-
147
- it('throws on undefined inside an object value', () => {
148
- throwsTypeError({ a: undefined }, /undefined/);
149
- });
150
-
151
- it('throws on undefined inside a nested object', () => {
152
- throwsTypeError({ a: { b: undefined } }, /undefined/);
153
- });
154
-
155
- it('throws on undefined inside an array', () => {
156
- throwsTypeError([1, undefined, 3], /undefined/);
157
- });
158
-
159
- it('throws on Date', () => {
160
- throwsTypeError(new Date(), /Date/);
161
- });
162
-
163
- it('throws on Date inside an object', () => {
164
- throwsTypeError({ created: new Date() }, /Date/);
165
- });
166
-
167
- it('throws on Map', () => {
168
- throwsTypeError(new Map([['a', 1]]), /Map/);
169
- });
170
-
171
- it('throws on Map inside an object', () => {
172
- throwsTypeError({ data: new Map() }, /Map/);
173
- });
174
-
175
- it('throws on Set', () => {
176
- throwsTypeError(new Set([1, 2, 3]), /Set/);
177
- });
178
-
179
- it('throws on Set inside an object', () => {
180
- throwsTypeError({ tags: new Set(['a', 'b']) }, /Set/);
181
- });
182
-
183
- it('throws on Buffer', () => {
184
- throwsTypeError(Buffer.from('hello'), /TypedArray|Buffer/);
185
- });
186
-
187
- it('throws on Uint8Array', () => {
188
- throwsTypeError(new Uint8Array([1, 2, 3]), /TypedArray|Buffer/);
189
- });
190
-
191
- it('throws on Int32Array', () => {
192
- throwsTypeError(new Int32Array([1, 2, 3]), /TypedArray|Buffer/);
193
- });
194
-
195
- it('throws on Float64Array', () => {
196
- throwsTypeError(new Float64Array([1.0, 2.0]), /TypedArray|Buffer/);
197
- });
198
-
199
- it('throws on function', () => {
200
- throwsTypeError(() => 42, /function/);
201
- });
202
-
203
- it('throws on function inside an object', () => {
204
- throwsTypeError({ fn: () => {} }, /function/);
205
- });
206
-
207
- it('throws on BigInt', () => {
208
- throwsTypeError(BigInt(9007199254740993), /BigInt/);
209
- });
210
-
211
- it('throws on BigInt inside an object', () => {
212
- throwsTypeError({ id: BigInt(1) }, /BigInt/);
213
- });
214
-
215
- it('throws on Symbol', () => {
216
- throwsTypeError(Symbol('test'), /Symbol/);
217
- });
218
-
219
- it('throws on circular reference (object)', () => {
220
- const obj: Record<string, unknown> = { a: 1 };
221
- obj.self = obj;
222
- throwsTypeError(obj, /circular/);
223
- });
224
-
225
- it('throws on circular reference (array)', () => {
226
- const arr: unknown[] = [1, 2];
227
- arr.push(arr);
228
- throwsTypeError(arr, /circular/);
229
- });
230
-
231
- it('throws on circular reference (nested)', () => {
232
- const inner: Record<string, unknown> = { x: 1 };
233
- const outer = { a: inner, b: inner }; // shared ref is fine (not circular)
234
- outer.a.parent = outer; // this makes it circular
235
- throwsTypeError(outer, /circular/);
236
- });
237
-
238
- it('does NOT throw for shared (non-circular) references', () => {
239
- // The same object appearing in two sibling branches is fine — it is not circular
240
- const shared = { x: 1 };
241
- expect(() => hashObject({ a: shared, b: shared })).not.toThrow();
242
- // And both branches must hash the same
243
- same({ a: shared, b: shared }, { a: { x: 1 }, b: { x: 1 } });
244
- });
245
-
246
- it('throws on NaN', () => {
247
- throwsTypeError(NaN, /non-finite/);
248
- });
249
-
250
- it('throws on Infinity', () => {
251
- throwsTypeError(Infinity, /non-finite/);
252
- });
253
-
254
- it('throws on -Infinity', () => {
255
- throwsTypeError(-Infinity, /non-finite/);
256
- });
257
-
258
- it('throws on NaN inside an object', () => {
259
- throwsTypeError({ value: NaN }, /non-finite/);
260
- });
261
-
262
- it('throws on Symbol inside an object', () => {
263
- throwsTypeError({ s: Symbol('test') }, /Symbol/);
264
- });
265
-
266
- it('throws on Buffer inside an object', () => {
267
- throwsTypeError({ data: Buffer.from('hello') }, /TypedArray|Buffer/);
268
- });
269
- });