@esri/solution-common 4.1.2 → 5.0.0

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 (261) hide show
  1. package/dist/cjs/completeItem.d.ts +29 -29
  2. package/dist/cjs/completeItem.js +81 -81
  3. package/dist/cjs/create-hub-request-options.d.ts +29 -29
  4. package/dist/cjs/create-hub-request-options.js +63 -63
  5. package/dist/cjs/deleteHelpers/deleteEmptyGroups.d.ts +24 -24
  6. package/dist/cjs/deleteHelpers/deleteEmptyGroups.js +41 -41
  7. package/dist/cjs/deleteHelpers/deleteGroupIfEmpty.d.ts +27 -27
  8. package/dist/cjs/deleteHelpers/deleteGroupIfEmpty.js +96 -96
  9. package/dist/cjs/deleteHelpers/deleteSolutionContents.d.ts +38 -38
  10. package/dist/cjs/deleteHelpers/deleteSolutionContents.js +129 -129
  11. package/dist/cjs/deleteHelpers/deleteSolutionFolder.d.ts +29 -29
  12. package/dist/cjs/deleteHelpers/deleteSolutionFolder.js +78 -78
  13. package/dist/cjs/deleteHelpers/deleteSolutionItem.d.ts +30 -30
  14. package/dist/cjs/deleteHelpers/deleteSolutionItem.js +53 -53
  15. package/dist/cjs/deleteHelpers/index.d.ts +22 -22
  16. package/dist/cjs/deleteHelpers/index.js +25 -25
  17. package/dist/cjs/deleteHelpers/reconstructBuildOrderIds.d.ts +27 -27
  18. package/dist/cjs/deleteHelpers/reconstructBuildOrderIds.js +33 -33
  19. package/dist/cjs/deleteHelpers/removeItems.d.ts +34 -34
  20. package/dist/cjs/deleteHelpers/removeItems.js +111 -111
  21. package/dist/cjs/deleteHelpers/reportProgress.d.ts +27 -27
  22. package/dist/cjs/deleteHelpers/reportProgress.js +45 -45
  23. package/dist/cjs/deleteSolution.d.ts +55 -55
  24. package/dist/cjs/deleteSolution.js +106 -106
  25. package/dist/cjs/dependencies.d.ts +26 -26
  26. package/dist/cjs/dependencies.js +170 -170
  27. package/dist/cjs/featureServiceHelpers.d.ts +791 -791
  28. package/dist/cjs/featureServiceHelpers.js +2420 -2420
  29. package/dist/cjs/generalHelpers.d.ts +392 -385
  30. package/dist/cjs/generalHelpers.js +857 -854
  31. package/dist/cjs/generalHelpers.js.map +1 -1
  32. package/dist/cjs/get-subscription-info.d.ts +27 -27
  33. package/dist/cjs/get-subscription-info.js +38 -38
  34. package/dist/cjs/getDeletableSolutionInfo.d.ts +29 -29
  35. package/dist/cjs/getDeletableSolutionInfo.js +52 -52
  36. package/dist/cjs/getItemTypeAbbrev.d.ts +19 -19
  37. package/dist/cjs/getItemTypeAbbrev.js +184 -184
  38. package/dist/cjs/getSolutionSummary.d.ts +27 -27
  39. package/dist/cjs/getSolutionSummary.js +100 -100
  40. package/dist/cjs/index.d.ts +43 -44
  41. package/dist/cjs/index.js +46 -47
  42. package/dist/cjs/index.js.map +1 -1
  43. package/dist/cjs/interfaces.d.ts +1334 -1334
  44. package/dist/cjs/interfaces.js +74 -74
  45. package/dist/cjs/interfaces.js.map +1 -1
  46. package/dist/cjs/libConnectors.d.ts +73 -73
  47. package/dist/cjs/libConnectors.js +114 -114
  48. package/dist/cjs/migrations/apply-schema.d.ts +24 -24
  49. package/dist/cjs/migrations/apply-schema.js +35 -35
  50. package/dist/cjs/migrations/is-legacy-solution.d.ts +24 -24
  51. package/dist/cjs/migrations/is-legacy-solution.js +39 -39
  52. package/dist/cjs/migrations/upgrade-three-dot-one.d.ts +27 -27
  53. package/dist/cjs/migrations/upgrade-three-dot-one.js +48 -48
  54. package/dist/cjs/migrations/upgrade-three-dot-zero.d.ts +27 -27
  55. package/dist/cjs/migrations/upgrade-three-dot-zero.js +42 -42
  56. package/dist/cjs/migrations/upgrade-two-dot-five.d.ts +24 -24
  57. package/dist/cjs/migrations/upgrade-two-dot-five.js +72 -72
  58. package/dist/cjs/migrations/upgrade-two-dot-four.d.ts +24 -24
  59. package/dist/cjs/migrations/upgrade-two-dot-four.js +71 -71
  60. package/dist/cjs/migrations/upgrade-two-dot-one.d.ts +7 -7
  61. package/dist/cjs/migrations/upgrade-two-dot-one.js +38 -38
  62. package/dist/cjs/migrations/upgrade-two-dot-seven.d.ts +23 -23
  63. package/dist/cjs/migrations/upgrade-two-dot-seven.js +57 -57
  64. package/dist/cjs/migrations/upgrade-two-dot-six.d.ts +27 -27
  65. package/dist/cjs/migrations/upgrade-two-dot-six.js +60 -60
  66. package/dist/cjs/migrations/upgrade-two-dot-three.d.ts +23 -23
  67. package/dist/cjs/migrations/upgrade-two-dot-three.js +54 -54
  68. package/dist/cjs/migrations/upgrade-two-dot-two.d.ts +23 -23
  69. package/dist/cjs/migrations/upgrade-two-dot-two.js +57 -57
  70. package/dist/cjs/migrations/upgrade-two-dot-zero.d.ts +44 -44
  71. package/dist/cjs/migrations/upgrade-two-dot-zero.js +94 -94
  72. package/dist/cjs/migrator.d.ts +25 -25
  73. package/dist/cjs/migrator.js +76 -76
  74. package/dist/cjs/resourceHelpers.d.ts +191 -191
  75. package/dist/cjs/resourceHelpers.js +383 -390
  76. package/dist/cjs/resourceHelpers.js.map +1 -1
  77. package/dist/cjs/resources/add-resource-from-blob.d.ts +26 -26
  78. package/dist/cjs/resources/add-resource-from-blob.js +51 -51
  79. package/dist/cjs/resources/addMetadataFromBlob.d.ts +25 -25
  80. package/dist/cjs/resources/addMetadataFromBlob.js +42 -42
  81. package/dist/cjs/resources/convert-item-resource-to-storage-resource.d.ts +32 -32
  82. package/dist/cjs/resources/convert-item-resource-to-storage-resource.js +69 -69
  83. package/dist/cjs/resources/convert-storage-resource-to-item-resource.d.ts +29 -29
  84. package/dist/cjs/resources/convert-storage-resource-to-item-resource.js +69 -69
  85. package/dist/cjs/resources/copyAssociatedFiles.d.ts +67 -67
  86. package/dist/cjs/resources/copyAssociatedFiles.js +301 -301
  87. package/dist/cjs/resources/copyDataIntoItem.d.ts +33 -33
  88. package/dist/cjs/resources/copyDataIntoItem.js +61 -62
  89. package/dist/cjs/resources/copyDataIntoItem.js.map +1 -1
  90. package/dist/cjs/resources/copyMetadataIntoItem.d.ts +26 -26
  91. package/dist/cjs/resources/copyMetadataIntoItem.js +45 -45
  92. package/dist/cjs/resources/copyResourceIntoZip.d.ts +33 -33
  93. package/dist/cjs/resources/copyResourceIntoZip.js +77 -77
  94. package/dist/cjs/resources/copyZipIntoItem.d.ts +25 -25
  95. package/dist/cjs/resources/copyZipIntoItem.js +53 -53
  96. package/dist/cjs/resources/createCopyResults.d.ts +25 -25
  97. package/dist/cjs/resources/createCopyResults.js +35 -35
  98. package/dist/cjs/resources/get-blob.d.ts +26 -26
  99. package/dist/cjs/resources/get-blob.js +26 -26
  100. package/dist/cjs/resources/getItemResourcesFilesFromPaths.d.ts +24 -24
  101. package/dist/cjs/resources/getItemResourcesFilesFromPaths.js +48 -48
  102. package/dist/cjs/resources/getItemResourcesPaths.d.ts +26 -26
  103. package/dist/cjs/resources/getItemResourcesPaths.js +72 -72
  104. package/dist/cjs/resources/index.d.ts +29 -29
  105. package/dist/cjs/resources/index.js +32 -32
  106. package/dist/cjs/resources/solution-resource.d.ts +35 -35
  107. package/dist/cjs/resources/solution-resource.js +30 -30
  108. package/dist/cjs/resources/solution-resource.js.map +1 -1
  109. package/dist/cjs/resources/transform-resource-paths-to-solution-resources.d.ts +56 -56
  110. package/dist/cjs/resources/transform-resource-paths-to-solution-resources.js +145 -145
  111. package/dist/cjs/restHelpers.d.ts +586 -585
  112. package/dist/cjs/restHelpers.js +1888 -1883
  113. package/dist/cjs/restHelpers.js.map +1 -1
  114. package/dist/cjs/restHelpersGet.d.ts +288 -288
  115. package/dist/cjs/restHelpersGet.js +803 -803
  116. package/dist/cjs/sharing/index.d.ts +16 -16
  117. package/dist/cjs/sharing/index.js +19 -19
  118. package/dist/cjs/sharing/share-item-to-groups.d.ts +26 -26
  119. package/dist/cjs/sharing/share-item-to-groups.js +43 -43
  120. package/dist/cjs/templatization.d.ts +139 -139
  121. package/dist/cjs/templatization.js +313 -313
  122. package/dist/cjs/trackingHelpers.d.ts +116 -116
  123. package/dist/cjs/trackingHelpers.js +216 -216
  124. package/dist/cjs/velocityHelpers.d.ts +57 -57
  125. package/dist/cjs/velocityHelpers.js +134 -134
  126. package/dist/cjs/workforceHelpers.d.ts +115 -115
  127. package/dist/cjs/workforceHelpers.js +746 -746
  128. package/dist/cjs/workforceHelpers.js.map +1 -1
  129. package/dist/esm/completeItem.d.ts +29 -29
  130. package/dist/esm/completeItem.js +76 -76
  131. package/dist/esm/create-hub-request-options.d.ts +29 -29
  132. package/dist/esm/create-hub-request-options.js +59 -59
  133. package/dist/esm/deleteHelpers/deleteEmptyGroups.d.ts +24 -24
  134. package/dist/esm/deleteHelpers/deleteEmptyGroups.js +37 -37
  135. package/dist/esm/deleteHelpers/deleteGroupIfEmpty.d.ts +27 -27
  136. package/dist/esm/deleteHelpers/deleteGroupIfEmpty.js +91 -91
  137. package/dist/esm/deleteHelpers/deleteSolutionContents.d.ts +38 -38
  138. package/dist/esm/deleteHelpers/deleteSolutionContents.js +124 -124
  139. package/dist/esm/deleteHelpers/deleteSolutionFolder.d.ts +29 -29
  140. package/dist/esm/deleteHelpers/deleteSolutionFolder.js +73 -73
  141. package/dist/esm/deleteHelpers/deleteSolutionItem.d.ts +30 -30
  142. package/dist/esm/deleteHelpers/deleteSolutionItem.js +48 -48
  143. package/dist/esm/deleteHelpers/index.d.ts +22 -22
  144. package/dist/esm/deleteHelpers/index.js +22 -22
  145. package/dist/esm/deleteHelpers/reconstructBuildOrderIds.d.ts +27 -27
  146. package/dist/esm/deleteHelpers/reconstructBuildOrderIds.js +28 -28
  147. package/dist/esm/deleteHelpers/removeItems.d.ts +34 -34
  148. package/dist/esm/deleteHelpers/removeItems.js +106 -106
  149. package/dist/esm/deleteHelpers/reportProgress.d.ts +27 -27
  150. package/dist/esm/deleteHelpers/reportProgress.js +41 -41
  151. package/dist/esm/deleteSolution.d.ts +55 -55
  152. package/dist/esm/deleteSolution.js +100 -100
  153. package/dist/esm/dependencies.d.ts +26 -26
  154. package/dist/esm/dependencies.js +166 -166
  155. package/dist/esm/featureServiceHelpers.d.ts +791 -791
  156. package/dist/esm/featureServiceHelpers.js +2336 -2336
  157. package/dist/esm/generalHelpers.d.ts +392 -385
  158. package/dist/esm/generalHelpers.js +810 -808
  159. package/dist/esm/generalHelpers.js.map +1 -1
  160. package/dist/esm/get-subscription-info.d.ts +27 -27
  161. package/dist/esm/get-subscription-info.js +34 -34
  162. package/dist/esm/getDeletableSolutionInfo.d.ts +29 -29
  163. package/dist/esm/getDeletableSolutionInfo.js +47 -47
  164. package/dist/esm/getItemTypeAbbrev.d.ts +19 -19
  165. package/dist/esm/getItemTypeAbbrev.js +180 -180
  166. package/dist/esm/getSolutionSummary.d.ts +27 -27
  167. package/dist/esm/getSolutionSummary.js +95 -95
  168. package/dist/esm/index.d.ts +43 -44
  169. package/dist/esm/index.js +43 -44
  170. package/dist/esm/index.js.map +1 -1
  171. package/dist/esm/interfaces.d.ts +1334 -1334
  172. package/dist/esm/interfaces.js +70 -70
  173. package/dist/esm/libConnectors.d.ts +73 -73
  174. package/dist/esm/libConnectors.js +104 -104
  175. package/dist/esm/migrations/apply-schema.d.ts +24 -24
  176. package/dist/esm/migrations/apply-schema.js +31 -31
  177. package/dist/esm/migrations/is-legacy-solution.d.ts +24 -24
  178. package/dist/esm/migrations/is-legacy-solution.js +35 -35
  179. package/dist/esm/migrations/upgrade-three-dot-one.d.ts +27 -27
  180. package/dist/esm/migrations/upgrade-three-dot-one.js +44 -44
  181. package/dist/esm/migrations/upgrade-three-dot-zero.d.ts +27 -27
  182. package/dist/esm/migrations/upgrade-three-dot-zero.js +38 -38
  183. package/dist/esm/migrations/upgrade-two-dot-five.d.ts +24 -24
  184. package/dist/esm/migrations/upgrade-two-dot-five.js +68 -68
  185. package/dist/esm/migrations/upgrade-two-dot-four.d.ts +24 -24
  186. package/dist/esm/migrations/upgrade-two-dot-four.js +67 -67
  187. package/dist/esm/migrations/upgrade-two-dot-one.d.ts +7 -7
  188. package/dist/esm/migrations/upgrade-two-dot-one.js +34 -34
  189. package/dist/esm/migrations/upgrade-two-dot-seven.d.ts +23 -23
  190. package/dist/esm/migrations/upgrade-two-dot-seven.js +53 -53
  191. package/dist/esm/migrations/upgrade-two-dot-six.d.ts +27 -27
  192. package/dist/esm/migrations/upgrade-two-dot-six.js +56 -56
  193. package/dist/esm/migrations/upgrade-two-dot-three.d.ts +23 -23
  194. package/dist/esm/migrations/upgrade-two-dot-three.js +50 -50
  195. package/dist/esm/migrations/upgrade-two-dot-two.d.ts +23 -23
  196. package/dist/esm/migrations/upgrade-two-dot-two.js +53 -53
  197. package/dist/esm/migrations/upgrade-two-dot-zero.d.ts +44 -44
  198. package/dist/esm/migrations/upgrade-two-dot-zero.js +87 -87
  199. package/dist/esm/migrator.d.ts +25 -25
  200. package/dist/esm/migrator.js +72 -72
  201. package/dist/esm/resourceHelpers.d.ts +191 -191
  202. package/dist/esm/resourceHelpers.js +364 -371
  203. package/dist/esm/resourceHelpers.js.map +1 -1
  204. package/dist/esm/resources/add-resource-from-blob.d.ts +26 -26
  205. package/dist/esm/resources/add-resource-from-blob.js +47 -47
  206. package/dist/esm/resources/addMetadataFromBlob.d.ts +25 -25
  207. package/dist/esm/resources/addMetadataFromBlob.js +38 -38
  208. package/dist/esm/resources/convert-item-resource-to-storage-resource.d.ts +32 -32
  209. package/dist/esm/resources/convert-item-resource-to-storage-resource.js +65 -65
  210. package/dist/esm/resources/convert-storage-resource-to-item-resource.d.ts +29 -29
  211. package/dist/esm/resources/convert-storage-resource-to-item-resource.js +65 -65
  212. package/dist/esm/resources/copyAssociatedFiles.d.ts +67 -67
  213. package/dist/esm/resources/copyAssociatedFiles.js +293 -293
  214. package/dist/esm/resources/copyDataIntoItem.d.ts +33 -33
  215. package/dist/esm/resources/copyDataIntoItem.js +56 -57
  216. package/dist/esm/resources/copyDataIntoItem.js.map +1 -1
  217. package/dist/esm/resources/copyMetadataIntoItem.d.ts +26 -26
  218. package/dist/esm/resources/copyMetadataIntoItem.js +41 -41
  219. package/dist/esm/resources/copyResourceIntoZip.d.ts +33 -33
  220. package/dist/esm/resources/copyResourceIntoZip.js +72 -72
  221. package/dist/esm/resources/copyZipIntoItem.d.ts +25 -25
  222. package/dist/esm/resources/copyZipIntoItem.js +49 -49
  223. package/dist/esm/resources/createCopyResults.d.ts +25 -25
  224. package/dist/esm/resources/createCopyResults.js +31 -31
  225. package/dist/esm/resources/get-blob.d.ts +26 -26
  226. package/dist/esm/resources/get-blob.js +22 -22
  227. package/dist/esm/resources/getItemResourcesFilesFromPaths.d.ts +24 -24
  228. package/dist/esm/resources/getItemResourcesFilesFromPaths.js +44 -44
  229. package/dist/esm/resources/getItemResourcesPaths.d.ts +26 -26
  230. package/dist/esm/resources/getItemResourcesPaths.js +68 -68
  231. package/dist/esm/resources/index.d.ts +29 -29
  232. package/dist/esm/resources/index.js +29 -29
  233. package/dist/esm/resources/solution-resource.d.ts +35 -35
  234. package/dist/esm/resources/solution-resource.js +27 -27
  235. package/dist/esm/resources/transform-resource-paths-to-solution-resources.d.ts +56 -56
  236. package/dist/esm/resources/transform-resource-paths-to-solution-resources.js +137 -137
  237. package/dist/esm/restHelpers.d.ts +586 -585
  238. package/dist/esm/restHelpers.js +1827 -1823
  239. package/dist/esm/restHelpers.js.map +1 -1
  240. package/dist/esm/restHelpersGet.d.ts +288 -288
  241. package/dist/esm/restHelpersGet.js +763 -763
  242. package/dist/esm/sharing/index.d.ts +16 -16
  243. package/dist/esm/sharing/index.js +16 -16
  244. package/dist/esm/sharing/share-item-to-groups.d.ts +26 -26
  245. package/dist/esm/sharing/share-item-to-groups.js +39 -39
  246. package/dist/esm/templatization.d.ts +139 -139
  247. package/dist/esm/templatization.js +293 -293
  248. package/dist/esm/trackingHelpers.d.ts +116 -116
  249. package/dist/esm/trackingHelpers.js +204 -204
  250. package/dist/esm/velocityHelpers.d.ts +57 -57
  251. package/dist/esm/velocityHelpers.js +128 -128
  252. package/dist/esm/workforceHelpers.d.ts +115 -115
  253. package/dist/esm/workforceHelpers.js +717 -717
  254. package/dist/esm/workforceHelpers.js.map +1 -1
  255. package/package.json +2 -2
  256. package/dist/cjs/polyfills.d.ts +0 -40
  257. package/dist/cjs/polyfills.js +0 -98
  258. package/dist/cjs/polyfills.js.map +0 -1
  259. package/dist/esm/polyfills.d.ts +0 -40
  260. package/dist/esm/polyfills.js +0 -93
  261. package/dist/esm/polyfills.js.map +0 -1
