diff --git a/packages/core/actions/package.json b/packages/core/actions/package.json index 4e95570e0..e0eba5993 100644 --- a/packages/core/actions/package.json +++ b/packages/core/actions/package.json @@ -13,5 +13,9 @@ "koa": "^2.13.4", "lodash": "4.17.21", "sequelize": "^6.26.0" + }, + "devDependencies": { + "@types/koa": "^2.15.0", + "@types/lodash": "^4.17.5" } } diff --git a/packages/core/actions/src/index.ts b/packages/core/actions/src/index.ts index 024eadd1e..75309bc96 100644 --- a/packages/core/actions/src/index.ts +++ b/packages/core/actions/src/index.ts @@ -1,8 +1,10 @@ import { Cache } from '@tachybase/cache'; import { Database } from '@tachybase/database'; import { Action } from '@tachybase/resourcer'; + import Koa from 'koa'; import lodash from 'lodash'; + import * as actions from './actions'; export * as utils from './utils'; @@ -18,6 +20,11 @@ export interface Context extends Koa.Context { body: any; app: any; + /** + * 是否包裹 data 对象,比如返回的 body 为 "success",withoutDataWrapping 为 false 的时候,返回的 body 会被包成 { "data": "success" } + */ + withoutDataWrapping?: boolean; + [key: string]: any; } diff --git a/packages/core/server/src/application.ts b/packages/core/server/src/application.ts index d78ac0d12..2e8bff026 100644 --- a/packages/core/server/src/application.ts +++ b/packages/core/server/src/application.ts @@ -21,7 +21,7 @@ import { Telemetry, TelemetryOptions } from '@tachybase/telemetry'; import { applyMixins, AsyncEmitter, importModule, Toposort, ToposortOptions } from '@tachybase/utils'; import { Command, CommandOptions, ParseOptions } from 'commander'; -import glob from 'glob'; +import { sync } from 'glob'; import { i18n, InitOptions } from 'i18next'; import Koa, { DefaultContext as KoaDefaultContext, DefaultState as KoaDefaultState } from 'koa'; import compose from 'koa-compose'; @@ -643,7 +643,7 @@ export class Application exten }; const extensions = ['js', 'ts']; const patten = `${directory}/*.{${extensions.join(',')}}`; - const files = glob.sync(patten, { + const files = sync(patten, { ignore: ['**/*.d.ts'], }); const appVersion = await this.version.get(); diff --git a/packages/core/server/src/middlewares/data-wrapping.ts b/packages/core/server/src/middlewares/data-wrapping.ts index 4f0323a8e..a732532ac 100644 --- a/packages/core/server/src/middlewares/data-wrapping.ts +++ b/packages/core/server/src/middlewares/data-wrapping.ts @@ -1,5 +1,5 @@ -import { Context, Next } from '@tachybase/actions'; import stream from 'stream'; +import { Context, Next } from '@tachybase/actions'; export function dataWrapping() { return async function dataWrapping(ctx: Context, next: Next) { diff --git a/packages/plugins/@hera/plugin-core/src/client/settings-manager-components/TokenConfiguration.tsx b/packages/plugins/@hera/plugin-core/src/client/settings-manager-components/TokenConfiguration.tsx index 981bca9e9..b1da6f323 100644 --- a/packages/plugins/@hera/plugin-core/src/client/settings-manager-components/TokenConfiguration.tsx +++ b/packages/plugins/@hera/plugin-core/src/client/settings-manager-components/TokenConfiguration.tsx @@ -9,11 +9,12 @@ import { getSSKey, TokenConfigurationResourceKey, useMapConfiguration } from '.. interface BaseConfigurationProps { type: 'feishu'; + children: React.ReactNode; } export const TokenTypes = [{ label: '飞书', value: 'feishu' }]; -const BaseConfiguration: React.FC = ({ type, children }) => { +const BaseConfiguration = ({ type, children }: BaseConfigurationProps) => { const [isDisabled, disableAction] = useBoolean(false); const apiClient = useAPIClient(); const [form] = Form.useForm(); diff --git a/packages/plugins/@hera/plugin-core/src/client/settings-manager-components/WebhookManager.tsx b/packages/plugins/@hera/plugin-core/src/client/settings-manager-components/WebhookManager.tsx new file mode 100644 index 000000000..fbe088790 --- /dev/null +++ b/packages/plugins/@hera/plugin-core/src/client/settings-manager-components/WebhookManager.tsx @@ -0,0 +1,687 @@ +import React from 'react'; +import { ExtendCollectionsProvider, SchemaComponent } from '@tachybase/client'; +import { ISchema } from '@tachybase/schema'; + +import { tval } from '../locale'; + +const collection = { + name: 'webhooks', + fields: [ + { + type: 'string', + name: 'name', + interface: 'input', + uiSchema: { + title: tval('name'), + type: 'string', + 'x-component': 'Input', + required: true, + } as ISchema, + }, + { + type: 'boolean', + name: 'enabled', + interface: 'radioGroup', + uiSchema: { + title: tval('Enabled'), + type: 'string', + enum: [ + { label: tval('On'), value: true, color: '#52c41a' }, + { label: tval('Off'), value: false }, + ], + 'x-component': 'Radio.Group', + 'x-decorator': 'FormItem', + default: false, + } as ISchema, + }, + { + type: 'string', + name: 'type', + interface: 'radioGroup', + uiSchema: { + title: tval('Type'), + type: 'string', + enum: [ + { label: tval('Code'), value: 'code' }, + { label: tval('Plugin'), value: 'plugin', disabled: true }, + ], + 'x-component': 'Radio.Group', + 'x-decorator': 'FormItem', + default: 'code', + } as ISchema, + }, + { + type: 'text', + name: 'code', + interface: 'textarea', + uiSchema: { + title: tval('Code'), + type: 'string', + 'x-component': 'Input.TextArea', + } as ISchema, + }, + ], +}; + +const schema: ISchema = { + type: 'void', + properties: { + table: { + type: 'void', + 'x-decorator': 'TableBlockProvider', + 'x-acl-action': 'webhooks:list', + 'x-use-decorator-props': 'useTableBlockDecoratorProps', + 'x-decorator-props': { + collection, + dataSource: 'main', + action: 'list', + params: { + pageSize: 20, + }, + rowKey: 'id', + showIndex: true, + dragSort: false, + }, + 'x-component': 'CardItem', + 'x-filter-targets': [], + properties: { + actions: { + type: 'void', + 'x-component': 'ActionBar', + 'x-component-props': { + style: { + marginBottom: 'var(--tb-spacing)', + }, + }, + properties: { + z8monqcdrdn: { + type: 'void', + 'x-action': 'create', + 'x-acl-action': 'create', + title: "{{t('Add new')}}", + 'x-component': 'Action', + 'x-decorator': 'ACLActionProvider', + 'x-component-props': { + openMode: 'drawer', + type: 'primary', + component: 'CreateRecordAction', + icon: 'PlusOutlined', + }, + 'x-align': 'right', + 'x-acl-action-props': { + skipScopeCheck: true, + }, + properties: { + drawer: { + type: 'void', + title: '{{ t("Add record") }}', + 'x-component': 'Action.Container', + 'x-component-props': { + className: 'nb-action-popup', + }, + properties: { + tabs: { + type: 'void', + 'x-component': 'Tabs', + 'x-component-props': {}, + properties: { + tab1: { + type: 'void', + title: '{{t("Add new")}}', + 'x-component': 'Tabs.TabPane', + 'x-component-props': {}, + properties: { + grid: { + type: 'void', + 'x-component': 'Grid', + properties: { + ei36i9ijtdz: { + type: 'void', + 'x-component': 'Grid.Row', + properties: { + uf8t2a39414: { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + xkkjkzn90fv: { + type: 'void', + 'x-acl-action-props': { + skipScopeCheck: true, + }, + 'x-acl-action': 'webhooks:create', + 'x-decorator': 'FormBlockProvider', + 'x-use-decorator-props': 'useCreateFormBlockDecoratorProps', + 'x-decorator-props': { + dataSource: 'main', + collection, + }, + 'x-component': 'CardItem', + properties: { + '5gbs46leolu': { + type: 'void', + 'x-component': 'FormV2', + 'x-use-component-props': 'useCreateFormBlockProps', + properties: { + '9tt9z4mql3z': { + type: 'void', + 'x-component': 'ActionBar', + 'x-component-props': { + style: { + marginBottom: 24, + }, + }, + properties: { + gqrnx8zyjp1: { + title: '{{t("Submit")}}', + 'x-action': 'submit', + 'x-component': 'Action', + 'x-component-props': { + type: 'primary', + htmlType: 'submit', + useProps: '{{ useCreateActionProps }}', + }, + 'x-action-settings': { + assignedValues: {}, + triggerWorkflows: [], + pageMode: false, + }, + type: 'void', + }, + }, + }, + grid: { + type: 'void', + 'x-component': 'Grid', + properties: { + '5sakq51jsle': { + type: 'void', + 'x-component': 'Grid.Row', + properties: { + '6p28yhfkrbi': { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + name: { + type: 'string', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'webhooks.name', + 'x-component-props': {}, + }, + }, + }, + }, + }, + y7idu8knr7g: { + type: 'void', + 'x-component': 'Grid.Row', + properties: { + zbq1q6f85lf: { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + enabled: { + type: 'string', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'webhooks.enabled', + 'x-component-props': {}, + }, + }, + }, + }, + }, + hmyd06j1xh1: { + type: 'void', + 'x-component': 'Grid.Row', + properties: { + '6l4tt4kcu2h': { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + workflow: { + type: 'string', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'webhooks.workflow', + 'x-component-props': { + fieldNames: { + value: 'id', + label: 'name', + }, + }, + }, + }, + }, + }, + }, + qrrbe5or0h5: { + type: 'void', + 'x-component': 'Grid.Row', + properties: { + '5w93jhg5355': { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + type: { + type: 'string', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'webhooks.type', + 'x-component-props': {}, + }, + }, + }, + }, + }, + '38fm61ehxvn': { + type: 'void', + 'x-component': 'Grid.Row', + properties: { + arovreokda8: { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + code: { + type: 'string', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'webhooks.code', + 'x-component-props': {}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + '8l8237xpji1': { + type: 'array', + 'x-component': 'TableV2', + 'x-use-component-props': 'useTableBlockProps', + 'x-component-props': { + rowKey: 'id', + rowSelection: { + type: 'checkbox', + }, + }, + properties: { + c5we84shjz1: { + type: 'void', + 'x-decorator': 'TableV2.Column.Decorator', + 'x-component': 'TableV2.Column', + properties: { + name: { + 'x-collection-field': 'webhooks.name', + 'x-component': 'CollectionField', + 'x-component-props': { + ellipsis: true, + }, + 'x-read-pretty': true, + 'x-decorator': null, + 'x-decorator-props': { + labelStyle: { + display: 'none', + }, + }, + }, + }, + }, + q5o7ghhoepw: { + type: 'void', + 'x-decorator': 'TableV2.Column.Decorator', + 'x-component': 'TableV2.Column', + properties: { + enabled: { + 'x-collection-field': 'webhooks.enabled', + 'x-component': 'CollectionField', + 'x-component-props': { + ellipsis: true, + }, + 'x-read-pretty': true, + 'x-decorator': null, + 'x-decorator-props': { + labelStyle: { + display: 'none', + }, + }, + }, + }, + }, + ud1epmyj09v: { + type: 'void', + 'x-decorator': 'TableV2.Column.Decorator', + 'x-component': 'TableV2.Column', + properties: { + workflow: { + 'x-collection-field': 'webhooks.workflow', + 'x-component': 'CollectionField', + 'x-component-props': { + fieldNames: { + value: 'id', + label: 'name', + }, + ellipsis: true, + size: 'small', + }, + 'x-read-pretty': true, + 'x-decorator': null, + 'x-decorator-props': { + labelStyle: { + display: 'none', + }, + }, + }, + }, + }, + '8i54l0rnfth': { + type: 'void', + 'x-decorator': 'TableV2.Column.Decorator', + 'x-component': 'TableV2.Column', + properties: { + type: { + 'x-collection-field': 'webhooks.type', + 'x-component': 'CollectionField', + 'x-component-props': {}, + 'x-read-pretty': true, + 'x-decorator': null, + 'x-decorator-props': { + labelStyle: { + display: 'none', + }, + }, + }, + }, + }, + xatpoztbh5h: { + type: 'void', + title: '{{ t("Actions") }}', + 'x-decorator': 'TableV2.Column.ActionBar', + 'x-component': 'TableV2.Column', + 'x-component-props': { + width: 150, + fixed: 'right', + }, + 'x-action-column': 'actions', + properties: { + gta931e187b: { + type: 'void', + 'x-decorator': 'DndContext', + 'x-component': 'Space', + 'x-component-props': { + split: '|', + }, + properties: { + oyggiyxrxlr: { + type: 'void', + title: '{{ t("Edit") }}', + 'x-action': 'update', + 'x-component': 'Action.Link', + 'x-component-props': { + openMode: 'drawer', + icon: 'EditOutlined', + }, + 'x-decorator': 'ACLActionProvider', + properties: { + drawer: { + type: 'void', + title: '{{ t("Edit record") }}', + 'x-component': 'Action.Container', + 'x-component-props': { + className: 'nb-action-popup', + }, + properties: { + tabs: { + type: 'void', + 'x-component': 'Tabs', + 'x-component-props': {}, + properties: { + tab1: { + type: 'void', + title: '{{t("Edit")}}', + 'x-component': 'Tabs.TabPane', + 'x-component-props': {}, + properties: { + grid: { + type: 'void', + 'x-component': 'Grid', + properties: { + to6mk4v552h: { + type: 'void', + 'x-component': 'Grid.Row', + properties: { + sqvdrzdbr7r: { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + '8uym9fty5oy': { + type: 'void', + 'x-acl-action-props': { + skipScopeCheck: false, + }, + 'x-acl-action': 'webhooks:update', + 'x-decorator': 'FormBlockProvider', + 'x-use-decorator-props': 'useEditFormBlockDecoratorProps', + 'x-decorator-props': { + action: 'get', + dataSource: 'main', + collection, + }, + 'x-component': 'CardItem', + properties: { + je28rbthifp: { + type: 'void', + 'x-component': 'FormV2', + 'x-use-component-props': 'useEditFormBlockProps', + properties: { + yviwt5e73dx: { + type: 'void', + 'x-component': 'ActionBar', + 'x-component-props': { + style: { + marginBottom: 'var(--tb-spacing)', + }, + }, + properties: { + unkmoqgvtvr: { + title: '{{ t("Submit") }}', + 'x-action': 'submit', + 'x-component': 'Action', + 'x-use-component-props': 'useUpdateActionProps', + 'x-component-props': { + type: 'primary', + htmlType: 'submit', + }, + 'x-action-settings': { + triggerWorkflows: [], + onSuccess: { + manualClose: false, + redirecting: false, + successMessage: '{{t("Updated successfully")}}', + }, + isDeltaChanged: false, + }, + type: 'void', + }, + }, + }, + grid: { + type: 'void', + 'x-component': 'Grid', + properties: { + '5sakq51jsle': { + type: 'void', + 'x-component': 'Grid.Row', + properties: { + '6p28yhfkrbi': { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + name: { + type: 'string', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'webhooks.name', + 'x-component-props': {}, + }, + }, + }, + }, + }, + y7idu8knr7g: { + type: 'void', + 'x-component': 'Grid.Row', + properties: { + zbq1q6f85lf: { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + enabled: { + type: 'string', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'webhooks.enabled', + 'x-component-props': {}, + }, + }, + }, + }, + }, + hmyd06j1xh1: { + type: 'void', + 'x-component': 'Grid.Row', + properties: { + '6l4tt4kcu2h': { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + workflow: { + type: 'string', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'webhooks.workflow', + 'x-component-props': { + fieldNames: { + value: 'id', + label: 'name', + }, + }, + }, + }, + }, + }, + }, + qrrbe5or0h5: { + type: 'void', + 'x-component': 'Grid.Row', + properties: { + '5w93jhg5355': { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + type: { + type: 'string', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'webhooks.type', + 'x-component-props': {}, + }, + }, + }, + }, + }, + '38fm61ehxvn': { + type: 'void', + 'x-component': 'Grid.Row', + properties: { + arovreokda8: { + type: 'void', + 'x-component': 'Grid.Col', + properties: { + code: { + type: 'string', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'webhooks.code', + 'x-component-props': {}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + q74i285l3sx: { + title: '{{ t("Delete") }}', + 'x-action': 'destroy', + 'x-component': 'Action.Link', + 'x-use-component-props': 'useDestroyActionProps', + 'x-component-props': { + icon: 'DeleteOutlined', + confirm: { + title: "{{t('Delete record')}}", + content: "{{t('Are you sure you want to delete it?')}}", + }, + }, + 'x-action-settings': { + triggerWorkflows: [], + }, + 'x-decorator': 'ACLActionProvider', + type: 'void', + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, +}; + +export const WebhookManager = () => { + return ( + + + + ); +}; diff --git a/packages/plugins/@hera/plugin-core/src/client/settings-manager-components/index.ts b/packages/plugins/@hera/plugin-core/src/client/settings-manager-components/index.ts index c43057447..4f3de72c0 100644 --- a/packages/plugins/@hera/plugin-core/src/client/settings-manager-components/index.ts +++ b/packages/plugins/@hera/plugin-core/src/client/settings-manager-components/index.ts @@ -4,6 +4,7 @@ import { tval } from '../locale'; import { Features } from './Features'; import { LinkManager } from './LinkManager'; import { Configuration } from './TokenConfiguration'; +import { WebhookManager } from './WebhookManager'; export * from './LinkManager'; export * from './TokenConfiguration'; @@ -30,5 +31,10 @@ export class PluginSettingsHelper { icon: 'ShareAltOutlined', Component: LinkManager, }); + this.app.pluginSettingsManager.add('hera.webhook', { + title: tval('Webhook manager'), + icon: 'ShareAltOutlined', + Component: WebhookManager, + }); } } diff --git a/packages/plugins/@hera/plugin-core/src/server/actions/index.ts b/packages/plugins/@hera/plugin-core/src/server/actions/index.ts index 3e9a28e4b..c2ebf644c 100644 --- a/packages/plugins/@hera/plugin-core/src/server/actions/index.ts +++ b/packages/plugins/@hera/plugin-core/src/server/actions/index.ts @@ -5,3 +5,4 @@ export * from './link-manager-controller'; export * from './system-message-controller'; export * from './departments'; export * from './users'; +export * from './webhooks'; diff --git a/packages/plugins/@hera/plugin-core/src/server/actions/webhooks.ts b/packages/plugins/@hera/plugin-core/src/server/actions/webhooks.ts new file mode 100644 index 000000000..6143c698b --- /dev/null +++ b/packages/plugins/@hera/plugin-core/src/server/actions/webhooks.ts @@ -0,0 +1,44 @@ +import { Context } from '@tachybase/actions'; +import { Action, Controller } from '@tachybase/utils'; + +@Controller('webhooks') +export class WebhookController { + @Action('trigger') + async getLink(ctx: Context) { + const { + params: { name }, + } = ctx.action; + const where = {}; + if (name) { + where['filter'] = { + name: name, + enabled: true, + }; + } + + if (!name) { + throw new Error('not support'); + } + const repo = ctx.db.getRepository('webhooks'); + const webhook = await repo.findOne(where); + const webhookCtx = { + action: ctx.action, + body: '', + }; + run(webhook.code, { + ctx: webhookCtx, + }); + if (webhookCtx.body) { + ctx.withoutDataWrapping = true; + ctx.body = webhookCtx.body; + } + } +} + +function run(jsCode: string, { ctx }) { + try { + return new Function('$root', `with($root) { ${jsCode}; }`)({ ctx }); + } catch (err) { + console.log('err', err); + } +} diff --git a/packages/plugins/@hera/plugin-core/src/server/collections/webhooks.ts b/packages/plugins/@hera/plugin-core/src/server/collections/webhooks.ts new file mode 100644 index 000000000..8e9af1bdf --- /dev/null +++ b/packages/plugins/@hera/plugin-core/src/server/collections/webhooks.ts @@ -0,0 +1,31 @@ +import { defineCollection } from '@tachybase/database'; + +export default defineCollection({ + name: 'webhooks', + dumpRules: { + group: 'required', + }, + fields: [ + { + name: 'name', + unique: true, + type: 'string', + }, + { + name: 'enabled', + type: 'boolean', + }, + { + name: 'workflowKey', + type: 'string', + }, + { + name: 'type', // code/plugin + type: 'string', + }, + { + name: 'code', + type: 'text', + }, + ], +}); diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/schemas/workflows.ts b/packages/plugins/@tachybase/plugin-workflow/src/client/schemas/workflows.ts index 3efce74b3..a566e507d 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/schemas/workflows.ts +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/schemas/workflows.ts @@ -1,10 +1,11 @@ -import { ISchema, useForm } from '@tachybase/schema'; +import React from 'react'; import { useActionContext, useRecord, useResourceActionContext, useResourceContext } from '@tachybase/client'; +import { ISchema, useForm } from '@tachybase/schema'; + import { message } from 'antd'; import { useTranslation } from 'react-i18next'; + import { NAMESPACE } from '../locale'; -// import { triggers } from '../triggers'; -import React from 'react'; import { executionSchema } from './executions'; const collection = { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 52fd3fee9..c121c9f11 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -173,6 +173,13 @@ importers: sequelize: specifier: ^6.26.0 version: 6.35.2 + devDependencies: + '@types/koa': + specifier: ^2.15.0 + version: 2.15.0 + '@types/lodash': + specifier: ^4.17.5 + version: 4.17.5 packages/core/app: dependencies: @@ -12179,23 +12186,23 @@ packages: /@types/koa-bodyparser@4.3.12: resolution: {integrity: sha512-hKMmRMVP889gPIdLZmmtou/BijaU1tHPyMNmcK7FAHAdATnRcGQQy78EqTTxLH1D4FTsrxIzklAQCso9oGoebQ==} dependencies: - '@types/koa': 2.13.12 + '@types/koa': 2.15.0 /@types/koa-compose@3.2.8: resolution: {integrity: sha512-4Olc63RY+MKvxMwVknCUDhRQX1pFQoBZ/lXcRLP69PQkEpze/0cr8LNqJQe5NFb/b19DWi2a5bTi2VAlQzhJuA==} dependencies: - '@types/koa': 2.13.12 + '@types/koa': 2.15.0 /@types/koa-multer@1.0.4: resolution: {integrity: sha512-Aty7k5W/bVgvCtyc7iwzjP1QXp1CPsQE3klmIEVBphK2bthjJjUpgkvFNChckA8DPxaatzFmnotWZnXLAAnLog==} dependencies: - '@types/koa': 2.13.12 + '@types/koa': 2.15.0 dev: true /@types/koa-send@4.1.6: resolution: {integrity: sha512-vgnNGoOJkx7FrF0Jl6rbK1f8bBecqAchKpXtKuXzqIEdXTDO6dsSTjr+eZ5m7ltSjH4K/E7auNJEQCAd0McUPA==} dependencies: - '@types/koa': 2.13.12 + '@types/koa': 2.15.0 dev: false /@types/koa@2.13.12: @@ -12210,10 +12217,22 @@ packages: '@types/koa-compose': 3.2.8 '@types/node': 20.12.8 + /@types/koa@2.15.0: + resolution: {integrity: sha512-7QFsywoE5URbuVnG3loe03QXuGajrnotr3gQkXcEBShORai23MePfFYdhz90FEtBBpkyIYQbVD+evKtloCgX3g==} + dependencies: + '@types/accepts': 1.3.7 + '@types/content-disposition': 0.5.8 + '@types/cookies': 0.7.10 + '@types/http-assert': 1.5.5 + '@types/http-errors': 2.0.4 + '@types/keygrip': 1.0.6 + '@types/koa-compose': 3.2.8 + '@types/node': 20.12.8 + /@types/koa__cors@5.0.0: resolution: {integrity: sha512-LCk/n25Obq5qlernGOK/2LUwa/2YJb2lxHUkkvYFDOpLXlVI6tKcdfCHRBQnOY4LwH6el5WOLs6PD/a8Uzau6g==} dependencies: - '@types/koa': 2.13.12 + '@types/koa': 2.15.0 dev: true /@types/linkify-it@3.0.5: @@ -12227,6 +12246,10 @@ packages: resolution: {integrity: sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ==} dev: true + /@types/lodash@4.17.5: + resolution: {integrity: sha512-MBIOHVZqVqgfro1euRDWX7OO0fBVUUMrN6Pwm8LQsz8cWhEpihlvR70ENj3f40j58TNxZaWv2ndSkInykNBBJw==} + dev: true + /@types/luxon@3.3.7: resolution: {integrity: sha512-gKc9P2d4g5uYwmy4s/MO/yOVPmvHyvzka1YH6i5dM03UrFofHSmgc0D0ymbDRStFWHusk6cwwF6nhLm/ckBbbQ==}