-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcontract.zod.ts
More file actions
182 lines (163 loc) · 5.54 KB
/
contract.zod.ts
File metadata and controls
182 lines (163 loc) · 5.54 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
173
174
175
176
177
178
179
180
181
182
import { z } from 'zod';
import { QuerySchema } from '../data/query.zod';
// ==========================================
// 1. Base Envelopes
// ==========================================
export const ApiErrorSchema = z.object({
code: z.string().describe('Error code (e.g. validation_error)'),
message: z.string().describe('Readable error message'),
category: z.string().optional().describe('Error category (e.g. validation, authorization)'),
details: z.unknown().optional().describe('Additional error context (e.g. field validation errors)'),
requestId: z.string().optional().describe('Request ID for tracking'),
});
export const BaseResponseSchema = z.object({
success: z.boolean().describe('Operation success status'),
error: ApiErrorSchema.optional().describe('Error details if success is false'),
meta: z.object({
timestamp: z.string(),
duration: z.number().optional(),
requestId: z.string().optional(),
traceId: z.string().optional(),
}).optional().describe('Response metadata'),
});
// ==========================================
// 2. Request Payloads (Inputs)
// ==========================================
export const RecordDataSchema = z.record(z.string(), z.unknown()).describe('Key-value map of record data');
/**
* Standard Create Request
*/
export const CreateRequestSchema = z.object({
data: RecordDataSchema.describe('Record data to insert'),
});
/**
* Standard Update Request
*/
export const UpdateRequestSchema = z.object({
data: RecordDataSchema.describe('Partial record data to update'),
});
/**
* Standard Bulk Request
*/
export const BulkRequestSchema = z.object({
records: z.array(RecordDataSchema).describe('Array of records to process'),
allOrNone: z.boolean().default(true).describe('If true, rollback entire transaction on any failure'),
});
/**
* Export Request
*/
export const ExportRequestSchema = z.intersection(
QuerySchema,
z.object({
format: z.enum(['csv', 'json', 'xlsx']).default('csv'),
})
);
// ==========================================
// 3. Response Payloads (Outputs)
// ==========================================
/**
* Single Record Response (Get/Create/Update)
*/
export const SingleRecordResponseSchema = BaseResponseSchema.extend({
data: RecordDataSchema.describe('The requested or modified record'),
});
/**
* List/Query Response
*/
export const ListRecordResponseSchema = BaseResponseSchema.extend({
data: z.array(RecordDataSchema).describe('Array of matching records'),
pagination: z.object({
total: z.number().optional().describe('Total matching records count'),
limit: z.number().optional().describe('Page size'),
offset: z.number().optional().describe('Page offset'),
cursor: z.string().optional().describe('Cursor for next page'),
nextCursor: z.string().optional().describe('Next cursor for pagination'),
hasMore: z.boolean().describe('Are there more pages?'),
}).describe('Pagination info'),
});
/**
* ID Request (Get/Delete)
*/
export const IdRequestSchema = z.object({
id: z.string().describe('Record ID'),
});
/**
* Modification Result (for Batch/Bulk operations)
*/
export const ModificationResultSchema = z.object({
id: z.string().optional().describe('Record ID if processed'),
success: z.boolean(),
errors: z.array(ApiErrorSchema).optional(),
index: z.number().optional().describe('Index in original request'),
data: z.unknown().optional().describe('Result data (e.g. created record)'),
});
/**
* Bulk Operation Response
*/
export const BulkResponseSchema = BaseResponseSchema.extend({
data: z.array(ModificationResultSchema).describe('Results for each item in the batch'),
});
/**
* Delete Response
*/
export const DeleteResponseSchema = BaseResponseSchema.extend({
id: z.string().describe('ID of the deleted record'),
});
// ==========================================
// 4. API Contract Registry
// ==========================================
/**
* Standard API Contracts map
* Used for generating SDKs and Documentation
*/
export const StandardApiContracts = {
create: {
input: CreateRequestSchema,
output: SingleRecordResponseSchema
},
delete: {
input: IdRequestSchema,
output: DeleteResponseSchema
},
get: {
input: IdRequestSchema,
output: SingleRecordResponseSchema
},
update: {
input: UpdateRequestSchema,
output: SingleRecordResponseSchema
},
list: {
input: QuerySchema,
output: ListRecordResponseSchema
},
bulkCreate: {
input: BulkRequestSchema,
output: BulkResponseSchema
},
bulkUpdate: {
input: BulkRequestSchema,
output: BulkResponseSchema
},
bulkUpsert: {
input: BulkRequestSchema,
output: BulkResponseSchema
},
bulkDelete: {
input: z.object({ ids: z.array(z.string()) }),
output: BulkResponseSchema
}
};
export type ApiError = z.infer<typeof ApiErrorSchema>;
export type BaseResponse = z.infer<typeof BaseResponseSchema>;
export type RecordData = z.infer<typeof RecordDataSchema>;
export type CreateRequest = z.infer<typeof CreateRequestSchema>;
export type UpdateRequest = z.infer<typeof UpdateRequestSchema>;
export type BulkRequest = z.infer<typeof BulkRequestSchema>;
export type ExportRequest = z.infer<typeof ExportRequestSchema>;
export type SingleRecordResponse = z.infer<typeof SingleRecordResponseSchema>;
export type ListRecordResponse = z.infer<typeof ListRecordResponseSchema>;
export type IdRequest = z.infer<typeof IdRequestSchema>;
export type ModificationResult = z.infer<typeof ModificationResultSchema>;
export type BulkResponse = z.infer<typeof BulkResponseSchema>;
export type DeleteResponse = z.infer<typeof DeleteResponseSchema>;