fix(plugin-custom-request): variables not work in form block (#2873)
* fix: custom-request not work in form * feat: setup logger * test: add test case and fix crush error * feat: improve logger * feat: update log option * fix: logger --------- Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
		
							parent
							
								
									07c5b7b0eb
								
							
						
					
					
						commit
						010c286f7c
					
				| @ -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); | ||||
|  | ||||
| @ -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, | ||||
|             }, | ||||
|           }, | ||||
|         }); | ||||
|  | ||||
| @ -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", | ||||
| } | ||||
| `; | ||||
| @ -9,10 +9,10 @@ describe('actions', () => { | ||||
|   let agent: ReturnType<MockServer['agent']>; | ||||
|   let resource: ReturnType<ReturnType<MockServer['agent']>['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(); | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| @ -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<string, any>) => { | ||||
|   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); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @ -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, | ||||
|       }, | ||||
|     }); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user