chore: Typescript database models (#2886)

closes #2798
This commit is contained in:
Tom Moor
2022-01-06 18:24:28 -08:00
committed by GitHub
parent d3cbf250e6
commit b20a341f0c
207 changed files with 5624 additions and 5315 deletions

View File

@@ -33,7 +33,7 @@ describe("documents.publish", () => {
const otherDocument = await buildDocument();
await otherDocument.destroy();
const document = await buildDocument({
version: null,
version: 0,
text: `[ ] checklist item`,
});
document.text = `[this is a link](${otherDocument.url})`;
@@ -54,6 +54,7 @@ describe("documents.publish", () => {
expect(backlinks.length).toBe(0);
});
});
describe("documents.update", () => {
test("should not fail on a document with no previous revisions", async () => {
const otherDocument = await buildDocument();
@@ -79,7 +80,7 @@ describe("documents.update", () => {
test("should not fail when previous revision is different document version", async () => {
const otherDocument = await buildDocument();
const document = await buildDocument({
version: null,
version: undefined,
text: `[ ] checklist item`,
});
document.text = `[this is a link](${otherDocument.url})`;
@@ -158,6 +159,7 @@ describe("documents.update", () => {
expect(backlinks[0].documentId).toBe(yetAnotherDocument.id);
});
});
describe("documents.delete", () => {
test("should destroy related backlinks", async () => {
const otherDocument = await buildDocument();
@@ -188,6 +190,7 @@ describe("documents.delete", () => {
expect(backlinks.length).toBe(0);
});
});
describe("documents.title_change", () => {
test("should update titles in backlinked documents", async () => {
const newTitle = "test";

View File

@@ -1,5 +1,5 @@
import { Op } from "sequelize";
import { Document, Backlink, Team } from "@server/models";
import { Op } from "@server/sequelize";
import parseDocumentIds from "@server/utils/parseDocumentIds";
import slugify from "@server/utils/slugify";
import { DocumentEvent, RevisionEvent } from "../../types";
@@ -105,7 +105,6 @@ export default class BacklinksProcessor {
],
});
await Promise.all(
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'backlink' implicitly has an 'any' type.
backlinks.map(async (backlink) => {
const previousUrl = `/doc/${slugify(previousTitle)}-${
document.urlId

View File

@@ -1,4 +1,4 @@
import { Document } from "@server/models";
import Document from "@server/models/Document";
import { globalEventQueue } from "../../queues";
import { Event } from "../../types";
@@ -17,7 +17,7 @@ export default class DebounceProcessor {
case "documents.update.delayed": {
const document = await Document.findByPk(event.documentId, {
fields: ["updatedAt"],
attributes: ["updatedAt"],
});
// If the document has been deleted then prevent further processing

View File

@@ -1,10 +1,11 @@
import fs from "fs";
import invariant from "invariant";
import Logger from "@server/logging/logger";
import mailer from "@server/mailer";
import { FileOperation, Collection, Event, Team, User } from "@server/models";
import { Event as TEvent } from "@server/types";
import { uploadToS3FromBuffer } from "@server/utils/s3";
import { archiveCollections } from "@server/utils/zip";
import Logger from "../../logging/logger";
import mailer from "../../mailer";
import { Event as TEvent } from "../../types";
export default class ExportsProcessor {
async on(event: TEvent) {
@@ -13,8 +14,14 @@ export default class ExportsProcessor {
case "collections.export_all": {
const { actorId, teamId } = event;
const team = await Team.findByPk(teamId);
invariant(team, "team operation not found");
const user = await User.findByPk(actorId);
invariant(user, "user operation not found");
const exportData = await FileOperation.findByPk(event.modelId);
invariant(exportData, "exportData not found");
const collectionIds =
// @ts-expect-error ts-migrate(2339) FIXME: Property 'collectionId' does not exist on type 'Co... Remove this comment to see the full error message
event.collectionId || (await user.collectionIds());
@@ -91,7 +98,6 @@ export default class ExportsProcessor {
}
async updateFileOperation(
// @ts-expect-error ts-migrate(2749) FIXME: 'FileOperation' refers to a value, but is being us... Remove this comment to see the full error message
fileOperation: FileOperation,
actorId: string,
teamId: string,
@@ -102,6 +108,7 @@ export default class ExportsProcessor {
name: "fileOperations.update",
teamId,
actorId,
// @ts-expect-error dataValues exists
data: fileOperation.dataValues,
});
}

View File

@@ -1,6 +1,7 @@
import fs from "fs";
import os from "os";
import File from "formidable/lib/file";
import invariant from "invariant";
import collectionImporter from "@server/commands/collectionImporter";
import { Attachment, User } from "@server/models";
import { Event } from "../../types";
@@ -11,14 +12,18 @@ export default class ImportsProcessor {
case "collections.import": {
const { type } = event.data;
const attachment = await Attachment.findByPk(event.modelId);
invariant(attachment, "attachment not found");
const user = await User.findByPk(event.actorId);
const buffer = await attachment.buffer;
invariant(user, "user not found");
const buffer: any = await attachment.buffer;
const tmpDir = os.tmpdir();
const tmpFilePath = `${tmpDir}/upload-${event.modelId}`;
await fs.promises.writeFile(tmpFilePath, buffer);
const file = new File({
name: attachment.name,
type: attachment.type,
type: attachment.contentType,
path: tmpFilePath,
});
await collectionImporter({

View File

@@ -1,3 +1,4 @@
import mailer from "@server/mailer";
import { View, NotificationSetting } from "@server/models";
import {
buildDocument,
@@ -5,13 +6,14 @@ import {
buildUser,
} from "@server/test/factories";
import { flushdb } from "@server/test/support";
import mailer from "../../mailer";
import NotificationsService from "./notifications";
jest.mock("../../mailer");
jest.mock("@server/mailer");
const Notifications = new NotificationsService();
beforeEach(() => flushdb());
beforeEach(jest.resetAllMocks);
describe("documents.publish", () => {
test("should not send a notification to author", async () => {
const user = await buildUser();
@@ -24,13 +26,16 @@ describe("documents.publish", () => {
teamId: user.teamId,
event: "documents.publish",
});
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{ name: "documents.publish"; doc... Remove this comment to see the full error message
await Notifications.on({
name: "documents.publish",
documentId: document.id,
collectionId: document.collectionId,
teamId: document.teamId,
actorId: document.createdById,
ip: "127.0.0.1",
data: {
title: document.title,
},
});
expect(mailer.documentNotification).not.toHaveBeenCalled();
});
@@ -45,13 +50,17 @@ describe("documents.publish", () => {
teamId: user.teamId,
event: "documents.publish",
});
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{ name: "documents.publish"; doc... Remove this comment to see the full error message
await Notifications.on({
name: "documents.publish",
documentId: document.id,
collectionId: document.collectionId,
teamId: document.teamId,
actorId: document.createdById,
ip: "127.0.0.1",
data: {
title: document.title,
},
});
expect(mailer.documentNotification).toHaveBeenCalled();
});
@@ -71,17 +80,21 @@ describe("documents.publish", () => {
teamId: user.teamId,
event: "documents.publish",
});
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{ name: "documents.publish"; doc... Remove this comment to see the full error message
await Notifications.on({
name: "documents.publish",
documentId: document.id,
collectionId: document.collectionId,
teamId: document.teamId,
actorId: document.createdById,
ip: "127.0.0.1",
data: {
title: document.title,
},
});
expect(mailer.documentNotification).not.toHaveBeenCalled();
});
});
describe("revisions.create", () => {
test("should send a notification to other collaborators", async () => {
const document = await buildDocument();
@@ -100,8 +113,6 @@ describe("revisions.create", () => {
documentId: document.id,
collectionId: document.collectionId,
teamId: document.teamId,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{ name: "revisions.create"; docu... Remove this comment to see the full error message
actorId: document.createdById,
});
expect(mailer.documentNotification).toHaveBeenCalled();
});
@@ -124,8 +135,6 @@ describe("revisions.create", () => {
documentId: document.id,
collectionId: document.collectionId,
teamId: document.teamId,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{ name: "revisions.create"; docu... Remove this comment to see the full error message
actorId: document.createdById,
});
expect(mailer.documentNotification).not.toHaveBeenCalled();
});
@@ -146,8 +155,6 @@ describe("revisions.create", () => {
documentId: document.id,
collectionId: document.collectionId,
teamId: document.teamId,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '{ name: "revisions.create"; docu... Remove this comment to see the full error message
actorId: document.createdById,
});
expect(mailer.documentNotification).not.toHaveBeenCalled();
});

View File

@@ -1,3 +1,6 @@
import { Op } from "sequelize";
import Logger from "@server/logging/logger";
import mailer from "@server/mailer";
import {
View,
Document,
@@ -6,15 +9,12 @@ import {
User,
NotificationSetting,
} from "@server/models";
import { Op } from "@server/sequelize";
import Logger from "../../logging/logger";
import mailer from "../../mailer";
import {
DocumentEvent,
CollectionEvent,
RevisionEvent,
Event,
} from "../../types";
} from "@server/types";
export default class NotificationsProcessor {
async on(event: Event) {
@@ -106,6 +106,10 @@ export default class NotificationsProcessor {
continue;
}
if (!setting.user.email) {
continue;
}
mailer.documentNotification({
to: setting.user.email,
eventName,
@@ -149,7 +153,7 @@ export default class NotificationsProcessor {
for (const setting of notificationSettings) {
// Suppress notifications for suspended users
if (setting.user.isSuspended) {
if (setting.user.isSuspended || !setting.user.email) {
continue;
}

View File

@@ -70,7 +70,7 @@ export default class SlackProcessor {
Document.findByPk(event.documentId),
Team.findByPk(event.teamId),
]);
if (!document) return;
if (!document || !team) return;
// never send notifications for draft documents
if (!document.publishedAt) return;

View File

@@ -1,4 +1,5 @@
import { subHours } from "date-fns";
import { Op } from "sequelize";
import {
Document,
Collection,
@@ -8,7 +9,6 @@ import {
Pin,
} from "@server/models";
import { presentPin } from "@server/presenters";
import { Op } from "@server/sequelize";
import { Event } from "../../types";
export default class WebsocketsProcessor {
@@ -21,6 +21,10 @@ export default class WebsocketsProcessor {
const document = await Document.findByPk(event.documentId, {
paranoid: false,
});
if (!document) {
return;
}
const channel = document.publishedAt
? `collection-${document.collectionId}`
: `user-${event.actorId}`;
@@ -44,6 +48,9 @@ export default class WebsocketsProcessor {
const document = await Document.findByPk(event.documentId, {
paranoid: false,
});
if (!document) {
return;
}
if (!document.publishedAt) {
return socketio.to(`user-${document.createdById}`).emit("entities", {
@@ -87,6 +94,9 @@ export default class WebsocketsProcessor {
const document = await Document.findByPk(event.documentId, {
paranoid: false,
});
if (!document) {
return;
}
const channel = document.publishedAt
? `collection-${document.collectionId}`
: `user-${event.actorId}`;
@@ -103,6 +113,9 @@ export default class WebsocketsProcessor {
case "documents.create": {
const document = await Document.findByPk(event.documentId);
if (!document) {
return;
}
return socketio.to(`user-${event.actorId}`).emit("entities", {
event: event.name,
documentIds: [
@@ -133,7 +146,6 @@ export default class WebsocketsProcessor {
},
paranoid: false,
});
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'document' implicitly has an 'any' type.
documents.forEach((document) => {
socketio.to(`collection-${document.collectionId}`).emit("entities", {
event: event.name,
@@ -162,6 +174,9 @@ export default class WebsocketsProcessor {
const collection = await Collection.findByPk(event.collectionId, {
paranoid: false,
});
if (!collection) {
return;
}
socketio
.to(
collection.permission
@@ -194,6 +209,9 @@ export default class WebsocketsProcessor {
const collection = await Collection.findByPk(event.collectionId, {
paranoid: false,
});
if (!collection) {
return;
}
return socketio.to(`team-${collection.teamId}`).emit("entities", {
event: event.name,
collectionIds: [
@@ -270,6 +288,9 @@ export default class WebsocketsProcessor {
case "collections.add_group": {
const group = await Group.findByPk(event.data.groupId);
if (!group) {
return;
}
// the users being added are not yet in the websocket channel for the collection
// so they need to be notified separately
@@ -293,6 +314,10 @@ export default class WebsocketsProcessor {
case "collections.remove_group": {
const group = await Group.findByPk(event.data.groupId);
if (!group) {
return;
}
const membershipUserIds = await Collection.membershipUserIds(
event.collectionId
);
@@ -337,6 +362,9 @@ export default class WebsocketsProcessor {
case "pins.create":
case "pins.update": {
const pin = await Pin.findByPk(event.modelId);
if (!pin) {
return;
}
return socketio
.to(
pin.collectionId
@@ -363,6 +391,9 @@ export default class WebsocketsProcessor {
const group = await Group.findByPk(event.modelId, {
paranoid: false,
});
if (!group) {
return;
}
return socketio.to(`team-${group.teamId}`).emit("entities", {
event: event.name,
groupIds: [
@@ -462,6 +493,10 @@ export default class WebsocketsProcessor {
const group = await Group.findByPk(event.modelId, {
paranoid: false,
});
if (!group) {
return;
}
socketio.to(`team-${group.teamId}`).emit("entities", {
event: event.name,
groupIds: [