@@ -1,294 +1,294 @@
1
- /** @license
2
- * Copyright 2021 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 functions for sending resources to AGO.
18
- */
19
- import { EFileType } from "../interfaces";
20
- import { chunkArray } from "@esri/hub-common";
21
- import { copyDataIntoItem } from "./copyDataIntoItem";
22
- import { copyMetadataIntoItem } from "./copyMetadataIntoItem";
23
- import { copyResourceIntoZip, copyResourceIntoZipFromInfo } from "./copyResourceIntoZip";
24
- import { copyZipIntoItem } from "./copyZipIntoItem";
25
- import { createCopyResults } from "./createCopyResults";
26
- import { blobToJson, jsonToFile } from "../generalHelpers";
27
- import { getBlobAsFile } from "../restHelpersGet";
28
- import JSZip from "jszip";
29
- // ------------------------------------------------------------------------------------------------------------------ //
30
- /**
31
- * Copies the files for storing the resources, metadata, and thumbnail of an item or group to a storage item
32
- * with a specified path by collecting files into zip files.
33
- *
34
- * @param files List of item files' URLs and folder/filenames for storing the files
35
- * @param destinationItemId Id of item to receive copy of resource/metadata/thumbnail
36
- * @param destinationAuthentication Credentials for the request to the storage
37
- * @param filesPerZip Number of files to include per zip file; AGO limits zips to 50 files
38
- * @returns A promise which resolves to a list of the result of the copies
39
- */
40
- export function copyFilesAsResources(files, destinationItemId, destinationAuthentication, filesPerZip = 40) {
41
- return new Promise(resolve => {
42
- let awaitAllItems = [];
43
- const zipInfos = [];
44
- if (files.length > 0) {
45
- // Bundle the resources into chunked zip updates because AGO tends to have problems with
46
- // many updates in a row to the same item: it claims success despite randomly failing.
47
- // Note that AGO imposes a limit of 50 files per zip, so we break the list of resource
48
- // file info into chunks below this threshold and start a zip for each
49
- // https://developers.arcgis.com/rest/users-groups-and-items/add-resources.htm
50
- const chunkedResourceFiles = chunkArray(files, filesPerZip);
51
- chunkedResourceFiles.forEach((chunk, index) => {
52
- // Create a zip for this chunk
53
- const zipInfo = {
54
- filename: `resources${index}.zip`,
55
- zip: new JSZip(),
56
- filelist: []
57
- };
58
- awaitAllItems = awaitAllItems.concat(chunk.map(file => copyResourceIntoZip(file, zipInfo)));
59
- zipInfos.push(zipInfo);
60
- });
61
- }
62
- if (awaitAllItems.length > 0) {
63
- // Wait until the Resource zip file(s) are prepared
64
- void Promise.all(awaitAllItems).then((results) => {
65
- // We have three types of results:
66
- // | fetchedFromSource | copiedToDestination | interpretation | |
67
- // +-------------------+---------------------+------------------------------------------------+
68
- // | false | * | could not fetch file from source |
69
- // | true | true | file has been fetched and sent to AGO |
70
- // | true | undefined | file has been fetched and will be sent via zip |
71
- // Filter out copiedToDestination===undefined; we'll get their status when we send their zip
72
- results = results.filter((result) => !(result.fetchedFromSource &&
73
- typeof result.copiedToDestination === "undefined"));
74
- // Now send the resources to AGO
75
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
76
- _copyAssociatedFileZips(zipInfos, destinationItemId, destinationAuthentication).then((zipResults) => {
77
- resolve(results.concat(zipResults));
78
- });
79
- });
80
- }
81
- else {
82
- // No data, metadata, or resources to send; we're done
83
- resolve([]);
84
- }
85
- });
86
- }
87
- /**
88
- * Copies the files described by a list of full URLs and storage folder/filename combinations for storing
89
- * the resources, metadata, and thumbnail of an item or group to a storage item with different
90
- * handling based on the type of file.
91
- *
92
- * @param fileInfos List of item files' URLs and folder/filenames for storing the files
93
- * @param sourceAuthentication Credentials for the request to the source
94
- * @param sourceItemId Id of item supplying resource/metadata
95
- * @param destinationItemId Id of item to receive copy of resource/metadata/thumbnail
96
- * @param destinationAuthentication Credentials for the request to the storage
97
- * @param template Description of item that will receive files
98
- * @returns A promise which resolves to a list of the result of the copies
99
- */
100
- export async function copyAssociatedFilesByType(fileInfos, sourceAuthentication, sourceItemId, destinationItemId, destinationAuthentication, template = {}) {
101
- return new Promise(resolve => {
102
- let awaitAllItems = [];
103
- let resourceFileInfos = fileInfos;
104
- awaitAllItems = fileInfos
105
- .filter(fileInfo => fileInfo.type === EFileType.Data ||
106
- fileInfo.type === EFileType.Metadata)
107
- .map(fileInfo => {
108
- // Handle Data and Metadata first
109
- switch (fileInfo.type) {
110
- case EFileType.Data:
111
- // We are updating an item with a zip file, which is written to AGO. If the updated
112
- // item is in a folder, the zip file is moved to the item's folder after being written.
113
- // Without the folder information in the URL, AGO writes the zip to the root folder,
114
- // which causes a conflict if an item with the same data is already in that root folder.
115
- return copyDataIntoItem(fileInfo, sourceAuthentication, destinationItemId, destinationAuthentication);
116
- case EFileType.Metadata:
117
- return copyMetadataIntoItem(fileInfo, sourceAuthentication, destinationItemId, destinationAuthentication);
118
- }
119
- });
120
- // Now add in the Resources
121
- resourceFileInfos = fileInfos.filter(fileInfo => fileInfo.type === EFileType.Info || fileInfo.type === EFileType.Resource);
122
- const zipInfos = [];
123
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
124
- const awaitAllResources = new Promise(resolve2 => {
125
- if (resourceFileInfos.length > 0) {
126
- // De-templatize as needed in files before adding them to the zip
127
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
128
- _detemplatizeResources(sourceAuthentication, sourceItemId, template, resourceFileInfos, destinationAuthentication)
129
- .then(() => {
130
- // Bundle the resources into chunked zip updates because AGO tends to have problems with
131
- // many updates in a row to the same item: it claims success despite randomly failing.
132
- // Note that AGO imposes a limit of 50 files per zip, so we break the list of resource
133
- // file info into chunks below this threshold and start a zip for each
134
- // https://developers.arcgis.com/rest/users-groups-and-items/add-resources.htm
135
- const chunkedResourceFileInfo = chunkArray(resourceFileInfos, 40); // leave a bit of room below threshold
136
- chunkedResourceFileInfo.forEach((chunk, index) => {
137
- // Create a zip for this chunk
138
- const zipInfo = {
139
- filename: `resources${index}.zip`,
140
- zip: new JSZip(),
141
- filelist: []
142
- };
143
- awaitAllItems = awaitAllItems.concat(chunk.map(fileInfo => {
144
- return copyResourceIntoZipFromInfo(fileInfo, sourceAuthentication, zipInfo);
145
- }));
146
- zipInfos.push(zipInfo);
147
- });
148
- resolve2(null);
149
- });
150
- }
151
- else {
152
- resolve2(null);
153
- }
154
- });
155
- // Wait until the Resource zip file(s) have been prepared
156
- void awaitAllResources.then(() => {
157
- if (awaitAllItems.length > 0) {
158
- // Wait until all Data and Metadata files have been copied
159
- void Promise.all(awaitAllItems).then((results) => {
160
- // We have three types of results:
161
- // | fetchedFromSource | copiedToDestination | interpretation | |
162
- // +-------------------+---------------------+------------------------------------------------+
163
- // | false | * | could not fetch file from source |
164
- // | true | true | file has been fetched and sent to AGO |
165
- // | true | undefined | file has been fetched and will be sent via zip |
166
- // Filter out copiedToDestination===undefined; we'll get their status when we send their zip
167
- results = results.filter((result) => !(result.fetchedFromSource &&
168
- typeof result.copiedToDestination === "undefined"));
169
- // Now send the resources to AGO
170
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
171
- _copyAssociatedFileZips(zipInfos, destinationItemId, destinationAuthentication).then((zipResults) => {
172
- resolve(results.concat(zipResults));
173
- });
174
- });
175
- }
176
- else {
177
- // No data, metadata, or resources to send; we're done
178
- resolve([]);
179
- }
180
- });
181
- });
182
- }
183
- /**
184
- * Copies one or more zipfiles to a storage item.
185
- *
186
- * @param zipInfos List of zip files containing files to store
187
- * @param destinationItemId Id of item to receive copy of resource/metadata/thumbnail
188
- * @param destinationAuthentication Credentials for the request to the storage
189
- * @returns A promise which resolves to a list of the result of the copies
190
- * @private
191
- */
192
- export function _copyAssociatedFileZips(zipInfos, destinationItemId, destinationAuthentication) {
193
- return new Promise(resolve => {
194
- const results = [];
195
- // Filter out empty zips, which can happen when none of the files in the chunk going into a zip
196
- // can be fetched; e.g., the only file is metadata.xml, and the source item doesn't have metadata
197
- const nonEmptyZipInfos = zipInfos.filter((zipInfo) => Object.keys(zipInfo.zip.files).length > 0);
198
- if (nonEmptyZipInfos.length > 0) {
199
- // Send the zip(s) to AGO
200
- void _sendZipsSeriallyToItem(nonEmptyZipInfos, destinationItemId, destinationAuthentication).then((zipResults) => {
201
- resolve(zipResults);
202
- });
203
- }
204
- else {
205
- // No resources to send; we're done
206
- resolve(results);
207
- }
208
- });
209
- }
210
- /**
211
- * Replace templatizations in an item's resources
212
- *
213
- * @param sourceAuthentication Credentials for the request to the source
214
- * @param sourceItemId Id of item supplying resource/metadata
215
- * @param itemTemplate Item being created
216
- * @param fileInfos Resources for the item; these resources are modified as needed
217
- * by removing the templatization: the `url` property is replaced by the `file` property
218
- * @param destinationAuthentication Credentials for the request to the storage
219
- *
220
- * @returns A promise that resolves when all de-templatization has completed
221
- */
222
- export function _detemplatizeResources(sourceAuthentication, sourceItemId, itemTemplate, fileInfos, destinationAuthentication) {
223
- const synchronizePromises = [];
224
- if (itemTemplate.type === "Vector Tile Service") {
225
- // Get the root.json files
226
- const rootJsonResources = fileInfos.filter(file => file.filename === "root.json");
227
- const templatizedResourcePath = "{{" + sourceItemId + ".url}}";
228
- const resourcePath = destinationAuthentication.portal + "/content/items/" + itemTemplate.itemId;
229
- const replacer = new RegExp(templatizedResourcePath, "g");
230
- // Templatize the paths in the files that reference the source item id
231
- rootJsonResources.forEach(rootFileResource => {
232
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
233
- synchronizePromises.push(new Promise(resolve => {
234
- // Fetch the file
235
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
236
- getBlobAsFile(rootFileResource.url, rootFileResource.filename, sourceAuthentication).then((file) => {
237
- // Read the file
238
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
239
- blobToJson(file)
240
- .then(fileJson => {
241
- // Templatize by turning JSON into string, replacing paths with template, and re-JSONing
242
- const updatedFileJson = JSON.parse(JSON.stringify(fileJson)
243
- .replace(replacer, resourcePath));
244
- // Write the changes back into the file
245
- rootFileResource.file = jsonToFile(updatedFileJson, rootFileResource.filename);
246
- rootFileResource.url = "";
247
- resolve(null);
248
- });
249
- });
250
- }));
251
- });
252
- }
253
- return Promise.all(synchronizePromises);
254
- }
255
- /**
256
- * Copies one or more zipfiles to a storage item in a serial fashion, waiting a bit between sends.
257
- *
258
- * @param zipInfos List of zip files containing files to store
259
- * @param destinationItemId Id of item to receive copy of resource/metadata/thumbnail
260
- * @param destinationAuthentication Credentials for the request to the storage
261
- * @returns A promise which resolves to a list of the result of the copies
262
- */
263
- function _sendZipsSeriallyToItem(zipInfos, destinationItemId, destinationAuthentication) {
264
- return new Promise(resolve => {
265
- let allResults = [];
266
- // Remove zip from bottom of list
267
- const zipInfoToSend = zipInfos.pop();
268
- // Send predecessors in list
269
- let sendOthersPromise = Promise.resolve([]);
270
- if (zipInfos.length > 0) {
271
- sendOthersPromise = _sendZipsSeriallyToItem(zipInfos, destinationItemId, destinationAuthentication);
272
- }
273
- void sendOthersPromise
274
- .then((response) => {
275
- allResults = response;
276
- // Stall a little to give AGO time to catch up
277
- return new Promise(resolveSleep => {
278
- setTimeout(() => resolveSleep(), 1000);
279
- });
280
- })
281
- .then(() => {
282
- // Now send the zip removed from bottom of the input list
283
- return copyZipIntoItem(zipInfoToSend, destinationItemId, destinationAuthentication);
284
- })
285
- .then((zipResult) => {
286
- // Save the result of copying this zip as a status for each of the files that it contains
287
- zipResult.filelist.forEach((fileInfo) => {
288
- allResults.push(createCopyResults(fileInfo, true, zipResult.copiedToDestination));
289
- });
290
- resolve(allResults);
291
- });
292
- });
293
- }
1
+ /** @license
2
+ * Copyright 2021 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 functions for sending resources to AGO.
18
+ */
19
+ import { EFileType } from "../interfaces";
20
+ import { chunkArray } from "@esri/hub-common";
21
+ import { copyDataIntoItem } from "./copyDataIntoItem";
22
+ import { copyMetadataIntoItem } from "./copyMetadataIntoItem";
23
+ import { copyResourceIntoZip, copyResourceIntoZipFromInfo } from "./copyResourceIntoZip";
24
+ import { copyZipIntoItem } from "./copyZipIntoItem";
25
+ import { createCopyResults } from "./createCopyResults";
26
+ import { blobToJson, jsonToFile } from "../generalHelpers";
27
+ import { getBlobAsFile } from "../restHelpersGet";
28
+ import JSZip from "jszip";
29
+ // ------------------------------------------------------------------------------------------------------------------ //
30
+ /**
31
+ * Copies the files for storing the resources, metadata, and thumbnail of an item or group to a storage item
32
+ * with a specified path by collecting files into zip files.
33
+ *
34
+ * @param files List of item files' URLs and folder/filenames for storing the files
35
+ * @param destinationItemId Id of item to receive copy of resource/metadata/thumbnail
36
+ * @param destinationAuthentication Credentials for the request to the storage
37
+ * @param filesPerZip Number of files to include per zip file; AGO limits zips to 50 files
38
+ * @returns A promise which resolves to a list of the result of the copies
39
+ */
40
+ export function copyFilesAsResources(files, destinationItemId, destinationAuthentication, filesPerZip = 40) {
41
+ return new Promise(resolve => {
42
+ let awaitAllItems = [];
43
+ const zipInfos = [];
44
+ if (files.length > 0) {
45
+ // Bundle the resources into chunked zip updates because AGO tends to have problems with
46
+ // many updates in a row to the same item: it claims success despite randomly failing.
47
+ // Note that AGO imposes a limit of 50 files per zip, so we break the list of resource
48
+ // file info into chunks below this threshold and start a zip for each
49
+ // https://developers.arcgis.com/rest/users-groups-and-items/add-resources.htm
50
+ const chunkedResourceFiles = chunkArray(files, filesPerZip);
51
+ chunkedResourceFiles.forEach((chunk, index) => {
52
+ // Create a zip for this chunk
53
+ const zipInfo = {
54
+ filename: `resources${index}.zip`,
55
+ zip: new JSZip(),
56
+ filelist: []
57
+ };
58
+ awaitAllItems = awaitAllItems.concat(chunk.map(file => copyResourceIntoZip(file, zipInfo)));
59
+ zipInfos.push(zipInfo);
60
+ });
61
+ }
62
+ if (awaitAllItems.length > 0) {
63
+ // Wait until the Resource zip file(s) are prepared
64
+ void Promise.all(awaitAllItems).then((results) => {
65
+ // We have three types of results:
66
+ // | fetchedFromSource | copiedToDestination | interpretation | |
67
+ // +-------------------+---------------------+------------------------------------------------+
68
+ // | false | * | could not fetch file from source |
69
+ // | true | true | file has been fetched and sent to AGO |
70
+ // | true | undefined | file has been fetched and will be sent via zip |
71
+ // Filter out copiedToDestination===undefined; we'll get their status when we send their zip
72
+ results = results.filter((result) => !(result.fetchedFromSource &&
73
+ typeof result.copiedToDestination === "undefined"));
74
+ // Now send the resources to AGO
75
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
76
+ _copyAssociatedFileZips(zipInfos, destinationItemId, destinationAuthentication).then((zipResults) => {
77
+ resolve(results.concat(zipResults));
78
+ });
79
+ });
80
+ }
81
+ else {
82
+ // No data, metadata, or resources to send; we're done
83
+ resolve([]);
84
+ }
85
+ });
86
+ }
87
+ /**
88
+ * Copies the files described by a list of full URLs and storage folder/filename combinations for storing
89
+ * the resources, metadata, and thumbnail of an item or group to a storage item with different
90
+ * handling based on the type of file.
91
+ *
92
+ * @param fileInfos List of item files' URLs and folder/filenames for storing the files
93
+ * @param sourceAuthentication Credentials for the request to the source
94
+ * @param sourceItemId Id of item supplying resource/metadata
95
+ * @param destinationItemId Id of item to receive copy of resource/metadata/thumbnail
96
+ * @param destinationAuthentication Credentials for the request to the storage
97
+ * @param template Description of item that will receive files
98
+ * @returns A promise which resolves to a list of the result of the copies
99
+ */
100
+ export async function copyAssociatedFilesByType(fileInfos, sourceAuthentication, sourceItemId, destinationItemId, destinationAuthentication, template = {}) {
101
+ return new Promise(resolve => {
102
+ let awaitAllItems = [];
103
+ let resourceFileInfos = fileInfos;
104
+ awaitAllItems = fileInfos
105
+ .filter(fileInfo => fileInfo.type === EFileType.Data ||
106
+ fileInfo.type === EFileType.Metadata)
107
+ .map(fileInfo => {
108
+ // Handle Data and Metadata first
109
+ switch (fileInfo.type) {
110
+ case EFileType.Data:
111
+ // We are updating an item with a zip file, which is written to AGO. If the updated
112
+ // item is in a folder, the zip file is moved to the item's folder after being written.
113
+ // Without the folder information in the URL, AGO writes the zip to the root folder,
114
+ // which causes a conflict if an item with the same data is already in that root folder.
115
+ return copyDataIntoItem(fileInfo, sourceAuthentication, destinationItemId, destinationAuthentication);
116
+ case EFileType.Metadata:
117
+ return copyMetadataIntoItem(fileInfo, sourceAuthentication, destinationItemId, destinationAuthentication);
118
+ }
119
+ });
120
+ // Now add in the Resources
121
+ resourceFileInfos = fileInfos.filter(fileInfo => fileInfo.type === EFileType.Info || fileInfo.type === EFileType.Resource);
122
+ const zipInfos = [];
123
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
124
+ const awaitAllResources = new Promise(resolve2 => {
125
+ if (resourceFileInfos.length > 0) {
126
+ // De-templatize as needed in files before adding them to the zip
127
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
128
+ _detemplatizeResources(sourceAuthentication, sourceItemId, template, resourceFileInfos, destinationAuthentication)
129
+ .then(() => {
130
+ // Bundle the resources into chunked zip updates because AGO tends to have problems with
131
+ // many updates in a row to the same item: it claims success despite randomly failing.
132
+ // Note that AGO imposes a limit of 50 files per zip, so we break the list of resource
133
+ // file info into chunks below this threshold and start a zip for each
134
+ // https://developers.arcgis.com/rest/users-groups-and-items/add-resources.htm
135
+ const chunkedResourceFileInfo = chunkArray(resourceFileInfos, 40); // leave a bit of room below threshold
136
+ chunkedResourceFileInfo.forEach((chunk, index) => {
137
+ // Create a zip for this chunk
138
+ const zipInfo = {
139
+ filename: `resources${index}.zip`,
140
+ zip: new JSZip(),
141
+ filelist: []
142
+ };
143
+ awaitAllItems = awaitAllItems.concat(chunk.map(fileInfo => {
144
+ return copyResourceIntoZipFromInfo(fileInfo, sourceAuthentication, zipInfo);
145
+ }));
146
+ zipInfos.push(zipInfo);
147
+ });
148
+ resolve2(null);
149
+ });
150
+ }
151
+ else {
152
+ resolve2(null);
153
+ }
154
+ });
155
+ // Wait until the Resource zip file(s) have been prepared
156
+ void awaitAllResources.then(() => {
157
+ if (awaitAllItems.length > 0) {
158
+ // Wait until all Data and Metadata files have been copied
159
+ void Promise.all(awaitAllItems).then((results) => {
160
+ // We have three types of results:
161
+ // | fetchedFromSource | copiedToDestination | interpretation | |
162
+ // +-------------------+---------------------+------------------------------------------------+
163
+ // | false | * | could not fetch file from source |
164
+ // | true | true | file has been fetched and sent to AGO |
165
+ // | true | undefined | file has been fetched and will be sent via zip |
166
+ // Filter out copiedToDestination===undefined; we'll get their status when we send their zip
167
+ results = results.filter((result) => !(result.fetchedFromSource &&
168
+ typeof result.copiedToDestination === "undefined"));
169
+ // Now send the resources to AGO
170
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
171
+ _copyAssociatedFileZips(zipInfos, destinationItemId, destinationAuthentication).then((zipResults) => {
172
+ resolve(results.concat(zipResults));
173
+ });
174
+ });
175
+ }
176
+ else {
177
+ // No data, metadata, or resources to send; we're done
178
+ resolve([]);
179
+ }
180
+ });
181
+ });
182
+ }
183
+ /**
184
+ * Copies one or more zipfiles to a storage item.
185
+ *
186
+ * @param zipInfos List of zip files containing files to store
187
+ * @param destinationItemId Id of item to receive copy of resource/metadata/thumbnail
188
+ * @param destinationAuthentication Credentials for the request to the storage
189
+ * @returns A promise which resolves to a list of the result of the copies
190
+ * @private
191
+ */
192
+ export function _copyAssociatedFileZips(zipInfos, destinationItemId, destinationAuthentication) {
193
+ return new Promise(resolve => {
194
+ const results = [];
195
+ // Filter out empty zips, which can happen when none of the files in the chunk going into a zip
196
+ // can be fetched; e.g., the only file is metadata.xml, and the source item doesn't have metadata
197
+ const nonEmptyZipInfos = zipInfos.filter((zipInfo) => Object.keys(zipInfo.zip.files).length > 0);
198
+ if (nonEmptyZipInfos.length > 0) {
199
+ // Send the zip(s) to AGO
200
+ void _sendZipsSeriallyToItem(nonEmptyZipInfos, destinationItemId, destinationAuthentication).then((zipResults) => {
201
+ resolve(zipResults);
202
+ });
203
+ }
204
+ else {
205
+ // No resources to send; we're done
206
+ resolve(results);
207
+ }
208
+ });
209
+ }
210
+ /**
211
+ * Replace templatizations in an item's resources
212
+ *
213
+ * @param sourceAuthentication Credentials for the request to the source
214
+ * @param sourceItemId Id of item supplying resource/metadata
215
+ * @param itemTemplate Item being created
216
+ * @param fileInfos Resources for the item; these resources are modified as needed
217
+ * by removing the templatization: the `url` property is replaced by the `file` property
218
+ * @param destinationAuthentication Credentials for the request to the storage
219
+ *
220
+ * @returns A promise that resolves when all de-templatization has completed
221
+ */
222
+ export function _detemplatizeResources(sourceAuthentication, sourceItemId, itemTemplate, fileInfos, destinationAuthentication) {
223
+ const synchronizePromises = [];
224
+ if (itemTemplate.type === "Vector Tile Service") {
225
+ // Get the root.json files
226
+ const rootJsonResources = fileInfos.filter(file => file.filename === "root.json");
227
+ const templatizedResourcePath = "{{" + sourceItemId + ".url}}";
228
+ const resourcePath = destinationAuthentication.portal + "/content/items/" + itemTemplate.itemId;
229
+ const replacer = new RegExp(templatizedResourcePath, "g");
230
+ // Templatize the paths in the files that reference the source item id
231
+ rootJsonResources.forEach(rootFileResource => {
232
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
233
+ synchronizePromises.push(new Promise(resolve => {
234
+ // Fetch the file
235
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
236
+ getBlobAsFile(rootFileResource.url, rootFileResource.filename, sourceAuthentication).then((file) => {
237
+ // Read the file
238
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
239
+ blobToJson(file)
240
+ .then(fileJson => {
241
+ // Templatize by turning JSON into string, replacing paths with template, and re-JSONing
242
+ const updatedFileJson = JSON.parse(JSON.stringify(fileJson)
243
+ .replace(replacer, resourcePath));
244
+ // Write the changes back into the file
245
+ rootFileResource.file = jsonToFile(updatedFileJson, rootFileResource.filename);
246
+ rootFileResource.url = "";
247
+ resolve(null);
248
+ });
249
+ });
250
+ }));
251
+ });
252
+ }
253
+ return Promise.all(synchronizePromises);
254
+ }
255
+ /**
256
+ * Copies one or more zipfiles to a storage item in a serial fashion, waiting a bit between sends.
257
+ *
258
+ * @param zipInfos List of zip files containing files to store
259
+ * @param destinationItemId Id of item to receive copy of resource/metadata/thumbnail
260
+ * @param destinationAuthentication Credentials for the request to the storage
261
+ * @returns A promise which resolves to a list of the result of the copies
262
+ */
263
+ function _sendZipsSeriallyToItem(zipInfos, destinationItemId, destinationAuthentication) {
264
+ return new Promise(resolve => {
265
+ let allResults = [];
266
+ // Remove zip from bottom of list
267
+ const zipInfoToSend = zipInfos.pop();
268
+ // Send predecessors in list
269
+ let sendOthersPromise = Promise.resolve([]);
270
+ if (zipInfos.length > 0) {
271
+ sendOthersPromise = _sendZipsSeriallyToItem(zipInfos, destinationItemId, destinationAuthentication);
272
+ }
273
+ void sendOthersPromise
274
+ .then((response) => {
275
+ allResults = response;
276
+ // Stall a little to give AGO time to catch up
277
+ return new Promise(resolveSleep => {
278
+ setTimeout(() => resolveSleep(), 1000);
279
+ });
280
+ })
281
+ .then(() => {
282
+ // Now send the zip removed from bottom of the input list
283
+ return copyZipIntoItem(zipInfoToSend, destinationItemId, destinationAuthentication);
284
+ })
285
+ .then((zipResult) => {
286
+ // Save the result of copying this zip as a status for each of the files that it contains
287
+ zipResult.filelist.forEach((fileInfo) => {
288
+ allResults.push(createCopyResults(fileInfo, true, zipResult.copiedToDestination));
289
+ });
290
+ resolve(allResults);
291
+ });
292
+ });
293
+ }
294
294
  //# sourceMappingURL=copyAssociatedFiles.js.map