-
Notifications
You must be signed in to change notification settings - Fork 238
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #346 from Esri/chore/arcgis-rest-js
Chore/arcgis rest js
- Loading branch information
Showing
19 changed files
with
685 additions
and
92 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
{ | ||
"name": "@esri/arcgis-rest-request", | ||
"version": "1.0.0-alpha.2", | ||
"description": "Common methods and utilities for @esri/arcgis-rest-* packages.", | ||
"main": "dist/node/index.js", | ||
"module": "dist/esm/index.js", | ||
"js:next": "dist/esm/index.js", | ||
"types": "dist/esm/index.d.ts", | ||
"license": "Apache-2.0", | ||
"dependencies": { | ||
"tslib": "^1.7.1" | ||
}, | ||
"scripts": { | ||
"prepublish": "npm run build", | ||
"build": "npm run build:node && npm run build:esm", | ||
"build:esm": "tsc --module es2015 --outDir ./dist/esm --declaration", | ||
"build:node": "tsc --module commonjs --outDir ./dist/node", | ||
"test": "npm run build" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/Esri/arcgis-rest-js.git" | ||
}, | ||
"contributors": [ | ||
{ | ||
"name": "Patrick Arlt", | ||
"email": "[email protected]", | ||
"url": "http://patrickarlt.com/" | ||
} | ||
], | ||
"bugs": { | ||
"url": "https://github.com/Esri/arcgis-rest-js/issues" | ||
}, | ||
"homepage": "https://github.com/Esri/arcgis-rest-js#readme", | ||
"devDependencies": { | ||
"typescript": "^2.6.2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export * from "./request"; | ||
export * from "./utils/encode-form-data"; | ||
export * from "./utils/encode-query-string"; | ||
export * from "./utils/check-for-errors"; | ||
export * from "./utils/ArcGISRequestError"; | ||
export * from "./utils/ArcGISAuthError"; | ||
export * from "./utils/ErrorTypes"; | ||
export * from "./utils/process-params"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
/* Copyright (c) 2017 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"; | ||
|
||
export interface IAuthenticationManager { | ||
getToken(url: string): Promise<string>; | ||
} | ||
|
||
/** | ||
* 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 interface IParams { | ||
f?: ResponseFormats; | ||
[key: string]: any; | ||
} | ||
|
||
/** | ||
* Options for the [`request()`](/api/arcgis-core/request/) method. | ||
*/ | ||
export interface IRequestOptions { | ||
/** | ||
* The HTTP method to send the request with. | ||
*/ | ||
httpMethod?: HTTPMethods; | ||
|
||
/** | ||
* The instance of `IAuthenticationManager` to use to authenticate this request. | ||
*/ | ||
authentication?: IAuthenticationManager; | ||
|
||
/** | ||
* The implementation of `fetch` to use. Defaults to a global `fetch` | ||
*/ | ||
fetch?: (input: RequestInfo, init?: RequestInit) => Promise<Response>; | ||
} | ||
|
||
/** | ||
* Generic method for making HTTP requests to ArcGIS REST API endpoints. | ||
* | ||
* ```js | ||
* import { request } from 'arcgis-core'; | ||
* | ||
* request('https://www.arcgis.com/sharing/rest') | ||
* .then((response) => { | ||
* console.log(response.currentVersion); // => 5.2 | ||
* }); | ||
* ``` | ||
* | ||
* ```js | ||
* import { request, HTTPMethods } from 'arcgis-core'; | ||
* | ||
* request('https://www.arcgis.com/sharing/rest', {}, { | ||
* httpMethod: "GET" | ||
* }).then((response) => { | ||
* console.log(response.currentVersion); // => 5.2 | ||
* }); | ||
* ``` | ||
* | ||
* ```js | ||
* import { request, HTTPMethods } from 'arcgis-core'; | ||
* | ||
* request('https://www.arcgis.com/sharing/rest/search', { | ||
* q: 'parks' | ||
* }).then((response) => { | ||
* console.log(response.total); // => 78379 | ||
* }); | ||
* ``` | ||
* | ||
* @param url - The URL of the ArcGIS REST API endpoint. | ||
* @param params - The parameters to pass to the endpoint. | ||
* @param requestOptions - Options for the request. | ||
* @returns A Promise that will resolve with the data from the request. | ||
*/ | ||
export function request( | ||
url: string, | ||
requestParams: IParams = { f: "json" }, | ||
requestOptions?: IRequestOptions | ||
): Promise<any> { | ||
const options: IRequestOptions = { | ||
...{ httpMethod: "POST", fetch: fetch.bind(Function("return this")()) }, | ||
...requestOptions | ||
}; | ||
|
||
const { httpMethod, authentication } = options; | ||
|
||
const params: IParams = { | ||
...{ f: "json" }, | ||
...requestParams | ||
}; | ||
|
||
const fetchOptions: RequestInit = { | ||
method: httpMethod | ||
}; | ||
|
||
return (authentication ? authentication.getToken(url) : Promise.resolve("")) | ||
.then(token => { | ||
if (token.length) { | ||
params.token = token; | ||
} | ||
|
||
if (httpMethod === "GET") { | ||
url = url + "?" + encodeQueryString(params); | ||
} | ||
|
||
if (httpMethod === "POST") { | ||
fetchOptions.body = encodeFormData(params); | ||
} | ||
|
||
return options.fetch(url, fetchOptions); | ||
}) | ||
.then(response => { | ||
switch (params.f) { | ||
case "json": | ||
return response.json(); | ||
case "geojson": | ||
return response.json(); | ||
case "html": | ||
return response.text(); | ||
case "text": | ||
return response.text(); | ||
/* istanbul ignore next blob responses are difficult to make cross platform we will just have to trust the isomorphic fetch will do its job */ | ||
case "image": | ||
return response.blob(); | ||
/* istanbul ignore next blob responses are difficult to make cross platform we will just have to trust the isomorphic fetch will do its job */ | ||
case "zip": | ||
return response.blob(); | ||
} | ||
}) | ||
.then(data => { | ||
if (params.f === "json" || params.f === "geojson") { | ||
return checkForErrors(data, url, params, options); | ||
} else { | ||
return data; | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/* Copyright (c) 2017 Environmental Systems Research Institute, Inc. | ||
* Apache-2.0 */ | ||
|
||
import { | ||
request, | ||
IRequestOptions, | ||
IParams, | ||
IAuthenticationManager | ||
} from "../request"; | ||
import { ArcGISRequestError } from "./ArcGISRequestError"; | ||
|
||
export type IRetryAuthError = ( | ||
url: string, | ||
params: IParams, | ||
options: IRequestOptions | ||
) => Promise<IAuthenticationManager>; | ||
|
||
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 params - The original params 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, | ||
params?: IParams, | ||
options?: IRequestOptions | ||
) { | ||
super(message, code, response, url, params, 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.params, this.options) | ||
.then(session => { | ||
const newOptions = { | ||
...this.options, | ||
...{ authentication: session } | ||
}; | ||
|
||
tries = tries + 1; | ||
return request(this.url, this.params, 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); | ||
}); | ||
} | ||
} |
81 changes: 81 additions & 0 deletions
81
packages/arcgis-rest-request/src/utils/ArcGISRequestError.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/* Copyright (c) 2017 Environmental Systems Research Institute, Inc. | ||
* Apache-2.0 */ | ||
|
||
import { IRequestOptions, IParams } from "../request"; | ||
|
||
// TypeScript 2.1 no longer allows you to extend built in types. See https://github.com/Microsoft/TypeScript/issues/12790#issuecomment-265981442 | ||
// and https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work | ||
// | ||
// This code is from MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Custom_Error_Types. | ||
export class ArcGISRequestError { | ||
/** | ||
* The name of this error. Will always be `"ArcGISRequestError"` to conform with the [`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) class. | ||
*/ | ||
name: string; | ||
|
||
/** | ||
* Formatted error message. See the [`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) class for more details. | ||
*/ | ||
message: string; | ||
|
||
/** | ||
* The errror message return from the request. | ||
*/ | ||
originalMessage: string; | ||
|
||
/** | ||
* The error code returned from the request. | ||
*/ | ||
code: string | number; | ||
|
||
/** | ||
* The original JSON response the caused the error. | ||
*/ | ||
response: any; | ||
|
||
/** | ||
* The URL of the original request that caused the error | ||
*/ | ||
url: string; | ||
|
||
/** | ||
* The parameters of the original request that caused the error | ||
*/ | ||
params: IParams; | ||
|
||
/** | ||
* The options of the original request that caused the error | ||
*/ | ||
options: IRequestOptions; | ||
|
||
/** | ||
* Create a new `ArcGISRequestError` 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 params - The original params of the request | ||
* @param options - The original options of the request | ||
*/ | ||
constructor( | ||
message = "UNKNOWN_ERROR", | ||
code: string | number = "UNKNOWN_ERROR_CODE", | ||
response?: any, | ||
url?: string, | ||
params?: IParams, | ||
options?: IRequestOptions | ||
) { | ||
this.name = "ArcGISRequestError"; | ||
this.message = | ||
code === "UNKNOWN_ERROR_CODE" ? message : `${code}: ${message}`; | ||
this.originalMessage = message; | ||
this.code = code; | ||
this.response = response; | ||
this.url = url; | ||
this.params = params; | ||
this.options = options; | ||
} | ||
} | ||
ArcGISRequestError.prototype = Object.create(Error.prototype); | ||
ArcGISRequestError.prototype.constructor = ArcGISRequestError; |
Oops, something went wrong.