Compare commits

..

1 Commits

Author SHA1 Message Date
Tom Moor 98f975cf07 Switch Linear to actor=app method 2025-04-27 10:57:27 -04:00
35 changed files with 104 additions and 163 deletions
+2 -3
View File
@@ -6,7 +6,6 @@ import { v4 } from "uuid";
import { EmbedDescriptor } from "@shared/editor/embeds";
import { MenuItem } from "@shared/editor/types";
import { MentionType } from "@shared/types";
import { isUrl } from "@shared/utils/urls";
import Integration from "~/models/Integration";
import useCurrentUser from "~/hooks/useCurrentUser";
import useStores from "~/hooks/useStores";
@@ -30,9 +29,9 @@ export const PasteMenu = observer(({ pastedText, embeds, ...props }: Props) => {
const user = useCurrentUser({ rejectOnEmpty: false });
let mentionType: MentionType | undefined;
const url = pastedText ? new URL(pastedText) : undefined;
if (pastedText && isUrl(pastedText)) {
const url = new URL(pastedText);
if (url) {
const integration = integrations.find((intg: Integration) =>
isURLMentionable({ url, integration: intg })
);
+3 -3
View File
@@ -174,7 +174,7 @@
"passport-oauth2": "^1.8.0",
"passport-slack-oauth2": "^1.2.0",
"patch-package": "^7.0.2",
"pg": "^8.15.6",
"pg": "^8.14.1",
"pg-tsquery": "^8.4.2",
"pluralize": "^8.0.0",
"png-chunks-extract": "^1.0.0",
@@ -209,7 +209,7 @@
"react-i18next": "^12.3.1",
"react-medium-image-zoom": "5.2.13",
"react-merge-refs": "^2.1.1",
"react-portal": "^4.3.0",
"react-portal": "^4.2.2",
"react-router-dom": "^5.3.4",
"react-virtualized-auto-sizer": "^1.0.26",
"react-waypoint": "^10.3.0",
@@ -356,7 +356,7 @@
"jest-environment-jsdom": "^29.7.0",
"jest-fetch-mock": "^3.0.3",
"lint-staged": "^13.3.0",
"nodemon": "^3.1.10",
"nodemon": "^3.1.9",
"postinstall-postinstall": "^2.1.0",
"prettier": "^2.8.8",
"react-refresh": "^0.14.2",
+5 -5
View File
@@ -77,14 +77,14 @@ router.get(
{ transaction }
);
transaction.afterCommit(async () => {
if (workspace.logoUrl) {
await new UploadLinearWorkspaceLogoTask().schedule({
if (workspace.logoUrl) {
transaction.afterCommit(async () => {
await UploadLinearWorkspaceLogoTask.schedule({
integrationId: integration.id,
logoUrl: workspace.logoUrl,
});
}
});
});
}
ctx.redirect(LinearUtils.successUrl());
}
@@ -66,6 +66,6 @@ export class NotionImportsProcessor extends ImportsProcessor<IntegrationService.
protected async scheduleTask(
importTask: ImportTask<IntegrationService.Notion>
): Promise<void> {
await new NotionAPIImportTask().schedule({ importTaskId: importTask.id });
await NotionAPIImportTask.schedule({ importTaskId: importTask.id });
}
}
@@ -77,7 +77,7 @@ export default class NotionAPIImportTask extends APIImportTask<IntegrationServic
protected async scheduleNextTask(
importTask: ImportTask<IntegrationService.Notion>
) {
await new NotionAPIImportTask().schedule({ importTaskId: importTask.id });
await NotionAPIImportTask.schedule({ importTaskId: importTask.id });
return;
}
@@ -29,12 +29,8 @@ describe("WebhookProcessor", () => {
await processor.perform(event);
expect(
jest.mocked(DeliverWebhookTask.prototype.schedule)
).toHaveBeenCalled();
expect(
jest.mocked(DeliverWebhookTask.prototype.schedule)
).toHaveBeenCalledWith({
expect(DeliverWebhookTask.schedule).toHaveBeenCalled();
expect(DeliverWebhookTask.schedule).toHaveBeenCalledWith({
event,
subscriptionId: subscription.id,
});
@@ -57,9 +53,7 @@ describe("WebhookProcessor", () => {
await processor.perform(event);
expect(
jest.mocked(DeliverWebhookTask.prototype.schedule)
).toHaveBeenCalledTimes(0);
expect(DeliverWebhookTask.schedule).toHaveBeenCalledTimes(0);
});
it("it schedules a delivery for the event for each subscription", async () => {
@@ -85,21 +79,13 @@ describe("WebhookProcessor", () => {
await processor.perform(event);
expect(
jest.mocked(DeliverWebhookTask.prototype.schedule)
).toHaveBeenCalled();
expect(
jest.mocked(DeliverWebhookTask.prototype.schedule)
).toHaveBeenCalledTimes(2);
expect(
jest.mocked(DeliverWebhookTask.prototype.schedule)
).toHaveBeenCalledWith({
expect(DeliverWebhookTask.schedule).toHaveBeenCalled();
expect(DeliverWebhookTask.schedule).toHaveBeenCalledTimes(2);
expect(DeliverWebhookTask.schedule).toHaveBeenCalledWith({
event,
subscriptionId: subscription.id,
});
expect(
jest.mocked(DeliverWebhookTask.prototype.schedule)
).toHaveBeenCalledWith({
expect(DeliverWebhookTask.schedule).toHaveBeenCalledWith({
event,
subscriptionId: subscriptionTwo.id,
});
@@ -24,10 +24,7 @@ export default class WebhookProcessor extends BaseProcessor {
await Promise.all(
applicableSubscriptions.map((subscription) =>
new DeliverWebhookTask().schedule({
event,
subscriptionId: subscription.id,
})
DeliverWebhookTask.schedule({ event, subscriptionId: subscription.id })
)
);
}
+1 -1
View File
@@ -24,7 +24,7 @@ type Props = {
/** Position of moved document within document structure */
index?: number;
/** The IP address of the user moving the document */
ip: string | null;
ip: string;
/** The database transaction to run within */
transaction?: Transaction;
};
@@ -4,11 +4,9 @@ import DeleteAttachmentTask from "@server/queues/tasks/DeleteAttachmentTask";
import { buildAttachment, buildDocument } from "@server/test/factories";
import documentPermanentDeleter from "./documentPermanentDeleter";
jest.mock("@server/queues/tasks/DeleteAttachmentTask");
beforeEach(() => {
jest.resetAllMocks();
});
jest.mock("@server/queues/tasks/DeleteAttachmentTask", () => ({
schedule: jest.fn(),
}));
describe("documentPermanentDeleter", () => {
it("should destroy documents", async () => {
@@ -62,9 +60,7 @@ describe("documentPermanentDeleter", () => {
await document.save();
const countDeletedDoc = await documentPermanentDeleter([document]);
expect(countDeletedDoc).toEqual(1);
expect(
jest.mocked(DeleteAttachmentTask.prototype.schedule)
).toHaveBeenCalledTimes(2);
expect(DeleteAttachmentTask.schedule).toHaveBeenCalledTimes(2);
expect(
await Document.unscoped().count({
where: {
+1 -1
View File
@@ -67,7 +67,7 @@ export default async function documentPermanentDeleter(documents: Document[]) {
"commands",
`Attachment ${attachmentId} scheduled for deletion`
);
await new DeleteAttachmentTask().schedule({
await DeleteAttachmentTask.schedule({
attachmentId,
teamId: document.teamId,
});
+1 -1
View File
@@ -56,5 +56,5 @@ export default async function userSuspender({
}
);
await new CleanupDemotedUserTask().schedule({ userId: user.id });
await CleanupDemotedUserTask.schedule({ userId: user.id });
}
+1 -1
View File
@@ -408,7 +408,7 @@ class Team extends ParanoidModel<
});
if (attachment) {
await new DeleteAttachmentTask().schedule({
await DeleteAttachmentTask.schedule({
attachmentId: attachment.id,
teamId: model.id,
});
+1 -1
View File
@@ -717,7 +717,7 @@ class User extends ParanoidModel<
});
if (attachment) {
await new DeleteAttachmentTask().schedule({
await DeleteAttachmentTask.schedule({
attachmentId: attachment.id,
teamId: model.teamId,
});
+2 -2
View File
@@ -17,7 +17,7 @@ export default class AvatarProcessor extends BaseProcessor {
});
if (user.avatarUrl) {
await new UploadUserAvatarTask().schedule({
await UploadUserAvatarTask.schedule({
userId: event.userId,
avatarUrl: user.avatarUrl,
});
@@ -30,7 +30,7 @@ export default class AvatarProcessor extends BaseProcessor {
});
if (team.avatarUrl) {
await new UploadTeamAvatarTask().schedule({
await UploadTeamAvatarTask.schedule({
teamId: event.teamId,
avatarUrl: team.avatarUrl,
});
@@ -12,7 +12,7 @@ export default class CollectionsProcessor extends BaseProcessor {
];
async perform(event: CollectionEvent) {
await new DetachDraftsFromCollectionTask().schedule({
await DetachDraftsFromCollectionTask.schedule({
collectionId: event.collectionId,
actorId: event.actorId,
ip: event.ip,
@@ -27,7 +27,7 @@ export default class DocumentSubscriptionProcessor extends BaseProcessor {
async perform(event: ReceivedEvent) {
switch (event.name) {
case "collections.remove_user": {
await new CollectionSubscriptionRemoveUserTask().schedule(event);
await CollectionSubscriptionRemoveUserTask.schedule(event);
return;
}
@@ -35,7 +35,7 @@ export default class DocumentSubscriptionProcessor extends BaseProcessor {
return this.handleRemoveGroupFromCollection(event);
case "documents.remove_user": {
await new DocumentSubscriptionRemoveUserTask().schedule(event);
await DocumentSubscriptionRemoveUserTask.schedule(event);
return;
}
@@ -57,11 +57,11 @@ export default class DocumentSubscriptionProcessor extends BaseProcessor {
async (groupUsers) => {
await Promise.all(
groupUsers.map((groupUser) =>
new CollectionSubscriptionRemoveUserTask().schedule({
CollectionSubscriptionRemoveUserTask.schedule({
...event,
name: "collections.remove_user",
userId: groupUser.userId,
} as CollectionUserEvent)
})
)
);
}
@@ -79,11 +79,11 @@ export default class DocumentSubscriptionProcessor extends BaseProcessor {
async (groupUsers) => {
await Promise.all(
groupUsers.map((groupUser) =>
new DocumentSubscriptionRemoveUserTask().schedule({
DocumentSubscriptionRemoveUserTask.schedule({
...event,
name: "documents.remove_user",
userId: groupUser.userId,
} as DocumentUserEvent)
})
)
);
}
@@ -20,12 +20,12 @@ export default class FileOperationCreatedProcessor extends BaseProcessor {
if (fileOperation.type === FileOperationType.Import) {
switch (fileOperation.format) {
case FileOperationFormat.MarkdownZip:
await new ImportMarkdownZipTask().schedule({
await ImportMarkdownZipTask.schedule({
fileOperationId: event.modelId,
});
break;
case FileOperationFormat.JSON:
await new ImportJSONTask().schedule({
await ImportJSONTask.schedule({
fileOperationId: event.modelId,
});
break;
@@ -36,17 +36,17 @@ export default class FileOperationCreatedProcessor extends BaseProcessor {
if (fileOperation.type === FileOperationType.Export) {
switch (fileOperation.format) {
case FileOperationFormat.HTMLZip:
await new ExportHTMLZipTask().schedule({
await ExportHTMLZipTask.schedule({
fileOperationId: event.modelId,
});
break;
case FileOperationFormat.MarkdownZip:
await new ExportMarkdownZipTask().schedule({
await ExportMarkdownZipTask.schedule({
fileOperationId: event.modelId,
});
break;
case FileOperationFormat.JSON:
await new ExportJSONTask().schedule({
await ExportJSONTask.schedule({
fileOperationId: event.modelId,
});
break;
@@ -20,7 +20,7 @@ export default class IntegrationCreatedProcessor extends BaseProcessor {
}
// Store the available issue sources in the integration record.
await new CacheIssueSourcesTask().schedule({
await CacheIssueSourcesTask.schedule({
integrationId: integration.id,
});
@@ -62,25 +62,25 @@ export default class NotificationsProcessor extends BaseProcessor {
return;
}
await new DocumentPublishedNotificationsTask().schedule(event);
await DocumentPublishedNotificationsTask.schedule(event);
}
async documentAddUser(event: DocumentUserEvent) {
if (!event.data.isNew || event.userId === event.actorId) {
return;
}
await new DocumentAddUserNotificationsTask().schedule(event);
await DocumentAddUserNotificationsTask.schedule(event);
}
async documentAddGroup(event: DocumentGroupEvent) {
if (!event.data.isNew) {
return;
}
await new DocumentAddGroupNotificationsTask().schedule(event);
await DocumentAddGroupNotificationsTask.schedule(event);
}
async revisionCreated(event: RevisionEvent) {
await new RevisionCreatedNotificationsTask().schedule(event);
await RevisionCreatedNotificationsTask.schedule(event);
}
async collectionCreated(event: CollectionEvent) {
@@ -93,7 +93,7 @@ export default class NotificationsProcessor extends BaseProcessor {
return;
}
await new CollectionCreatedNotificationsTask().schedule(event);
await CollectionCreatedNotificationsTask.schedule(event);
}
async collectionAddUser(event: CollectionUserEvent) {
@@ -101,14 +101,14 @@ export default class NotificationsProcessor extends BaseProcessor {
return;
}
await new CollectionAddUserNotificationsTask().schedule(event);
await CollectionAddUserNotificationsTask.schedule(event);
}
async commentCreated(event: CommentEvent) {
await new CommentCreatedNotificationsTask().schedule(event);
await CommentCreatedNotificationsTask.schedule(event);
}
async commentUpdated(event: CommentEvent) {
await new CommentUpdatedNotificationsTask().schedule(event);
await CommentUpdatedNotificationsTask.schedule(event);
}
}
@@ -37,7 +37,7 @@ export default class RevisionsProcessor extends BaseProcessor {
return;
}
await new DocumentUpdateTextTask().schedule(event);
await DocumentUpdateTextTask.schedule(event);
const user = await User.findByPk(event.actorId, {
paranoid: false,
@@ -6,6 +6,6 @@ export default class UserDemotedProcessor extends BaseProcessor {
static applicableEvents: TEvent["name"][] = ["users.demote"];
async perform(event: UserEvent) {
await new CleanupDemotedUserTask().schedule({ userId: event.userId });
await CleanupDemotedUserTask.schedule({ userId: event.userId });
}
}
+1 -3
View File
@@ -325,9 +325,7 @@ export default abstract class APIImportTask<
([url, attachment]) => ({ attachmentId: attachment.id, url })
);
// publish task after attachments are persisted in DB.
const job = await new UploadAttachmentsForImportTask().schedule(
uploadItems
);
const job = await UploadAttachmentsForImportTask.schedule(uploadItems);
await job.finished();
} catch (err) {
// upload attachments failure is not critical enough to fail the whole import.
+1 -18
View File
@@ -21,7 +21,7 @@ export default abstract class BaseTask<T extends Record<string, any>> {
static cron: TaskSchedule | undefined;
/**
* Schedule this task type to be processed asynchronously by a worker.
* Schedule this task type to be processed asyncronously by a worker.
*
* @param props Properties to be used by the task
* @returns A promise that resolves once the job is placed on the task queue
@@ -39,23 +39,6 @@ export default abstract class BaseTask<T extends Record<string, any>> {
);
}
/**
* Schedule this task type to be processed asynchronously by a worker.
*
* @param props Properties to be used by the task
* @param options Job options such as priority and retry strategy, as defined by Bull.
* @returns A promise that resolves once the job is placed on the task queue
*/
public schedule(props: T, options?: JobOptions): Promise<Job> {
return taskQueue.add(
{
name: this.constructor.name,
props,
},
{ ...options, ...this.options }
);
}
/**
* Execute the task.
*
@@ -29,7 +29,7 @@ export default class CleanupDeletedTeamsTask extends BaseTask<Props> {
});
for (const team of teams) {
await new CleanupDeletedTeamTask().schedule({
await CleanupDeletedTeamTask.schedule({
teamId: team.id,
});
}
@@ -7,7 +7,7 @@ import BaseTask from "./BaseTask";
type Props = {
collectionId: string;
actorId: string;
ip: string | null;
ip: string;
};
export default class DetachDraftsFromCollectionTask extends BaseTask<Props> {
@@ -1,6 +1,6 @@
import { Op } from "sequelize";
import { GroupUser } from "@server/models";
import { DocumentGroupEvent, DocumentUserEvent } from "@server/types";
import { DocumentGroupEvent } from "@server/types";
import BaseTask, { TaskPriority } from "./BaseTask";
import DocumentAddUserNotificationsTask from "./DocumentAddUserNotificationsTask";
@@ -19,12 +19,11 @@ export default class DocumentAddGroupNotificationsTask extends BaseTask<Document
async (groupUsers) => {
await Promise.all(
groupUsers.map(async (groupUser) => {
await new DocumentAddUserNotificationsTask().schedule({
await DocumentAddUserNotificationsTask.schedule({
...event,
name: "documents.add_user",
modelId: event.data.membershipId,
userId: groupUser.userId,
} as DocumentUserEvent);
});
})
);
}
+1 -1
View File
@@ -12,7 +12,7 @@ type Props = {
sourceMetadata: Pick<Required<SourceMetadata>, "fileName" | "mimeType">;
publish?: boolean;
collectionId?: string;
parentDocumentId?: string | null;
parentDocumentId?: string;
ip: string;
key: string;
};
@@ -38,7 +38,7 @@ export default class UpdateTeamsAttachmentsSizeTask extends BaseTask<Props> {
const teamIds = rows.map((row) => row.teamId);
for (const teamId of teamIds) {
await new UpdateTeamAttachmentsSizeTask().schedule({ teamId });
await UpdateTeamAttachmentsSizeTask.schedule({ teamId });
}
}
);
+1 -1
View File
@@ -166,7 +166,7 @@ router.post(
)
);
const job = await new UploadAttachmentFromUrlTask().schedule({
const job = await UploadAttachmentFromUrlTask.schedule({
attachmentId: attachment.id,
url,
});
+1 -1
View File
@@ -135,7 +135,7 @@ router.post("auth.info", auth(), async (ctx: APIContext<T.AuthInfoReq>) => {
// If the user did not _just_ sign in then we need to check if they continue
// to have access to the workspace they are signed into.
if (user.lastSignedInAt && user.lastSignedInAt < subHours(new Date(), 1)) {
await new ValidateSSOAccessTask().schedule({ userId: user.id });
await ValidateSSOAccessTask.schedule({ userId: user.id });
}
ctx.body = {
+3 -6
View File
@@ -29,8 +29,7 @@ const cronHandler = async (ctx: APIContext<T.CronSchemaReq>) => {
for (const name in tasks) {
const TaskClass = tasks[name];
if (TaskClass.cron === period) {
// @ts-expect-error We won't instantiate an abstract class
await new TaskClass().schedule({ limit });
await TaskClass.schedule({ limit });
// Backwards compatibility for installations that have not set up
// cron jobs periods other than daily.
@@ -39,15 +38,13 @@ const cronHandler = async (ctx: APIContext<T.CronSchemaReq>) => {
!receivedPeriods.has(TaskSchedule.Minute) &&
(period === TaskSchedule.Hour || period === TaskSchedule.Day)
) {
// @ts-expect-error We won't instantiate an abstract class
await new TaskClass().schedule({ limit });
await TaskClass.schedule({ limit });
} else if (
TaskClass.cron === TaskSchedule.Hour &&
!receivedPeriods.has(TaskSchedule.Hour) &&
period === TaskSchedule.Day
) {
// @ts-expect-error We won't instantiate an abstract class
await new TaskClass().schedule({ limit });
await TaskClass.schedule({ limit });
}
}
+2 -3
View File
@@ -1539,7 +1539,7 @@ router.post(
acl,
});
const job = await new DocumentImportTask().schedule({
const job = await DocumentImportTask.schedule({
key,
sourceMetadata: {
fileName,
@@ -1549,7 +1549,6 @@ router.post(
collectionId,
parentDocumentId,
publish,
ip: ctx.request.ip,
});
const response: DocumentImportTaskResponse = await job.finished();
if ("error" in response) {
@@ -2063,7 +2062,7 @@ router.post(
});
if (documents.length) {
await new EmptyTrashTask().schedule({
await EmptyTrashTask.schedule({
documentIds: documents.map((doc) => doc.id),
});
}
+1 -2
View File
@@ -7,8 +7,7 @@ export default function init() {
for (const name in tasks) {
const TaskClass = tasks[name];
if (TaskClass.cron === schedule) {
// @ts-expect-error We won't instantiate an abstract class
await new TaskClass().schedule({ limit: 10000 });
await TaskClass.schedule({ limit: 10000 });
}
}
}
+1 -13
View File
@@ -4,7 +4,6 @@ import cookie from "cookie";
import Koa from "koa";
import IO from "socket.io";
import { createAdapter } from "socket.io-redis";
import env from "@server/env";
import { AuthenticationError } from "@server/errors";
import Logger from "@server/logging/Logger";
import Metrics from "@server/logging/Metrics";
@@ -39,8 +38,7 @@ export default function init(
pingInterval: 15000,
pingTimeout: 30000,
cors: {
// Included for completeness, though CORS does not apply to websocket transport.
origin: env.isCloudHosted ? "*" : env.URL,
origin: "*",
methods: ["GET", "POST"],
},
});
@@ -62,16 +60,6 @@ export default function init(
"upgrade",
function (req: IncomingMessage, socket: Duplex, head: Buffer) {
if (req.url?.startsWith(path) && ioHandleUpgrade) {
// For on-premise deployments, ensure the websocket origin matches the deployed URL.
// In cloud-hosted we support any origin for custom domains.
if (
!env.isCloudHosted &&
(!req.headers.origin || !env.URL.startsWith(req.headers.origin))
) {
socket.end(`HTTP/1.1 400 Bad Request\r\n`);
return;
}
ioHandleUpgrade(req, socket, head);
return;
}
+32 -32
View File
@@ -12246,10 +12246,10 @@ nodemailer@^6.10.0:
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.10.0.tgz#1f24c9de94ad79c6206f66d132776b6503003912"
integrity sha512-SQ3wZCExjeSatLE/HBaXS5vqUOQk6GtBdIIKxiFdmm01mOQZX/POJkO3SUX1wDiYcwUOJwT23scFSC9fY2H8IA==
nodemon@^3.1.10:
version "3.1.10"
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.1.10.tgz#5015c5eb4fffcb24d98cf9454df14f4fecec9bc1"
integrity sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==
nodemon@^3.1.9:
version "3.1.9"
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.1.9.tgz#df502cdc3b120e1c3c0c6e4152349019efa7387b"
integrity sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==
dependencies:
chokidar "^3.5.2"
debug "^4"
@@ -12830,30 +12830,30 @@ performance-now@^2.1.0:
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
pg-cloudflare@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.2.5.tgz#2e3649c38a7a9c74a7e5327c8098a2fd9af595bd"
integrity sha512-OOX22Vt0vOSRrdoUPKJ8Wi2OpE/o/h9T8X1s4qSkCedbNah9ei2W2765be8iMVxQUsvgT7zIAT2eIa9fs5+vtg==
pg-cloudflare@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz#e6d5833015b170e23ae819e8c5d7eaedb472ca98"
integrity "sha1-5tWDMBWxcOI66Bnoxdfq7bRyypg= sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q=="
pg-connection-string@^2.6.1, pg-connection-string@^2.8.5:
version "2.8.5"
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.8.5.tgz#82cefd0269cb64a09603342d9b69e8392e6eb6cd"
integrity sha512-Ni8FuZ8yAF+sWZzojvtLE2b03cqjO5jNULcHFfM9ZZ0/JXrgom5pBREbtnAw7oxsxJqHw9Nz/XWORUEL3/IFow==
pg-connection-string@^2.6.1, pg-connection-string@^2.7.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.7.0.tgz#f1d3489e427c62ece022dba98d5262efcb168b37"
integrity sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==
pg-int8@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c"
integrity "sha1-lDvUY79bcbQXARX4D478mgwOt4w= sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="
pg-pool@^3.9.6:
version "3.9.6"
resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.9.6.tgz#c6fde89dee615d6c262724e68a3a37e9593157fc"
integrity sha512-rFen0G7adh1YmgvrmE5IPIqbb+IgEzENUm+tzm6MLLDSlPRoZVhzU1WdML9PV2W5GOdRA9qBKURlbt1OsXOsPw==
pg-pool@^3.8.0:
version "3.8.0"
resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.8.0.tgz#e6bce7fc4506a8d6106551363fc5283e5445b776"
integrity sha512-VBw3jiVm6ZOdLBTIcXLNdSotb6Iy3uOCwDGFAksZCXmi10nyRvnP2v3jl4d+IsLYRyXf6o9hIm/ZtUzlByNUdw==
pg-protocol@^1.9.5:
version "1.9.5"
resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.9.5.tgz#e544eff37d6ab79c26281d7c0b59ac9be4862686"
integrity sha512-DYTWtWpfd5FOro3UnAfwvhD8jh59r2ig8bPtc9H8Ds7MscE/9NYruUQWFAOuraRl29jwcT2kyMFQ3MxeaVjUhg==
pg-protocol@^1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.8.0.tgz#c707101dd07813868035a44571488e4b98639d48"
integrity sha512-jvuYlEkL03NRvOoyoRktBK7+qU5kOvlAwvmrH8sr3wbLrOdVWsRxQfz8mMy9sZFsqJ1hEWNfdWKI4SAmoL+j7g==
pg-tsquery@^8.4.2:
version "8.4.2"
@@ -12871,18 +12871,18 @@ pg-types@^2.1.0:
postgres-date "~1.0.4"
postgres-interval "^1.1.0"
pg@^8.15.6:
version "8.15.6"
resolved "https://registry.yarnpkg.com/pg/-/pg-8.15.6.tgz#2a28e98fb6cab18b886ce58b2c184d712a94880a"
integrity sha512-yvao7YI3GdmmrslNVsZgx9PfntfWrnXwtR+K/DjI0I/sTKif4Z623um+sjVZ1hk5670B+ODjvHDAckKdjmPTsg==
pg@^8.14.1:
version "8.14.1"
resolved "https://registry.yarnpkg.com/pg/-/pg-8.14.1.tgz#2e3d1f287b64797cdfc8d1ba000f61a7ff8d66ed"
integrity sha512-0TdbqfjwIun9Fm/r89oB7RFQ0bLgduAhiIqIXOsyKoiC/L54DbuAAzIEN/9Op0f1Po9X7iCPXGoa/Ah+2aI8Xw==
dependencies:
pg-connection-string "^2.8.5"
pg-pool "^3.9.6"
pg-protocol "^1.9.5"
pg-connection-string "^2.7.0"
pg-pool "^3.8.0"
pg-protocol "^1.8.0"
pg-types "^2.1.0"
pgpass "1.x"
optionalDependencies:
pg-cloudflare "^1.2.5"
pg-cloudflare "^1.1.1"
pgpass@1.x:
version "1.0.4"
@@ -13521,10 +13521,10 @@ react-merge-refs@^2.1.1:
resolved "https://registry.yarnpkg.com/react-merge-refs/-/react-merge-refs-2.1.1.tgz#e46763f8f1b881c0226ee54a1a2a10ffefba0233"
integrity sha512-jLQXJ/URln51zskhgppGJ2ub7b2WFKGq3cl3NYKtlHoTG+dN2q7EzWrn3hN3EgPsTMvpR9tpq5ijdp7YwFZkag==
react-portal@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/react-portal/-/react-portal-4.3.0.tgz#92ca3492b1309883134f317a6aa88004534c860f"
integrity sha512-qs/2uKq1ifB3J1+K8ExfgUvCDZqlqCkfOEhqTELEDTfosloKiuzOzc7hl7IQ/7nohiFZD41BUYU0boAsIsGYHw==
react-portal@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/react-portal/-/react-portal-4.2.2.tgz#bff1e024147d6041ba8c530ffc99d4c8248f49fa"
integrity "sha1-v/HgJBR9YEG6jFMP/JnUyCSPSfo= sha512-vS18idTmevQxyQpnde0Td6ZcUlv+pD8GTyR42n3CHUQq9OHi1C4jDE4ZWEbEsrbrLRhSECYiao58cvocwMtP7Q=="
dependencies:
prop-types "^15.5.8"