Skip to content

Commit

Permalink
remove stringifyDates, not needed as JSON serializer converts to ISO …
Browse files Browse the repository at this point in the history
…string as well (#133)
  • Loading branch information
kahlstrm committed May 19, 2024
1 parent 31bc6d6 commit 51efaec
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 45 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"lint": "eslint packages",
"lint:fix": "npm run lint -- --fix",
"typecheck": "pnpm run -r --workspace-concurrency=1 typecheck",
"test": "pnpm run -r test"
"test": "pnpm run -r test",
"test:backend": "pnpm run --filter ilmomasiina-backend test"
},
"repository": {
"type": "git",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Op, WhereOptions } from 'sequelize';
import type { AuditLogResponse, AuditLoqQuery } from '@tietokilta/ilmomasiina-models';
import { auditLoqQuery } from '@tietokilta/ilmomasiina-models';
import { AuditLog } from '../../../models/auditlog';
import { stringifyDates } from '../../utils';
import { StringifyApi } from '../../utils';

const MAX_LOGS = 100;

Expand Down Expand Up @@ -57,11 +57,12 @@ export default async function getAuditLogItems(
});

response.status(200);
return {
rows: logs.rows.map((r) => stringifyDates({
const res = {
rows: logs.rows.map((r) => ({
...r.get({ plain: true }),
createdAt: r.createdAt,
})),
count: logs.count,
};
return res as unknown as StringifyApi<typeof res>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Event } from '../../../models/event';
import { Question } from '../../../models/question';
import { Quota } from '../../../models/quota';
import { eventDetailsForAdmin } from '../../events/getEventDetails';
import { stringifyDates, toDate } from '../../utils';
import { toDate } from '../../utils';

export default async function createEvent(
request: FastifyRequest<{ Body: EventCreateBody }>,
Expand Down Expand Up @@ -55,5 +55,5 @@ export default async function createEvent(
const eventDetails = await eventDetailsForAdmin(event.id);

response.status(201);
return stringifyDates(eventDetails);
return eventDetails;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { Event } from '../../models/event';
import { Question } from '../../models/question';
import { Quota } from '../../models/quota';
import { Signup } from '../../models/signup';
import { stringifyDates } from '../utils';
import { StringifyApi } from '../utils';

export async function eventDetailsForUser(
eventSlug: EventSlug,
Expand Down Expand Up @@ -87,15 +87,15 @@ export async function eventDetailsForUser(
registrationClosed = now > endDate;
}

return {
...stringifyDates(event.get({ plain: true })),
const res = {
...(event.get({ plain: true })),
questions: event.questions!.map((question) => question.get({ plain: true })),
quotas: quotas.map((quota) => ({
...quota.get({ plain: true }),
signups: event.signupsPublic // Hide all signups from non-admins if answers are not public
// When signups are public:
? quota.signups!.map((signup) => ({
...stringifyDates(signup.get({ plain: true })),
...(signup.get({ plain: true })),
// Hide name if necessary
firstName: event.nameQuestion && signup.namePublic ? signup.firstName : null,
lastName: event.nameQuestion && signup.namePublic ? signup.lastName : null,
Expand All @@ -111,6 +111,7 @@ export async function eventDetailsForUser(
millisTillOpening,
registrationClosed,
};
return res as unknown as StringifyApi<typeof res>;
}

export async function eventDetailsForAdmin(
Expand Down Expand Up @@ -165,7 +166,7 @@ export async function eventDetailsForAdmin(
});

// Admins get a simple result with many columns
return stringifyDates({
const res = {
...event.get({ plain: true }),
questions: event.questions!.map((question) => question.get({ plain: true })),
updatedAt: event.updatedAt,
Expand All @@ -179,7 +180,8 @@ export async function eventDetailsForAdmin(
})),
signupCount: quota.signups!.length,
})),
});
};
return res as unknown as StringifyApi<typeof res>;
}

export async function getEventDetailsForUser(
Expand Down
10 changes: 5 additions & 5 deletions packages/ilmomasiina-backend/src/routes/events/getEventsList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Quota } from '../../models/quota';
import { Signup } from '../../models/signup';
import { ascNullsFirst } from '../../models/util';
import { InitialSetupNeeded, isInitialSetupDone } from '../admin/users/createInitialUser';
import { stringifyDates } from '../utils';
import { StringifyApi } from '../utils';

function eventOrder(): Order {
return [
Expand Down Expand Up @@ -60,15 +60,15 @@ export async function getEventsListForUser(
});

const res = events.map((event) => ({
...stringifyDates(event.get({ plain: true })),
...event.get({ plain: true }),
quotas: event.quotas!.map((quota) => ({
...quota.get({ plain: true }),
signupCount: Number(quota.signupCount),
})),
}));

reply.status(200);
return res;
return res as StringifyApi<typeof res>;
}
export async function getEventsListForAdmin(
request: FastifyRequest<{ Querystring: EventListQuery }>,
Expand Down Expand Up @@ -103,13 +103,13 @@ export async function getEventsListForAdmin(
});

const res = events.map((event) => ({
...stringifyDates(event.get({ plain: true })),
...event.get({ plain: true }),
quotas: event.quotas!.map((quota) => ({
...quota.get({ plain: true }),
signupCount: Number(quota.signupCount!),
})),
}));

reply.status(200);
return res;
return res as StringifyApi<typeof res>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Event } from '../../models/event';
import { Question } from '../../models/question';
import { Quota } from '../../models/quota';
import { Signup } from '../../models/signup';
import { stringifyDates } from '../utils';
import { StringifyApi } from '../utils';
import { NoSuchSignup } from './errors';

/** Requires editTokenVerification */
Expand Down Expand Up @@ -46,19 +46,19 @@ export default async function getSignupForEdit(

const response = {
signup: {
...stringifyDates(signup.get({ plain: true })),
...signup.get({ plain: true }),
confirmed: Boolean(signup.confirmedAt),
status: signup.status,
answers: signup.answers!,
quota: signup.quota!,
},
event: {
...stringifyDates(event.get({ plain: true })),
...event.get({ plain: true }),
questions: event.questions!.map((question) => question.get({ plain: true })),
},
};

reply.status(200);

return response;
return response as unknown as StringifyApi<typeof response>;
}
30 changes: 6 additions & 24 deletions packages/ilmomasiina-backend/src/routes/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/** Converts given value to a Date if it is a string, and otherwise just passthroughs the input */
// eslint-disable-next-line import/prefer-default-export
export function toDate<T>(s: T): Date | Exclude<T, string> {
return typeof s === 'string' ? new Date(s) : s as Exclude<T, string>;
}
Expand All @@ -8,32 +9,13 @@ export type StringifyApi<T> = {
[P in keyof T]: (
// all arrays are stringified recursively
T[P] extends (infer E)[] ? StringifyApi<E>[]
// Date | null --> string | null
// Date --> string
// (also matches "x: null", but that's an useless type anyway)
// Date | null --> string | null
// Date --> string
// (also matches "x: null", but that's an useless type anyway)
: T[P] extends Date | null ? (null extends T[P] ? string | null : string)
// basic types: any subset of boolean | number | string | null --> itself
// basic types: any subset of boolean | number | string | null --> itself
: T[P] extends boolean | number | string | null ? T[P]
// other types (essentially, objects) are stringified recursively
// other types (essentially, objects) are stringified recursively
: StringifyApi<T[P]>
);
};

/** Recursively converts all `Date` objects in the given object to strings. */
export function stringifyDates<T>(obj: T): StringifyApi<T> {
if (typeof obj !== 'object' || obj === null) {
return obj as any;
}
if (Array.isArray(obj)) {
return obj.map(stringifyDates) as any;
}
return Object.fromEntries(Object.entries(obj).map(([key, val]) => {
if (val instanceof Date) {
return [key, val.toISOString()];
}
if (typeof val === 'object' && val !== null) {
return [key, stringifyDates(val)];
}
return [key, val];
})) as any;
}

0 comments on commit 51efaec

Please sign in to comment.