@esri/solution-common 6.1.3 → 6.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (404) hide show
  1. package/dist/cjs/arcgisRestJS.d.ts +63 -0
  2. package/dist/cjs/arcgisRestJS.js +158 -0
  3. package/dist/cjs/arcgisRestJS.js.map +1 -0
  4. package/dist/cjs/completeItem.d.ts +30 -0
  5. package/dist/cjs/completeItem.js +72 -0
  6. package/dist/cjs/completeItem.js.map +1 -0
  7. package/dist/cjs/create-hub-request-options.d.ts +29 -0
  8. package/dist/cjs/create-hub-request-options.js +64 -0
  9. package/dist/cjs/create-hub-request-options.js.map +1 -0
  10. package/dist/cjs/deleteHelpers/deleteEmptyGroups.d.ts +24 -0
  11. package/dist/cjs/deleteHelpers/deleteEmptyGroups.js +42 -0
  12. package/dist/cjs/deleteHelpers/deleteEmptyGroups.js.map +1 -0
  13. package/dist/cjs/deleteHelpers/deleteGroupIfEmpty.d.ts +27 -0
  14. package/dist/cjs/deleteHelpers/deleteGroupIfEmpty.js +99 -0
  15. package/dist/cjs/deleteHelpers/deleteGroupIfEmpty.js.map +1 -0
  16. package/dist/cjs/deleteHelpers/deleteSolutionContents.d.ts +39 -0
  17. package/dist/cjs/deleteHelpers/deleteSolutionContents.js +127 -0
  18. package/dist/cjs/deleteHelpers/deleteSolutionContents.js.map +1 -0
  19. package/dist/cjs/deleteHelpers/deleteSolutionFolder.d.ts +29 -0
  20. package/dist/cjs/deleteHelpers/deleteSolutionFolder.js +81 -0
  21. package/dist/cjs/deleteHelpers/deleteSolutionFolder.js.map +1 -0
  22. package/dist/cjs/deleteHelpers/deleteSolutionItem.d.ts +31 -0
  23. package/dist/cjs/deleteHelpers/deleteSolutionItem.js +52 -0
  24. package/dist/cjs/deleteHelpers/deleteSolutionItem.js.map +1 -0
  25. package/dist/cjs/deleteHelpers/index.d.ts +22 -0
  26. package/dist/cjs/deleteHelpers/index.js +26 -0
  27. package/dist/cjs/deleteHelpers/index.js.map +1 -0
  28. package/dist/cjs/deleteHelpers/reconstructBuildOrderIds.d.ts +27 -0
  29. package/dist/cjs/deleteHelpers/reconstructBuildOrderIds.js +34 -0
  30. package/dist/cjs/deleteHelpers/reconstructBuildOrderIds.js.map +1 -0
  31. package/dist/cjs/deleteHelpers/removeItems.d.ts +35 -0
  32. package/dist/cjs/deleteHelpers/removeItems.js +116 -0
  33. package/dist/cjs/deleteHelpers/removeItems.js.map +1 -0
  34. package/dist/cjs/deleteHelpers/reportProgress.d.ts +27 -0
  35. package/dist/cjs/deleteHelpers/reportProgress.js +46 -0
  36. package/dist/cjs/deleteHelpers/reportProgress.js.map +1 -0
  37. package/dist/cjs/deleteSolution.d.ts +56 -0
  38. package/dist/cjs/deleteSolution.js +107 -0
  39. package/dist/cjs/deleteSolution.js.map +1 -0
  40. package/dist/cjs/dependencies.d.ts +26 -0
  41. package/dist/cjs/dependencies.js +171 -0
  42. package/dist/cjs/dependencies.js.map +1 -0
  43. package/dist/cjs/featureServiceHelpers.d.ts +847 -0
  44. package/dist/cjs/featureServiceHelpers.js +2553 -0
  45. package/dist/cjs/featureServiceHelpers.js.map +1 -0
  46. package/dist/cjs/formHelpers.d.ts +26 -0
  47. package/dist/cjs/formHelpers.js +40 -0
  48. package/dist/cjs/formHelpers.js.map +1 -0
  49. package/dist/cjs/generalHelpers.d.ts +447 -0
  50. package/dist/cjs/generalHelpers.js +959 -0
  51. package/dist/cjs/generalHelpers.js.map +1 -0
  52. package/dist/cjs/get-subscription-info.d.ts +27 -0
  53. package/dist/cjs/get-subscription-info.js +38 -0
  54. package/dist/cjs/get-subscription-info.js.map +1 -0
  55. package/dist/cjs/getDeletableSolutionInfo.d.ts +30 -0
  56. package/dist/cjs/getDeletableSolutionInfo.js +53 -0
  57. package/dist/cjs/getDeletableSolutionInfo.js.map +1 -0
  58. package/dist/cjs/getItemTypeAbbrev.d.ts +19 -0
  59. package/dist/cjs/getItemTypeAbbrev.js +186 -0
  60. package/dist/cjs/getItemTypeAbbrev.js.map +1 -0
  61. package/dist/cjs/getSolutionSummary.d.ts +28 -0
  62. package/dist/cjs/getSolutionSummary.js +100 -0
  63. package/dist/cjs/getSolutionSummary.js.map +1 -0
  64. package/dist/cjs/index.d.ts +49 -0
  65. package/dist/cjs/index.js +53 -0
  66. package/dist/cjs/index.js.map +1 -0
  67. package/dist/cjs/interfaces.d.ts +1446 -0
  68. package/dist/cjs/interfaces.js +72 -0
  69. package/dist/cjs/interfaces.js.map +1 -0
  70. package/dist/cjs/item-reuse.d.ts +140 -0
  71. package/dist/cjs/item-reuse.js +176 -0
  72. package/dist/cjs/item-reuse.js.map +1 -0
  73. package/dist/cjs/libConnectors.d.ts +73 -0
  74. package/dist/cjs/libConnectors.js +115 -0
  75. package/dist/cjs/libConnectors.js.map +1 -0
  76. package/dist/cjs/migrations/apply-schema.d.ts +24 -0
  77. package/dist/cjs/migrations/apply-schema.js +36 -0
  78. package/dist/cjs/migrations/apply-schema.js.map +1 -0
  79. package/dist/cjs/migrations/is-legacy-solution.d.ts +24 -0
  80. package/dist/cjs/migrations/is-legacy-solution.js +39 -0
  81. package/dist/cjs/migrations/is-legacy-solution.js.map +1 -0
  82. package/dist/cjs/migrations/upgrade-three-dot-one.d.ts +26 -0
  83. package/dist/cjs/migrations/upgrade-three-dot-one.js +48 -0
  84. package/dist/cjs/migrations/upgrade-three-dot-one.js.map +1 -0
  85. package/dist/cjs/migrations/upgrade-three-dot-zero.d.ts +27 -0
  86. package/dist/cjs/migrations/upgrade-three-dot-zero.js +43 -0
  87. package/dist/cjs/migrations/upgrade-three-dot-zero.js.map +1 -0
  88. package/dist/cjs/migrations/upgrade-two-dot-five.d.ts +24 -0
  89. package/dist/cjs/migrations/upgrade-two-dot-five.js +73 -0
  90. package/dist/cjs/migrations/upgrade-two-dot-five.js.map +1 -0
  91. package/dist/cjs/migrations/upgrade-two-dot-four.d.ts +24 -0
  92. package/dist/cjs/migrations/upgrade-two-dot-four.js +72 -0
  93. package/dist/cjs/migrations/upgrade-two-dot-four.js.map +1 -0
  94. package/dist/cjs/migrations/upgrade-two-dot-one.d.ts +7 -0
  95. package/dist/cjs/migrations/upgrade-two-dot-one.js +39 -0
  96. package/dist/cjs/migrations/upgrade-two-dot-one.js.map +1 -0
  97. package/dist/cjs/migrations/upgrade-two-dot-seven.d.ts +23 -0
  98. package/dist/cjs/migrations/upgrade-two-dot-seven.js +58 -0
  99. package/dist/cjs/migrations/upgrade-two-dot-seven.js.map +1 -0
  100. package/dist/cjs/migrations/upgrade-two-dot-six.d.ts +27 -0
  101. package/dist/cjs/migrations/upgrade-two-dot-six.js +61 -0
  102. package/dist/cjs/migrations/upgrade-two-dot-six.js.map +1 -0
  103. package/dist/cjs/migrations/upgrade-two-dot-three.d.ts +23 -0
  104. package/dist/cjs/migrations/upgrade-two-dot-three.js +55 -0
  105. package/dist/cjs/migrations/upgrade-two-dot-three.js.map +1 -0
  106. package/dist/cjs/migrations/upgrade-two-dot-two.d.ts +23 -0
  107. package/dist/cjs/migrations/upgrade-two-dot-two.js +58 -0
  108. package/dist/cjs/migrations/upgrade-two-dot-two.js.map +1 -0
  109. package/dist/cjs/migrations/upgrade-two-dot-zero.d.ts +44 -0
  110. package/dist/cjs/migrations/upgrade-two-dot-zero.js +95 -0
  111. package/dist/cjs/migrations/upgrade-two-dot-zero.js.map +1 -0
  112. package/dist/cjs/migrator.d.ts +25 -0
  113. package/dist/cjs/migrator.js +75 -0
  114. package/dist/cjs/migrator.js.map +1 -0
  115. package/dist/cjs/resourceHelpers.d.ts +192 -0
  116. package/dist/cjs/resourceHelpers.js +380 -0
  117. package/dist/cjs/resourceHelpers.js.map +1 -0
  118. package/dist/cjs/resources/add-resource.d.ts +38 -0
  119. package/dist/cjs/resources/add-resource.js +84 -0
  120. package/dist/cjs/resources/add-resource.js.map +1 -0
  121. package/dist/cjs/resources/addMetadataFromBlob.d.ts +25 -0
  122. package/dist/cjs/resources/addMetadataFromBlob.js +43 -0
  123. package/dist/cjs/resources/addMetadataFromBlob.js.map +1 -0
  124. package/dist/cjs/resources/convert-item-resource-to-storage-resource.d.ts +32 -0
  125. package/dist/cjs/resources/convert-item-resource-to-storage-resource.js +70 -0
  126. package/dist/cjs/resources/convert-item-resource-to-storage-resource.js.map +1 -0
  127. package/dist/cjs/resources/convert-storage-resource-to-item-resource.d.ts +29 -0
  128. package/dist/cjs/resources/convert-storage-resource-to-item-resource.js +70 -0
  129. package/dist/cjs/resources/convert-storage-resource-to-item-resource.js.map +1 -0
  130. package/dist/cjs/resources/copyAssociatedFiles.d.ts +79 -0
  131. package/dist/cjs/resources/copyAssociatedFiles.js +348 -0
  132. package/dist/cjs/resources/copyAssociatedFiles.js.map +1 -0
  133. package/dist/cjs/resources/copyDataIntoItem.d.ts +34 -0
  134. package/dist/cjs/resources/copyDataIntoItem.js +45 -0
  135. package/dist/cjs/resources/copyDataIntoItem.js.map +1 -0
  136. package/dist/cjs/resources/copyMetadataIntoItem.d.ts +27 -0
  137. package/dist/cjs/resources/copyMetadataIntoItem.js +44 -0
  138. package/dist/cjs/resources/copyMetadataIntoItem.js.map +1 -0
  139. package/dist/cjs/resources/copyResourceIntoZip.d.ts +34 -0
  140. package/dist/cjs/resources/copyResourceIntoZip.js +74 -0
  141. package/dist/cjs/resources/copyResourceIntoZip.js.map +1 -0
  142. package/dist/cjs/resources/copyZipIntoItem.d.ts +26 -0
  143. package/dist/cjs/resources/copyZipIntoItem.js +53 -0
  144. package/dist/cjs/resources/copyZipIntoItem.js.map +1 -0
  145. package/dist/cjs/resources/createCopyResults.d.ts +25 -0
  146. package/dist/cjs/resources/createCopyResults.js +36 -0
  147. package/dist/cjs/resources/createCopyResults.js.map +1 -0
  148. package/dist/cjs/resources/get-blob.d.ts +25 -0
  149. package/dist/cjs/resources/get-blob.js +42 -0
  150. package/dist/cjs/resources/get-blob.js.map +1 -0
  151. package/dist/cjs/resources/getItemResourcesFilesFromPaths.d.ts +25 -0
  152. package/dist/cjs/resources/getItemResourcesFilesFromPaths.js +49 -0
  153. package/dist/cjs/resources/getItemResourcesFilesFromPaths.js.map +1 -0
  154. package/dist/cjs/resources/getItemResourcesPaths.d.ts +27 -0
  155. package/dist/cjs/resources/getItemResourcesPaths.js +80 -0
  156. package/dist/cjs/resources/getItemResourcesPaths.js.map +1 -0
  157. package/dist/cjs/resources/index.d.ts +30 -0
  158. package/dist/cjs/resources/index.js +34 -0
  159. package/dist/cjs/resources/index.js.map +1 -0
  160. package/dist/cjs/resources/solution-resource.d.ts +35 -0
  161. package/dist/cjs/resources/solution-resource.js +31 -0
  162. package/dist/cjs/resources/solution-resource.js.map +1 -0
  163. package/dist/cjs/resources/transform-resource-paths-to-solution-resources.d.ts +56 -0
  164. package/dist/cjs/resources/transform-resource-paths-to-solution-resources.js +140 -0
  165. package/dist/cjs/resources/transform-resource-paths-to-solution-resources.js.map +1 -0
  166. package/dist/cjs/resources/update-resource.d.ts +27 -0
  167. package/dist/cjs/resources/update-resource.js +52 -0
  168. package/dist/cjs/resources/update-resource.js.map +1 -0
  169. package/dist/cjs/restHelpers.d.ts +634 -0
  170. package/dist/cjs/restHelpers.js +2008 -0
  171. package/dist/cjs/restHelpers.js.map +1 -0
  172. package/dist/cjs/restHelpersGet.d.ts +303 -0
  173. package/dist/cjs/restHelpersGet.js +835 -0
  174. package/dist/cjs/restHelpersGet.js.map +1 -0
  175. package/dist/cjs/sharing/index.d.ts +16 -0
  176. package/dist/cjs/sharing/index.js +20 -0
  177. package/dist/cjs/sharing/index.js.map +1 -0
  178. package/dist/cjs/sharing/share-item-to-groups.d.ts +26 -0
  179. package/dist/cjs/sharing/share-item-to-groups.js +44 -0
  180. package/dist/cjs/sharing/share-item-to-groups.js.map +1 -0
  181. package/dist/cjs/templatization.d.ts +139 -0
  182. package/dist/cjs/templatization.js +311 -0
  183. package/dist/cjs/templatization.js.map +1 -0
  184. package/dist/cjs/trackingHelpers.d.ts +115 -0
  185. package/dist/cjs/trackingHelpers.js +212 -0
  186. package/dist/cjs/trackingHelpers.js.map +1 -0
  187. package/dist/cjs/velocityHelpers.d.ts +68 -0
  188. package/dist/cjs/velocityHelpers.js +151 -0
  189. package/dist/cjs/velocityHelpers.js.map +1 -0
  190. package/dist/cjs/webtoolHelpers.d.ts +57 -0
  191. package/dist/cjs/webtoolHelpers.js +102 -0
  192. package/dist/cjs/webtoolHelpers.js.map +1 -0
  193. package/dist/cjs/workflowHelpers.d.ts +112 -0
  194. package/dist/cjs/workflowHelpers.js +284 -0
  195. package/dist/cjs/workflowHelpers.js.map +1 -0
  196. package/dist/cjs/workforceHelpers.d.ts +121 -0
  197. package/dist/cjs/workforceHelpers.js +720 -0
  198. package/dist/cjs/workforceHelpers.js.map +1 -0
  199. package/dist/cjs/zip-utils.d.ts +85 -0
  200. package/dist/cjs/zip-utils.js +154 -0
  201. package/dist/cjs/zip-utils.js.map +1 -0
  202. package/dist/esm/arcgisRestJS.d.ts +63 -0
  203. package/dist/esm/arcgisRestJS.js +110 -0
  204. package/dist/esm/arcgisRestJS.js.map +1 -0
  205. package/dist/esm/completeItem.d.ts +30 -0
  206. package/dist/esm/completeItem.js +67 -0
  207. package/dist/esm/completeItem.js.map +1 -0
  208. package/dist/esm/create-hub-request-options.d.ts +29 -0
  209. package/dist/esm/create-hub-request-options.js +60 -0
  210. package/dist/esm/create-hub-request-options.js.map +1 -0
  211. package/dist/esm/deleteHelpers/deleteEmptyGroups.d.ts +24 -0
  212. package/dist/esm/deleteHelpers/deleteEmptyGroups.js +38 -0
  213. package/dist/esm/deleteHelpers/deleteEmptyGroups.js.map +1 -0
  214. package/dist/esm/deleteHelpers/deleteGroupIfEmpty.d.ts +27 -0
  215. package/dist/esm/deleteHelpers/deleteGroupIfEmpty.js +95 -0
  216. package/dist/esm/deleteHelpers/deleteGroupIfEmpty.js.map +1 -0
  217. package/dist/esm/deleteHelpers/deleteSolutionContents.d.ts +39 -0
  218. package/dist/esm/deleteHelpers/deleteSolutionContents.js +122 -0
  219. package/dist/esm/deleteHelpers/deleteSolutionContents.js.map +1 -0
  220. package/dist/esm/deleteHelpers/deleteSolutionFolder.d.ts +29 -0
  221. package/dist/esm/deleteHelpers/deleteSolutionFolder.js +77 -0
  222. package/dist/esm/deleteHelpers/deleteSolutionFolder.js.map +1 -0
  223. package/dist/esm/deleteHelpers/deleteSolutionItem.d.ts +31 -0
  224. package/dist/esm/deleteHelpers/deleteSolutionItem.js +48 -0
  225. package/dist/esm/deleteHelpers/deleteSolutionItem.js.map +1 -0
  226. package/dist/esm/deleteHelpers/index.d.ts +22 -0
  227. package/dist/esm/deleteHelpers/index.js +23 -0
  228. package/dist/esm/deleteHelpers/index.js.map +1 -0
  229. package/dist/esm/deleteHelpers/reconstructBuildOrderIds.d.ts +27 -0
  230. package/dist/esm/deleteHelpers/reconstructBuildOrderIds.js +29 -0
  231. package/dist/esm/deleteHelpers/reconstructBuildOrderIds.js.map +1 -0
  232. package/dist/esm/deleteHelpers/removeItems.d.ts +35 -0
  233. package/dist/esm/deleteHelpers/removeItems.js +111 -0
  234. package/dist/esm/deleteHelpers/removeItems.js.map +1 -0
  235. package/dist/esm/deleteHelpers/reportProgress.d.ts +27 -0
  236. package/dist/esm/deleteHelpers/reportProgress.js +42 -0
  237. package/dist/esm/deleteHelpers/reportProgress.js.map +1 -0
  238. package/dist/esm/deleteSolution.d.ts +56 -0
  239. package/dist/esm/deleteSolution.js +101 -0
  240. package/dist/esm/deleteSolution.js.map +1 -0
  241. package/dist/esm/dependencies.d.ts +26 -0
  242. package/dist/esm/dependencies.js +167 -0
  243. package/dist/esm/dependencies.js.map +1 -0
  244. package/dist/esm/featureServiceHelpers.d.ts +847 -0
  245. package/dist/esm/featureServiceHelpers.js +2466 -0
  246. package/dist/esm/featureServiceHelpers.js.map +1 -0
  247. package/dist/esm/formHelpers.d.ts +26 -0
  248. package/dist/esm/formHelpers.js +35 -0
  249. package/dist/esm/formHelpers.js.map +1 -0
  250. package/dist/esm/generalHelpers.d.ts +447 -0
  251. package/dist/esm/generalHelpers.js +903 -0
  252. package/dist/esm/generalHelpers.js.map +1 -0
  253. package/dist/esm/get-subscription-info.d.ts +27 -0
  254. package/dist/esm/get-subscription-info.js +34 -0
  255. package/dist/esm/get-subscription-info.js.map +1 -0
  256. package/dist/esm/getDeletableSolutionInfo.d.ts +30 -0
  257. package/dist/esm/getDeletableSolutionInfo.js +48 -0
  258. package/dist/esm/getDeletableSolutionInfo.js.map +1 -0
  259. package/dist/esm/getItemTypeAbbrev.d.ts +19 -0
  260. package/dist/esm/getItemTypeAbbrev.js +182 -0
  261. package/dist/esm/getItemTypeAbbrev.js.map +1 -0
  262. package/dist/esm/getSolutionSummary.d.ts +28 -0
  263. package/dist/esm/getSolutionSummary.js +95 -0
  264. package/dist/esm/getSolutionSummary.js.map +1 -0
  265. package/dist/esm/index.d.ts +49 -0
  266. package/dist/esm/index.js +50 -0
  267. package/dist/esm/index.js.map +1 -0
  268. package/dist/esm/interfaces.d.ts +1446 -0
  269. package/dist/esm/interfaces.js +69 -0
  270. package/dist/esm/interfaces.js.map +1 -0
  271. package/dist/esm/item-reuse.d.ts +140 -0
  272. package/dist/esm/item-reuse.js +167 -0
  273. package/dist/esm/item-reuse.js.map +1 -0
  274. package/dist/esm/libConnectors.d.ts +73 -0
  275. package/dist/esm/libConnectors.js +105 -0
  276. package/dist/esm/libConnectors.js.map +1 -0
  277. package/dist/esm/migrations/apply-schema.d.ts +24 -0
  278. package/dist/esm/migrations/apply-schema.js +32 -0
  279. package/dist/esm/migrations/apply-schema.js.map +1 -0
  280. package/dist/esm/migrations/is-legacy-solution.d.ts +24 -0
  281. package/dist/esm/migrations/is-legacy-solution.js +35 -0
  282. package/dist/esm/migrations/is-legacy-solution.js.map +1 -0
  283. package/dist/esm/migrations/upgrade-three-dot-one.d.ts +26 -0
  284. package/dist/esm/migrations/upgrade-three-dot-one.js +44 -0
  285. package/dist/esm/migrations/upgrade-three-dot-one.js.map +1 -0
  286. package/dist/esm/migrations/upgrade-three-dot-zero.d.ts +27 -0
  287. package/dist/esm/migrations/upgrade-three-dot-zero.js +39 -0
  288. package/dist/esm/migrations/upgrade-three-dot-zero.js.map +1 -0
  289. package/dist/esm/migrations/upgrade-two-dot-five.d.ts +24 -0
  290. package/dist/esm/migrations/upgrade-two-dot-five.js +69 -0
  291. package/dist/esm/migrations/upgrade-two-dot-five.js.map +1 -0
  292. package/dist/esm/migrations/upgrade-two-dot-four.d.ts +24 -0
  293. package/dist/esm/migrations/upgrade-two-dot-four.js +68 -0
  294. package/dist/esm/migrations/upgrade-two-dot-four.js.map +1 -0
  295. package/dist/esm/migrations/upgrade-two-dot-one.d.ts +7 -0
  296. package/dist/esm/migrations/upgrade-two-dot-one.js +35 -0
  297. package/dist/esm/migrations/upgrade-two-dot-one.js.map +1 -0
  298. package/dist/esm/migrations/upgrade-two-dot-seven.d.ts +23 -0
  299. package/dist/esm/migrations/upgrade-two-dot-seven.js +54 -0
  300. package/dist/esm/migrations/upgrade-two-dot-seven.js.map +1 -0
  301. package/dist/esm/migrations/upgrade-two-dot-six.d.ts +27 -0
  302. package/dist/esm/migrations/upgrade-two-dot-six.js +57 -0
  303. package/dist/esm/migrations/upgrade-two-dot-six.js.map +1 -0
  304. package/dist/esm/migrations/upgrade-two-dot-three.d.ts +23 -0
  305. package/dist/esm/migrations/upgrade-two-dot-three.js +51 -0
  306. package/dist/esm/migrations/upgrade-two-dot-three.js.map +1 -0
  307. package/dist/esm/migrations/upgrade-two-dot-two.d.ts +23 -0
  308. package/dist/esm/migrations/upgrade-two-dot-two.js +54 -0
  309. package/dist/esm/migrations/upgrade-two-dot-two.js.map +1 -0
  310. package/dist/esm/migrations/upgrade-two-dot-zero.d.ts +44 -0
  311. package/dist/esm/migrations/upgrade-two-dot-zero.js +88 -0
  312. package/dist/esm/migrations/upgrade-two-dot-zero.js.map +1 -0
  313. package/dist/esm/migrator.d.ts +25 -0
  314. package/dist/esm/migrator.js +71 -0
  315. package/dist/esm/migrator.js.map +1 -0
  316. package/dist/esm/resourceHelpers.d.ts +192 -0
  317. package/dist/esm/resourceHelpers.js +361 -0
  318. package/dist/esm/resourceHelpers.js.map +1 -0
  319. package/dist/esm/resources/add-resource.d.ts +38 -0
  320. package/dist/esm/resources/add-resource.js +79 -0
  321. package/dist/esm/resources/add-resource.js.map +1 -0
  322. package/dist/esm/resources/addMetadataFromBlob.d.ts +25 -0
  323. package/dist/esm/resources/addMetadataFromBlob.js +39 -0
  324. package/dist/esm/resources/addMetadataFromBlob.js.map +1 -0
  325. package/dist/esm/resources/convert-item-resource-to-storage-resource.d.ts +32 -0
  326. package/dist/esm/resources/convert-item-resource-to-storage-resource.js +66 -0
  327. package/dist/esm/resources/convert-item-resource-to-storage-resource.js.map +1 -0
  328. package/dist/esm/resources/convert-storage-resource-to-item-resource.d.ts +29 -0
  329. package/dist/esm/resources/convert-storage-resource-to-item-resource.js +66 -0
  330. package/dist/esm/resources/convert-storage-resource-to-item-resource.js.map +1 -0
  331. package/dist/esm/resources/copyAssociatedFiles.d.ts +79 -0
  332. package/dist/esm/resources/copyAssociatedFiles.js +339 -0
  333. package/dist/esm/resources/copyAssociatedFiles.js.map +1 -0
  334. package/dist/esm/resources/copyDataIntoItem.d.ts +34 -0
  335. package/dist/esm/resources/copyDataIntoItem.js +40 -0
  336. package/dist/esm/resources/copyDataIntoItem.js.map +1 -0
  337. package/dist/esm/resources/copyMetadataIntoItem.d.ts +27 -0
  338. package/dist/esm/resources/copyMetadataIntoItem.js +40 -0
  339. package/dist/esm/resources/copyMetadataIntoItem.js.map +1 -0
  340. package/dist/esm/resources/copyResourceIntoZip.d.ts +34 -0
  341. package/dist/esm/resources/copyResourceIntoZip.js +69 -0
  342. package/dist/esm/resources/copyResourceIntoZip.js.map +1 -0
  343. package/dist/esm/resources/copyZipIntoItem.d.ts +26 -0
  344. package/dist/esm/resources/copyZipIntoItem.js +49 -0
  345. package/dist/esm/resources/copyZipIntoItem.js.map +1 -0
  346. package/dist/esm/resources/createCopyResults.d.ts +25 -0
  347. package/dist/esm/resources/createCopyResults.js +32 -0
  348. package/dist/esm/resources/createCopyResults.js.map +1 -0
  349. package/dist/esm/resources/get-blob.d.ts +25 -0
  350. package/dist/esm/resources/get-blob.js +38 -0
  351. package/dist/esm/resources/get-blob.js.map +1 -0
  352. package/dist/esm/resources/getItemResourcesFilesFromPaths.d.ts +25 -0
  353. package/dist/esm/resources/getItemResourcesFilesFromPaths.js +45 -0
  354. package/dist/esm/resources/getItemResourcesFilesFromPaths.js.map +1 -0
  355. package/dist/esm/resources/getItemResourcesPaths.d.ts +27 -0
  356. package/dist/esm/resources/getItemResourcesPaths.js +76 -0
  357. package/dist/esm/resources/getItemResourcesPaths.js.map +1 -0
  358. package/dist/esm/resources/index.d.ts +30 -0
  359. package/dist/esm/resources/index.js +31 -0
  360. package/dist/esm/resources/index.js.map +1 -0
  361. package/dist/esm/resources/solution-resource.d.ts +35 -0
  362. package/dist/esm/resources/solution-resource.js +28 -0
  363. package/dist/esm/resources/solution-resource.js.map +1 -0
  364. package/dist/esm/resources/transform-resource-paths-to-solution-resources.d.ts +56 -0
  365. package/dist/esm/resources/transform-resource-paths-to-solution-resources.js +132 -0
  366. package/dist/esm/resources/transform-resource-paths-to-solution-resources.js.map +1 -0
  367. package/dist/esm/resources/update-resource.d.ts +27 -0
  368. package/dist/esm/resources/update-resource.js +48 -0
  369. package/dist/esm/resources/update-resource.js.map +1 -0
  370. package/dist/esm/restHelpers.d.ts +634 -0
  371. package/dist/esm/restHelpers.js +1943 -0
  372. package/dist/esm/restHelpers.js.map +1 -0
  373. package/dist/esm/restHelpersGet.d.ts +303 -0
  374. package/dist/esm/restHelpersGet.js +793 -0
  375. package/dist/esm/restHelpersGet.js.map +1 -0
  376. package/dist/esm/sharing/index.d.ts +16 -0
  377. package/dist/esm/sharing/index.js +17 -0
  378. package/dist/esm/sharing/index.js.map +1 -0
  379. package/dist/esm/sharing/share-item-to-groups.d.ts +26 -0
  380. package/dist/esm/sharing/share-item-to-groups.js +40 -0
  381. package/dist/esm/sharing/share-item-to-groups.js.map +1 -0
  382. package/dist/esm/templatization.d.ts +139 -0
  383. package/dist/esm/templatization.js +291 -0
  384. package/dist/esm/templatization.js.map +1 -0
  385. package/dist/esm/trackingHelpers.d.ts +115 -0
  386. package/dist/esm/trackingHelpers.js +200 -0
  387. package/dist/esm/trackingHelpers.js.map +1 -0
  388. package/dist/esm/velocityHelpers.d.ts +68 -0
  389. package/dist/esm/velocityHelpers.js +144 -0
  390. package/dist/esm/velocityHelpers.js.map +1 -0
  391. package/dist/esm/webtoolHelpers.d.ts +57 -0
  392. package/dist/esm/webtoolHelpers.js +95 -0
  393. package/dist/esm/webtoolHelpers.js.map +1 -0
  394. package/dist/esm/workflowHelpers.d.ts +112 -0
  395. package/dist/esm/workflowHelpers.js +270 -0
  396. package/dist/esm/workflowHelpers.js.map +1 -0
  397. package/dist/esm/workforceHelpers.d.ts +121 -0
  398. package/dist/esm/workforceHelpers.js +691 -0
  399. package/dist/esm/workforceHelpers.js.map +1 -0
  400. package/dist/esm/zip-utils.d.ts +85 -0
  401. package/dist/esm/zip-utils.js +142 -0
  402. package/dist/esm/zip-utils.js.map +1 -0
  403. package/dist/solution.js_commit.txt +7 -0
  404. package/package.json +2 -2
