Admin-On-REST自定义REST客户端无法编译

时间:2018-01-17 23:02:54

标签: javascript reactjs rest admin-on-rest foxx

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调用引发)数据

当我从以下位置更改客户端的import语句时,

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程序员,我很想知道如何解决这个问题,以便能够绑定到我的后端进行进一步测试。

- )

感谢您的任何提示!

1 个答案:

答案 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外部导入的内容都必须已经编译好。