feat: support webhook-manager (#1152)

Reviewed-on: daoyoucloud/tachybase#1152
This commit is contained in:
sealday 2024-06-11 17:18:34 +08:00
parent dd6dd616d3
commit 7ef88ad093
12 changed files with 817 additions and 12 deletions

View File

@ -13,5 +13,9 @@
"koa": "^2.13.4", "koa": "^2.13.4",
"lodash": "4.17.21", "lodash": "4.17.21",
"sequelize": "^6.26.0" "sequelize": "^6.26.0"
},
"devDependencies": {
"@types/koa": "^2.15.0",
"@types/lodash": "^4.17.5"
} }
} }

View File

@ -1,8 +1,10 @@
import { Cache } from '@tachybase/cache'; import { Cache } from '@tachybase/cache';
import { Database } from '@tachybase/database'; import { Database } from '@tachybase/database';
import { Action } from '@tachybase/resourcer'; import { Action } from '@tachybase/resourcer';
import Koa from 'koa'; import Koa from 'koa';
import lodash from 'lodash'; import lodash from 'lodash';
import * as actions from './actions'; import * as actions from './actions';
export * as utils from './utils'; export * as utils from './utils';
@ -18,6 +20,11 @@ export interface Context extends Koa.Context {
body: any; body: any;
app: any; app: any;
/**
* data body "success"withoutDataWrapping false body { "data": "success" }
*/
withoutDataWrapping?: boolean;
[key: string]: any; [key: string]: any;
} }

View File

@ -21,7 +21,7 @@ import { Telemetry, TelemetryOptions } from '@tachybase/telemetry';
import { applyMixins, AsyncEmitter, importModule, Toposort, ToposortOptions } from '@tachybase/utils'; import { applyMixins, AsyncEmitter, importModule, Toposort, ToposortOptions } from '@tachybase/utils';
import { Command, CommandOptions, ParseOptions } from 'commander'; import { Command, CommandOptions, ParseOptions } from 'commander';
import glob from 'glob'; import { sync } from 'glob';
import { i18n, InitOptions } from 'i18next'; import { i18n, InitOptions } from 'i18next';
import Koa, { DefaultContext as KoaDefaultContext, DefaultState as KoaDefaultState } from 'koa'; import Koa, { DefaultContext as KoaDefaultContext, DefaultState as KoaDefaultState } from 'koa';
import compose from 'koa-compose'; import compose from 'koa-compose';
@ -643,7 +643,7 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
}; };
const extensions = ['js', 'ts']; const extensions = ['js', 'ts'];
const patten = `${directory}/*.{${extensions.join(',')}}`; const patten = `${directory}/*.{${extensions.join(',')}}`;
const files = glob.sync(patten, { const files = sync(patten, {
ignore: ['**/*.d.ts'], ignore: ['**/*.d.ts'],
}); });
const appVersion = await this.version.get(); const appVersion = await this.version.get();

View File

@ -1,5 +1,5 @@
import { Context, Next } from '@tachybase/actions';
import stream from 'stream'; import stream from 'stream';
import { Context, Next } from '@tachybase/actions';
export function dataWrapping() { export function dataWrapping() {
return async function dataWrapping(ctx: Context, next: Next) { return async function dataWrapping(ctx: Context, next: Next) {

View File

@ -9,11 +9,12 @@ import { getSSKey, TokenConfigurationResourceKey, useMapConfiguration } from '..
interface BaseConfigurationProps { interface BaseConfigurationProps {
type: 'feishu'; type: 'feishu';
children: React.ReactNode;
} }
export const TokenTypes = [{ label: '飞书', value: 'feishu' }]; export const TokenTypes = [{ label: '飞书', value: 'feishu' }];
const BaseConfiguration: React.FC<BaseConfigurationProps> = ({ type, children }) => { const BaseConfiguration = ({ type, children }: BaseConfigurationProps) => {
const [isDisabled, disableAction] = useBoolean(false); const [isDisabled, disableAction] = useBoolean(false);
const apiClient = useAPIClient(); const apiClient = useAPIClient();
const [form] = Form.useForm(); const [form] = Form.useForm();

View File

@ -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 (
<ExtendCollectionsProvider collections={[collection]}>
<SchemaComponent memoized schema={schema}></SchemaComponent>
</ExtendCollectionsProvider>
);
};

View File

@ -4,6 +4,7 @@ import { tval } from '../locale';
import { Features } from './Features'; import { Features } from './Features';
import { LinkManager } from './LinkManager'; import { LinkManager } from './LinkManager';
import { Configuration } from './TokenConfiguration'; import { Configuration } from './TokenConfiguration';
import { WebhookManager } from './WebhookManager';
export * from './LinkManager'; export * from './LinkManager';
export * from './TokenConfiguration'; export * from './TokenConfiguration';
@ -30,5 +31,10 @@ export class PluginSettingsHelper {
icon: 'ShareAltOutlined', icon: 'ShareAltOutlined',
Component: LinkManager, Component: LinkManager,
}); });
this.app.pluginSettingsManager.add('hera.webhook', {
title: tval('Webhook manager'),
icon: 'ShareAltOutlined',
Component: WebhookManager,
});
} }
} }

View File

@ -5,3 +5,4 @@ export * from './link-manager-controller';
export * from './system-message-controller'; export * from './system-message-controller';
export * from './departments'; export * from './departments';
export * from './users'; export * from './users';
export * from './webhooks';

View File

@ -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);
}
}

View File

@ -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',
},
],
});

View File

