diff --git a/packages/core/logger/src/create-logger.ts b/packages/core/logger/src/create-logger.ts index 2920d4652..ff376f15d 100644 --- a/packages/core/logger/src/create-logger.ts +++ b/packages/core/logger/src/create-logger.ts @@ -19,7 +19,7 @@ const Transports = { ...options, }); }, - dailyRotateFile(options: any) { + dailyRotateFile(options: any = {}) { let dirname = getLoggerFilePath(); if (!path.isAbsolute(dirname)) { dirname = path.resolve(process.cwd(), dirname); diff --git a/packages/plugins/@nocobase/plugin-custom-request/src/client/hooks/useCustomizeRequestActionProps.ts b/packages/plugins/@nocobase/plugin-custom-request/src/client/hooks/useCustomizeRequestActionProps.ts index 18b145bde..d2926d19d 100644 --- a/packages/plugins/@nocobase/plugin-custom-request/src/client/hooks/useCustomizeRequestActionProps.ts +++ b/packages/plugins/@nocobase/plugin-custom-request/src/client/hooks/useCustomizeRequestActionProps.ts @@ -47,7 +47,7 @@ export const useCustomizeRequestActionProps = () => { await form.submit(); } - const requestConfig = {}; + let formValues = {}; const methods = ['POST', 'PUT', 'PATCH']; if (xAction === 'customize:form:request' && methods.includes(options['method'])) { const fieldNames = fields.map((field) => field.name); @@ -60,7 +60,7 @@ export const useCustomizeRequestActionProps = () => { resource, actionFields: getActiveFieldsName?.('form') || [], }); - requestConfig['data'] = values; + formValues = values; } actionField.data ??= {}; @@ -70,10 +70,10 @@ export const useCustomizeRequestActionProps = () => { url: `/customRequests:send/${fieldSchema['x-uid']}`, method: 'POST', data: { - requestConfig, currentRecord: { id: record[getPrimaryKey()], appends: service.params[0].appends, + data: formValues, }, }, }); diff --git a/packages/plugins/@nocobase/plugin-custom-request/src/server/__tests__/__snapshots__/actions.test.ts.snap b/packages/plugins/@nocobase/plugin-custom-request/src/server/__tests__/__snapshots__/actions.test.ts.snap new file mode 100644 index 000000000..81af83be9 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-custom-request/src/server/__tests__/__snapshots__/actions.test.ts.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`actions send basic 1`] = `undefined`; + +exports[`actions send currentRecord.data 1`] = ` +{ + "username": "testname", +} +`; diff --git a/packages/plugins/@nocobase/plugin-custom-request/src/server/__tests__/actions.test.ts b/packages/plugins/@nocobase/plugin-custom-request/src/server/__tests__/actions.test.ts index ae3ec1993..098ad74fd 100644 --- a/packages/plugins/@nocobase/plugin-custom-request/src/server/__tests__/actions.test.ts +++ b/packages/plugins/@nocobase/plugin-custom-request/src/server/__tests__/actions.test.ts @@ -9,10 +9,10 @@ describe('actions', () => { let agent: ReturnType; let resource: ReturnType['resource']>; - beforeEach(async () => { + beforeAll(async () => { app = mockServer({ registerActions: true, - acl: true, + acl: false, plugins: ['users', 'auth', 'acl', 'custom-request'], }); @@ -24,35 +24,47 @@ describe('actions', () => { }); describe('send', () => { - let params; - beforeEach(async () => { - app.resource({ - name: 'custom-request-test', - actions: { - test(ctx: Context) { - params = ctx.action.params; - console.log('🚀 ~ file: actions.test.ts:34 ~ test ~ params:', params); - return 'test ok'; - }, - }, + let params = null; + beforeAll(async () => { + app.resourcer.getResource('customRequests').addAction('test', (ctx: Context) => { + params = ctx.action.params.values; + return ctx.action.params.values; }); - }); - beforeEach(async () => { await repo.create({ values: { key: 'test', options: { - url: 'http://localhost:13000/api/custom-request-test:test', + url: '/customRequests:test', method: 'GET', + data: { + username: '{{ currentRecord.username }}', + }, }, }, }); }); + test('basic', async () => { const res = await resource.send({ filterByTk: 'test', }); - console.log(res.status); + expect(res.status).toBe(200); + expect(params).toMatchSnapshot(); + }); + + test('currentRecord.data', async () => { + const res = await resource.send({ + filterByTk: 'test', + values: { + currentRecord: { + data: { + username: 'testname', + }, + }, + }, + }); + expect(res.status).toBe(200); + expect(params).toMatchSnapshot(); }); }); }); diff --git a/packages/plugins/@nocobase/plugin-custom-request/src/server/actions/send.ts b/packages/plugins/@nocobase/plugin-custom-request/src/server/actions/send.ts index 4b08213cd..f4fa214b6 100644 --- a/packages/plugins/@nocobase/plugin-custom-request/src/server/actions/send.ts +++ b/packages/plugins/@nocobase/plugin-custom-request/src/server/actions/send.ts @@ -1,8 +1,8 @@ import { Context, Next } from '@nocobase/actions'; -import actions from '@nocobase/actions'; import { parse } from '@nocobase/utils'; import axios from 'axios'; +import CustomRequestPlugin from '../plugin'; const getHeaders = (headers: Record) => { return Object.keys(headers).reduce((hds, key) => { @@ -29,14 +29,14 @@ const omitNullAndUndefined = (obj: any) => { }, {}); }; -export async function send(ctx: Context, next: Next) { +export async function send(this: CustomRequestPlugin, ctx: Context, next: Next) { const { filterByTk, resourceName, values = {} } = ctx.action.params; const { - currentRecord: { id: currentRecordId, appends: currentRecordAppends } = { + currentRecord = { id: 0, appends: [], + data: {}, }, - requestConfig: requestConfigFirst = {}, } = values; // root role has all permissions @@ -68,45 +68,66 @@ export async function send(ctx: Context, next: Next) { ctx.withoutDataWrapping = true; - const { collectionName, url, headers = {}, params = {}, data = {}, ...options } = requestConfig.options; - let currentRecord = {}; - if (collectionName && typeof currentRecordId !== 'undefined') { + const { collectionName, url, headers = [], params = [], data = {}, ...options } = requestConfig.options; + let currentRecordVariables = {}; + if (collectionName && typeof currentRecord.id !== 'undefined') { const recordRepo = ctx.db.getRepository(collectionName); - currentRecord = await recordRepo.findOne({ - filterByTk: currentRecordId, - appends: currentRecordAppends, + currentRecordVariables = await recordRepo.findOne({ + filterByTk: currentRecord.id, + appends: currentRecord.appends, }); } const variables = { - currentRecord, + currentRecord: { + ...currentRecordVariables, + ...currentRecord.data, + }, currentUser: ctx.auth.user, currentTime: new Date().toISOString(), }; - try { - ctx.body = await axios({ - baseURL: ctx.origin, - ...options, - url: parse(url)(variables), + const axiosRequestConfig = { + baseURL: ctx.origin, + ...options, + url: parse(url)(variables), + headers: { + Authorization: 'Bearer ' + ctx.getBearerToken(), + ...getHeaders(ctx.headers), + ...omitNullAndUndefined(parse(arrayToObject(headers))(variables)), + }, + params: parse(arrayToObject(params))(variables), + data: parse(data)(variables), + }; + + const requestUrl = axios.getUri(axiosRequestConfig); + this.logger.info(`custom-request:send:${filterByTk} request url ${requestUrl}`); + this.logger.info( + `custom-request:send:${filterByTk} request config ${JSON.stringify({ + ...axiosRequestConfig, headers: { - Authorization: 'Bearer ' + ctx.getBearerToken(), - ...getHeaders(ctx.headers), - ...omitNullAndUndefined(parse(arrayToObject(headers))(variables)), + ...axiosRequestConfig.headers, + Authorization: null, }, - params: parse(arrayToObject(params))(variables), - data: parse({ - ...data, - ...requestConfigFirst?.data, - })(variables), - }).then((res) => { + })}`, + ); + + try { + ctx.body = await axios(axiosRequestConfig).then((res) => { + this.logger.info(`custom-request:send:${filterByTk} success`); return res.data; }); - } catch (err: any) { + } catch (err) { if (axios.isAxiosError(err)) { ctx.status = err.response?.status || 500; ctx.body = err.response?.data || { message: err.message }; + this.logger.error( + `custom-request:send:${filterByTk} error. status: ${ctx.status}, body: ${ + typeof ctx.body === 'string' ? ctx.body : JSON.stringify(ctx.body) + }`, + ); } else { + this.logger.error(`custom-request:send:${filterByTk} error. status: ${ctx.status}, message: ${err.message}`); ctx.throw(500, err?.message); } } diff --git a/packages/plugins/@nocobase/plugin-custom-request/src/server/plugin.ts b/packages/plugins/@nocobase/plugin-custom-request/src/server/plugin.ts index 68ae8cff8..22a60362e 100644 --- a/packages/plugins/@nocobase/plugin-custom-request/src/server/plugin.ts +++ b/packages/plugins/@nocobase/plugin-custom-request/src/server/plugin.ts @@ -1,12 +1,31 @@ +import { Logger, LoggerOptions, Transports, createLogger, getLoggerFilePath } from '@nocobase/logger'; import { InstallOptions, Plugin } from '@nocobase/server'; import { resolve } from 'path'; -import { send } from './actions/send'; import { listByCurrentRole } from './actions/listByCurrentRole'; +import { send } from './actions/send'; export class CustomRequestPlugin extends Plugin { + logger: Logger; + afterAdd() {} - beforeLoad() {} + beforeLoad() { + this.logger = this.getLogger(); + } + + getLogger(): Logger { + const logger = createLogger({ + transports: [ + 'console', + Transports.dailyRotateFile({ + dirname: getLoggerFilePath('custom-request'), + filename: this.app.name + '-%DATE%.log', + }), + ], + } as LoggerOptions); + + return logger; + } async load() { await this.db.import({ @@ -16,7 +35,7 @@ export class CustomRequestPlugin extends Plugin { this.app.resource({ name: 'customRequests', actions: { - send, + send: send.bind(this), listByCurrentRole, }, });