从Admin-On-REST Tutorial开始后,我尝试使用自定义REST-Client implementation将应用程序绑定到现有的ArangoDB后端。 后端公开了一个简单的自动生成的“默认”FOXX HTTP API。
这基本上与simple client
一起使用。为了更好地集成,我的目标是使用基于json client
的自定义客户端。因此,我将admin-on-rest/src/rest/jsonServer.js
文件复制到我的项目中。我将其修改为该文件内容:
import { stringify } from 'query-string';
import { fetchJson, flattenObject } from 'admin-on-rest';
import {
GET_LIST,
GET_ONE,
GET_MANY,
GET_MANY_REFERENCE,
CREATE,
UPDATE,
DELETE,
} from 'admin-on-rest';
/**
* Maps admin-on-rest queries to a json-server powered REST API
*
* @see https://github.com/typicode/json-server
* @example
* GET_LIST => GET http://my.api.url/posts?_sort=title&_order=ASC&_start=0&_end=24
* GET_ONE => GET http://my.api.url/posts/123
* GET_MANY => GET http://my.api.url/posts/123, GET http://my.api.url/posts/456, GET http://my.api.url/posts/789
* UPDATE => PUT http://my.api.url/posts/123
* CREATE => POST http://my.api.url/posts/123
* DELETE => DELETE http://my.api.url/posts/123
*/
export default (apiUrl, httpClient = fetchJson) => {
/**
* @param {String} type One of the constants appearing at the top if this file, e.g. 'UPDATE'
* @param {String} resource Name of the resource to fetch, e.g. 'posts'
* @param {Object} params The REST request params, depending on the type
* @returns {Object} { url, options } The HTTP request parameters
*/
const convertRESTRequestToHTTP = (type, resource, params) => {
let url = '';
const options = {};
switch (type) {
case GET_LIST: {
const { page, perPage } = params.pagination;
const { field, order } = params.sort;
const query = {
...flattenObject(params.filter),
_sort: field,
_order: order,
_start: (page - 1) * perPage,
_end: page * perPage,
};
url = `${apiUrl}/${resource}?${stringify(query)}`;
break;
}
case GET_ONE:
url = `${apiUrl}/${resource}/${params.id}`;
break;
case GET_MANY_REFERENCE: {
const { page, perPage } = params.pagination;
const { field, order } = params.sort;
const query = {
...flattenObject(params.filter),
[params.target]: params.id,
_sort: field,
_order: order,
_start: (page - 1) * perPage,
_end: page * perPage,
};
url = `${apiUrl}/${resource}?${stringify(query)}`;
break;
}
case UPDATE:
url = `${apiUrl}/${resource}/${params.id}`;
options.method = 'PUT';
options.body = JSON.stringify(params.data);
break;
case CREATE:
url = `${apiUrl}/${resource}`;
options.method = 'POST';
options.body = JSON.stringify(params.data);
break;
case DELETE:
url = `${apiUrl}/${resource}/${params.id}`;
options.method = 'DELETE';
break;
default:
throw new Error(`Unsupported fetch action type ${type}`);
}
return { url, options };
};
/**
* @param {Object} response HTTP response from fetch()
* @param {String} type One of the constants appearing at the top if this file, e.g. 'UPDATE'
* @param {String} resource Name of the resource to fetch, e.g. 'posts'
* @param {Object} params The REST request params, depending on the type
* @returns {Object} REST response
*/
const convertHTTPResponseToREST = (response, type, resource, params) => {
const { headers, json } = response;
switch (type) {
case GET_LIST:
return {
data: json.map((obj) => {
obj.id = obj._key;
delete obj['_key'];
return obj;
}),
total: headers.get('X-Total-Count')
};
case GET_MANY_REFERENCE:
if (!headers.has('x-total-count')) {
throw new Error(
'The X-Total-Count header is missing in the HTTP Response. The jsonServer REST client expects responses for lists of resources to contain this header with the total number of results to build the pagination. If you are using CORS, did you declare X-Total-Count in the Access-Control-Expose-Headers header?'
);
}
return {
data: json,
total: parseInt(
headers
.get('x-total-count')
.split('/')
.pop(),
10
),
};
case CREATE:
return { data: { ...params.data, id: json.id } };
default:
return { data: json };
}
};
/**
* @param {string} type Request type, e.g GET_LIST
* @param {string} resource Resource name, e.g. "posts"
* @param {Object} payload Request parameters. Depends on the request type
* @returns {Promise} the Promise for a REST response
*/
return (type, resource, params) => {
// json-server doesn't handle WHERE IN requests, so we fallback to calling GET_ONE n times instead
if (type === GET_MANY) {
return Promise.all(
params.ids.map(id => httpClient(`${apiUrl}/${resource}/${id}`))
).then(responses => ({
data: responses.map(response => response.json),
}));
}
const { url, options } = convertRESTRequestToHTTP(
type,
resource,
params
);
return httpClient(url, options).then(response =>
convertHTTPResponseToREST(response, type, resource, params)
);
};
};
这很像原版 - 我只编辑过:
import
部分convertHTTPResponseToREST
部分的GET_LIST
方法。最后,我通过App.js
文件将其绑定到应用程序中,使其看起来像:
import CustomRestClientJson from './CustomRestClientJson'
const App = () => (
<Admin restClient={CustomRestClientJson('http://localhost:8529/_db/orgraph/admin')}>
<Resource name="assets" list={AssetList} />
</Admin>
);
问题在于:
a。)在尝试加载时,应用程序在浏览器中失败并出现Object(...) is not a function
错误(在客户端...flattenObject(params.filter)
方法中调用convertRESTRequestToHTTP
调用引发)数据
b。)或yarn
构建/编译失败:
import { stringify } from 'query-string';
import { fetchJson, flattenObject } from 'admin-on-rest';
import {
GET_LIST,
GET_ONE,
GET_MANY,
GET_MANY_REFERENCE,
CREATE,
UPDATE,
DELETE,
} from 'admin-on-rest';
为:
import { stringify } from 'query-string';
import { fetchJson, flattenObject } from 'admin-on-rest/src/util/fetch';
import {
GET_LIST,
GET_ONE,
GET_MANY,
GET_MANY_REFERENCE,
CREATE,
UPDATE,
DELETE
} from 'admin-on-rest/src/rest/types';
出现以下错误:
Failed to compile.
./node_modules/admin-on-rest/src/util/fetch.js
Module parse failed: Unexpected token (20:24)
You may need an appropriate loader to handle this file type.
| }
|
| return fetch(url, { ...options, headers: requestHeaders })
| .then(response =>
| response.text().then(text => ({
所以,由于我不是React程序员,我很想知道如何解决这个问题,以便能够绑定到我的后端进行进一步测试。
- )
感谢您的任何提示!
答案 0 :(得分:2)
我没有阅读整个说明,但您应该通过更改
来解决您的错误 import { fetchJson, flattenObject } from 'admin-on-rest/src/util/fetch';
为:
import { fetchJson, flattenObject } from 'admin-on-rest/lib/util/fetch';
您的项目babel
不会在node_modules
下转换任何代码。无论您从src
外部导入的内容都必须已经编译好。