@ -1,10 +1,11 @@
import { ISchema, useForm } from '@tachybase/schema'; import React from 'react';
import { useActionContext, useRecord, useResourceActionContext, useResourceContext } from '@tachybase/client'; import { useActionContext, useRecord, useResourceActionContext, useResourceContext } from '@tachybase/client';
import { ISchema, useForm } from '@tachybase/schema';
import { message } from 'antd'; import { message } from 'antd';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { NAMESPACE } from '../locale'; import { NAMESPACE } from '../locale';
// import { triggers } from '../triggers';
import React from 'react';
import { executionSchema } from './executions'; import { executionSchema } from './executions';
const collection = { const collection = {

View File

@ -173,6 +173,13 @@ importers:
sequelize: sequelize:
specifier: ^6.26.0 specifier: ^6.26.0
version: 6.35.2 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: packages/core/app:
dependencies: dependencies:
@ -12179,23 +12186,23 @@ packages:
/@types/koa-bodyparser@4.3.12: /@types/koa-bodyparser@4.3.12:
resolution: {integrity: sha512-hKMmRMVP889gPIdLZmmtou/BijaU1tHPyMNmcK7FAHAdATnRcGQQy78EqTTxLH1D4FTsrxIzklAQCso9oGoebQ==} resolution: {integrity: sha512-hKMmRMVP889gPIdLZmmtou/BijaU1tHPyMNmcK7FAHAdATnRcGQQy78EqTTxLH1D4FTsrxIzklAQCso9oGoebQ==}
dependencies: dependencies:
'@types/koa': 2.13.12 '@types/koa': 2.15.0
/@types/koa-compose@3.2.8: /@types/koa-compose@3.2.8:
resolution: {integrity: sha512-4Olc63RY+MKvxMwVknCUDhRQX1pFQoBZ/lXcRLP69PQkEpze/0cr8LNqJQe5NFb/b19DWi2a5bTi2VAlQzhJuA==} resolution: {integrity: sha512-4Olc63RY+MKvxMwVknCUDhRQX1pFQoBZ/lXcRLP69PQkEpze/0cr8LNqJQe5NFb/b19DWi2a5bTi2VAlQzhJuA==}
dependencies: dependencies:
'@types/koa': 2.13.12 '@types/koa': 2.15.0
/@types/koa-multer@1.0.4: /@types/koa-multer@1.0.4:
resolution: {integrity: sha512-Aty7k5W/bVgvCtyc7iwzjP1QXp1CPsQE3klmIEVBphK2bthjJjUpgkvFNChckA8DPxaatzFmnotWZnXLAAnLog==} resolution: {integrity: sha512-Aty7k5W/bVgvCtyc7iwzjP1QXp1CPsQE3klmIEVBphK2bthjJjUpgkvFNChckA8DPxaatzFmnotWZnXLAAnLog==}
dependencies: dependencies:
'@types/koa': 2.13.12 '@types/koa': 2.15.0
dev: true dev: true
/@types/koa-send@4.1.6: /@types/koa-send@4.1.6:
resolution: {integrity: sha512-vgnNGoOJkx7FrF0Jl6rbK1f8bBecqAchKpXtKuXzqIEdXTDO6dsSTjr+eZ5m7ltSjH4K/E7auNJEQCAd0McUPA==} resolution: {integrity: sha512-vgnNGoOJkx7FrF0Jl6rbK1f8bBecqAchKpXtKuXzqIEdXTDO6dsSTjr+eZ5m7ltSjH4K/E7auNJEQCAd0McUPA==}
dependencies: dependencies:
'@types/koa': 2.13.12 '@types/koa': 2.15.0
dev: false dev: false
/@types/koa@2.13.12: /@types/koa@2.13.12:
@ -12210,10 +12217,22 @@ packages:
'@types/koa-compose': 3.2.8 '@types/koa-compose': 3.2.8
'@types/node': 20.12.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: /@types/koa__cors@5.0.0:
resolution: {integrity: sha512-LCk/n25Obq5qlernGOK/2LUwa/2YJb2lxHUkkvYFDOpLXlVI6tKcdfCHRBQnOY4LwH6el5WOLs6PD/a8Uzau6g==} resolution: {integrity: sha512-LCk/n25Obq5qlernGOK/2LUwa/2YJb2lxHUkkvYFDOpLXlVI6tKcdfCHRBQnOY4LwH6el5WOLs6PD/a8Uzau6g==}
dependencies: dependencies:
'@types/koa': 2.13.12 '@types/koa': 2.15.0
dev: true dev: true
/@types/linkify-it@3.0.5: /@types/linkify-it@3.0.5:
@ -12227,6 +12246,10 @@ packages:
resolution: {integrity: sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ==} resolution: {integrity: sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ==}
dev: true dev: true
/@types/lodash@4.17.5:
resolution: {integrity: sha512-MBIOHVZqVqgfro1euRDWX7OO0fBVUUMrN6Pwm8LQsz8cWhEpihlvR70ENj3f40j58TNxZaWv2ndSkInykNBBJw==}
dev: true
/@types/luxon@3.3.7: /@types/luxon@3.3.7:
resolution: {integrity: sha512-gKc9P2d4g5uYwmy4s/MO/yOVPmvHyvzka1YH6i5dM03UrFofHSmgc0D0ymbDRStFWHusk6cwwF6nhLm/ckBbbQ==} resolution: {integrity: sha512-gKc9P2d4g5uYwmy4s/MO/yOVPmvHyvzka1YH6i5dM03UrFofHSmgc0D0ymbDRStFWHusk6cwwF6nhLm/ckBbbQ==}