diff --git a/packages/arcgis-rest-request/src/index.ts b/packages/arcgis-rest-request/src/index.ts index 1c83a1adac..c499a2ad3d 100644 --- a/packages/arcgis-rest-request/src/index.ts +++ b/packages/arcgis-rest-request/src/index.ts @@ -4,10 +4,11 @@ export * from "./request"; export * from "./utils/encode-form-data"; export * from "./utils/encode-query-string"; -export * from "./utils/check-for-errors"; +export * from "./utils/warn"; export * from "./utils/ArcGISRequestError"; -export * from "./utils/ArcGISAuthError"; +export * from "./utils/retryAuthError"; export * from "./utils/ErrorTypes"; +export * from "./utils/params"; export * from "./utils/process-params"; export * from "./utils/get-portal"; export * from "./utils/get-portal-url"; diff --git a/packages/arcgis-rest-request/src/request.ts b/packages/arcgis-rest-request/src/request.ts index e59dd2570a..565968584a 100644 --- a/packages/arcgis-rest-request/src/request.ts +++ b/packages/arcgis-rest-request/src/request.ts @@ -1,45 +1,12 @@ /* Copyright (c) 2017-2018 Environmental Systems Research Institute, Inc. * Apache-2.0 */ -import { checkForErrors } from "./utils/check-for-errors"; import { encodeFormData } from "./utils/encode-form-data"; import { encodeQueryString } from "./utils/encode-query-string"; import { requiresFormData } from "./utils/process-params"; import { ArcGISRequestError } from "./utils/ArcGISRequestError"; - -export type GrantTypes = - | "authorization_code" - | "refresh_token" - | "client_credentials" - | "exchange_refresh_token"; - -export interface IParams { - f?: ResponseFormats; - [key: string]: any; -} - -export interface IGenerateTokenParams extends IParams { - username?: string; - password?: string; - expiration?: number; - token?: string; - serverUrl?: string; -} - -export interface IFetchTokenParams extends IParams { - client_id: string; - client_secret?: string; - grant_type: GrantTypes; - redirect_uri?: string; - refresh_token?: string; - code?: string; -} - -export interface ITokenRequestOptions { - params?: IGenerateTokenParams | IFetchTokenParams; - httpMethod?: HTTPMethods; - fetch?: (input: RequestInfo, init?: RequestInit) => Promise; -} +import { IRetryAuthError } from "./utils/retryAuthError"; +import { HTTPMethods, IParams, ITokenRequestOptions } from "./utils/params"; /** * Authentication can be supplied to `request` via [`UserSession`](../../auth/UserSession/) or [`ApplicationSession`](../../auth/ApplicationSession/). Both classes extend `IAuthenticationManager`. @@ -62,22 +29,6 @@ export interface IAuthenticationManager { getToken(url: string, requestOptions?: ITokenRequestOptions): Promise; } -/** - * HTTP methods used by the ArcGIS REST API. - */ -export type HTTPMethods = "GET" | "POST"; - -/** - * Valid response formats for the `f` parameter. - */ -export type ResponseFormats = - | "json" - | "geojson" - | "text" - | "html" - | "image" - | "zip"; - /** * Options for the `request()` method. */ @@ -291,3 +242,111 @@ export function request( } }); } + +export class ArcGISAuthError extends ArcGISRequestError { + /** + * Create a new `ArcGISAuthError` object. + * + * @param message - The error message from the API + * @param code - The error code from the API + * @param response - The original response from the API that caused the error + * @param url - The original url of the request + * @param options - The original options of the request + */ + constructor( + message = "AUTHENTICATION_ERROR", + code: string | number = "AUTHENTICATION_ERROR_CODE", + response?: any, + url?: string, + options?: IRequestOptions + ) { + super(message, code, response, url, options); + this.name = "ArcGISAuthError"; + this.message = + code === "AUTHENTICATION_ERROR_CODE" ? message : `${code}: ${message}`; + } + + retry(getSession: IRetryAuthError, retryLimit = 3) { + let tries = 0; + + const retryRequest = (resolve: any, reject: any) => { + getSession(this.url, this.options) + .then(session => { + const newOptions = { + ...this.options, + ...{ authentication: session } + }; + + tries = tries + 1; + return request(this.url, newOptions); + }) + .then(response => { + resolve(response); + }) + .catch(e => { + if (e.name === "ArcGISAuthError" && tries < retryLimit) { + retryRequest(resolve, reject); + } else if (e.name === "ArcGISAuthError" && tries >= retryLimit) { + reject(this); + } else { + reject(e); + } + }); + }; + + return new Promise((resolve, reject) => { + retryRequest(resolve, reject); + }); + } +} + +/** + * Checks for errors in a JSON response from the ArcGIS REST API. If there are no errors, it will return the `data` passed in. If there is an error, it will throw an `ArcGISRequestError` or `ArcGISAuthError`. + * + * @param data The response JSON to check for errors. + * @param url The url of the original request + * @param params The parameters of the original request + * @param options The options of the original request + * @returns The data that was passed in the `data` parameter + */ +export function checkForErrors( + response: any, + url?: string, + params?: IParams, + options?: IRequestOptions +): any { + // this is an error message from billing.arcgis.com backend + if (response.code >= 400) { + const { message, code } = response; + throw new ArcGISRequestError(message, code, response, url, options); + } + + // error from ArcGIS Online or an ArcGIS Portal or server instance. + if (response.error) { + const { message, code, messageCode } = response.error; + const errorCode = messageCode || code || "UNKNOWN_ERROR_CODE"; + + if (code === 498 || code === 499 || messageCode === "GWM_0003") { + throw new ArcGISAuthError(message, errorCode, response, url, options); + } + + throw new ArcGISRequestError(message, errorCode, response, url, options); + } + + // error from a status check + if (response.status === "failed" || response.status === "failure") { + let message: string; + let code: string = "UNKNOWN_ERROR_CODE"; + + try { + message = JSON.parse(response.statusMessage).message; + code = JSON.parse(response.statusMessage).code; + } catch (e) { + message = response.statusMessage || response.message; + } + + throw new ArcGISRequestError(message, code, response, url, options); + } + + return response; +} diff --git a/packages/arcgis-rest-request/src/utils/ArcGISAuthError.ts b/packages/arcgis-rest-request/src/utils/ArcGISAuthError.ts deleted file mode 100644 index 129f08be6a..0000000000 --- a/packages/arcgis-rest-request/src/utils/ArcGISAuthError.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (c) 2017 Environmental Systems Research Institute, Inc. - * Apache-2.0 */ - -import { request, IRequestOptions, IAuthenticationManager } from "../request"; -import { ArcGISRequestError } from "./ArcGISRequestError"; - -export type IRetryAuthError = ( - url: string, - options: IRequestOptions -) => Promise; - -export class ArcGISAuthError extends ArcGISRequestError { - /** - * Create a new `ArcGISAuthError` object. - * - * @param message - The error message from the API - * @param code - The error code from the API - * @param response - The original response from the API that caused the error - * @param url - The original url of the request - * @param options - The original options of the request - */ - constructor( - message = "AUTHENTICATION_ERROR", - code: string | number = "AUTHENTICATION_ERROR_CODE", - response?: any, - url?: string, - options?: IRequestOptions - ) { - super(message, code, response, url, options); - this.name = "ArcGISAuthError"; - this.message = - code === "AUTHENTICATION_ERROR_CODE" ? message : `${code}: ${message}`; - } - - retry(getSession: IRetryAuthError, retryLimit = 3) { - let tries = 0; - - const retryRequest = (resolve: any, reject: any) => { - getSession(this.url, this.options) - .then(session => { - const newOptions = { - ...this.options, - ...{ authentication: session } - }; - - tries = tries + 1; - return request(this.url, newOptions); - }) - .then(response => { - resolve(response); - }) - .catch(e => { - if (e.name === "ArcGISAuthError" && tries < retryLimit) { - retryRequest(resolve, reject); - } else if (e.name === "ArcGISAuthError" && tries >= retryLimit) { - reject(this); - } else { - reject(e); - } - }); - }; - - return new Promise((resolve, reject) => { - retryRequest(resolve, reject); - }); - } -} diff --git a/packages/arcgis-rest-request/src/utils/append-custom-params.ts b/packages/arcgis-rest-request/src/utils/append-custom-params.ts index f2fc25ee5b..12a3eda97f 100644 --- a/packages/arcgis-rest-request/src/utils/append-custom-params.ts +++ b/packages/arcgis-rest-request/src/utils/append-custom-params.ts @@ -21,7 +21,7 @@ export function appendCustomParams( key !== "portal" && key !== "maxUrlLength" && key !== "endpoint" && - key !== "fields" + key !== "formatCodedValues" ) { newOptions.params[key] = (oldOptions as { [key: string]: any })[key]; } diff --git a/packages/arcgis-rest-request/src/utils/check-for-errors.ts b/packages/arcgis-rest-request/src/utils/check-for-errors.ts deleted file mode 100644 index 6b5992f633..0000000000 --- a/packages/arcgis-rest-request/src/utils/check-for-errors.ts +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright (c) 2017 Environmental Systems Research Institute, Inc. - * Apache-2.0 */ - -import { ArcGISRequestError } from "./ArcGISRequestError"; -import { ArcGISAuthError } from "./ArcGISAuthError"; -import { IRequestOptions, IParams } from "../request"; -/** - * Checks for errors in a JSON response from the ArcGIS REST API. If there are no errors, it will return the `data` passed in. If there is an error, it will throw an `ArcGISRequestError` or `ArcGISAuthError`. - * - * @param data The response JSON to check for errors. - * @param url The url of the original request - * @param params The parameters of the original request - * @param options The options of the original request - * @returns The data that was passed in the `data` parameter - */ -export function checkForErrors( - response: any, - url?: string, - params?: IParams, - options?: IRequestOptions -): any { - // this is an error message from billing.arcgis.com backend - if (response.code >= 400) { - const { message, code } = response; - throw new ArcGISRequestError(message, code, response, url, options); - } - - // error from ArcGIS Online or an ArcGIS Portal or server instance. - if (response.error) { - const { message, code, messageCode } = response.error; - const errorCode = messageCode || code || "UNKNOWN_ERROR_CODE"; - - if (code === 498 || code === 499 || messageCode === "GWM_0003") { - throw new ArcGISAuthError(message, errorCode, response, url, options); - } - - throw new ArcGISRequestError(message, errorCode, response, url, options); - } - - // error from a status check - if (response.status === "failed" || response.status === "failure") { - let message: string; - let code: string = "UNKNOWN_ERROR_CODE"; - - try { - message = JSON.parse(response.statusMessage).message; - code = JSON.parse(response.statusMessage).code; - } catch (e) { - message = response.statusMessage || response.message; - } - - throw new ArcGISRequestError(message, code, response, url, options); - } - - return response; -} - -/** - * Method used internally to surface messages to developers. - */ -export function warn(message: string) { - if (console && console.warn) { - console.warn.apply(console, [message]); - } -} diff --git a/packages/arcgis-rest-request/src/utils/params.ts b/packages/arcgis-rest-request/src/utils/params.ts new file mode 100644 index 0000000000..388b31ded6 --- /dev/null +++ b/packages/arcgis-rest-request/src/utils/params.ts @@ -0,0 +1,52 @@ +/* Copyright (c) 2017 Environmental Systems Research Institute, Inc. +* Apache-2.0 */ + +/** + * HTTP methods used by the ArcGIS REST API. + */ +export type HTTPMethods = "GET" | "POST"; + +/** + * Valid response formats for the `f` parameter. + */ +export type ResponseFormats = + | "json" + | "geojson" + | "text" + | "html" + | "image" + | "zip"; + +export type GrantTypes = + | "authorization_code" + | "refresh_token" + | "client_credentials" + | "exchange_refresh_token"; + +export interface IParams { + f?: ResponseFormats; + [key: string]: any; +} + +export interface IGenerateTokenParams extends IParams { + username?: string; + password?: string; + expiration?: number; + token?: string; + serverUrl?: string; +} + +export interface IFetchTokenParams extends IParams { + client_id: string; + client_secret?: string; + grant_type: GrantTypes; + redirect_uri?: string; + refresh_token?: string; + code?: string; +} + +export interface ITokenRequestOptions { + params?: IGenerateTokenParams | IFetchTokenParams; + httpMethod?: HTTPMethods; + fetch?: (input: RequestInfo, init?: RequestInit) => Promise; +} diff --git a/packages/arcgis-rest-request/src/utils/retryAuthError.ts b/packages/arcgis-rest-request/src/utils/retryAuthError.ts new file mode 100644 index 0000000000..27a78a4b8f --- /dev/null +++ b/packages/arcgis-rest-request/src/utils/retryAuthError.ts @@ -0,0 +1,9 @@ +/* Copyright (c) 2017 Environmental Systems Research Institute, Inc. + * Apache-2.0 */ + +import { IRequestOptions, IAuthenticationManager } from "../request"; + +export type IRetryAuthError = ( + url: string, + options: IRequestOptions +) => Promise; diff --git a/packages/arcgis-rest-request/src/utils/warn.ts b/packages/arcgis-rest-request/src/utils/warn.ts new file mode 100644 index 0000000000..ab754bb731 --- /dev/null +++ b/packages/arcgis-rest-request/src/utils/warn.ts @@ -0,0 +1,11 @@ +/* Copyright (c) 2017-2018 Environmental Systems Research Institute, Inc. + * Apache-2.0 */ + +/** + * Method used internally to surface messages to developers. + */ +export function warn(message: string) { + if (console && console.warn) { + console.warn.apply(console, [message]); + } +}