具有语法错误的Flow API服务器

时间:2019-07-02 00:38:41

标签: reactjs flowtype

因此,据我所知,我是React的Flow服务器和客户端应用程序。

我对Flow并没有太多的经验,但是当我运行npm run flow时,出现以下错误:

Launching Flow server for /Users/danale/Projects/engage-application.framework
Spawned flow server (pid=82774)
Logs will go to /private/tmp/flow/zSUserszSdanalezSProjectszSengage-application.framework.log
Error: lib/utils/call-api/index.js.flow:86
 86:   url: string = '',
                   ^ Unexpected token =

Error: src/utils/call-api/index.js:86
 86:   url: string = '',
                   ^ Unexpected token =

它引用了这两个文件:

// @flow
import 'whatwg-fetch';
import { RequestInit } from 'whatwg-fetch';
import { merge } from 'lodash/fp';
import { camelCase } from 'lodash';
import urlLib from 'url';

export const DEFAULT_URL = 'http://localhost';

const normalizeCasing = object => {
  if (!object || typeof object !== 'object') {
    return object;
  }
  if (Array.isArray(object)) {
    return object.map(normalizeCasing);
  }

  return Object.keys(object).reduce((acc, key) => {
    return {
      ...acc,
      [camelCase(key)]: normalizeCasing(object[key]),
    };
  }, {});
};

export const defaultFetchHeaders: { [key: string]: any } = {
  compress: false,
  credentials: 'same-origin',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
};

const cleanBody = entity =>
  Object.keys(entity).reduce((acc, key: string) => {
    const value = entity[key];
    if (value == null || (typeof value === 'string' && !value.trim().length)) {
      return acc;
    }
    if (typeof value === 'object') {
      if (!Object.keys(value).length) {
        return acc;
      }
      return {
        ...acc,
        [key]: cleanBody(value),
      };
    }
    return {
      ...acc,
      [key]: value,
    };
  }, {});

export const isServerError = (status: number) => {
  if (status >= 500 && status < 600) {
    return true;
  }
  return false;
};

type CallApiInit = RequestInit & {
  params?: { [key: string]: string | number },
};

type CallApiOptions = {
  normalize: boolean,
};

const isAbsolutePath = (url: string) => {
  return /https?:\/\//.test(url);
};

export const resolveUrl = (baseUrl: string, url?: string = '') => {
  if (!url) {
    return baseUrl;
  }
  if (baseUrl && isAbsolutePath(baseUrl) && !isAbsolutePath(url)) {
    return urlLib.resolve(baseUrl, url);
  }
  return url;
};

export const callApi = (
  url: string = '',
  options?: CallApiInit = {},
  { normalize = true }?: CallApiOptions = { normalize: true }
) => {
  const apiUrl = resolveUrl(DEFAULT_URL, url);
  const { params, ...restOptions } = options;
  const urlObj = urlLib.parse(apiUrl);
  urlObj.query = urlObj.query || params || '';
  const urlString = urlLib.format(urlObj);
  const fetchOptions = merge(defaultFetchHeaders)(restOptions);
  return fetch(urlString, cleanBody(fetchOptions)).then(resp => {
    if (resp.status !== 204) {
      return resp.text().then(text => {
        try {
          return { resp, json: JSON.parse(text) };
        } catch (e) {
          return { resp, json: { message: text } };
        }
      }).then(obj => {
        const results = {
          ...obj,
          json: normalize ? normalizeCasing(obj.json) : obj.json,
        };
        return isServerError(results.resp.status) ? Promise.reject(results) : results;
      });
    }
    return { json: null, resp };
  });
};

export const callApiFactory = (
  baseUrl: string = '',
  baseOptions?: CallApiInit = {}
) => (url: string = '', options?: CallApiInit = {}, ...rest) => {
  return callApi(
    resolveUrl(baseUrl, url),
    merge(baseOptions)(options),
    ...rest
  );
};

export default callApiFactory;

// @flow
import 'whatwg-fetch';
import { RequestInit } from 'whatwg-fetch';
import { merge } from 'lodash/fp';
import { camelCase } from 'lodash';
import urlLib from 'url';

export const DEFAULT_URL = 'http://localhost';

const normalizeCasing = object => {
  if (!object || typeof object !== 'object') {
    return object;
  }
  if (Array.isArray(object)) {
    return object.map(normalizeCasing);
  }

  return Object.keys(object).reduce((acc, key) => {
    return {
      ...acc,
      [camelCase(key)]: normalizeCasing(object[key]),
    };
  }, {});
};

export const defaultFetchHeaders: { [key: string]: any } = {
  compress: false,
  credentials: 'same-origin',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
};

const cleanBody = entity =>
  Object.keys(entity).reduce((acc, key: string) => {
    const value = entity[key];
    if (value == null || (typeof value === 'string' && !value.trim().length)) {
      return acc;
    }
    if (typeof value === 'object') {
      if (!Object.keys(value).length) {
        return acc;
      }
      return {
        ...acc,
        [key]: cleanBody(value),
      };
    }
    return {
      ...acc,
      [key]: value,
    };
  }, {});

