Skip to content

Commit 00ca27d

Browse files
committed
feat(discussion): parse user name response
- remove unused UserNameResponse types and only keep relevant fields - join all errors responses instead of only picking the first one
1 parent a1b4a69 commit 00ca27d

File tree

3 files changed

+39
-64
lines changed

3 files changed

+39
-64
lines changed

dotcom-rendering/src/components/Discussion/CommentForm.tsx

+2-3
Original file line numberDiff line numberDiff line change
@@ -421,13 +421,12 @@ export const CommentForm = ({
421421
}
422422

423423
const response = await addUserName(user.authStatus, userName);
424-
if (response.status === 'ok') {
424+
if (response.kind === 'ok') {
425425
// If we are able to submit userName we should continue with submitting comment
426426
void submitForm();
427427
setUserNameMissing(false);
428428
} else {
429-
response.errors &&
430-
setError(response.errors[0]?.message ?? 'unknown error');
429+
setError(response.error);
431430
}
432431
};
433432

dotcom-rendering/src/lib/discussionApi.tsx

+22-4
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ import type {
88
GetDiscussionSuccess,
99
OrderByType,
1010
ThreadsType,
11-
UserNameResponse,
1211
} from '../types/discussion';
1312
import {
1413
discussionApiResponseSchema,
1514
parseAbuseResponse,
1615
parseCommentRepliesResponse,
1716
parseCommentResponse,
17+
postUsernameResponseSchema,
1818
} from '../types/discussion';
1919
import type { SignedInWithCookies, SignedInWithOkta } from './identity';
2020
import { getOptionsHeadersWithOkta } from './identity';
@@ -337,11 +337,11 @@ export const recommend =
337337
export const addUserName = async (
338338
authStatus: SignedInWithCookies | SignedInWithOkta,
339339
userName: string,
340-
): Promise<UserNameResponse> => {
340+
): Promise<Result<string, true>> => {
341341
const url = options.idApiUrl + `/user/me/username`;
342342
const authOptions = getOptionsHeadersWithOkta(authStatus);
343343

344-
const resp = await fetch(url, {
344+
const jsonResult = await fetchJSON(url, {
345345
method: 'POST',
346346
body: JSON.stringify({
347347
publicFields: {
@@ -356,7 +356,25 @@ export const addUserName = async (
356356
credentials: authOptions.credentials,
357357
});
358358

359-
return resp.json();
359+
if (jsonResult.kind === 'error') {
360+
return jsonResult;
361+
}
362+
363+
const result = safeParse(postUsernameResponseSchema, jsonResult.value);
364+
365+
if (!result.success) {
366+
return { kind: 'error', error: 'An unknown error occured' };
367+
}
368+
if (result.output.status === 'error') {
369+
return {
370+
kind: 'error',
371+
error: result.output.errors
372+
.map(({ message }) => message)
373+
.join('\n'),
374+
};
375+
}
376+
377+
return { kind: 'ok', value: true };
360378
};
361379

362380
export const pickComment = async (

dotcom-rendering/src/types/discussion.ts

+15-57
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
boolean,
55
integer,
66
literal,
7+
minLength,
78
number,
89
object,
910
optional,
@@ -252,63 +253,20 @@ export const parseAbuseResponse = (data: unknown): Result<string, true> => {
252253
: { kind: 'error', error: output.message };
253254
};
254255

255-
type UserNameError = {
256-
message: string;
257-
description: string;
258-
context: string;
259-
};
260-
261-
type UserConsents = {
262-
id: string;
263-
actor: string;
264-
version: number;
265-
consented: boolean;
266-
timestamp: string;
267-
privacyPolicyVersion: number;
268-
};
269-
270-
type UserGroups = {
271-
path: string;
272-
packageCode: string;
273-
};
274-
275-
type UserNameUser = {
276-
dates: { accountCreatedDate: string };
277-
consents: UserConsents[];
278-
userGroups: UserGroups[];
279-
publicFields: {
280-
username: string;
281-
displayName: string;
282-
};
283-
statusFields: {
284-
userEmailValidated: boolean;
285-
};
286-
privateFields: {
287-
legacyPackages: string;
288-
legacyProducts: string;
289-
// Optional fields. See scala @ https://github.com/guardian/identity/blob/07142212b1571d5f8e0a60585c6511abb3620f8c/identity-model-play/src/main/scala/com/gu/identity/model/play/PrivateFields.scala#L5-L18
290-
brazeUuid?: string;
291-
puzzleUuid?: string;
292-
googleTagId?: string;
293-
firstName?: string;
294-
secondName?: string;
295-
registrationIp?: string;
296-
lastActiveIpAddress?: string;
297-
registrationType?: string;
298-
registrationPlatform?: string;
299-
telephoneNumber?: string;
300-
title?: string;
301-
};
302-
primaryEmailAddress: string;
303-
id: string;
304-
hasPassword: boolean;
305-
};
306-
307-
export type UserNameResponse = {
308-
status: 'ok' | 'error';
309-
user: UserNameUser;
310-
errors?: UserNameError[];
311-
};
256+
export const postUsernameResponseSchema = variant('status', [
257+
object({
258+
status: literal('error'),
259+
errors: array(
260+
object({
261+
message: string(),
262+
}),
263+
[minLength(1)],
264+
),
265+
}),
266+
object({
267+
status: literal('ok'),
268+
}),
269+
]);
312270

313271
const orderBy = ['newest', 'oldest', 'recommendations'] as const;
314272
export const isOrderBy = guard(orderBy);

0 commit comments

Comments
 (0)