-
-
Notifications
You must be signed in to change notification settings - Fork 82
/
Copy pathschemaHash.ts
67 lines (57 loc) · 1.81 KB
/
schemaHash.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import type { JSONSchema } from './index.js';
import { schemaInfo, type SchemaInfo } from './schemaInfo.js';
export function schemaHash(schema: JSONSchema): string {
return hashCode(_schemaHash(schemaInfo(schema, false, []), 0, []));
}
function _schemaHash(info: SchemaInfo | undefined, depth: number, path: string[]): string {
if (!info) return '';
function tab() {
return ' '.repeat(depth);
}
function mapSchemas(schemas: JSONSchema[]) {
return schemas
.map((s) => _schemaHash(schemaInfo(s, info?.isOptional ?? false, path), depth + 1, path))
.filter((s) => s)
.join('|');
}
function nullish() {
const output: string[] = [];
if (info?.isNullable) output.push('null');
if (info?.isOptional) output.push('undefined');
return !output.length ? '' : '|' + output.join('|');
}
// Union
if (info.union) {
return 'Union {\n ' + tab() + mapSchemas(info.union) + '\n' + tab() + '}' + nullish();
}
// Objects
if (info.properties) {
const output: string[] = [];
for (const [key, prop] of Object.entries(info.properties)) {
const propInfo = schemaInfo(
prop,
!info.required?.includes(key) || prop.default !== undefined,
[key]
);
output.push(key + ': ' + _schemaHash(propInfo, depth + 1, path));
}
return 'Object {\n ' + tab() + output.join(',\n ') + '\n' + tab() + '}' + nullish();
}
// Arrays
if (info.array) {
return 'Array[' + mapSchemas(info.array) + ']' + nullish();
}
return info.types.join('|') + nullish();
}
// https://stackoverflow.com/a/8831937/70894
function hashCode(str: string) {
let hash = 0;
for (let i = 0, len = str.length; i < len; i++) {
const chr = str.charCodeAt(i);
hash = (hash << 5) - hash + chr;
hash |= 0; // Convert to 32bit integer
}
// Make it unsigned, for the hash appearance
if (hash < 0) hash = hash >>> 0;
return hash.toString(36);
}