@@ -0,0 +1,1943 @@
1
+ /** @license
2
+ * Copyright 2018 Esri
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /**
17
+ * Provides common functions involving the arcgis-rest-js library.
18
+ *
19
+ * @module restHelpers
20
+ */
21
+ import { removeLayerOptimization, setDefaultSpatialReference, validateSpatialReferenceAndExtent, processContingentValues, } from "./featureServiceHelpers";
22
+ import { appendQueryParam, blobToJson, blobToText, checkUrlPathTermination, deleteProp, deleteProps, fail, getProp, getUniqueTitle, setCreateProp, } from "./generalHelpers";
23
+ import { restAddItemData as portalAddItemData, addItemRelationship, addItemResource, createFolder, createGroup, createItemInFolder, getItem, moveItem as portalMoveItem, restRemoveFolder as portalRemoveFolder, restRemoveGroup as portalRemoveGroup, removeGroupUsers as portalRemoveGroupUsers, restRemoveItem as portalRemoveItem, restSearchGroups as portalSearchGroups, restSearchItems as portalSearchItems, request, searchGroupContent, SearchQueryBuilder, setItemAccess, shareItemWithGroup, svcAdminAddToServiceDefinition, svcAdminCreateFeatureService, restUpdateItem as portalUpdateItem, restUpdateGroup as portalUpdateGroup, UserSession, } from "./arcgisRestJS";
24
+ import { createZip } from "./libConnectors";
25
+ import { getItemBase, getItemDataAsJson } from "./restHelpersGet";
26
+ import { getWorkforceDependencies, isWorkforceProject, getWorkforceServiceInfo } from "./workforceHelpers";
27
+ import { hasUnresolvedVariables, replaceInTemplate } from "./templatization";
28
+ import { isTrackingViewTemplate, setTrackingOptions } from "./trackingHelpers";
29
+ // ------------------------------------------------------------------------------------------------------------------ //
30
+ export function addItemData(id, data, authentication) {
31
+ const addDataOptions = {
32
+ id,
33
+ data,
34
+ authentication,
35
+ };
36
+ return portalAddItemData(addDataOptions);
37
+ }
38
+ /**
39
+ * Creates a UserSession via a function so that the global arcgisSolution variable can access authentication.
40
+ *
41
+ * @param options See https://esri.github.io/arcgis-rest-js/api/auth/IUserSessionOptions/
42
+ * @returns UserSession
43
+ */
44
+ export function getUserSession(options = {}) {
45
+ return new UserSession(options);
46
+ }
47
+ /**
48
+ * Adds a forward relationship between two items.
49
+ *
50
+ * @param originItemId Origin of relationship
51
+ * @param destinationItemId Destination of relationship
52
+ * @param relationshipType Type of relationship
53
+ * @param authentication Credentials for the request
54
+ * @returns A Promise to add item resources.
55
+ */
56
+ export function addForwardItemRelationship(originItemId, destinationItemId, relationshipType, authentication) {
57
+ return new Promise((resolve) => {
58
+ const requestOptions = {
59
+ originItemId,
60
+ destinationItemId,
61
+ relationshipType,
62
+ authentication,
63
+ };
64
+ addItemRelationship(requestOptions).then((response) => {
65
+ resolve({
66
+ success: response.success,
67
+ itemId: originItemId,
68
+ });
69
+ }, () => {
70
+ resolve({
71
+ success: false,
72
+ itemId: originItemId,
73
+ });
74
+ });
75
+ });
76
+ }
77
+ /**
78
+ * Adds forward relationships for an item.
79
+ *
80
+ * @param originItemId Origin of relationship
81
+ * @param destinationRelationships Destinations
82
+ * @param authentication Credentials for the request
83
+ * @returns A Promise to add item resources.
84
+ */
85
+ export function addForwardItemRelationships(originItemId, destinationRelationships, authentication) {
86
+ return new Promise((resolve) => {
87
+ // Set up relationships using updated relationship information
88
+ const relationshipPromises = new Array();
89
+ destinationRelationships.forEach((relationship) => {
90
+ relationship.relatedItemIds.forEach((relatedItemId) => {
91
+ relationshipPromises.push(addForwardItemRelationship(originItemId, relatedItemId, relationship.relationshipType, authentication));
92
+ });
93
+ });
94
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
95
+ Promise.all(relationshipPromises).then((responses) => resolve(responses));
96
+ });
97
+ }
98
+ /**
99
+ * Adds a token to the query parameters of a URL.
100
+ *
101
+ * @param url URL to use as base
102
+ * @param authentication Credentials to be used to generate token for URL
103
+ * @returns A promise that will resolve with the supplied URL with `token=<token>` added to its query params
104
+ * unless either the URL doesn't exist or the token can't be generated
105
+ */
106
+ export function addTokenToUrl(url, authentication) {
107
+ return new Promise((resolve) => {
108
+ if (!url || !authentication) {
109
+ resolve(url);
110
+ }
111
+ else {
112
+ authentication.getToken(url).then((token) => {
113
+ /* istanbul ignore else */
114
+ if (token) {
115
+ url = appendQueryParam(url, "token=" + token);
116
+ }
117
+ resolve(url);
118
+ }, () => resolve(url));
119
+ }
120
+ });
121
+ }
122
+ /**
123
+ * Calls addToDefinition for the service.
124
+ *
125
+ * Added retry due to some solutions failing to deploy in specific orgs/hives due to timeouts.
126
+ * On the first pass we will use the quicker sync request to add.
127
+ * If it fails we will use an async request that will avoid the timeout errors.
128
+ *
129
+ * @param url URL to use as base
130
+ * @param options the info to add to the services definition
131
+ * @param skipRetry a boolean to control if retry logic will be used. Defaults to false.
132
+ * @param useAsync a boolean to control if we will use an async request
133
+ * @returns A promise that will resolve when the request has completed
134
+ */
135
+ export function addToServiceDefinition(url, options, skipRetry = false, useAsync = false) {
136
+ /* istanbul ignore else */
137
+ if (useAsync) {
138
+ options.params = { ...options.params, async: true };
139
+ }
140
+ return new Promise((resolve, reject) => {
141
+ svcAdminAddToServiceDefinition(url, options).then((result) => {
142
+ checkRequestStatus(result, options.authentication).then(() => resolve(null), (e) => reject(fail(e)));
143
+ }, (e) => {
144
+ if (!skipRetry) {
145
+ addToServiceDefinition(url, options, true, true).then(() => resolve(null), (e) => reject(e));
146
+ }
147
+ else {
148
+ reject(fail(e));
149
+ }
150
+ });
151
+ });
152
+ }
153
+ /**
154
+ * When using an async request we need to poll the status url to know when the request has completed or failed.
155
+ *
156
+ * @param result the result returned from the addToDefinition request.
157
+ * This will contain a status url or the standard sync result.
158
+ * @param authentication Credentials to be used to generate token for URL
159
+ * @returns A promise that will resolve when the request has completed
160
+ */
161
+ export function checkRequestStatus(result, authentication) {
162
+ return new Promise((resolve, reject) => {
163
+ const url = result.statusURL || result.statusUrl;
164
+ if (url) {
165
+ const checkStatus = setInterval(() => {
166
+ request(url, { authentication }).then((r) => {
167
+ /* istanbul ignore else */
168
+ if (["completed", "success"].indexOf(r.status.toLowerCase()) > -1) {
169
+ clearInterval(checkStatus);
170
+ resolve();
171
+ }
172
+ else if (r.status.toLowerCase() === "failed") {
173
+ clearInterval(checkStatus);
174
+ reject(r);
175
+ }
176
+ }, (e) => {
177
+ clearInterval(checkStatus);
178
+ reject(e);
179
+ });
180
+ }, 2000);
181
+ }
182
+ else {
183
+ resolve();
184
+ }
185
+ });
186
+ }
187
+ /**
188
+ * Converts a general search into an ISearchOptions structure.
189
+ *
190
+ * @param search Search specified in one of three ways
191
+ * @returns Recast search
192
+ */
193
+ export function convertToISearchOptions(search) {
194
+ // Convert the search into an ISearchOptions
195
+ let searchOptions = {
196
+ q: "",
197
+ start: 1,
198
+ num: 100,
199
+ };
200
+ if (typeof search === "string") {
201
+ // Insert query into defaults
202
+ searchOptions.q = search;
203
+ }
204
+ else if (search instanceof SearchQueryBuilder) {
205
+ // Insert query into defaults
206
+ searchOptions.q = search.toParam();
207
+ }
208
+ else {
209
+ // search is ISearchOptions
210
+ searchOptions = {
211
+ ...searchOptions,
212
+ ...search, // request
213
+ };
214
+ }
215
+ // Remove the sortField if it's "relevance"; that's the default option and is not meant to be specified
216
+ if (searchOptions.sortField === "relevance") {
217
+ delete searchOptions.sortField;
218
+ }
219
+ return searchOptions;
220
+ }
221
+ /**
222
+ * Simple validate function to ensure all coordinates are numbers
223
+ * In some cases orgs can have null or undefined coordinate values associated with the org extent
224
+ *
225
+ * @param extent the extent to validate
226
+ * @returns the provided extent or a default global extent if some coordinates are not numbers
227
+ * @private
228
+ */
229
+ export function _validateExtent(extent) {
230
+ // in some cases orgs can have invalid extents defined
231
+ // this is a simple validate function that will ensure coordiantes are numbers
232
+ // using -179,-89,179,89 because the project call is returning "NaN" when using -180,-90,180,90
233
+ const hasInvalid = typeof extent.xmin !== "number" ||
234
+ typeof extent.xmax !== "number" ||
235
+ typeof extent.ymax !== "number" ||
236
+ typeof extent.ymin !== "number";
237
+ if (hasInvalid) {
238
+ extent.xmin = -179;
239
+ extent.xmax = 179;
240
+ extent.ymax = 89;
241
+ extent.ymin = -89;
242
+ extent.spatialReference = { wkid: 4326 };
243
+ }
244
+ return extent;
245
+ }
246
+ /**
247
+ * If the request to convert the extent fails it has commonly been due to an invalid extent.
248
+ * This function will first attempt to use the provided extent. If it fails it will default to
249
+ * the source items extent and if that fails it will then use a default global extent.
250
+ *
251
+ * @param extent the extent to convert
252
+ * @param fallbackExtent the extent to convert if the main extent does not project to the outSR
253
+ * @param outSR the spatial reference to project to
254
+ * @param geometryServiceUrl the service url for the geometry service to use
255
+ * @param authentication the credentials for the requests
256
+ * @returns the extent projected to the provided spatial reference
257
+ * or the world extent projected to the provided spatial reference
258
+ * @private
259
+ */
260
+ export function convertExtentWithFallback(extent, fallbackExtent, outSR, geometryServiceUrl, authentication) {
261
+ return new Promise((resolve, reject) => {
262
+ const defaultExtent = {
263
+ xmin: -179,
264
+ xmax: 179,
265
+ ymin: -89,
266
+ ymax: 89,
267
+ spatialReference: { wkid: 4326 },
268
+ };
269
+ convertExtent(_validateExtent(extent), outSR, geometryServiceUrl, authentication).then((extentResponse) => {
270
+ // in some cases project will complete successfully but return "NaN" values
271
+ // check for this and call convert again if it does
272
+ const extentResponseString = JSON.stringify(extentResponse);
273
+ const validatedExtent = JSON.stringify(_validateExtent(extentResponse));
274
+ if (extentResponseString === validatedExtent) {
275
+ resolve(extentResponse);
276
+ }
277
+ else {
278
+ convertExtent(fallbackExtent || defaultExtent, outSR, geometryServiceUrl, authentication).then(resolve, (e) => reject(fail(e)));
279
+ }
280
+ },
281
+ // if convert fails try again with default global extent
282
+ () => {
283
+ convertExtent(defaultExtent, outSR, geometryServiceUrl, authentication).then(resolve, (e) => reject(fail(e)));
284
+ });
285
+ });
286
+ }
287
+ /**
288
+ * Converts an extent to a specified spatial reference.
289
+ *
290
+ * @param extent Extent object to check and (possibly) to project
291
+ * @param outSR Desired spatial reference
292
+ * @param geometryServiceUrl Path to geometry service providing `findTransformations` and `project` services
293
+ * @param authentication Credentials for the request
294
+ * @returns Original extent if it's already using outSR or the extents projected into the outSR
295
+ */
296
+ export function convertExtent(extent, outSR, geometryServiceUrl, authentication) {
297
+ const _requestOptions = { authentication };
298
+ return new Promise((resolve, reject) => {
299
+ if (extent.spatialReference.wkid === outSR?.wkid || !outSR) {
300
+ resolve(extent);
301
+ }
302
+ else {
303
+ _requestOptions.params = {
304
+ f: "json",
305
+ inSR: extent.spatialReference.wkid,
306
+ outSR: outSR.wkid,
307
+ extentOfInterest: JSON.stringify(extent),
308
+ };
309
+ request(checkUrlPathTermination(geometryServiceUrl) + "findTransformations", _requestOptions).then((response) => {
310
+ const transformations = response && response.transformations ? response.transformations : undefined;
311
+ let transformation;
312
+ if (transformations && transformations.length > 0) {
313
+ // if a forward single transformation is found use that...otherwise check for and use composite
314
+ transformation = transformations[0].wkid
315
+ ? transformations[0].wkid
316
+ : transformations[0].geoTransforms
317
+ ? transformations[0]
318
+ : undefined;
319
+ }
320
+ _requestOptions.params = {
321
+ f: "json",
322
+ outSR: outSR.wkid,
323
+ inSR: extent.spatialReference.wkid,
324
+ geometries: {
325
+ geometryType: "esriGeometryPoint",
326
+ geometries: [
327
+ { x: extent.xmin, y: extent.ymin },
328
+ { x: extent.xmax, y: extent.ymax },
329
+ ],
330
+ },
331
+ transformation: transformation,
332
+ };
333
+ request(checkUrlPathTermination(geometryServiceUrl) + "project", _requestOptions).then((projectResponse) => {
334
+ const projectGeom = projectResponse.geometries.length === 2 ? projectResponse.geometries : undefined;
335
+ if (projectGeom) {
336
+ resolve({
337
+ xmin: projectGeom[0].x,
338
+ ymin: projectGeom[0].y,
339
+ xmax: projectGeom[1].x,
340
+ ymax: projectGeom[1].y,
341
+ spatialReference: outSR,
342
+ });
343
+ }
344
+ else {
345
+ resolve(undefined);
346
+ }
347
+ }, (e) => reject(fail(e)));
348
+ }, (e) => reject(fail(e)));
349
+ }
350
+ });
351
+ }
352
+ /**
353
+ * Publishes a feature service as an AGOL item; it does not include its layers and tables
354
+ *
355
+ * @param newItemTemplate Template of item to be created
356
+ * @param authentication Credentials for the request
357
+ * @param templateDictionary Hash of facts: org URL, adlib replacements, user; .user.folders property contains a list
358
+ * @returns A promise that will resolve with an object reporting success and the Solution id
359
+ */
360
+ export function createFeatureService(newItemTemplate, authentication, templateDictionary) {
361
+ return new Promise((resolve, reject) => {
362
+ // Create item
363
+ _getCreateServiceOptions(newItemTemplate, authentication, templateDictionary).then((createOptions) => {
364
+ svcAdminCreateFeatureService(createOptions).then((createResponse) => {
365
+ // Federated servers may have inconsistent casing, so lowerCase it
366
+ createResponse.encodedServiceURL = _lowercaseDomain(createResponse.encodedServiceURL);
367
+ createResponse.serviceurl = _lowercaseDomain(createResponse.serviceurl);
368
+ resolve(createResponse);
369
+ }, (e) => reject(fail(e)));
370
+ }, (e) => reject(fail(e)));
371
+ });
372
+ }
373
+ /**
374
+ * Publishes an item and its data, metadata, and resources as an AGOL item.
375
+ *
376
+ * @param itemInfo Item's `item` section
377
+ * @param folderId Id of folder to receive item; null indicates that the item goes into the root
378
+ * folder; ignored for Group item type
379
+ * @param destinationAuthentication Credentials for for requests to where the item is to be created
380
+ * @param itemThumbnailUrl URL to image to use for item thumbnail
381
+ * @param itemThumbnailAuthentication Credentials for requests to the thumbnail source
382
+ * @param dataFile Item's `data` section
383
+ * @param metadataFile Item's metadata file
384
+ * @param resourcesFiles Item's resources
385
+ * @param access Access to set for item: "public", "org", "private"
386
+ * @returns A promise that will resolve with an object reporting success or failure and the Solution id
387
+ */
388
+ export function createFullItem(itemInfo, folderId, destinationAuthentication, itemThumbnailUrl, itemThumbnailAuthentication, dataFile, metadataFile, resourcesFiles, access = "private") {
389
+ return new Promise((resolve, reject) => {
390
+ // Create item
391
+ const createOptions = {
392
+ item: {
393
+ ...itemInfo,
394
+ },
395
+ folderId,
396
+ authentication: destinationAuthentication,
397
+ };
398
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
399
+ addTokenToUrl(itemThumbnailUrl, itemThumbnailAuthentication).then((updatedThumbnailUrl) => {
400
+ /* istanbul ignore else */
401
+ if (updatedThumbnailUrl) {
402
+ createOptions.item.thumbnailUrl = appendQueryParam(updatedThumbnailUrl, "w=400");
403
+ }
404
+ createItemInFolder(createOptions).then((createResponse) => {
405
+ if (createResponse.success) {
406
+ let accessDef;
407
+ // Set access if it is not AGOL default
408
+ // Set the access manually since the access value in createItem appears to be ignored
409
+ // Need to run serially; will not work reliably if done in parallel with adding the data section
410
+ if (access !== "private") {
411
+ const accessOptions = {
412
+ id: createResponse.id,
413
+ access: access === "public" ? "public" : "org",
414
+ authentication: destinationAuthentication,
415
+ };
416
+ accessDef = setItemAccess(accessOptions);
417
+ }
418
+ else {
419
+ accessDef = Promise.resolve({
420
+ itemId: createResponse.id,
421
+ });
422
+ }
423
+ // Now add attached items
424
+ accessDef.then(() => {
425
+ const updateDefs = [];
426
+ // Add the data section
427
+ if (dataFile) {
428
+ updateDefs.push(_addItemDataFile(createResponse.id, dataFile, destinationAuthentication));
429
+ }
430
+ // Add the resources via a zip because AGO sometimes loses resources if many are added at the
431
+ // same time to the same item
432
+ if (Array.isArray(resourcesFiles) && resourcesFiles.length > 0) {
433
+ updateDefs.push(new Promise((rsrcResolve, rsrcReject) => {
434
+ createZip("resources.zip", resourcesFiles).then((zipfile) => {
435
+ const addResourceOptions = {
436
+ id: createResponse.id,
437
+ resource: zipfile,
438
+ authentication: destinationAuthentication,
439
+ params: {
440
+ archive: true,
441
+ },
442
+ };
443
+ addItemResource(addResourceOptions).then(rsrcResolve, rsrcReject);
444
+ }, rsrcReject);
445
+ }));
446
+ }
447
+ // Add the metadata section
448
+ if (metadataFile) {
449
+ updateDefs.push(_addItemMetadataFile(createResponse.id, metadataFile, destinationAuthentication));
450
+ }
451
+ // Wait until all adds are done
452
+ Promise.all(updateDefs).then(() => resolve(createResponse), (e) => reject(fail(e)));
453
+ }, (e) => reject(fail(e)));
454
+ }
455
+ else {
456
+ reject(fail());
457
+ }
458
+ }, (e) => reject(fail(e)));
459
+ });
460
+ });
461
+ }
462
+ /**
463
+ * Publishes an item and its data as an AGOL item.
464
+ *
465
+ * @param itemInfo Item's `item` section
466
+ * @param dataInfo Item's `data` section
467
+ * @param authentication Credentials for the request
468
+ * @param folderId Id of folder to receive item; null indicates that the item goes into the root
469
+ * folder; ignored for Group item type
470
+ * @param access Access to set for item: "public", "org", "private"
471
+ * @returns A promise that will resolve with an object reporting success and the Solution id
472
+ */
473
+ export function createItemWithData(itemInfo, dataInfo, authentication, folderId, access = "private") {
474
+ return new Promise((resolve, reject) => {
475
+ // Create item
476
+ const createOptions = {
477
+ item: {
478
+ title: "_",
479
+ ...itemInfo,
480
+ data: dataInfo,
481
+ },
482
+ folderId,
483
+ authentication: authentication,
484
+ };
485
+ if (itemInfo.thumbnail) {
486
+ createOptions.params = {
487
+ // Pass thumbnail file in via params because item property is serialized, which discards a blob
488
+ thumbnail: itemInfo.thumbnail,
489
+ };
490
+ delete createOptions.item.thumbnail;
491
+ }
492
+ createItemInFolder(createOptions).then((createResponse) => {
493
+ if (createResponse.success) {
494
+ if (access !== "private") {
495
+ // Set access if it is not AGOL default
496
+ // Set the access manually since the access value in createItem appears to be ignored
497
+ const accessOptions = {
498
+ id: createResponse.id,
499
+ access: access === "public" ? "public" : "org",
500
+ authentication: authentication,
501
+ };
502
+ setItemAccess(accessOptions).then(() => {
503
+ resolve({
504
+ folder: createResponse.folder,
505
+ id: createResponse.id,
506
+ success: true,
507
+ });
508
+ }, (e) => reject(fail(e)));
509
+ }
510
+ else {
511
+ resolve({
512
+ folder: createResponse.folder,
513
+ id: createResponse.id,
514
+ success: true,
515
+ });
516
+ }
517
+ }
518
+ else {
519
+ reject(fail());
520
+ }
521
+ }, (e) => reject(fail(e)));
522
+ });
523
+ }
524
+ /**
525
+ * Creates a folder using a numeric suffix to ensure uniqueness if necessary.
526
+ *
527
+ * @param title Folder title, used as-is if possible and with suffix otherwise
528
+ * @param templateDictionary Hash of facts: org URL, adlib replacements, user; .user.folders property contains a list
529
+ * of known folder names; function updates list with existing names not yet known, and creates .user.folders if it
530
+ * doesn't exist in the dictionary
531
+ * @param authentication Credentials for creating folder
532
+ * @returns Id of created folder
533
+ */
534
+ export function createUniqueFolder(title, templateDictionary, authentication) {
535
+ return new Promise((resolve, reject) => {
536
+ // Get a title that is not already in use
537
+ const folderTitle = getUniqueTitle(title, templateDictionary, "user.folders");
538
+ const folderCreationParam = {
539
+ title: folderTitle,
540
+ authentication: authentication,
541
+ };
542
+ createFolder(folderCreationParam).then((ok) => resolve(ok), (err) => {
543
+ // If the name already exists, we'll try again
544
+ const errorDetails = getProp(err, "response.error.details");
545
+ if (Array.isArray(errorDetails) && errorDetails.length > 0) {
546
+ const nameNotAvailMsg = "Folder title '" + folderTitle + "' not available.";
547
+ if (errorDetails.indexOf(nameNotAvailMsg) >= 0) {
548
+ // Create the user.folders property if it doesn't exist
549
+ /* istanbul ignore else */
550
+ if (!getProp(templateDictionary, "user.folders")) {
551
+ setCreateProp(templateDictionary, "user.folders", []);
552
+ }
553
+ templateDictionary.user.folders.push({
554
+ title: folderTitle,
555
+ });
556
+ createUniqueFolder(title, templateDictionary, authentication).then(resolve, reject);
557
+ }
558
+ else {
559
+ reject(err);
560
+ }
561
+ }
562
+ else {
563
+ // Otherwise, error out
564
+ reject(err);
565
+ }
566
+ });
567
+ });
568
+ }
569
+ /**
570
+ * Creates a group using numeric suffix to ensure uniqueness.
571
+ *
572
+ * @param title Group title, used as-is if possible and with suffix otherwise
573
+ * @param templateDictionary Hash of facts: org URL, adlib replacements, user
574
+ * @param authentication Credentials for creating group
575
+ * @param owner Optional arg for the Tracking owner
576
+ * If the tracking owner is not the one deploying the solution
577
+ * tracker groups will be created under the deployment user but
578
+ * will be reassigned to the tracking owner.
579
+ * @returns Information about created group
580
+ */
581
+ export function createUniqueGroup(title, groupItem, templateDictionary, authentication, owner) {
582
+ return new Promise((resolve, reject) => {
583
+ let groupsPromise;
584
+ // when working with tracker we need to consider the groups of the deploying user as well as the groups
585
+ // of the tracking user...must be unique for both
586
+ if (owner && owner !== authentication.username) {
587
+ groupsPromise = searchAllGroups(`(owner:${owner}) orgid:${templateDictionary.organization.id}`, authentication);
588
+ }
589
+ else {
590
+ groupsPromise = Promise.resolve([]);
591
+ }
592
+ // first get the tracker owner groups
593
+ groupsPromise.then((groups) => {
594
+ templateDictionary["allGroups"] = groups.concat(getProp(templateDictionary, "user.groups"));
595
+ // Get a title that is not already in use
596
+ groupItem.title = getUniqueTitle(title, templateDictionary, "allGroups");
597
+ const groupCreationParam = {
598
+ group: groupItem,
599
+ authentication: authentication,
600
+ };
601
+ createGroup(groupCreationParam).then(resolve, (err) => {
602
+ // If the name already exists, we'll try again
603
+ const errorDetails = getProp(err, "response.error.details");
604
+ if (Array.isArray(errorDetails) && errorDetails.length > 0) {
605
+ const nameNotAvailMsg = "You already have a group named '" + groupItem.title + "'. Try a different name.";
606
+ if (errorDetails.indexOf(nameNotAvailMsg) >= 0) {
607
+ templateDictionary.user.groups.push({
608
+ title: groupItem.title,
609
+ });
610
+ createUniqueGroup(title, groupItem, templateDictionary, authentication).then(resolve, reject);
611
+ }
612
+ else {
613
+ reject(err);
614
+ }
615
+ }
616
+ else {
617
+ // Otherwise, error out
618
+ reject(err);
619
+ }
620
+ });
621
+ }, (e) => reject(e));
622
+ });
623
+ }
624
+ /**
625
+ * Gets the ids of the dependencies of an AGOL feature service item.
626
+ * Dependencies will only exist when the service is a view.
627
+ *
628
+ * @param itemTemplate Template of item to be created
629
+ * @param authentication Credentials for the request
630
+ * @returns A promise that will resolve a list of dependencies
631
+ */
632
+ export function extractDependencies(itemTemplate, authentication) {
633
+ const dependencies = [];
634
+ return new Promise((resolve, reject) => {
635
+ // Get service dependencies when the item is a view
636
+ // This step is skipped for tracker views as they will already have a source service in the org
637
+ if (itemTemplate.properties.service.isView && itemTemplate.item.url && !isTrackingViewTemplate(itemTemplate)) {
638
+ request(checkUrlPathTermination(itemTemplate.item.url) + "sources?f=json", {
639
+ authentication: authentication,
640
+ }).then((response) => {
641
+ /* istanbul ignore else */
642
+ if (response && response.services) {
643
+ response.services.forEach((layer) => {
644
+ dependencies.push({
645
+ id: layer.serviceItemId,
646
+ name: layer.name,
647
+ });
648
+ });
649
+ }
650
+ resolve(dependencies);
651
+ }, (e) => reject(fail(e)));
652
+ }
653
+ else if (isWorkforceProject(itemTemplate)) {
654
+ resolve(getWorkforceDependencies(itemTemplate, dependencies));
655
+ }
656
+ else {
657
+ resolve(dependencies);
658
+ }
659
+ });
660
+ }
661
+ /**
662
+ * Get json info for the services layers
663
+ *
664
+ * @param serviceUrl the url for the service
665
+ * @param layerList list of base layer info
666
+ * @param authentication Credentials for the request
667
+ * @returns A promise that will resolve a list of dependencies
668
+ */
669
+ export function getLayers(serviceUrl, layerList, authentication) {
670
+ return new Promise((resolve, reject) => {
671
+ if (layerList.length === 0) {
672
+ resolve([]);
673
+ }
674
+ // get the admin URL
675
+ serviceUrl = serviceUrl.replace("/rest/services", "/rest/admin/services");
676
+ const requestsDfd = [];
677
+ layerList.forEach((layer) => {
678
+ const requestOptions = {
679
+ authentication: authentication,
680
+ };
681
+ requestsDfd.push(request(checkUrlPathTermination(serviceUrl) + layer["id"] + "?f=json", requestOptions));
682
+ });
683
+ // Wait until all layers are heard from
684
+ Promise.all(requestsDfd).then((layers) => resolve(layers), (e) => reject(fail(e)));
685
+ });
686
+ }
687
+ /**
688
+ * Add additional options to a layers definition.
689
+ *
690
+ * @param args The IPostProcessArgs for the request(s)
691
+ * @param isPortal boolean to indicate if we are deploying to portal
692
+ *
693
+ * @returns An array of update instructions
694
+ * @private
695
+ */
696
+ export function getLayerUpdates(args, isPortal) {
697
+ const adminUrl = args.itemTemplate.item.url.replace("rest/services", "rest/admin/services");
698
+ const updates = [];
699
+ const refresh = _getUpdate(adminUrl, null, null, args, "refresh");
700
+ updates.push(refresh);
701
+ Object.keys(args.objects).forEach((id) => {
702
+ const obj = Object.assign({}, args.objects[id]);
703
+ // These properties cannot be set in the update definition when working with portal
704
+ if (isPortal) {
705
+ deleteProps(obj, ["type", "id", "relationships", "sourceServiceFields"]);
706
+ }
707
+ // handle definition deletes
708
+ // removes previous editFieldsInfo fields if their names were changed
709
+ if (obj.hasOwnProperty("deleteFields")) {
710
+ updates.push(_getUpdate(adminUrl, id, obj, args, "delete"));
711
+ deleteProp(obj, "deleteFields");
712
+ updates.push(_getUpdate(adminUrl, null, null, args, "refresh"));
713
+ }
714
+ });
715
+ const subtypeUpdates = _getSubtypeUpdates({
716
+ message: "add subtype updates",
717
+ objects: args.objects,
718
+ itemTemplate: args.itemTemplate,
719
+ authentication: args.authentication,
720
+ });
721
+ /* istanbul ignore else */
722
+ if (subtypeUpdates.length > 0 && isPortal) {
723
+ subtypeUpdates.forEach((subtypeUpdate) => {
724
+ updates.push(_getUpdate(adminUrl + subtypeUpdate.id, null, { subtypeField: subtypeUpdate.subtypeField }, args, "update"));
725
+ updates.push(_getUpdate(adminUrl + subtypeUpdate.id, null, { defaultSubtypeCode: subtypeUpdate.defaultSubtypeCode }, args, "update"));
726
+ updates.push(_getUpdate(adminUrl + subtypeUpdate.id, null, { subtypes: subtypeUpdate.subtypes }, args, "add"));
727
+ });
728
+ }
729
+ // issue: #706
730
+ // Add source service relationships
731
+ // views will now always add all layers in a single call and will inherit the relationships from the source service
732
+ if (!args.itemTemplate.properties.service.isView) {
733
+ const relUpdates = _getRelationshipUpdates({
734
+ message: "updated layer relationships",
735
+ objects: args.objects,
736
+ itemTemplate: args.itemTemplate,
737
+ authentication: args.authentication,
738
+ });
739
+ // issue: #724
740
+ // In portal the order the relationships are added needs to follow the layer order
741
+ // otherwise the relationship IDs will be reset
742
+ relUpdates.layers = _sortRelationships(args.itemTemplate.properties.layers, args.itemTemplate.properties.tables, relUpdates);
743
+ /* istanbul ignore else */
744
+ if (relUpdates.layers.length > 0) {
745
+ updates.push(_getUpdate(adminUrl, null, relUpdates, args, "add"));
746
+ updates.push(refresh);
747
+ }
748
+ // handle contingent values
749
+ const contingentValuesUpdates = _getContingentValuesUpdates({
750
+ message: "add layer contingent values",
751
+ objects: args.objects,
752
+ itemTemplate: args.itemTemplate,
753
+ authentication: args.authentication,
754
+ });
755
+ /* istanbul ignore else */
756
+ if (contingentValuesUpdates.length > 0) {
757
+ contingentValuesUpdates.forEach((conUpdate) => {
758
+ updates.push(_getUpdate(adminUrl + conUpdate.id, null, conUpdate.contingentValues, args, "add"));
759
+ });
760
+ }
761
+ }
762
+ // issue: https://devtopia.esri.com/WebGIS/solution-deployment-apps/issues/273
763
+ // For portal only...add specific indexes with existing supplementary addToDefinition call if it exists
764
+ // or with a new addToDefinition call if one doesn't already exist
765
+ if (isPortal) {
766
+ Object.keys(args.objects).forEach((id) => {
767
+ const obj = Object.assign({}, args.objects[id]);
768
+ let update;
769
+ if (Array.isArray(obj.indexes) && obj.indexes.length > 0) {
770
+ const layerHasExistingAdd = updates.some((u) => {
771
+ if (u.url.indexOf(`${id}/addToDefinition`) > -1) {
772
+ update = u;
773
+ return true;
774
+ }
775
+ });
776
+ if (layerHasExistingAdd) {
777
+ // append to existing addToDef
778
+ update.params.addToDefinition = {
779
+ ...update.params.addToDefinition,
780
+ indexes: obj.indexes,
781
+ };
782
+ }
783
+ else {
784
+ // create new addToDef
785
+ updates.push(_getUpdate(checkUrlPathTermination(adminUrl) + id, null, { indexes: obj.indexes }, args, "add"));
786
+ }
787
+ }
788
+ });
789
+ }
790
+ return updates.length === 1 ? [] : updates;
791
+ }
792
+ /**
793
+ * Moves an AGO item to a specified folder.
794
+ *
795
+ * @param itemId Id of item to move
796
+ * @param folderId Id of folder to receive item
797
+ * @param authentication Credentials for the request
798
+ * @returns A Promise resolving to the results of the move
799
+ */
800
+ export async function moveItemToFolder(itemId, folderId, authentication) {
801
+ const moveOptions = {
802
+ itemId,
803
+ folderId,
804
+ authentication,
805
+ };
806
+ return portalMoveItem(moveOptions);
807
+ }
808
+ /**
809
+ * Moves a list of AGO items to a specified folder.
810
+ *
811
+ * @param itemIds Ids of items to move
812
+ * @param folderId Id of folder to receive item
813
+ * @param authentication Credentials for the request
814
+ * @returns A Promise resolving to the results of the moves
815
+ */
816
+ export async function moveItemsToFolder(itemIds, folderId, authentication) {
817
+ const movePromises = new Array();
818
+ itemIds.forEach((itemId) => {
819
+ movePromises.push(moveItemToFolder(itemId, folderId, authentication));
820
+ });
821
+ return Promise.all(movePromises);
822
+ }
823
+ /**
824
+ * Sorts relationships based on order of supporting layers and tables in the service definition
825
+ *
826
+ * @param layers the layers from the service
827
+ * @param tables the tables from the service
828
+ * @param relUpdates the relationships to add for the service
829
+ *
830
+ * @returns An array with relationships that have been sorted
831
+ * @private
832
+ */
833
+ export function _sortRelationships(layers, tables, relUpdates) {
834
+ const ids = [].concat(layers.map((l) => l.id), tables.map((t) => t.id));
835
+ // In portal the order the relationships are added needs to follow the layer order
836
+ // otherwise the relationship IDs will be reset
837
+ const _relUpdateLayers = [];
838
+ ids.forEach((id) => {
839
+ relUpdates.layers.some((relUpdate) => {
840
+ if (id === relUpdate.id) {
841
+ _relUpdateLayers.push(relUpdate);
842
+ return true;
843
+ }
844
+ else {
845
+ return false;
846
+ }
847
+ });
848
+ });
849
+ return _relUpdateLayers;
850
+ }
851
+ /**
852
+ * Add additional options to a layers definition
853
+ *
854
+ * Added retry due to some solutions failing to deploy in specific orgs/hives
855
+ *
856
+ *
857
+ * @param Update will contain either add, update, or delete from service definition call
858
+ * @param skipRetry defaults to false. when true the retry logic will be ignored
859
+ * @returns A promise that will resolve when service definition call has completed
860
+ * @private
861
+ */
862
+ /* istanbul ignore else */
863
+ export function getRequest(update, skipRetry = false, useAsync = false, isPortal = false) {
864
+ return new Promise((resolve, reject) => {
865
+ const options = {
866
+ params: update.params,
867
+ authentication: update.args.authentication,
868
+ };
869
+ /* istanbul ignore else */
870
+ if ((useAsync && update.url.indexOf("addToDefinition") > -1) ||
871
+ update.url.indexOf("updateDefinition") > -1 ||
872
+ update.url.indexOf("deleteFromDefinition") > -1) {
873
+ options.params = { ...options.params, async: true };
874
+ }
875
+ request(update.url, options).then((result) => {
876
+ checkRequestStatus(result, options.authentication).then(() => resolve(null), (e) => reject(fail(e)));
877
+ }, (e) => {
878
+ if (!skipRetry) {
879
+ getRequest(update, true, true, isPortal).then(() => resolve(), (e) => reject(e));
880
+ }
881
+ else {
882
+ reject(e);
883
+ }
884
+ });
885
+ });
886
+ }
887
+ /**
888
+ * Fills in missing data, including full layer and table definitions, in a feature services' definition.
889
+ *
890
+ * @param itemTemplate Feature service item, data, dependencies definition to be modified
891
+ * @param authentication Credentials for the request to AGOL
892
+ * @returns A promise that will resolve when fullItem has been updated
893
+ * @private
894
+ */
895
+ export function getServiceLayersAndTables(itemTemplate, authentication) {
896
+ return new Promise((resolve, reject) => {
897
+ // To have enough information for reconstructing the service, we'll supplement
898
+ // the item and data sections with sections for the service, full layers, and
899
+ // full tables
900
+ // Extra steps must be taken for workforce version 2
901
+ const isWorkforceService = isWorkforceProject(itemTemplate);
902
+ // Get the service description
903
+ if (itemTemplate.item.url) {
904
+ getFeatureServiceProperties(itemTemplate.item.url, authentication, isWorkforceService).then((properties) => {
905
+ itemTemplate.properties = properties;
906
+ resolve(itemTemplate);
907
+ }, (e) => reject(fail(e)));
908
+ }
909
+ else {
910
+ resolve(itemTemplate);
911
+ }
912
+ });
913
+ }
914
+ /**
915
+ * Get service properties for the given url and update key props
916
+ *
917
+ * @param serviceUrl the feature service url
918
+ * @param authentication Credentials for the request to AGOL
919
+ * @param workforceService boolean to indicate if extra workforce service steps should be handled
920
+ * @returns A promise that will resolve with the service properties
921
+ * @private
922
+ */
923
+ export function getFeatureServiceProperties(serviceUrl, authentication, workforceService = false) {
924
+ return new Promise((resolve, reject) => {
925
+ const properties = {
926
+ service: {},
927
+ layers: [],
928
+ tables: [],
929
+ };
930
+ // get the admin URL
931
+ serviceUrl = serviceUrl.replace("/rest/services", "/rest/admin/services");
932
+ // Get the service description
933
+ request(serviceUrl + "?f=json", {
934
+ authentication: authentication,
935
+ }).then((serviceData) => {
936
+ properties.service = _parseAdminServiceData(serviceData);
937
+ // Copy cacheMaxAge to top level so that AGO sees it when deploying the service
938
+ // serviceData may have set it if there isn't an adminServiceInfo
939
+ /* istanbul ignore else */
940
+ if (serviceData.adminServiceInfo?.cacheMaxAge) {
941
+ properties.service.cacheMaxAge = serviceData.adminServiceInfo.cacheMaxAge;
942
+ }
943
+ // Move the layers and tables out of the service's data section
944
+ /* istanbul ignore else */
945
+ if (serviceData.layers) {
946
+ properties.layers = serviceData.layers;
947
+ // Fill in properties that the service layer doesn't provide
948
+ // and remove properties that should not exist in the template
949
+ properties.layers.forEach((layer) => {
950
+ layer.serviceItemId = properties.service.serviceItemId;
951
+ layer.extent = null;
952
+ removeLayerOptimization(layer);
953
+ });
954
+ }
955
+ delete serviceData.layers;
956
+ /* istanbul ignore else */
957
+ if (serviceData.tables) {
958
+ properties.tables = serviceData.tables;
959
+ // Fill in properties that the service layer doesn't provide
960
+ properties.tables.forEach((table) => {
961
+ table.serviceItemId = properties.service.serviceItemId;
962
+ table.extent = null;
963
+ });
964
+ }
965
+ delete serviceData.tables;
966
+ // Ensure solution items have unique indexes on relationship key fields
967
+ _updateIndexesForRelationshipKeyFields(properties);
968
+ processContingentValues(properties, serviceUrl, authentication).then(() => {
969
+ if (workforceService) {
970
+ getWorkforceServiceInfo(properties, serviceUrl, authentication).then(resolve, reject);
971
+ }
972
+ else {
973
+ resolve(properties);
974
+ }
975
+ }, (e) => reject(fail(e)));
976
+ }, (e) => reject(fail(e)));
977
+ });
978
+ }
979
+ /**
980
+ * Fetches the configuration of a workflow.
981
+ *
982
+ * @param itemId Id of the workflow item
983
+ * @param workflowBaseUrl URL of the workflow manager, e.g., "https://workflow.arcgis.com/orgId"
984
+ * @param authentication Credentials for the request to AGOL
985
+ * @returns Promise resolving with the workflow configuration in a zip file
986
+ * @throws {WorkflowJsonExceptionDTO} if request to workflow manager fails
987
+ */
988
+ export async function getWorkflowConfigurationZip(itemId, workflowBaseUrl, authentication) {
989
+ const url = `${workflowBaseUrl}/admin/${itemId}/export`;
990
+ return request(url, {
991
+ authentication,
992
+ headers: {
993
+ "Accept": "application/octet-stream",
994
+ "Authorization": `Bearer ${authentication.token}`,
995
+ "X-Esri-Authorization": `Bearer ${authentication.token}`,
996
+ },
997
+ params: {
998
+ f: "zip",
999
+ },
1000
+ });
1001
+ }
1002
+ /**
1003
+ * Sets the configuration of a workflow.
1004
+ *
1005
+ * @param itemId Id of the workflow item
1006
+ * @param configurationZipFile Configuration files in a zip file
1007
+ * @param workflowBaseUrl URL of the workflow manager, e.g., "https://workflow.arcgis.com/orgId"
1008
+ * @param authentication Credentials for the request to AGOL
1009
+ * @returns Promise resolving with the workflow configuration in a zip file
1010
+ * @throws {WorkflowJsonExceptionDTO} if request to workflow manager fails
1011
+ */
1012
+ export async function setWorkflowConfigurationZip(itemId, configurationZipFile, workflowBaseUrl, authentication) {
1013
+ const url = `${workflowBaseUrl}/admin/${itemId}/import`;
1014
+ return request(url, {
1015
+ authentication,
1016
+ headers: {
1017
+ "Accept": "application/octet-stream",
1018
+ "Authorization": `Bearer ${authentication.token}`,
1019
+ "X-Esri-Authorization": `Bearer ${authentication.token}`,
1020
+ },
1021
+ params: {
1022
+ file: configurationZipFile,
1023
+ },
1024
+ });
1025
+ }
1026
+ /**
1027
+ * Parses the layers array and will filter subsets of Layers and Tables
1028
+ * Layers and Tables are both returned in the layers array when we access a feature service from the admin api.
1029
+ *
1030
+ * @param adminData The data of the feature service
1031
+ * @returns A mutated version of the provided adminData
1032
+ * @private
1033
+ */
1034
+ export function _parseAdminServiceData(adminData) {
1035
+ const layers = adminData.layers || [];
1036
+ const tables = adminData.tables || [];
1037
+ setCreateProp(adminData, "layers", layers.filter((l) => l.type === "Feature Layer"));
1038
+ // TODO understand if the concat is necessary.
1039
+ // Not sure if the admin api will ever actually return a tables collection here.
1040
+ setCreateProp(adminData, "tables", tables.concat(layers.filter((l) => l.type === "Table")));
1041
+ return adminData;
1042
+ }
1043
+ /**
1044
+ * livingatlas designation test.
1045
+ * These layers should not be templatized or depolyed
1046
+ *
1047
+ * @param groupDesignations the items group designations to evaluate
1048
+ * @returns A boolean indicating if the invalid designation is found in the item info
1049
+ */
1050
+ export function hasInvalidGroupDesignations(groupDesignations) {
1051
+ const invalidGroupDesignations = ["livingatlas"];
1052
+ return groupDesignations ? invalidGroupDesignations.indexOf(groupDesignations) > -1 : false;
1053
+ }
1054
+ /**
1055
+ * Removes a folder from AGO.
1056
+ *
1057
+ * @param folderId Id of a folder to delete
1058
+ * @param authentication Credentials for the request to AGO
1059
+ * @returns A promise that will resolve with the result of the request
1060
+ */
1061
+ export function removeFolder(folderId, authentication) {
1062
+ return new Promise((resolve, reject) => {
1063
+ const requestOptions = {
1064
+ folderId: folderId,
1065
+ authentication: authentication,
1066
+ };
1067
+ portalRemoveFolder(requestOptions).then((result) => (result.success ? resolve(result) : reject(result)), reject);
1068
+ });
1069
+ }
1070
+ /**
1071
+ * Removes a group from AGO.
1072
+ *
1073
+ * @param groupId Id of a group to delete
1074
+ * @param authentication Credentials for the request to AGO
1075
+ * @returns A promise that will resolve with the result of the request
1076
+ */
1077
+ export function removeGroup(groupId, authentication) {
1078
+ return new Promise((resolve, reject) => {
1079
+ const requestOptions = {
1080
+ id: groupId,
1081
+ authentication: authentication,
1082
+ };
1083
+ portalRemoveGroup(requestOptions).then((result) => (result.success ? resolve(result) : reject(result)), reject);
1084
+ });
1085
+ }
1086
+ /**
1087
+ * Removes an item from AGO.
1088
+ *
1089
+ * @param itemId Id of an item to delete
1090
+ * @param authentication Credentials for the request to AGO
1091
+ * @param permanentDelete If true (the default), the item is permanently deleted; if false and the item type
1092
+ * supports the recycle bin, the item will be put into the recycle bin
1093
+ * @returns A promise that will resolve with the result of the request
1094
+ */
1095
+ export function removeItem(itemId, authentication, permanentDelete = true) {
1096
+ return new Promise((resolve, reject) => {
1097
+ const requestOptions = {
1098
+ id: itemId,
1099
+ authentication: authentication,
1100
+ params: {
1101
+ permanentDelete,
1102
+ },
1103
+ };
1104
+ portalRemoveItem(requestOptions).then((result) => (result.success ? resolve(result) : reject(result)), reject);
1105
+ });
1106
+ }
1107
+ /**
1108
+ * Removes an item or group from AGO.
1109
+ *
1110
+ * @param itemId Id of an item or group to delete
1111
+ * @param authentication Credentials for the request to AGO
1112
+ * @param permanentDelete If true (the default), the item is permanently deleted; if false and the item type
1113
+ * supports the recycle bin, the item will be put into the recycle bin; note that this does not apply to groups
1114
+ * @returns A promise that will resolve with the result of the request
1115
+ */
1116
+ export function removeItemOrGroup(itemId, authentication, permanentDelete = true) {
1117
+ return new Promise((resolve, reject) => {
1118
+ removeItem(itemId, authentication, permanentDelete).then(resolve, (error) => {
1119
+ removeGroup(itemId, authentication).then(resolve, () => reject(error));
1120
+ });
1121
+ });
1122
+ }
1123
+ /**
1124
+ * Searches for items matching a query and that the caller has access to.
1125
+ *
1126
+ * @param search Search string (e.g., "q=redlands+map") or a more detailed structure that can include authentication
1127
+ * @returns Promise resolving with search results
1128
+ * @see https://developers.arcgis.com/rest/users-groups-and-items/search.htm
1129
+ */
1130
+ export function searchItems(search) {
1131
+ return portalSearchItems(search);
1132
+ }
1133
+ /**
1134
+ * Searches for items matching a query and that the caller has access to, continuing recursively until done.
1135
+ *
1136
+ * @param search Search string (e.g., "q=redlands+map") or a more detailed structure that can include authentication
1137
+ * @param accumulatedResponse Response built from previous requests
1138
+ * @returns Promise resolving with search results
1139
+ * @see https://developers.arcgis.com/rest/users-groups-and-items/search.htm
1140
+ */
1141
+ export function searchAllItems(search, accumulatedResponse) {
1142
+ // Convert the search into an ISearchOptions
1143
+ const searchOptions = convertToISearchOptions(search);
1144
+ // Provide a base into which results can be concatenated
1145
+ const completeResponse = accumulatedResponse
1146
+ ? accumulatedResponse
1147
+ : {
1148
+ query: searchOptions.q,
1149
+ start: 1,
1150
+ num: 100,
1151
+ nextStart: -1,
1152
+ total: 0,
1153
+ results: [],
1154
+ };
1155
+ return new Promise((resolve, reject) => {
1156
+ searchItems(search).then((response) => {
1157
+ completeResponse.results = completeResponse.results.concat(response.results);
1158
+ completeResponse.num = completeResponse.total = completeResponse.results.length;
1159
+ if (response.nextStart > 0) {
1160
+ // Insert nextStart into next query
1161
+ searchOptions.start = response.nextStart;
1162
+ resolve(searchAllItems(searchOptions, completeResponse));
1163
+ }
1164
+ else {
1165
+ resolve(completeResponse);
1166
+ }
1167
+ }, (e) => reject(e));
1168
+ });
1169
+ }
1170
+ /**
1171
+ * Searches for groups matching criteria.
1172
+ *
1173
+ * @param searchString Text for which to search, e.g., 'redlands+map', 'type:"Web Map" -type:"Web Mapping Application"'
1174
+ * @param authentication Credentials for the request to AGO
1175
+ * @param additionalSearchOptions Adjustments to search, such as tranche size
1176
+ * @returns A promise that will resolve with a structure with a tranche of results and
1177
+ * describing how many items are available
1178
+ * @see https://developers.arcgis.com/rest/users-groups-and-items/group-search.htm
1179
+ * @see https://developers.arcgis.com/rest/users-groups-and-items/search-reference.htm
1180
+ */
1181
+ export function searchGroups(searchString, authentication, additionalSearchOptions) {
1182
+ const searchOptions = {
1183
+ q: searchString,
1184
+ params: {
1185
+ ...additionalSearchOptions,
1186
+ },
1187
+ authentication: authentication,
1188
+ };
1189
+ return portalSearchGroups(searchOptions);
1190
+ }
1191
+ /**
1192
+ * Searches for groups matching criteria recurusively.
1193
+ *
1194
+ * @param searchString Text for which to search, e.g., 'redlands+map', 'type:"Web Map" -type:"Web Mapping Application"'
1195
+ * @param authentication Credentials for the request to AGO
1196
+ * @param groups List of groups that have been found from previous requests
1197
+ * @param inPagingParams The paging params for the recurisve searching
1198
+ *
1199
+ * @returns A promise that will resolve with all groups that meet the search criteria
1200
+ */
1201
+ export function searchAllGroups(searchString, authentication, groups, inPagingParams) {
1202
+ const pagingParams = inPagingParams
1203
+ ? inPagingParams
1204
+ : {
1205
+ start: 1,
1206
+ num: 24,
1207
+ };
1208
+ const additionalSearchOptions = {
1209
+ sortField: "title",
1210
+ sortOrder: "asc",
1211
+ ...pagingParams,
1212
+ };
1213
+ // Provide a base onto which results can be concatenated
1214
+ let finalResults = groups ? groups : [];
1215
+ return new Promise((resolve, reject) => {
1216
+ searchGroups(searchString, authentication, additionalSearchOptions).then((response) => {
1217
+ finalResults = finalResults.concat(response.results);
1218
+ if (response.nextStart > 0) {
1219
+ pagingParams.start = response.nextStart;
1220
+ resolve(searchAllGroups(searchString, authentication, finalResults, pagingParams));
1221
+ }
1222
+ else {
1223
+ resolve(finalResults);
1224
+ }
1225
+ }, (e) => reject(e));
1226
+ });
1227
+ }
1228
+ /**
1229
+ * Searches for group contents matching criteria recursively.
1230
+ *
1231
+ * @param groupId Group whose contents are to be searched
1232
+ * @param searchString Text for which to search, e.g., 'redlands+map', 'type:"Web Map" -type:"Web Mapping Application"'
1233
+ * @param authentication Credentials for the request to AGO
1234
+ * @param additionalSearchOptions Adjustments to search, such as tranche size and categories of interest; categories
1235
+ * are supplied as an array: each array element consists of one or more categories to be ORed; array elements are ANDed
1236
+ * @param portalUrl Rest Url of the portal to perform the search
1237
+ * @param accumulatedResponse Response built from previous requests
1238
+ * @returns A promise that will resolve with a structure with a tranche of results and
1239
+ * describing how many items are available
1240
+ * @see https://developers.arcgis.com/rest/users-groups-and-items/group-content-search.htm
1241
+ * @see https://developers.arcgis.com/rest/users-groups-and-items/search-reference.htm
1242
+ */
1243
+ export function searchGroupAllContents(groupId, searchString, authentication, additionalSearchOptions, portalUrl, accumulatedResponse) {
1244
+ additionalSearchOptions = additionalSearchOptions ? additionalSearchOptions : {};
1245
+ // Provide a base into which results can be concatenated
1246
+ const completeResponse = accumulatedResponse
1247
+ ? accumulatedResponse
1248
+ : {
1249
+ query: searchString,
1250
+ start: 1,
1251
+ num: 100,
1252
+ nextStart: -1,
1253
+ total: 0,
1254
+ results: [],
1255
+ };
1256
+ // Remove the sortField if it's "relevance"; that's the default option and is not meant to be specified
1257
+ if (additionalSearchOptions.sortField === "relevance") {
1258
+ delete additionalSearchOptions.sortField;
1259
+ }
1260
+ return new Promise((resolve, reject) => {
1261
+ searchGroupContents(groupId, searchString, authentication, additionalSearchOptions, portalUrl).then((response) => {
1262
+ completeResponse.results = completeResponse.results.concat(response.results);
1263
+ completeResponse.num = completeResponse.total = completeResponse.results.length;
1264
+ if (response.nextStart > 0) {
1265
+ additionalSearchOptions.start = response.nextStart;
1266
+ resolve(searchGroupAllContents(groupId, searchString, authentication, additionalSearchOptions, portalUrl, completeResponse));
1267
+ }
1268
+ else {
1269
+ resolve(completeResponse);
1270
+ }
1271
+ }, (e) => reject(e));
1272
+ });
1273
+ }
1274
+ /**
1275
+ * Searches for group contents matching criteria.
1276
+ *
1277
+ * @param groupId Group whose contents are to be searched
1278
+ * @param searchString Text for which to search, e.g., 'redlands+map', 'type:"Web Map" -type:"Web Mapping Application"'
1279
+ * @param authentication Credentials for the request to AGO
1280
+ * @param additionalSearchOptions Adjustments to search, such as tranche size and categories of interest; categories
1281
+ * are supplied as an array: each array element consists of one or more categories to be ORed; array elements are ANDed
1282
+ * @param portalUrl Rest Url of the portal to perform the search
1283
+ * @returns A promise that will resolve with a structure with a tranche of results and
1284
+ * describing how many items are available
1285
+ * @see https://developers.arcgis.com/rest/users-groups-and-items/group-content-search.htm
1286
+ * @see https://developers.arcgis.com/rest/users-groups-and-items/search-reference.htm
1287
+ */
1288
+ export function searchGroupContents(groupId, searchString, authentication, additionalSearchOptions, portalUrl) {
1289
+ const searchOptions = {
1290
+ groupId,
1291
+ q: searchString,
1292
+ params: Object.assign({
1293
+ num: 100,
1294
+ }, additionalSearchOptions),
1295
+ authentication: authentication,
1296
+ portal: portalUrl,
1297
+ };
1298
+ // If search options include `categories`, switch to new arcgis-rest-js format
1299
+ /* istanbul ignore else */
1300
+ if (Array.isArray(searchOptions.params.categories)) {
1301
+ searchOptions.params.categories = searchOptions.params.categories.map((andGroup) => andGroup.split(","));
1302
+ }
1303
+ return searchGroupContent(searchOptions);
1304
+ }
1305
+ /**
1306
+ * Reassign ownership of a group
1307
+ *
1308
+ * @param groupId Group to remove users from
1309
+ * @param userName The new owner for the group
1310
+ * @param authentication Credentials for the request to
1311
+ *
1312
+ * @returns A promise that will resolve after the group ownership has been assigned
1313
+ *
1314
+ */
1315
+ export function reassignGroup(groupId, userName, authentication) {
1316
+ const requestOptions = {
1317
+ authentication: authentication,
1318
+ params: {
1319
+ targetUsername: userName,
1320
+ },
1321
+ };
1322
+ return request(`${authentication.portal}/community/groups/${groupId}/reassign`, requestOptions);
1323
+ }
1324
+ /**
1325
+ * Remove users from a group
1326
+ *
1327
+ * @param groupId Group to remove users from
1328
+ * @param users List of users to remove from the group
1329
+ * @param authentication Credentials for the request to
1330
+ *
1331
+ * @returns A promise that will resolve after the users have been removed
1332
+ *
1333
+ */
1334
+ export function removeUsers(groupId, users, authentication) {
1335
+ return portalRemoveGroupUsers({
1336
+ id: groupId,
1337
+ users,
1338
+ authentication,
1339
+ });
1340
+ }
1341
+ /**
1342
+ * Shares an item to the defined group
1343
+ *
1344
+ * @param groupId Group to share with
1345
+ * @param id the item id to share with the group
1346
+ * @param destinationAuthentication Credentials for the request to AGO
1347
+ * @param owner owner of the group when sharing tracking items (can be different from the deploying user)
1348
+ *
1349
+ * @returns A promise that will resolve after the item has been shared
1350
+ *
1351
+ */
1352
+ export function shareItem(groupId, id, destinationAuthentication, owner) {
1353
+ return new Promise((resolve, reject) => {
1354
+ const shareOptions = {
1355
+ groupId,
1356
+ id,
1357
+ authentication: destinationAuthentication,
1358
+ };
1359
+ /* istanbul ignore else */
1360
+ if (owner) {
1361
+ shareOptions.owner = owner;
1362
+ }
1363
+ shareItemWithGroup(shareOptions).then(() => resolve(null), (e) => reject(fail(e)));
1364
+ });
1365
+ }
1366
+ /**
1367
+ * Updates an item.
1368
+ *
1369
+ * @param itemInfo The base info of an item; note that this content will be serialized, which doesn't work
1370
+ * for binary content
1371
+ * @param authentication Credentials for request
1372
+ * @param folderId Item's folder
1373
+ * @param additionalParams Updates that are put under the `params` property, which is not serialized
1374
+ * @return
1375
+ */
1376
+ export function updateItem(itemInfo, authentication, folderId, additionalParams) {
1377
+ return new Promise((resolve, reject) => {
1378
+ const updateOptions = {
1379
+ item: itemInfo,
1380
+ folderId: folderId,
1381
+ authentication: authentication,
1382
+ params: {
1383
+ ...(additionalParams ?? {}),
1384
+ },
1385
+ };
1386
+ portalUpdateItem(updateOptions).then((response) => (response.success ? resolve(response) : reject(response)), (err) => reject(err));
1387
+ });
1388
+ }
1389
+ /**
1390
+ * Updates a group.
1391
+ *
1392
+ * @param groupInfo The base info of a group; note that this content will be serialized, which doesn't work
1393
+ * for binary content
1394
+ * @param authentication Credentials for request
1395
+ * @param additionalParams Updates that are put under the `params` property, which is not serialized
1396
+ * @returns A Promise that will resolve with the success/failure status of the request
1397
+ */
1398
+ export function updateGroup(groupInfo, authentication, additionalParams) {
1399
+ return new Promise((resolve, reject) => {
1400
+ const updateOptions = {
1401
+ group: groupInfo,
1402
+ authentication,
1403
+ params: {
1404
+ ...(additionalParams ?? {}),
1405
+ },
1406
+ };
1407
+ portalUpdateGroup(updateOptions).then((response) => (response.success ? resolve(response) : reject(response)), (err) => reject(err));
1408
+ });
1409
+ }
1410
+ /**
1411
+ * Updates an item.
1412
+ *
1413
+ * @param itemInfo The base info of an item
1414
+ * @param data The items data section
1415
+ * @param authentication Credentials for requests
1416
+ * @param thumbnail optional thumbnail to update
1417
+ * @param access "public" or "org"
1418
+ * @return
1419
+ */
1420
+ export function updateItemExtended(itemInfo, data, authentication, thumbnail, access, templateDictionary) {
1421
+ return new Promise((resolve, reject) => {
1422
+ const updateOptions = {
1423
+ item: itemInfo,
1424
+ params: {
1425
+ text: data || {}, // AGO ignores update if `data` is empty
1426
+ },
1427
+ authentication: authentication,
1428
+ };
1429
+ if (thumbnail) {
1430
+ updateOptions.params.thumbnail = thumbnail;
1431
+ }
1432
+ if (isTrackingViewTemplate(undefined, itemInfo) && templateDictionary) {
1433
+ updateOptions.owner = templateDictionary.locationTracking.owner;
1434
+ }
1435
+ portalUpdateItem(updateOptions).then((result) => {
1436
+ if (access && access !== "private") {
1437
+ // Set access if it is not AGOL default
1438
+ // Set the access manually since the access value in createItem appears to be ignored
1439
+ const accessOptions = {
1440
+ id: itemInfo.id,
1441
+ access: access === "public" ? "public" : "org",
1442
+ authentication: authentication,
1443
+ };
1444
+ setItemAccess(accessOptions).then(() => resolve(result), (e) => reject(fail(e)));
1445
+ }
1446
+ else {
1447
+ resolve(result);
1448
+ }
1449
+ }, (e) => reject(fail(e)));
1450
+ });
1451
+ }
1452
+ /**
1453
+ * Update an item's base and data using a dictionary.
1454
+ *
1455
+ * @param {string} itemId The item ID
1456
+ * @param {any} templateDictionary The template dictionary
1457
+ * @param {UserSession} authentication The destination session info
1458
+ * @returns Promise resolving to successfulness of update
1459
+ */
1460
+ export function updateItemTemplateFromDictionary(itemId, templateDictionary, authentication) {
1461
+ return new Promise((resolve, reject) => {
1462
+ // Fetch the items as stored in AGO
1463
+ Promise.all([getItemBase(itemId, authentication), getItemDataAsJson(itemId, authentication)])
1464
+ .then(([item, data]) => {
1465
+ // Do they have any variables?
1466
+ if (hasUnresolvedVariables(item) || hasUnresolvedVariables(data)) {
1467
+ // Update if so
1468
+ const { item: updatedItem, data: updatedData } = replaceInTemplate({ item, data }, templateDictionary);
1469
+ _reportVariablesInItem(itemId, item.type, updatedItem, updatedData);
1470
+ return updateItemExtended(updatedItem, updatedData, authentication);
1471
+ }
1472
+ else {
1473
+ // Shortcut out if not
1474
+ return Promise.resolve({
1475
+ success: true,
1476
+ id: itemId,
1477
+ });
1478
+ }
1479
+ })
1480
+ .then((result) => resolve(result))
1481
+ .catch((error) => reject(error));
1482
+ });
1483
+ }
1484
+ /**
1485
+ * Updates the URL of an item.
1486
+ *
1487
+ * @param id AGOL id of item to update
1488
+ * @param url URL to assign to item's base section
1489
+ * @param authentication Credentials for the request
1490
+ * @returns A promise that will resolve with the item id when the item has been updated or an AGO-style JSON failure
1491
+ * response
1492
+ */
1493
+ export function updateItemURL(id, url, authentication) {
1494
+ const numAttempts = 3;
1495
+ return _updateItemURL(id, url, authentication, numAttempts);
1496
+ }
1497
+ // ------------------------------------------------------------------------------------------------------------------ //
1498
+ /**
1499
+ * Adds a data section to an item.
1500
+ *
1501
+ * @param itemId Id of item to receive data file
1502
+ * @param dataFile Data to be added
1503
+ * @param authentication Credentials for the request
1504
+ * @returns Promise reporting success or failure
1505
+ * @private
1506
+ */
1507
+ export function _addItemDataFile(itemId, dataFile, authentication) {
1508
+ return new Promise((resolve, reject) => {
1509
+ const _addItemData = (data) => {
1510
+ addItemData(itemId, data, authentication).then(resolve, reject);
1511
+ };
1512
+ // Item data has to be submitted as text or JSON for those file types
1513
+ if (dataFile.type.startsWith("text/plain")) {
1514
+ blobToText(dataFile).then(_addItemData, reject);
1515
+ }
1516
+ else if (dataFile.type === "application/json") {
1517
+ blobToJson(dataFile).then(_addItemData, reject);
1518
+ }
1519
+ else {
1520
+ _addItemData(dataFile);
1521
+ }
1522
+ });
1523
+ }
1524
+ /**
1525
+ * Adds a metadata file to an item.
1526
+ *
1527
+ * @param itemId Id of item to receive data file
1528
+ * @param metadataFile Metadata to be added
1529
+ * @param authentication Credentials for the request
1530
+ * @returns Promise reporting success or failure
1531
+ * @private
1532
+ */
1533
+ export function _addItemMetadataFile(itemId, metadataFile, authentication) {
1534
+ return new Promise((resolve, reject) => {
1535
+ const addMetadataOptions = {
1536
+ item: {
1537
+ id: itemId,
1538
+ },
1539
+ params: {
1540
+ // Pass metadata in via params because item property is serialized, which discards a blob
1541
+ metadata: metadataFile,
1542
+ },
1543
+ authentication: authentication,
1544
+ };
1545
+ portalUpdateItem(addMetadataOptions).then(resolve, reject);
1546
+ });
1547
+ }
1548
+ /**
1549
+ * Accumulates the number of relationships in a collection of layers.
1550
+ *
1551
+ * @param List of layers to examine
1552
+ * @returns The number of relationships
1553
+ * @private
1554
+ */
1555
+ export function _countRelationships(layers) {
1556
+ const reducer = (accumulator, currentLayer) => accumulator + (currentLayer.relationships ? currentLayer.relationships.length : 0);
1557
+ return layers.reduce(reducer, 0);
1558
+ }
1559
+ /**
1560
+ * Gets the full definitions of the layers affiliated with a hosted service.
1561
+ *
1562
+ * @param serviceUrl URL to hosted service
1563
+ * @param layerList List of layers at that service...must contain id
1564
+ * @param authentication Credentials for the request
1565
+ * @returns A promise that will resolve with a list of the layers from the admin api
1566
+ * @private
1567
+ */
1568
+ export function _getCreateServiceOptions(newItemTemplate, authentication, templateDictionary) {
1569
+ return new Promise((resolve, reject) => {
1570
+ const serviceInfo = newItemTemplate.properties;
1571
+ const folderId = templateDictionary.folderId;
1572
+ const isPortal = templateDictionary.isPortal;
1573
+ const itemId = newItemTemplate.itemId;
1574
+ validateSpatialReferenceAndExtent(serviceInfo, newItemTemplate, templateDictionary);
1575
+ const fallbackExtent = _getFallbackExtent(serviceInfo, templateDictionary);
1576
+ const params = {};
1577
+ const itemInfo = {
1578
+ title: newItemTemplate.item.title,
1579
+ name: newItemTemplate.item.name,
1580
+ };
1581
+ const _item = {
1582
+ ...itemInfo,
1583
+ preserveLayerIds: true,
1584
+ };
1585
+ const createOptions = {
1586
+ item: _item,
1587
+ folderId,
1588
+ params,
1589
+ authentication: authentication,
1590
+ };
1591
+ createOptions.item = !isTrackingViewTemplate(newItemTemplate)
1592
+ ? _setItemProperties(createOptions.item, newItemTemplate, serviceInfo, params, isPortal)
1593
+ : setTrackingOptions(newItemTemplate, createOptions, templateDictionary);
1594
+ // project the portals extent to match that of the service
1595
+ convertExtentWithFallback(templateDictionary.organization.defaultExtent, fallbackExtent, serviceInfo.service.spatialReference, templateDictionary.organization.helperServices.geometry.url, authentication).then((extent) => {
1596
+ templateDictionary[itemId].solutionExtent = extent;
1597
+ setDefaultSpatialReference(templateDictionary, itemId, extent.spatialReference);
1598
+ createOptions.item = replaceInTemplate(createOptions.item, templateDictionary);
1599
+ createOptions.params = replaceInTemplate(createOptions.params, templateDictionary);
1600
+ if (newItemTemplate.item.thumbnail) {
1601
+ // Pass thumbnail file in via params because item property is serialized, which discards a blob
1602
+ createOptions.params.thumbnail = newItemTemplate.item.thumbnail;
1603
+ }
1604
+ resolve(createOptions);
1605
+ }, (e) => reject(fail(e)));
1606
+ });
1607
+ }
1608
+ /**
1609
+ * When the services spatial reference does not match that of it's default extent
1610
+ * use the out SRs default extent if it exists in the templateDictionary
1611
+ * this should be set when adding a custom out wkid to the params before calling deploy
1612
+ * this will help avoid situations where the orgs default extent and default world extent
1613
+ * will not project successfully to the out SR
1614
+ *
1615
+ * @param serviceInfo the object that contains the spatial reference to evaluate
1616
+ * @param templateDictionary the template dictionary
1617
+ * @returns the extent to use as the fallback
1618
+ * @private
1619
+ */
1620
+ export function _getFallbackExtent(serviceInfo, templateDictionary) {
1621
+ const serviceSR = serviceInfo.service.spatialReference;
1622
+ const serviceInfoWkid = getProp(serviceInfo, "defaultExtent.spatialReference.wkid");
1623
+ const customDefaultExtent = getProp(templateDictionary, "params.defaultExtent");
1624
+ return serviceInfoWkid && serviceInfoWkid === serviceSR.wkid
1625
+ ? serviceInfo.defaultExtent
1626
+ : customDefaultExtent
1627
+ ? customDefaultExtent
1628
+ : serviceInfo.defaultExtent;
1629
+ }
1630
+ /**
1631
+ * Add relationships to all layers in one call to retain fully functioning composite relationships
1632
+ *
1633
+ * @param args The IPostProcessArgs for the request(s)
1634
+ * @returns Any relationships that should be updated for the service
1635
+ * @private
1636
+ */
1637
+ export function _getRelationshipUpdates(args) {
1638
+ const rels = {
1639
+ layers: [],
1640
+ };
1641
+ Object.keys(args.objects).forEach((k) => {
1642
+ const obj = args.objects[k];
1643
+ /* istanbul ignore else */
1644
+ if (obj.relationships && obj.relationships.length > 0) {
1645
+ rels.layers.push({
1646
+ id: obj.id,
1647
+ relationships: obj.relationships,
1648
+ });
1649
+ }
1650
+ deleteProp(obj, "relationships");
1651
+ });
1652
+ return rels;
1653
+ }
1654
+ /**
1655
+ * Get the stored contingent values and structure them to be added to the services layers.
1656
+ *
1657
+ * @param args The IPostProcessArgs for the request(s)
1658
+ * @returns Any contingent values that should be added to the service.
1659
+ * @private
1660
+ */
1661
+ export function _getContingentValuesUpdates(args) {
1662
+ const contingentValues = [];
1663
+ Object.keys(args.objects).forEach((k) => {
1664
+ const obj = args.objects[k];
1665
+ /* istanbul ignore else */
1666
+ if (obj.contingentValues) {
1667
+ contingentValues.push({
1668
+ id: obj.id,
1669
+ contingentValues: obj.contingentValues,
1670
+ });
1671
+ }
1672
+ deleteProp(obj, "contingentValues");
1673
+ });
1674
+ return contingentValues;
1675
+ }
1676
+ /**
1677
+ * Get the stored subtype values and structure them to be added to the services layers.
1678
+ *
1679
+ * @param args The IPostProcessArgs for the request(s)
1680
+ * @returns Any subtype values that should be added to the service.
1681
+ * @private
1682
+ */
1683
+ export function _getSubtypeUpdates(args) {
1684
+ const subtypeUpdates = [];
1685
+ Object.keys(args.objects).forEach((k) => {
1686
+ const obj = args.objects[k];
1687
+ /* istanbul ignore else */
1688
+ if (obj.subtypeField) {
1689
+ subtypeUpdates.push({
1690
+ id: obj.id,
1691
+ subtypeField: obj.subtypeField,
1692
+ subtypes: obj.subtypes,
1693
+ defaultSubtypeCode: obj.defaultSubtypeCode,
1694
+ });
1695
+ }
1696
+ deleteProp(obj, "subtypeField");
1697
+ deleteProp(obj, "subtypes");
1698
+ deleteProp(obj, "defaultSubtypeCode");
1699
+ });
1700
+ return subtypeUpdates;
1701
+ }
1702
+ /**
1703
+ * Get refresh, add, update, or delete definition info
1704
+ *
1705
+ * @param url the base admin url for the service
1706
+ * @param id the id of the layer
1707
+ * @param obj parameters for the request
1708
+ * @param args various arguments to help support the request
1709
+ * @param type type of update the request will handle
1710
+ * @returns IUpdate that has the request url and arguments
1711
+ * @private
1712
+ */
1713
+ export function _getUpdate(url, id, obj, args, type) {
1714
+ const ops = {
1715
+ delete: {
1716
+ url: checkUrlPathTermination(url) + id + "/deleteFromDefinition",
1717
+ params: {
1718
+ deleteFromDefinition: {
1719
+ fields: obj && obj.hasOwnProperty("deleteFields") ? obj.deleteFields : [],
1720
+ },
1721
+ },
1722
+ },
1723
+ update: {
1724
+ url: checkUrlPathTermination(url) + (id ? `${id}/updateDefinition` : "updateDefinition"),
1725
+ params: {
1726
+ updateDefinition: obj,
1727
+ },
1728
+ },
1729
+ add: {
1730
+ url: checkUrlPathTermination(url) + "addToDefinition",
1731
+ params: {
1732
+ addToDefinition: obj,
1733
+ },
1734
+ },
1735
+ refresh: {
1736
+ url: checkUrlPathTermination(url) + "refresh",
1737
+ params: {
1738
+ f: "json",
1739
+ },
1740
+ },
1741
+ };
1742
+ return {
1743
+ url: ops[type].url,
1744
+ params: ops[type].params,
1745
+ args: args,
1746
+ };
1747
+ }
1748
+ /**
1749
+ * Changes just the domain part of a URL to lowercase.
1750
+ *
1751
+ * @param url URL to modify
1752
+ * @return Adjusted URL
1753
+ * @see From `getServerRootUrl` in arcgis-rest-js' ArcGISIdentityManager.ts
1754
+ * @private
1755
+ */
1756
+ export function _lowercaseDomain(url) {
1757
+ if (!url) {
1758
+ return url;
1759
+ }
1760
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1761
+ const [_, protocol, domainAndPath] = url.match(/(https?:\/\/)(.+)/);
1762
+ const [domain, ...path] = domainAndPath.split("/");
1763
+ // Only the domain is lowercased because in some cases an org id might be
1764
+ // in the path which cannot be lowercased.
1765
+ return `${protocol}${domain.toLowerCase()}/${path.join("/")}`;
1766
+ }
1767
+ /**
1768
+ * Checks the two main parts of an item for unresolved variables and reports any found.
1769
+ *
1770
+ * @param base Item's base section
1771
+ * @param data Item's data section
1772
+ * @private
1773
+ */
1774
+ export function _reportVariablesInItem(itemId, itemType, base, data) {
1775
+ const getUnresolved = (v) => {
1776
+ return JSON.stringify(v).match(/{{.+?}}/gim);
1777
+ };
1778
+ // Provide feedback about any remaining unresolved variables
1779
+ /* istanbul ignore else */
1780
+ if (base && hasUnresolvedVariables(base)) {
1781
+ console.log(itemId + " (" + itemType + ") contains variables in base: " + JSON.stringify(getUnresolved(base)));
1782
+ }
1783
+ /* istanbul ignore else */
1784
+ if (data && hasUnresolvedVariables(data)) {
1785
+ console.log(itemId + " (" + itemType + ") contains variables in data: " + JSON.stringify(getUnresolved(data)));
1786
+ }
1787
+ }
1788
+ /**
1789
+ * Updates a feature service item.
1790
+ *
1791
+ * @param item Item to update
1792
+ * @param itemTemplate item template for the new item
1793
+ * @param serviceInfo Service information
1794
+ * @param params arcgis-rest-js params to update
1795
+ * @param isPortal Is the service hosted in a portal?
1796
+ * @returns Updated item
1797
+ * @private
1798
+ */
1799
+ export function _setItemProperties(item, itemTemplate, serviceInfo, params, isPortal) {
1800
+ // Set the capabilities
1801
+ const portalCapabilities = ["Create", "Query", "Editing", "Update", "Delete", "Uploads", "Sync", "Extract"];
1802
+ const capabilities = getProp(serviceInfo, "service.capabilities") || (isPortal ? "" : []);
1803
+ item.capabilities = isPortal
1804
+ ? capabilities
1805
+ .split(",")
1806
+ .filter((c) => portalCapabilities.indexOf(c) > -1)
1807
+ .join(",")
1808
+ : capabilities;
1809
+ if (serviceInfo.service.capabilities) {
1810
+ serviceInfo.service.capabilities = item.capabilities;
1811
+ }
1812
+ // Handle index update for any pre-published solution items that
1813
+ // have non-unique indexes on relationship key fields
1814
+ _updateIndexesForRelationshipKeyFields(serviceInfo);
1815
+ // set create options item properties
1816
+ const keyProperties = [
1817
+ "isView",
1818
+ "sourceSchemaChangesAllowed",
1819
+ "isUpdatableView",
1820
+ "capabilities",
1821
+ "isMultiServicesView",
1822
+ ];
1823
+ const deleteKeys = ["layers", "tables"];
1824
+ /* istanbul ignore else */
1825
+ if (isPortal) {
1826
+ // removed for issue #423 causing FS to fail to create
1827
+ deleteKeys.push("adminServiceInfo");
1828
+ }
1829
+ const itemKeys = Object.keys(item);
1830
+ const serviceKeys = Object.keys(serviceInfo.service);
1831
+ serviceKeys.forEach((k) => {
1832
+ /* istanbul ignore else */
1833
+ if (itemKeys.indexOf(k) === -1 && deleteKeys.indexOf(k) < 0) {
1834
+ item[k] = serviceInfo.service[k];
1835
+ // These need to be included via params otherwise...
1836
+ // addToDef calls fail when adding adminLayerInfo
1837
+ /* istanbul ignore else */
1838
+ if (serviceInfo.service.isView && keyProperties.indexOf(k) > -1) {
1839
+ params[k] = serviceInfo.service[k];
1840
+ }
1841
+ }
1842
+ });
1843
+ // Enable editor tracking on layer with related tables is not supported.
1844
+ /* istanbul ignore else */
1845
+ if (item.isMultiServicesView && getProp(item, "editorTrackingInfo.enableEditorTracking")) {
1846
+ item.editorTrackingInfo.enableEditorTracking = false;
1847
+ params["editorTrackingInfo"] = item.editorTrackingInfo;
1848
+ }
1849
+ /* istanbul ignore else */
1850
+ if (isPortal) {
1851
+ // portal will fail when initialExtent is defined but null
1852
+ // removed for issue #449 causing FS to fail to create on portal
1853
+ /* istanbul ignore else */
1854
+ if (Object.keys(item).indexOf("initialExtent") > -1 && !item.initialExtent) {
1855
+ deleteProp(item, "initialExtent");
1856
+ }
1857
+ }
1858
+ return item;
1859
+ }
1860
+ /**
1861
+ * Set isUnique as true for indexes that reference origin relationship keyFields.
1862
+ *
1863
+ * @param serviceInfo Service information
1864
+ * @private
1865
+ */
1866
+ export function _updateIndexesForRelationshipKeyFields(serviceInfo) {
1867
+ const layersAndTables = (serviceInfo.layers || []).concat(serviceInfo.tables || []);
1868
+ layersAndTables.forEach((item) => {
1869
+ const relationships = item.relationships;
1870
+ const indexes = item.indexes;
1871
+ /* istanbul ignore else */
1872
+ if (relationships && relationships.length > 0 && indexes && indexes.length > 0) {
1873
+ const keyFields = relationships.reduce((acc, v) => {
1874
+ /* istanbul ignore else */
1875
+ if (v.role === "esriRelRoleOrigin" && v.keyField && acc.indexOf(v.keyField) < 0) {
1876
+ acc.push(v.keyField);
1877
+ }
1878
+ return acc;
1879
+ }, []);
1880
+ indexes.map((i) => {
1881
+ /* istanbul ignore else */
1882
+ if (keyFields.some((k) => {
1883
+ const regEx = new RegExp(`\\b${k}\\b`);
1884
+ return regEx.test(i.fields);
1885
+ })) {
1886
+ i.isUnique = true;
1887
+ }
1888
+ return i;
1889
+ });
1890
+ }
1891
+ });
1892
+ }
1893
+ /**
1894
+ * Updates the URL of an item.
1895
+ *
1896
+ * @param id AGOL id of item to update
1897
+ * @param url URL to assign to item's base section
1898
+ * @param authentication Credentials for the request
1899
+ * @param numAttempts Number of times to try to set the URL if AGO says that it updated the URL, but really didn't
1900
+ * @returns A promise that will resolve with the item id when the item has been updated or an AGO-style JSON failure
1901
+ * response
1902
+ * @private
1903
+ */
1904
+ export function _updateItemURL(id, url, authentication, numAttempts = 1) {
1905
+ // Introduce a lag because AGO update appears to choke with rapid subsequent calls
1906
+ const msLag = 1000;
1907
+ return new Promise((resolve, reject) => {
1908
+ // Update the item's URL
1909
+ const options = { item: { id, url }, authentication: authentication };
1910
+ portalUpdateItem(options).then((result) => {
1911
+ if (!result.success) {
1912
+ reject(fail(result));
1913
+ }
1914
+ else {
1915
+ // Get the item to see if the URL really changed; we'll delay a bit before testing because AGO
1916
+ // has a timing problem with URL updates
1917
+ setTimeout(() => {
1918
+ getItem(id, { authentication: authentication }).then((item) => {
1919
+ const iBrace = item.url.indexOf("{");
1920
+ if (iBrace > -1) {
1921
+ console.warn(id + " has template variable: " + item.url.substr(iBrace));
1922
+ }
1923
+ if (url === item.url) {
1924
+ resolve(id);
1925
+ }
1926
+ else {
1927
+ // If it fails, try again if we have sufficient attempts remaining
1928
+ const errorMsg = "URL not updated for " + item.type + " " + item.id + ": " + item.url + " (" + numAttempts + ")";
1929
+ if (--numAttempts > 0) {
1930
+ _updateItemURL(id, url, authentication, numAttempts).then(resolve, reject);
1931
+ }
1932
+ else {
1933
+ console.error(id + ": " + errorMsg + "; FAILED");
1934
+ reject(errorMsg);
1935
+ }
1936
+ }
1937
+ }, (e) => reject(fail(e)));
1938
+ }, msLag);
1939
+ }
1940
+ }, (e) => reject(fail(e)));
1941
+ });
1942
+ }
1943
+ //# sourceMappingURL=restHelpers.js.map