-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtesters.ts
More file actions
172 lines (142 loc) · 4.66 KB
/
testers.ts
File metadata and controls
172 lines (142 loc) · 4.66 KB
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import type { JSONSchema, UISchemaElement } from './types.js';
/**
* Helper to create a ranked tester
* Returns rank if predicate is true, -1 otherwise
*/
export const rankWith = (rank: number, predicate: boolean): number => {
return predicate ? rank : -1;
};
/**
* Basic type testers
*/
export const isStringType = (schema: JSONSchema): boolean => {
if (schema.type === 'string') return true;
if (schema.const !== undefined && typeof schema.const === 'string') return true;
return false;
};
export const isNumberType = (schema: JSONSchema): boolean => {
if (schema.type === 'number' || schema.type === 'integer') return true;
if (schema.const !== undefined && typeof schema.const === 'number') return true;
return false;
};
export const isIntegerType = (schema: JSONSchema): boolean => {
return schema.type === 'integer';
};
export const isBooleanType = (schema: JSONSchema): boolean => {
if (schema.type === 'boolean') return true;
if (schema.const !== undefined && typeof schema.const === 'boolean') return true;
return false;
};
export const isObjectType = (schema: JSONSchema): boolean => {
return schema.type === 'object' || (schema.type === undefined && schema.properties !== undefined);
};
export const isArrayType = (schema: JSONSchema): boolean => {
return schema.type === 'array';
};
/**
* JSON object tester - for freeform JSON editing
* Matches objects with additionalProperties but no defined properties,
* or any field with x-render: "jsoneditor"
*/
export const isJsonType = (schema: JSONSchema): boolean => {
// Explicit opt-in via x-render extension
if ((schema as any)['x-render'] === 'jsoneditor') {
return true;
}
// Automatic detection: object with additionalProperties but no defined properties
return (
schema.type === 'object' &&
schema.additionalProperties !== undefined &&
(!schema.properties || Object.keys(schema.properties).length === 0)
);
};
export const isNullType = (schema: JSONSchema): boolean => {
return schema.type === 'null';
};
/**
* Const tester - for fields that can only have one specific value
*/
export const hasConst = (schema: JSONSchema): boolean => {
return schema.const !== undefined;
};
/**
* Enum tester
*/
export const isEnumType = (schema: JSONSchema): boolean => {
return Array.isArray(schema.enum) && schema.enum.length > 0;
};
/**
* Format-specific testers
*/
export const hasFormat = (format: string) => (schema: JSONSchema): boolean => {
return schema.format === format;
};
export const isEmailFormat = (schema: JSONSchema): boolean => {
return isStringType(schema) && schema.format === 'email';
};
export const isDateFormat = (schema: JSONSchema): boolean => {
return isStringType(schema) && schema.format === 'date';
};
export const isTimeFormat = (schema: JSONSchema): boolean => {
return isStringType(schema) && schema.format === 'time';
};
export const isDateTimeFormat = (schema: JSONSchema): boolean => {
return isStringType(schema) && schema.format === 'date-time';
};
export const isUrlFormat = (schema: JSONSchema): boolean => {
return isStringType(schema) && (schema.format === 'url' || schema.format === 'uri');
};
/**
* Composition testers
*/
export const hasOneOf = (schema: JSONSchema): boolean => {
return Array.isArray(schema.oneOf) && schema.oneOf.length > 0;
};
export const hasAnyOf = (schema: JSONSchema): boolean => {
return Array.isArray(schema.anyOf) && schema.anyOf.length > 0;
};
export const hasAllOf = (schema: JSONSchema): boolean => {
return Array.isArray(schema.allOf) && schema.allOf.length > 0;
};
/**
* Discriminated union tester
*/
export const isDiscriminatedUnion = (schema: JSONSchema): boolean => {
return hasOneOf(schema) && schema.discriminator !== undefined;
};
/**
* Conditional schema tester
*/
export const hasConditional = (schema: JSONSchema): boolean => {
return schema.if !== undefined;
};
/**
* Custom extension tester factory
*/
export const hasExtension = (extensionKey: string) => (schema: JSONSchema): boolean => {
return schema[extensionKey as keyof JSONSchema] !== undefined;
};
/**
* Combines multiple testers with AND logic
*/
export const and = (...testers: Array<(schema: JSONSchema) => boolean>) => {
return (schema: JSONSchema): boolean => {
return testers.every(tester => tester(schema));
};
};
/**
* Combines multiple testers with OR logic
*/
export const or = (...testers: Array<(schema: JSONSchema) => boolean>) => {
return (schema: JSONSchema): boolean => {
return testers.some(tester => tester(schema));
};
};
/**
* Negates a tester
*/
export const not = (tester: (schema: JSONSchema) => boolean) => {
return (schema: JSONSchema): boolean => {
return !tester(schema);
};
};