diff --git a/apps/docs/triggers/scheduled.mdx b/apps/docs/triggers/scheduled.mdx index 5a88f4b6e89..65ceba9fc54 100644 --- a/apps/docs/triggers/scheduled.mdx +++ b/apps/docs/triggers/scheduled.mdx @@ -83,3 +83,27 @@ This is especially useful for scheduled triggers that run on a very short interv Set your `triggerTTL` to the same time (or double) as the rateOf the trigger. + +## Live-only scheduled events + +In many cases, you only want scheduled events to run when your code is running on a server, and not locally during development. To do this, you can check the `context.environment` property together with the `context.isTest` property, like so: + +```ts +new Trigger({ + id: "check-scheduler", + name: "Check Scheduler", + on: scheduleEvent({ rateOf: { minutes: 10 } }), + logLevel: "info", + triggerTTL: 600, + run: async (event, context) => { + // Return if in development and not running a test + if (context.environment === "development" && !context.isTest) { + return; + } + + // do stuff here + }, +}).listen(); +``` + +By checking `context.isTest`, you can manually test scheduled events locally before pushing to live. diff --git a/apps/internal-triggers/Dockerfile b/apps/internal-triggers/Dockerfile new file mode 100644 index 00000000000..27416529a20 --- /dev/null +++ b/apps/internal-triggers/Dockerfile @@ -0,0 +1,51 @@ +FROM node:16-bullseye AS pruner +RUN apt-get update && apt-get install openssl -y +WORKDIR /app +RUN npm install turbo -g +COPY . . +RUN turbo prune --scope=internal-triggers --docker +RUN find . -name "node_modules" -type d -prune -exec rm -rf '{}' + + +# Base strategy to have layer caching +FROM node:16-bullseye AS base +RUN apt-get update && apt-get install openssl +WORKDIR /app +COPY .gitignore .gitignore +COPY --from=pruner /app/out/json/ . +COPY --from=pruner /app/out/pnpm-lock.yaml ./pnpm-lock.yaml +COPY --from=pruner /app/out/pnpm-workspace.yaml ./pnpm-workspace.yaml + +FROM base AS production-deps +WORKDIR /app +RUN corepack enable +ENV NODE_ENV production +RUN pnpm install --prod --frozen-lockfile + +FROM base AS builder +WORKDIR /app +RUN npm install turbo -g +COPY turbo.json turbo.json +RUN corepack enable +COPY --from=pruner /app/out/full/ . +ENV NODE_ENV development +RUN pnpm install --ignore-scripts --frozen-lockfile +ENV NODE_ENV production +RUN pnpm run build --filter=internal-triggers + +# Runner +FROM node:16-bullseye AS runner +RUN apt-get update && apt-get install openssl +RUN npm install turbo -g +WORKDIR /app +RUN corepack enable +ENV NODE_ENV production +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 internal-triggersjs +RUN chown -R internal-triggersjs:nodejs /app +USER internal-triggersjs + +COPY --from=pruner --chown=internal-triggersjs:nodejs /app/out/full/ . +COPY --from=production-deps --chown=internal-triggersjs:nodejs /app . +COPY --from=builder --chown=internal-triggersjs:nodejs /app/apps/internal-triggers/dist/index.js ./apps/internal-triggers/dist/index.js + +ENTRYPOINT ["pnpm", "--filter", "internal-triggers", "run", "start"] \ No newline at end of file diff --git a/apps/internal-triggers/package.json b/apps/internal-triggers/package.json new file mode 100644 index 00000000000..ed195efef0f --- /dev/null +++ b/apps/internal-triggers/package.json @@ -0,0 +1,31 @@ +{ + "name": "internal-triggers", + "version": "1.0.0", + "description": "A Node.js server that hosts our internal triggers", + "main": "dist/index.js", + "private": true, + "scripts": { + "clean": "rimraf dist", + "build": "npm run clean && npm run build:tsup", + "build:tsup": "tsup", + "dev": "tsx --require ./node_modules/dotenv/config src/index.ts", + "start": "node dist/index.js" + }, + "keywords": [], + "author": "", + "dependencies": { + "@trigger.dev/integrations": "^0.1.13", + "@trigger.dev/sdk": "^0.2.10", + "pg": "^8.8.0", + "zod": "^3.20.2" + }, + "devDependencies": { + "@trigger.dev/tsconfig": "workspace:*", + "@types/node": "16", + "@types/pg": "^8.6.6", + "dotenv": "^16.0.3", + "rimraf": "^3.0.2", + "tsup": "^6.5.0", + "typescript": "^4.9.4" + } +} \ No newline at end of file diff --git a/apps/internal-triggers/src/db.ts b/apps/internal-triggers/src/db.ts new file mode 100644 index 00000000000..0c43c571f67 --- /dev/null +++ b/apps/internal-triggers/src/db.ts @@ -0,0 +1,43 @@ +import { Pool, QueryResultRow } from "pg"; + +const pool = new Pool({ connectionString: process.env.DATABASE_URL }); + +export async function query( + text: string, + params?: any[] +) { + return pool.query(text, params); +} + +export async function getTableCount( + tableName: string, + startAt: Date, + endAt: Date +) { + const tableCount = await query<{ count: string }>( + `SELECT COUNT(*) as count FROM "${tableName}" WHERE "${tableName}"."createdAt" >= $1 AND "${tableName}"."createdAt" < $2`, + [startAt, endAt] + ).then((result) => parseInt(result.rows[0].count, 10)); + + return tableCount; +} + +export async function getClient() { + const client = await pool.connect(); + const query = client.query; + const release = client.release; + // set a timeout of 5 seconds, after which we will log this client's last query + const timeout = setTimeout(() => { + console.error("A client has been checked out for more than 5 seconds!"); + }, 5000); + + client.release = () => { + // clear our timeout + clearTimeout(timeout); + // set the methods back to their old un-monkey-patched version + client.query = query; + client.release = release; + return release.apply(client); + }; + return client; +} diff --git a/apps/internal-triggers/src/index.ts b/apps/internal-triggers/src/index.ts new file mode 100644 index 00000000000..9ff6b16298d --- /dev/null +++ b/apps/internal-triggers/src/index.ts @@ -0,0 +1,6 @@ +import { checkScheduler, uptimeCheck, healthCheck } from "./monitoring"; + +// checkScheduler.listen(); +// healthCheck.listen(); + +uptimeCheck.listen(); diff --git a/apps/webapp/app/triggers/monitoring.server.ts b/apps/internal-triggers/src/monitoring.ts similarity index 73% rename from apps/webapp/app/triggers/monitoring.server.ts rename to apps/internal-triggers/src/monitoring.ts index 39b6c57b0a6..4285eea241f 100644 --- a/apps/webapp/app/triggers/monitoring.server.ts +++ b/apps/internal-triggers/src/monitoring.ts @@ -1,34 +1,49 @@ import { Trigger, scheduleEvent, customEvent } from "@trigger.dev/sdk"; import { slack } from "@trigger.dev/integrations"; -import { prisma } from "~/db.server"; +import { getTableCount } from "./db"; import { z } from "zod"; export const uptimeCheck = new Trigger({ id: "uptime-check", name: "Uptime Check", on: scheduleEvent({ rateOf: { minutes: 5 } }), - logLevel: "info", + logLevel: "debug", triggerTTL: 300, + endpoint: process.env.TRIGGER_WSS_URL, run: async (event, context) => { if (context.environment === "development" && !context.isTest) { return; } - const filterCondition = { - where: { createdAt: { gte: event.lastRunAt, lt: event.scheduledTime } }, - }; + const { lastRunAt, scheduledTime } = event; + + if (!lastRunAt) { + return; + } // Grab counts of workflows, runs, and steps - const userCount = await prisma.user.count(filterCondition); - const workflowCount = await prisma.workflow.count(filterCondition); - const runCount = await prisma.workflowRun.count(filterCondition); - const stepCount = await prisma.workflowRunStep.count(filterCondition); + const userCount = await getTableCount("User", lastRunAt, scheduledTime); + const workflowCount = await getTableCount( + "Workflow", + lastRunAt, + scheduledTime + ); + const runCount = await getTableCount( + "WorkflowRun", + lastRunAt, + scheduledTime + ); + const stepCount = await getTableCount( + "WorkflowRunStep", + lastRunAt, + scheduledTime + ); await slack.postMessage("Uptime Notification", { channelName: "monitoring", text: `[${ context.environment - }][${event.scheduledTime.toLocaleString()}] Uptime Check: ${userCount} new users, ${workflowCount} new workflows, ${runCount} new runs, ${stepCount} new steps.`, + }][${event.scheduledTime.toLocaleString()}] Uptime Check: ${userCount} new users, ${workflowCount} new workflows, ${runCount} new runs, ${stepCount} new steps`, }); }, }); @@ -36,6 +51,9 @@ export const uptimeCheck = new Trigger({ export const healthCheck = new Trigger({ id: "health-check", name: "Health Check", + endpoint: process.env.TRIGGER_WSS_URL, + logLevel: "debug", + triggerTTL: 600, on: customEvent({ name: "health.check", schema: z.object({ @@ -43,8 +61,6 @@ export const healthCheck = new Trigger({ host: z.string(), }), }), - logLevel: "info", - triggerTTL: 600, run: async (event, context) => { const response = await context.fetch("fetch site", event.url, { method: "GET", @@ -71,7 +87,12 @@ export const checkScheduler = new Trigger({ on: scheduleEvent({ rateOf: { minutes: 10 } }), logLevel: "info", triggerTTL: 600, + endpoint: process.env.TRIGGER_WSS_URL, run: async (event, context) => { + if (context.environment === "development" && !context.isTest) { + return; + } + await context.sendEvent("health.check trigger.dev", { name: "health.check", payload: { diff --git a/apps/internal-triggers/tsconfig.json b/apps/internal-triggers/tsconfig.json new file mode 100644 index 00000000000..1d34f5b3d2b --- /dev/null +++ b/apps/internal-triggers/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "@trigger.dev/tsconfig/node16.json", + "include": ["./src/**/*.ts", "tsup.config.ts"], + "compilerOptions": { + "experimentalDecorators": true, + "emitDecoratorMetadata": true + }, + "exclude": ["node_modules"] +} diff --git a/apps/internal-triggers/tsup.config.ts b/apps/internal-triggers/tsup.config.ts new file mode 100644 index 00000000000..74c4f4dc148 --- /dev/null +++ b/apps/internal-triggers/tsup.config.ts @@ -0,0 +1,19 @@ +import { defineConfig } from "tsup"; + +export default defineConfig([ + { + name: "main", + entry: ["./src/index.ts"], + outDir: "./dist", + platform: "node", + format: ["cjs"], + legacyOutput: true, + sourcemap: true, + clean: true, + bundle: true, + splitting: false, + dts: true, + external: ["http", "https", "util", "events", "tty", "os", "timers"], + esbuildPlugins: [], + }, +]); diff --git a/apps/webapp/app/entry.server.tsx b/apps/webapp/app/entry.server.tsx index f06ef773c91..5a5ec14bac9 100644 --- a/apps/webapp/app/entry.server.tsx +++ b/apps/webapp/app/entry.server.tsx @@ -3,7 +3,6 @@ import { RemixServer } from "@remix-run/react"; import { renderToString } from "react-dom/server"; import * as Sentry from "~/services/sentry.server"; import * as MessageBroker from "~/services/messageBroker.server"; -import * as Triggers from "~/triggers/init.server"; export default function handleRequest( request: Request, @@ -27,4 +26,3 @@ export default function handleRequest( Sentry.init(); MessageBroker.init(); -Triggers.init(); diff --git a/apps/webapp/app/triggers/init.server.ts b/apps/webapp/app/triggers/init.server.ts deleted file mode 100644 index 8107f39b8d2..00000000000 --- a/apps/webapp/app/triggers/init.server.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { uptimeCheck, healthCheck, checkScheduler } from "./monitoring.server"; - -declare global { - var __triggers_initialized: boolean; -} - -export function init() { - if (global.__triggers_initialized) { - return; - } - - global.__triggers_initialized = true; - - uptimeCheck.listen(); - healthCheck.listen(); - checkScheduler.listen(); - - console.log(`🛎 Triggers initialized`); -} diff --git a/flightcontrol.json b/flightcontrol.json index c5f096a2e11..0cded020cae 100644 --- a/flightcontrol.json +++ b/flightcontrol.json @@ -62,11 +62,10 @@ "packages/internal-pulsar/src/**", "./pnpm-lock.yaml" ], - "dependsOn": ["p-db"], + "dependsOn": [ + "p-db" + ], "envVariables": { - "TRIGGER_API_KEY": { - "fromParameterStore": "/Prod/webapp/TRIGGER_API_KEY" - }, "FROM_EMAIL": "hello@email.trigger.dev", "REPLY_TO_EMAIL": "hello@trigger.dev", "RESEND_API_KEY": { @@ -148,7 +147,37 @@ "fromParameterStore": "/Prod/Pulsar/wss/Role" }, "PLATFORM_API_URL": "https://app.trigger.dev", - "TRIGGER_LOG_LEVEL": "debug" + "TRIGGER_LOG_LEVEL": "debug", + "TRIGGER_API_KEY": { + "fromParameterStore": "/Prod/webapp/TRIGGER_API_KEY" + } + } + }, + { + "id": "p-triggers", + "name": "Prod Triggers", + "type": "fargate-worker", + "buildType": "docker", + "dockerfilePath": "./apps/internal-triggers/Dockerfile", + "dockerContext": ".", + "cpu": 1, + "memory": 2, + "minInstances": 1, + "maxInstances": 2, + "watchPaths": [ + "apps/internal-triggers/src/**", + "apps/internal-triggers/tsconfig.json", + "apps/internal-triggers/tsup.config.ts", + "apps/internal-triggers/package.json" + ], + "envVariables": { + "TRIGGER_LOG_LEVEL": "debug", + "DATABASE_URL": { + "fromService": { + "id": "p-db", + "value": "dbConnectionString" + } + } } }, { @@ -238,7 +267,9 @@ "packages/internal-pulsar/src/**", "./pnpm-lock.yaml" ], - "dependsOn": ["s-db"], + "dependsOn": [ + "s-db" + ], "envVariables": { "FROM_EMAIL": "hello@email.trigger.dev", "REPLY_TO_EMAIL": "hello@trigger.dev", @@ -348,4 +379,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index edb916e6231..8693b872850 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,33 @@ importers: devDependencies: mintlify: 2.0.16 + apps/internal-triggers: + specifiers: + '@trigger.dev/integrations': ^0.1.13 + '@trigger.dev/sdk': ^0.2.10 + '@trigger.dev/tsconfig': workspace:* + '@types/node': '16' + '@types/pg': ^8.6.6 + dotenv: ^16.0.3 + pg: ^8.8.0 + rimraf: ^3.0.2 + tsup: ^6.5.0 + typescript: ^4.9.4 + zod: ^3.20.2 + dependencies: + '@trigger.dev/integrations': link:../../packages/trigger-integrations + '@trigger.dev/sdk': link:../../packages/trigger-sdk + pg: 8.8.0 + zod: 3.20.2 + devDependencies: + '@trigger.dev/tsconfig': link:../../config-packages/tsconfig + '@types/node': 16.18.11 + '@types/pg': 8.6.6 + dotenv: 16.0.3 + rimraf: 3.0.2 + tsup: 6.5.0_typescript@4.9.4 + typescript: 4.9.4 + apps/webapp: specifiers: '@aws-sdk/client-s3': ^3.186.0 @@ -184,7 +211,7 @@ importers: '@aws-sdk/client-s3': 3.245.0 '@aws-sdk/s3-request-presigner': 3.245.0 '@cfworker/json-schema': 1.12.5 - '@codemirror/autocomplete': 6.4.0_eo6pz6bvsllvatnnwfprpuflde + '@codemirror/autocomplete': 6.4.0_czcfkg2f66rxeiodoti7r2gulu '@codemirror/commands': 6.1.3 '@codemirror/lang-javascript': 6.1.2 '@codemirror/lang-json': 6.0.1 @@ -211,7 +238,7 @@ importers: '@trigger.dev/integrations': link:../../packages/trigger-integrations '@trigger.dev/providers': link:../../packages/trigger-providers '@trigger.dev/sdk': link:../../packages/trigger-sdk - '@uiw/react-codemirror': 4.19.5_aguurb4bmecpxzejz52amioxne + '@uiw/react-codemirror': 4.19.5_k4ec5g7vuuzzonc3d6xbjnmmle bcryptjs: 2.4.3 classnames: 2.3.2 clsx: 1.2.1 @@ -780,7 +807,7 @@ importers: tsup: ^6.5.0 zod: ^3.20.2 dependencies: - '@react-email/render': 0.0.3_react@18.2.0 + '@react-email/render': 0.0.3 '@trigger.dev/providers': link:../trigger-providers '@trigger.dev/sdk': link:../trigger-sdk zod: 3.20.2 @@ -3485,13 +3512,12 @@ packages: prettier: 2.8.2 dev: false - /@codemirror/autocomplete/6.4.0_eo6pz6bvsllvatnnwfprpuflde: + /@codemirror/autocomplete/6.4.0_czcfkg2f66rxeiodoti7r2gulu: resolution: {integrity: sha512-HLF2PnZAm1s4kGs30EiqKMgD7XsYaQ0XJnMR0rofEWQ5t5D60SfqpDIkIh1ze5tiEbyUWm8+VJ6W1/erVvBMIA==} peerDependencies: '@codemirror/language': ^6.0.0 '@codemirror/state': ^6.0.0 '@codemirror/view': ^6.0.0 - '@lezer/common': ^1.0.0 dependencies: '@codemirror/language': 6.3.2 '@codemirror/state': 6.2.0 @@ -3511,7 +3537,7 @@ packages: /@codemirror/lang-javascript/6.1.2: resolution: {integrity: sha512-OcwLfZXdQ1OHrLiIcKCn7MqZ7nx205CMKlhe+vL88pe2ymhT9+2P+QhwkYGxMICj8TDHyp8HFKVwpiisUT7iEQ==} dependencies: - '@codemirror/autocomplete': 6.4.0_eo6pz6bvsllvatnnwfprpuflde + '@codemirror/autocomplete': 6.4.0_czcfkg2f66rxeiodoti7r2gulu '@codemirror/language': 6.3.2 '@codemirror/lint': 6.1.0 '@codemirror/state': 6.2.0 @@ -4719,6 +4745,16 @@ packages: react-dom: 18.2.0_react@18.2.0 dev: false + /@react-email/render/0.0.3: + resolution: {integrity: sha512-+4eOrLGdTCJjoJU3PunekErjo3PFnhSDFjVINBHrfJT+1wlVdhWfDo7hFdzXJx/JOOYqmnZTilU/umGLdRumKQ==} + engines: {node: '>=18.0.0'} + dependencies: + pretty: 2.0.0 + react-dom: 18.2.0 + transitivePeerDependencies: + - react + dev: false + /@react-email/render/0.0.3_react@18.2.0: resolution: {integrity: sha512-+4eOrLGdTCJjoJU3PunekErjo3PFnhSDFjVINBHrfJT+1wlVdhWfDo7hFdzXJx/JOOYqmnZTilU/umGLdRumKQ==} engines: {node: '>=18.0.0'} @@ -4834,7 +4870,7 @@ packages: eslint: 8.31.0 eslint-import-resolver-node: 0.3.6 eslint-import-resolver-typescript: 3.5.3_hnftvkj7qg3s6bbigj4pr6djxy - eslint-plugin-import: 2.27.4_qdjeohovcytra7xto5vgmxssaq + eslint-plugin-import: 2.27.4_2ac3tknkazjoq5fxmuugu665ny eslint-plugin-jest: 26.9.0_ohsifnwenhmxgcp7mend4dnv74 eslint-plugin-jest-dom: 4.0.3_eslint@8.31.0 eslint-plugin-jsx-a11y: 6.7.1_eslint@8.31.0 @@ -5701,6 +5737,14 @@ packages: /@types/normalize-package-data/2.4.1: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} + /@types/pg/8.6.6: + resolution: {integrity: sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==} + dependencies: + '@types/node': 18.11.18 + pg-protocol: 1.5.0 + pg-types: 2.2.0 + dev: true + /@types/prismjs/1.26.0: resolution: {integrity: sha512-ZTaqn/qSqUuAq1YwvOFQfVW1AR/oQJlLSZVustdjwI+GZ8kr0MSHBj0tsXPW1EqHubx50gtBEjbPGsdZwQwCjQ==} dev: true @@ -5814,7 +5858,7 @@ packages: /@types/ws/8.5.4: resolution: {integrity: sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==} dependencies: - '@types/node': 16.18.11 + '@types/node': 18.11.18 dev: true /@types/yargs-parser/21.0.0: @@ -5964,18 +6008,17 @@ packages: eslint-visitor-keys: 3.3.0 dev: true - /@uiw/codemirror-extensions-basic-setup/4.19.5_tbeldtdcrf45b35pezgkzq2u4e: + /@uiw/codemirror-extensions-basic-setup/4.19.5_wd2tsis3in55bkaiwnc2c46tom: resolution: {integrity: sha512-1zt7ZPJ01xKkSW/KDy0FZNga0bngN1fC594wCVG7FBi60ehfcAucpooQ+JSPScKXopxcb+ugPKZvVLzr9/OfzA==} peerDependencies: '@codemirror/autocomplete': '>=6.0.0' '@codemirror/commands': '>=6.0.0' '@codemirror/language': '>=6.0.0' - '@codemirror/lint': '>=6.0.0' '@codemirror/search': '>=6.0.0' '@codemirror/state': '>=6.0.0' '@codemirror/view': '>=6.0.0' dependencies: - '@codemirror/autocomplete': 6.4.0_eo6pz6bvsllvatnnwfprpuflde + '@codemirror/autocomplete': 6.4.0_czcfkg2f66rxeiodoti7r2gulu '@codemirror/commands': 6.1.3 '@codemirror/language': 6.3.2 '@codemirror/lint': 6.1.0 @@ -5984,14 +6027,11 @@ packages: '@codemirror/view': 6.7.2 dev: false - /@uiw/react-codemirror/4.19.5_aguurb4bmecpxzejz52amioxne: + /@uiw/react-codemirror/4.19.5_k4ec5g7vuuzzonc3d6xbjnmmle: resolution: {integrity: sha512-ZCHh8d7beXbF8/t7F1+yHht6A9Y6CdKeOkZq4A09lxJEnyTQrj1FMf2zvfaqc7K23KNjkTCtSlbqKKbVDgrWaw==} peerDependencies: - '@babel/runtime': '>=7.11.0' '@codemirror/state': '>=6.0.0' - '@codemirror/theme-one-dark': '>=6.0.0' '@codemirror/view': '>=6.0.0' - codemirror: '>=6.0.0' react: '>=16.8.0' react-dom: '>=16.8.0' dependencies: @@ -6000,14 +6040,13 @@ packages: '@codemirror/state': 6.2.0 '@codemirror/theme-one-dark': 6.1.0 '@codemirror/view': 6.7.2 - '@uiw/codemirror-extensions-basic-setup': 4.19.5_tbeldtdcrf45b35pezgkzq2u4e - codemirror: 6.0.1_@lezer+common@1.0.2 + '@uiw/codemirror-extensions-basic-setup': 4.19.5_wd2tsis3in55bkaiwnc2c46tom + codemirror: 6.0.1 react: 18.2.0 react-dom: 18.2.0_react@18.2.0 transitivePeerDependencies: - '@codemirror/autocomplete' - '@codemirror/language' - - '@codemirror/lint' - '@codemirror/search' dev: false @@ -6535,7 +6574,7 @@ packages: /axios/0.25.0_debug@4.3.4: resolution: {integrity: sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==} dependencies: - follow-redirects: 1.15.2_debug@4.3.4 + follow-redirects: 1.15.2 transitivePeerDependencies: - debug dev: true @@ -6543,7 +6582,7 @@ packages: /axios/0.27.2: resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==} dependencies: - follow-redirects: 1.15.2_debug@4.3.4 + follow-redirects: 1.15.2 form-data: 4.0.0 transitivePeerDependencies: - debug @@ -6814,6 +6853,11 @@ packages: resolution: {integrity: sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==} engines: {node: '>=0.10'} + /buffer-writer/2.0.0: + resolution: {integrity: sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==} + engines: {node: '>=4'} + dev: false + /buffer/5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} dependencies: @@ -7321,18 +7365,16 @@ packages: engines: {node: '>=0.10.0'} dev: false - /codemirror/6.0.1_@lezer+common@1.0.2: + /codemirror/6.0.1: resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==} dependencies: - '@codemirror/autocomplete': 6.4.0_eo6pz6bvsllvatnnwfprpuflde + '@codemirror/autocomplete': 6.4.0_czcfkg2f66rxeiodoti7r2gulu '@codemirror/commands': 6.1.3 '@codemirror/language': 6.3.2 '@codemirror/lint': 6.1.0 '@codemirror/search': 6.2.3 '@codemirror/state': 6.2.0 '@codemirror/view': 6.7.2 - transitivePeerDependencies: - - '@lezer/common' dev: false /collection-visit/1.0.0: @@ -8638,7 +8680,7 @@ packages: eslint: 8.31.0 eslint-import-resolver-node: 0.3.7 eslint-import-resolver-typescript: 2.7.1_hnftvkj7qg3s6bbigj4pr6djxy - eslint-plugin-import: 2.27.4_eslint@8.31.0 + eslint-plugin-import: 2.27.4_2es4x7ly2gmvaoztzzbbx3tgsy eslint-plugin-jsx-a11y: 6.7.1_eslint@8.31.0 eslint-plugin-react: 7.31.8_eslint@8.31.0 eslint-plugin-react-hooks: 4.6.0_eslint@8.31.0 @@ -8694,7 +8736,7 @@ packages: dependencies: debug: 4.3.4 eslint: 8.31.0 - eslint-plugin-import: 2.27.4_eslint@8.31.0 + eslint-plugin-import: 2.27.4_2es4x7ly2gmvaoztzzbbx3tgsy glob: 7.2.3 is-glob: 4.0.3 resolve: 1.22.1 @@ -8713,7 +8755,7 @@ packages: debug: 4.3.4 enhanced-resolve: 5.12.0 eslint: 8.31.0 - eslint-plugin-import: 2.27.4_qdjeohovcytra7xto5vgmxssaq + eslint-plugin-import: 2.27.4_2ac3tknkazjoq5fxmuugu665ny get-tsconfig: 4.3.0 globby: 13.1.3 is-core-module: 2.11.0 @@ -8723,7 +8765,7 @@ packages: - supports-color dev: true - /eslint-module-utils/2.7.4_py7h5widiydke2tta7oabbx7ru: + /eslint-module-utils/2.7.4_co4ldsxivxjwelu6vt6qmibemq: resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==} engines: {node: '>=4'} peerDependencies: @@ -8744,14 +8786,16 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: + '@typescript-eslint/parser': 5.48.1_iukboom6ndih5an6iafl45j2fe debug: 3.2.7 eslint: 8.31.0 eslint-import-resolver-node: 0.3.7 + eslint-import-resolver-typescript: 2.7.1_hnftvkj7qg3s6bbigj4pr6djxy transitivePeerDependencies: - supports-color dev: true - /eslint-module-utils/2.7.4_sqt5xxn4ciiurbqrzlaarm6ama: + /eslint-module-utils/2.7.4_v73lhamtbyinynmwa5fn7kpmfq: resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==} engines: {node: '>=4'} peerDependencies: @@ -8776,6 +8820,7 @@ packages: debug: 3.2.7 eslint: 8.31.0 eslint-import-resolver-node: 0.3.7 + eslint-import-resolver-typescript: 3.5.3_hnftvkj7qg3s6bbigj4pr6djxy transitivePeerDependencies: - supports-color dev: true @@ -8800,7 +8845,7 @@ packages: regexpp: 3.2.0 dev: true - /eslint-plugin-import/2.27.4_eslint@8.31.0: + /eslint-plugin-import/2.27.4_2ac3tknkazjoq5fxmuugu665ny: resolution: {integrity: sha512-Z1jVt1EGKia1X9CnBCkpAOhWy8FgQ7OmJ/IblEkT82yrFU/xJaxwujaTzLWqigewwynRQ9mmHfX9MtAfhxm0sA==} engines: {node: '>=4'} peerDependencies: @@ -8810,6 +8855,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: + '@typescript-eslint/parser': 5.48.1_iukboom6ndih5an6iafl45j2fe array-includes: 3.1.6 array.prototype.flat: 1.3.1 array.prototype.flatmap: 1.3.1 @@ -8817,7 +8863,7 @@ packages: doctrine: 2.1.0 eslint: 8.31.0 eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.7.4_py7h5widiydke2tta7oabbx7ru + eslint-module-utils: 2.7.4_v73lhamtbyinynmwa5fn7kpmfq has: 1.0.3 is-core-module: 2.11.0 is-glob: 4.0.3 @@ -8832,7 +8878,7 @@ packages: - supports-color dev: true - /eslint-plugin-import/2.27.4_qdjeohovcytra7xto5vgmxssaq: + /eslint-plugin-import/2.27.4_2es4x7ly2gmvaoztzzbbx3tgsy: resolution: {integrity: sha512-Z1jVt1EGKia1X9CnBCkpAOhWy8FgQ7OmJ/IblEkT82yrFU/xJaxwujaTzLWqigewwynRQ9mmHfX9MtAfhxm0sA==} engines: {node: '>=4'} peerDependencies: @@ -8850,7 +8896,7 @@ packages: doctrine: 2.1.0 eslint: 8.31.0 eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.7.4_sqt5xxn4ciiurbqrzlaarm6ama + eslint-module-utils: 2.7.4_co4ldsxivxjwelu6vt6qmibemq has: 1.0.3 is-core-module: 2.11.0 is-glob: 4.0.3 @@ -9660,17 +9706,6 @@ packages: debug: optional: true - /follow-redirects/1.15.2_debug@4.3.4: - resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - dependencies: - debug: 4.3.4 - /for-each/0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} dependencies: @@ -13296,6 +13331,10 @@ packages: semver: 6.3.0 dev: true + /packet-reader/1.0.0: + resolution: {integrity: sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==} + dev: false + /pako/0.2.9: resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} dev: true @@ -13454,6 +13493,59 @@ packages: is-reference: 3.0.1 dev: true + /pg-connection-string/2.5.0: + resolution: {integrity: sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==} + dev: false + + /pg-int8/1.0.1: + resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} + engines: {node: '>=4.0.0'} + + /pg-pool/3.5.2_pg@8.8.0: + resolution: {integrity: sha512-His3Fh17Z4eg7oANLob6ZvH8xIVen3phEZh2QuyrIl4dQSDVEabNducv6ysROKpDNPSD+12tONZVWfSgMvDD9w==} + peerDependencies: + pg: '>=8.0' + dependencies: + pg: 8.8.0 + dev: false + + /pg-protocol/1.5.0: + resolution: {integrity: sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==} + + /pg-types/2.2.0: + resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} + engines: {node: '>=4'} + dependencies: + pg-int8: 1.0.1 + postgres-array: 2.0.0 + postgres-bytea: 1.0.0 + postgres-date: 1.0.7 + postgres-interval: 1.2.0 + + /pg/8.8.0: + resolution: {integrity: sha512-UXYN0ziKj+AeNNP7VDMwrehpACThH7LUl/p8TDFpEUuSejCUIwGSfxpHsPvtM6/WXFy6SU4E5RG4IJV/TZAGjw==} + engines: {node: '>= 8.0.0'} + peerDependencies: + pg-native: '>=3.0.1' + peerDependenciesMeta: + pg-native: + optional: true + dependencies: + buffer-writer: 2.0.0 + packet-reader: 1.0.0 + pg-connection-string: 2.5.0 + pg-pool: 3.5.2_pg@8.8.0 + pg-protocol: 1.5.0 + pg-types: 2.2.0 + pgpass: 1.0.5 + dev: false + + /pgpass/1.0.5: + resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==} + dependencies: + split2: 4.1.0 + dev: false + /picocolors/1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} @@ -13607,6 +13699,24 @@ packages: picocolors: 1.0.0 source-map-js: 1.0.2 + /postgres-array/2.0.0: + resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} + engines: {node: '>=4'} + + /postgres-bytea/1.0.0: + resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==} + engines: {node: '>=0.10.0'} + + /postgres-date/1.0.7: + resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} + engines: {node: '>=0.10.0'} + + /postgres-interval/1.2.0: + resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} + engines: {node: '>=0.10.0'} + dependencies: + xtend: 4.0.2 + /posthog-js/1.39.4: resolution: {integrity: sha512-Elpf1gwyuObueXi89iH+9pP+WhpkiivP8Qwej4RzOLwSTa7Floaa4rgAw7rnCnX1PtRoJ3F0kqb6q9T+aZjRiA==} dependencies: @@ -13962,6 +14072,15 @@ packages: shallow-equal: 1.2.1 dev: false + /react-dom/18.2.0: + resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} + peerDependencies: + react: ^18.2.0 + dependencies: + loose-envify: 1.4.0 + scheduler: 0.23.0 + dev: false + /react-dom/18.2.0_react@18.2.0: resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} peerDependencies: @@ -15129,6 +15248,11 @@ packages: through: 2.3.8 dev: true + /split2/4.1.0: + resolution: {integrity: sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==} + engines: {node: '>= 10.x'} + dev: false + /sprintf-js/1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}