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