culparepellendus 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (470) hide show
  1. package/.env.example +2 -0
  2. package/.eslintrc.js +20 -0
  3. package/.github/workflows/deploy-docs.yml +27 -0
  4. package/.github/workflows/pre-release-tests.yml +45 -0
  5. package/.github/workflows/pull-request-tests.yml +45 -0
  6. package/.prettierignore +2 -0
  7. package/.prettierrc +19 -0
  8. package/.vscode/launch.json +24 -0
  9. package/.vscode/settings.json +3 -0
  10. package/codecov.yml +7 -0
  11. package/demos/.eslintrc.js +13 -0
  12. package/demos/ago-node-cli/README.md +29 -0
  13. package/demos/ago-node-cli/ago.js +33 -0
  14. package/demos/ago-node-cli/index.js +11 -0
  15. package/demos/ago-node-cli/lib/item-export-command.js +48 -0
  16. package/demos/ago-node-cli/lib/item-search-command.js +35 -0
  17. package/demos/ago-node-cli/package-lock.json +430 -0
  18. package/demos/ago-node-cli/package.json +30 -0
  19. package/demos/attachments/README.md +5 -0
  20. package/demos/attachments/index.html +165 -0
  21. package/demos/attachments/package-lock.json +543 -0
  22. package/demos/attachments/package.json +18 -0
  23. package/demos/batch-geocoder-node/NYC_Restaurant_Inspection_Results.csv +100 -0
  24. package/demos/batch-geocoder-node/README.md +15 -0
  25. package/demos/batch-geocoder-node/batch-geocode.js +115 -0
  26. package/demos/batch-geocoder-node/config-template.js +18 -0
  27. package/demos/batch-geocoder-node/package-lock.json +336 -0
  28. package/demos/batch-geocoder-node/package.json +37 -0
  29. package/demos/express/README.md +15 -0
  30. package/demos/express/config.json.template +3 -0
  31. package/demos/express/package-lock.json +1008 -0
  32. package/demos/express/package.json +18 -0
  33. package/demos/express/server.js +33 -0
  34. package/demos/feature-service-browser/README.md +6 -0
  35. package/demos/feature-service-browser/index.html +122 -0
  36. package/demos/feature-service-browser/package-lock.json +543 -0
  37. package/demos/feature-service-browser/package.json +18 -0
  38. package/demos/geocoder-browser/README.md +10 -0
  39. package/demos/geocoder-browser/config.js.template +1 -0
  40. package/demos/geocoder-browser/index.html +131 -0
  41. package/demos/geocoder-browser/package-lock.json +610 -0
  42. package/demos/geocoder-browser/package.json +19 -0
  43. package/demos/geocoder-browser/post-sign-in.html +25 -0
  44. package/demos/jsapi-integration/README.md +25 -0
  45. package/demos/jsapi-integration/config.js +6 -0
  46. package/demos/jsapi-integration/index.html +93 -0
  47. package/demos/jsapi-integration/package-lock.json +247 -0
  48. package/demos/jsapi-integration/package.json +19 -0
  49. package/demos/node-cli-item-management/README.md +10 -0
  50. package/demos/node-cli-item-management/index.js +238 -0
  51. package/demos/node-cli-item-management/package-lock.json +432 -0
  52. package/demos/node-cli-item-management/package.json +27 -0
  53. package/demos/node-cli-item-management/screenshot.png +0 -0
  54. package/demos/oauth2-browser/README.md +14 -0
  55. package/demos/oauth2-browser/authenticate.html +30 -0
  56. package/demos/oauth2-browser/config.js.template +6 -0
  57. package/demos/oauth2-browser/index.html +211 -0
  58. package/demos/oauth2-browser/logo.svg +4 -0
  59. package/demos/oauth2-browser/package-lock.json +474 -0
  60. package/demos/oauth2-browser/package.json +18 -0
  61. package/demos/oauth2-browser/style.css +36 -0
  62. package/demos/oauth2-browser-retry/README.md +25 -0
  63. package/demos/oauth2-browser-retry/authenticate.html +22 -0
  64. package/demos/oauth2-browser-retry/index.html +116 -0
  65. package/demos/oauth2-browser-retry/logo.svg +4 -0
  66. package/demos/stream-response-to-file/README.md +7 -0
  67. package/demos/stream-response-to-file/index.js +36 -0
  68. package/demos/stream-response-to-file/output/.gitkeep +0 -0
  69. package/demos/stream-response-to-file/package-lock.json +227 -0
  70. package/demos/stream-response-to-file/package.json +33 -0
  71. package/demos/tree-shaking-rollup/.babelrc +3 -0
  72. package/demos/tree-shaking-rollup/README.md +9 -0
  73. package/demos/tree-shaking-rollup/index.html +11 -0
  74. package/demos/tree-shaking-rollup/package-lock.json +5646 -0
  75. package/demos/tree-shaking-rollup/package.json +25 -0
  76. package/demos/tree-shaking-rollup/rollup.config.js +17 -0
  77. package/demos/tree-shaking-rollup/src/index.js +8 -0
  78. package/demos/tree-shaking-webpack/README.md +8 -0
  79. package/demos/tree-shaking-webpack/index.html +11 -0
  80. package/demos/tree-shaking-webpack/package-lock.json +11455 -0
  81. package/demos/tree-shaking-webpack/package.json +24 -0
  82. package/demos/tree-shaking-webpack/src/index.js +10 -0
  83. package/demos/tree-shaking-webpack/webpack.config.js +27 -0
  84. package/demos/vue/.env.example +11 -0
  85. package/demos/vue/.eslintrc.js +17 -0
  86. package/demos/vue/.postcssrc.js +5 -0
  87. package/demos/vue/README.md +17 -0
  88. package/demos/vue/babel.config.js +3 -0
  89. package/demos/vue/package-lock.json +28044 -0
  90. package/demos/vue/package.json +33 -0
  91. package/demos/vue/public/favicon.ico +0 -0
  92. package/demos/vue/public/index.html +24 -0
  93. package/demos/vue/src/assets/logo.svg +29 -0
  94. package/demos/vue/src/components/App.vue +305 -0
  95. package/demos/vue/src/components/Authenticate.vue +65 -0
  96. package/demos/vue/src/components/Loader.vue +230 -0
  97. package/demos/vue/src/main.js +92 -0
  98. package/demos/webmap-checker-sapper/.env.example +5 -0
  99. package/demos/webmap-checker-sapper/README.md +123 -0
  100. package/demos/webmap-checker-sapper/appveyor.yml +18 -0
  101. package/demos/webmap-checker-sapper/cypress/fixtures/example.json +5 -0
  102. package/demos/webmap-checker-sapper/cypress/integration/spec.js +19 -0
  103. package/demos/webmap-checker-sapper/cypress/plugins/index.js +17 -0
  104. package/demos/webmap-checker-sapper/cypress/support/commands.js +25 -0
  105. package/demos/webmap-checker-sapper/cypress/support/index.js +20 -0
  106. package/demos/webmap-checker-sapper/cypress.json +4 -0
  107. package/demos/webmap-checker-sapper/package-lock.json +9622 -0
  108. package/demos/webmap-checker-sapper/package.json +50 -0
  109. package/demos/webmap-checker-sapper/rollup.config.js +87 -0
  110. package/demos/webmap-checker-sapper/src/client.js +20 -0
  111. package/demos/webmap-checker-sapper/src/components/LayerStatus.html +108 -0
  112. package/demos/webmap-checker-sapper/src/components/Nav.html +21 -0
  113. package/demos/webmap-checker-sapper/src/components/WebMap.html +62 -0
  114. package/demos/webmap-checker-sapper/src/routes/_error.html +41 -0
  115. package/demos/webmap-checker-sapper/src/routes/_layout.html +21 -0
  116. package/demos/webmap-checker-sapper/src/routes/auth/authorize.js +18 -0
  117. package/demos/webmap-checker-sapper/src/routes/auth/exchange-token.js +20 -0
  118. package/demos/webmap-checker-sapper/src/routes/auth/post-sign-in.js +24 -0
  119. package/demos/webmap-checker-sapper/src/routes/auth/sign-out.js +10 -0
  120. package/demos/webmap-checker-sapper/src/routes/index.html +20 -0
  121. package/demos/webmap-checker-sapper/src/routes/webmaps/[webmapId].html +83 -0
  122. package/demos/webmap-checker-sapper/src/routes/webmaps/index.html +59 -0
  123. package/demos/webmap-checker-sapper/src/server.js +101 -0
  124. package/demos/webmap-checker-sapper/src/service-worker.js +82 -0
  125. package/demos/webmap-checker-sapper/src/template.html +33 -0
  126. package/demos/webmap-checker-sapper/src/userInfoMiddleware.js +21 -0
  127. package/demos/webmap-checker-sapper/src/utils.js +33 -0
  128. package/demos/webmap-checker-sapper/static/favicon.png +0 -0
  129. package/demos/webmap-checker-sapper/static/global.css +36 -0
  130. package/demos/webmap-checker-sapper/static/manifest.json +20 -0
  131. package/demos/webmap-checker-sapper/static/svelte-logo-192.png +0 -0
  132. package/demos/webmap-checker-sapper/static/svelte-logo-512.png +0 -0
  133. package/docs/.eslintrc.js +12 -0
  134. package/docs/FAQ.md +48 -0
  135. package/docs/HISTORY.md +62 -0
  136. package/docs/acetate.config.js +262 -0
  137. package/docs/build-typedoc.js +434 -0
  138. package/docs/generate-srihashes.js +53 -0
  139. package/docs/src/_layout.html +86 -0
  140. package/docs/src/api/_declaration.html +600 -0
  141. package/docs/src/api/_layout.html +204 -0
  142. package/docs/src/api/_package.html +38 -0
  143. package/docs/src/api/index.html +16 -0
  144. package/docs/src/guides/_layout.html +24 -0
  145. package/docs/src/guides/amd-requirejs-dojo.md +40 -0
  146. package/docs/src/guides/browser-authentication.md +39 -0
  147. package/docs/src/guides/bundlers.md +52 -0
  148. package/docs/src/guides/cli-authentication.md +9 -0
  149. package/docs/src/guides/client-server-authentication.md +9 -0
  150. package/docs/src/guides/embedded-apps.md +106 -0
  151. package/docs/src/guides/from-a-cdn.md +38 -0
  152. package/docs/src/guides/index.md +59 -0
  153. package/docs/src/guides/node.md +104 -0
  154. package/docs/src/guides/package-overview.md +111 -0
  155. package/docs/src/guides/server-authentication.md +9 -0
  156. package/docs/src/guides/whats-new-v2-0.md +305 -0
  157. package/docs/src/img/icons.png +0 -0
  158. package/docs/src/img/icons@2x.png +0 -0
  159. package/docs/src/img/oauth-browser.png +0 -0
  160. package/docs/src/index.html +12 -0
  161. package/docs/src/js/api-search.js +112 -0
  162. package/docs/src/js/nav-toggle.js +41 -0
  163. package/docs/src/sass/_highlight.scss +96 -0
  164. package/docs/src/sass/_icons.scss +157 -0
  165. package/docs/src/sass/style.scss +242 -0
  166. package/docs/src/srihashes.json +12 -0
  167. package/jasmine.json +7 -0
  168. package/jasmine.live.json +7 -0
  169. package/karma.conf.js +107 -0
  170. package/lerna.json +8 -0
  171. package/notes/README.md +68 -0
  172. package/package.json +87 -0
  173. package/packages/arcgis-rest-auth/README.md +71 -0
  174. package/packages/arcgis-rest-auth/package-lock.json +27 -0
  175. package/packages/arcgis-rest-auth/package.json +69 -0
  176. package/packages/arcgis-rest-auth/post-message-auth-spec.md +70 -0
  177. package/packages/arcgis-rest-auth/src/ApiKey.ts +41 -0
  178. package/packages/arcgis-rest-auth/src/ApplicationSession.ts +122 -0
  179. package/packages/arcgis-rest-auth/src/UserSession.ts +1376 -0
  180. package/packages/arcgis-rest-auth/src/app-tokens.ts +131 -0
  181. package/packages/arcgis-rest-auth/src/authenticated-request-options.ts +24 -0
  182. package/packages/arcgis-rest-auth/src/federation-utils.ts +85 -0
  183. package/packages/arcgis-rest-auth/src/fetch-token.ts +50 -0
  184. package/packages/arcgis-rest-auth/src/generate-token.ts +35 -0
  185. package/packages/arcgis-rest-auth/src/index.ts +13 -0
  186. package/packages/arcgis-rest-auth/src/validate-app-access.ts +68 -0
  187. package/packages/arcgis-rest-auth/test/ApiKey.test.ts +35 -0
  188. package/packages/arcgis-rest-auth/test/ApplicationSession.test.ts +124 -0
  189. package/packages/arcgis-rest-auth/test/UserSession.test.ts +2430 -0
  190. package/packages/arcgis-rest-auth/test/app-tokens.test.ts +95 -0
  191. package/packages/arcgis-rest-auth/test/federation-utils.test.ts +323 -0
  192. package/packages/arcgis-rest-auth/test/fetchToken.test.ts +112 -0
  193. package/packages/arcgis-rest-auth/test/generateToken.test.ts +102 -0
  194. package/packages/arcgis-rest-auth/test/utils.ts +14 -0
  195. package/packages/arcgis-rest-auth/test/validate-app-access.test.ts +46 -0
  196. package/packages/arcgis-rest-auth/tsconfig.json +6 -0
  197. package/packages/arcgis-rest-demographics/README.md +75 -0
  198. package/packages/arcgis-rest-demographics/package-lock.json +11 -0
  199. package/packages/arcgis-rest-demographics/package.json +69 -0
  200. package/packages/arcgis-rest-demographics/src/getAvailableCountries.ts +113 -0
  201. package/packages/arcgis-rest-demographics/src/getAvailableDataCollections.ts +166 -0
  202. package/packages/arcgis-rest-demographics/src/getAvailableGeographyLevels.ts +88 -0
  203. package/packages/arcgis-rest-demographics/src/getGeography.ts +152 -0
  204. package/packages/arcgis-rest-demographics/src/helpers.ts +28 -0
  205. package/packages/arcgis-rest-demographics/src/index.ts +8 -0
  206. package/packages/arcgis-rest-demographics/src/queryDemographicData.ts +106 -0
  207. package/packages/arcgis-rest-demographics/test/getAvailableCountries.test.ts +92 -0
  208. package/packages/arcgis-rest-demographics/test/getAvailableDataCollections.test.ts +115 -0
  209. package/packages/arcgis-rest-demographics/test/getAvailableGeographyLevels.test.ts +72 -0
  210. package/packages/arcgis-rest-demographics/test/getGeography.test.ts +141 -0
  211. package/packages/arcgis-rest-demographics/test/mocks/responses.ts +4 -0
  212. package/packages/arcgis-rest-demographics/test/queryDemographicData.test.live.ts +42 -0
  213. package/packages/arcgis-rest-demographics/test/queryDemographicData.test.ts +113 -0
  214. package/packages/arcgis-rest-demographics/tsconfig.json +6 -0
  215. package/packages/arcgis-rest-feature-layer/README.md +77 -0
  216. package/packages/arcgis-rest-feature-layer/package-lock.json +11 -0
  217. package/packages/arcgis-rest-feature-layer/package.json +64 -0
  218. package/packages/arcgis-rest-feature-layer/src/add.ts +56 -0
  219. package/packages/arcgis-rest-feature-layer/src/addAttachment.ts +53 -0
  220. package/packages/arcgis-rest-feature-layer/src/applyEdits.ts +95 -0
  221. package/packages/arcgis-rest-feature-layer/src/decodeValues.ts +122 -0
  222. package/packages/arcgis-rest-feature-layer/src/delete.ts +61 -0
  223. package/packages/arcgis-rest-feature-layer/src/deleteAttachments.ts +52 -0
  224. package/packages/arcgis-rest-feature-layer/src/getAllLayersAndTables.ts +30 -0
  225. package/packages/arcgis-rest-feature-layer/src/getAttachments.ts +55 -0
  226. package/packages/arcgis-rest-feature-layer/src/getLayer.ts +24 -0
  227. package/packages/arcgis-rest-feature-layer/src/getService.ts +26 -0
  228. package/packages/arcgis-rest-feature-layer/src/helpers.ts +97 -0
  229. package/packages/arcgis-rest-feature-layer/src/index.ts +32 -0
  230. package/packages/arcgis-rest-feature-layer/src/query.ts +204 -0
  231. package/packages/arcgis-rest-feature-layer/src/queryRelated.ts +89 -0
  232. package/packages/arcgis-rest-feature-layer/src/update.ts +60 -0
  233. package/packages/arcgis-rest-feature-layer/src/updateAttachment.ts +59 -0
  234. package/packages/arcgis-rest-feature-layer/test/attachments.test.ts +200 -0
  235. package/packages/arcgis-rest-feature-layer/test/crud.test.ts +197 -0
  236. package/packages/arcgis-rest-feature-layer/test/decodeValues.test.ts +67 -0
  237. package/packages/arcgis-rest-feature-layer/test/getAllLayersAndTables.test.ts +28 -0
  238. package/packages/arcgis-rest-feature-layer/test/getLayer.test.ts +31 -0
  239. package/packages/arcgis-rest-feature-layer/test/getService.test.ts +31 -0
  240. package/packages/arcgis-rest-feature-layer/test/helpers.test.ts +25 -0
  241. package/packages/arcgis-rest-feature-layer/test/mocks/allLayersAndTablesResponse.ts +906 -0
  242. package/packages/arcgis-rest-feature-layer/test/mocks/cvdQueryResponse.ts +225 -0
  243. package/packages/arcgis-rest-feature-layer/test/mocks/feature.ts +302 -0
  244. package/packages/arcgis-rest-feature-layer/test/mocks/fields.ts +779 -0
  245. package/packages/arcgis-rest-feature-layer/test/mocks/foo.txt +1 -0
  246. package/packages/arcgis-rest-feature-layer/test/mocks/service.ts +398 -0
  247. package/packages/arcgis-rest-feature-layer/test/query.test.ts +167 -0
  248. package/packages/arcgis-rest-feature-layer/tsconfig.json +6 -0
  249. package/packages/arcgis-rest-geocoding/README.md +86 -0
  250. package/packages/arcgis-rest-geocoding/package-lock.json +43 -0
  251. package/packages/arcgis-rest-geocoding/package.json +66 -0
  252. package/packages/arcgis-rest-geocoding/src/bulk.ts +104 -0
  253. package/packages/arcgis-rest-geocoding/src/geocode.ts +166 -0
  254. package/packages/arcgis-rest-geocoding/src/helpers.ts +56 -0
  255. package/packages/arcgis-rest-geocoding/src/index.ts +15 -0
  256. package/packages/arcgis-rest-geocoding/src/reverse.ts +84 -0
  257. package/packages/arcgis-rest-geocoding/src/suggest.ts +45 -0
  258. package/packages/arcgis-rest-geocoding/test/bulk.test.ts +194 -0
  259. package/packages/arcgis-rest-geocoding/test/geocode.test.ts +253 -0
  260. package/packages/arcgis-rest-geocoding/test/helpers.test.ts +85 -0
  261. package/packages/arcgis-rest-geocoding/test/mocks/responses.ts +591 -0
  262. package/packages/arcgis-rest-geocoding/test/reverse.test.ts +126 -0
  263. package/packages/arcgis-rest-geocoding/test/suggest.test.ts +53 -0
  264. package/packages/arcgis-rest-geocoding/tsconfig.json +6 -0
  265. package/packages/arcgis-rest-portal/README.md +73 -0
  266. package/packages/arcgis-rest-portal/package-lock.json +37 -0
  267. package/packages/arcgis-rest-portal/package.json +64 -0
  268. package/packages/arcgis-rest-portal/src/groups/add-users.ts +140 -0
  269. package/packages/arcgis-rest-portal/src/groups/create.ts +43 -0
  270. package/packages/arcgis-rest-portal/src/groups/get.ts +184 -0
  271. package/packages/arcgis-rest-portal/src/groups/helpers.ts +14 -0
  272. package/packages/arcgis-rest-portal/src/groups/invite-users.ts +127 -0
  273. package/packages/arcgis-rest-portal/src/groups/join.ts +57 -0
  274. package/packages/arcgis-rest-portal/src/groups/notification.ts +77 -0
  275. package/packages/arcgis-rest-portal/src/groups/protect.ts +56 -0
  276. package/packages/arcgis-rest-portal/src/groups/remove-users.ts +76 -0
  277. package/packages/arcgis-rest-portal/src/groups/remove.ts +32 -0
  278. package/packages/arcgis-rest-portal/src/groups/search.ts +47 -0
  279. package/packages/arcgis-rest-portal/src/groups/update-user-membership.ts +63 -0
  280. package/packages/arcgis-rest-portal/src/groups/update.ts +39 -0
  281. package/packages/arcgis-rest-portal/src/index.ts +70 -0
  282. package/packages/arcgis-rest-portal/src/items/add.ts +138 -0
  283. package/packages/arcgis-rest-portal/src/items/content.ts +67 -0
  284. package/packages/arcgis-rest-portal/src/items/create.ts +150 -0
  285. package/packages/arcgis-rest-portal/src/items/export.ts +80 -0
  286. package/packages/arcgis-rest-portal/src/items/get.ts +437 -0
  287. package/packages/arcgis-rest-portal/src/items/helpers.ts +292 -0
  288. package/packages/arcgis-rest-portal/src/items/protect.ts +41 -0
  289. package/packages/arcgis-rest-portal/src/items/reassign.ts +61 -0
  290. package/packages/arcgis-rest-portal/src/items/remove.ts +141 -0
  291. package/packages/arcgis-rest-portal/src/items/search.ts +25 -0
  292. package/packages/arcgis-rest-portal/src/items/update.ts +185 -0
  293. package/packages/arcgis-rest-portal/src/items/upload.ts +125 -0
  294. package/packages/arcgis-rest-portal/src/orgs/notification.ts +131 -0
  295. package/packages/arcgis-rest-portal/src/services/get-unique-service-name.ts +35 -0
  296. package/packages/arcgis-rest-portal/src/services/is-service-name-available.ts +30 -0
  297. package/packages/arcgis-rest-portal/src/sharing/access.ts +84 -0
  298. package/packages/arcgis-rest-portal/src/sharing/helpers.ts +81 -0
  299. package/packages/arcgis-rest-portal/src/sharing/is-item-shared-with-group.ts +42 -0
  300. package/packages/arcgis-rest-portal/src/sharing/share-item-with-group.ts +340 -0
  301. package/packages/arcgis-rest-portal/src/sharing/unshare-item-with-group.ts +105 -0
  302. package/packages/arcgis-rest-portal/src/users/get-user-tags.ts +52 -0
  303. package/packages/arcgis-rest-portal/src/users/get-user-url.ts +18 -0
  304. package/packages/arcgis-rest-portal/src/users/get-user.ts +58 -0
  305. package/packages/arcgis-rest-portal/src/users/invitation.ts +156 -0
  306. package/packages/arcgis-rest-portal/src/users/notification.ts +68 -0
  307. package/packages/arcgis-rest-portal/src/users/search-users.ts +37 -0
  308. package/packages/arcgis-rest-portal/src/users/update.ts +66 -0
  309. package/packages/arcgis-rest-portal/src/util/SearchQueryBuilder.ts +391 -0
  310. package/packages/arcgis-rest-portal/src/util/array.ts +16 -0
  311. package/packages/arcgis-rest-portal/src/util/generic-search.ts +114 -0
  312. package/packages/arcgis-rest-portal/src/util/get-portal-settings.ts +45 -0
  313. package/packages/arcgis-rest-portal/src/util/get-portal-url.ts +28 -0
  314. package/packages/arcgis-rest-portal/src/util/get-portal.ts +53 -0
  315. package/packages/arcgis-rest-portal/src/util/get-subscription-info.ts +43 -0
  316. package/packages/arcgis-rest-portal/src/util/scrub-control-chars.ts +13 -0
  317. package/packages/arcgis-rest-portal/src/util/search.ts +47 -0
  318. package/packages/arcgis-rest-portal/test/groups/add-users.test.ts +239 -0
  319. package/packages/arcgis-rest-portal/test/groups/crud.test.ts +180 -0
  320. package/packages/arcgis-rest-portal/test/groups/get.test.ts +176 -0
  321. package/packages/arcgis-rest-portal/test/groups/invite-users.test.ts +146 -0
  322. package/packages/arcgis-rest-portal/test/groups/join.test.ts +72 -0
  323. package/packages/arcgis-rest-portal/test/groups/notification.test.ts +112 -0
  324. package/packages/arcgis-rest-portal/test/groups/protect.test.ts +72 -0
  325. package/packages/arcgis-rest-portal/test/groups/remove-users.test.ts +140 -0
  326. package/packages/arcgis-rest-portal/test/groups/search.test.ts +151 -0
  327. package/packages/arcgis-rest-portal/test/groups/update-user-membership.test.ts +62 -0
  328. package/packages/arcgis-rest-portal/test/items/add.test.ts +323 -0
  329. package/packages/arcgis-rest-portal/test/items/content.test.ts +156 -0
  330. package/packages/arcgis-rest-portal/test/items/create.test.ts +400 -0
  331. package/packages/arcgis-rest-portal/test/items/export.test.ts +122 -0
  332. package/packages/arcgis-rest-portal/test/items/get.test.ts +583 -0
  333. package/packages/arcgis-rest-portal/test/items/helpers.test.ts +60 -0
  334. package/packages/arcgis-rest-portal/test/items/protect.test.ts +122 -0
  335. package/packages/arcgis-rest-portal/test/items/reassign.test.ts +131 -0
  336. package/packages/arcgis-rest-portal/test/items/remove.test.ts +261 -0
  337. package/packages/arcgis-rest-portal/test/items/search.test.ts +322 -0
  338. package/packages/arcgis-rest-portal/test/items/update.test.ts +556 -0
  339. package/packages/arcgis-rest-portal/test/items/upload.test.ts +282 -0
  340. package/packages/arcgis-rest-portal/test/mocks/groups/responses.ts +208 -0
  341. package/packages/arcgis-rest-portal/test/mocks/items/foo.zip +0 -0
  342. package/packages/arcgis-rest-portal/test/mocks/items/item.ts +526 -0
  343. package/packages/arcgis-rest-portal/test/mocks/items/resources.ts +38 -0
  344. package/packages/arcgis-rest-portal/test/mocks/items/search.ts +121 -0
  345. package/packages/arcgis-rest-portal/test/mocks/portal/response.ts +126 -0
  346. package/packages/arcgis-rest-portal/test/mocks/portal/settings-response.ts +56 -0
  347. package/packages/arcgis-rest-portal/test/mocks/sharing/sharing.ts +18 -0
  348. package/packages/arcgis-rest-portal/test/mocks/users/invitation.ts +70 -0
  349. package/packages/arcgis-rest-portal/test/mocks/users/notification.ts +34 -0
  350. package/packages/arcgis-rest-portal/test/mocks/users/user-search.ts +388 -0
  351. package/packages/arcgis-rest-portal/test/mocks/users/user-tags.ts +5 -0
  352. package/packages/arcgis-rest-portal/test/mocks/users/user.ts +174 -0
  353. package/packages/arcgis-rest-portal/test/orgs/notification.test.ts +144 -0
  354. package/packages/arcgis-rest-portal/test/services/get-unique-service-name.test.ts +59 -0
  355. package/packages/arcgis-rest-portal/test/services/is-service-name-available.test.ts +46 -0
  356. package/packages/arcgis-rest-portal/test/sharing/access.test.ts +162 -0
  357. package/packages/arcgis-rest-portal/test/sharing/helpers.test.ts +55 -0
  358. package/packages/arcgis-rest-portal/test/sharing/share-item-with-group.test.ts +1382 -0
  359. package/packages/arcgis-rest-portal/test/sharing/unshare-item-with-group.test.ts +288 -0
  360. package/packages/arcgis-rest-portal/test/users/get-user-tags.test.ts +71 -0
  361. package/packages/arcgis-rest-portal/test/users/get-user-url.test.ts +40 -0
  362. package/packages/arcgis-rest-portal/test/users/get-user.test.ts +90 -0
  363. package/packages/arcgis-rest-portal/test/users/invitation.test.ts +127 -0
  364. package/packages/arcgis-rest-portal/test/users/notification.test.ts +77 -0
  365. package/packages/arcgis-rest-portal/test/users/search.test.ts +42 -0
  366. package/packages/arcgis-rest-portal/test/users/update.test.ts +151 -0
  367. package/packages/arcgis-rest-portal/test/util/SearchQueryBuilder.test.ts +345 -0
  368. package/packages/arcgis-rest-portal/test/util/array.test.ts +30 -0
  369. package/packages/arcgis-rest-portal/test/util/get-portal-settings.test.ts +68 -0
  370. package/packages/arcgis-rest-portal/test/util/get-portal-url.test.ts +37 -0
  371. package/packages/arcgis-rest-portal/test/util/portal.test.ts +148 -0
  372. package/packages/arcgis-rest-portal/test/util/scrub-control-chars.test.ts +22 -0
  373. package/packages/arcgis-rest-portal/tsconfig.json +6 -0
  374. package/packages/arcgis-rest-request/README.md +72 -0
  375. package/packages/arcgis-rest-request/package-lock.json +13 -0
  376. package/packages/arcgis-rest-request/package.json +60 -0
  377. package/packages/arcgis-rest-request/src/index.ts +25 -0
  378. package/packages/arcgis-rest-request/src/request.ts +433 -0
  379. package/packages/arcgis-rest-request/src/utils/ArcGISRequestError.ts +76 -0
  380. package/packages/arcgis-rest-request/src/utils/ErrorTypes.ts +29 -0
  381. package/packages/arcgis-rest-request/src/utils/GrantTypes.ts +5 -0
  382. package/packages/arcgis-rest-request/src/utils/HTTPMethods.ts +6 -0
  383. package/packages/arcgis-rest-request/src/utils/IAuthenticationManager.ts +22 -0
  384. package/packages/arcgis-rest-request/src/utils/IFetchTokenParams.ts +11 -0
  385. package/packages/arcgis-rest-request/src/utils/IGenerateTokenParams.ts +9 -0
  386. package/packages/arcgis-rest-request/src/utils/IParamBuilder.ts +3 -0
  387. package/packages/arcgis-rest-request/src/utils/IParams.ts +6 -0
  388. package/packages/arcgis-rest-request/src/utils/IParamsBuilder.ts +5 -0
  389. package/packages/arcgis-rest-request/src/utils/IRequestOptions.ts +54 -0
  390. package/packages/arcgis-rest-request/src/utils/ITokenRequestOptions.ts +9 -0
  391. package/packages/arcgis-rest-request/src/utils/ResponseFormats.ts +10 -0
  392. package/packages/arcgis-rest-request/src/utils/append-custom-params.ts +49 -0
  393. package/packages/arcgis-rest-request/src/utils/clean-url.ts +20 -0
  394. package/packages/arcgis-rest-request/src/utils/decode-query-string.ts +27 -0
  395. package/packages/arcgis-rest-request/src/utils/encode-form-data.ts +38 -0
  396. package/packages/arcgis-rest-request/src/utils/encode-query-string.ts +35 -0
  397. package/packages/arcgis-rest-request/src/utils/process-params.ts +109 -0
  398. package/packages/arcgis-rest-request/src/utils/retryAuthError.ts +10 -0
  399. package/packages/arcgis-rest-request/src/utils/warn.ts +11 -0
  400. package/packages/arcgis-rest-request/src/utils/with-options.ts +48 -0
  401. package/packages/arcgis-rest-request/test/mocks/errors.ts +76 -0
  402. package/packages/arcgis-rest-request/test/mocks/geojson-feature-collection.ts +13 -0
  403. package/packages/arcgis-rest-request/test/mocks/param-builder.ts +7 -0
  404. package/packages/arcgis-rest-request/test/mocks/sharing-rest-info.ts +41 -0
  405. package/packages/arcgis-rest-request/test/mocks/webmap.ts +41 -0
  406. package/packages/arcgis-rest-request/test/request.test.ts +621 -0
  407. package/packages/arcgis-rest-request/test/utils/ArcGISAuthError.test.ts +191 -0
  408. package/packages/arcgis-rest-request/test/utils/ArcGISRequestError.test.ts +51 -0
  409. package/packages/arcgis-rest-request/test/utils/check-for-errors.test.ts +111 -0
  410. package/packages/arcgis-rest-request/test/utils/clean-url.test.ts +50 -0
  411. package/packages/arcgis-rest-request/test/utils/encode-form-data.test.ts +133 -0
  412. package/packages/arcgis-rest-request/test/utils/encode-query-string.test.ts +18 -0
  413. package/packages/arcgis-rest-request/test/utils/process-params.test.ts +205 -0
  414. package/packages/arcgis-rest-request/test/utils/with-options.test.ts +133 -0
  415. package/packages/arcgis-rest-request/tsconfig.json +4 -0
  416. package/packages/arcgis-rest-routing/README.md +75 -0
  417. package/packages/arcgis-rest-routing/package-lock.json +43 -0
  418. package/packages/arcgis-rest-routing/package.json +65 -0
  419. package/packages/arcgis-rest-routing/src/closestFacility.ts +225 -0
  420. package/packages/arcgis-rest-routing/src/helpers.ts +104 -0
  421. package/packages/arcgis-rest-routing/src/index.ts +14 -0
  422. package/packages/arcgis-rest-routing/src/originDestinationMatrix.ts +223 -0
  423. package/packages/arcgis-rest-routing/src/serviceArea.ts +173 -0
  424. package/packages/arcgis-rest-routing/src/solveRoute.ts +180 -0
  425. package/packages/arcgis-rest-routing/test/closestFacility.test.ts +683 -0
  426. package/packages/arcgis-rest-routing/test/mocks/inputs.ts +132 -0
  427. package/packages/arcgis-rest-routing/test/mocks/responses.ts +13322 -0
  428. package/packages/arcgis-rest-routing/test/originDestinationMatrix.test.ts +797 -0
  429. package/packages/arcgis-rest-routing/test/serviceArea.test.ts +601 -0
  430. package/packages/arcgis-rest-routing/test/solveRoute.test.ts +677 -0
  431. package/packages/arcgis-rest-routing/tsconfig.json +6 -0
  432. package/packages/arcgis-rest-service-admin/README.md +73 -0
  433. package/packages/arcgis-rest-service-admin/package-lock.json +11 -0
  434. package/packages/arcgis-rest-service-admin/package.json +65 -0
  435. package/packages/arcgis-rest-service-admin/src/addTo.ts +70 -0
  436. package/packages/arcgis-rest-service-admin/src/create.ts +189 -0
  437. package/packages/arcgis-rest-service-admin/src/get-service-admin-info.ts +34 -0
  438. package/packages/arcgis-rest-service-admin/src/get-view-sources.ts +20 -0
  439. package/packages/arcgis-rest-service-admin/src/index.ts +14 -0
  440. package/packages/arcgis-rest-service-admin/src/update.ts +50 -0
  441. package/packages/arcgis-rest-service-admin/test/addTo.test.ts +350 -0
  442. package/packages/arcgis-rest-service-admin/test/create.test.ts +294 -0
  443. package/packages/arcgis-rest-service-admin/test/get-service-admin-info.test.ts +37 -0
  444. package/packages/arcgis-rest-service-admin/test/get-view-sources.test.ts +40 -0
  445. package/packages/arcgis-rest-service-admin/test/mocks/layerDefinition.ts +79 -0
  446. package/packages/arcgis-rest-service-admin/test/mocks/service.ts +81 -0
  447. package/packages/arcgis-rest-service-admin/test/update.test.ts +115 -0
  448. package/packages/arcgis-rest-service-admin/tsconfig.json +5 -0
  449. package/packages/arcgis-rest-types/README.md +66 -0
  450. package/packages/arcgis-rest-types/package-lock.json +5 -0
  451. package/packages/arcgis-rest-types/package.json +54 -0
  452. package/packages/arcgis-rest-types/src/feature.ts +42 -0
  453. package/packages/arcgis-rest-types/src/geometry.ts +272 -0
  454. package/packages/arcgis-rest-types/src/group.ts +72 -0
  455. package/packages/arcgis-rest-types/src/index.ts +9 -0
  456. package/packages/arcgis-rest-types/src/item.ts +81 -0
  457. package/packages/arcgis-rest-types/src/service.ts +156 -0
  458. package/packages/arcgis-rest-types/src/statisticDefinition.ts +33 -0
  459. package/packages/arcgis-rest-types/src/symbol.ts +170 -0
  460. package/packages/arcgis-rest-types/src/user.ts +49 -0
  461. package/packages/arcgis-rest-types/src/webmap.ts +1405 -0
  462. package/packages/arcgis-rest-types/tsconfig.json +10 -0
  463. package/support/changelog.js +393 -0
  464. package/support/deploy-doc-site.js +16 -0
  465. package/support/dev.sh +6 -0
  466. package/support/publish.sh +47 -0
  467. package/support/test-helpers.js +9 -0
  468. package/tsconfig.json +63 -0
  469. package/umd-base-profile.js +81 -0
  470. package/umd-production-profile.js +13 -0
