|
1 | 1 | /** |
2 | | - * Fixture schemas for testing using the type builder. |
3 | | - * These schemas represent realistic scenarios covering all node types. |
| 2 | + * Fixture schemas for testing random value generation. |
| 3 | + * These schemas represent different JSON Type configurations that can be used |
| 4 | + * across multiple test modules. |
4 | 5 | */ |
5 | 6 |
|
6 | | -import {t} from '../type'; |
| 7 | +import {s} from '../schema'; |
7 | 8 |
|
8 | 9 | /** |
9 | | - * User profile schema with nested objects and optional fields |
10 | | - */ |
11 | | -export const User = t |
12 | | - .object({ |
13 | | - id: t.str, |
14 | | - name: t.object({ |
15 | | - first: t.str, |
16 | | - last: t.str, |
17 | | - }), |
18 | | - email: t.String({format: 'ascii'}), |
19 | | - age: t.Number({gte: 0, lte: 150}), |
20 | | - verified: t.bool, |
21 | | - }) |
22 | | - .opt('avatar', t.String({format: 'ascii'})); |
23 | | - |
24 | | -/** |
25 | | - * Product catalog schema with arrays and formatted numbers |
26 | | - */ |
27 | | -export const Product = t.Object( |
28 | | - t.prop('id', t.String({format: 'ascii'})), |
29 | | - t.prop('name', t.String({min: 1, max: 100})), |
30 | | - t.prop('price', t.Number({format: 'f64', gte: 0})), |
31 | | - t.prop('inStock', t.bool), |
32 | | - t.prop('categories', t.Array(t.str, {min: 1})), |
33 | | - t.prop('tags', t.Array(t.str)), |
34 | | - t.propOpt('description', t.String({max: 1000})), |
35 | | - t.propOpt('discount', t.Number({gte: 0, lte: 1})), |
36 | | -); |
37 | | - |
38 | | -/** |
39 | | - * Blog post schema with timestamps and rich content |
40 | | - */ |
41 | | -export const BlogPost = t.Object( |
42 | | - t.prop('id', t.str), |
43 | | - t.prop('title', t.String({min: 1, max: 200})), |
44 | | - t.prop('content', t.str), |
45 | | - t.prop('author', t.Ref<typeof User>('User')), |
46 | | - t.prop('publishedAt', t.Number({format: 'u64'})), |
47 | | - t.prop('status', t.enum('draft', 'published', 'archived')), |
48 | | - t.propOpt('updatedAt', t.Number({format: 'u64'})), |
49 | | - t.propOpt('tags', t.Array(t.str)), |
50 | | -); |
51 | | - |
52 | | -/** |
53 | | - * API response schema with discriminated unions |
54 | | - */ |
55 | | -export const ApiResponse = t.Or( |
56 | | - t.object({ |
57 | | - success: t.Const(true), |
58 | | - data: t.any, |
59 | | - timestamp: t.Number({format: 'u64'}), |
60 | | - }), |
61 | | - t.object({ |
62 | | - success: t.Const(false), |
63 | | - error: t.object({ |
64 | | - code: t.String({format: 'ascii'}), |
65 | | - message: t.str, |
66 | | - }), |
67 | | - timestamp: t.Number({format: 'u64'}), |
68 | | - }), |
69 | | -); |
70 | | - |
71 | | -/** |
72 | | - * File metadata schema with binary data |
73 | | - */ |
74 | | -export const FileMetadata = t.Object( |
75 | | - t.prop('name', t.str), |
76 | | - t.prop('size', t.Number({format: 'u64', gte: 0})), |
77 | | - t.prop('mimeType', t.str), |
78 | | - t.prop('data', t.Binary(t.any)), |
79 | | - t.prop('checksum', t.String({format: 'ascii', min: 64, max: 64})), |
80 | | - t.prop('uploadedAt', t.Number({format: 'u64'})), |
81 | | - t.propOpt('metadata', t.Map(t.str)), |
82 | | -); |
83 | | - |
84 | | -/** |
85 | | - * Configuration schema with maps and default values |
86 | | - */ |
87 | | -export const Configuration = t.Object( |
88 | | - t.prop('environment', t.enum('development', 'staging', 'production')), |
89 | | - t.prop( |
90 | | - 'database', |
91 | | - t.object({ |
92 | | - host: t.str, |
93 | | - port: t.Number({format: 'u16', gte: 1, lte: 65535}), |
94 | | - name: t.str, |
95 | | - }), |
96 | | - ), |
97 | | - t.prop('features', t.Map(t.bool)), |
98 | | - t.prop('secrets', t.Map(t.str)), |
99 | | - t.propOpt( |
100 | | - 'logging', |
101 | | - t.object({ |
102 | | - level: t.enum('debug', 'info', 'warn', 'error'), |
103 | | - output: t.str, |
104 | | - }), |
105 | | - ), |
106 | | -); |
107 | | - |
108 | | -/** |
109 | | - * Event data schema with tuples and coordinates |
110 | | - */ |
111 | | -export const Event = t.Object( |
112 | | - t.prop('id', t.String({format: 'ascii'})), |
113 | | - t.prop('type', t.enum('click', 'view', 'purchase', 'signup')), |
114 | | - t.prop('timestamp', t.Number({format: 'u64'})), |
115 | | - t.prop('userId', t.maybe(t.str)), |
116 | | - t.prop('location', t.Tuple([t.Number({format: 'f64'}), t.Number({format: 'f64'})])), |
117 | | - t.prop('metadata', t.Map(t.Or(t.str, t.num, t.bool))), |
118 | | - t.propOpt('sessionId', t.str), |
119 | | -); |
120 | | - |
121 | | -/** |
122 | | - * Contact information schema with formatted strings |
123 | | - */ |
124 | | -export const ContactInfo = t.Object( |
125 | | - t.prop( |
126 | | - 'name', |
127 | | - t.object({ |
128 | | - first: t.String({min: 1}), |
129 | | - last: t.String({min: 1}), |
130 | | - }), |
131 | | - ), |
132 | | - t.prop('emails', t.Array(t.String({format: 'ascii'}), {min: 1})), |
133 | | - t.prop('phones', t.Array(t.tuple(t.enum('home', 'work', 'mobile'), t.str))), |
134 | | - t.propOpt( |
135 | | - 'address', |
136 | | - t.object({ |
137 | | - street: t.str, |
138 | | - city: t.str, |
139 | | - country: t.String({format: 'ascii', min: 2, max: 2}), |
140 | | - postalCode: t.str, |
141 | | - }), |
142 | | - ), |
143 | | - t.propOpt('socialMedia', t.Map(t.String({format: 'ascii'}))), |
144 | | -); |
145 | | - |
146 | | -/** |
147 | | - * Database record schema with references |
148 | | - */ |
149 | | -export const DatabaseRecord = t.Object( |
150 | | - t.prop('id', t.String({format: 'ascii'})), |
151 | | - t.prop('createdAt', t.Number({format: 'u64'})), |
152 | | - t.prop('updatedAt', t.Number({format: 'u64'})), |
153 | | - t.prop('version', t.Number({format: 'u32', gte: 1})), |
154 | | - t.prop('createdBy', t.Ref<typeof User>('User')), |
155 | | - t.propOpt('updatedBy', t.Ref<typeof User>('User')), |
156 | | - t.propOpt('deletedAt', t.Number({format: 'u64'})), |
157 | | -); |
158 | | - |
159 | | -/** |
160 | | - * Function type schema |
161 | | - */ |
162 | | -export const UserValidator = t.Function( |
163 | | - t.object({ |
164 | | - userData: t.any, |
165 | | - strict: t.bool, |
166 | | - }), |
167 | | - t.object({ |
168 | | - valid: t.bool, |
169 | | - errors: t.Array(t.str), |
170 | | - }), |
171 | | - {title: 'User Validation Function'}, |
172 | | -); |
173 | | - |
174 | | -/** |
175 | | - * Streaming API schema |
176 | | - */ |
177 | | -export const EventStream = t.Function$( |
178 | | - t.object({ |
179 | | - filter: t.maybe(t.str), |
180 | | - limit: t.maybe(t.Number({format: 'u32'})), |
181 | | - }), |
182 | | - t.Ref<typeof Event>('Event'), |
183 | | - {title: 'Event Streaming Function'}, |
184 | | -); |
185 | | - |
186 | | -/** |
187 | | - * Complex nested schema |
188 | | - */ |
189 | | -export const ComplexNested = t.Object( |
190 | | - t.prop( |
191 | | - 'data', |
192 | | - t.Map( |
193 | | - t.Or( |
194 | | - t.str, |
195 | | - t.num, |
196 | | - t.Array( |
197 | | - t.Map( |
198 | | - t.object({ |
199 | | - key: t.str, |
200 | | - value: t.Or(t.str, t.num, t.bool, t.nil), |
201 | | - nested: t.maybe(t.Map(t.any)), |
202 | | - }), |
203 | | - ), |
204 | | - ), |
205 | | - ), |
206 | | - ), |
207 | | - ), |
208 | | - t.prop( |
209 | | - 'metadata', |
210 | | - t.object({ |
211 | | - version: t.str, |
212 | | - schema: t.String({format: 'ascii'}), |
213 | | - checksum: t.String({format: 'ascii'}), |
214 | | - }), |
215 | | - ), |
216 | | -); |
217 | | - |
218 | | -/** |
219 | | - * Basic primitive type schemas for backward compatibility |
| 10 | + * Basic primitive type schemas |
220 | 11 | */ |
221 | 12 | export const primitiveSchemas = { |
222 | | - string: t.str.getSchema(), |
223 | | - stringWithMinMax: t.String({min: 5, max: 10}).getSchema(), |
224 | | - number: t.num.getSchema(), |
225 | | - numberWithFormat: t.Number({format: 'u32'}).getSchema(), |
226 | | - numberWithRange: t.Number({gte: 0, lte: 100}).getSchema(), |
227 | | - boolean: t.bool.getSchema(), |
228 | | - const: t.Const('fixed-value' as const).getSchema(), |
229 | | - any: t.any.getSchema(), |
| 13 | + string: s.String(), |
| 14 | + stringWithMinMax: s.String({min: 5, max: 10}), |
| 15 | + number: s.Number(), |
| 16 | + numberWithFormat: s.Number({format: 'u32'}), |
| 17 | + numberWithRange: s.Number({gte: 0, lte: 100}), |
| 18 | + boolean: s.Boolean(), |
| 19 | + const: s.Const('fixed-value' as const), |
| 20 | + any: s.Any(), |
230 | 21 | } as const; |
231 | 22 |
|
232 | 23 | /** |
233 | | - * Complex composite type schemas for backward compatibility |
| 24 | + * Complex composite type schemas |
234 | 25 | */ |
235 | 26 | export const compositeSchemas = { |
236 | | - simpleArray: t.Array(t.str).getSchema(), |
237 | | - arrayWithBounds: t.Array(t.num, {min: 2, max: 5}).getSchema(), |
238 | | - simpleObject: t.Object(t.prop('id', t.str), t.prop('name', t.str), t.prop('active', t.bool)).getSchema(), |
239 | | - objectWithOptionalFields: t |
240 | | - .Object(t.prop('id', t.str), t.propOpt('name', t.str), t.propOpt('count', t.num)) |
241 | | - .getSchema(), |
242 | | - nestedObject: t |
243 | | - .Object( |
244 | | - t.prop( |
245 | | - 'user', |
246 | | - t.Object(t.prop('id', t.num), t.prop('profile', t.Object(t.prop('name', t.str), t.prop('email', t.str)))), |
247 | | - ), |
248 | | - t.prop('tags', t.Array(t.str)), |
249 | | - ) |
250 | | - .getSchema(), |
251 | | - tuple: t.tuple(t.str, t.num, t.bool).getSchema(), |
252 | | - map: t.Map(t.str).getSchema(), |
253 | | - mapWithComplexValue: t.Map(t.Object(t.prop('value', t.num), t.prop('label', t.str))).getSchema(), |
254 | | - union: t.Or(t.str, t.num, t.bool).getSchema(), |
255 | | - complexUnion: t |
256 | | - .Or(t.str, t.Object(t.prop('type', t.Const('object' as const)), t.prop('data', t.any)), t.Array(t.num)) |
257 | | - .getSchema(), |
258 | | - binary: t.bin.getSchema(), |
| 27 | + simpleArray: s.Array(s.String()), |
| 28 | + arrayWithBounds: s.Array(s.Number(), {min: 2, max: 5}), |
| 29 | + simpleObject: s.Object([s.prop('id', s.String()), s.prop('name', s.String()), s.prop('active', s.Boolean())]), |
| 30 | + objectWithOptionalFields: s.Object([ |
| 31 | + s.prop('id', s.String()), |
| 32 | + s.propOpt('name', s.String()), |
| 33 | + s.propOpt('count', s.Number()), |
| 34 | + ]), |
| 35 | + nestedObject: s.Object([ |
| 36 | + s.prop( |
| 37 | + 'user', |
| 38 | + s.Object([ |
| 39 | + s.prop('id', s.Number()), |
| 40 | + s.prop('profile', s.Object([s.prop('name', s.String()), s.prop('email', s.String())])), |
| 41 | + ]), |
| 42 | + ), |
| 43 | + s.prop('tags', s.Array(s.String())), |
| 44 | + ]), |
| 45 | + tuple: s.Tuple([s.String(), s.Number(), s.Boolean()]), |
| 46 | + map: s.Map(s.String()), |
| 47 | + mapWithComplexValue: s.Map(s.Object([s.prop('value', s.Number()), s.prop('label', s.String())])), |
| 48 | + union: s.Or(s.String(), s.Number(), s.Boolean()), |
| 49 | + complexUnion: s.Or( |
| 50 | + s.String(), |
| 51 | + s.Object([s.prop('type', s.Const('object' as const)), s.prop('data', s.Any())]), |
| 52 | + s.Array(s.Number()), |
| 53 | + ), |
| 54 | + binary: s.bin, |
259 | 55 | } as const; |
260 | 56 |
|
261 | 57 | /** |
|
0 commit comments