schemock 0.0.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/LICENSE +21 -0
- package/README.md +82 -0
- package/dist/adapters/index.d.mts +1364 -0
- package/dist/adapters/index.d.ts +1364 -0
- package/dist/adapters/index.js +36988 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/index.mjs +36972 -0
- package/dist/adapters/index.mjs.map +1 -0
- package/dist/cli/index.d.mts +831 -0
- package/dist/cli/index.d.ts +831 -0
- package/dist/cli/index.js +4425 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/index.mjs +4401 -0
- package/dist/cli/index.mjs.map +1 -0
- package/dist/cli.js +6776 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +39439 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +39367 -0
- package/dist/index.mjs.map +1 -0
- package/dist/middleware/index.d.mts +688 -0
- package/dist/middleware/index.d.ts +688 -0
- package/dist/middleware/index.js +921 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/index.mjs +899 -0
- package/dist/middleware/index.mjs.map +1 -0
- package/dist/react/index.d.mts +316 -0
- package/dist/react/index.d.ts +316 -0
- package/dist/react/index.js +466 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/index.mjs +456 -0
- package/dist/react/index.mjs.map +1 -0
- package/dist/runtime/index.d.mts +814 -0
- package/dist/runtime/index.d.ts +814 -0
- package/dist/runtime/index.js +1270 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/index.mjs +1246 -0
- package/dist/runtime/index.mjs.map +1 -0
- package/dist/schema/index.d.mts +838 -0
- package/dist/schema/index.d.ts +838 -0
- package/dist/schema/index.js +696 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/index.mjs +681 -0
- package/dist/schema/index.mjs.map +1 -0
- package/dist/types-C1MiZh1d.d.ts +96 -0
- package/dist/types-C2bd2vgy.d.mts +773 -0
- package/dist/types-C2bd2vgy.d.ts +773 -0
- package/dist/types-C9VMgu3E.d.mts +289 -0
- package/dist/types-DV2DS7wj.d.mts +96 -0
- package/dist/types-c2AN3vky.d.ts +289 -0
- package/package.json +116 -0
|
@@ -0,0 +1,681 @@
|
|
|
1
|
+
// src/schema/types.ts
|
|
2
|
+
function isComputedField(field2) {
|
|
3
|
+
return typeof field2 === "object" && field2 !== null && "_computed" in field2 && field2._computed === true;
|
|
4
|
+
}
|
|
5
|
+
function isRelation(field2) {
|
|
6
|
+
return typeof field2 === "object" && field2 !== null && "type" in field2 && ["hasMany", "belongsTo", "hasOne"].includes(field2.type);
|
|
7
|
+
}
|
|
8
|
+
function isEndpointSchema(value) {
|
|
9
|
+
return typeof value === "object" && value !== null && "_endpoint" in value && value._endpoint === true;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// src/schema/field.ts
|
|
13
|
+
function createBaseBuilder(state) {
|
|
14
|
+
const builder = {
|
|
15
|
+
type: state.type,
|
|
16
|
+
hint: state.hint,
|
|
17
|
+
isNullable: state.isNullable,
|
|
18
|
+
isUnique: state.isUnique,
|
|
19
|
+
isReadOnly: state.isReadOnly,
|
|
20
|
+
defaultValue: state.defaultValue,
|
|
21
|
+
constraints: state.constraints,
|
|
22
|
+
items: state.items,
|
|
23
|
+
shape: state.shape,
|
|
24
|
+
target: state.target,
|
|
25
|
+
values: state.values,
|
|
26
|
+
nullable() {
|
|
27
|
+
return createBaseBuilder({ ...state, isNullable: true });
|
|
28
|
+
},
|
|
29
|
+
unique(message) {
|
|
30
|
+
return createBaseBuilder({
|
|
31
|
+
...state,
|
|
32
|
+
isUnique: true,
|
|
33
|
+
constraints: { ...state.constraints, message: message || state.constraints?.message }
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
readOnly() {
|
|
37
|
+
return createBaseBuilder({ ...state, isReadOnly: true });
|
|
38
|
+
},
|
|
39
|
+
default(value) {
|
|
40
|
+
return createBaseBuilder({ ...state, defaultValue: value });
|
|
41
|
+
},
|
|
42
|
+
min(value, message) {
|
|
43
|
+
return createBaseBuilder({
|
|
44
|
+
...state,
|
|
45
|
+
constraints: { ...state.constraints, min: value, message: message || state.constraints?.message }
|
|
46
|
+
});
|
|
47
|
+
},
|
|
48
|
+
max(value, message) {
|
|
49
|
+
return createBaseBuilder({
|
|
50
|
+
...state,
|
|
51
|
+
constraints: { ...state.constraints, max: value, message: message || state.constraints?.message }
|
|
52
|
+
});
|
|
53
|
+
},
|
|
54
|
+
pattern(regex, message) {
|
|
55
|
+
return createBaseBuilder({
|
|
56
|
+
...state,
|
|
57
|
+
constraints: { ...state.constraints, pattern: regex, message: message || state.constraints?.message }
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
return builder;
|
|
62
|
+
}
|
|
63
|
+
function createStringBuilder(state) {
|
|
64
|
+
const base = createBaseBuilder(state);
|
|
65
|
+
return {
|
|
66
|
+
...base,
|
|
67
|
+
min(length, message) {
|
|
68
|
+
return createStringBuilder({
|
|
69
|
+
...state,
|
|
70
|
+
constraints: { ...state.constraints, min: length, message: message || state.constraints?.message }
|
|
71
|
+
});
|
|
72
|
+
},
|
|
73
|
+
max(length, message) {
|
|
74
|
+
return createStringBuilder({
|
|
75
|
+
...state,
|
|
76
|
+
constraints: { ...state.constraints, max: length, message: message || state.constraints?.message }
|
|
77
|
+
});
|
|
78
|
+
},
|
|
79
|
+
pattern(regex, message) {
|
|
80
|
+
return createStringBuilder({
|
|
81
|
+
...state,
|
|
82
|
+
constraints: { ...state.constraints, pattern: regex, message: message || state.constraints?.message }
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function createNumberBuilder(state) {
|
|
88
|
+
const base = createBaseBuilder(state);
|
|
89
|
+
return {
|
|
90
|
+
...base,
|
|
91
|
+
min(value, message) {
|
|
92
|
+
return createNumberBuilder({
|
|
93
|
+
...state,
|
|
94
|
+
constraints: { ...state.constraints, min: value, message: message || state.constraints?.message }
|
|
95
|
+
});
|
|
96
|
+
},
|
|
97
|
+
max(value, message) {
|
|
98
|
+
return createNumberBuilder({
|
|
99
|
+
...state,
|
|
100
|
+
constraints: { ...state.constraints, max: value, message: message || state.constraints?.message }
|
|
101
|
+
});
|
|
102
|
+
},
|
|
103
|
+
int() {
|
|
104
|
+
return createNumberBuilder({ ...state, hint: "number.int" });
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function createDateBuilder(state) {
|
|
109
|
+
const base = createBaseBuilder(state);
|
|
110
|
+
return {
|
|
111
|
+
...base,
|
|
112
|
+
past() {
|
|
113
|
+
return createDateBuilder({ ...state, hint: "date.past" });
|
|
114
|
+
},
|
|
115
|
+
future() {
|
|
116
|
+
return createDateBuilder({ ...state, hint: "date.future" });
|
|
117
|
+
},
|
|
118
|
+
recent() {
|
|
119
|
+
return createDateBuilder({ ...state, hint: "date.recent" });
|
|
120
|
+
},
|
|
121
|
+
between(options) {
|
|
122
|
+
return createDateBuilder({
|
|
123
|
+
...state,
|
|
124
|
+
hint: "date.between",
|
|
125
|
+
constraints: {
|
|
126
|
+
...state.constraints,
|
|
127
|
+
// Store date range in constraints for MockAdapter to use
|
|
128
|
+
min: new Date(options.from).getTime(),
|
|
129
|
+
max: new Date(options.to).getTime()
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function createEnumBuilder(values, defaultVal) {
|
|
136
|
+
const state = {
|
|
137
|
+
type: "enum",
|
|
138
|
+
values,
|
|
139
|
+
hint: "helpers.arrayElement",
|
|
140
|
+
defaultValue: defaultVal
|
|
141
|
+
};
|
|
142
|
+
const base = createBaseBuilder(state);
|
|
143
|
+
return {
|
|
144
|
+
...base,
|
|
145
|
+
default(value) {
|
|
146
|
+
return createEnumBuilder(values, value);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function createRefBuilder(target) {
|
|
151
|
+
const state = {
|
|
152
|
+
type: "ref",
|
|
153
|
+
target,
|
|
154
|
+
hint: "string.uuid"
|
|
155
|
+
};
|
|
156
|
+
return {
|
|
157
|
+
...createBaseBuilder(state),
|
|
158
|
+
target
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function createArrayBuilder(itemType, constraints) {
|
|
162
|
+
const state = {
|
|
163
|
+
type: "array",
|
|
164
|
+
items: itemType,
|
|
165
|
+
hint: "array",
|
|
166
|
+
constraints
|
|
167
|
+
};
|
|
168
|
+
const base = createBaseBuilder(state);
|
|
169
|
+
return {
|
|
170
|
+
...base,
|
|
171
|
+
min(length) {
|
|
172
|
+
return createArrayBuilder(itemType, { ...constraints, min: length });
|
|
173
|
+
},
|
|
174
|
+
max(length) {
|
|
175
|
+
return createArrayBuilder(itemType, { ...constraints, max: length });
|
|
176
|
+
},
|
|
177
|
+
length(count) {
|
|
178
|
+
return createArrayBuilder(itemType, { ...constraints, min: count, max: count });
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function createObjectBuilder(shape) {
|
|
183
|
+
const state = {
|
|
184
|
+
type: "object",
|
|
185
|
+
shape,
|
|
186
|
+
hint: "object"
|
|
187
|
+
};
|
|
188
|
+
return {
|
|
189
|
+
...createBaseBuilder(state),
|
|
190
|
+
shape
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function createComputedField(config) {
|
|
194
|
+
return {
|
|
195
|
+
...config,
|
|
196
|
+
_computed: true
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
var field = {
|
|
200
|
+
// -------------------------------------------------------------------------
|
|
201
|
+
// Primitive Types
|
|
202
|
+
// -------------------------------------------------------------------------
|
|
203
|
+
/**
|
|
204
|
+
* UUID v4 string field
|
|
205
|
+
* @returns FieldBuilder<string>
|
|
206
|
+
*/
|
|
207
|
+
uuid() {
|
|
208
|
+
return createBaseBuilder({ type: "uuid", hint: "string.uuid" });
|
|
209
|
+
},
|
|
210
|
+
/**
|
|
211
|
+
* String field with optional hint for mock data generation
|
|
212
|
+
* @param opts - Options including faker hint
|
|
213
|
+
*/
|
|
214
|
+
string(opts) {
|
|
215
|
+
return createStringBuilder({ type: "string", hint: opts?.hint || "lorem.word" });
|
|
216
|
+
},
|
|
217
|
+
/**
|
|
218
|
+
* Number field with optional constraints
|
|
219
|
+
* @param opts - Min, max, and integer constraints
|
|
220
|
+
*/
|
|
221
|
+
number(opts) {
|
|
222
|
+
const constraints = {};
|
|
223
|
+
if (opts?.min !== void 0) constraints.min = opts.min;
|
|
224
|
+
if (opts?.max !== void 0) constraints.max = opts.max;
|
|
225
|
+
return createNumberBuilder({
|
|
226
|
+
type: "number",
|
|
227
|
+
hint: opts?.int ? "number.int" : "number.float",
|
|
228
|
+
constraints: Object.keys(constraints).length > 0 ? constraints : void 0
|
|
229
|
+
});
|
|
230
|
+
},
|
|
231
|
+
/**
|
|
232
|
+
* Boolean field
|
|
233
|
+
*/
|
|
234
|
+
boolean() {
|
|
235
|
+
return createBaseBuilder({ type: "boolean", hint: "datatype.boolean" });
|
|
236
|
+
},
|
|
237
|
+
/**
|
|
238
|
+
* Date field with optional constraints
|
|
239
|
+
* @param opts - Past/future constraints
|
|
240
|
+
*/
|
|
241
|
+
date(opts) {
|
|
242
|
+
let hint = "date.anytime";
|
|
243
|
+
if (opts?.past) hint = "date.past";
|
|
244
|
+
if (opts?.future) hint = "date.future";
|
|
245
|
+
return createDateBuilder({ type: "date", hint });
|
|
246
|
+
},
|
|
247
|
+
// -------------------------------------------------------------------------
|
|
248
|
+
// Semantic Types (Faker-based)
|
|
249
|
+
// -------------------------------------------------------------------------
|
|
250
|
+
/**
|
|
251
|
+
* Email string field
|
|
252
|
+
*/
|
|
253
|
+
email() {
|
|
254
|
+
return createStringBuilder({ type: "string", hint: "internet.email" });
|
|
255
|
+
},
|
|
256
|
+
/**
|
|
257
|
+
* URL string field
|
|
258
|
+
*/
|
|
259
|
+
url() {
|
|
260
|
+
return createStringBuilder({ type: "string", hint: "internet.url" });
|
|
261
|
+
},
|
|
262
|
+
// -------------------------------------------------------------------------
|
|
263
|
+
// Faker Namespace Proxies
|
|
264
|
+
// -------------------------------------------------------------------------
|
|
265
|
+
/**
|
|
266
|
+
* Person-related fields (names, titles, etc.)
|
|
267
|
+
*/
|
|
268
|
+
person: {
|
|
269
|
+
fullName() {
|
|
270
|
+
return createStringBuilder({ type: "string", hint: "person.fullName" });
|
|
271
|
+
},
|
|
272
|
+
firstName() {
|
|
273
|
+
return createStringBuilder({ type: "string", hint: "person.firstName" });
|
|
274
|
+
},
|
|
275
|
+
lastName() {
|
|
276
|
+
return createStringBuilder({ type: "string", hint: "person.lastName" });
|
|
277
|
+
},
|
|
278
|
+
bio() {
|
|
279
|
+
return createStringBuilder({ type: "string", hint: "person.bio" });
|
|
280
|
+
},
|
|
281
|
+
jobTitle() {
|
|
282
|
+
return createStringBuilder({ type: "string", hint: "person.jobTitle" });
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
/**
|
|
286
|
+
* Internet-related fields (emails, URLs, usernames, etc.)
|
|
287
|
+
*/
|
|
288
|
+
internet: {
|
|
289
|
+
email() {
|
|
290
|
+
return createStringBuilder({ type: "string", hint: "internet.email" });
|
|
291
|
+
},
|
|
292
|
+
url() {
|
|
293
|
+
return createStringBuilder({ type: "string", hint: "internet.url" });
|
|
294
|
+
},
|
|
295
|
+
avatar() {
|
|
296
|
+
return createStringBuilder({ type: "string", hint: "internet.avatar" });
|
|
297
|
+
},
|
|
298
|
+
userName() {
|
|
299
|
+
return createStringBuilder({ type: "string", hint: "internet.userName" });
|
|
300
|
+
},
|
|
301
|
+
password() {
|
|
302
|
+
return createStringBuilder({ type: "string", hint: "internet.password" });
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
/**
|
|
306
|
+
* Lorem ipsum text generation
|
|
307
|
+
*/
|
|
308
|
+
lorem: {
|
|
309
|
+
word() {
|
|
310
|
+
return createStringBuilder({ type: "string", hint: "lorem.word" });
|
|
311
|
+
},
|
|
312
|
+
sentence() {
|
|
313
|
+
return createStringBuilder({ type: "string", hint: "lorem.sentence" });
|
|
314
|
+
},
|
|
315
|
+
paragraph() {
|
|
316
|
+
return createStringBuilder({ type: "string", hint: "lorem.paragraph" });
|
|
317
|
+
},
|
|
318
|
+
paragraphs(count = 3) {
|
|
319
|
+
return createStringBuilder({ type: "string", hint: `lorem.paragraphs:${count}` });
|
|
320
|
+
}
|
|
321
|
+
},
|
|
322
|
+
/**
|
|
323
|
+
* Location-related fields (addresses, cities, etc.)
|
|
324
|
+
*/
|
|
325
|
+
location: {
|
|
326
|
+
city() {
|
|
327
|
+
return createStringBuilder({ type: "string", hint: "location.city" });
|
|
328
|
+
},
|
|
329
|
+
country() {
|
|
330
|
+
return createStringBuilder({ type: "string", hint: "location.country" });
|
|
331
|
+
},
|
|
332
|
+
streetAddress() {
|
|
333
|
+
return createStringBuilder({ type: "string", hint: "location.streetAddress" });
|
|
334
|
+
},
|
|
335
|
+
zipCode() {
|
|
336
|
+
return createStringBuilder({ type: "string", hint: "location.zipCode" });
|
|
337
|
+
},
|
|
338
|
+
latitude() {
|
|
339
|
+
return createNumberBuilder({ type: "number", hint: "location.latitude" });
|
|
340
|
+
},
|
|
341
|
+
longitude() {
|
|
342
|
+
return createNumberBuilder({ type: "number", hint: "location.longitude" });
|
|
343
|
+
}
|
|
344
|
+
},
|
|
345
|
+
/**
|
|
346
|
+
* Phone-related fields
|
|
347
|
+
*/
|
|
348
|
+
phone: {
|
|
349
|
+
number() {
|
|
350
|
+
return createStringBuilder({ type: "string", hint: "phone.number" });
|
|
351
|
+
}
|
|
352
|
+
},
|
|
353
|
+
/**
|
|
354
|
+
* Image-related fields
|
|
355
|
+
*/
|
|
356
|
+
image: {
|
|
357
|
+
avatar() {
|
|
358
|
+
return createStringBuilder({ type: "string", hint: "image.avatar" });
|
|
359
|
+
},
|
|
360
|
+
url(options) {
|
|
361
|
+
const hint = options ? `image.url:${options.width || 640}x${options.height || 480}` : "image.url";
|
|
362
|
+
return createStringBuilder({ type: "string", hint });
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
/**
|
|
366
|
+
* Company-related fields
|
|
367
|
+
*/
|
|
368
|
+
company: {
|
|
369
|
+
name() {
|
|
370
|
+
return createStringBuilder({ type: "string", hint: "company.name" });
|
|
371
|
+
},
|
|
372
|
+
catchPhrase() {
|
|
373
|
+
return createStringBuilder({ type: "string", hint: "company.catchPhrase" });
|
|
374
|
+
}
|
|
375
|
+
},
|
|
376
|
+
/**
|
|
377
|
+
* Commerce-related fields
|
|
378
|
+
*/
|
|
379
|
+
commerce: {
|
|
380
|
+
productName() {
|
|
381
|
+
return createStringBuilder({ type: "string", hint: "commerce.productName" });
|
|
382
|
+
},
|
|
383
|
+
price() {
|
|
384
|
+
return createNumberBuilder({ type: "number", hint: "commerce.price" });
|
|
385
|
+
},
|
|
386
|
+
department() {
|
|
387
|
+
return createStringBuilder({ type: "string", hint: "commerce.department" });
|
|
388
|
+
}
|
|
389
|
+
},
|
|
390
|
+
// -------------------------------------------------------------------------
|
|
391
|
+
// Complex Types
|
|
392
|
+
// -------------------------------------------------------------------------
|
|
393
|
+
/**
|
|
394
|
+
* Enum field with type-safe values
|
|
395
|
+
* @param values - Allowed enum values
|
|
396
|
+
*
|
|
397
|
+
* @example
|
|
398
|
+
* ```typescript
|
|
399
|
+
* field.enum(['admin', 'user', 'guest']).default('user')
|
|
400
|
+
* ```
|
|
401
|
+
*/
|
|
402
|
+
enum(values) {
|
|
403
|
+
return createEnumBuilder(values);
|
|
404
|
+
},
|
|
405
|
+
/**
|
|
406
|
+
* Reference to another entity
|
|
407
|
+
* @param target - Target entity name
|
|
408
|
+
*
|
|
409
|
+
* @example
|
|
410
|
+
* ```typescript
|
|
411
|
+
* field.ref('user') // References the 'user' entity
|
|
412
|
+
* ```
|
|
413
|
+
*/
|
|
414
|
+
ref(target) {
|
|
415
|
+
return createRefBuilder(target);
|
|
416
|
+
},
|
|
417
|
+
/**
|
|
418
|
+
* Array of items
|
|
419
|
+
* @param itemType - The field definition for array items
|
|
420
|
+
*
|
|
421
|
+
* @example
|
|
422
|
+
* ```typescript
|
|
423
|
+
* field.array(field.string()) // Array of strings
|
|
424
|
+
* field.array(field.uuid()).length(5) // Fixed-length array
|
|
425
|
+
* ```
|
|
426
|
+
*/
|
|
427
|
+
array(itemType) {
|
|
428
|
+
return createArrayBuilder(itemType);
|
|
429
|
+
},
|
|
430
|
+
/**
|
|
431
|
+
* Nested object with defined shape
|
|
432
|
+
* @param shape - Object shape definition
|
|
433
|
+
*
|
|
434
|
+
* @example
|
|
435
|
+
* ```typescript
|
|
436
|
+
* field.object({
|
|
437
|
+
* street: field.location.streetAddress(),
|
|
438
|
+
* city: field.location.city(),
|
|
439
|
+
* zip: field.location.zipCode(),
|
|
440
|
+
* })
|
|
441
|
+
* ```
|
|
442
|
+
*/
|
|
443
|
+
object(shape) {
|
|
444
|
+
return createObjectBuilder(shape);
|
|
445
|
+
},
|
|
446
|
+
/**
|
|
447
|
+
* Computed field that derives its value from other fields or data
|
|
448
|
+
* @param config - Computed field configuration
|
|
449
|
+
*
|
|
450
|
+
* @example
|
|
451
|
+
* ```typescript
|
|
452
|
+
* field.computed({
|
|
453
|
+
* mock: () => faker.person.fullName(),
|
|
454
|
+
* resolve: (entity) => `${entity.firstName} ${entity.lastName}`,
|
|
455
|
+
* dependsOn: ['firstName', 'lastName'],
|
|
456
|
+
* })
|
|
457
|
+
* ```
|
|
458
|
+
*/
|
|
459
|
+
computed(config) {
|
|
460
|
+
return createComputedField(config);
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
// src/schema/relations.ts
|
|
465
|
+
function hasOne(target, options) {
|
|
466
|
+
return {
|
|
467
|
+
type: "hasOne",
|
|
468
|
+
target,
|
|
469
|
+
foreignKey: options?.foreignKey,
|
|
470
|
+
eager: options?.eager
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
function hasMany(target, options) {
|
|
474
|
+
return {
|
|
475
|
+
type: "hasMany",
|
|
476
|
+
target,
|
|
477
|
+
foreignKey: options?.foreignKey,
|
|
478
|
+
orderBy: options?.orderBy,
|
|
479
|
+
limit: options?.limit,
|
|
480
|
+
through: options?.through,
|
|
481
|
+
otherKey: options?.otherKey
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
function belongsTo(target, options) {
|
|
485
|
+
return {
|
|
486
|
+
type: "belongsTo",
|
|
487
|
+
target,
|
|
488
|
+
foreignKey: options?.foreignKey,
|
|
489
|
+
eager: options?.eager
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// src/schema/define-data.ts
|
|
494
|
+
function convertToFieldDefinition(field2) {
|
|
495
|
+
const isBuilder = "isNullable" in field2 || "isUnique" in field2 || "isReadOnly" in field2 || "defaultValue" in field2;
|
|
496
|
+
if (!isBuilder) {
|
|
497
|
+
return field2;
|
|
498
|
+
}
|
|
499
|
+
const builder = field2;
|
|
500
|
+
const definition = {
|
|
501
|
+
type: builder.type,
|
|
502
|
+
hint: builder.hint,
|
|
503
|
+
nullable: builder.isNullable,
|
|
504
|
+
unique: builder.isUnique,
|
|
505
|
+
readOnly: builder.isReadOnly,
|
|
506
|
+
default: builder.defaultValue,
|
|
507
|
+
constraints: builder.constraints,
|
|
508
|
+
target: builder.target,
|
|
509
|
+
values: builder.values
|
|
510
|
+
};
|
|
511
|
+
if (builder.items) {
|
|
512
|
+
definition.items = builder.items;
|
|
513
|
+
}
|
|
514
|
+
if (builder.shape) {
|
|
515
|
+
definition.shape = builder.shape;
|
|
516
|
+
}
|
|
517
|
+
return definition;
|
|
518
|
+
}
|
|
519
|
+
function defineData(name, definitions, options) {
|
|
520
|
+
const fields = {};
|
|
521
|
+
const relations = {};
|
|
522
|
+
const computed = {};
|
|
523
|
+
for (const [key, value] of Object.entries(definitions)) {
|
|
524
|
+
if (isComputedField(value)) {
|
|
525
|
+
computed[key] = value;
|
|
526
|
+
} else if (isRelation(value)) {
|
|
527
|
+
relations[key] = value;
|
|
528
|
+
} else {
|
|
529
|
+
const fieldValue = value;
|
|
530
|
+
fields[key] = convertToFieldDefinition(fieldValue);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
if (!fields.id) {
|
|
534
|
+
fields.id = {
|
|
535
|
+
type: "uuid",
|
|
536
|
+
hint: "string.uuid",
|
|
537
|
+
readOnly: true
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
const timestamps = options?.timestamps ?? true;
|
|
541
|
+
if (timestamps) {
|
|
542
|
+
if (!fields.createdAt) {
|
|
543
|
+
fields.createdAt = {
|
|
544
|
+
type: "date",
|
|
545
|
+
hint: "date.past",
|
|
546
|
+
readOnly: true
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
if (!fields.updatedAt) {
|
|
550
|
+
fields.updatedAt = {
|
|
551
|
+
type: "date",
|
|
552
|
+
hint: "date.recent",
|
|
553
|
+
readOnly: true
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
const schema = {
|
|
558
|
+
name,
|
|
559
|
+
fields,
|
|
560
|
+
timestamps,
|
|
561
|
+
api: options?.api,
|
|
562
|
+
rls: options?.rls
|
|
563
|
+
};
|
|
564
|
+
if (Object.keys(relations).length > 0) {
|
|
565
|
+
schema.relations = relations;
|
|
566
|
+
}
|
|
567
|
+
if (Object.keys(computed).length > 0) {
|
|
568
|
+
schema.computed = computed;
|
|
569
|
+
}
|
|
570
|
+
return schema;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// src/schema/define-view.ts
|
|
574
|
+
function embed(entity, config) {
|
|
575
|
+
return {
|
|
576
|
+
_embed: true,
|
|
577
|
+
entity,
|
|
578
|
+
config
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
function isEmbedMarker(value) {
|
|
582
|
+
return typeof value === "object" && value !== null && "_embed" in value && value._embed === true;
|
|
583
|
+
}
|
|
584
|
+
function pick(entity, fields) {
|
|
585
|
+
const result = {};
|
|
586
|
+
for (const fieldName of fields) {
|
|
587
|
+
if (fieldName in entity.fields) {
|
|
588
|
+
result[fieldName] = entity.fields[fieldName];
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
return result;
|
|
592
|
+
}
|
|
593
|
+
function omit(entity, fields) {
|
|
594
|
+
const result = { ...entity.fields };
|
|
595
|
+
for (const fieldName of fields) {
|
|
596
|
+
delete result[fieldName];
|
|
597
|
+
}
|
|
598
|
+
return result;
|
|
599
|
+
}
|
|
600
|
+
function defineView(name, fields, options) {
|
|
601
|
+
const processedFields = {};
|
|
602
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
603
|
+
if (isEmbedMarker(value)) {
|
|
604
|
+
processedFields[key] = {
|
|
605
|
+
_embed: true,
|
|
606
|
+
entity: value.entity,
|
|
607
|
+
config: value.config
|
|
608
|
+
};
|
|
609
|
+
} else if (typeof value === "object" && value !== null && !("type" in value) && !("_computed" in value)) {
|
|
610
|
+
processedFields[key] = value;
|
|
611
|
+
} else {
|
|
612
|
+
processedFields[key] = value;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
return {
|
|
616
|
+
name,
|
|
617
|
+
fields: processedFields,
|
|
618
|
+
endpoint: options.endpoint,
|
|
619
|
+
params: options.params
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// src/schema/define-endpoint.ts
|
|
624
|
+
function normalizeField(field2) {
|
|
625
|
+
const isBuilder = "isNullable" in field2 || "isUnique" in field2 || "isReadOnly" in field2 || "defaultValue" in field2;
|
|
626
|
+
if (!isBuilder) {
|
|
627
|
+
return field2;
|
|
628
|
+
}
|
|
629
|
+
const builder = field2;
|
|
630
|
+
const definition = {
|
|
631
|
+
type: builder.type,
|
|
632
|
+
hint: builder.hint,
|
|
633
|
+
nullable: builder.isNullable,
|
|
634
|
+
unique: builder.isUnique,
|
|
635
|
+
readOnly: builder.isReadOnly,
|
|
636
|
+
default: builder.defaultValue,
|
|
637
|
+
constraints: builder.constraints,
|
|
638
|
+
target: builder.target,
|
|
639
|
+
values: builder.values
|
|
640
|
+
};
|
|
641
|
+
if (builder.items) {
|
|
642
|
+
definition.items = builder.items;
|
|
643
|
+
}
|
|
644
|
+
if (builder.shape) {
|
|
645
|
+
definition.shape = builder.shape;
|
|
646
|
+
}
|
|
647
|
+
return definition;
|
|
648
|
+
}
|
|
649
|
+
function normalizeFields(fields) {
|
|
650
|
+
const result = {};
|
|
651
|
+
if (!fields) return result;
|
|
652
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
653
|
+
result[key] = normalizeField(value);
|
|
654
|
+
}
|
|
655
|
+
return result;
|
|
656
|
+
}
|
|
657
|
+
function defineEndpoint(path, config) {
|
|
658
|
+
if (!path.startsWith("/")) {
|
|
659
|
+
throw new Error(`Endpoint path must start with '/': ${path}`);
|
|
660
|
+
}
|
|
661
|
+
const params = normalizeFields(config.params);
|
|
662
|
+
const body = normalizeFields(config.body);
|
|
663
|
+
const response = normalizeFields(config.response);
|
|
664
|
+
if (Object.keys(body).length > 0 && config.method === "GET") {
|
|
665
|
+
console.warn(`Warning: GET endpoints typically don't have a body. Consider using params instead for ${path}`);
|
|
666
|
+
}
|
|
667
|
+
return {
|
|
668
|
+
path,
|
|
669
|
+
method: config.method,
|
|
670
|
+
params,
|
|
671
|
+
body,
|
|
672
|
+
response,
|
|
673
|
+
mockResolver: config.mockResolver,
|
|
674
|
+
description: config.description,
|
|
675
|
+
_endpoint: true
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
export { belongsTo, defineData, defineEndpoint, defineView, embed, field, hasMany, hasOne, isComputedField, isEmbedMarker, isEndpointSchema, isRelation, omit, pick };
|
|
680
|
+
//# sourceMappingURL=index.mjs.map
|
|
681
|
+
//# sourceMappingURL=index.mjs.map
|