diff --git a/package.json b/package.json index 49e740ae..6a7a9587 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "@types/jest": "30.0.0", "@types/node": "22.18.0", "@types/proper-lockfile": "4.1.4", + "audit-ci": "7.1.0", "esbuild": "0.25.0", "esbuild-node-externals": "1.14.0", "husky": "8.0.3", @@ -29,7 +30,6 @@ "testcontainers": "11.13.0", "typescript": "5.9.2", "update-dotenv": "1.1.1", - "audit-ci": "7.1.0", "yargs": "17.7.2" }, "scripts": { @@ -109,7 +109,8 @@ "esm": "npm:esm-wallaby@3.2.35", "@types/koa": "3.0.1", "brace-expansion": "5.0.5", - "@smithy/node-http-handler": "4.4.16" + "@smithy/node-http-handler": "4.4.16", + "**/lodash": "4.18.1" }, "engines": { "node": ">=22.0.0 <23.0.0" diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index b10df368..ac0cbdaf 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -54,7 +54,7 @@ "koa-passport": "6.0.0", "koa-pino-logger": "4.0.0", "@koa/router": "13.1.0", - "lodash": "4.17.23", + "lodash": "4.18.1", "node-fetch": "2.6.7", "passport-google-oauth": "2.0.0", "passport-local": "1.0.0", diff --git a/packages/backend-core/src/docUpdates/index.ts b/packages/backend-core/src/docUpdates/index.ts deleted file mode 100644 index ac4ae5e6..00000000 --- a/packages/backend-core/src/docUpdates/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { asyncEventQueue, init as initQueue } from "../events/asyncEvents" -import { - default as DocumentUpdateProcessor, - type ProcessorMap, -} from "../events/processors/async/DocumentUpdateProcessor" - -let processingPromise: Promise -let documentProcessor: DocumentUpdateProcessor - -export function init(processors: ProcessorMap) { - if (!asyncEventQueue) { - initQueue() - } - if (!documentProcessor) { - documentProcessor = new DocumentUpdateProcessor(processors) - } - // if not processing in this instance, kick it off - if (!processingPromise) { - processingPromise = asyncEventQueue.process(async (job) => { - const { event, identity, properties } = job.data - await documentProcessor.processEvent(event, identity, properties) - }) - } -} diff --git a/packages/backend-core/src/events/asyncEvents/index.ts b/packages/backend-core/src/events/asyncEvents/index.ts deleted file mode 100644 index ddcbf3a5..00000000 --- a/packages/backend-core/src/events/asyncEvents/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./publisher" -export * from "./queue" diff --git a/packages/backend-core/src/events/asyncEvents/publisher.ts b/packages/backend-core/src/events/asyncEvents/publisher.ts deleted file mode 100644 index 2588b8e1..00000000 --- a/packages/backend-core/src/events/asyncEvents/publisher.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { AsyncEvents } from "@budibase/types" -import { asyncEventQueue, type EventPayload, init } from "./queue" - -export async function publishAsyncEvent(payload: EventPayload) { - if (!asyncEventQueue) { - init() - } - const { event, identity } = payload - if (AsyncEvents.indexOf(event) !== -1 && identity.tenantId) { - await asyncEventQueue.add(payload) - } -} diff --git a/packages/backend-core/src/events/asyncEvents/queue.ts b/packages/backend-core/src/events/asyncEvents/queue.ts deleted file mode 100644 index cdbd227e..00000000 --- a/packages/backend-core/src/events/asyncEvents/queue.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { Event, Identity } from "@budibase/types" -import { BudibaseQueue, JobQueue } from "../../queue" - -export interface EventPayload { - event: Event - identity: Identity - properties: any - timestamp?: string | number -} - -export let asyncEventQueue: BudibaseQueue - -export function init() { - asyncEventQueue = new BudibaseQueue(JobQueue.SYSTEM_EVENT_QUEUE, { - jobTags: (event: EventPayload) => { - return { - "event.name": event.event, - } - }, - }) -} - -export async function shutdown() { - if (asyncEventQueue) { - await asyncEventQueue.close() - } -} diff --git a/packages/backend-core/src/events/documentId.ts b/packages/backend-core/src/events/documentId.ts deleted file mode 100644 index add3dabe..00000000 --- a/packages/backend-core/src/events/documentId.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { - type DatasourceDeletedEvent, - Event, - type QueryDeletedEvent, - type TableDeletedEvent, - type UserCreatedEvent, - type UserDeletedEvent, - type UserPermissionAssignedEvent, - type UserPermissionRemovedEvent, - type UserUpdatedEvent, - type ViewDeletedEvent, - type WorkspaceAppDeletedEvent, -} from "@budibase/types" - -const getEventProperties: Record string | undefined> = { - [Event.USER_CREATED]: (properties: UserCreatedEvent) => properties.userId, - [Event.USER_UPDATED]: (properties: UserUpdatedEvent) => properties.userId, - [Event.USER_DELETED]: (properties: UserDeletedEvent) => properties.userId, - [Event.USER_PERMISSION_ADMIN_ASSIGNED]: (properties: UserPermissionAssignedEvent) => - properties.userId, - [Event.USER_PERMISSION_ADMIN_REMOVED]: (properties: UserPermissionRemovedEvent) => - properties.userId, - [Event.USER_PERMISSION_BUILDER_ASSIGNED]: (properties: UserPermissionAssignedEvent) => - properties.userId, - [Event.USER_PERMISSION_BUILDER_REMOVED]: (properties: UserPermissionRemovedEvent) => - properties.userId, - [Event.DATASOURCE_DELETED]: (properties: DatasourceDeletedEvent) => properties.datasourceId, - [Event.TABLE_DELETED]: (properties: TableDeletedEvent) => properties.tableId, - [Event.QUERY_DELETED]: (properties: QueryDeletedEvent) => properties.queryId, - [Event.WORKSPACE_APP_DELETED]: (properties: WorkspaceAppDeletedEvent) => - properties.workspaceAppId, - [Event.VIEW_DELETED]: (properties: ViewDeletedEvent) => properties.id, -} - -export function getDocumentId(event: Event, properties: any) { - const extractor = getEventProperties[event] - if (!extractor) { - throw new Error("Event does not have a method of document ID extraction") - } - return extractor(properties) -} diff --git a/packages/backend-core/src/events/processors/async/DocumentUpdateProcessor.ts b/packages/backend-core/src/events/processors/async/DocumentUpdateProcessor.ts deleted file mode 100644 index cabf7d21..00000000 --- a/packages/backend-core/src/events/processors/async/DocumentUpdateProcessor.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { DocUpdateEvent, Event, EventProcessor, Identity } from "@budibase/types" -import { doInTenant } from "../../../context" -import { shutdown } from "../../asyncEvents" -import { getDocumentId } from "../../documentId" - -export type Processor = (update: DocUpdateEvent) => Promise -export type ProcessorMap = { events: Event[]; processor: Processor }[] - -export default class DocumentUpdateProcessor implements EventProcessor { - processors: ProcessorMap = [] - - constructor(processors: ProcessorMap) { - this.processors = processors - } - - async processEvent(event: Event, identity: Identity, properties: any) { - const tenantId = identity.realTenantId - const docId = getDocumentId(event, properties) - if (!(tenantId && docId)) { - return - } - for (const { events, processor } of this.processors) { - if (events.includes(event)) { - await doInTenant(tenantId, async () => { - await processor({ - id: docId, - tenantId, - appId: properties.appId, - properties, - }) - }) - } - } - } - - shutdown() { - return shutdown() - } -} diff --git a/packages/backend-core/src/index.ts b/packages/backend-core/src/index.ts index 4dd5cb27..2186d45d 100644 --- a/packages/backend-core/src/index.ts +++ b/packages/backend-core/src/index.ts @@ -7,7 +7,6 @@ export * as context from "./context" export * as csv from "./csv" export * as db from "./db" export * as docIds from "./docIds" -export * as docUpdates from "./docUpdates" export * from "./Endpoint" export { default as env, setEnv, withEnv } from "./environment" export * as errors from "./errors" diff --git a/packages/backend-core/src/queue/constants.ts b/packages/backend-core/src/queue/constants.ts index ae5157fa..5b00b6f6 100644 --- a/packages/backend-core/src/queue/constants.ts +++ b/packages/backend-core/src/queue/constants.ts @@ -1,8 +1,4 @@ export enum JobQueue { - AUTOMATION = "automationQueue", - APP_BACKUP = "appBackupQueue", - AUDIT_LOG = "auditLogQueue", - SYSTEM_EVENT_QUEUE = "systemEventQueue", APP_MIGRATION = "appMigration", DOC_WRITETHROUGH_QUEUE = "docWritethroughQueue", DEV_REVERT_PROCESSOR = "devRevertProcessorQueue", diff --git a/packages/backend-core/src/queue/listeners.ts b/packages/backend-core/src/queue/listeners.ts index 3bccac7b..d06787ad 100644 --- a/packages/backend-core/src/queue/listeners.ts +++ b/packages/backend-core/src/queue/listeners.ts @@ -77,10 +77,6 @@ enum BullEvent { } enum QueueEventType { - AUTOMATION_EVENT = "automation-event", - APP_BACKUP_EVENT = "app-backup-event", - AUDIT_LOG_EVENT = "audit-log-event", - SYSTEM_EVENT = "system-event", APP_MIGRATION = "app-migration", DOC_WRITETHROUGH = "doc-writethrough", DEV_REVERT_EVENT = "dev-revert-event", @@ -88,10 +84,6 @@ enum QueueEventType { } const EventTypeMap: { [key in JobQueue]: QueueEventType } = { - [JobQueue.AUTOMATION]: QueueEventType.AUTOMATION_EVENT, - [JobQueue.APP_BACKUP]: QueueEventType.APP_BACKUP_EVENT, - [JobQueue.AUDIT_LOG]: QueueEventType.AUDIT_LOG_EVENT, - [JobQueue.SYSTEM_EVENT_QUEUE]: QueueEventType.SYSTEM_EVENT, [JobQueue.APP_MIGRATION]: QueueEventType.APP_MIGRATION, [JobQueue.DOC_WRITETHROUGH_QUEUE]: QueueEventType.DOC_WRITETHROUGH, [JobQueue.DEV_REVERT_PROCESSOR]: QueueEventType.DEV_REVERT_EVENT, diff --git a/packages/backend-core/src/queue/queue.ts b/packages/backend-core/src/queue/queue.ts index d5214ef8..2299375e 100644 --- a/packages/backend-core/src/queue/queue.ts +++ b/packages/backend-core/src/queue/queue.ts @@ -54,7 +54,7 @@ export class BudibaseQueue { } private initQueue() { - const redisOpts = getRedisOptions() + const redisOpts = getRedisOptions() as QueueOptions["redis"] const queueConfig: QueueOptions = { redis: redisOpts, settings: { @@ -75,7 +75,10 @@ export class BudibaseQueue { ) { queue = new BullQueue(this.jobQueue, { ...queueConfig, - redis: { host: "localhost", port: Number(process.env.BULL_TEST_REDIS_PORT) }, + redis: { + host: "localhost", + port: Number(process.env.BULL_TEST_REDIS_PORT), + }, }) } else { queue = new InMemoryQueue(this.jobQueue, queueConfig) as any diff --git a/packages/backend-core/src/utils/utils.ts b/packages/backend-core/src/utils/utils.ts index 115ddebd..5ec39cfa 100644 --- a/packages/backend-core/src/utils/utils.ts +++ b/packages/backend-core/src/utils/utils.ts @@ -1,10 +1,4 @@ -import { - AuditedEventFriendlyName, - type Ctx, - type Event, - TenantResolutionStrategy, - type Workspace, -} from "@budibase/types" +import { type Ctx, TenantResolutionStrategy, type Workspace } from "@budibase/types" import type { SetOption } from "cookies" import jwt, { type Secret } from "jsonwebtoken" import { DocumentType, Header, MAX_VALID_DATE, SEPARATOR } from "../constants" @@ -228,10 +222,6 @@ export function timeout(timeMs: number) { return new Promise((resolve) => setTimeout(resolve, timeMs)) } -export function isAudited(event: Event) { - return Boolean(AuditedEventFriendlyName[event]) -} - export function hasCircularStructure(json: any) { if (typeof json !== "object") { return false diff --git a/packages/builder/package.json b/packages/builder/package.json index 6734f1fe..365681b9 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -69,7 +69,7 @@ "dayjs": "1.10.8", "downloadjs": "1.4.7", "fast-json-patch": "^3.1.1", - "lodash": "4.17.23", + "lodash": "4.18.1", "marked": "15.0.8", "remixicon": "2.5.0", "sanitize-html": "2.13.0", @@ -77,7 +77,7 @@ "svelte-dnd-action": "0.9.64", "svelte-loading-spinners": "^0.3.6", "svelte-portal": "^2.2.1", - "yup": "0.32.11" + "yup": "1.7.1" }, "devDependencies": { "@babel/plugin-transform-runtime": "^7.13.10", diff --git a/packages/frontend-core/package.json b/packages/frontend-core/package.json index 06590961..cc3bafc3 100644 --- a/packages/frontend-core/package.json +++ b/packages/frontend-core/package.json @@ -13,7 +13,7 @@ "@budibase/shared-core": "*", "@budibase/types": "*", "dayjs": "1.10.8", - "lodash": "4.17.23", + "lodash": "4.18.1", "shortid": "2.2.17", "socket.io-client": "4.7.5" } diff --git a/packages/server/package.json b/packages/server/package.json index f4278246..527c28df 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -54,7 +54,6 @@ "@koa/router": "13.1.0", "@socket.io/redis-adapter": "8.2.1", "@types/xml2js": "0.4.14", - "archiver": "7.0.1", "bcrypt": "6.0.0", "bson": "6.9.0", "buffer": "6.0.3", @@ -86,7 +85,7 @@ "koa-send": "5.0.1", "koa-useragent": "4.1.0", "koa2-ratelimit": "1.1.3", - "lodash": "4.17.23", + "lodash": "4.18.1", "mailparser": "3.7.2", "memorystream": "0.3.1", "minio": "8.0.7", @@ -116,7 +115,6 @@ "devDependencies": { "@babel/core": "^7.22.5", "@babel/preset-env": "7.16.11", - "@types/archiver": "6.0.2", "@types/formidable": "^3.4.6", "@types/global-agent": "2.1.1", "@types/html-to-text": "^9.0.4", diff --git a/packages/server/src/api/controllers/row/index.ts b/packages/server/src/api/controllers/row/index.ts index 74bf9fbe..5950e3a0 100644 --- a/packages/server/src/api/controllers/row/index.ts +++ b/packages/server/src/api/controllers/row/index.ts @@ -5,7 +5,6 @@ import { type DeleteRow, type DeleteRowRequest, type DeleteRows, - EventType, type ExportRowsRequest, type ExportRowsResponse, type FetchEnrichedRowResponse, @@ -43,7 +42,6 @@ function pickApi() { } export async function patch(ctx: UserCtx): Promise { - const appId = ctx.appId const { tableId } = utils.getSourceId(ctx) const body = ctx.request.body @@ -57,21 +55,11 @@ export async function patch(ctx: UserCtx): Pr const response = await api.patch(ctx) return response } - const { row, table, oldRow } = isExternalTableID(tableId) - ? await api.patch(ctx) - : await runQuery() + const { row, table } = isExternalTableID(tableId) ? await api.patch(ctx) : await runQuery() if (!row) { ctx.throw(404, "Row not found") } - ctx.eventEmitter?.emitRow({ - eventName: EventType.ROW_UPDATE, - appId, - row, - table, - oldRow, - user: sdk.users.getUserContextBindings(ctx.user), - }) ctx.message = `${table.name} updated successfully.` ctx.body = row gridSocket?.emitRowUpdate(ctx, row) @@ -83,8 +71,6 @@ export async function patch(ctx: UserCtx): Pr export const save = async (ctx: UserCtx) => { const { tableId, viewId } = utils.getSourceId(ctx) const sourceId = viewId || tableId - - const appId = ctx.appId const body = ctx.request.body // user metadata doesn't exist yet - don't allow creation @@ -104,13 +90,6 @@ export const save = async (ctx: UserCtx) => { ? await sdk.rows.save(sourceId, ctx.request.body, ctx.user?._id) : await saveQuery() - ctx.eventEmitter?.emitRow({ - eventName: EventType.ROW_SAVE, - appId, - row, - table, - user: sdk.users.getUserContextBindings(ctx.user), - }) ctx.message = `${table.name} saved successfully` ctx.body = row gridSocket?.emitRowUpdate(ctx, row) @@ -158,8 +137,6 @@ async function processDeleteRowsRequest(ctx: UserCtx) { } async function deleteRows(ctx: UserCtx) { - const appId = ctx.appId - const deleteRequest = ctx.request.body as DeleteRows deleteRequest.rows = await processDeleteRowsRequest(ctx) @@ -167,28 +144,15 @@ async function deleteRows(ctx: UserCtx) { const { rows } = await pickApi().bulkDestroy(ctx) for (const row of rows) { - ctx.eventEmitter?.emitRow({ - eventName: EventType.ROW_DELETE, - appId, - row, - user: sdk.users.getUserContextBindings(ctx.user), - }) gridSocket?.emitRowDeletion(ctx, row) } return rows } async function deleteRow(ctx: UserCtx) { - const appId = ctx.appId const api = pickApi() const resp = await api.destroy(ctx) - ctx.eventEmitter?.emitRow({ - eventName: EventType.ROW_DELETE, - appId, - row: resp.row, - user: sdk.users.getUserContextBindings(ctx.user), - }) gridSocket?.emitRowDeletion(ctx, resp.row) return resp diff --git a/packages/server/src/api/controllers/table/index.ts b/packages/server/src/api/controllers/table/index.ts index d787fad8..c3491d77 100644 --- a/packages/server/src/api/controllers/table/index.ts +++ b/packages/server/src/api/controllers/table/index.ts @@ -12,7 +12,6 @@ import { type CsvToJsonResponse, type DeleteTableResponse, DocumentType, - EventType, type FetchTablesResponse, FieldType, type FindTableResponse, @@ -100,7 +99,6 @@ export async function find(ctx: UserCtx) { } export async function save(ctx: UserCtx) { - const appId = ctx.appId const { rows, ...table } = ctx.request.body const renaming = ctx.request.body._rename @@ -119,18 +117,15 @@ export async function save(ctx: UserCtx) { savedTable = await processTable(savedTable) } ctx.message = `Table ${table.name} saved successfully.` - ctx.eventEmitter?.emitTable(EventType.TABLE_SAVE, appId, { ...savedTable }) ctx.body = savedTable builderSocket?.emitTableUpdate(ctx, cloneDeep(savedTable)) } export async function destroy(ctx: UserCtx) { - const appId = ctx.appId const tableId = ctx.params.tableId const deletedTable = await external.destroy(ctx) - ctx.eventEmitter?.emitTable(EventType.TABLE_DELETE, appId, deletedTable) ctx.table = deletedTable ctx.body = { message: `Table ${tableId} deleted.` } builderSocket?.emitTableDeletion(ctx, deletedTable) diff --git a/packages/server/src/events/AutomationEmitter.ts b/packages/server/src/events/AutomationEmitter.ts deleted file mode 100644 index f8fa7f62..00000000 --- a/packages/server/src/events/AutomationEmitter.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { context } from "@budibase/backend-core" -import { - type ContextEmitter, - DocumentType, - type EventType, - type Row, - type Table, - type UserBindings, - type Workspace, -} from "@budibase/types" -import env from "../environment" -import mainEmitter from "./index" -import { rowEmission, tableEmission } from "./utils" - -const MAX_AUTOMATIONS_ALLOWED = 5 - -class AutomationEmitter implements ContextEmitter { - chainCount: number - metadata: { automationChainCount: number } - - constructor(chainCount: number) { - this.chainCount = chainCount - this.metadata = { - automationChainCount: chainCount, - } - } - - async getMaxAutomationChain() { - const db = context.getWorkspaceDB() - const appMetadata = await db.get(DocumentType.WORKSPACE_METADATA) - const chainAutomations = appMetadata?.automations?.chainAutomations - - if (chainAutomations === true) { - return MAX_AUTOMATIONS_ALLOWED - } else if (env.isTest()) { - return 0 - } else if (chainAutomations === undefined && env.SELF_HOSTED) { - return MAX_AUTOMATIONS_ALLOWED - } else { - return 0 - } - } - - async emitRow({ - eventName, - appId, - row, - table, - oldRow, - user, - }: { - eventName: EventType.ROW_SAVE | EventType.ROW_DELETE | EventType.ROW_UPDATE - appId: string - row: Row - table?: Table - oldRow?: Row - user: UserBindings - }) { - const MAX_AUTOMATION_CHAIN = await this.getMaxAutomationChain() - - // don't emit even if we've reached max automation chain - if (this.chainCount >= MAX_AUTOMATION_CHAIN) { - return - } - rowEmission({ - emitter: mainEmitter, - eventName, - appId, - row, - table, - oldRow, - metadata: this.metadata, - user, - }) - } - - async emitTable(eventName: string, appId: string, table?: Table) { - const MAX_AUTOMATION_CHAIN = await this.getMaxAutomationChain() - - // don't emit even if we've reached max automation chain - if (this.chainCount >= MAX_AUTOMATION_CHAIN) { - return - } - - tableEmission({ - emitter: mainEmitter, - eventName, - appId, - table, - metadata: this.metadata, - }) - } -} - -export default AutomationEmitter diff --git a/packages/server/src/events/BudibaseEmitter.ts b/packages/server/src/events/BudibaseEmitter.ts deleted file mode 100644 index cace2916..00000000 --- a/packages/server/src/events/BudibaseEmitter.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { EventEmitter } from "node:events" -import type { ContextEmitter, EventType, Row, Table, UserBindings } from "@budibase/types" -import { rowEmission, tableEmission } from "./utils" - -/** - * keeping event emitter in one central location as it might be used for things other than - * automations (what it was for originally) - having a central emitter will be useful in the - * future. - */ - -/** - * Extending the standard emitter to some syntactic sugar and standardisation to the emitted event. - * This is specifically quite important for template strings used in automations. - */ -class BudibaseEmitter extends EventEmitter implements ContextEmitter { - emitRow({ - eventName, - appId, - row, - table, - oldRow, - user, - }: { - eventName: EventType.ROW_SAVE | EventType.ROW_DELETE | EventType.ROW_UPDATE - appId: string - row: Row - table?: Table - oldRow?: Row - user: UserBindings - }) { - rowEmission({ emitter: this, eventName, appId, row, table, oldRow, user }) - } - - emitTable(eventName: EventType, appId: string, table?: Table) { - tableEmission({ emitter: this, eventName, appId, table }) - } - - emitPort(portNumber?: number | string) { - this.emit("internal:port", portNumber) - } -} - -export default BudibaseEmitter diff --git a/packages/server/src/events/docUpdates/index.ts b/packages/server/src/events/docUpdates/index.ts deleted file mode 100644 index fa7a6231..00000000 --- a/packages/server/src/events/docUpdates/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./processors" diff --git a/packages/server/src/events/docUpdates/processors.ts b/packages/server/src/events/docUpdates/processors.ts deleted file mode 100644 index 202d0722..00000000 --- a/packages/server/src/events/docUpdates/processors.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { docUpdates } from "@budibase/backend-core" -import workspaceResourceProcessor from "./workspaceFavourites" - -let started = false - -export function init() { - if (started) { - return - } - const processors = [workspaceResourceProcessor()] - docUpdates.init(processors) - started = true -} diff --git a/packages/server/src/events/docUpdates/syncUsers.ts b/packages/server/src/events/docUpdates/syncUsers.ts deleted file mode 100644 index 5571d5a6..00000000 --- a/packages/server/src/events/docUpdates/syncUsers.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { constants, logging, queue } from "@budibase/backend-core" -import { type DocUpdateEvent, WorkspaceUserSyncEvents } from "@budibase/types" -import { syncUsersAcrossWorkspaces } from "../../sdk/workspace/workspaces/sync" - -export class UserSyncProcessor { - private static _queue: queue.BudibaseQueue<{ userId: string }> - - public static get queue() { - if (!UserSyncProcessor._queue) { - UserSyncProcessor._queue = new queue.BudibaseQueue<{ userId: string }>( - queue.JobQueue.BATCH_USER_SYNC_PROCESSOR, - { - jobOptions: { - removeOnComplete: true, - removeOnFail: 1000, - }, - } - ) - } - - return UserSyncProcessor._queue - } - - init() { - UserSyncProcessor.queue.process(1, async (job) => { - const pendingJobs = await UserSyncProcessor.queue.getBullQueue().getWaiting(0, 100) - - const userIds = Array.from(new Set([job, ...pendingJobs].map((m) => m.data.userId))) - await syncUsersAcrossWorkspaces(userIds) - - for (const job of pendingJobs) { - await job.remove() - } - }) - } - - async add(userIds: string[]) { - for (const userId of userIds) { - await UserSyncProcessor.queue.add({ userId }) - } - } -} - -let userSyncProcessor: UserSyncProcessor - -export function getUserSyncProcessor(): UserSyncProcessor { - if (!userSyncProcessor) { - userSyncProcessor = new UserSyncProcessor() - userSyncProcessor.init() - } - return userSyncProcessor -} - -export default function process() { - const processor = async (update: DocUpdateEvent) => { - try { - const docId = update.id - const isGroup = docId.startsWith(constants.DocumentType.GROUP) - const userIds: string[] = [] - - if (isGroup) { - if ("userIds" in update.properties) { - userIds.push(...update.properties.userIds) - } - } else { - userIds.push(docId) - } - - const batchSyncProcessor = getUserSyncProcessor() - await batchSyncProcessor.add(userIds) - } catch (err: any) { - // if something not found - no changes to perform - if (err?.status === 404) { - return - } - // The user has already been sync in another process - else if (err?.status === 409) { - return - } else { - logging.logAlert("Failed to perform user/group app sync", err) - } - } - } - return { events: WorkspaceUserSyncEvents, processor } -} diff --git a/packages/server/src/events/docUpdates/workspaceFavourites.ts b/packages/server/src/events/docUpdates/workspaceFavourites.ts deleted file mode 100644 index bdc69794..00000000 --- a/packages/server/src/events/docUpdates/workspaceFavourites.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { constants, context, logging } from "@budibase/backend-core" -import { type DocUpdateEvent, WorkspaceResourceEvents } from "@budibase/types" -import sdk from "../../sdk" - -const { DATASOURCE, TABLE, WORKSPACE_APP, QUERY, MEM_VIEW } = constants.DocumentType - -export default function process() { - const processor = async (update: DocUpdateEvent) => { - try { - const docId = update.id - const appId = update.appId - - const isWSResource = [DATASOURCE, TABLE, WORKSPACE_APP, QUERY, MEM_VIEW].find((type) => - docId.startsWith(type) - ) - - if (isWSResource! && appId) { - context.doInWorkspaceContext(appId, async () => { - const result = await sdk.workspace.findByResourceId(docId) - const [fav] = result - if (fav) { - // Purge - await sdk.workspace.remove(fav._id, fav._rev) - } - }) - } - } catch (err: any) { - // if something not found - no changes to perform - if (err?.status === 404) { - return - } - // The user has already been synced in another process - else if (err?.status === 409) { - return - } else { - logging.logAlert("Failed to sync workspace resource faves", err) - } - } - } - return { events: WorkspaceResourceEvents, processor } -} diff --git a/packages/server/src/events/index.ts b/packages/server/src/events/index.ts deleted file mode 100644 index 23c3f3e5..00000000 --- a/packages/server/src/events/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import BudibaseEmitter from "./BudibaseEmitter" - -const emitter = new BudibaseEmitter() - -export { init } from "./docUpdates" -export default emitter diff --git a/packages/server/src/events/utils.ts b/packages/server/src/events/utils.ts deleted file mode 100644 index 51773375..00000000 --- a/packages/server/src/events/utils.ts +++ /dev/null @@ -1,80 +0,0 @@ -import type { Row, Table, UserBindings } from "@budibase/types" -import type BudibaseEmitter from "./BudibaseEmitter" - -type BBEventOpts = { - emitter: BudibaseEmitter - eventName: string - appId: string - table?: Table - row?: Row - oldRow?: Row - metadata?: any - user?: UserBindings -} - -interface BBEventTable extends Table { - tableId?: string -} - -type BBEvent = { - appId: string - tableId?: string - row?: Row - oldRow?: Row - table?: BBEventTable - id?: string - revision?: string - metadata?: any - user?: UserBindings -} - -export function rowEmission({ - emitter, - eventName, - appId, - row, - table, - metadata, - oldRow, - user, -}: BBEventOpts) { - const event: BBEvent = { - row, - oldRow, - appId, - tableId: row?.tableId, - user, - } - if (table) { - event.table = table - } - event.id = row?._id - if (row?._rev) { - event.revision = row._rev - } - if (metadata) { - event.metadata = metadata - } - emitter.emit(eventName, event) -} - -export function tableEmission({ emitter, eventName, appId, table, metadata }: BBEventOpts) { - const tableId = table?._id - const inputTable: BBEventTable | undefined = table - if (inputTable) { - inputTable.tableId = tableId - } - const event: BBEvent = { - table: inputTable, - appId, - tableId: tableId, - } - event.id = tableId - if (table?._rev) { - event.revision = table._rev - } - if (metadata) { - event.metadata = metadata - } - emitter.emit(eventName, event) -} diff --git a/packages/server/src/startup/index.ts b/packages/server/src/startup/index.ts index a3d5c276..9f05e2b2 100644 --- a/packages/server/src/startup/index.ts +++ b/packages/server/src/startup/index.ts @@ -12,7 +12,6 @@ import bson from "bson" import type Koa from "koa" import * as api from "../api" import env from "../environment" -import { default as eventEmitter, init as eventInit } from "../events" import * as jsRunner from "../jsRunner" import sdk from "../sdk" import * as fileSystem from "../utilities/fileSystem" @@ -28,7 +27,6 @@ export function getState(): State { } async function initRoutes(app: Koa) { - app.context.eventEmitter = eventEmitter app.context.auth = {} // api routes @@ -52,9 +50,6 @@ export async function startup(opts: { app?: Koa; server?: Server; force?: boolea env._set("PORT", address.port) } - console.log("Emitting port event") - eventEmitter.emitPort(env.PORT) - console.log("Initialising file system") fileSystem.init() @@ -64,9 +59,6 @@ export async function startup(opts: { app?: Koa; server?: Server; force?: boolea console.log("Initialising writethrough cache") cache.docWritethrough.init() - console.log("Initialising events") - eventInit() - if (app && server) { console.log("Initialising websockets") initialiseWebsockets(app, server) diff --git a/packages/shared-core/package.json b/packages/shared-core/package.json index fc772e45..d65d64c4 100644 --- a/packages/shared-core/package.json +++ b/packages/shared-core/package.json @@ -17,8 +17,7 @@ "test:watch": "yarn test --watchAll" }, "dependencies": { - "@budibase/types": "*", - "cron-validate": "1.4.5" + "@budibase/types": "*" }, "devDependencies": { "rimraf": "3.0.2" diff --git a/packages/types/src/core/events.ts b/packages/types/src/core/events.ts deleted file mode 100644 index e16e3c94..00000000 --- a/packages/types/src/core/events.ts +++ /dev/null @@ -1,8 +0,0 @@ -export enum EventType { - ROW_SAVE = "row:save", - ROW_UPDATE = "row:update", - ROW_DELETE = "row:delete", - TABLE_SAVE = "table:save", - TABLE_UPDATED = "table:updated", - TABLE_DELETE = "table:delete", -} diff --git a/packages/types/src/core/index.ts b/packages/types/src/core/index.ts index 5501536a..f65b76a4 100644 --- a/packages/types/src/core/index.ts +++ b/packages/types/src/core/index.ts @@ -1,3 +1,2 @@ export * from "./common" -export * from "./events" export * from "./installation" diff --git a/packages/types/src/sdk/events.ts b/packages/types/src/sdk/events.ts index 729f184b..ab3f0a20 100644 --- a/packages/types/src/sdk/events.ts +++ b/packages/types/src/sdk/events.ts @@ -1,35 +1,5 @@ import type { Hosting } from ".." -// GROUPS - -export enum GroupType { - TENANT = "tenant", - INSTALLATION = "installation", -} - -export interface Group { - id: string - type: IdentityType - environment: string - hosting: Hosting -} - -export interface TenantGroup extends Group { - // account level information is associated with the tenant group - // as we don't have this at the user level - profession?: string // only available in cloud - companySize?: string // only available in cloud - createdAt?: string | number - createdVersion: string - installationId: string -} - -export interface InstallationGroup extends Group { - version: string -} - -// IDENTITIES - export enum IdentityType { USER = "user", TENANT = "tenant", @@ -48,481 +18,8 @@ export interface Identity { environment: string installationId?: string tenantId?: string - // usable - no unique format realTenantId?: string hostInfo?: HostInfo } -export interface UserIdentity extends Identity { - verified: boolean - accountHolder: boolean - providerType?: string - builder?: boolean - admin?: boolean -} - -export enum Event { - // USER - USER_CREATED = "user:created", - USER_UPDATED = "user:updated", - USER_DELETED = "user:deleted", - - // USER / ONBOARDING - USER_ONBOARDING_COMPLETE = "user:onboarding:complete", - - // USER / PERMISSIONS - USER_PERMISSION_ADMIN_ASSIGNED = "user:admin:assigned", - USER_PERMISSION_ADMIN_REMOVED = "user:admin:removed", - USER_PERMISSION_BUILDER_ASSIGNED = "user:builder:assigned", - USER_PERMISSION_BUILDER_REMOVED = "user:builder:removed", - - // USER / INVITE - USER_INVITED = "user:invited", - USER_INVITED_ACCEPTED = "user:invite:accepted", - - // USER / PASSWORD - USER_PASSWORD_FORCE_RESET = "user:password:force:reset", - USER_PASSWORD_UPDATED = "user:password:updated", - USER_PASSWORD_RESET_REQUESTED = "user:password:reset:requested", - USER_PASSWORD_RESET = "user:password:reset", - - // USER / COLLABORATION - USER_DATA_COLLABORATION = "user:data:collaboration", - - // EMAIL - EMAIL_SMTP_CREATED = "email:smtp:created", - EMAIL_SMTP_UPDATED = "email:smtp:updated", - - // AI - AI_CONFIG_CREATED = "ai:config:created", - AI_CONFIG_UPDATED = "ai:config:updated", - - // AUTH - AUTH_SSO_CREATED = "auth:sso:created", - AUTH_SSO_UPDATED = "auth:sso:updated", - AUTH_SSO_ACTIVATED = "auth:sso:activated", - AUTH_SSO_DEACTIVATED = "auth:sso:deactivated", - AUTH_LOGIN = "auth:login", - AUTH_LOGOUT = "auth:logout", - - // ORG - ORG_NAME_UPDATED = "org:info:name:updated", - ORG_LOGO_UPDATED = "org:info:logo:updated", - ORG_PLATFORM_URL_UPDATED = "org:platformurl:updated", - - // INSTALLATION - INSTALLATION_VERSION_CHECKED = "installation:version:checked", - INSTALLATION_VERSION_UPGRADED = "installation:version:upgraded", - INSTALLATION_VERSION_DOWNGRADED = "installation:version:downgraded", - INSTALLATION_FIRST_STARTUP = "installation:firstStartup", - - // ORG / ANALYTICS - ANALYTICS_OPT_OUT = "analytics:opt:out", - ANALYTICS_OPT_IN = "analytics:opt:in", - - // WORKSPACE - WORKSPACE_CREATED = "app:created", - WORKSPACE_UPDATED = "app:updated", - WORKSPACE_DELETED = "app:deleted", - WORKSPACE_DUPLICATED = "app:duplicated", - WORKSPACE_PUBLISHED = "app:published", - WORKSPACE_UNPUBLISHED = "app:unpublished", - WORKSPACE_TEMPLATE_IMPORTED = "app:template:imported", - WORKSPACE_FILE_IMPORTED = "app:file:imported", - WORKSPACE_APP_VERSION_UPDATED = "app:version:updated", - WORKSPACE_APP_VERSION_REVERTED = "app:version:reverted", - WORKSPACE_REVERTED = "app:reverted", - WORKSPACE_EXPORTED = "app:exported", - - // ROLE - ROLE_CREATED = "role:created", - ROLE_UPDATED = "role:updated", - ROLE_DELETED = "role:deleted", - ROLE_ASSIGNED = "role:assigned", - ROLE_UNASSIGNED = "role:unassigned", - - // SERVE - SERVED_BUILDER = "served:builder", - SERVED_APP = "served:app", - SERVED_APP_PREVIEW = "served:app:preview", - - // DATASOURCE - DATASOURCE_CREATED = "datasource:created", - DATASOURCE_UPDATED = "datasource:updated", - DATASOURCE_DELETED = "datasource:deleted", - - // QUERY - QUERY_CREATED = "query:created", - QUERY_UPDATED = "query:updated", - QUERY_DELETED = "query:deleted", - QUERY_IMPORT = "query:import", - QUERIES_RUN = "queries:run", - QUERY_PREVIEWED = "query:previewed", - - // TABLE - TABLE_CREATED = "table:created", - TABLE_UPDATED = "table:updated", - TABLE_DELETED = "table:deleted", - TABLE_EXPORTED = "table:exported", - TABLE_IMPORTED = "table:imported", - TABLE_DATA_IMPORTED = "table:data:imported", - - // VIEW - VIEW_CREATED = "view:created", - VIEW_UPDATED = "view:updated", - VIEW_DELETED = "view:deleted", - VIEW_EXPORTED = "view:exported", - VIEW_FILTER_CREATED = "view:filter:created", - VIEW_FILTER_UPDATED = "view:filter:updated", - VIEW_FILTER_DELETED = "view:filter:deleted", - VIEW_CALCULATION_CREATED = "view:calculation:created", - VIEW_CALCULATION_UPDATED = "view:calculation:updated", - VIEW_CALCULATION_DELETED = "view:calculation:deleted", - VIEW_JOIN_CREATED = "view:join:created", - - // ROWS - ROWS_CREATED = "rows:created", - ROWS_IMPORTED = "rows:imported", - - // COMPONENT - COMPONENT_CREATED = "component:created", - COMPONENT_DELETED = "component:deleted", - - // SCREEN - SCREEN_CREATED = "screen:created", - SCREEN_DELETED = "screen:deleted", - - // LAYOUT - LAYOUT_CREATED = "layout:created", - LAYOUT_DELETED = "layout:deleted", - - // AUTOMATION - AUTOMATION_CREATED = "automation:created", - AUTOMATION_DELETED = "automation:deleted", - AUTOMATION_TESTED = "automation:tested", - AUTOMATIONS_RUN = "automations:run", - AUTOMATION_STEP_CREATED = "automation:step:created", - AUTOMATION_STEP_DELETED = "automation:step:deleted", - AUTOMATION_TRIGGER_UPDATED = "automation:trigger:updated", - - // LICENSE - LICENSE_PLAN_CHANGED = "license:plan:changed", - LICENSE_ACTIVATED = "license:activated", - LICENSE_PAYMENT_FAILED = "license:payment:failed", - LICENSE_PAYMENT_RECOVERED = "license:payment:recovered", - LICENSE_CHECKOUT_OPENED = "license:checkout:opened", - LICENSE_CHECKOUT_SUCCESS = "license:checkout:success", - LICENSE_PORTAL_OPENED = "license:portal:opened", - - // BACKFILL - APP_BACKFILL_SUCCEEDED = "app:backfill:succeeded", - APP_BACKFILL_FAILED = "app:backfill:failed", - TENANT_BACKFILL_SUCCEEDED = "tenant:backfill:succeeded", - TENANT_BACKFILL_FAILED = "tenant:backfill:failed", - INSTALLATION_BACKFILL_SUCCEEDED = "installation:backfill:succeeded", - INSTALLATION_BACKFILL_FAILED = "installation:backfill:failed", - - // USER - USER_GROUP_CREATED = "user_group:created", - USER_GROUP_UPDATED = "user_group:updated", - USER_GROUP_DELETED = "user_group:deleted", - USER_GROUP_USERS_ADDED = "user_group:user_added", - USER_GROUP_USERS_REMOVED = "user_group:users_deleted", - USER_GROUP_PERMISSIONS_EDITED = "user_group:permissions_edited", - USER_GROUP_ONBOARDING = "user_group:onboarding_added", - - // PLUGIN - PLUGIN_INIT = "plugin:init", - PLUGIN_IMPORTED = "plugin:imported", - PLUGIN_DELETED = "plugin:deleted", - - // BACKUP - APP_BACKUP_RESTORED = "app:backup:restored", - APP_BACKUP_TRIGGERED = "app:backup:triggered", - - // ENVIRONMENT VARIABLE - ENVIRONMENT_VARIABLE_CREATED = "environment_variable:created", - ENVIRONMENT_VARIABLE_DELETED = "environment_variable:deleted", - ENVIRONMENT_VARIABLE_UPGRADE_PANEL_OPENED = "environment_variable:upgrade_panel_opened", - - // AUDIT LOG - AUDIT_LOGS_FILTERED = "audit_log:filtered", - AUDIT_LOGS_DOWNLOADED = "audit_log:downloaded", - - // ROW ACTION - ROW_ACTION_CREATED = "row_action:created", - - //ACTION - ACTION_AUTOMATION_STEP_EXECUTED = "action:automation_step:executed", - ACTION_CRUD_EXECUTED = "action:crud:executed", - ACTION_AI_AGENT_EXECUTED = "action:ai_agent:executed", - - // WORKSPACE APP - WORKSPACE_APP_CREATED = "workspace_app:created", - WORKSPACE_APP_UPDATED = "workspace_app:updated", - WORKSPACE_APP_DELETED = "workspace_app:deleted", - - // GENERIC - RESOURCE_COPIED_TO_WORKSPACE = "resource:copied_to_workspace", -} - -export const WorkspaceUserSyncEvents: Event[] = [ - Event.USER_CREATED, - Event.USER_UPDATED, - Event.USER_DELETED, - Event.USER_PERMISSION_ADMIN_ASSIGNED, - Event.USER_PERMISSION_ADMIN_REMOVED, - Event.USER_PERMISSION_BUILDER_ASSIGNED, - Event.USER_PERMISSION_BUILDER_REMOVED, - Event.USER_GROUP_CREATED, - Event.USER_GROUP_UPDATED, - Event.USER_GROUP_DELETED, - Event.USER_GROUP_USERS_ADDED, - Event.USER_GROUP_USERS_REMOVED, - Event.USER_GROUP_PERMISSIONS_EDITED, -] - -// Favourites -export const WorkspaceResourceEvents: Event[] = [ - Event.AUTOMATION_DELETED, - Event.WORKSPACE_APP_DELETED, - Event.DATASOURCE_DELETED, - Event.TABLE_DELETED, - Event.QUERY_DELETED, - Event.VIEW_DELETED, -] - -export const AsyncEvents: Event[] = [...WorkspaceUserSyncEvents, ...WorkspaceResourceEvents] - -// all events that are not audited have been added to this record as undefined, this means -// that Typescript can protect us against new events being added and auditing of those -// events not being considered. This might be a little ugly, but provides a level of -// Typescript build protection for the audit log feature, any new event also needs to be -// added to this map, during which the developer will need to consider if it should be -// a user facing event or not. -export const AuditedEventFriendlyName: Record = { - // USER - [Event.USER_CREATED]: `User "{{ email }}" created{{#if viaScim}} via SCIM{{/if}}`, - [Event.USER_UPDATED]: `User "{{ email }}" updated{{#if viaScim}} via SCIM{{/if}}`, - [Event.USER_DELETED]: `User "{{ email }}" deleted{{#if viaScim}} via SCIM{{/if}}`, - [Event.USER_PERMISSION_ADMIN_ASSIGNED]: `User "{{ email }}" admin role assigned`, - [Event.USER_PERMISSION_ADMIN_REMOVED]: `User "{{ email }}" admin role removed`, - [Event.USER_PERMISSION_BUILDER_ASSIGNED]: `User "{{ email }}" builder role assigned`, - [Event.USER_PERMISSION_BUILDER_REMOVED]: `User "{{ email }}" builder role removed`, - [Event.USER_INVITED]: `User "{{ email }}" invited`, - [Event.USER_INVITED_ACCEPTED]: `User "{{ email }}" accepted invite`, - [Event.USER_PASSWORD_UPDATED]: `User "{{ email }}" password updated`, - [Event.USER_PASSWORD_RESET_REQUESTED]: `User "{{ email }}" password reset requested`, - [Event.USER_PASSWORD_RESET]: `User "{{ email }}" password reset`, - [Event.USER_GROUP_CREATED]: `User group "{{ name }}" created{{#if viaScim}} via SCIM{{/if}}`, - [Event.USER_GROUP_UPDATED]: `User group "{{ name }}" updated{{#if viaScim}} via SCIM{{/if}}`, - [Event.USER_GROUP_DELETED]: `User group "{{ name }}" deleted{{#if viaScim}} via SCIM{{/if}}`, - [Event.USER_GROUP_USERS_ADDED]: `User group "{{ name }}" {{ count }} users added{{#if viaScim}} via SCIM{{/if}}`, - [Event.USER_GROUP_USERS_REMOVED]: `User group "{{ name }}" {{ count }} users removed{{#if viaScim}} via SCIM{{/if}}`, - [Event.USER_GROUP_PERMISSIONS_EDITED]: `User group "{{ name }}" permissions edited`, - [Event.USER_PASSWORD_FORCE_RESET]: undefined, - [Event.USER_GROUP_ONBOARDING]: undefined, - [Event.USER_ONBOARDING_COMPLETE]: undefined, - [Event.USER_DATA_COLLABORATION]: undefined, - - // EMAIL - [Event.EMAIL_SMTP_CREATED]: `Email configuration created`, - [Event.EMAIL_SMTP_UPDATED]: `Email configuration updated`, - - // AI - [Event.AI_CONFIG_CREATED]: `AI configuration created`, - [Event.AI_CONFIG_UPDATED]: `AI configuration updated`, - - // AUTH - [Event.AUTH_SSO_CREATED]: `SSO configuration created`, - [Event.AUTH_SSO_UPDATED]: `SSO configuration updated`, - [Event.AUTH_SSO_ACTIVATED]: `SSO configuration activated`, - [Event.AUTH_SSO_DEACTIVATED]: `SSO configuration deactivated`, - [Event.AUTH_LOGIN]: `User "{{ email }}" logged in`, - [Event.AUTH_LOGOUT]: `User "{{ email }}" logged out`, - - // ORG - [Event.ORG_NAME_UPDATED]: `Organisation name updated`, - [Event.ORG_LOGO_UPDATED]: `Organisation logo updated`, - [Event.ORG_PLATFORM_URL_UPDATED]: `Organisation platform URL updated`, - - // APP - [Event.WORKSPACE_CREATED]: `App "{{ name }}" created`, - [Event.WORKSPACE_UPDATED]: `App "{{ name }}" updated`, - [Event.WORKSPACE_DELETED]: `App "{{ name }}" deleted`, - [Event.WORKSPACE_DUPLICATED]: `App "{{ name }}" duplicated`, - [Event.WORKSPACE_PUBLISHED]: `App "{{ name }}" published`, - [Event.WORKSPACE_UNPUBLISHED]: `App "{{ name }}" unpublished`, - [Event.WORKSPACE_TEMPLATE_IMPORTED]: `App "{{ name }}" template imported`, - [Event.WORKSPACE_FILE_IMPORTED]: `App "{{ name }}" file imported`, - [Event.WORKSPACE_APP_VERSION_UPDATED]: `App "{{ name }}" version updated`, - [Event.WORKSPACE_APP_VERSION_REVERTED]: `App "{{ name }}" version reverted`, - [Event.WORKSPACE_REVERTED]: `App "{{ name }}" reverted`, - [Event.WORKSPACE_EXPORTED]: `App "{{ name }}" exported`, - [Event.APP_BACKUP_RESTORED]: `App backup "{{ name }}" restored`, - [Event.APP_BACKUP_TRIGGERED]: `App backup "{{ name }}" triggered`, - - // DATASOURCE - [Event.DATASOURCE_CREATED]: `Datasource created`, - [Event.DATASOURCE_UPDATED]: `Datasource updated`, - [Event.DATASOURCE_DELETED]: `Datasource deleted`, - - // QUERY - [Event.QUERY_CREATED]: `Query created`, - [Event.QUERY_UPDATED]: `Query updated`, - [Event.QUERY_DELETED]: `Query deleted`, - [Event.QUERY_IMPORT]: `Query import`, - [Event.QUERIES_RUN]: undefined, - [Event.QUERY_PREVIEWED]: undefined, - - // TABLE - [Event.TABLE_CREATED]: `Table "{{ name }}" created`, - [Event.TABLE_UPDATED]: `Table "{{ name }}" updated`, - [Event.TABLE_DELETED]: `Table "{{ name }}" deleted`, - [Event.TABLE_EXPORTED]: `Table "{{ name }}" exported`, - [Event.TABLE_IMPORTED]: `Table "{{ name }}" imported`, - [Event.TABLE_DATA_IMPORTED]: `Data imported to table`, - - // ROWS - [Event.ROWS_CREATED]: `Rows created`, - [Event.ROWS_IMPORTED]: `Rows imported`, - - // AUTOMATION - [Event.AUTOMATION_CREATED]: `Automation "{{ name }}" created`, - [Event.AUTOMATION_DELETED]: `Automation "{{ name }}" deleted`, - [Event.AUTOMATION_STEP_CREATED]: `Automation "{{ name }}" step added`, - [Event.AUTOMATION_STEP_DELETED]: `Automation "{{ name }}" step removed`, - [Event.AUTOMATION_TESTED]: undefined, - [Event.AUTOMATIONS_RUN]: undefined, - [Event.AUTOMATION_TRIGGER_UPDATED]: undefined, - - // SCREEN - [Event.SCREEN_CREATED]: `Screen "{{ name }}" created`, - [Event.SCREEN_DELETED]: `Screen "{{ name }}" deleted`, - - // COMPONENT - [Event.COMPONENT_CREATED]: `Component created`, - [Event.COMPONENT_DELETED]: `Component deleted`, - - // ENVIRONMENT VARIABLE - [Event.ENVIRONMENT_VARIABLE_CREATED]: `Environment variable created`, - [Event.ENVIRONMENT_VARIABLE_DELETED]: `Environment variable deleted`, - [Event.ENVIRONMENT_VARIABLE_UPGRADE_PANEL_OPENED]: undefined, - - // PLUGIN - [Event.PLUGIN_IMPORTED]: `Plugin imported`, - [Event.PLUGIN_DELETED]: `Plugin deleted`, - [Event.PLUGIN_INIT]: undefined, - - // ACTIONS - NOT AUDITED - [Event.ACTION_AUTOMATION_STEP_EXECUTED]: undefined, - [Event.ACTION_CRUD_EXECUTED]: undefined, - [Event.ACTION_AI_AGENT_EXECUTED]: undefined, - - // ROLE - NOT AUDITED - [Event.ROLE_CREATED]: undefined, - [Event.ROLE_UPDATED]: undefined, - [Event.ROLE_DELETED]: undefined, - [Event.ROLE_ASSIGNED]: undefined, - [Event.ROLE_UNASSIGNED]: undefined, - - // LICENSE - NOT AUDITED - [Event.LICENSE_PLAN_CHANGED]: undefined, - [Event.LICENSE_ACTIVATED]: undefined, - [Event.LICENSE_PAYMENT_FAILED]: undefined, - [Event.LICENSE_PAYMENT_RECOVERED]: undefined, - [Event.LICENSE_CHECKOUT_OPENED]: undefined, - [Event.LICENSE_CHECKOUT_SUCCESS]: undefined, - [Event.LICENSE_PORTAL_OPENED]: undefined, - - // BACKFILL - NOT AUDITED - [Event.APP_BACKFILL_SUCCEEDED]: undefined, - [Event.APP_BACKFILL_FAILED]: undefined, - [Event.TENANT_BACKFILL_SUCCEEDED]: undefined, - [Event.TENANT_BACKFILL_FAILED]: undefined, - [Event.INSTALLATION_BACKFILL_SUCCEEDED]: undefined, - [Event.INSTALLATION_BACKFILL_FAILED]: undefined, - - // LAYOUT - NOT AUDITED - [Event.LAYOUT_CREATED]: undefined, - [Event.LAYOUT_DELETED]: undefined, - - // VIEW - NOT AUDITED - [Event.VIEW_CREATED]: undefined, - [Event.VIEW_UPDATED]: undefined, - [Event.VIEW_DELETED]: undefined, - [Event.VIEW_EXPORTED]: undefined, - [Event.VIEW_FILTER_CREATED]: undefined, - [Event.VIEW_FILTER_UPDATED]: undefined, - [Event.VIEW_FILTER_DELETED]: undefined, - [Event.VIEW_CALCULATION_CREATED]: undefined, - [Event.VIEW_CALCULATION_UPDATED]: undefined, - [Event.VIEW_CALCULATION_DELETED]: undefined, - [Event.VIEW_JOIN_CREATED]: undefined, - - // SERVED - NOT AUDITED - [Event.SERVED_BUILDER]: undefined, - [Event.SERVED_APP]: undefined, - [Event.SERVED_APP_PREVIEW]: undefined, - - // ANALYTICS - NOT AUDITED - [Event.ANALYTICS_OPT_OUT]: undefined, - [Event.ANALYTICS_OPT_IN]: undefined, - - // INSTALLATION - NOT AUDITED - [Event.INSTALLATION_VERSION_CHECKED]: undefined, - [Event.INSTALLATION_VERSION_UPGRADED]: undefined, - [Event.INSTALLATION_VERSION_DOWNGRADED]: undefined, - [Event.INSTALLATION_FIRST_STARTUP]: undefined, - - // AUDIT LOG - NOT AUDITED - [Event.AUDIT_LOGS_FILTERED]: undefined, - [Event.AUDIT_LOGS_DOWNLOADED]: undefined, - - // ROW ACTIONS - NOT AUDITED - [Event.ROW_ACTION_CREATED]: undefined, - - // WORKSPACE APP - [Event.WORKSPACE_APP_CREATED]: undefined, - [Event.WORKSPACE_APP_DELETED]: undefined, - [Event.WORKSPACE_APP_UPDATED]: undefined, - - [Event.RESOURCE_COPIED_TO_WORKSPACE]: `{{ resource.type }} copied to workspace`, -} - export type TableExportFormat = "json" | "csv" - -export type DocUpdateEvent = { - id: string - tenantId: string - appId?: string - properties: any -} - -// properties added at the final stage of the event pipeline -export interface BaseEvent { - version?: string - service?: string - environment?: string - appId?: string - installationId?: string - tenantId?: string - hosting?: Hosting - // any props in the audited section will be removed before passing events - // up out of system (purely for use with auditing) - audited?: { - [key: string]: any - } -} - -export interface EventProcessor { - processEvent( - event: Event, - identity: Identity, - properties: any, - timestamp?: string | number - ): Promise - identify?(identity: Identity, timestamp?: string | number): Promise - identifyGroup?(group: Group, timestamp?: string | number): Promise - shutdown?(): Promise -} diff --git a/packages/types/src/sdk/events/datasource.ts b/packages/types/src/sdk/events/datasource.ts deleted file mode 100644 index 4ac7a5fa..00000000 --- a/packages/types/src/sdk/events/datasource.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type { BaseEvent } from "../events" - -export interface DatasourceCreatedEvent extends BaseEvent { - datasourceId: string - source: string - custom: boolean -} - -export interface DatasourceUpdatedEvent extends BaseEvent { - datasourceId: string - source: string - custom: boolean -} - -export interface DatasourceDeletedEvent extends BaseEvent { - datasourceId: string - source: string - custom: boolean -} diff --git a/packages/types/src/sdk/events/index.ts b/packages/types/src/sdk/events/index.ts deleted file mode 100644 index 3752e8ff..00000000 --- a/packages/types/src/sdk/events/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./datasource" -export * from "./query" -export * from "./table" -export * from "./user" diff --git a/packages/types/src/sdk/events/query.ts b/packages/types/src/sdk/events/query.ts deleted file mode 100644 index 0eed86a1..00000000 --- a/packages/types/src/sdk/events/query.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { BaseEvent } from "../events" - -export interface QueryCreatedEvent extends BaseEvent { - queryId: string - datasourceId: string - source: string - queryVerb: string -} - -export interface QueryUpdatedEvent extends BaseEvent { - queryId: string - datasourceId: string - source: string - queryVerb: string -} - -export interface QueryDeletedEvent extends BaseEvent { - queryId: string - datasourceId: string - source: string - queryVerb: string -} - -export interface QueryImportedEvent extends BaseEvent { - datasourceId: string - source: string - count: number - importSource: string -} - -export interface QueryPreviewedEvent extends BaseEvent { - queryId?: string - datasourceId: string - source: string - queryVerb: string -} - -export interface QueriesRunEvent extends BaseEvent { - count: number -} diff --git a/packages/types/src/sdk/events/table.ts b/packages/types/src/sdk/events/table.ts deleted file mode 100644 index d5921ff6..00000000 --- a/packages/types/src/sdk/events/table.ts +++ /dev/null @@ -1,48 +0,0 @@ -import type { BaseEvent, TableExportFormat } from "../events" - -export interface TableCreatedEvent extends BaseEvent { - tableId: string - audited: { - name: string - } -} - -export interface TableUpdatedEvent extends BaseEvent { - tableId: string - defaultValues: boolean | undefined - audited: { - name: string - } -} - -export interface TableDeletedEvent extends BaseEvent { - tableId: string - audited: { - name: string - } -} - -export interface TableExportedEvent extends BaseEvent { - tableId: string - format: TableExportFormat - audited: { - name: string - } -} - -export interface TableImportedEvent extends BaseEvent { - tableId: string - audited: { - name: string - } -} -export interface WorkspaceAppDeletedEvent extends BaseEvent { - workspaceAppId: string - audited: { - name: string - } -} -export interface ViewDeletedEvent extends BaseEvent { - tableId?: string - id?: string -} diff --git a/packages/types/src/sdk/events/user.ts b/packages/types/src/sdk/events/user.ts deleted file mode 100644 index 6c5a0916..00000000 --- a/packages/types/src/sdk/events/user.ts +++ /dev/null @@ -1,84 +0,0 @@ -import type { BaseEvent } from "../events" - -export interface UserCreatedEvent extends BaseEvent { - userId: string - viaScim?: boolean - audited: { - email: string - } -} - -export interface UserUpdatedEvent extends BaseEvent { - userId: string - viaScim?: boolean - audited: { - email: string - } -} - -export interface UserDeletedEvent extends BaseEvent { - userId: string - viaScim?: boolean - audited: { - email: string - } -} - -export interface UserPermissionAssignedEvent extends BaseEvent { - userId: string - audited: { - email: string - } -} - -export interface UserPermissionRemovedEvent extends BaseEvent { - userId: string - audited: { - email: string - } -} - -export interface UserInvitedEvent extends BaseEvent { - audited: { - email: string - } -} - -export interface UserInviteAcceptedEvent extends BaseEvent { - userId: string - audited: { - email: string - } -} - -export interface UserPasswordForceResetEvent extends BaseEvent { - userId: string - audited: { - email: string - } -} - -export interface UserPasswordUpdatedEvent extends BaseEvent { - userId: string - audited: { - email: string - } -} - -export interface UserPasswordResetRequestedEvent extends BaseEvent { - userId: string - audited: { - email: string - } -} - -export interface UserPasswordResetEvent extends BaseEvent { - userId: string - audited: { - email: string - } -} - -export interface UserDataCollaborationEvent extends BaseEvent { - users: number -} diff --git a/packages/types/src/sdk/index.ts b/packages/types/src/sdk/index.ts index 0ad48b79..892c48ad 100644 --- a/packages/types/src/sdk/index.ts +++ b/packages/types/src/sdk/index.ts @@ -5,7 +5,6 @@ export * from "./datasources" export * from "./db" export * from "./environmentVariables" export * from "./events" -export * from "./events/index" export * from "./hosting" export * from "./koa" export * from "./locks" diff --git a/packages/types/src/sdk/koa.ts b/packages/types/src/sdk/koa.ts index 24255dbf..d6ce62e4 100644 --- a/packages/types/src/sdk/koa.ts +++ b/packages/types/src/sdk/koa.ts @@ -1,8 +1,7 @@ import type { File } from "formidable" import type { Context, Request } from "koa" import type { UserAgentContext } from "koa-useragent" -import type { EventType } from "../core" -import type { Role, Row, Table, User, UserBindings, UserRoles, UserSSO } from "../documents" +import type { Role, User, UserRoles, UserSSO } from "../documents" export enum LoginMethod { API_KEY = "api_key", @@ -60,7 +59,6 @@ export interface UserCtx< user: ContextUser state: { nonce?: string } roleId?: string - eventEmitter?: ContextEmitter loginMethod?: LoginMethod } @@ -71,32 +69,3 @@ export interface UserCtx< export interface BBContext extends Ctx { user?: ContextUser } - -export interface ContextEmitter { - emitRow(values: { - eventName: EventType.ROW_SAVE - appId: string - row: Row - table: Table - user: UserBindings - }): void - emitRow(values: { - eventName: EventType.ROW_UPDATE - appId: string - row: Row - table: Table - oldRow: Row - user: UserBindings - }): void - emitRow(values: { - eventName: EventType.ROW_DELETE - appId: string - row: Row - user: UserBindings - }): void - emitTable( - eventName: EventType.TABLE_SAVE | EventType.TABLE_DELETE, - appId: string, - table?: Table - ): void -} diff --git a/packages/worker/package.json b/packages/worker/package.json index 9fad8c0b..09e2d649 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -50,12 +50,11 @@ "koa-body": "7.0.1", "koa-compress": "4.0.1", "koa-passport": "4.1.4", - "koa-redis": "4.0.1", "koa-send": "5.0.1", "koa-session": "5.13.1", "koa-static": "5.0.0", "koa-useragent": "4.1.0", - "lodash": "4.17.23", + "lodash": "4.18.1", "marked": "15.0.11", "node-fetch": "2.6.7", "nodemailer": "7.0.11", diff --git a/packages/worker/src/index.ts b/packages/worker/src/index.ts index 3db36c3c..2a756d8b 100644 --- a/packages/worker/src/index.ts +++ b/packages/worker/src/index.ts @@ -15,7 +15,6 @@ import { bootstrap } from "global-agent" import gracefulShutdown from "http-graceful-shutdown" import Application, { type Middleware } from "koa" import koaBody, { HttpMethodEnum } from "koa-body" -import RedisStore from "koa-redis" import api from "./api" import { loadTemplateConfig } from "./constants/templates" import * as db from "./db" @@ -62,8 +61,18 @@ let store: any const sessionMiddleware: Middleware = async (ctx: any, next: any) => { if (!store) { const redisClient = await redis.clients.getSessionClient() - // @ts-expect-error - koa-redis types are weird - store = RedisStore({ client: redisClient.client }) + store = { + async get(key: string) { + const data = await redisClient.client.get(key) + return data ? JSON.parse(data) : null + }, + async set(key: string, sess: any, maxAge: number) { + await redisClient.client.setex(key, maxAge / 1000, JSON.stringify(sess)) + }, + async destroy(key: string) { + await redisClient.client.del(key) + }, + } } return koaSession( diff --git a/packages/worker/src/koa-redis.d.ts b/packages/worker/src/koa-redis.d.ts deleted file mode 100644 index ad1b7a46..00000000 --- a/packages/worker/src/koa-redis.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module "koa-redis" {} diff --git a/yarn.lock b/yarn.lock index 758584c9..88aa0af2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2124,7 +2124,7 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/runtime@^7.10.5", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.8.3", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.12.5", "@babel/runtime@^7.9.2": version "7.29.2" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.29.2.tgz#9a6e2d05f4b6692e1801cd4fb176ad823930ed5e" integrity sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g== @@ -5657,13 +5657,6 @@ dependencies: "@types/node" "*" -"@types/archiver@6.0.2": - version "6.0.2" - resolved "https://registry.yarnpkg.com/@types/archiver/-/archiver-6.0.2.tgz#0daf8c83359cbde69de1e4b33dcade6a48a929e2" - integrity sha512-KmROQqbQzKGuaAbmK+ZcytkJ51+YqDa7NmbXjmtC5YBLSyQYo21YaUnQ3HbaPFKL1ooo6RQ6OPYPIDyxfpDDXw== - dependencies: - "@types/readdir-glob" "*" - "@types/aria-query@^5.0.1": version "5.0.4" resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" @@ -6031,11 +6024,6 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.200.tgz#435b6035c7eba9cdf1e039af8212c9e9281e7149" integrity sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q== -"@types/lodash@^4.14.165", "@types/lodash@^4.14.175": - version "4.17.24" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.24.tgz#4ae334fc62c0e915ca8ed8e35dcc6d4eeb29215f" - integrity sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ== - "@types/long@^4.0.0": version "4.0.2" resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" @@ -6312,13 +6300,6 @@ dependencies: "@types/node" "*" -"@types/readdir-glob@*": - version "1.1.5" - resolved "https://registry.yarnpkg.com/@types/readdir-glob/-/readdir-glob-1.1.5.tgz#21a4a98898fc606cb568ad815f2a0eedc24d412a" - integrity sha512-raiuEPUYqXu+nvtY2Pe8s8FEmZ3x5yAH4VkLdihcPdalvsHltomrRC9BzuStrJ9yk06470hS0Crw0f1pXqD+Hg== - dependencies: - "@types/node" "*" - "@types/redis@^2.8.0": version "2.8.32" resolved "https://registry.yarnpkg.com/@types/redis/-/redis-2.8.32.tgz#1d3430219afbee10f8cfa389dad2571a05ecfb11" @@ -7094,7 +7075,7 @@ archiver-utils@^5.0.0, archiver-utils@^5.0.2: normalize-path "^3.0.0" readable-stream "^4.0.0" -archiver@7.0.1, archiver@^7.0.1: +archiver@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/archiver/-/archiver-7.0.1.tgz#c9d91c350362040b8927379c7aa69c0655122f61" integrity sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ== @@ -8204,14 +8185,7 @@ co-body@^6.2.0: raw-body "^2.3.3" type-is "^1.6.16" -co-wrap-all@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/co-wrap-all/-/co-wrap-all-1.0.0.tgz#370ae3e8333510a53f6b2f7fdfbe4568a11b7ecf" - integrity sha512-aru6gLi2vTUazr+MxVm3Rv6ST7/EKtFj9BrfkcOrbCO2Qv6LqJdE71m88HhHiBEviKw/ucVrwoGLrq2xHpOsJA== - dependencies: - co "^4.0.0" - -co@^4.0.0, co@^4.6.0: +co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== @@ -8661,13 +8635,6 @@ cron-parser@^4.2.1: dependencies: luxon "^3.2.1" -cron-validate@1.4.5: - version "1.4.5" - resolved "https://registry.yarnpkg.com/cron-validate/-/cron-validate-1.4.5.tgz#eceb221f7558e6302e5f84c7b3a454fdf4d064c3" - integrity sha512-nKlOJEnYKudMn/aNyNH8xxWczlfpaazfWV32Pcx/2St51r2bxWbGhZD7uwzMcRhunA/ZNL+Htm/i0792Z59UMQ== - dependencies: - yup "0.32.9" - cross-spawn@^7.0.3, cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" @@ -11605,7 +11572,7 @@ ioredis@5.3.2: redis-parser "^3.0.0" standard-as-callback "^2.1.0" -ioredis@^4.14.1, ioredis@^4.28.5: +ioredis@^4.28.5: version "4.31.0" resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.31.0.tgz#2aa72dc63162c04b2d65a7fa82e52277f8f23e66" integrity sha512-tVrCrc4LWJwX82GD79dZ0teZQGq+5KJEGpXJRgzHOrhHtLgF9ME6rTwDV5+HN5bjnvmtrnS8ioXhflY16sy2HQ== @@ -13103,16 +13070,6 @@ koa-pino-logger@4.0.0: dependencies: pino-http "^6.5.0" -koa-redis@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/koa-redis/-/koa-redis-4.0.1.tgz#57ac1b46d9ab851221a9f4952c1e8d4bf289db40" - integrity sha512-o2eTVNo1NBnloeUGhHed5Q2ZvJSLpUEj/+E1/7oH5EmH8WuQ+QLdl/VawkshxdFQ47W1p6V09lM3hCTu7D0YnQ== - dependencies: - "@babel/runtime" "^7.8.3" - co-wrap-all "^1.0.0" - debug "^4.1.1" - ioredis "^4.14.1" - koa-send@5.0.1, koa-send@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/koa-send/-/koa-send-5.0.1.tgz#39dceebfafb395d0d60beaffba3a70b4f543fe79" @@ -13539,11 +13496,6 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lodash-es@^4.17.15, lodash-es@^4.17.21: - version "4.17.23" - resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.23.tgz#58c4360fd1b5d33afc6c0bbd3d1149349b1138e0" - integrity sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg== - lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" @@ -13649,10 +13601,10 @@ lodash.xor@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.xor/-/lodash.xor-4.5.0.tgz#4d48ed7e98095b0632582ba714d3ff8ae8fb1db6" integrity sha512-sVN2zimthq7aZ5sPGXnSz32rZPuqcparVW50chJQe+mzTYV+IsxSsl/2gnkWWE2Of7K3myBQBqtLKOUEHJKRsQ== -lodash@4.17.23, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21: - version "4.17.23" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.23.tgz#f113b0378386103be4f6893388c73d0bde7f2c5a" - integrity sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w== +lodash@4.18.1, lodash@^4.17.15, lodash@^4.17.21: + version "4.18.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.18.1.tgz#ff2b66c1f6326d59513de2407bf881439812771c" + integrity sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q== log-symbols@^4.0.0, log-symbols@^4.1.0: version "4.1.0" @@ -14357,11 +14309,6 @@ nano@11.0.3: resolved "https://registry.yarnpkg.com/nano/-/nano-11.0.3.tgz#61dffb1133d9f844030550008964835098ccc8d2" integrity sha512-bOiBWTW5sA92Rp2Tuu5LmujUe0rre5AAKuiXuhjD4tBAVRZRrKWK0AJyEYWFm9PN8TRktsbUfUdDb//c5Cr3Dg== -nanoclone@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4" - integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA== - nanoid@^3.3.11: version "3.3.11" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" @@ -16267,7 +16214,7 @@ properties-reader@^3.0.1: "@kwsites/file-exists" "^1.1.1" mkdirp "^3.0.1" -property-expr@^2.0.4: +property-expr@^2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.6.tgz#f77bc00d5928a6c748414ad12882e83f24aec1e8" integrity sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA== @@ -18429,6 +18376,11 @@ timekeeper@2.2.0: resolved "https://registry.yarnpkg.com/timekeeper/-/timekeeper-2.2.0.tgz#9645731fce9e3280a18614a57a9d1b72af3ca368" integrity sha512-W3AmPTJWZkRwu+iSNxPIsLZ2ByADsOLbbLxe46UJyWj3mlYLlwucKiq+/dPm0l9wTzqoF3/2PH0AGFCebjq23A== +tiny-case@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-case/-/tiny-case-1.0.3.tgz#d980d66bc72b5d5a9ca86fb7c9ffdb9c898ddd03" + integrity sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q== + tiny-glob@^0.2.9: version "0.2.9" resolved "https://registry.yarnpkg.com/tiny-glob/-/tiny-glob-0.2.9.tgz#2212d441ac17928033b110f8b3640683129d31e2" @@ -18716,6 +18668,11 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== +type-fest@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" + integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== + type-fest@^5.3.1: version "5.5.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-5.5.0.tgz#78fca72f3a1f9ec964e6ae260db492b070c56f3b" @@ -19716,31 +19673,15 @@ yoctocolors-cjs@^2.1.3: resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz#7e4964ea8ec422b7a40ac917d3a344cfd2304baa" integrity sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw== -yup@0.32.11: - version "0.32.11" - resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.11.tgz#d67fb83eefa4698607982e63f7ca4c5ed3cf18c5" - integrity sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg== +yup@1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/yup/-/yup-1.7.1.tgz#4c47c6bb367df08d4bc597f8c4c4f5fc4277f6ab" + integrity sha512-GKHFX2nXul2/4Dtfxhozv701jLQHdf6J34YDh2cEkpqoo8le5Mg6/LrdseVLrFarmFygZTlfIhHx/QKfb/QWXw== dependencies: - "@babel/runtime" "^7.15.4" - "@types/lodash" "^4.14.175" - lodash "^4.17.21" - lodash-es "^4.17.21" - nanoclone "^0.2.1" - property-expr "^2.0.4" - toposort "^2.0.2" - -yup@0.32.9: - version "0.32.9" - resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.9.tgz#9367bec6b1b0e39211ecbca598702e106019d872" - integrity sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg== - dependencies: - "@babel/runtime" "^7.10.5" - "@types/lodash" "^4.14.165" - lodash "^4.17.20" - lodash-es "^4.17.15" - nanoclone "^0.2.1" - property-expr "^2.0.4" + property-expr "^2.0.5" + tiny-case "^1.0.3" toposort "^2.0.2" + type-fest "^2.19.0" z-schema@^4.2.3: version "4.2.4"