The road to zero TypeScript errors (#1756)

* Type fixes

* Type fixes

* Type fixes

* Type fixes

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
Omar López 2022-02-10 03:44:46 -07:00 committed by GitHub
parent 798930bf23
commit 5d0ba3dafc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 54 additions and 53 deletions

2
environment.d.ts vendored
View File

@ -14,7 +14,7 @@ declare namespace NodeJS {
readonly ZOOM_CLIENT_SECRET: string | undefined;
readonly EMAIL_FROM: string | undefined;
readonly EMAIL_SERVER_HOST: string | undefined;
readonly EMAIL_SERVER_PORT: number | undefined;
readonly EMAIL_SERVER_PORT: string | undefined;
readonly EMAIL_SERVER_USER: string | undefined;
readonly EMAIL_SERVER_PASSWORD: string | undefined;
readonly CRON_API_KEY: string | undefined;

View File

@ -33,7 +33,7 @@ export const symmetricDecrypt = function (text: string, key: string) {
const _key = Buffer.from(key, "latin1");
const components = text.split(":");
const iv_from_ciphertext = Buffer.from(components.shift(), OUTPUT_ENCODING);
const iv_from_ciphertext = Buffer.from(components.shift() || "", OUTPUT_ENCODING);
const decipher = crypto.createDecipheriv(ALGORITHM, _key, iv_from_ciphertext);
let deciphered = decipher.update(components.join(":"), OUTPUT_ENCODING, INPUT_ENCODING);
deciphered += decipher.final(INPUT_ENCODING);

View File

@ -18,7 +18,7 @@ export interface EventResult {
success: boolean;
uid: string;
createdEvent?: Event;
updatedEvent?: Event;
updatedEvent?: Event | Event[];
originalEvent: CalendarEvent;
}
@ -207,9 +207,10 @@ export default class EventManager {
// If and only if event type is a dedicated meeting, update the dedicated video meeting.
if (isDedicated) {
const result = await this.updateVideoEvent(evt, booking);
if (result.updatedEvent) {
evt.videoCallData = result.updatedEvent;
evt.location = result.updatedEvent.url;
const [updatedEvent] = Array.isArray(result.updatedEvent) ? result.updatedEvent : [result.updatedEvent];
if (updatedEvent) {
evt.videoCallData = updatedEvent;
evt.location = updatedEvent.url;
}
results.push(result);
}

View File

@ -8,6 +8,7 @@ import { VideoCallData } from "@lib/videoClient";
import { NewCalendarEventType } from "../constants/types";
import { ConferenceData } from "./GoogleCalendar";
import type { Event } from "@lib/events/EventManager";
export type Person = {
name: string;
@ -66,7 +67,7 @@ type EventBusyDate = Record<"start" | "end", Date | string>;
export interface Calendar {
createEvent(event: CalendarEvent): Promise<NewCalendarEventType>;
updateEvent(uid: string, event: CalendarEvent): Promise<unknown>;
updateEvent(uid: string, event: CalendarEvent): Promise<Event | Event[]>;
deleteEvent(uid: string, event: CalendarEvent): Promise<unknown>;

View File

@ -25,6 +25,7 @@ import { CALDAV_CALENDAR_TYPE } from "../constants/generals";
import { CalendarEventType, EventBusyDate, NewCalendarEventType } from "../constants/types";
import { Calendar, CalendarEvent, IntegrationCalendar } from "../interfaces/Calendar";
import { convertDate, getAttendees, getDuration } from "../utils/CalendarUtils";
import type { Event } from "@lib/events/EventManager";
dayjs.extend(utc);
dayjs.extend(timezone);
@ -121,7 +122,7 @@ export default abstract class BaseCalendarService implements Calendar {
}
}
async updateEvent(uid: string, event: CalendarEvent): Promise<unknown> {
async updateEvent(uid: string, event: CalendarEvent) {
try {
const events = await this.getEventsByUID(uid);
@ -141,7 +142,12 @@ export default abstract class BaseCalendarService implements Calendar {
if (error) {
this.log.debug("Error creating iCalString");
return {};
return {
type: event.type,
id: typeof event.uid === "string" ? event.uid : "-1",
password: "",
url: typeof event.location === "string" ? event.location : "-1",
};
}
const eventsToUpdate = events.filter((e) => e.uid === uid);
@ -157,7 +163,7 @@ export default abstract class BaseCalendarService implements Calendar {
headers: this.headers,
});
})
);
).then((p) => p.map((r) => r.json() as unknown as Event));
} catch (reason) {
this.log.error(reason);

View File

@ -23,22 +23,22 @@ export function parseZone(
date,
{
utc: true,
...format,
...(typeof format === "string" ? { format } : { ...format }),
},
locale,
strict
);
}
const [, dateTime, sign, tzHour, tzMinute] = match;
const uOffset: number = tzHour * 60 + parseInt(tzMinute, 10);
const uOffset: number = parseInt(tzHour) * 60 + parseInt(tzMinute, 10);
const offset = sign === "+" ? uOffset : -uOffset;
return dayjs(
dateTime,
{
$offset: offset,
...format,
} as dayjs.OptionType,
...(typeof format === "string" ? { format } : { ...format }),
} as dayjs.OptionType & { $offset: number },
locale,
strict
);

View File

@ -1,10 +1,13 @@
function detectTransport(): string | any {
import SendmailTransport from "nodemailer/lib/sendmail-transport";
import SMTPConnection from "nodemailer/lib/smtp-connection";
function detectTransport(): SendmailTransport.Options | SMTPConnection.Options | string {
if (process.env.EMAIL_SERVER) {
return process.env.EMAIL_SERVER;
}
if (process.env.EMAIL_SERVER_HOST) {
const port = parseInt(process.env.EMAIL_SERVER_PORT);
const port = parseInt(process.env.EMAIL_SERVER_PORT!);
const transport = {
host: process.env.EMAIL_SERVER_HOST,
port,

View File

@ -1,31 +0,0 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { getSession } from "@lib/auth";
import prisma from "../../../lib/prisma";
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const session = await getSession({ req: req });
if (!session) {
res.status(401).json({ message: "Not authenticated" });
return;
}
if (req.method == "PATCH") {
const startMins = req.body.start;
const endMins = req.body.end;
await prisma.schedule.update({
where: {
id: session.user.id,
},
data: {
startTime: startMins,
endTime: endMins,
},
});
res.status(200).json({ message: "Start and end times updated successfully" });
}
}

View File

@ -533,9 +533,14 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
if (results.length) {
// TODO: Handle created event metadata more elegantly
metadata.hangoutLink = results[0].updatedEvent?.hangoutLink;
metadata.conferenceData = results[0].updatedEvent?.conferenceData;
metadata.entryPoints = results[0].updatedEvent?.entryPoints;
const [updatedEvent] = Array.isArray(results[0].updatedEvent)
? results[0].updatedEvent
: [results[0].updatedEvent];
if (updatedEvent) {
metadata.hangoutLink = updatedEvent.hangoutLink;
metadata.conferenceData = updatedEvent.conferenceData;
metadata.entryPoints = updatedEvent.entryPoints;
}
}
await sendRescheduledEmails({ ...evt, additionInformation: metadata });

View File

@ -5,6 +5,7 @@ import { getSession } from "@lib/auth";
import prisma from "@lib/prisma";
import { resizeBase64Image } from "@server/lib/resizeBase64Image";
import { PrismaClientKnownRequestError } from "@prisma/client/runtime";
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const session = await getSession({ req: req });
@ -36,8 +37,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
},
});
} catch (e) {
if (e.code === "P2002") {
return res.status(409).json({ message: "Username already taken" });
if (e instanceof PrismaClientKnownRequestError) {
if (e.code === "P2002") {
return res.status(409).json({ message: "Username already taken" });
}
}
throw e;
}

View File

@ -1,10 +1,11 @@
import { getSession } from "@lib/auth";
import { NextPageContext } from "next";
function RedirectPage() {
return;
}
export async function getServerSideProps(context) {
export async function getServerSideProps(context: NextPageContext) {
const session = await getSession(context);
if (!session?.user?.id) {
return { redirect: { permanent: false, destination: "/auth/login" } };

View File

@ -6,6 +6,7 @@ import { WEBHOOK_TRIGGER_EVENTS } from "@lib/webhooks/constants";
import sendPayload from "@lib/webhooks/sendPayload";
import { createProtectedRouter } from "@server/createRouter";
import { getTranslation } from "@server/lib/i18n";
export const webhookRouter = createProtectedRouter()
.query("list", {
@ -94,6 +95,11 @@ export const webhookRouter = createProtectedRouter()
}),
async resolve({ input }) {
const { url, type, payloadTemplate } = input;
const translation = await getTranslation("en", "common");
const language = {
locale: "en",
translate: translation,
};
const data = {
type: "Test",
@ -106,12 +112,14 @@ export const webhookRouter = createProtectedRouter()
email: "jdoe@example.com",
name: "John Doe",
timeZone: "Europe/London",
language,
},
],
organizer: {
name: "Cal",
email: "",
timeZone: "Europe/London",
language,
},
};

View File

@ -10,6 +10,8 @@ it("can find lucky users", async () => {
timeZone: "GMT",
bufferTime: 0,
email: "test@example.com",
destinationCalendar: null,
locale: "en",
},
{
id: 2,
@ -19,6 +21,8 @@ it("can find lucky users", async () => {
timeZone: "GMT",
bufferTime: 0,
email: "test2@example.com",
destinationCalendar: null,
locale: "en",
},
];
expect(