@@ -0,0 +1,1376 @@
1
+ /* Copyright (c) 2017-2019 Environmental Systems Research Institute, Inc.
2
+ * Apache-2.0 */
3
+
4
+ /**
5
+ * /generateToken returns a token that cannot be refreshed.
6
+ *
7
+ * oauth2/token can return a token *and* a refreshToken.
8
+ * up until the refreshToken expires, you can use it (and a clientId)
9
+ * to fetch fresh credentials without a username and password.
10
+ *
11
+ * the catch is that this 'authorization_code' flow is only utilized
12
+ * by server based OAuth 2 Node.js applications that call /authorize first.
13
+ */
14
+
15
+ import * as http from "http";
16
+ import {
17
+ request,
18
+ IRequestOptions,
19
+ ArcGISAuthError,
20
+ IAuthenticationManager,
21
+ ITokenRequestOptions,
22
+ cleanUrl,
23
+ encodeQueryString,
24
+ decodeQueryString,
25
+ } from "@esri/arcgis-rest-request";
26
+ import { IUser } from "@esri/arcgis-rest-types";
27
+ import { generateToken } from "./generate-token";
28
+ import { fetchToken, IFetchTokenResponse } from "./fetch-token";
29
+ import { canUseOnlineToken, isFederated } from "./federation-utils";
30
+ import { IAppAccess, validateAppAccess } from "./validate-app-access";
31
+
32
+ /**
33
+ * Internal utility for resolving a Promise from outside its constructor.
34
+ *
35
+ * See: http://lea.verou.me/2016/12/resolve-promises-externally-with-this-one-weird-trick/
36
+ */
37
+ interface IDeferred<T> {
38
+ promise: Promise<T>;
39
+ resolve: (v: T) => void;
40
+ reject: (v: any) => void;
41
+ }
42
+
43
+ export type AuthenticationProvider =
44
+ | "arcgis"
45
+ | "facebook"
46
+ | "google"
47
+ | "github"
48
+ | "apple";
49
+
50
+ /**
51
+ * Represents a [credential](https://developers.arcgis.com/javascript/latest/api-reference/esri-identity-Credential.html)
52
+ * object used to access a secure ArcGIS resource.
53
+ */
54
+ export interface ICredential {
55
+ expires: number;
56
+ server: string;
57
+ ssl: boolean;
58
+ token: string;
59
+ userId: string;
60
+ }
61
+
62
+ function defer<T>(): IDeferred<T> {
63
+ const deferred: any = {
64
+ promise: null,
65
+ resolve: null,
66
+ reject: null,
67
+ };
68
+
69
+ deferred.promise = new Promise((resolve, reject) => {
70
+ deferred.resolve = resolve;
71
+ deferred.reject = reject;
72
+ });
73
+
74
+ return deferred as IDeferred<T>;
75
+ }
76
+
77
+ /**
78
+ * Options for static OAuth 2.0 helper methods on `UserSession`.
79
+ */
80
+ export interface IOAuth2Options {
81
+ /**
82
+ * Client ID of your application. Can be obtained by registering an application
83
+ * on [ArcGIS for Developers](https://developers.arcgis.com/documentation/core-concepts/security-and-authentication/signing-in-arcgis-online-users/#registering-your-application),
84
+ * [ArcGIS Online](http://doc.arcgis.com/en/arcgis-online/share-maps/add-items.htm#ESRI_SECTION1_0D1B620254F745AE84F394289F8AF44B) or on your instance of ArcGIS Enterprise.
85
+ */
86
+ clientId: string;
87
+
88
+ /**
89
+ * A valid URL to redirect to after a user authorizes your application. Can be set on [ArcGIS for Developers](https://developers.arcgis.com/documentation/core-concepts/security-and-authentication/signing-in-arcgis-online-users/#registering-your-application),
90
+ * [ArcGIS Online](http://doc.arcgis.com/en/arcgis-online/share-maps/add-items.htm#ESRI_SECTION1_0D1B620254F745AE84F394289F8AF44B) or on your instance of ArcGIS Enterprise.
91
+ */
92
+ redirectUri: string;
93
+
94
+ /**
95
+ * The ArcGIS Online or ArcGIS Enterprise portal you want to use for authentication. Defaults to `https://www.arcgis.com/sharing/rest` for the ArcGIS Online portal.
96
+ */
97
+ portal?: string;
98
+
99
+ /**
100
+ * ArcGIS Authentication is used by default. Specifying an alternative will take users directly to the corresponding provider's OAuth page.
101
+ */
102
+
103
+ provider?: AuthenticationProvider;
104
+
105
+ /**
106
+ * The requested validity in minutes for a token. Defaults to 20160 (two weeks).
107
+ */
108
+ expiration?: number;
109
+
110
+ /**
111
+ * Duration (in minutes) that a token will be valid. Defaults to 20160 (two weeks).
112
+ *
113
+ * @deprecated use 'expiration' instead
114
+ */
115
+ duration?: number;
116
+
117
+ /**
118
+ * Determines whether to open the authorization window in a new tab/window or in the current window.
119
+ *
120
+ * @browserOnly
121
+ */
122
+ popup?: boolean;
123
+
124
+ /**
125
+ * The window features passed to [window.open()](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) when `popup` is true. Defaults to `height=400,width=600,menubar=no,location=yes,resizable=yes,scrollbars=yes,status=yes`
126
+ *
127
+ * @browserOnly
128
+ */
129
+ popupWindowFeatures?: string;
130
+
131
+ /**
132
+ * Duration (in minutes) that a refresh token will be valid.
133
+ *
134
+ * @nodeOnly
135
+ */
136
+ refreshTokenTTL?: number;
137
+
138
+ /**
139
+ * The locale assumed to render the login page.
140
+ *
141
+ * @browserOnly
142
+ */
143
+ locale?: string;
144
+
145
+ /**
146
+ * Applications can specify an opaque value for this parameter to correlate the authorization request sent with the received response. By default, clientId is used.
147
+ *
148
+ * @browserOnly
149
+ */
150
+ state?: string;
151
+
152
+ [key: string]: any;
153
+ }
154
+
155
+ /**
156
+ * Options for the `UserSession` constructor.
157
+ */
158
+ export interface IUserSessionOptions {
159
+ /**
160
+ * Client ID of your application. Can be obtained by registering an application
161
+ * on [ArcGIS for Developers](https://developers.arcgis.com/documentation/core-concepts/security-and-authentication/signing-in-arcgis-online-users/#registering-your-application),
162
+ * [ArcGIS Online](http://doc.arcgis.com/en/arcgis-online/share-maps/add-items.htm#ESRI_SECTION1_0D1B620254F745AE84F394289F8AF44B) or on your instance of ArcGIS Enterprise.
163
+ */
164
+ clientId?: string;
165
+
166
+ /**
167
+ * A valid URL to redirect to after a user authorizes your application. Can be set on [ArcGIS for Developers](https://developers.arcgis.com/documentation/core-concepts/security-and-authentication/signing-in-arcgis-online-users/#registering-your-application),
168
+ * [ArcGIS Online](http://doc.arcgis.com/en/arcgis-online/share-maps/add-items.htm#ESRI_SECTION1_0D1B620254F745AE84F394289F8AF44B) or on your instance of ArcGIS Enterprise.
169
+ */
170
+ redirectUri?: string;
171
+
172
+ /**
173
+ * OAuth 2.0 refresh token from a previous user session.
174
+ */
175
+ refreshToken?: string;
176
+
177
+ /**
178
+ * Expiration date of the `refreshToken`
179
+ */
180
+ refreshTokenExpires?: Date;
181
+
182
+ /**
183
+ * The authenticated user's username. Guaranteed to be unique across ArcGIS Online or your instance of ArcGIS Enterprise.
184
+ */
185
+ username?: string;
186
+
187
+ /**
188
+ * Password for this user. Used in CLI apps where users cannot do OAuth 2.0.
189
+ */
190
+ password?: string;
191
+
192
+ /**
193
+ * OAuth 2.0 access token from a previous user session.
194
+ */
195
+ token?: string;
196
+
197
+ /**
198
+ * Expiration date for the `token`
199
+ */
200
+ tokenExpires?: Date;
201
+
202
+ /**
203
+ * The ArcGIS Online or ArcGIS Enterprise portal you want to use for authentication. Defaults to `https://www.arcgis.com/sharing/rest` for the ArcGIS Online portal.
204
+ */
205
+ portal?: string;
206
+
207
+ /**
208
+ * This value is set to true automatically if the ArcGIS Organization requires that requests be made over https.
209
+ */
210
+ ssl?: boolean;
211
+
212
+ /**
213
+ * ArcGIS Authentication is used by default. Specifying an alternative will take users directly to the corresponding provider's OAuth page.
214
+ */
215
+ provider?: AuthenticationProvider;
216
+
217
+ /**
218
+ * Duration of requested token validity in minutes. Used when requesting tokens with `username` and `password` or when validating the identity of unknown servers. Defaults to two weeks.
219
+ */
220
+ tokenDuration?: number;
221
+
222
+ /**
223
+ * Duration (in minutes) that a refresh token will be valid.
224
+ */
225
+ refreshTokenTTL?: number;
226
+
227
+ /**
228
+ * An unfederated ArcGIS Server instance known to recognize credentials supplied manually.
229
+ * ```js
230
+ * {
231
+ * server: "https://sampleserver6.arcgisonline.com/arcgis",
232
+ * token: "SOSlV3v..",
233
+ * tokenExpires: new Date(1545415669763)
234
+ * }
235
+ * ```
236
+ */
237
+ server?: string;
238
+ }
239
+
240
+ /**
241
+ * ```js
242
+ * import { UserSession } from '@esri/arcgis-rest-auth';
243
+ * UserSession.beginOAuth2({
244
+ * // register an app of your own to create a unique clientId
245
+ * clientId: "abc123",
246
+ * redirectUri: 'https://yourapp.com/authenticate.html'
247
+ * })
248
+ * .then(session)
249
+ * // or
250
+ * new UserSession({
251
+ * username: "jsmith",
252
+ * password: "123456"
253
+ * })
254
+ * // or
255
+ * UserSession.deserialize(cache)
256
+ * ```
257
+ * Used to authenticate both ArcGIS Online and ArcGIS Enterprise users. `UserSession` includes helper methods for [OAuth 2.0](/arcgis-rest-js/guides/browser-authentication/) in both browser and server applications.
258
+ */
259
+ export class UserSession implements IAuthenticationManager {
260
+ /**
261
+ * The current ArcGIS Online or ArcGIS Enterprise `token`.
262
+ */
263
+ get token() {
264
+ return this._token;
265
+ }
266
+
267
+ /**
268
+ * The expiration time of the current `token`.
269
+ */
270
+ get tokenExpires() {
271
+ return this._tokenExpires;
272
+ }
273
+
274
+ /**
275
+ * The current token to ArcGIS Online or ArcGIS Enterprise.
276
+ */
277
+ get refreshToken() {
278
+ return this._refreshToken;
279
+ }
280
+
281
+ /**
282
+ * The expiration time of the current `refreshToken`.
283
+ */
284
+ get refreshTokenExpires() {
285
+ return this._refreshTokenExpires;
286
+ }
287
+
288
+ /**
289
+ * Deprecated, use `federatedServers` instead.
290
+ *
291
+ * @deprecated
292
+ */
293
+ get trustedServers() {
294
+ console.log("DEPRECATED: use federatedServers instead");
295
+ return this.federatedServers;
296
+ }
297
+
298
+ /**
299
+ * Begins a new browser-based OAuth 2.0 sign in. If `options.popup` is `true` the
300
+ * authentication window will open in a new tab/window and the function will return
301
+ * Promise&lt;UserSession&gt;. Otherwise, the user will be redirected to the
302
+ * authorization page in their current tab/window and the function will return `undefined`.
303
+ *
304
+ * @browserOnly
305
+ */
306
+ /* istanbul ignore next */
307
+ public static beginOAuth2(
308
+ options: IOAuth2Options,
309
+ win: any = window
310
+ ): Promise<UserSession> | undefined {
311
+ if (options.duration) {
312
+ console.log(
313
+ "DEPRECATED: 'duration' is deprecated - use 'expiration' instead"
314
+ );
315
+ }
316
+
317
+ const {
318
+ portal,
319
+ provider,
320
+ clientId,
321
+ expiration,
322
+ redirectUri,
323
+ popup,
324
+ popupWindowFeatures,
325
+ state,
326
+ locale,
327
+ params,
328
+ }: IOAuth2Options = {
329
+ ...{
330
+ portal: "https://www.arcgis.com/sharing/rest",
331
+ provider: "arcgis",
332
+ expiration: 20160,
333
+ popup: true,
334
+ popupWindowFeatures:
335
+ "height=400,width=600,menubar=no,location=yes,resizable=yes,scrollbars=yes,status=yes",
336
+ state: options.clientId,
337
+ locale: "",
338
+ },
339
+ ...options,
340
+ };
341
+ let url: string;
342
+ if (provider === "arcgis") {
343
+ url = `${portal}/oauth2/authorize?client_id=${clientId}&response_type=token&expiration=${
344
+ options.duration || expiration
345
+ }&redirect_uri=${encodeURIComponent(
346
+ redirectUri
347
+ )}&state=${state}&locale=${locale}`;
348
+ } else {
349
+ url = `${portal}/oauth2/social/authorize?client_id=${clientId}&socialLoginProviderName=${provider}&autoAccountCreateForSocial=true&response_type=token&expiration=${
350
+ options.duration || expiration
351
+ }&redirect_uri=${encodeURIComponent(
352
+ redirectUri
353
+ )}&state=${state}&locale=${locale}`;
354
+ }
355
+
356
+ // append additional params
357
+ if (params) {
358
+ url = `${url}&${encodeQueryString(params)}`;
359
+ }
360
+
361
+ if (!popup) {
362
+ win.location.href = url;
363
+ return undefined;
364
+ }
365
+
366
+ const session = defer<UserSession>();
367
+
368
+ win[`__ESRI_REST_AUTH_HANDLER_${clientId}`] = function (
369
+ errorString: any,
370
+ oauthInfoString: string
371
+ ) {
372
+ if (errorString) {
373
+ const error = JSON.parse(errorString);
374
+ session.reject(new ArcGISAuthError(error.errorMessage, error.error));
375
+ return;
376
+ }
377
+
378
+ if (oauthInfoString) {
379
+ const oauthInfo = JSON.parse(oauthInfoString);
380
+ session.resolve(
381
+ new UserSession({
382
+ clientId,
383
+ portal,
384
+ ssl: oauthInfo.ssl,
385
+ token: oauthInfo.token,
386
+ tokenExpires: new Date(oauthInfo.expires),
387
+ username: oauthInfo.username,
388
+ })
389
+ );
390
+ }
391
+ };
392
+
393
+ win.open(url, "oauth-window", popupWindowFeatures);
394
+
395
+ return session.promise;
396
+ }
397
+
398
+ /**
399
+ * Completes a browser-based OAuth 2.0 sign in. If `options.popup` is `true` the user
400
+ * will be returned to the previous window. Otherwise a new `UserSession`
401
+ * will be returned. You must pass the same values for `options.popup` and
402
+ * `options.portal` as you used in `beginOAuth2()`.
403
+ *
404
+ * @browserOnly
405
+ */
406
+ /* istanbul ignore next */
407
+ public static completeOAuth2(options: IOAuth2Options, win: any = window) {
408
+ const { portal, clientId, popup }: IOAuth2Options = {
409
+ ...{ portal: "https://www.arcgis.com/sharing/rest", popup: true },
410
+ ...options,
411
+ };
412
+
413
+ function completeSignIn(error: any, oauthInfo?: IFetchTokenResponse) {
414
+ try {
415
+ let handlerFn;
416
+ const handlerFnName = `__ESRI_REST_AUTH_HANDLER_${clientId}`;
417
+
418
+ if (popup) {
419
+ // Guard b/c IE does not support window.opener
420
+ if (win.opener) {
421
+ if (win.opener.parent && win.opener.parent[handlerFnName]) {
422
+ handlerFn = win.opener.parent[handlerFnName];
423
+ } else if (win.opener && win.opener[handlerFnName]) {
424
+ // support pop-out oauth from within an iframe
425
+ handlerFn = win.opener[handlerFnName];
426
+ }
427
+ } else {
428
+ // IE
429
+ if (win !== win.parent && win.parent && win.parent[handlerFnName]) {
430
+ handlerFn = win.parent[handlerFnName];
431
+ }
432
+ }
433
+ // if we have a handler fn, call it and close the window
434
+ if (handlerFn) {
435
+ handlerFn(
436
+ error ? JSON.stringify(error) : undefined,
437
+ JSON.stringify(oauthInfo)
438
+ );
439
+ win.close();
440
+ return undefined;
441
+ }
442
+ }
443
+ } catch (e) {
444
+ throw new ArcGISAuthError(
445
+ `Unable to complete authentication. It's possible you specified popup based oAuth2 but no handler from "beginOAuth2()" present. This generally happens because the "popup" option differs between "beginOAuth2()" and "completeOAuth2()".`
446
+ );
447
+ }
448
+
449
+ if (error) {
450
+ throw new ArcGISAuthError(error.errorMessage, error.error);
451
+ }
452
+
453
+ return new UserSession({
454
+ clientId,
455
+ portal,
456
+ ssl: oauthInfo.ssl,
457
+ token: oauthInfo.token,
458
+ tokenExpires: oauthInfo.expires,
459
+ username: oauthInfo.username,
460
+ });
461
+ }
462
+
463
+ const params = decodeQueryString(win.location.hash);
464
+
465
+ if (!params.access_token) {
466
+ let error;
467
+ let errorMessage = "Unknown error";
468
+
469
+ if (params.error) {
470
+ error = params.error;
471
+ errorMessage = params.error_description;
472
+ }
473
+
474
+ return completeSignIn({ error, errorMessage });
475
+ }
476
+
477
+ const token = params.access_token;
478
+ const expires = new Date(
479
+ Date.now() + parseInt(params.expires_in, 10) * 1000 - 60 * 1000
480
+ );
481
+ const username = params.username;
482
+ const ssl = params.ssl === "true";
483
+
484
+ return completeSignIn(undefined, {
485
+ token,
486
+ expires,
487
+ ssl,
488
+ username,
489
+ });
490
+ }
491
+
492
+ /**
493
+ * Request session information from the parent application
494
+ *
495
+ * When an application is embedded into another application via an IFrame, the embedded app can
496
+ * use `window.postMessage` to request credentials from the host application. This function wraps
497
+ * that behavior.
498
+ *
499
+ * The ArcGIS API for Javascript has this built into the Identity Manager as of the 4.19 release.
500
+ *
501
+ * Note: The parent application will not respond if the embedded app's origin is not:
502
+ * - the same origin as the parent or *.arcgis.com (JSAPI)
503
+ * - in the list of valid child origins (REST-JS)
504
+ *
505
+ *
506
+ * @param parentOrigin origin of the parent frame. Passed into the embedded application as `parentOrigin` query param
507
+ * @browserOnly
508
+ */
509
+ public static fromParent(parentOrigin: string, win?: any): Promise<any> {
510
+ /* istanbul ignore next: must pass in a mockwindow for tests so we can't cover the other branch */
511
+ if (!win && window) {
512
+ win = window;
513
+ }
514
+ // Declare handler outside of promise scope so we can detach it
515
+ let handler: (event: any) => void;
516
+ // return a promise that will resolve when the handler receives
517
+ // session information from the correct origin
518
+ return new Promise((resolve, reject) => {
519
+ // create an event handler that just wraps the parentMessageHandler
520
+ handler = (event: any) => {
521
+ // ensure we only listen to events from the parent
522
+ if (event.source === win.parent && event.data) {
523
+ try {
524
+ return resolve(UserSession.parentMessageHandler(event));
525
+ } catch (err) {
526
+ return reject(err);
527
+ }
528
+ }
529
+ };
530
+ // add listener
531
+ win.addEventListener("message", handler, false);
532
+ win.parent.postMessage(
533
+ { type: "arcgis:auth:requestCredential" },
534
+ parentOrigin
535
+ );
536
+ }).then((session) => {
537
+ win.removeEventListener("message", handler, false);
538
+ return session;
539
+ });
540
+ }
541
+
542
+ /**
543
+ * Begins a new server-based OAuth 2.0 sign in. This will redirect the user to
544
+ * the ArcGIS Online or ArcGIS Enterprise authorization page.
545
+ *
546
+ * @nodeOnly
547
+ */
548
+ public static authorize(
549
+ options: IOAuth2Options,
550
+ response: http.ServerResponse
551
+ ) {
552
+ if (options.duration) {
553
+ console.log(
554
+ "DEPRECATED: 'duration' is deprecated - use 'expiration' instead"
555
+ );
556
+ }
557
+ const { portal, clientId, expiration, redirectUri }: IOAuth2Options = {
558
+ ...{ portal: "https://arcgis.com/sharing/rest", expiration: 20160 },
559
+ ...options,
560
+ };
561
+
562
+ response.writeHead(301, {
563
+ Location: `${portal}/oauth2/authorize?client_id=${clientId}&expiration=${
564
+ options.duration || expiration
565
+ }&response_type=code&redirect_uri=${encodeURIComponent(redirectUri)}`,
566
+ });
567
+
568
+ response.end();
569
+ }
570
+
571
+ /**
572
+ * Completes the server-based OAuth 2.0 sign in process by exchanging the `authorizationCode`
573
+ * for a `access_token`.
574
+ *
575
+ * @nodeOnly
576
+ */
577
+ public static exchangeAuthorizationCode(
578
+ options: IOAuth2Options,
579
+ authorizationCode: string
580
+ ): Promise<UserSession> {
581
+ const { portal, clientId, redirectUri, refreshTokenTTL }: IOAuth2Options = {
582
+ ...{
583
+ portal: "https://www.arcgis.com/sharing/rest",
584
+ refreshTokenTTL: 20160,
585
+ },
586
+ ...options,
587
+ };
588
+
589
+ return fetchToken(`${portal}/oauth2/token`, {
590
+ params: {
591
+ grant_type: "authorization_code",
592
+ client_id: clientId,
593
+ redirect_uri: redirectUri,
594
+ code: authorizationCode,
595
+ },
596
+ }).then((response) => {
597
+ return new UserSession({
598
+ clientId,
599
+ portal,
600
+ ssl: response.ssl,
601
+ redirectUri,
602
+ refreshToken: response.refreshToken,
603
+ refreshTokenTTL,
604
+ refreshTokenExpires: new Date(
605
+ Date.now() + (refreshTokenTTL - 1) * 60 * 1000
606
+ ),
607
+ token: response.token,
608
+ tokenExpires: response.expires,
609
+ username: response.username,
610
+ });
611
+ });
612
+ }
613
+
614
+ public static deserialize(str: string) {
615
+ const options = JSON.parse(str);
616
+ return new UserSession({
617
+ clientId: options.clientId,
618
+ refreshToken: options.refreshToken,
619
+ refreshTokenExpires: new Date(options.refreshTokenExpires),
620
+ username: options.username,
621
+ password: options.password,
622
+ token: options.token,
623
+ tokenExpires: new Date(options.tokenExpires),
624
+ portal: options.portal,
625
+ ssl: options.ssl,
626
+ tokenDuration: options.tokenDuration,
627
+ redirectUri: options.redirectUri,
628
+ refreshTokenTTL: options.refreshTokenTTL,
629
+ });
630
+ }
631
+
632
+ /**
633
+ * Translates authentication from the format used in the [ArcGIS API for JavaScript](https://developers.arcgis.com/javascript/).
634
+ *
635
+ * ```js
636
+ * UserSession.fromCredential({
637
+ * userId: "jsmith",
638
+ * token: "secret"
639
+ * });
640
+ * ```
641
+ *
642
+ * @returns UserSession
643
+ */
644
+ public static fromCredential(credential: ICredential) {
645
+ // At ArcGIS Online 9.1, credentials no longer include the ssl and expires properties
646
+ // Here, we provide default values for them to cover this condition
647
+ const ssl = typeof credential.ssl !== "undefined" ? credential.ssl : true;
648
+ const expires = credential.expires || Date.now() + 7200000; /* 2 hours */
649
+
650
+ return new UserSession({
651
+ portal: credential.server.includes("sharing/rest")
652
+ ? credential.server
653
+ : credential.server + `/sharing/rest`,
654
+ ssl,
655
+ token: credential.token,
656
+ username: credential.userId,
657
+ tokenExpires: new Date(expires),
658
+ });
659
+ }
660
+
661
+ /**
662
+ * Handle the response from the parent
663
+ * @param event DOM Event
664
+ */
665
+ private static parentMessageHandler(event: any): UserSession {
666
+ if (event.data.type === "arcgis:auth:credential") {
667
+ return UserSession.fromCredential(event.data.credential);
668
+ }
669
+ if (event.data.type === "arcgis:auth:error") {
670
+ const err = new Error(event.data.error.message);
671
+ err.name = event.data.error.name;
672
+ throw err;
673
+ } else {
674
+ throw new Error("Unknown message type.");
675
+ }
676
+ }
677
+
678
+ /**
679
+ * Client ID being used for authentication if provided in the `constructor`.
680
+ */
681
+ public readonly clientId: string;
682
+
683
+ /**
684
+ * The currently authenticated user if provided in the `constructor`.
685
+ */
686
+ public readonly username: string;
687
+
688
+ /**
689
+ * The currently authenticated user's password if provided in the `constructor`.
690
+ */
691
+ public readonly password: string;
692
+
693
+ /**
694
+ * The current portal the user is authenticated with.
695
+ */
696
+ public readonly portal: string;
697
+
698
+ /**
699
+ * This value is set to true automatically if the ArcGIS Organization requires that requests be made over https.
700
+ */
701
+ public readonly ssl: boolean;
702
+
703
+ /**
704
+ * The authentication provider to use.
705
+ */
706
+ public readonly provider: AuthenticationProvider;
707
+
708
+ /**
709
+ * Determines how long new tokens requested are valid.
710
+ */
711
+ public readonly tokenDuration: number;
712
+
713
+ /**
714
+ * A valid redirect URI for this application if provided in the `constructor`.
715
+ */
716
+ public readonly redirectUri: string;
717
+
718
+ /**
719
+ * Duration of new OAuth 2.0 refresh token validity (in minutes).
720
+ */
721
+ public readonly refreshTokenTTL: number;
722
+
723
+ /**
724
+ * An unfederated ArcGIS Server instance known to recognize credentials supplied manually.
725
+ * ```js
726
+ * {
727
+ * server: "https://sampleserver6.arcgisonline.com/arcgis",
728
+ * token: "SOSlV3v..",
729
+ * tokenExpires: new Date(1545415669763)
730
+ * }
731
+ * ```
732
+ */
733
+ public readonly server: string;
734
+
735
+ /**
736
+ * Hydrated by a call to [getUser()](#getUser-summary).
737
+ */
738
+ private _user: IUser;
739
+
740
+ /**
741
+ * Hydrated by a call to [getPortal()](#getPortal-summary).
742
+ */
743
+ private _portalInfo: any;
744
+
745
+ private _token: string;
746
+ private _tokenExpires: Date;
747
+ private _refreshToken: string;
748
+ private _refreshTokenExpires: Date;
749
+ private _pendingUserRequest: Promise<IUser>;
750
+ private _pendingPortalRequest: Promise<any>;
751
+
752
+ /**
753
+ * Internal object to keep track of pending token requests. Used to prevent
754
+ * duplicate token requests.
755
+ */
756
+ private _pendingTokenRequests: {
757
+ [key: string]: Promise<string>;
758
+ };
759
+
760
+ /**
761
+ * Internal list of tokens to 3rd party servers (federated servers) that have
762
+ * been created via `generateToken`. The object key is the root URL of the server.
763
+ */
764
+ private federatedServers: {
765
+ [key: string]: {
766
+ token: string;
767
+ expires: Date;
768
+ };
769
+ };
770
+
771
+ /**
772
+ * Internal list of 3rd party domains that should receive all cookies (credentials: "include").
773
+ * Used to for PKI and IWA workflows in high security environments.
774
+ */
775
+ private trustedDomains: string[];
776
+
777
+ private _hostHandler: any;
778
+
779
+ constructor(options: IUserSessionOptions) {
780
+ this.clientId = options.clientId;
781
+ this._refreshToken = options.refreshToken;
782
+ this._refreshTokenExpires = options.refreshTokenExpires;
783
+ this.username = options.username;
784
+ this.password = options.password;
785
+ this._token = options.token;
786
+ this._tokenExpires = options.tokenExpires;
787
+ this.portal = options.portal
788
+ ? cleanUrl(options.portal)
789
+ : "https://www.arcgis.com/sharing/rest";
790
+ this.ssl = options.ssl;
791
+ this.provider = options.provider || "arcgis";
792
+ this.tokenDuration = options.tokenDuration || 20160;
793
+ this.redirectUri = options.redirectUri;
794
+ this.refreshTokenTTL = options.refreshTokenTTL || 20160;
795
+ this.server = options.server;
796
+
797
+ this.federatedServers = {};
798
+ this.trustedDomains = [];
799
+
800
+ // if a non-federated server was passed explicitly, it should be trusted.
801
+ if (options.server) {
802
+ // if the url includes more than '/arcgis/', trim the rest
803
+ const root = this.getServerRootUrl(options.server);
804
+
805
+ this.federatedServers[root] = {
806
+ token: options.token,
807
+ expires: options.tokenExpires,
808
+ };
809
+ }
810
+ this._pendingTokenRequests = {};
811
+ }
812
+
813
+ /**
814
+ * Returns authentication in a format useable in the [ArcGIS API for JavaScript](https://developers.arcgis.com/javascript/).
815
+ *
816
+ * ```js
817
+ * esriId.registerToken(session.toCredential());
818
+ * ```
819
+ *
820
+ * @returns ICredential
821
+ */
822
+ public toCredential(): ICredential {
823
+ return {
824
+ expires: this.tokenExpires.getTime(),
825
+ server: this.portal,
826
+ ssl: this.ssl,
827
+ token: this.token,
828
+ userId: this.username,
829
+ };
830
+ }
831
+
832
+ /**
833
+ * Returns information about the currently logged in [user](https://developers.arcgis.com/rest/users-groups-and-items/user.htm). Subsequent calls will *not* result in additional web traffic.
834
+ *
835
+ * ```js
836
+ * session.getUser()
837
+ * .then(response => {
838
+ * console.log(response.role); // "org_admin"
839
+ * })
840
+ * ```
841
+ *
842
+ * @param requestOptions - Options for the request. NOTE: `rawResponse` is not supported by this operation.
843
+ * @returns A Promise that will resolve with the data from the response.
844
+ */
845
+ public getUser(requestOptions?: IRequestOptions): Promise<IUser> {
846
+ if (this._pendingUserRequest) {
847
+ return this._pendingUserRequest;
848
+ } else if (this._user) {
849
+ return Promise.resolve(this._user);
850
+ } else {
851
+ const url = `${this.portal}/community/self`;
852
+
853
+ const options = {
854
+ httpMethod: "GET",
855
+ authentication: this,
856
+ ...requestOptions,
857
+ rawResponse: false,
858
+ } as IRequestOptions;
859
+
860
+ this._pendingUserRequest = request(url, options).then((response) => {
861
+ this._user = response;
862
+ this._pendingUserRequest = null;
863
+ return response;
864
+ });
865
+
866
+ return this._pendingUserRequest;
867
+ }
868
+ }
869
+
870
+ /**
871
+ * Returns information about the currently logged in user's [portal](https://developers.arcgis.com/rest/users-groups-and-items/portal-self.htm). Subsequent calls will *not* result in additional web traffic.
872
+ *
873
+ * ```js
874
+ * session.getPortal()
875
+ * .then(response => {
876
+ * console.log(portal.name); // "City of ..."
877
+ * })
878
+ * ```
879
+ *
880
+ * @param requestOptions - Options for the request. NOTE: `rawResponse` is not supported by this operation.
881
+ * @returns A Promise that will resolve with the data from the response.
882
+ */
883
+ public getPortal(requestOptions?: IRequestOptions): Promise<any> {
884
+ if (this._pendingPortalRequest) {
885
+ return this._pendingPortalRequest;
886
+ } else if (this._portalInfo) {
887
+ return Promise.resolve(this._portalInfo);
888
+ } else {
889
+ const url = `${this.portal}/portals/self`;
890
+
891
+ const options = {
892
+ httpMethod: "GET",
893
+ authentication: this,
894
+ ...requestOptions,
895
+ rawResponse: false,
896
+ } as IRequestOptions;
897
+
898
+ this._pendingPortalRequest = request(url, options).then((response) => {
899
+ this._portalInfo = response;
900
+ this._pendingPortalRequest = null;
901
+ return response;
902
+ });
903
+
904
+ return this._pendingPortalRequest;
905
+ }
906
+ }
907
+
908
+ /**
909
+ * Returns the username for the currently logged in [user](https://developers.arcgis.com/rest/users-groups-and-items/user.htm). Subsequent calls will *not* result in additional web traffic. This is also used internally when a username is required for some requests but is not present in the options.
910
+ *
911
+ * * ```js
912
+ * session.getUsername()
913
+ * .then(response => {
914
+ * console.log(response); // "casey_jones"
915
+ * })
916
+ * ```
917
+ */
918
+ public getUsername() {
919
+ if (this.username) {
920
+ return Promise.resolve(this.username);
921
+ } else if (this._user) {
922
+ return Promise.resolve(this._user.username);
923
+ } else {
924
+ return this.getUser().then((user) => {
925
+ return user.username;
926
+ });
927
+ }
928
+ }
929
+
930
+ /**
931
+ * Gets an appropriate token for the given URL. If `portal` is ArcGIS Online and
932
+ * the request is to an ArcGIS Online domain `token` will be used. If the request
933
+ * is to the current `portal` the current `token` will also be used. However if
934
+ * the request is to an unknown server we will validate the server with a request
935
+ * to our current `portal`.
936
+ */
937
+ public getToken(url: string, requestOptions?: ITokenRequestOptions) {
938
+ if (canUseOnlineToken(this.portal, url)) {
939
+ return this.getFreshToken(requestOptions);
940
+ } else if (new RegExp(this.portal, "i").test(url)) {
941
+ return this.getFreshToken(requestOptions);
942
+ } else {
943
+ return this.getTokenForServer(url, requestOptions);
944
+ }
945
+ }
946
+
947
+ /**
948
+ * Get application access information for the current user
949
+ * see `validateAppAccess` function for details
950
+ *
951
+ * @param clientId application client id
952
+ */
953
+ public validateAppAccess(clientId: string): Promise<IAppAccess> {
954
+ return this.getToken(this.portal).then((token) => {
955
+ return validateAppAccess(token, clientId);
956
+ });
957
+ }
958
+
959
+ public toJSON(): IUserSessionOptions {
960
+ return {
961
+ clientId: this.clientId,
962
+ refreshToken: this.refreshToken,
963
+ refreshTokenExpires: this.refreshTokenExpires,
964
+ username: this.username,
965
+ password: this.password,
966
+ token: this.token,
967
+ tokenExpires: this.tokenExpires,
968
+ portal: this.portal,
969
+ ssl: this.ssl,
970
+ tokenDuration: this.tokenDuration,
971
+ redirectUri: this.redirectUri,
972
+ refreshTokenTTL: this.refreshTokenTTL,
973
+ };
974
+ }
975
+
976
+ public serialize() {
977
+ return JSON.stringify(this);
978
+ }
979
+ /**
980
+ * For a "Host" app that embeds other platform apps via iframes, after authenticating the user
981
+ * and creating a UserSession, the app can then enable "post message" style authentication by calling
982
+ * this method.
983
+ *
984
+ * Internally this adds an event listener on window for the `message` event
985
+ *
986
+ * @param validChildOrigins Array of origins that are allowed to request authentication from the host app
987
+ */
988
+ public enablePostMessageAuth(validChildOrigins: string[], win?: any): any {
989
+ /* istanbul ignore next: must pass in a mockwindow for tests so we can't cover the other branch */
990
+ if (!win && window) {
991
+ win = window;
992
+ }
993
+ this._hostHandler = this.createPostMessageHandler(validChildOrigins);
994
+ win.addEventListener("message", this._hostHandler, false);
995
+ }
996
+
997
+ /**
998
+ * For a "Host" app that has embedded other platform apps via iframes, when the host needs
999
+ * to transition routes, it should call `UserSession.disablePostMessageAuth()` to remove
1000
+ * the event listener and prevent memory leaks
1001
+ */
1002
+ public disablePostMessageAuth(win?: any) {
1003
+ /* istanbul ignore next: must pass in a mockwindow for tests so we can't cover the other branch */
1004
+ if (!win && window) {
1005
+ win = window;
1006
+ }
1007
+ win.removeEventListener("message", this._hostHandler, false);
1008
+ }
1009
+
1010
+ /**
1011
+ * Manually refreshes the current `token` and `tokenExpires`.
1012
+ */
1013
+ public refreshSession(
1014
+ requestOptions?: ITokenRequestOptions
1015
+ ): Promise<UserSession> {
1016
+ // make sure subsequent calls to getUser() don't returned cached metadata
1017
+ this._user = null;
1018
+
1019
+ if (this.username && this.password) {
1020
+ return this.refreshWithUsernameAndPassword(requestOptions);
1021
+ }
1022
+
1023
+ if (this.clientId && this.refreshToken) {
1024
+ return this.refreshWithRefreshToken();
1025
+ }
1026
+
1027
+ return Promise.reject(new ArcGISAuthError("Unable to refresh token."));
1028
+ }
1029
+
1030
+ /**
1031
+ * Determines the root of the ArcGIS Server or Portal for a given URL.
1032
+ *
1033
+ * @param url the URl to determine the root url for.
1034
+ */
1035
+ public getServerRootUrl(url: string) {
1036
+ const [root] = cleanUrl(url).split(
1037
+ /\/rest(\/admin)?\/services(?:\/|#|\?|$)/
1038
+ );
1039
+ const [match, protocol, domainAndPath] = root.match(/(https?:\/\/)(.+)/);
1040
+ const [domain, ...path] = domainAndPath.split("/");
1041
+
1042
+ // only the domain is lowercased because in some cases an org id might be
1043
+ // in the path which cannot be lowercased.
1044
+ return `${protocol}${domain.toLowerCase()}/${path.join("/")}`;
1045
+ }
1046
+
1047
+ /**
1048
+ * Returns the proper [`credentials`] option for `fetch` for a given domain.
1049
+ * See [trusted server](https://enterprise.arcgis.com/en/portal/latest/administer/windows/configure-security.htm#ESRI_SECTION1_70CC159B3540440AB325BE5D89DBE94A).
1050
+ * Used internally by underlying request methods to add support for specific security considerations.
1051
+ *
1052
+ * @param url The url of the request
1053
+ * @returns "include" or "same-origin"
1054
+ */
1055
+ public getDomainCredentials(url: string): RequestCredentials {
1056
+ if (!this.trustedDomains || !this.trustedDomains.length) {
1057
+ return "same-origin";
1058
+ }
1059
+
1060
+ return this.trustedDomains.some((domainWithProtocol) => {
1061
+ return url.startsWith(domainWithProtocol);
1062
+ })
1063
+ ? "include"
1064
+ : "same-origin";
1065
+ }
1066
+
1067
+ /**
1068
+ * Return a function that closes over the validOrigins array and
1069
+ * can be used as an event handler for the `message` event
1070
+ *
1071
+ * @param validOrigins Array of valid origins
1072
+ */
1073
+ private createPostMessageHandler(
1074
+ validOrigins: string[]
1075
+ ): (event: any) => void {
1076
+ // return a function that closes over the validOrigins and
1077
+ // has access to the credential
1078
+ return (event: any) => {
1079
+ // Verify that the origin is valid
1080
+ // Note: do not use regex's here. validOrigins is an array so we're checking that the event's origin
1081
+ // is in the array via exact match. More info about avoiding postMessage xss issues here
1082
+ // https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html#tipsbypasses-in-postmessage-vulnerabilities
1083
+ const isValidOrigin = validOrigins.indexOf(event.origin) > -1;
1084
+ // JSAPI handles this slightly differently - instead of checking a list, it will respond if
1085
+ // event.origin === window.location.origin || event.origin.endsWith('.arcgis.com')
1086
+ // For Hub, and to enable cross domain debugging with port's in urls, we are opting to
1087
+ // use a list of valid origins
1088
+
1089
+ // Ensure the message type is something we want to handle
1090
+ const isValidType = event.data.type === "arcgis:auth:requestCredential";
1091
+
1092
+ const isTokenValid = this.tokenExpires.getTime() > Date.now();
1093
+
1094
+ if (isValidOrigin && isValidType) {
1095
+ let msg = {};
1096
+ if (isTokenValid) {
1097
+ const credential = this.toCredential();
1098
+ // arcgis:auth:error with {name: "", message: ""}
1099
+ // the following line allows us to conform to our spec without changing other depended-on functionality
1100
+ // https://github.com/Esri/arcgis-rest-js/blob/master/packages/arcgis-rest-auth/post-message-auth-spec.md#arcgisauthcredential
1101
+ credential.server = credential.server.replace("/sharing/rest", "");
1102
+ msg = { type: "arcgis:auth:credential", credential };
1103
+ } else {
1104
+ // Return an error
1105
+ msg = {
1106
+ type: "arcgis:auth:error",
1107
+ error: {
1108
+ name: "tokenExpiredError",
1109
+ message:
1110
+ "Session token was expired, and not returned to the child application",
1111
+ },
1112
+ };
1113
+ }
1114
+ event.source.postMessage(msg, event.origin);
1115
+ }
1116
+ };
1117
+ }
1118
+
1119
+ /**
1120
+ * Validates that a given URL is properly federated with our current `portal`.
1121
+ * Attempts to use the internal `federatedServers` cache first.
1122
+ */
1123
+ private getTokenForServer(
1124
+ url: string,
1125
+ requestOptions?: ITokenRequestOptions
1126
+ ) {
1127
+ // requests to /rest/services/ and /rest/admin/services/ are both valid
1128
+ // Federated servers may have inconsistent casing, so lowerCase it
1129
+ const root = this.getServerRootUrl(url);
1130
+ const existingToken = this.federatedServers[root];
1131
+
1132
+ if (
1133
+ existingToken &&
1134
+ existingToken.expires &&
1135
+ existingToken.expires.getTime() > Date.now()
1136
+ ) {
1137
+ return Promise.resolve(existingToken.token);
1138
+ }
1139
+
1140
+ if (this._pendingTokenRequests[root]) {
1141
+ return this._pendingTokenRequests[root];
1142
+ }
1143
+
1144
+ this._pendingTokenRequests[root] = this.fetchAuthorizedDomains().then(
1145
+ () => {
1146
+ return request(`${root}/rest/info`, {
1147
+ credentials: this.getDomainCredentials(url),
1148
+ })
1149
+ .then((response) => {
1150
+ if (response.owningSystemUrl) {
1151
+ /**
1152
+ * if this server is not owned by this portal
1153
+ * bail out with an error since we know we wont
1154
+ * be able to generate a token
1155
+ */
1156
+ if (!isFederated(response.owningSystemUrl, this.portal)) {
1157
+ throw new ArcGISAuthError(
1158
+ `${url} is not federated with ${this.portal}.`,
1159
+ "NOT_FEDERATED"
1160
+ );
1161
+ } else {
1162
+ /**
1163
+ * if the server is federated, use the relevant token endpoint.
1164
+ */
1165
+ return request(
1166
+ `${response.owningSystemUrl}/sharing/rest/info`,
1167
+ requestOptions
1168
+ );
1169
+ }
1170
+ } else if (
1171
+ response.authInfo &&
1172
+ this.federatedServers[root] !== undefined
1173
+ ) {
1174
+ /**
1175
+ * if its a stand-alone instance of ArcGIS Server that doesn't advertise
1176
+ * federation, but the root server url is recognized, use its built in token endpoint.
1177
+ */
1178
+ return Promise.resolve({
1179
+ authInfo: response.authInfo,
1180
+ });
1181
+ } else {
1182
+ throw new ArcGISAuthError(
1183
+ `${url} is not federated with any portal and is not explicitly trusted.`,
1184
+ "NOT_FEDERATED"
1185
+ );
1186
+ }
1187
+ })
1188
+ .then((response: any) => {
1189
+ return response.authInfo.tokenServicesUrl;
1190
+ })
1191
+ .then((tokenServicesUrl: string) => {
1192
+ // an expired token cant be used to generate a new token
1193
+ if (this.token && this.tokenExpires.getTime() > Date.now()) {
1194
+ return generateToken(tokenServicesUrl, {
1195
+ params: {
1196
+ token: this.token,
1197
+ serverUrl: url,
1198
+ expiration: this.tokenDuration,
1199
+ client: "referer",
1200
+ },
1201
+ });
1202
+ // generate an entirely fresh token if necessary
1203
+ } else {
1204
+ return generateToken(tokenServicesUrl, {
1205
+ params: {
1206
+ username: this.username,
1207
+ password: this.password,
1208
+ expiration: this.tokenDuration,
1209
+ client: "referer",
1210
+ },
1211
+ }).then((response: any) => {
1212
+ this._token = response.token;
1213
+ this._tokenExpires = new Date(response.expires);
1214
+ return response;
1215
+ });
1216
+ }
1217
+ })
1218
+ .then((response) => {
1219
+ this.federatedServers[root] = {
1220
+ expires: new Date(response.expires),
1221
+ token: response.token,
1222
+ };
1223
+ delete this._pendingTokenRequests[root];
1224
+ return response.token;
1225
+ });
1226
+ }
1227
+ );
1228
+
1229
+ return this._pendingTokenRequests[root];
1230
+ }
1231
+
1232
+ /**
1233
+ * Returns an unexpired token for the current `portal`.
1234
+ */
1235
+ private getFreshToken(requestOptions?: ITokenRequestOptions) {
1236
+ if (this.token && !this.tokenExpires) {
1237
+ return Promise.resolve(this.token);
1238
+ }
1239
+
1240
+ if (
1241
+ this.token &&
1242
+ this.tokenExpires &&
1243
+ this.tokenExpires.getTime() > Date.now()
1244
+ ) {
1245
+ return Promise.resolve(this.token);
1246
+ }
1247
+
1248
+ if (!this._pendingTokenRequests[this.portal]) {
1249
+ this._pendingTokenRequests[this.portal] = this.refreshSession(
1250
+ requestOptions
1251
+ ).then((session) => {
1252
+ this._pendingTokenRequests[this.portal] = null;
1253
+ return session.token;
1254
+ });
1255
+ }
1256
+
1257
+ return this._pendingTokenRequests[this.portal];
1258
+ }
1259
+
1260
+ /**
1261
+ * Refreshes the current `token` and `tokenExpires` with `username` and
1262
+ * `password`.
1263
+ */
1264
+ private refreshWithUsernameAndPassword(
1265
+ requestOptions?: ITokenRequestOptions
1266
+ ) {
1267
+ const options = {
1268
+ params: {
1269
+ username: this.username,
1270
+ password: this.password,
1271
+ expiration: this.tokenDuration,
1272
+ },
1273
+ ...requestOptions,
1274
+ };
1275
+ return generateToken(`${this.portal}/generateToken`, options).then(
1276
+ (response: any) => {
1277
+ this._token = response.token;
1278
+ this._tokenExpires = new Date(response.expires);
1279
+ return this;
1280
+ }
1281
+ );
1282
+ }
1283
+
1284
+ /**
1285
+ * Refreshes the current `token` and `tokenExpires` with `refreshToken`.
1286
+ */
1287
+ private refreshWithRefreshToken(requestOptions?: ITokenRequestOptions) {
1288
+ if (
1289
+ this.refreshToken &&
1290
+ this.refreshTokenExpires &&
1291
+ this.refreshTokenExpires.getTime() < Date.now()
1292
+ ) {
1293
+ return this.refreshRefreshToken(requestOptions);
1294
+ }
1295
+
1296
+ const options: ITokenRequestOptions = {
1297
+ params: {
1298
+ client_id: this.clientId,
1299
+ refresh_token: this.refreshToken,
1300
+ grant_type: "refresh_token",
1301
+ },
1302
+ ...requestOptions,
1303
+ };
1304
+ return fetchToken(`${this.portal}/oauth2/token`, options).then(
1305
+ (response) => {
1306
+ this._token = response.token;
1307
+ this._tokenExpires = response.expires;
1308
+ return this;
1309
+ }
1310
+ );
1311
+ }
1312
+
1313
+ /**
1314
+ * Exchanges an unexpired `refreshToken` for a new one, also updates `token` and
1315
+ * `tokenExpires`.
1316
+ */
1317
+ private refreshRefreshToken(requestOptions?: ITokenRequestOptions) {
1318
+ const options: ITokenRequestOptions = {
1319
+ params: {
1320
+ client_id: this.clientId,
1321
+ refresh_token: this.refreshToken,
1322
+ redirect_uri: this.redirectUri,
1323
+ grant_type: "exchange_refresh_token",
1324
+ },
1325
+ ...requestOptions,
1326
+ };
1327
+
1328
+ return fetchToken(`${this.portal}/oauth2/token`, options).then(
1329
+ (response) => {
1330
+ this._token = response.token;
1331
+ this._tokenExpires = response.expires;
1332
+ this._refreshToken = response.refreshToken;
1333
+ this._refreshTokenExpires = new Date(
1334
+ Date.now() + (this.refreshTokenTTL - 1) * 60 * 1000
1335
+ );
1336
+ return this;
1337
+ }
1338
+ );
1339
+ }
1340
+
1341
+ /**
1342
+ * ensures that the authorizedCrossOriginDomains are obtained from the portal and cached
1343
+ * so we can check them later.
1344
+ *
1345
+ * @returns this
1346
+ */
1347
+ private fetchAuthorizedDomains() {
1348
+ // if this token is for a specific server or we don't have a portal
1349
+ // don't get the portal info because we cant get the authorizedCrossOriginDomains
1350
+ if (this.server || !this.portal) {
1351
+ return Promise.resolve(this);
1352
+ }
1353
+
1354
+ return this.getPortal().then((portalInfo) => {
1355
+ /**
1356
+ * Specific domains can be configured as secure.esri.com or https://secure.esri.com this
1357
+ * normalizes to https://secure.esri.com so we can use startsWith later.
1358
+ */
1359
+ if (
1360
+ portalInfo.authorizedCrossOriginDomains &&
1361
+ portalInfo.authorizedCrossOriginDomains.length
1362
+ ) {
1363
+ this.trustedDomains = portalInfo.authorizedCrossOriginDomains
1364
+ .filter((d: string) => !d.startsWith("http://"))
1365
+ .map((d: string) => {
1366
+ if (d.startsWith("https://")) {
1367
+ return d;
1368
+ } else {
1369
+ return `https://${d}`;
1370
+ }
1371
+ });
1372
+ }
1373
+ return this;
1374
+ });
1375
+ }
1376
+ }