export const isServerError = (status: number) => {
  if (status >= 500 && status < 600) {
    return true;
  }
  return false;
};

type CallApiInit = RequestInit & {
  params?: { [key: string]: string | number },
};

type CallApiOptions = {
  normalize: boolean,
};

const isAbsolutePath = (url: string) => {
  return /https?:\/\//.test(url);
};

export const resolveUrl = (baseUrl: string, url?: string = '') => {
  if (!url) {
    return baseUrl;
  }
  if (baseUrl && isAbsolutePath(baseUrl) && !isAbsolutePath(url)) {
    return urlLib.resolve(baseUrl, url);
  }
  return url;
};

export const callApi = (
  url: string = '',
  options?: CallApiInit = {},
  { normalize = true }?: CallApiOptions = { normalize: true }
) => {
  const apiUrl = resolveUrl(DEFAULT_URL, url);
  const { params, ...restOptions } = options;
  const urlObj = urlLib.parse(apiUrl);
  urlObj.query = urlObj.query || params || '';
  const urlString = urlLib.format(urlObj);
  const fetchOptions = merge(defaultFetchHeaders)(restOptions);
  return fetch(urlString, cleanBody(fetchOptions)).then(resp => {
    if (resp.status !== 204) {
      return resp.text().then(text => {
        try {
          return { resp, json: JSON.parse(text) };
        } catch (e) {
          return { resp, json: { message: text } };
        }
      }).then(obj => {
        const results = {
          ...obj,
          json: normalize ? normalizeCasing(obj.json) : obj.json,
        };
        return isServerError(results.resp.status) ? Promise.reject(results) : results;
      });
    }
    return { json: null, resp };
  });
};

export const callApiFactory = (
  baseUrl: string = '',
  baseOptions?: CallApiInit = {}
) => (url: string = '', options?: CallApiInit = {}, ...rest) => {
  return callApi(
    resolveUrl(baseUrl, url),
    merge(baseOptions)(options),
    ...rest
  );
};

export default callApiFactory;

这是否意味着Flow不支持以下内容:url: string = '',?我是Flow的新手,通常不会在大多数项目中使用它。我对TypeScript中的类型注释有一定的了解,但是我不认为这与这里发生的事情有关。

这是package.json文件:

{
  "name": "@nfib/engage-framework",
  "version": "1.2.13",
  "files": [
    "lib"
  ],
  "main": "lib/index.js",
  "scripts": {
    "check": "npm run lint && npm run test",
    "test": "jest",
    "lint": "eslint src/",
    "prebuild": "rimraf lib",
    "flow": "flow",
    "build": "npm run build:lib && npm run build:flow",
    "build:lib": "babel src/ -d lib/ --ignore '**/*.spec.js,__mocks__,__snapshots__'",
    "build:flow": "flow-copy-source src/ lib/ -v --ignore '**/*.spec.js,__mocks__,__snapshots__'"
  },
  "keywords": [],
  "author": "NFIB ITPE",
  "license": "UNLICENSED",
  "description": "Common application framework for the engage project",
  "devDependencies": {
    "babel-cli": "^6.24.1",
    "babel-eslint": "^7.2.3",
    "babel-jest": "^20.0.3",
    "babel-plugin-lodash": "^3.2.11",
    "babel-preset-env": "^1.3.3",
    "babel-preset-flow": "^6.23.0",
    "babel-preset-stage-2": "^6.24.1",
    "eslint": "^4.4.1",
    "eslint-plugin-flow": "^2.29.1",
    "eslint-plugin-react": "^7.2.0",
    "flow-bin": "^0.52.0",
    "flow-copy-source": "^1.2.0",
    "jest-cli": "^20.0.4",
    "jest-fetch-mock": "^1.2.1",
    "rimraf": "^2.6.1"
  },
  "dependencies": {
    "body-parser": "^1.17.2",
    "camelcase-keys": "^4.1.0",
    "lodash.merge": "^4.6.0",
    "url": "^0.11.0",
    "http-proxy-middleware": "^0.17.4",
    "express": "^4.15.4",
    "express-redirect": "^1.2.2",
    "express-session": "^1.15.5",
    "cheerio": "^0.22.0",
    "cors": "^2.8.4",
    "helmet": "^3.8.1",
    "morgan": "^1.8.2",
    "lodash": "^4.17.4",
    "whatwg-fetch": "^2.0.3"
  }
}

1 个答案:

答案 0 :(得分:0)

  

这是否意味着Flow不支持此功能:url: string = ''

Flow支持这一点,没关系。

问题出在这一行:

{ normalize = true }?: CallApiOptions = { normalize: true }

流程(我也认为是人类)几乎无法识别这里的内容,而导致此解析错误的原因是

如果您在这一行中减少逻辑,即为:

extraOpts?: CallApiOptions = { normalize: true }

check让流变得开心。