Skip to content

Commit cc795d3

Browse files
committed
wip: cast object to map
1 parent 44fc44a commit cc795d3

File tree

3 files changed

+67
-37
lines changed

3 files changed

+67
-37
lines changed

itest/test/attachments.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ beforeAll(async () => {
6868
});
6969

7070
test('Get single attachment', async () => {
71+
await expect(api.getAttachment(1)).resolves.toMatchInlineSnapshot();
72+
7173
await expect(api.getAttachment(1)).resolves.toEqual({
7274
bug_id: expect.anything(),
7375
content_type: 'image/png',

src/link.ts

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { URLSearchParams, URL } from 'url';
2-
import { z } from 'zod';
2+
import { z, ZodSchema } from 'zod';
33

44
import axios, { AxiosRequestConfig } from 'axios';
55
import { loginResponseSchema } from './types';
@@ -28,10 +28,10 @@ function isError(payload: unknown): payload is ApiError {
2828
return payload && typeof payload == 'object' && payload.error;
2929
}
3030

31-
async function performRequest<TValues>(
32-
config: AxiosRequestConfig,
33-
schema: z.Schema<TValues>,
34-
): Promise<TValues> {
31+
async function performRequest<
32+
TSchema extends ZodSchema,
33+
KValues extends z.infer<TSchema>,
34+
>(config: AxiosRequestConfig, schema: TSchema): Promise<KValues> {
3535
try {
3636
let response = await axios.request({
3737
...config,
@@ -67,10 +67,10 @@ export abstract class BugzillaLink {
6767
this.instance = new URL('rest/', instance);
6868
}
6969

70-
protected abstract request<TValues>(
71-
config: AxiosRequestConfig,
72-
schema: z.Schema<TValues>,
73-
): Promise<TValues>;
70+
protected abstract request<
71+
TSchema extends ZodSchema,
72+
KValues extends z.infer<TSchema>,
73+
>(config: AxiosRequestConfig, schema: TSchema): Promise<KValues>;
7474

7575
protected buildURL(path: string, query?: SearchParams): URL {
7676
let url = new URL(path, this.instance);
@@ -80,11 +80,11 @@ export abstract class BugzillaLink {
8080
return url;
8181
}
8282

83-
public async get<TValues>(
83+
public async get<TSchema extends ZodSchema, KValues extends z.infer<TSchema>>(
8484
path: string,
85-
schema: z.Schema<TValues>,
85+
schema: TSchema,
8686
searchParams?: SearchParams,
87-
): Promise<TValues> {
87+
): Promise<KValues> {
8888
return this.request(
8989
{
9090
url: this.buildURL(path, searchParams).toString(),
@@ -93,12 +93,16 @@ export abstract class BugzillaLink {
9393
);
9494
}
9595

96-
public async post<R, TValues>(
96+
public async post<
97+
R,
98+
TSchema extends ZodSchema,
99+
KValues extends z.infer<TSchema>,
100+
>(
97101
path: string,
98-
schema: z.Schema<TValues>,
102+
schema: TSchema,
99103
content: R,
100104
searchParams?: SearchParams,
101-
): Promise<TValues> {
105+
): Promise<KValues> {
102106
return this.request(
103107
{
104108
url: this.buildURL(path, searchParams).toString(),
@@ -112,12 +116,16 @@ export abstract class BugzillaLink {
112116
);
113117
}
114118

115-
public async put<R, TValues>(
119+
public async put<
120+
R,
121+
TSchema extends ZodSchema,
122+
KValues extends z.infer<TSchema>,
123+
>(
116124
path: string,
117-
schema: z.Schema<TValues>,
125+
schema: TSchema,
118126
content: R,
119127
searchParams?: SearchParams,
120-
): Promise<TValues> {
128+
): Promise<KValues> {
121129
return this.request(
122130
{
123131
url: this.buildURL(path, searchParams).toString(),
@@ -133,10 +141,10 @@ export abstract class BugzillaLink {
133141
}
134142

135143
export class PublicLink extends BugzillaLink {
136-
protected async request<TValues>(
137-
config: AxiosRequestConfig,
138-
schema: z.Schema<TValues>,
139-
): Promise<TValues> {
144+
protected async request<
145+
TSchema extends ZodSchema,
146+
KValues extends z.infer<TSchema>,
147+
>(config: AxiosRequestConfig, schema: TSchema): Promise<KValues> {
140148
return performRequest(config, schema);
141149
}
142150
}
@@ -152,10 +160,10 @@ export class ApiKeyLink extends BugzillaLink {
152160
super(instance);
153161
}
154162

155-
protected async request<TValues>(
156-
config: AxiosRequestConfig,
157-
schema: z.Schema<TValues>,
158-
): Promise<TValues> {
163+
protected async request<
164+
TSchema extends ZodSchema,
165+
KValues extends z.infer<TSchema>,
166+
>(config: AxiosRequestConfig, schema: TSchema): Promise<KValues> {
159167
return performRequest(
160168
{
161169
...config,
@@ -201,10 +209,10 @@ export class PasswordLink extends BugzillaLink {
201209
return loginInfo.token;
202210
}
203211

204-
protected async request<TValues>(
205-
config: AxiosRequestConfig,
206-
schema: z.Schema<TValues>,
207-
): Promise<TValues> {
212+
protected async request<
213+
TSchema extends ZodSchema,
214+
KValues extends z.infer<TSchema>,
215+
>(config: AxiosRequestConfig, schema: TSchema): Promise<KValues> {
208216
if (!this.token) {
209217
this.token = await this.login();
210218
}

src/types.ts

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,29 @@ export const commentsTemplateSchema = z.object({
144144

145145
export type CommentsTemplate = z.infer<typeof commentsTemplateSchema>;
146146

147+
function castObjectToMap<K extends z.ZodTypeAny, V extends z.ZodTypeAny>(
148+
keyValidator: K,
149+
valueValidator: V,
150+
) {
151+
return z.record(keyValidator, valueValidator).transform(record => {
152+
let result = new Map<z.infer<K>, z.infer<V>>();
153+
154+
for (let [k, v] of Object.entries(record)) {
155+
// if (typeof k === 'number') {
156+
// result.set(k, v);
157+
// }
158+
if (k?.toString()) {
159+
result.set(k.toString(), v);
160+
}
161+
}
162+
163+
return result;
164+
});
165+
}
166+
147167
export const commentsSchema = z.object({
148-
bugs: z.map(z.number(), commentsTemplateSchema),
149-
comments: z.map(z.number(), commentSchema),
168+
bugs: castObjectToMap(z.number(), commentsTemplateSchema),
169+
comments: castObjectToMap(z.number(), commentSchema),
150170
});
151171

152172
export type Comments = z.infer<typeof commentsSchema>;
@@ -222,7 +242,7 @@ export const updateBugContentSchema = z.object({
222242
cc: updateListSchema(z.string()).optional(),
223243
is_cc_accessible: z.boolean().optional(),
224244
comment: createCommentContentSchema.optional(),
225-
comment_is_private: z.map(z.number(), z.boolean()).optional(),
245+
comment_is_private: castObjectToMap(z.number(), z.boolean()).optional(),
226246
comment_tags: z.array(z.string()).optional(),
227247
component: z.string().optional(),
228248
deadline: z.string().datetime().optional(),
@@ -262,7 +282,7 @@ export const updatedBugSchema = z.object({
262282
id: z.number(),
263283
alias: z.array(z.string()),
264284
last_change_time: z.string().datetime(),
265-
changes: z.map(z.string(), changesSchema),
285+
changes: castObjectToMap(z.string(), changesSchema),
266286
});
267287

268288
export type UpdatedBug = z.infer<typeof updatedBugSchema>;
@@ -294,8 +314,8 @@ export const attachmentSchema = z.object({
294314
export type Attachment = z.infer<typeof attachmentSchema>;
295315

296316
export const attachmentsSchema = z.object({
297-
bugs: z.map(z.number(), z.array(attachmentSchema)),
298-
attachments: z.map(z.number(), attachmentSchema),
317+
bugs: castObjectToMap(z.number(), z.array(attachmentSchema)),
318+
attachments: castObjectToMap(z.number(), attachmentSchema),
299319
});
300320

301321
export type Attachments = z.infer<typeof attachmentsSchema>;
@@ -343,7 +363,7 @@ export type UpdateAttachmentContent = z.infer<
343363
export const updatedAttachmentSchema = z.object({
344364
id: z.number(),
345365
last_change_time: z.string().datetime(),
346-
changes: z.map(z.string(), changesSchema),
366+
changes: castObjectToMap(z.string(), changesSchema),
347367
});
348368

349369
export type UpdatedAttachment = z.infer<typeof updatedAttachmentSchema>;

0 commit comments

Comments
 (0)