|
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