@esri/solution-deployer 1.1.2 → 1.1.3

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 (38) hide show
  1. package/dist/esm/deploySolutionFromTemplate.js +70 -66
  2. package/dist/esm/deploySolutionFromTemplate.js.map +1 -1
  3. package/dist/esm/deploySolutionItems.js +159 -166
  4. package/dist/esm/deploySolutionItems.js.map +1 -1
  5. package/dist/esm/deployer.js +13 -14
  6. package/dist/esm/deployer.js.map +1 -1
  7. package/dist/esm/deployerUtils.js +17 -22
  8. package/dist/esm/deployerUtils.js.map +1 -1
  9. package/dist/esm/helpers/post-process.js +12 -14
  10. package/dist/esm/helpers/post-process.js.map +1 -1
  11. package/dist/esm/helpers/share-templates-to-groups.js +29 -6
  12. package/dist/esm/helpers/share-templates-to-groups.js.map +1 -1
  13. package/dist/esm/helpers/sortTemplates.js +2 -4
  14. package/dist/esm/helpers/sortTemplates.js.map +1 -1
  15. package/dist/esm/module-map.js +2 -2
  16. package/dist/esm/module-map.js.map +1 -1
  17. package/dist/node/deploySolutionFromTemplate.js +76 -72
  18. package/dist/node/deploySolutionFromTemplate.js.map +1 -1
  19. package/dist/node/deploySolutionItems.js +161 -168
  20. package/dist/node/deploySolutionItems.js.map +1 -1
  21. package/dist/node/deployer.js +16 -17
  22. package/dist/node/deployer.js.map +1 -1
  23. package/dist/node/deployerUtils.js +18 -23
  24. package/dist/node/deployerUtils.js.map +1 -1
  25. package/dist/node/helpers/post-process.js +16 -18
  26. package/dist/node/helpers/post-process.js.map +1 -1
  27. package/dist/node/helpers/share-templates-to-groups.js +30 -7
  28. package/dist/node/helpers/share-templates-to-groups.js.map +1 -1
  29. package/dist/node/helpers/sortTemplates.js +2 -4
  30. package/dist/node/helpers/sortTemplates.js.map +1 -1
  31. package/dist/node/index.js +1 -1
  32. package/dist/node/module-map.js +9 -9
  33. package/dist/node/module-map.js.map +1 -1
  34. package/dist/umd/deployer.umd.js +1621 -1651
  35. package/dist/umd/deployer.umd.js.map +1 -1
  36. package/dist/umd/deployer.umd.min.js +3 -3
  37. package/dist/umd/deployer.umd.min.js.map +1 -1
  38. package/package.json +30 -30
@@ -1,7 +1,7 @@
1
1
  /* @preserve
2
- * @esri/solution-deployer - v1.1.2 - Apache-2.0
2
+ * @esri/solution-deployer - v1.1.3 - Apache-2.0
3
3
  * Copyright (c) 2018-2021 Esri, Inc.
4
- * Tue Aug 31 2021 00:03:54 GMT-0700 (Pacific Daylight Time)
4
+ * Mon Oct 18 2021 09:05:22 GMT-0700 (Pacific Daylight Time)
5
5
  *
6
6
  * Licensed under the Apache License, Version 2.0 (the "License");
7
7
  * you may not use this file except in compliance with the License.
@@ -16,1666 +16,1636 @@
16
16
  * limitations under the License.
17
17
  */
18
18
  (function (global, factory) {
19
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@esri/solution-common'), require('@esri/solution-feature-layer'), require('@esri/solution-file'), require('@esri/solution-form'), require('@esri/solution-group'), require('@esri/solution-simple-types'), require('@esri/solution-storymap'), require('@esri/solution-velocity'), require('@esri/solution-web-experience'), require('@esri/solution-hub-types'), require('@esri/hub-common'), require('@esri/arcgis-rest-portal')) :
20
- typeof define === 'function' && define.amd ? define(['exports', '@esri/solution-common', '@esri/solution-feature-layer', '@esri/solution-file', '@esri/solution-form', '@esri/solution-group', '@esri/solution-simple-types', '@esri/solution-storymap', '@esri/solution-velocity', '@esri/solution-web-experience', '@esri/solution-hub-types', '@esri/hub-common', '@esri/arcgis-rest-portal'], factory) :
21
- (global = global || self, factory(global.arcgisSolution = global.arcgisSolution || {}, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisHub, global.arcgisRest));
19
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@esri/solution-common'), require('@esri/solution-feature-layer'), require('@esri/solution-file'), require('@esri/solution-form'), require('@esri/solution-group'), require('@esri/solution-simple-types'), require('@esri/solution-storymap'), require('@esri/solution-velocity'), require('@esri/solution-web-experience'), require('@esri/solution-hub-types'), require('@esri/hub-common'), require('@esri/arcgis-rest-portal')) :
20
+ typeof define === 'function' && define.amd ? define(['exports', '@esri/solution-common', '@esri/solution-feature-layer', '@esri/solution-file', '@esri/solution-form', '@esri/solution-group', '@esri/solution-simple-types', '@esri/solution-storymap', '@esri/solution-velocity', '@esri/solution-web-experience', '@esri/solution-hub-types', '@esri/hub-common', '@esri/arcgis-rest-portal'], factory) :
21
+ (global = global || self, factory(global.arcgisSolution = global.arcgisSolution || {}, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisHub, global.arcgisRest));
22
22
  }(this, (function (exports, common, featureLayer, fileProcessor, formProcessor, group, solutionSimpleTypes, solutionStorymap, solutionVelocity, solutionWebExperience, solutionHubTypes, hubCommon, portal) { 'use strict';
23
23
 
24
- /*! *****************************************************************************
25
- Copyright (c) Microsoft Corporation. All rights reserved.
26
- Licensed under the Apache License, Version 2.0 (the "License"); you may not use
27
- this file except in compliance with the License. You may obtain a copy of the
28
- License at http://www.apache.org/licenses/LICENSE-2.0
29
-
30
- THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
31
- KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
32
- WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
33
- MERCHANTABLITY OR NON-INFRINGEMENT.
34
-
35
- See the Apache Version 2.0 License for specific language governing permissions
36
- and limitations under the License.
37
- ***************************************************************************** */
38
-
39
- var __assign = function() {
40
- __assign = Object.assign || function __assign(t) {
41
- for (var s, i = 1, n = arguments.length; i < n; i++) {
42
- s = arguments[i];
43
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
44
- }
45
- return t;
46
- };
47
- return __assign.apply(this, arguments);
48
- };
49
-
50
- function __read(o, n) {
51
- var m = typeof Symbol === "function" && o[Symbol.iterator];
52
- if (!m) return o;
53
- var i = m.call(o), r, ar = [], e;
54
- try {
55
- while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
56
- }
57
- catch (error) { e = { error: error }; }
58
- finally {
59
- try {
60
- if (r && !r.done && (m = i["return"])) m.call(i);
61
- }
62
- finally { if (e) throw e.error; }
63
- }
64
- return ar;
65
- }
24
+ /** @license
25
+ * Copyright 2020 Esri
26
+ *
27
+ * Licensed under the Apache License, Version 2.0 (the "License");
28
+ * you may not use this file except in compliance with the License.
29
+ * You may obtain a copy of the License at
30
+ *
31
+ * http://www.apache.org/licenses/LICENSE-2.0
32
+ *
33
+ * Unless required by applicable law or agreed to in writing, software
34
+ * distributed under the License is distributed on an "AS IS" BASIS,
35
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
36
+ * See the License for the specific language governing permissions and
37
+ * limitations under the License.
38
+ */
39
+ const UNSUPPORTED = null;
40
+ /**
41
+ * Mapping from item type to module with type-specific template-handling code.
42
+ * AGO types come from a blend of arcgis-portal-app\src\js\arcgisonline\pages\item\_Info.js and
43
+ * arcgis-portal-app\src\js\arcgis-components\src\_utils\metadata\item\displayName.ts
44
+ */
45
+ const moduleMap = {
46
+ ////////////////////////////////////////////////////////
47
+ // Group type
48
+ Group: group,
49
+ ////////////////////////////////////////////////////////
50
+ // Layer types
51
+ "Big Data Analytic": solutionVelocity.VelocityProcessor,
52
+ "Feature Collection": solutionSimpleTypes.simpleTypes,
53
+ "Feature Service": featureLayer,
54
+ Feed: solutionVelocity.VelocityProcessor,
55
+ "Geocoding Service": undefined,
56
+ "Geodata Service": undefined,
57
+ "Geometry Service": undefined,
58
+ "Geoprocessing Service": undefined,
59
+ "Globe Service": undefined,
60
+ "Image Service": undefined,
61
+ KML: undefined,
62
+ "Map Service": featureLayer,
63
+ "Network Analysis Service": undefined,
64
+ "Real Time Analytic": solutionVelocity.VelocityProcessor,
65
+ "Relational Database Connection": undefined,
66
+ "Scene Service": undefined,
67
+ "Stream Service": undefined,
68
+ Tool: undefined,
69
+ "Vector Tile Service": undefined,
70
+ WFS: undefined,
71
+ WMS: undefined,
72
+ WMTS: undefined,
73
+ "Workflow Manager Service": undefined,
74
+ ////////////////////////////////////////////////////////
75
+ // Map types
76
+ "3D Web Scene": undefined,
77
+ "Web Map": solutionSimpleTypes.simpleTypes,
78
+ "Web Scene": solutionSimpleTypes.simpleTypes,
79
+ ////////////////////////////////////////////////////////
80
+ // App types
81
+ Application: undefined,
82
+ Dashboard: solutionSimpleTypes.simpleTypes,
83
+ "Data Store": undefined,
84
+ "Desktop Application": undefined,
85
+ "Excalibur Imagery Project": undefined,
86
+ Form: formProcessor,
87
+ "Hub Initiative": UNSUPPORTED,
88
+ "Hub Page": solutionHubTypes.HubPageProcessor,
89
+ "Hub Site Application": solutionHubTypes.HubSiteProcessor,
90
+ "Insights Model": solutionSimpleTypes.simpleTypes,
91
+ "Insights Page": undefined,
92
+ "Insights Theme": undefined,
93
+ "Insights Workbook": undefined,
94
+ Mission: undefined,
95
+ "Mobile Application": undefined,
96
+ Notebook: solutionSimpleTypes.notebookProcessor,
97
+ "Oriented Imagery Catalog": solutionSimpleTypes.simpleTypes,
98
+ "Ortho Mapping Project": undefined,
99
+ "QuickCapture Project": solutionSimpleTypes.quickcaptureProcessor,
100
+ "Site Application": solutionHubTypes.HubSiteProcessor,
101
+ "Site Page": solutionHubTypes.HubPageProcessor,
102
+ Solution: UNSUPPORTED,
103
+ StoryMap: solutionStorymap.StoryMapProcessor,
104
+ "Urban Model": undefined,
105
+ "Web Experience Template": undefined,
106
+ "Web Experience": solutionWebExperience.WebExperienceProcessor,
107
+ "Web Mapping Application": solutionSimpleTypes.simpleTypes,
108
+ "Workforce Project": solutionSimpleTypes.simpleTypes,
109
+ ////////////////////////////////////////////////////////
110
+ // File types
111
+ "360 VR Experience": fileProcessor,
112
+ "AppBuilder Extension": fileProcessor,
113
+ "AppBuilder Widget Package": fileProcessor,
114
+ "Application Configuration": fileProcessor,
115
+ "ArcGIS Pro Add In": fileProcessor,
116
+ "ArcGIS Pro Configuration": fileProcessor,
117
+ "ArcPad Package": fileProcessor,
118
+ "Basemap Package": fileProcessor,
119
+ "CAD Drawing": fileProcessor,
120
+ "CityEngine Web Scene": fileProcessor,
121
+ "Code Attachment": UNSUPPORTED,
122
+ "Code Sample": fileProcessor,
123
+ "Color Set": fileProcessor,
124
+ "Compact Tile Package": fileProcessor,
125
+ "CSV Collection": fileProcessor,
126
+ CSV: fileProcessor,
127
+ "Deep Learning Package": fileProcessor,
128
+ "Desktop Add In": fileProcessor,
129
+ "Desktop Application Template": fileProcessor,
130
+ "Desktop Style": fileProcessor,
131
+ "Document Link": fileProcessor,
132
+ "Explorer Add In": fileProcessor,
133
+ "Explorer Layer": fileProcessor,
134
+ "Explorer Map": fileProcessor,
135
+ "Feature Collection Template": fileProcessor,
136
+ "File Geodatabase": fileProcessor,
137
+ GeoJson: fileProcessor,
138
+ GeoPackage: fileProcessor,
139
+ "Geoprocessing Package": fileProcessor,
140
+ "Geoprocessing Sample": fileProcessor,
141
+ "Globe Document": fileProcessor,
142
+ "Image Collection": fileProcessor,
143
+ Image: fileProcessor,
144
+ "iWork Keynote": fileProcessor,
145
+ "iWork Numbers": fileProcessor,
146
+ "iWork Pages": fileProcessor,
147
+ "KML Collection": fileProcessor,
148
+ "Layer Package": fileProcessor,
149
+ "Layer Template": fileProcessor,
150
+ Layer: fileProcessor,
151
+ Layout: fileProcessor,
152
+ "Locator Package": fileProcessor,
153
+ "Map Document": fileProcessor,
154
+ "Map Package": fileProcessor,
155
+ "Map Template": fileProcessor,
156
+ "Microsoft Excel": fileProcessor,
157
+ "Microsoft Powerpoint": fileProcessor,
158
+ "Microsoft Word": fileProcessor,
159
+ "Mobile Basemap Package": fileProcessor,
160
+ "Mobile Map Package": fileProcessor,
161
+ "Mobile Scene Package": fileProcessor,
162
+ "Native Application": fileProcessor,
163
+ "Native Application Installer": fileProcessor,
164
+ "Native Application Template": fileProcessor,
165
+ netCDF: fileProcessor,
166
+ "Operation View": fileProcessor,
167
+ "Operations Dashboard Add In": fileProcessor,
168
+ "Operations Dashboard Extension": fileProcessor,
169
+ PDF: fileProcessor,
170
+ "Pro Layer Package": fileProcessor,
171
+ "Pro Layer": fileProcessor,
172
+ "Pro Map Package": fileProcessor,
173
+ "Pro Map": fileProcessor,
174
+ "Pro Report": fileProcessor,
175
+ "Project Package": fileProcessor,
176
+ "Project Template": fileProcessor,
177
+ "Published Map": fileProcessor,
178
+ "Raster function template": fileProcessor,
179
+ "Report Template": fileProcessor,
180
+ "Rule Package": fileProcessor,
181
+ "Scene Document": fileProcessor,
182
+ "Scene Package": fileProcessor,
183
+ "Service Definition": fileProcessor,
184
+ Shapefile: fileProcessor,
185
+ "Statistical Data Collection": fileProcessor,
186
+ Style: fileProcessor,
187
+ "Survey123 Add In": fileProcessor,
188
+ "Symbol Set": fileProcessor,
189
+ "Task File": fileProcessor,
190
+ "Tile Package": fileProcessor,
191
+ "Toolbox Package": fileProcessor,
192
+ "Vector Tile Package": fileProcessor,
193
+ "Viewer Configuration": fileProcessor,
194
+ "Visio Document": fileProcessor,
195
+ "Window Mobile Package": fileProcessor,
196
+ "Windows Mobile Package": fileProcessor,
197
+ "Windows Viewer Add In": fileProcessor,
198
+ "Windows Viewer Configuration": fileProcessor,
199
+ "Workflow Manager Package": fileProcessor,
200
+ ////////////////////////////////////////////////////////
201
+ // Testing "types"
202
+ Undefined: undefined,
203
+ Unsupported: UNSUPPORTED
204
+ };
66
205
 
67
- /** @license
68
- * Copyright 2020 Esri
69
- *
70
- * Licensed under the Apache License, Version 2.0 (the "License");
71
- * you may not use this file except in compliance with the License.
72
- * You may obtain a copy of the License at
73
- *
74
- * http://www.apache.org/licenses/LICENSE-2.0
75
- *
76
- * Unless required by applicable law or agreed to in writing, software
77
- * distributed under the License is distributed on an "AS IS" BASIS,
78
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
79
- * See the License for the specific language governing permissions and
80
- * limitations under the License.
81
- */
82
- var UNSUPPORTED = null;
83
- /**
84
- * Mapping from item type to module with type-specific template-handling code.
85
- * AGO types come from a blend of arcgis-portal-app\src\js\arcgisonline\pages\item\_Info.js and
86
- * arcgis-portal-app\src\js\arcgis-components\src\_utils\metadata\item\displayName.ts
87
- */
88
- var moduleMap = {
89
- ////////////////////////////////////////////////////////
90
- // Group type
91
- Group: group,
92
- ////////////////////////////////////////////////////////
93
- // Layer types
94
- "Big Data Analytic": solutionVelocity.VelocityProcessor,
95
- "Feature Collection": solutionSimpleTypes.simpleTypes,
96
- "Feature Service": featureLayer,
97
- Feed: solutionVelocity.VelocityProcessor,
98
- "Geocoding Service": undefined,
99
- "Geodata Service": undefined,
100
- "Geometry Service": undefined,
101
- "Geoprocessing Service": undefined,
102
- "Globe Service": undefined,
103
- "Image Service": undefined,
104
- KML: undefined,
105
- "Map Service": featureLayer,
106
- "Network Analysis Service": undefined,
107
- "Real Time Analytic": solutionVelocity.VelocityProcessor,
108
- "Relational Database Connection": undefined,
109
- "Scene Service": undefined,
110
- "Stream Service": undefined,
111
- Tool: undefined,
112
- "Vector Tile Service": undefined,
113
- WFS: undefined,
114
- WMS: undefined,
115
- WMTS: undefined,
116
- "Workflow Manager Service": undefined,
117
- ////////////////////////////////////////////////////////
118
- // Map types
119
- "3D Web Scene": undefined,
120
- "Web Map": solutionSimpleTypes.simpleTypes,
121
- "Web Scene": solutionSimpleTypes.simpleTypes,
122
- ////////////////////////////////////////////////////////
123
- // App types
124
- Application: undefined,
125
- Dashboard: solutionSimpleTypes.simpleTypes,
126
- "Data Store": undefined,
127
- "Desktop Application": undefined,
128
- "Excalibur Imagery Project": undefined,
129
- Form: formProcessor,
130
- "Hub Initiative": UNSUPPORTED,
131
- "Hub Page": solutionHubTypes.HubPageProcessor,
132
- "Hub Site Application": solutionHubTypes.HubSiteProcessor,
133
- "Insights Model": solutionSimpleTypes.simpleTypes,
134
- "Insights Page": undefined,
135
- "Insights Theme": undefined,
136
- "Insights Workbook": undefined,
137
- Mission: undefined,
138
- "Mobile Application": undefined,
139
- Notebook: solutionSimpleTypes.notebookProcessor,
140
- "Oriented Imagery Catalog": solutionSimpleTypes.simpleTypes,
141
- "Ortho Mapping Project": undefined,
142
- "QuickCapture Project": solutionSimpleTypes.quickcaptureProcessor,
143
- "Site Application": solutionHubTypes.HubSiteProcessor,
144
- "Site Page": solutionHubTypes.HubPageProcessor,
145
- Solution: UNSUPPORTED,
146
- StoryMap: solutionStorymap.StoryMapProcessor,
147
- "Urban Model": undefined,
148
- "Web Experience Template": undefined,
149
- "Web Experience": solutionWebExperience.WebExperienceProcessor,
150
- "Web Mapping Application": solutionSimpleTypes.simpleTypes,
151
- "Workforce Project": solutionSimpleTypes.simpleTypes,
152
- ////////////////////////////////////////////////////////
153
- // File types
154
- "360 VR Experience": fileProcessor,
155
- "AppBuilder Extension": fileProcessor,
156
- "AppBuilder Widget Package": fileProcessor,
157
- "Application Configuration": fileProcessor,
158
- "ArcGIS Pro Add In": fileProcessor,
159
- "ArcGIS Pro Configuration": fileProcessor,
160
- "ArcPad Package": fileProcessor,
161
- "Basemap Package": fileProcessor,
162
- "CAD Drawing": fileProcessor,
163
- "CityEngine Web Scene": fileProcessor,
164
- "Code Attachment": UNSUPPORTED,
165
- "Code Sample": fileProcessor,
166
- "Color Set": fileProcessor,
167
- "Compact Tile Package": fileProcessor,
168
- "CSV Collection": fileProcessor,
169
- CSV: fileProcessor,
170
- "Deep Learning Package": fileProcessor,
171
- "Desktop Add In": fileProcessor,
172
- "Desktop Application Template": fileProcessor,
173
- "Desktop Style": fileProcessor,
174
- "Document Link": fileProcessor,
175
- "Explorer Add In": fileProcessor,
176
- "Explorer Layer": fileProcessor,
177
- "Explorer Map": fileProcessor,
178
- "Feature Collection Template": fileProcessor,
179
- "File Geodatabase": fileProcessor,
180
- GeoJson: fileProcessor,
181
- GeoPackage: fileProcessor,
182
- "Geoprocessing Package": fileProcessor,
183
- "Geoprocessing Sample": fileProcessor,
184
- "Globe Document": fileProcessor,
185
- "Image Collection": fileProcessor,
186
- Image: fileProcessor,
187
- "iWork Keynote": fileProcessor,
188
- "iWork Numbers": fileProcessor,
189
- "iWork Pages": fileProcessor,
190
- "KML Collection": fileProcessor,
191
- "Layer Package": fileProcessor,
192
- "Layer Template": fileProcessor,
193
- Layer: fileProcessor,
194
- Layout: fileProcessor,
195
- "Locator Package": fileProcessor,
196
- "Map Document": fileProcessor,
197
- "Map Package": fileProcessor,
198
- "Map Template": fileProcessor,
199
- "Microsoft Excel": fileProcessor,
200
- "Microsoft Powerpoint": fileProcessor,
201
- "Microsoft Word": fileProcessor,
202
- "Mobile Basemap Package": fileProcessor,
203
- "Mobile Map Package": fileProcessor,
204
- "Mobile Scene Package": fileProcessor,
205
- "Native Application": fileProcessor,
206
- "Native Application Installer": fileProcessor,
207
- "Native Application Template": fileProcessor,
208
- netCDF: fileProcessor,
209
- "Operation View": fileProcessor,
210
- "Operations Dashboard Add In": fileProcessor,
211
- "Operations Dashboard Extension": fileProcessor,
212
- PDF: fileProcessor,
213
- "Pro Layer Package": fileProcessor,
214
- "Pro Layer": fileProcessor,
215
- "Pro Map Package": fileProcessor,
216
- "Pro Map": fileProcessor,
217
- "Pro Report": fileProcessor,
218
- "Project Package": fileProcessor,
219
- "Project Template": fileProcessor,
220
- "Published Map": fileProcessor,
221
- "Raster function template": fileProcessor,
222
- "Report Template": fileProcessor,
223
- "Rule Package": fileProcessor,
224
- "Scene Document": fileProcessor,
225
- "Scene Package": fileProcessor,
226
- "Service Definition": fileProcessor,
227
- Shapefile: fileProcessor,
228
- "Statistical Data Collection": fileProcessor,
229
- Style: fileProcessor,
230
- "Survey123 Add In": fileProcessor,
231
- "Symbol Set": fileProcessor,
232
- "Task File": fileProcessor,
233
- "Tile Package": fileProcessor,
234
- "Toolbox Package": fileProcessor,
235
- "Vector Tile Package": fileProcessor,
236
- "Viewer Configuration": fileProcessor,
237
- "Visio Document": fileProcessor,
238
- "Window Mobile Package": fileProcessor,
239
- "Windows Mobile Package": fileProcessor,
240
- "Windows Viewer Add In": fileProcessor,
241
- "Windows Viewer Configuration": fileProcessor,
242
- "Workflow Manager Package": fileProcessor,
243
- ////////////////////////////////////////////////////////
244
- // Testing "types"
245
- Undefined: undefined,
246
- Unsupported: UNSUPPORTED
247
- };
206
+ /** @license
207
+ * Copyright 2018 Esri
208
+ *
209
+ * Licensed under the Apache License, Version 2.0 (the "License");
210
+ * you may not use this file except in compliance with the License.
211
+ * You may obtain a copy of the License at
212
+ *
213
+ * http://www.apache.org/licenses/LICENSE-2.0
214
+ *
215
+ * Unless required by applicable law or agreed to in writing, software
216
+ * distributed under the License is distributed on an "AS IS" BASIS,
217
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
218
+ * See the License for the specific language governing permissions and
219
+ * limitations under the License.
220
+ */
221
+ const UNSUPPORTED$1 = null;
222
+ // ------------------------------------------------------------------------------------------------------------------ //
223
+ /**
224
+ * Deploys a set of items defined by templates.
225
+ *
226
+ * @param portalSharingUrl Server/sharing
227
+ * @param storageItemId Id of storage item
228
+ * @param templates A collection of AGO item templates
229
+ * @param storageAuthentication Credentials for the organization with the source items
230
+ * @param templateDictionary Hash of facts: org URL, adlib replacements
231
+ * @param deployedSolutionId Id of deployed Solution item
232
+ * @param destinationAuthentication Credentials for the destination organization
233
+ * @param options Options to tune deployment
234
+ * @return A promise that will resolve with the list of information about the created items
235
+ */
236
+ function deploySolutionItems(portalSharingUrl, storageItemId, templates, storageAuthentication, templateDictionary, deployedSolutionId, destinationAuthentication, options) {
237
+ return new Promise((resolve, reject) => {
238
+ // Prepare feedback mechanism
239
+ const totalEstimatedCost = _estimateDeploymentCost(templates) + 1; // solution items, plus avoid divide by 0
240
+ let percentDone = 10; // allow for previous deployment work
241
+ const progressPercentStep = (99 - percentDone) / totalEstimatedCost; // leave some % for caller for wrapup
242
+ const failedTemplateItemIds = [];
243
+ const deployedItemIds = [];
244
+ let statusOK = true;
245
+ // TODO: move to separate fn
246
+ const itemProgressCallback = (itemId, status, costUsed, createdItemId // supplied when status is EItemProgressStatus.Created or .Finished
247
+ ) => {
248
+ percentDone += progressPercentStep * costUsed;
249
+ /* istanbul ignore else */
250
+ if (options.progressCallback) {
251
+ if (status === common.EItemProgressStatus.Finished) {
252
+ const event = {
253
+ event: common.SItemProgressStatus[status],
254
+ data: itemId
255
+ };
256
+ options.progressCallback(Math.round(percentDone), options.jobId, event);
257
+ }
258
+ else {
259
+ options.progressCallback(Math.round(percentDone), options.jobId);
260
+ }
261
+ }
262
+ /* istanbul ignore if */
263
+ if (options.consoleProgress) {
264
+ console.log(Date.now(), itemId, options.jobId ?? "", common.SItemProgressStatus[status], percentDone.toFixed(0) + "%", costUsed, createdItemId ? "==> " + createdItemId : "");
265
+ }
266
+ if (status === common.EItemProgressStatus.Created) {
267
+ deployedItemIds.push(createdItemId);
268
+ }
269
+ else if (status === common.EItemProgressStatus.Failed) {
270
+ failedTemplateItemIds.push(itemId);
271
+ console.error("Item " + itemId + " has failed");
272
+ statusOK = false;
273
+ }
274
+ return statusOK;
275
+ // ---------------------------------------------------------------------------------------------------------------
276
+ };
277
+ // portal does not allow views of a single source to be created at the same time
278
+ if (common.getProp(templateDictionary, "organization.isPortal")) {
279
+ templates = _evaluateSharedViewSources(templates);
280
+ }
281
+ // Create an ordered graph of the templates so that dependencies are created before the items that need them.
282
+ // Because cycles are permitted, we also keep track of items that need to be patched later because their
283
+ // dependencies are necessarily created after they are created.
284
+ const { buildOrder, itemsToBePatched } = common.topologicallySortItems(templates);
285
+ // For each item in order from no dependencies to dependent on other items,
286
+ // * replace template symbols using template dictionary
287
+ // * create item in destination group
288
+ // * add created item's id into the template dictionary
289
+ const awaitAllItems = [];
290
+ const reuseItemsDef = _reuseDeployedItems(templates, options.enableItemReuse ?? false, templateDictionary, destinationAuthentication);
291
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
292
+ reuseItemsDef.then(() => {
293
+ const useExistingItemsDef = _useExistingItems(templates, common.getProp(templateDictionary, "params.useExisting"), templateDictionary, destinationAuthentication);
294
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
295
+ useExistingItemsDef.then(() => {
296
+ templates = common.setNamesAndTitles(templates, templateDictionary.solutionItemId);
297
+ buildOrder.forEach((id) => {
298
+ // Get the item's template out of the list of templates
299
+ const template = common.findTemplateInList(templates, id);
300
+ awaitAllItems.push(_createItemFromTemplateWhenReady(template, common.generateStorageFilePaths(portalSharingUrl, storageItemId, template.resources, options.storageVersion), storageAuthentication, templateDictionary, destinationAuthentication, itemProgressCallback));
301
+ });
302
+ // Wait until all items have been created
303
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
304
+ Promise.all(awaitAllItems).then((clonedSolutionItems) => {
305
+ if (failedTemplateItemIds.length === 0) {
306
+ // Do we have any items to be patched (i.e., they refer to dependencies using the template id rather
307
+ // than the cloned id because the item had to be created before the dependency)? Flag these items
308
+ // for post processing in the list of clones.
309
+ _flagPatchItemsForPostProcessing(itemsToBePatched, templateDictionary, clonedSolutionItems);
310
+ resolve(clonedSolutionItems);
311
+ }
312
+ else {
313
+ // Delete created items
314
+ const progressOptions = {
315
+ consoleProgress: true
316
+ };
317
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
318
+ common.deleteSolutionByComponents(deployedSolutionId, deployedItemIds, templates, templateDictionary, destinationAuthentication, progressOptions)
319
+ .then(() => reject(common.failWithIds(failedTemplateItemIds)));
320
+ }
321
+ });
322
+ });
323
+ }, e => {
324
+ console.error(e);
325
+ reject(common.fail(e));
326
+ });
327
+ });
328
+ }
329
+ /**
330
+ * For each item to be patched, convert it to its cloned id and mark the item as needing post processing.
331
+ *
332
+ * @param itemsToBePatched List of items that need to have their dependencies patched
333
+ * @param templateDictionary Hash of facts: org URL, adlib replacements
334
+ * @param templates A collection of AGO item templates
335
+ */
336
+ function _flagPatchItemsForPostProcessing(itemsToBePatched, templateDictionary, templates) {
337
+ let itemIdsToBePatched = Object.keys(itemsToBePatched);
338
+ /* istanbul ignore else */
339
+ if (itemIdsToBePatched.length > 0) {
340
+ // Replace the ids of the items to be patched (which are template ids) with their cloned versions
341
+ itemIdsToBePatched = itemIdsToBePatched.map(id => templateDictionary[id].itemId);
342
+ // Make sure that the items to be patched are flagged for post processing
343
+ templates.forEach(item => {
344
+ /* istanbul ignore else */
345
+ if (itemIdsToBePatched.includes(item.id)) {
346
+ item.postProcess = true;
347
+ }
348
+ });
349
+ }
350
+ }
351
+ /**
352
+ * Portal does not allow views of a single source to be created at the same time.
353
+ *
354
+ * Update view templates with an array of other view template ids that it should wait on.
355
+ *
356
+ * @param templates a collection of AGO item templates
357
+ *
358
+ * @returns An updated array of item templates
359
+ *
360
+ */
361
+ function _evaluateSharedViewSources(templates) {
362
+ // update the templates so we can defer the deployment when more than one view shares the same source
363
+ // these are not classic dependencies but are in some ways similar
364
+ const views = _getViews(templates);
365
+ _updateViewTemplates(templates, views);
366
+ const viewHash = _getViewHash(views);
367
+ let processed = [];
368
+ const visited = [];
369
+ Object.keys(viewHash).forEach(k => {
370
+ const _views = viewHash[k];
371
+ _views.forEach(cv => {
372
+ const template = common.findTemplateInList(templates, cv);
373
+ const syncViews = common.getProp(template, "properties.syncViews");
374
+ /* istanbul ignore else */
375
+ if (visited.indexOf(template.itemId) > -1) {
376
+ processed = processed.concat(syncViews);
377
+ }
378
+ /* istanbul ignore else */
379
+ if (syncViews && syncViews.length > 0) {
380
+ // when a view has multiple dependencies we need to retain the syncViews if they have been set already...
381
+ common.setProp(template, "properties.syncViews", common.cloneObject(processed));
382
+ }
383
+ /* istanbul ignore else */
384
+ if (processed.indexOf(cv) < 0) {
385
+ processed.push(cv);
386
+ }
387
+ /* istanbul ignore else */
388
+ if (visited.indexOf(template.itemId) < 0) {
389
+ visited.push(template.itemId);
390
+ }
391
+ });
392
+ processed = [];
393
+ });
394
+ return templates;
395
+ }
396
+ /**
397
+ * Add a syncViews array to each template that will hold all other view ids that
398
+ * have the same FS dependency.
399
+ * These arrays will be processed later to only contain ids that each view will need to wait on.
400
+ *
401
+ * @param templates a collection of AGO item templates
402
+ * @param views an array of view template details
403
+ *
404
+ * @returns An updated array of item templates
405
+ *
406
+ */
407
+ function _updateViewTemplates(templates, views) {
408
+ views.forEach(v => {
409
+ v.dependencies.forEach((id) => {
410
+ templates = templates.map(t => {
411
+ /* istanbul ignore else */
412
+ if (common.getProp(t, "properties.service.isView") &&
413
+ t.dependencies.indexOf(id) > -1 &&
414
+ t.itemId !== v.id) {
415
+ /* istanbul ignore else */
416
+ if (!Array.isArray(t.properties.syncViews)) {
417
+ t.properties.syncViews = [];
418
+ }
419
+ /* istanbul ignore else */
420
+ if (t.properties.syncViews.indexOf(v.id) < 0) {
421
+ t.properties.syncViews.push(v.id);
422
+ }
423
+ }
424
+ return t;
425
+ });
426
+ });
427
+ });
428
+ return templates;
429
+ }
430
+ /**
431
+ * Get all view templates from the source templates collection
432
+ *
433
+ * @param views A collection of view ID and dependencies
434
+ *
435
+ * @returns an array of objects with the source FS id as the key and a list of views that are
436
+ * dependant upon it
437
+ *
438
+ * @protected
439
+ */
440
+ function _getViewHash(views) {
441
+ const viewHash = {};
442
+ views.forEach(v => {
443
+ v.dependencies.forEach((d) => {
444
+ /* istanbul ignore else */
445
+ if (Object.keys(viewHash).indexOf(d) < 0) {
446
+ viewHash[d] = [v.id];
447
+ }
448
+ else if (viewHash[d].indexOf(v.id) < 0) {
449
+ viewHash[d].push(v.id);
450
+ }
451
+ });
452
+ });
453
+ return viewHash;
454
+ }
455
+ /**
456
+ * Get all view templates from the source templates collection
457
+ *
458
+ * @param templates A collection of AGO item templates
459
+ *
460
+ * @returns an array with the view id and its dependencies
461
+ *
462
+ * @protected
463
+ */
464
+ function _getViews(templates) {
465
+ return templates.reduce((acc, v) => {
466
+ /* istanbul ignore else */
467
+ if (common.getProp(v, "properties.service.isView")) {
468
+ acc.push({
469
+ id: v.itemId,
470
+ dependencies: v.dependencies
471
+ });
472
+ }
473
+ return acc;
474
+ }, []);
475
+ }
476
+ /**
477
+ * Search for existing items and update the templateDictionary with key details
478
+ *
479
+ * @param templates A collection of AGO item templates
480
+ * @param reuseItems Option to search for existing items
481
+ * @param templateDictionary Hash of facts: org URL, adlib replacements, deferreds for dependencies
482
+ * @param authentication Credentials for the requests
483
+ *
484
+ * @returns A Promise that will resolve once existing items have been evaluated
485
+ *
486
+ * @protected
487
+ */
488
+ function _reuseDeployedItems(templates, reuseItems, templateDictionary, authentication) {
489
+ return new Promise((resolve, reject) => {
490
+ if (reuseItems) {
491
+ const existingItemsByKeyword = _findExistingItemByKeyword(templates, templateDictionary, authentication);
492
+ Promise.all(existingItemsByKeyword).then((existingItemsByKeywordResponse) => {
493
+ const existingItemsByTag = _handleExistingItems(existingItemsByKeywordResponse, templateDictionary, authentication, true);
494
+ Promise.all(existingItemsByTag).then(existingItemsByTagResponse => {
495
+ _handleExistingItems(existingItemsByTagResponse, templateDictionary, authentication, false);
496
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
497
+ _updateTemplateDictionary(templates, templateDictionary, authentication).then(resolve);
498
+ }, e => reject(common.fail(e)));
499
+ }, e => reject(common.fail(e)));
500
+ }
501
+ else {
502
+ resolve(null);
503
+ }
504
+ });
505
+ }
506
+ /**
507
+ * Search for existing items and update the templateDictionary with key details
508
+ *
509
+ * Subtle difference between _reuseDeployedItems and _useExistingItems
510
+ * _reuseDeployedItems: will search all existing items based on specific type keywords
511
+ * that would have been added by a previous deployment
512
+ * _useExistingItems: will search for an existing item that the user provided
513
+ * the item id for while configuring in the deployment app.
514
+ * This type of item would not necessarily have been laid down by a previous deployment and
515
+ * can thus not expect that it will have the type keywords
516
+ *
517
+ * @param templates A collection of AGO item templates
518
+ * @param useExisting Option to search for existing items
519
+ * @param templateDictionary Hash of facts: org URL, adlib replacements, deferreds for dependencies
520
+ * @param authentication Credentials for the requests
521
+ *
522
+ * @returns A Promise that will resolve once existing items have been evaluated
523
+ *
524
+ * @protected
525
+ */
526
+ function _useExistingItems(templates, useExisting, templateDictionary, authentication) {
527
+ return new Promise(resolve => {
528
+ if (useExisting) {
529
+ const itemDefs = [];
530
+ const sourceIdHash = {};
531
+ const itemIds = [];
532
+ Object.keys(templateDictionary.params).forEach(k => {
533
+ const v = templateDictionary.params[k];
534
+ /* istanbul ignore else */
535
+ if (v.itemId && /[0-9A-F]{32}/i.test(k)) {
536
+ _updateTemplateDictionaryById(templateDictionary, k, v.itemId, v);
537
+ // need to check and set the typeKeyword if it doesn't exist on this service yet
538
+ // when the user has passed in an itemId that does not come from a previous deployment
539
+ itemDefs.push(common.getItemBase(v.itemId, authentication));
540
+ sourceIdHash[v.itemId] = k;
541
+ /* istanbul ignore else */
542
+ if (itemIds.indexOf(k) < 0) {
543
+ itemIds.push(k);
544
+ }
545
+ }
546
+ });
547
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
548
+ _setTypekeywordForExisting(itemDefs, sourceIdHash, authentication).then(() => {
549
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
550
+ _updateTemplateDictionary(itemIds.map(id => common.getTemplateById(templates, id)), templateDictionary, authentication).then(resolve);
551
+ });
552
+ }
553
+ else {
554
+ resolve(null);
555
+ }
556
+ });
557
+ }
558
+ /**
559
+ * Verify if the existing item has the source-<itemId> typeKeyword and set it if not
560
+ * This allows items that did not come from deployment to be found for reuse after they
561
+ * have been used once via a custom itemId param
562
+ *
563
+ * @param itemDefs
564
+ * @param sourceIdHash key value pairs..actual itemId is the key and the source itemId is the value
565
+ * @param authentication credentials for the requests
566
+ *
567
+ * @return a promise to indicate when the requests are complete
568
+ */
569
+ function _setTypekeywordForExisting(itemDefs, sourceIdHash, authentication) {
570
+ return new Promise(resolve => {
571
+ if (itemDefs.length > 0) {
572
+ Promise.all(itemDefs).then(results => {
573
+ const itemUpdateDefs = [];
574
+ results.forEach(result => {
575
+ const sourceId = sourceIdHash[result.id];
576
+ /* istanbul ignore else */
577
+ if (result && sourceId && result.typeKeywords) {
578
+ const sourceKeyword = `source-${sourceId}`;
579
+ const typeKeywords = result.typeKeywords;
580
+ /* istanbul ignore else */
581
+ if (typeKeywords.indexOf(sourceKeyword) < 0) {
582
+ typeKeywords.push(sourceKeyword);
583
+ const itemUpdate = { id: result.id, typeKeywords };
584
+ itemUpdateDefs.push(common.updateItem(itemUpdate, authentication));
585
+ }
586
+ }
587
+ });
588
+ // wait for updates to finish before we resolve
589
+ if (itemUpdateDefs.length > 0) {
590
+ Promise.all(itemUpdateDefs).then(resolve, () => resolve(undefined));
591
+ }
592
+ else {
593
+ resolve(undefined);
594
+ }
595
+ }, () => resolve(undefined));
596
+ }
597
+ else {
598
+ resolve(undefined);
599
+ }
600
+ });
601
+ }
602
+ /**
603
+ * Update the templateDictionary with key details by item type
604
+ *
605
+ * @param templates A collection of AGO item templates
606
+ * @param templateDictionary Hash of facts: org URL, adlib replacements, deferreds for dependencies
607
+ *
608
+ * @protected
609
+ */
610
+ function _updateTemplateDictionary(templates, templateDictionary, authentication) {
611
+ return new Promise(resolve => {
612
+ const defs = [];
613
+ const urls = [];
614
+ const types = [];
615
+ const ids = [];
616
+ templates.forEach(t => {
617
+ const templateInfo = templateDictionary[t.itemId];
618
+ /* istanbul ignore else */
619
+ if (templateInfo && templateInfo.url && templateInfo.itemId) {
620
+ /* istanbul ignore else */
621
+ if (t.item.type === "Feature Service") {
622
+ const enterpriseIDMapping = common.getProp(templateDictionary, `params.${t.itemId}.enterpriseIDMapping`);
623
+ Object.assign(templateDictionary[t.itemId], common.getLayerSettings(common.getLayersAndTables(t), templateInfo.url, templateInfo.itemId, enterpriseIDMapping));
624
+ // if the service has veiws keep track of the fields so we can use them to
625
+ // compare with the view fields
626
+ /* istanbul ignore else */
627
+ if (common.getProp(t, "properties.service.hasViews")) {
628
+ common._updateTemplateDictionaryFields(t, templateDictionary, false);
629
+ }
630
+ }
631
+ // for fs query with its url...for non fs query the item
632
+ // this is to verify situations where we have a stale search index that will
633
+ // say some items exist when they don't really exist
634
+ // searching the services url or with the item id will return an error when this condition occurs
635
+ /* istanbul ignore else */
636
+ if (urls.indexOf(templateInfo.url) < 0) {
637
+ defs.push(t.item.type === "Feature Service"
638
+ ? common.rest_request(templateInfo.url, { authentication })
639
+ : common.getItemBase(templateInfo.itemId, authentication));
640
+ urls.push(templateInfo.url);
641
+ types.push(t.item.type);
642
+ ids.push(templateInfo.itemId);
643
+ }
644
+ }
645
+ });
646
+ if (defs.length > 0) {
647
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
648
+ Promise.all(defs.map(p => p.catch(e => e))).then(results => {
649
+ /* istanbul ignore else */
650
+ if (Array.isArray(results) && results.length > 0) {
651
+ const fieldDefs = [];
652
+ results.forEach((r, i) => {
653
+ // a feature service result will contain a serviceItemId if it was successfully fetched
654
+ if (r.serviceItemId && types[i] === "Feature Service") {
655
+ Object.keys(templateDictionary).forEach(k => {
656
+ const v = templateDictionary[k];
657
+ /* istanbul ignore else */
658
+ if (v.itemId && v.itemId === r.serviceItemId) {
659
+ common.setDefaultSpatialReference(templateDictionary, k, r.spatialReference);
660
+ // keep the extent values from these responses as well
661
+ common.setCreateProp(templateDictionary, `${k}.defaultExtent`, r.fullExtent || r.initialExtent);
662
+ const layerIds = (r.layers || []).map((l) => l.id);
663
+ const tablesIds = (r.tables || []).map((t) => t.id);
664
+ fieldDefs.push(common.getExistingLayersAndTables(urls[i], layerIds.concat(tablesIds), authentication));
665
+ }
666
+ });
667
+ }
668
+ else {
669
+ /* istanbul ignore else */
670
+ if (types[i] === "Feature Service" ||
671
+ common.getProp(r, "response.error")) {
672
+ // if an error is returned we need to clean up the templateDictionary
673
+ templateDictionary = _updateTemplateDictionaryForError(templateDictionary, ids[i]);
674
+ }
675
+ }
676
+ });
677
+ if (fieldDefs.length > 0) {
678
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
679
+ Promise.all(fieldDefs).then(layerTableResult => {
680
+ layerTableResult.forEach(l => {
681
+ l.forEach((ll) => {
682
+ Object.keys(templateDictionary).forEach(k => {
683
+ /* istanbul ignore else */
684
+ if (templateDictionary[k].itemId === ll.serviceItemId) {
685
+ let sourceId = "";
686
+ Object.keys(templateDictionary).some(_k => {
687
+ /* istanbul ignore else */
688
+ if (templateDictionary[_k].itemId === ll.serviceItemId) {
689
+ sourceId = _k;
690
+ return true;
691
+ }
692
+ });
693
+ const enterpriseIDMapping = common.getProp(templateDictionary, `params.${sourceId}.enterpriseIDMapping`);
694
+ if (enterpriseIDMapping) {
695
+ Object.keys(enterpriseIDMapping).forEach(id => {
696
+ if (enterpriseIDMapping[id].toString() ===
697
+ ll.id.toString()) {
698
+ _setFields(templateDictionary, k, id, ll.fields);
699
+ }
700
+ });
701
+ }
702
+ else {
703
+ _setFields(templateDictionary, k, ll.id, ll.fields);
704
+ }
705
+ }
706
+ });
707
+ });
708
+ });
709
+ resolve(null);
710
+ });
711
+ }
712
+ else {
713
+ resolve(null);
714
+ }
715
+ }
716
+ else {
717
+ resolve(null);
718
+ }
719
+ });
720
+ }
721
+ else {
722
+ resolve(null);
723
+ }
724
+ });
725
+ }
726
+ /**
727
+ * Add the fields from the source layer to the template dictionary for any required replacements
728
+ *
729
+ * @param templateDictionary Hash of facts: org URL, adlib replacements, deferreds for dependencies
730
+ * @param itemId the id for the item
731
+ * @param layerId the id for the layer
732
+ * @param fields the fields to transfer
733
+ *
734
+ * @protected
735
+ */
736
+ function _setFields(templateDictionary, itemId, layerId, fields) {
737
+ const layerInfo = common.getProp(templateDictionary, `${itemId}.layer${layerId}`);
738
+ /* istanbul ignore else */
739
+ if (layerInfo && fields) {
740
+ layerInfo.fields = fields;
741
+ }
742
+ }
743
+ /**
744
+ * In some cases an item id search will return a stale item reference
745
+ * it will subsequently fail when we try to fetch the underlying service.
746
+ *
747
+ * We need to remove the item info that has been added to the template dictionary
748
+ * and treat the item as we do other items that don't already exist on deployment.
749
+ *
750
+ * @param result the service request result
751
+ * @param templateDictionary Hash of facts: org URL, adlib replacements, deferreds for dependencies
752
+ *
753
+ * @protected
754
+ */
755
+ function _updateTemplateDictionaryForError(templateDictionary, itemId) {
756
+ /* istanbul ignore else */
757
+ if (itemId) {
758
+ let removeKey = "";
759
+ Object.keys(templateDictionary).some(k => {
760
+ /* istanbul ignore else */
761
+ if (templateDictionary[k].itemId === itemId) {
762
+ removeKey = k;
763
+ return true;
764
+ }
765
+ });
766
+ /* istanbul ignore else */
767
+ if (removeKey !== "") {
768
+ delete templateDictionary[removeKey];
769
+ }
770
+ }
771
+ return templateDictionary;
772
+ }
773
+ /**
774
+ * Optionally search by tags and then update the templateDictionary based on the search results
775
+ *
776
+ * @param existingItemsResponse response object from search by typeKeyword and type
777
+ * @param templateDictionary Hash of facts: org URL, adlib replacements, deferreds for dependencies
778
+ * @param authentication Credentials for the request
779
+ * @param addTagQuery Boolean to indicate if a search by tag should happen
780
+ * @return A promise that will resolve with an array of results
781
+ * @protected
782
+ */
783
+ function _handleExistingItems(existingItemsResponse, templateDictionary, authentication, addTagQuery) {
784
+ // if items are not found by type keyword search by tag
785
+ const existingItemsByTag = [Promise.resolve(null)];
786
+ /* istanbul ignore else */
787
+ if (existingItemsResponse && Array.isArray(existingItemsResponse)) {
788
+ existingItemsResponse.forEach(existingItem => {
789
+ /* istanbul ignore else */
790
+ if (Array.isArray(existingItem?.results)) {
791
+ let result;
792
+ const results = existingItem.results;
793
+ if (results.length === 1) {
794
+ result = results[0];
795
+ }
796
+ else if (results.length > 1) {
797
+ result = results.reduce((a, b) => a.created > b.created ? a : b);
798
+ }
799
+ else {
800
+ if (addTagQuery && existingItem.query) {
801
+ const tagQuery = existingItem.query.replace("typekeywords", "tags");
802
+ existingItemsByTag.push(_findExistingItem(tagQuery, authentication));
803
+ }
804
+ }
805
+ if (result) {
806
+ const sourceId = existingItem.query
807
+ ? existingItem.query.match(/[0-9A-F]{32}/i)[0]
808
+ : existingItem.sourceId;
809
+ /* istanbul ignore else */
810
+ if (sourceId) {
811
+ _updateTemplateDictionaryById(templateDictionary, sourceId, result.id, result);
812
+ }
813
+ }
814
+ }
815
+ });
816
+ }
817
+ return existingItemsByTag;
818
+ }
819
+ function _updateTemplateDictionaryById(templateDictionary, sourceId, itemId, v) {
820
+ templateDictionary[sourceId] = Object.assign(templateDictionary[sourceId] || {}, {
821
+ def: Promise.resolve(common.generateEmptyCreationResponse(v.type, itemId)),
822
+ itemId,
823
+ name: v.name,
824
+ title: v.title,
825
+ url: v.url
826
+ });
827
+ }
828
+ /**
829
+ * Search items based on user query
830
+ *
831
+ * @param query Query string to use
832
+ * @param authentication Credentials for the request
833
+ * @return A promise that will resolve with an array of results
834
+ * @protected
835
+ */
836
+ function _findExistingItemByKeyword(templates, templateDictionary, authentication) {
837
+ const existingItemsDefs = [];
838
+ templates.forEach(template => {
839
+ if (template.item.type === "Group") {
840
+ const userGroups = templateDictionary.user?.groups;
841
+ /* istanbul ignore else */
842
+ if (Array.isArray(userGroups)) {
843
+ existingItemsDefs.push(Promise.resolve({
844
+ results: userGroups
845
+ .filter(g => g.tags.indexOf(`source-${template.itemId}`) > -1)
846
+ .map(g => {
847
+ g.type = "Group";
848
+ return g;
849
+ }),
850
+ sourceId: template.itemId
851
+ }));
852
+ }
853
+ }
854
+ else {
855
+ existingItemsDefs.push(_findExistingItem(`typekeywords:source-${template.itemId} type:${template.item.type} owner:${templateDictionary.user.username}`, authentication));
856
+ }
857
+ });
858
+ return existingItemsDefs;
859
+ }
860
+ /**
861
+ * Search items based on user query
862
+ *
863
+ * @param query Query string to use
864
+ * @param authentication Credentials for the request
865
+ * @return A promise that will resolve with an array of results
866
+ * @protected
867
+ */
868
+ function _findExistingItem(query, authentication) {
869
+ const searchOptions = {
870
+ q: query,
871
+ authentication: authentication,
872
+ pagingParam: { start: 1, num: 100 }
873
+ };
874
+ return common.searchItems(searchOptions);
875
+ }
876
+ /**
877
+ * Creates an item from a template once the item's dependencies have been created.
878
+ *
879
+ * @param template Template of item to deploy
880
+ * @param resourceFilePaths URL, folder, and filename for each item resource/metadata/thumbnail
881
+ * @param templateDictionary Hash of facts: org URL, adlib replacements, deferreds for dependencies
882
+ * @param userSession Options for the request
883
+ * @param itemProgressCallback Function for reporting progress updates from type-specific template handlers
884
+ * @return A promise that will resolve with the id of the deployed item (which is simply returned if it's
885
+ * already in the templates list
886
+ * @protected
887
+ */
888
+ function _createItemFromTemplateWhenReady(template, resourceFilePaths, storageAuthentication, templateDictionary, destinationAuthentication, itemProgressCallback) {
889
+ // ensure this is present
890
+ template.dependencies = template.dependencies || [];
891
+ // if there is no entry in the templateDictionary
892
+ // or if we have a basic entry without the deferred request for its creation, add it
893
+ if (!templateDictionary.hasOwnProperty(template.itemId) ||
894
+ !common.getProp(templateDictionary[template.itemId], "def")) {
895
+ let createResponse;
896
+ let statusCode = common.EItemProgressStatus.Unknown;
897
+ let itemHandler;
898
+ templateDictionary[template.itemId] =
899
+ templateDictionary[template.itemId] || {};
900
+ // Save the deferred for the use of items that depend on this item being created first
901
+ templateDictionary[template.itemId].def = new Promise(resolve => {
902
+ // Wait until all of the item's dependencies are deployed
903
+ const _awaitDependencies = template.dependencies.reduce((acc, id) => {
904
+ const def = common.getProp(templateDictionary, `${id}.def`);
905
+ // can't use maybePush as that clones the object, which does not work for Promises
906
+ /* istanbul ignore else */
907
+ if (def) {
908
+ acc.push(def);
909
+ }
910
+ return acc;
911
+ }, []);
912
+ const syncViews = common.getProp(template, "properties.syncViews");
913
+ const awaitDependencies = syncViews && syncViews.length > 0
914
+ ? syncViews.reduce((acc, v) => {
915
+ const def = common.getProp(templateDictionary, `${v}.def`);
916
+ /* istanbul ignore else */
917
+ if (def) {
918
+ acc.push(def);
919
+ }
920
+ return acc;
921
+ }, _awaitDependencies)
922
+ : _awaitDependencies;
923
+ Promise.all(awaitDependencies)
924
+ .then(() => {
925
+ // Find the conversion handler for this item type
926
+ const templateType = template.type;
927
+ itemHandler = moduleMap[templateType];
928
+ if (!itemHandler || itemHandler === UNSUPPORTED$1) {
929
+ if (itemHandler === UNSUPPORTED$1) {
930
+ statusCode = common.EItemProgressStatus.Ignored;
931
+ throw new Error();
932
+ }
933
+ else {
934
+ statusCode = common.EItemProgressStatus.Failed;
935
+ throw new Error();
936
+ }
937
+ }
938
+ // Get the item's thumbnail
939
+ return common.getThumbnailFromStorageItem(storageAuthentication, resourceFilePaths);
940
+ })
941
+ .then(thumbnail => {
942
+ template.item.thumbnail = thumbnail;
943
+ // Delegate the creation of the item to the handler
944
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
945
+ return itemHandler.createItemFromTemplate(template, templateDictionary, destinationAuthentication, itemProgressCallback);
946
+ })
947
+ .then((response) => {
948
+ if (response.id === "") {
949
+ statusCode = common.EItemProgressStatus.Failed;
950
+ throw new Error("handled"); // fails to create item
951
+ }
952
+ /* istanbul ignore else */
953
+ createResponse = response;
954
+ if (createResponse.item.item.url) {
955
+ common.setCreateProp(templateDictionary, template.itemId + ".url", createResponse.item.item.url);
956
+ }
957
+ if (resourceFilePaths.length > 0) {
958
+ // Copy resources, metadata, form
959
+ return common.copyFilesFromStorageItem(storageAuthentication, resourceFilePaths, templateDictionary.folderId, createResponse.id, destinationAuthentication, createResponse.item);
960
+ }
961
+ else {
962
+ return Promise.resolve(null);
963
+ }
964
+ })
965
+ .then(() => {
966
+ resolve(createResponse);
967
+ })
968
+ .catch(error => {
969
+ if (!error || error.message !== "handled") {
970
+ itemProgressCallback(template.itemId, statusCode === common.EItemProgressStatus.Unknown
971
+ ? common.EItemProgressStatus.Failed
972
+ : statusCode, 0);
973
+ }
974
+ // Item type not supported or fails to get item dependencies
975
+ resolve(common.generateEmptyCreationResponse(template.type));
976
+ });
977
+ });
978
+ }
979
+ return templateDictionary[template.itemId].def;
980
+ }
981
+ /**
982
+ * Accumulates the estimated deployment cost of a set of templates.
983
+ *
984
+ * @param templates Templates to examine
985
+ * @return Sum of estimated deployment costs
986
+ * @protected
987
+ */
988
+ function _estimateDeploymentCost(templates) {
989
+ return templates.reduce((accumulatedEstimatedCost, template) => {
990
+ return (accumulatedEstimatedCost + (template.estimatedDeploymentCostFactor || 1));
991
+ }, 0);
992
+ }
993
+ // TODO: Return a Promise vs array of promises
994
+ function _getGroupUpdates(template, authentication, templateDictionary) {
995
+ const groups = template.groups || [];
996
+ return groups.map((sourceGroupId) => {
997
+ return common.shareItem(templateDictionary[sourceGroupId].itemId, template.itemId, authentication, common.isTrackingViewTemplate(template) ? templateDictionary.locationTracking.owner : undefined);
998
+ });
999
+ }
248
1000
 
249
- /** @license
250
- * Copyright 2018 Esri
251
- *
252
- * Licensed under the Apache License, Version 2.0 (the "License");
253
- * you may not use this file except in compliance with the License.
254
- * You may obtain a copy of the License at
255
- *
256
- * http://www.apache.org/licenses/LICENSE-2.0
257
- *
258
- * Unless required by applicable law or agreed to in writing, software
259
- * distributed under the License is distributed on an "AS IS" BASIS,
260
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
261
- * See the License for the specific language governing permissions and
262
- * limitations under the License.
263
- */
264
- var UNSUPPORTED$1 = null;
265
- // ------------------------------------------------------------------------------------------------------------------ //
266
- /**
267
- * Deploys a set of items defined by templates.
268
- *
269
- * @param portalSharingUrl Server/sharing
270
- * @param storageItemId Id of storage item
271
- * @param templates A collection of AGO item templates
272
- * @param storageAuthentication Credentials for the organization with the source items
273
- * @param templateDictionary Hash of facts: org URL, adlib replacements
274
- * @param deployedSolutionId Id of deployed Solution item
275
- * @param destinationAuthentication Credentials for the destination organization
276
- * @param options Options to tune deployment
277
- * @return A promise that will resolve with the list of information about the created items
278
- */
279
- function deploySolutionItems(portalSharingUrl, storageItemId, templates, storageAuthentication, templateDictionary, deployedSolutionId, destinationAuthentication, options) {
280
- return new Promise(function (resolve, reject) {
281
- var _a;
282
- // Prepare feedback mechanism
283
- var totalEstimatedCost = _estimateDeploymentCost(templates) + 1; // solution items, plus avoid divide by 0
284
- var percentDone = 10; // allow for previous deployment work
285
- var progressPercentStep = (99 - percentDone) / totalEstimatedCost; // leave some % for caller for wrapup
286
- var failedTemplateItemIds = [];
287
- var deployedItemIds = [];
288
- var statusOK = true;
289
- // TODO: move to separate fn
290
- var itemProgressCallback = function (itemId, status, costUsed, createdItemId // supplied when status is EItemProgressStatus.Created or .Finished
291
- ) {
292
- var _a;
293
- percentDone += progressPercentStep * costUsed;
294
- /* istanbul ignore else */
295
- if (options.progressCallback) {
296
- if (status === common.EItemProgressStatus.Finished) {
297
- var event_1 = {
298
- event: common.SItemProgressStatus[status],
299
- data: itemId
300
- };
301
- options.progressCallback(Math.round(percentDone), options.jobId, event_1);
302
- }
303
- else {
304
- options.progressCallback(Math.round(percentDone), options.jobId);
305
- }
306
- }
307
- /* istanbul ignore if */
308
- if (options.consoleProgress) {
309
- console.log(Date.now(), itemId, (_a = options.jobId) !== null && _a !== void 0 ? _a : "", common.SItemProgressStatus[status], percentDone.toFixed(0) + "%", costUsed, createdItemId ? "==> " + createdItemId : "");
310
- }
311
- if (status === common.EItemProgressStatus.Created) {
312
- deployedItemIds.push(createdItemId);
313
- }
314
- else if (status === common.EItemProgressStatus.Failed) {
315
- failedTemplateItemIds.push(itemId);
316
- console.error("Item " + itemId + " has failed");
317
- statusOK = false;
318
- }
319
- return statusOK;
320
- // ---------------------------------------------------------------------------------------------------------------
321
- };
322
- // portal does not allow views of a single source to be created at the same time
323
- if (common.getProp(templateDictionary, "organization.isPortal")) {
324
- templates = _evaluateSharedViewSources(templates);
325
- }
326
- // Create an ordered graph of the templates so that dependencies are created before the items that need them.
327
- // Because cycles are permitted, we also keep track of items that need to be patched later because their
328
- // dependencies are necessarily created after they are created.
329
- var _b = common.topologicallySortItems(templates), buildOrder = _b.buildOrder, itemsToBePatched = _b.itemsToBePatched;
330
- // For each item in order from no dependencies to dependent on other items,
331
- // * replace template symbols using template dictionary
332
- // * create item in destination group
333
- // * add created item's id into the template dictionary
334
- var awaitAllItems = [];
335
- var reuseItemsDef = _reuseDeployedItems(templates, (_a = options.enableItemReuse) !== null && _a !== void 0 ? _a : false, templateDictionary, destinationAuthentication);
336
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
337
- reuseItemsDef.then(function () {
338
- var useExistingItemsDef = _useExistingItems(templates, common.getProp(templateDictionary, "params.useExisting"), templateDictionary, destinationAuthentication);
339
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
340
- useExistingItemsDef.then(function () {
341
- templates = common.setNamesAndTitles(templates, templateDictionary.solutionItemId);
342
- buildOrder.forEach(function (id) {
343
- // Get the item's template out of the list of templates
344
- var template = common.findTemplateInList(templates, id);
345
- awaitAllItems.push(_createItemFromTemplateWhenReady(template, common.generateStorageFilePaths(portalSharingUrl, storageItemId, template.resources, options.storageVersion), storageAuthentication, templateDictionary, destinationAuthentication, itemProgressCallback));
346
- });
347
- // Wait until all items have been created
348
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
349
- Promise.all(awaitAllItems).then(function (clonedSolutionItems) {
350
- if (failedTemplateItemIds.length === 0) {
351
- // Do we have any items to be patched (i.e., they refer to dependencies using the template id rather
352
- // than the cloned id because the item had to be created before the dependency)? Flag these items
353
- // for post processing in the list of clones.
354
- _flagPatchItemsForPostProcessing(itemsToBePatched, templateDictionary, clonedSolutionItems);
355
- resolve(clonedSolutionItems);
356
- }
357
- else {
358
- // Delete created items
359
- var progressOptions = {
360
- consoleProgress: true
361
- };
362
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
363
- common.deleteSolutionByComponents(deployedSolutionId, deployedItemIds, templates, templateDictionary, destinationAuthentication, progressOptions)
364
- .then(function () {
365
- return reject(common.failWithIds(failedTemplateItemIds));
366
- });
367
- }
368
- });
369
- });
370
- }, function (e) {
371
- console.error(e);
372
- reject(common.fail(e));
373
- });
374
- });
375
- }
376
- /**
377
- * For each item to be patched, convert it to its cloned id and mark the item as needing post processing.
378
- *
379
- * @param itemsToBePatched List of items that need to have their dependencies patched
380
- * @param templateDictionary Hash of facts: org URL, adlib replacements
381
- * @param templates A collection of AGO item templates
382
- */
383
- function _flagPatchItemsForPostProcessing(itemsToBePatched, templateDictionary, templates) {
384
- var itemIdsToBePatched = Object.keys(itemsToBePatched);
385
- /* istanbul ignore else */
386
- if (itemIdsToBePatched.length > 0) {
387
- // Replace the ids of the items to be patched (which are template ids) with their cloned versions
388
- itemIdsToBePatched = itemIdsToBePatched.map(function (id) { return templateDictionary[id].itemId; });
389
- // Make sure that the items to be patched are flagged for post processing
390
- templates.forEach(function (item) {
391
- /* istanbul ignore else */
392
- if (itemIdsToBePatched.includes(item.id)) {
393
- item.postProcess = true;
394
- }
395
- });
396
- }
397
- }
398
- /**
399
- * Portal does not allow views of a single source to be created at the same time.
400
- *
401
- * Update view templates with an array of other view template ids that it should wait on.
402
- *
403
- * @param templates a collection of AGO item templates
404
- *
405
- * @returns An updated array of item templates
406
- *
407
- */
408
- function _evaluateSharedViewSources(templates) {
409
- // update the templates so we can defer the deployment when more than one view shares the same source
410
- // these are not classic dependencies but are in some ways similar
411
- var views = _getViews(templates);
412
- _updateViewTemplates(templates, views);
413
- var viewHash = _getViewHash(views);
414
- var processed = [];
415
- var visited = [];
416
- Object.keys(viewHash).forEach(function (k) {
417
- var _views = viewHash[k];
418
- _views.forEach(function (cv) {
419
- var template = common.findTemplateInList(templates, cv);
420
- var syncViews = common.getProp(template, "properties.syncViews");
421
- /* istanbul ignore else */
422
- if (visited.indexOf(template.itemId) > -1) {
423
- processed = processed.concat(syncViews);
424
- }
425
- /* istanbul ignore else */
426
- if (syncViews && syncViews.length > 0) {
427
- // when a view has multiple dependencies we need to retain the syncViews if they have been set already...
428
- common.setProp(template, "properties.syncViews", common.cloneObject(processed));
429
- }
430
- /* istanbul ignore else */
431
- if (processed.indexOf(cv) < 0) {
432
- processed.push(cv);
433
- }
434
- /* istanbul ignore else */
435
- if (visited.indexOf(template.itemId) < 0) {
436
- visited.push(template.itemId);
437
- }
438
- });
439
- processed = [];
440
- });
441
- return templates;
442
- }
443
- /**
444
- * Add a syncViews array to each template that will hold all other view ids that
445
- * have the same FS dependency.
446
- * These arrays will be processed later to only contain ids that each view will need to wait on.
447
- *
448
- * @param templates a collection of AGO item templates
449
- * @param views an array of view template details
450
- *
451
- * @returns An updated array of item templates
452
- *
453
- */
454
- function _updateViewTemplates(templates, views) {
455
- views.forEach(function (v) {
456
- v.dependencies.forEach(function (id) {
457
- templates = templates.map(function (t) {
458
- /* istanbul ignore else */
459
- if (common.getProp(t, "properties.service.isView") &&
460
- t.dependencies.indexOf(id) > -1 &&
461
- t.itemId !== v.id) {
462
- /* istanbul ignore else */
463
- if (!Array.isArray(t.properties.syncViews)) {
464
- t.properties.syncViews = [];
465
- }
466
- /* istanbul ignore else */
467
- if (t.properties.syncViews.indexOf(v.id) < 0) {
468
- t.properties.syncViews.push(v.id);
469
- }
470
- }
471
- return t;
472
- });
473
- });
474
- });
475
- return templates;
476
- }
477
- /**
478
- * Get all view templates from the source templates collection
479
- *
480
- * @param views A collection of view ID and dependencies
481
- *
482
- * @returns an array of objects with the source FS id as the key and a list of views that are
483
- * dependant upon it
484
- *
485
- * @protected
486
- */
487
- function _getViewHash(views) {
488
- var viewHash = {};
489
- views.forEach(function (v) {
490
- v.dependencies.forEach(function (d) {
491
- /* istanbul ignore else */
492
- if (Object.keys(viewHash).indexOf(d) < 0) {
493
- viewHash[d] = [v.id];
494
- }
495
- else if (viewHash[d].indexOf(v.id) < 0) {
496
- viewHash[d].push(v.id);
497
- }
498
- });
499
- });
500
- return viewHash;
501
- }
502
- /**
503
- * Get all view templates from the source templates collection
504
- *
505
- * @param templates A collection of AGO item templates
506
- *
507
- * @returns an array with the view id and its dependencies
508
- *
509
- * @protected
510
- */
511
- function _getViews(templates) {
512
- return templates.reduce(function (acc, v) {
513
- /* istanbul ignore else */
514
- if (common.getProp(v, "properties.service.isView")) {
515
- acc.push({
516
- id: v.itemId,
517
- dependencies: v.dependencies
518
- });
519
- }
520
- return acc;
521
- }, []);
522
- }
523
- /**
524
- * Search for existing items and update the templateDictionary with key details
525
- *
526
- * @param templates A collection of AGO item templates
527
- * @param reuseItems Option to search for existing items
528
- * @param templateDictionary Hash of facts: org URL, adlib replacements, deferreds for dependencies
529
- * @param authentication Credentials for the requests
530
- *
531
- * @returns A Promise that will resolve once existing items have been evaluated
532
- *
533
- * @protected
534
- */
535
- function _reuseDeployedItems(templates, reuseItems, templateDictionary, authentication) {
536
- return new Promise(function (resolve, reject) {
537
- if (reuseItems) {
538
- var existingItemsByKeyword = _findExistingItemByKeyword(templates, templateDictionary, authentication);
539
- Promise.all(existingItemsByKeyword).then(function (existingItemsByKeywordResponse) {
540
- var existingItemsByTag = _handleExistingItems(existingItemsByKeywordResponse, templateDictionary, authentication, true);
541
- Promise.all(existingItemsByTag).then(function (existingItemsByTagResponse) {
542
- _handleExistingItems(existingItemsByTagResponse, templateDictionary, authentication, false);
543
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
544
- _updateTemplateDictionary(templates, templateDictionary, authentication).then(resolve);
545
- }, function (e) { return reject(common.fail(e)); });
546
- }, function (e) { return reject(common.fail(e)); });
547
- }
548
- else {
549
- resolve(null);
550
- }
551
- });
552
- }
553
- /**
554
- * Search for existing items and update the templateDictionary with key details
555
- *
556
- * Subtle difference between _reuseDeployedItems and _useExistingItems
557
- * _reuseDeployedItems: will search all existing items based on specific type keywords
558
- * that would have been added by a previous deployment
559
- * _useExistingItems: will search for an existing item that the user provided
560
- * the item id for while configuring in the deployment app.
561
- * This type of item would not necessarily have been laid down by a previous deployment and
562
- * can thus not expect that it will have the type keywords
563
- *
564
- * @param templates A collection of AGO item templates
565
- * @param useExisting Option to search for existing items
566
- * @param templateDictionary Hash of facts: org URL, adlib replacements, deferreds for dependencies
567
- * @param authentication Credentials for the requests
568
- *
569
- * @returns A Promise that will resolve once existing items have been evaluated
570
- *
571
- * @protected
572
- */
573
- function _useExistingItems(templates, useExisting, templateDictionary, authentication) {
574
- return new Promise(function (resolve) {
575
- if (useExisting) {
576
- var itemDefs_1 = [];
577
- var sourceIdHash_1 = {};
578
- var itemIds_1 = [];
579
- Object.keys(templateDictionary.params).forEach(function (k) {
580
- var v = templateDictionary.params[k];
581
- /* istanbul ignore else */
582
- if (v.itemId && /[0-9A-F]{32}/i.test(k)) {
583
- _updateTemplateDictionaryById(templateDictionary, k, v.itemId, v);
584
- // need to check and set the typeKeyword if it doesn't exist on this service yet
585
- // when the user has passed in an itemId that does not come from a previous deployment
586
- itemDefs_1.push(common.getItemBase(v.itemId, authentication));
587
- sourceIdHash_1[v.itemId] = k;
588
- /* istanbul ignore else */
589
- if (itemIds_1.indexOf(k) < 0) {
590
- itemIds_1.push(k);
591
- }
592
- }
593
- });
594
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
595
- _setTypekeywordForExisting(itemDefs_1, sourceIdHash_1, authentication).then(function () {
596
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
597
- _updateTemplateDictionary(itemIds_1.map(function (id) { return common.getTemplateById(templates, id); }), templateDictionary, authentication).then(resolve);
598
- });
599
- }
600
- else {
601
- resolve(null);
602
- }
603
- });
604
- }
605
- /**
606
- * Verify if the existing item has the source-<itemId> typeKeyword and set it if not
607
- * This allows items that did not come from deployment to be found for reuse after they
608
- * have been used once via a custom itemId param
609
- *
610
- * @param itemDefs
611
- * @param sourceIdHash key value pairs..actual itemId is the key and the source itemId is the value
612
- * @param authentication credentials for the requests
613
- *
614
- * @return a promise to indicate when the requests are complete
615
- */
616
- function _setTypekeywordForExisting(itemDefs, sourceIdHash, authentication) {
617
- return new Promise(function (resolve) {
618
- if (itemDefs.length > 0) {
619
- Promise.all(itemDefs).then(function (results) {
620
- var itemUpdateDefs = [];
621
- results.forEach(function (result) {
622
- var sourceId = sourceIdHash[result.id];
623
- /* istanbul ignore else */
624
- if (result && sourceId && result.typeKeywords) {
625
- var sourceKeyword = "source-" + sourceId;
626
- var typeKeywords = result.typeKeywords;
627
- /* istanbul ignore else */
628
- if (typeKeywords.indexOf(sourceKeyword) < 0) {
629
- typeKeywords.push(sourceKeyword);
630
- var itemUpdate = { id: result.id, typeKeywords: typeKeywords };
631
- itemUpdateDefs.push(common.updateItem(itemUpdate, authentication));
632
- }
633
- }
634
- });
635
- // wait for updates to finish before we resolve
636
- if (itemUpdateDefs.length > 0) {
637
- Promise.all(itemUpdateDefs).then(resolve, function () { return resolve(undefined); });
638
- }
639
- else {
640
- resolve(undefined);
641
- }
642
- }, function () { return resolve(undefined); });
643
- }
644
- else {
645
- resolve(undefined);
646
- }
647
- });
648
- }
649
- /**
650
- * Update the templateDictionary with key details by item type
651
- *
652
- * @param templates A collection of AGO item templates
653
- * @param templateDictionary Hash of facts: org URL, adlib replacements, deferreds for dependencies
654
- *
655
- * @protected
656
- */
657
- function _updateTemplateDictionary(templates, templateDictionary, authentication) {
658
- return new Promise(function (resolve) {
659
- var defs = [];
660
- var urls = [];
661
- var types = [];
662
- var ids = [];
663
- templates.forEach(function (t) {
664
- var templateInfo = templateDictionary[t.itemId];
665
- /* istanbul ignore else */
666
- if (templateInfo && templateInfo.url && templateInfo.itemId) {
667
- /* istanbul ignore else */
668
- if (t.item.type === "Feature Service") {
669
- var enterpriseIDMapping = common.getProp(templateDictionary, "params." + t.itemId + ".enterpriseIDMapping");
670
- Object.assign(templateDictionary[t.itemId], common.getLayerSettings(common.getLayersAndTables(t), templateInfo.url, templateInfo.itemId, enterpriseIDMapping));
671
- // if the service has veiws keep track of the fields so we can use them to
672
- // compare with the view fields
673
- /* istanbul ignore else */
674
- if (common.getProp(t, "properties.service.hasViews")) {
675
- common._updateTemplateDictionaryFields(t, templateDictionary, false);
676
- }
677
- }
678
- // for fs query with its url...for non fs query the item
679
- // this is to verify situations where we have a stale search index that will
680
- // say some items exist when they don't really exist
681
- // searching the services url or with the item id will return an error when this condition occurs
682
- /* istanbul ignore else */
683
- if (urls.indexOf(templateInfo.url) < 0) {
684
- defs.push(t.item.type === "Feature Service"
685
- ? common.rest_request(templateInfo.url, { authentication: authentication })
686
- : common.getItemBase(templateInfo.itemId, authentication));
687
- urls.push(templateInfo.url);
688
- types.push(t.item.type);
689
- ids.push(templateInfo.itemId);
690
- }
691
- }
692
- });
693
- if (defs.length > 0) {
694
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
695
- Promise.all(defs.map(function (p) { return p.catch(function (e) { return e; }); })).then(function (results) {
696
- /* istanbul ignore else */
697
- if (Array.isArray(results) && results.length > 0) {
698
- var fieldDefs_1 = [];
699
- results.forEach(function (r, i) {
700
- // a feature service result will contain a serviceItemId if it was successfully fetched
701
- if (r.serviceItemId && types[i] === "Feature Service") {
702
- Object.keys(templateDictionary).forEach(function (k) {
703
- var v = templateDictionary[k];
704
- /* istanbul ignore else */
705
- if (v.itemId && v.itemId === r.serviceItemId) {
706
- common.setDefaultSpatialReference(templateDictionary, k, r.spatialReference);
707
- // keep the extent values from these responses as well
708
- common.setCreateProp(templateDictionary, k + ".defaultExtent", r.fullExtent || r.initialExtent);
709
- var layerIds = (r.layers || []).map(function (l) { return l.id; });
710
- var tablesIds = (r.tables || []).map(function (t) { return t.id; });
711
- fieldDefs_1.push(common.getExistingLayersAndTables(urls[i], layerIds.concat(tablesIds), authentication));
712
- }
713
- });
714
- }
715
- else {
716
- /* istanbul ignore else */
717
- if (types[i] === "Feature Service" ||
718
- common.getProp(r, "response.error")) {
719
- // if an error is returned we need to clean up the templateDictionary
720
- templateDictionary = _updateTemplateDictionaryForError(templateDictionary, ids[i]);
721
- }
722
- }
723
- });
724
- if (fieldDefs_1.length > 0) {
725
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
726
- Promise.all(fieldDefs_1).then(function (layerTableResult) {
727
- layerTableResult.forEach(function (l) {
728
- l.forEach(function (ll) {
729
- Object.keys(templateDictionary).forEach(function (k) {
730
- /* istanbul ignore else */
731
- if (templateDictionary[k].itemId === ll.serviceItemId) {
732
- var sourceId_1 = "";
733
- Object.keys(templateDictionary).some(function (_k) {
734
- /* istanbul ignore else */
735
- if (templateDictionary[_k].itemId === ll.serviceItemId) {
736
- sourceId_1 = _k;
737
- return true;
738
- }
739
- });
740
- var enterpriseIDMapping_1 = common.getProp(templateDictionary, "params." + sourceId_1 + ".enterpriseIDMapping");
741
- if (enterpriseIDMapping_1) {
742
- Object.keys(enterpriseIDMapping_1).forEach(function (id) {
743
- if (enterpriseIDMapping_1[id].toString() ===
744
- ll.id.toString()) {
745
- _setFields(templateDictionary, k, id, ll.fields);
746
- }
747
- });
748
- }
749
- else {
750
- _setFields(templateDictionary, k, ll.id, ll.fields);
751
- }
752
- }
753
- });
754
- });
755
- });
756
- resolve(null);
757
- });
758
- }
759
- else {
760
- resolve(null);
761
- }
762
- }
763
- else {
764
- resolve(null);
765
- }
766
- });
767
- }
768
- else {
769
- resolve(null);
770
- }
771
- });
772
- }
773
- /**
774
- * Add the fields from the source layer to the template dictionary for any required replacements
775
- *
776
- * @param templateDictionary Hash of facts: org URL, adlib replacements, deferreds for dependencies
777
- * @param itemId the id for the item
778
- * @param layerId the id for the layer
779
- * @param fields the fields to transfer
780
- *
781
- * @protected
782
- */
783
- function _setFields(templateDictionary, itemId, layerId, fields) {
784
- var layerInfo = common.getProp(templateDictionary, itemId + ".layer" + layerId);
785
- /* istanbul ignore else */
786
- if (layerInfo && fields) {
787
- layerInfo.fields = fields;
788
- }
789
- }
790
- /**
791
- * In some cases an item id search will return a stale item reference
792
- * it will subsequently fail when we try to fetch the underlying service.
793
- *
794
- * We need to remove the item info that has been added to the template dictionary
795
- * and treat the item as we do other items that don't already exist on deployment.
796
- *
797
- * @param result the service request result
798
- * @param templateDictionary Hash of facts: org URL, adlib replacements, deferreds for dependencies
799
- *
800
- * @protected
801
- */
802
- function _updateTemplateDictionaryForError(templateDictionary, itemId) {
803
- /* istanbul ignore else */
804
- if (itemId) {
805
- var removeKey_1 = "";
806
- Object.keys(templateDictionary).some(function (k) {
807
- /* istanbul ignore else */
808
- if (templateDictionary[k].itemId === itemId) {
809
- removeKey_1 = k;
810
- return true;
811
- }
812
- });
813
- /* istanbul ignore else */
814
- if (removeKey_1 !== "") {
815
- delete templateDictionary[removeKey_1];
816
- }
817
- }
818
- return templateDictionary;
819
- }
820
- /**
821
- * Optionally search by tags and then update the templateDictionary based on the search results
822
- *
823
- * @param existingItemsResponse response object from search by typeKeyword and type
824
- * @param templateDictionary Hash of facts: org URL, adlib replacements, deferreds for dependencies
825
- * @param authentication Credentials for the request
826
- * @param addTagQuery Boolean to indicate if a search by tag should happen
827
- * @return A promise that will resolve with an array of results
828
- * @protected
829
- */
830
- function _handleExistingItems(existingItemsResponse, templateDictionary, authentication, addTagQuery) {
831
- // if items are not found by type keyword search by tag
832
- var existingItemsByTag = [Promise.resolve(null)];
833
- /* istanbul ignore else */
834
- if (existingItemsResponse && Array.isArray(existingItemsResponse)) {
835
- existingItemsResponse.forEach(function (existingItem) {
836
- /* istanbul ignore else */
837
- if (Array.isArray(existingItem === null || existingItem === void 0 ? void 0 : existingItem.results)) {
838
- var result = void 0;
839
- var results = existingItem.results;
840
- if (results.length === 1) {
841
- result = results[0];
842
- }
843
- else if (results.length > 1) {
844
- result = results.reduce(function (a, b) {
845
- return a.created > b.created ? a : b;
846
- });
847
- }
848
- else {
849
- if (addTagQuery && existingItem.query) {
850
- var tagQuery = existingItem.query.replace("typekeywords", "tags");
851
- existingItemsByTag.push(_findExistingItem(tagQuery, authentication));
852
- }
853
- }
854
- if (result) {
855
- var sourceId = existingItem.query
856
- ? existingItem.query.match(/[0-9A-F]{32}/i)[0]
857
- : existingItem.sourceId;
858
- /* istanbul ignore else */
859
- if (sourceId) {
860
- _updateTemplateDictionaryById(templateDictionary, sourceId, result.id, result);
861
- }
862
- }
863
- }
864
- });
865
- }
866
- return existingItemsByTag;
867
- }
868
- function _updateTemplateDictionaryById(templateDictionary, sourceId, itemId, v) {
869
- templateDictionary[sourceId] = Object.assign(templateDictionary[sourceId] || {}, {
870
- def: Promise.resolve(common.generateEmptyCreationResponse(v.type, itemId)),
871
- itemId: itemId,
872
- name: v.name,
873
- title: v.title,
874
- url: v.url
875
- });
876
- }
877
- /**
878
- * Search items based on user query
879
- *
880
- * @param query Query string to use
881
- * @param authentication Credentials for the request
882
- * @return A promise that will resolve with an array of results
883
- * @protected
884
- */
885
- function _findExistingItemByKeyword(templates, templateDictionary, authentication) {
886
- var existingItemsDefs = [];
887
- templates.forEach(function (template) {
888
- var _a;
889
- if (template.item.type === "Group") {
890
- var userGroups = (_a = templateDictionary.user) === null || _a === void 0 ? void 0 : _a.groups;
891
- /* istanbul ignore else */
892
- if (Array.isArray(userGroups)) {
893
- existingItemsDefs.push(Promise.resolve({
894
- results: userGroups
895
- .filter(function (g) { return g.tags.indexOf("source-" + template.itemId) > -1; })
896
- .map(function (g) {
897
- g.type = "Group";
898
- return g;
899
- }),
900
- sourceId: template.itemId
901
- }));
902
- }
903
- }
904
- else {
905
- existingItemsDefs.push(_findExistingItem("typekeywords:source-" + template.itemId + " type:" + template.item.type + " owner:" + templateDictionary.user.username, authentication));
906
- }
907
- });
908
- return existingItemsDefs;
909
- }
910
- /**
911
- * Search items based on user query
912
- *
913
- * @param query Query string to use
914
- * @param authentication Credentials for the request
915
- * @return A promise that will resolve with an array of results
916
- * @protected
917
- */
918
- function _findExistingItem(query, authentication) {
919
- var searchOptions = {
920
- q: query,
921
- authentication: authentication,
922
- pagingParam: { start: 1, num: 100 }
923
- };
924
- return common.searchItems(searchOptions);
925
- }
926
- /**
927
- * Creates an item from a template once the item's dependencies have been created.
928
- *
929
- * @param template Template of item to deploy
930
- * @param resourceFilePaths URL, folder, and filename for each item resource/metadata/thumbnail
931
- * @param templateDictionary Hash of facts: org URL, adlib replacements, deferreds for dependencies
932
- * @param userSession Options for the request
933
- * @param itemProgressCallback Function for reporting progress updates from type-specific template handlers
934
- * @return A promise that will resolve with the id of the deployed item (which is simply returned if it's
935
- * already in the templates list
936
- * @protected
937
- */
938
- function _createItemFromTemplateWhenReady(template, resourceFilePaths, storageAuthentication, templateDictionary, destinationAuthentication, itemProgressCallback) {
939
- // ensure this is present
940
- template.dependencies = template.dependencies || [];
941
- // if there is no entry in the templateDictionary
942
- // or if we have a basic entry without the deferred request for its creation, add it
943
- if (!templateDictionary.hasOwnProperty(template.itemId) ||
944
- !common.getProp(templateDictionary[template.itemId], "def")) {
945
- var createResponse_1;
946
- var statusCode_1 = common.EItemProgressStatus.Unknown;
947
- var itemHandler_1;
948
- templateDictionary[template.itemId] =
949
- templateDictionary[template.itemId] || {};
950
- // Save the deferred for the use of items that depend on this item being created first
951
- templateDictionary[template.itemId].def = new Promise(function (resolve) {
952
- // Wait until all of the item's dependencies are deployed
953
- var _awaitDependencies = template.dependencies.reduce(function (acc, id) {
954
- var def = common.getProp(templateDictionary, id + ".def");
955
- // can't use maybePush as that clones the object, which does not work for Promises
956
- /* istanbul ignore else */
957
- if (def) {
958
- acc.push(def);
959
- }
960
- return acc;
961
- }, []);
962
- var syncViews = common.getProp(template, "properties.syncViews");
963
- var awaitDependencies = syncViews && syncViews.length > 0
964
- ? syncViews.reduce(function (acc, v) {
965
- var def = common.getProp(templateDictionary, v + ".def");
966
- /* istanbul ignore else */
967
- if (def) {
968
- acc.push(def);
969
- }
970
- return acc;
971
- }, _awaitDependencies)
972
- : _awaitDependencies;
973
- Promise.all(awaitDependencies)
974
- .then(function () {
975
- // Find the conversion handler for this item type
976
- var templateType = template.type;
977
- itemHandler_1 = moduleMap[templateType];
978
- if (!itemHandler_1 || itemHandler_1 === UNSUPPORTED$1) {
979
- if (itemHandler_1 === UNSUPPORTED$1) {
980
- statusCode_1 = common.EItemProgressStatus.Ignored;
981
- throw new Error();
982
- }
983
- else {
984
- statusCode_1 = common.EItemProgressStatus.Failed;
985
- throw new Error();
986
- }
987
- }
988
- // Get the item's thumbnail
989
- return common.getThumbnailFromStorageItem(storageAuthentication, resourceFilePaths);
990
- })
991
- .then(function (thumbnail) {
992
- template.item.thumbnail = thumbnail;
993
- // Delegate the creation of the item to the handler
994
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
995
- return itemHandler_1.createItemFromTemplate(template, templateDictionary, destinationAuthentication, itemProgressCallback);
996
- })
997
- .then(function (response) {
998
- if (response.id === "") {
999
- statusCode_1 = common.EItemProgressStatus.Failed;
1000
- throw new Error("handled"); // fails to create item
1001
- }
1002
- /* istanbul ignore else */
1003
- createResponse_1 = response;
1004
- if (createResponse_1.item.item.url) {
1005
- common.setCreateProp(templateDictionary, template.itemId + ".url", createResponse_1.item.item.url);
1006
- }
1007
- if (resourceFilePaths.length > 0) {
1008
- // Copy resources, metadata, form
1009
- return common.copyFilesFromStorageItem(storageAuthentication, resourceFilePaths, templateDictionary.folderId, createResponse_1.id, destinationAuthentication, createResponse_1.item);
1010
- }
1011
- else {
1012
- return Promise.resolve(null);
1013
- }
1014
- })
1015
- .then(function () {
1016
- resolve(createResponse_1);
1017
- })
1018
- .catch(function (error) {
1019
- if (!error || error.message !== "handled") {
1020
- itemProgressCallback(template.itemId, statusCode_1 === common.EItemProgressStatus.Unknown
1021
- ? common.EItemProgressStatus.Failed
1022
- : statusCode_1, 0);
1023
- }
1024
- // Item type not supported or fails to get item dependencies
1025
- resolve(common.generateEmptyCreationResponse(template.type));
1026
- });
1027
- });
1028
- }
1029
- return templateDictionary[template.itemId].def;
1030
- }
1031
- /**
1032
- * Accumulates the estimated deployment cost of a set of templates.
1033
- *
1034
- * @param templates Templates to examine
1035
- * @return Sum of estimated deployment costs
1036
- * @protected
1037
- */
1038
- function _estimateDeploymentCost(templates) {
1039
- return templates.reduce(function (accumulatedEstimatedCost, template) {
1040
- return (accumulatedEstimatedCost + (template.estimatedDeploymentCostFactor || 1));
1041
- }, 0);
1042
- }
1043
- // TODO: Return a Promise vs array of promises
1044
- function _getGroupUpdates(template, authentication, templateDictionary) {
1045
- var groups = template.groups || [];
1046
- return groups.map(function (sourceGroupId) {
1047
- return common.shareItem(templateDictionary[sourceGroupId].itemId, template.itemId, authentication);
1048
- });
1049
- }
1001
+ /** @license
1002
+ * Copyright 2020 Esri
1003
+ *
1004
+ * Licensed under the Apache License, Version 2.0 (the "License");
1005
+ * you may not use this file except in compliance with the License.
1006
+ * You may obtain a copy of the License at
1007
+ *
1008
+ * http://www.apache.org/licenses/LICENSE-2.0
1009
+ *
1010
+ * Unless required by applicable law or agreed to in writing, software
1011
+ * distributed under the License is distributed on an "AS IS" BASIS,
1012
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1013
+ * See the License for the specific language governing permissions and
1014
+ * limitations under the License.
1015
+ */
1016
+ /**
1017
+ * Given the created templates
1018
+ *
1019
+ * @param templates
1020
+ * @param templateDictionary
1021
+ * @param authentication
1022
+ */
1023
+ function shareTemplatesToGroups(templates, templateDictionary, authentication) {
1024
+ // Filter to entries with groups to share to
1025
+ const templatesWithGroups = templates.filter(e => {
1026
+ return e.groups && e.groups.length > 0;
1027
+ });
1028
+ // fire off all the promises
1029
+ return Promise.all(templatesWithGroups.map(tmpl => {
1030
+ const groupIds = tmpl.groups.reduce((acc, sourceGroupId) => {
1031
+ return hubCommon.maybePush(common.getProp(templateDictionary, `${sourceGroupId}.itemId`), acc);
1032
+ }, []);
1033
+ // need to pass the tracking owner when sharing to tracking group
1034
+ if (common.isTrackingViewTemplate(tmpl) && !common.getProp(templateDictionary, "locationTracking.userIsOwner")) {
1035
+ const trackingGroupId = common.getProp(tmpl, "item.properties.trackViewGroup");
1036
+ const owner = common.getProp(templateDictionary, "locationTracking.owner");
1037
+ /* istanbul ignore else */
1038
+ if (trackingGroupId && owner) {
1039
+ const trackerGroupIds = groupIds.filter(id => {
1040
+ return id === common.replaceInTemplate(trackingGroupId, templateDictionary);
1041
+ });
1042
+ if (trackerGroupIds.length !== groupIds.length) {
1043
+ const nonTrackerGroupIds = groupIds.filter(id => id !== trackingGroupId);
1044
+ return Promise.all([
1045
+ common.shareItemToGroups(trackerGroupIds, tmpl.itemId, authentication, owner),
1046
+ common.shareItemToGroups(nonTrackerGroupIds, tmpl.itemId, authentication)
1047
+ ]);
1048
+ }
1049
+ else {
1050
+ return common.shareItemToGroups(groupIds, tmpl.itemId, authentication, owner);
1051
+ }
1052
+ }
1053
+ }
1054
+ else {
1055
+ return common.shareItemToGroups(groupIds, tmpl.itemId, authentication);
1056
+ }
1057
+ }));
1058
+ }
1050
1059
 
1051
- /** @license
1052
- * Copyright 2020 Esri
1053
- *
1054
- * Licensed under the Apache License, Version 2.0 (the "License");
1055
- * you may not use this file except in compliance with the License.
1056
- * You may obtain a copy of the License at
1057
- *
1058
- * http://www.apache.org/licenses/LICENSE-2.0
1059
- *
1060
- * Unless required by applicable law or agreed to in writing, software
1061
- * distributed under the License is distributed on an "AS IS" BASIS,
1062
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1063
- * See the License for the specific language governing permissions and
1064
- * limitations under the License.
1065
- */
1066
- /**
1067
- * Given the created templates
1068
- *
1069
- * @param templates
1070
- * @param templateDictionary
1071
- * @param authentication
1072
- */
1073
- function shareTemplatesToGroups(templates, templateDictionary, authentication) {
1074
- // Filter to entries with groups to share to
1075
- var templatesWithGroups = templates.filter(function (e) {
1076
- return e.groups && e.groups.length > 0;
1077
- });
1078
- // fire off all the promises
1079
- return Promise.all(templatesWithGroups.map(function (tmpl) {
1080
- var groupIds = tmpl.groups.reduce(function (acc, sourceGroupId) {
1081
- return hubCommon.maybePush(common.getProp(templateDictionary, sourceGroupId + ".itemId"), acc);
1082
- }, []);
1083
- return common.shareItemToGroups(groupIds, tmpl.itemId, authentication);
1084
- }));
1085
- }
1060
+ /** @license
1061
+ * Copyright 2020 Esri
1062
+ *
1063
+ * Licensed under the Apache License, Version 2.0 (the "License");
1064
+ * you may not use this file except in compliance with the License.
1065
+ * You may obtain a copy of the License at
1066
+ *
1067
+ * http://www.apache.org/licenses/LICENSE-2.0
1068
+ *
1069
+ * Unless required by applicable law or agreed to in writing, software
1070
+ * distributed under the License is distributed on an "AS IS" BASIS,
1071
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1072
+ * See the License for the specific language governing permissions and
1073
+ * limitations under the License.
1074
+ */
1075
+ /**
1076
+ * Delegate post-processing to the type specific
1077
+ * processors. This allows each type to have fine-grained
1078
+ * control over what they do. Common post-processing is
1079
+ * exposed as functions that can be imported
1080
+ *
1081
+ * @param deployedSolutionId
1082
+ * @param templates
1083
+ * @param clonedSolutions
1084
+ * @param authentication
1085
+ * @param templateDictionary
1086
+ */
1087
+ function postProcess(deployedSolutionId, templates, clonedSolutions, authentication, templateDictionary) {
1088
+ // connect the solution with its items; groups cannot be connected
1089
+ const relationshipPromises = clonedSolutions
1090
+ .filter(entry => entry.type !== "Group")
1091
+ .map(entry => portal.addItemRelationship({
1092
+ originItemId: deployedSolutionId,
1093
+ destinationItemId: entry.id,
1094
+ relationshipType: "Solution2Item",
1095
+ authentication: authentication
1096
+ }) // TODO: remove `as any`, which is here until arcgis-rest-js' ItemRelationshipType defn catches up
1097
+ );
1098
+ // delegate sharing to groups
1099
+ const sharePromises = shareTemplatesToGroups(templates, templateDictionary, authentication);
1100
+ // what needs post processing?
1101
+ const itemsToProcess = clonedSolutions.filter(entry => entry.postProcess);
1102
+ // map over these items
1103
+ const postProcessPromises = itemsToProcess.reduce((acc, entry) => {
1104
+ const itemHandler = moduleMap[entry.type];
1105
+ // only delegate if the handler has a postProcess method
1106
+ if (itemHandler && itemHandler.postProcess) {
1107
+ acc.push(itemHandler.postProcess(entry.id, entry.type, clonedSolutions, common.getTemplateById(templates, entry.id), templates, templateDictionary, authentication));
1108
+ }
1109
+ return acc;
1110
+ }, []);
1111
+ return Promise.all([sharePromises].concat(postProcessPromises, relationshipPromises));
1112
+ }
1086
1113
 
1087
- /** @license
1088
- * Copyright 2020 Esri
1089
- *
1090
- * Licensed under the Apache License, Version 2.0 (the "License");
1091
- * you may not use this file except in compliance with the License.
1092
- * You may obtain a copy of the License at
1093
- *
1094
- * http://www.apache.org/licenses/LICENSE-2.0
1095
- *
1096
- * Unless required by applicable law or agreed to in writing, software
1097
- * distributed under the License is distributed on an "AS IS" BASIS,
1098
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1099
- * See the License for the specific language governing permissions and
1100
- * limitations under the License.
1101
- */
1102
- /**
1103
- * Delegate post-processing to the type specific
1104
- * processors. This allows each type to have fine-grained
1105
- * control over what they do. Common post-processing is
1106
- * exposed as functions that can be imported
1107
- *
1108
- * @param deployedSolutionId
1109
- * @param templates
1110
- * @param clonedSolutions
1111
- * @param authentication
1112
- * @param templateDictionary
1113
- */
1114
- function postProcess(deployedSolutionId, templates, clonedSolutions, authentication, templateDictionary) {
1115
- // connect the solution with its items; groups cannot be connected
1116
- var relationshipPromises = clonedSolutions
1117
- .filter(function (entry) { return entry.type !== "Group"; })
1118
- .map(function (entry) {
1119
- return portal.addItemRelationship({
1120
- originItemId: deployedSolutionId,
1121
- destinationItemId: entry.id,
1122
- relationshipType: "Solution2Item",
1123
- authentication: authentication
1124
- });
1125
- } // TODO: remove `as any`, which is here until arcgis-rest-js' ItemRelationshipType defn catches up
1126
- );
1127
- // delegate sharing to groups
1128
- var sharePromises = shareTemplatesToGroups(templates, templateDictionary, authentication);
1129
- // what needs post processing?
1130
- var itemsToProcess = clonedSolutions.filter(function (entry) { return entry.postProcess; });
1131
- // map over these items
1132
- var postProcessPromises = itemsToProcess.reduce(function (acc, entry) {
1133
- var itemHandler = moduleMap[entry.type];
1134
- // only delegate if the handler has a postProcess method
1135
- if (itemHandler && itemHandler.postProcess) {
1136
- acc.push(itemHandler.postProcess(entry.id, entry.type, clonedSolutions, common.getTemplateById(templates, entry.id), templates, templateDictionary, authentication));
1137
- }
1138
- return acc;
1139
- }, []);
1140
- return Promise.all([sharePromises].concat(postProcessPromises, relationshipPromises));
1141
- }
1114
+ /**
1115
+ * Sorts a list of templates in place to match a provided sort-order list.
1116
+ *
1117
+ * @param templates List of templates in a Solution
1118
+ * @param sortOrderIds List of template ids in the desired sort order
1119
+ */
1120
+ function sortTemplates(templates, sortOrderIds) {
1121
+ templates.sort((template1, template2) => sortOrderIds.indexOf(template1.itemId) -
1122
+ sortOrderIds.indexOf(template2.itemId));
1123
+ }
1142
1124
 
1143
- /**
1144
- * Sorts a list of templates in place to match a provided sort-order list.
1145
- *
1146
- * @param templates List of templates in a Solution
1147
- * @param sortOrderIds List of template ids in the desired sort order
1148
- */
1149
- function sortTemplates(templates, sortOrderIds) {
1150
- templates.sort(function (template1, template2) {
1151
- return sortOrderIds.indexOf(template1.itemId) -
1152
- sortOrderIds.indexOf(template2.itemId);
1153
- });
1154
- }
1125
+ /** @license
1126
+ * Copyright 2018 Esri
1127
+ *
1128
+ * Licensed under the Apache License, Version 2.0 (the "License");
1129
+ * you may not use this file except in compliance with the License.
1130
+ * You may obtain a copy of the License at
1131
+ *
1132
+ * http://www.apache.org/licenses/LICENSE-2.0
1133
+ *
1134
+ * Unless required by applicable law or agreed to in writing, software
1135
+ * distributed under the License is distributed on an "AS IS" BASIS,
1136
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1137
+ * See the License for the specific language governing permissions and
1138
+ * limitations under the License.
1139
+ */
1140
+ // NOTE: Moved to separate file to allow stubbing in main deploySolution tests
1141
+ function deploySolutionFromTemplate(templateSolutionId, solutionTemplateBase, solutionTemplateData, authentication, options) {
1142
+ options.storageVersion = common.extractSolutionVersion(solutionTemplateData);
1143
+ return new Promise((resolve, reject) => {
1144
+ // It is possible to provide a separate authentication for the source
1145
+ const storageAuthentication = options.storageAuthentication
1146
+ ? options.storageAuthentication
1147
+ : authentication;
1148
+ // Replacement dictionary and high-level deployment ids for cleanup
1149
+ // TODO: Extract all templateDictionary prep into a separate function
1150
+ const templateDictionary = options.templateDictionary ?? {};
1151
+ let deployedFolderId;
1152
+ let deployedSolutionId;
1153
+ _applySourceToDeployOptions(options, solutionTemplateBase, templateDictionary, authentication);
1154
+ if (options.additionalTypeKeywords) {
1155
+ solutionTemplateBase.typeKeywords = [].concat(solutionTemplateBase.typeKeywords, options.additionalTypeKeywords);
1156
+ }
1157
+ // Get the thumbnail file
1158
+ let thumbFilename = "thumbnail";
1159
+ let thumbDef = Promise.resolve(null);
1160
+ if (!options.thumbnail && options.thumbnailurl) {
1161
+ // Figure out the thumbnail's filename
1162
+ thumbFilename =
1163
+ common.getFilenameFromUrl(options.thumbnailurl) || thumbFilename;
1164
+ const thumbnailurl = common.appendQueryParam(options.thumbnailurl, "w=400");
1165
+ delete options.thumbnailurl;
1166
+ // Fetch the thumbnail
1167
+ thumbDef = common.getBlobAsFile(thumbnailurl, thumbFilename, storageAuthentication, [400]);
1168
+ }
1169
+ _replaceParamVariables(solutionTemplateData, templateDictionary);
1170
+ // Get information about deployment environment
1171
+ Promise.all([
1172
+ common.getPortal("", authentication),
1173
+ common.getUser(authentication),
1174
+ common.getFoldersAndGroups(authentication),
1175
+ thumbDef
1176
+ ])
1177
+ .then(responses => {
1178
+ const [portalResponse, userResponse, foldersAndGroupsResponse, thumbnailFile] = responses;
1179
+ if (!options.thumbnail && thumbnailFile) {
1180
+ options.thumbnail = thumbnailFile;
1181
+ }
1182
+ // update template items with source-itemId type keyword
1183
+ solutionTemplateData.templates = solutionTemplateData.templates.map((template) => {
1184
+ const sourceId = "source-" + template.itemId;
1185
+ /* istanbul ignore else */
1186
+ if (template.item) {
1187
+ /* istanbul ignore else */
1188
+ if (template.item.typeKeywords) {
1189
+ template.item.typeKeywords.push(sourceId);
1190
+ }
1191
+ /* istanbul ignore else */
1192
+ if (template.item.tags &&
1193
+ common.getProp(template, "item.type") === "Group") {
1194
+ template.item.tags.push(sourceId);
1195
+ }
1196
+ }
1197
+ return template;
1198
+ });
1199
+ templateDictionary.isPortal = portalResponse.isPortal;
1200
+ templateDictionary.organization = Object.assign(templateDictionary.organization || {}, portalResponse);
1201
+ // TODO: Add more computed properties here
1202
+ // portal: portalResponse
1203
+ // orgextent as bbox for assignment onto items
1204
+ // more info in #266 https://github.com/Esri/solution.js/issues/266
1205
+ templateDictionary.portalBaseUrl = _getPortalBaseUrl(portalResponse, authentication);
1206
+ templateDictionary.user = userResponse;
1207
+ templateDictionary.user.folders = foldersAndGroupsResponse.folders;
1208
+ templateDictionary.user.groups = foldersAndGroupsResponse.groups.filter((group) => group.owner === templateDictionary.user.username);
1209
+ // if we have tracking views and the user is not admin or the org doesn't support tracking an error is thrown
1210
+ common.setLocationTrackingEnabled(portalResponse, userResponse, templateDictionary, solutionTemplateData.templates);
1211
+ const trackingOwnerPromise = common.getTackingServiceOwner(templateDictionary, authentication);
1212
+ // Create a folder to hold the deployed solution. We use the solution name, appending a sequential
1213
+ // suffix if the folder exists, e.g.,
1214
+ // * Manage Right of Way Activities
1215
+ // * Manage Right of Way Activities 1
1216
+ // * Manage Right of Way Activities 2
1217
+ const folderPromise = common.createUniqueFolder(solutionTemplateBase.title, templateDictionary, authentication);
1218
+ // Apply the portal extents to the solution
1219
+ const portalExtent = portalResponse.defaultExtent;
1220
+ const extentsPromise = common.convertExtentWithFallback(portalExtent, undefined, { wkid: 4326 }, portalResponse.helperServices.geometry.url, authentication);
1221
+ // Await completion of async actions: folder creation & extents conversion
1222
+ return Promise.all([folderPromise, extentsPromise, trackingOwnerPromise]);
1223
+ })
1224
+ .then(responses => {
1225
+ const [folderResponse, wgs84Extent, trackingOwnerResponse] = responses;
1226
+ deployedFolderId = folderResponse.folder.id;
1227
+ templateDictionary.folderId = deployedFolderId;
1228
+ templateDictionary.solutionItemExtent =
1229
+ wgs84Extent.xmin +
1230
+ "," +
1231
+ wgs84Extent.ymin +
1232
+ "," +
1233
+ wgs84Extent.xmax +
1234
+ "," +
1235
+ wgs84Extent.ymax;
1236
+ // Hub Solutions depend on organization defaultExtentBBox as a nested array not a string
1237
+ templateDictionary.organization.defaultExtentBBox = [
1238
+ [wgs84Extent.xmin, wgs84Extent.ymin],
1239
+ [wgs84Extent.xmax, wgs84Extent.ymax]
1240
+ ];
1241
+ // update templateDictionary to indicate if the user owns the tracking service
1242
+ // this will affect how we handle group sharing
1243
+ /* istanbul ignore else */
1244
+ if (templateDictionary.locationTrackingEnabled) {
1245
+ common.setCreateProp(templateDictionary, "locationTracking.userIsOwner", trackingOwnerResponse);
1246
+ }
1247
+ // Create a deployed Solution item
1248
+ const createSolutionItemBase = {
1249
+ ...common.sanitizeJSONAndReportChanges(solutionTemplateBase),
1250
+ type: "Solution",
1251
+ typeKeywords: ["Solution"]
1252
+ };
1253
+ if (options.additionalTypeKeywords) {
1254
+ createSolutionItemBase.typeKeywords = ["Solution"].concat(options.additionalTypeKeywords);
1255
+ }
1256
+ // Create deployed solution item
1257
+ createSolutionItemBase.thumbnail = options.thumbnail;
1258
+ return common.createItemWithData(createSolutionItemBase, {}, authentication, deployedFolderId);
1259
+ })
1260
+ .then(createSolutionResponse => {
1261
+ deployedSolutionId = createSolutionResponse.id;
1262
+ // Protect the solution item
1263
+ const protectOptions = {
1264
+ id: deployedSolutionId,
1265
+ authentication
1266
+ };
1267
+ return portal.protectItem(protectOptions);
1268
+ })
1269
+ .then(() => {
1270
+ // TODO: Attach the whole solution model so we can
1271
+ // have stuff like `{{solution.item.title}}
1272
+ templateDictionary.solutionItemId = deployedSolutionId;
1273
+ solutionTemplateBase.id = deployedSolutionId;
1274
+ solutionTemplateBase.tryitUrl = _checkedReplaceAll(solutionTemplateBase.tryitUrl, templateSolutionId, deployedSolutionId);
1275
+ solutionTemplateBase.url = _checkedReplaceAll(solutionTemplateBase.url, templateSolutionId, deployedSolutionId);
1276
+ // Handle the contained item templates
1277
+ return deploySolutionItems(storageAuthentication.portal, templateSolutionId, solutionTemplateData.templates, storageAuthentication, templateDictionary, deployedSolutionId, authentication, options);
1278
+ })
1279
+ .then((clonedSolutionsResponse) => {
1280
+ solutionTemplateData.templates = solutionTemplateData.templates.map((itemTemplate) => {
1281
+ // Update ids present in template dictionary
1282
+ itemTemplate.itemId = common.getProp(templateDictionary, `${itemTemplate.itemId}.itemId`);
1283
+ // Update the dependencies hash to point to the new item ids
1284
+ itemTemplate.dependencies = itemTemplate.dependencies.map((id) => hubCommon.getWithDefault(templateDictionary, `${id}.itemId`, id));
1285
+ return itemTemplate;
1286
+ });
1287
+ // Sort the templates into build order, which is provided by clonedSolutionsResponse
1288
+ sortTemplates(solutionTemplateData.templates, clonedSolutionsResponse.map(response => response.id));
1289
+ // Wrap up with post-processing, in which we deal with groups and cycle remnants
1290
+ return postProcess(deployedSolutionId, solutionTemplateData.templates, clonedSolutionsResponse, authentication, templateDictionary);
1291
+ })
1292
+ .then(() => {
1293
+ // Update solution item using internal representation & and the updated data JSON
1294
+ solutionTemplateBase.typeKeywords = [].concat(solutionTemplateBase.typeKeywords, ["Deployed"]);
1295
+ const iTemplateKeyword = solutionTemplateBase.typeKeywords.indexOf("Template");
1296
+ /* istanbul ignore else */
1297
+ if (iTemplateKeyword >= 0) {
1298
+ solutionTemplateBase.typeKeywords.splice(iTemplateKeyword, 1);
1299
+ }
1300
+ solutionTemplateData.templates = solutionTemplateData.templates.map((itemTemplate) => _purgeTemplateProperties(itemTemplate));
1301
+ solutionTemplateData.templates = _updateGroupReferences(solutionTemplateData.templates, templateDictionary);
1302
+ // Update solution items data using template dictionary, and then update the
1303
+ // itemId & dependencies in each item template
1304
+ solutionTemplateBase.data = common.replaceInTemplate(solutionTemplateData, templateDictionary);
1305
+ // Write any user defined params to the solution
1306
+ /* istanbul ignore else */
1307
+ if (templateDictionary.params) {
1308
+ solutionTemplateBase.data.params = templateDictionary.params;
1309
+ }
1310
+ return common.updateItem(solutionTemplateBase, authentication, deployedFolderId);
1311
+ })
1312
+ .then(() => resolve(solutionTemplateBase.id), reject);
1313
+ });
1314
+ }
1315
+ /**
1316
+ * Update the deployOptions with the group properties
1317
+ *
1318
+ * @param deployOptions
1319
+ * @param sourceInfo
1320
+ * @param authentication
1321
+ * @param isGroup Boolean to indicate if the files are associated with a group or item
1322
+ * @internal
1323
+ */
1324
+ function _applySourceToDeployOptions(deployOptions, solutionTemplateBase, templateDictionary, authentication) {
1325
+ // Deploy a solution from the template's contents,
1326
+ // using the template's information as defaults for the deployed solution item
1327
+ ["title", "snippet", "description", "tags"].forEach(prop => {
1328
+ deployOptions[prop] = deployOptions[prop] ?? solutionTemplateBase[prop];
1329
+ if (deployOptions[prop]) {
1330
+ solutionTemplateBase[prop] = deployOptions[prop];
1331
+ // carry these options forward on the templateDict
1332
+ templateDictionary[prop] = deployOptions[prop];
1333
+ }
1334
+ });
1335
+ if (!deployOptions.thumbnailurl && solutionTemplateBase.thumbnail) {
1336
+ // Get the full path to the thumbnail
1337
+ deployOptions.thumbnailurl = common.generateSourceThumbnailUrl(authentication.portal, solutionTemplateBase.id, solutionTemplateBase.thumbnail);
1338
+ delete solutionTemplateBase.thumbnail;
1339
+ }
1340
+ return deployOptions;
1341
+ }
1342
+ function _replaceParamVariables(solutionTemplateData, templateDictionary) {
1343
+ // a custom params object can be passed in with the options to deploy a solution
1344
+ // in most cases we can defer to the item type handlers to use these values
1345
+ // for variable replacement
1346
+ // for spatial reference specifically we need to replace up front so the default extent
1347
+ // logic can execute as expected
1348
+ solutionTemplateData.templates = solutionTemplateData.templates.map((template) => {
1349
+ // can't do this as it causes other values that don't exist in the dict yet to revert to defaults they may have defined
1350
+ // return common.replaceInTemplate(template, templateDictionary);
1351
+ /* istanbul ignore else */
1352
+ if (template.type === "Feature Service") {
1353
+ const paramsLookup = "params.";
1354
+ const wkidItemPath = "item.spatialReference.wkid";
1355
+ template = _updateProp(template, wkidItemPath, paramsLookup, templateDictionary);
1356
+ const wkidServicePath = "properties.service.spatialReference.wkid";
1357
+ template = _updateProp(template, wkidServicePath, paramsLookup, templateDictionary);
1358
+ }
1359
+ return template;
1360
+ });
1361
+ }
1362
+ function _updateProp(template, path, lookup, templateDictionary) {
1363
+ const wkid = common.getProp(template, path);
1364
+ /* istanbul ignore else */
1365
+ if (wkid && typeof wkid === "string" && wkid.indexOf(lookup) > -1) {
1366
+ common.setProp(template, path, common.replaceInTemplate(wkid, templateDictionary));
1367
+ }
1368
+ return template;
1369
+ }
1370
+ function _checkedReplaceAll(template, oldValue, newValue) {
1371
+ let newTemplate;
1372
+ if (template && template.indexOf(oldValue) > -1) {
1373
+ const re = new RegExp(oldValue, "g");
1374
+ newTemplate = template.replace(re, newValue);
1375
+ }
1376
+ else {
1377
+ newTemplate = template;
1378
+ }
1379
+ return newTemplate;
1380
+ }
1381
+ function _getPortalBaseUrl(portalResponse, authentication) {
1382
+ // As of Spring 2020, only HTTPS (see
1383
+ // https://www.esri.com/arcgis-blog/products/product/administration/2019-arcgis-transport-security-improvements/)
1384
+ const scheme = "https"; // portalResponse.allSSL ? "https" : "http";
1385
+ const urlKey = common.getProp(portalResponse, "urlKey");
1386
+ const customBaseUrl = common.getProp(portalResponse, "customBaseUrl");
1387
+ const enterpriseBaseUrl = common.getProp(portalResponse, "portalHostname");
1388
+ return urlKey && customBaseUrl
1389
+ ? `${scheme}://${urlKey}.${customBaseUrl}`
1390
+ : enterpriseBaseUrl
1391
+ ? `${scheme}://${enterpriseBaseUrl}`
1392
+ : authentication.portal.replace("/sharing/rest", "");
1393
+ }
1394
+ function _updateGroupReferences(itemTemplates, templateDictionary) {
1395
+ const groupIds = itemTemplates.reduce((result, t) => {
1396
+ if (t.type === "Group") {
1397
+ result.push(t.itemId);
1398
+ }
1399
+ return result;
1400
+ }, []);
1401
+ Object.keys(templateDictionary).forEach(k => {
1402
+ const newId = templateDictionary[k].itemId;
1403
+ if (groupIds.indexOf(newId) > -1) {
1404
+ itemTemplates.forEach(t => {
1405
+ t.groups = t.groups.map((id) => (id === k ? newId : id));
1406
+ });
1407
+ }
1408
+ });
1409
+ return itemTemplates;
1410
+ }
1411
+ function _purgeTemplateProperties(itemTemplate) {
1412
+ const retainProps = ["itemId", "type", "dependencies", "groups"];
1413
+ const deleteProps = Object.keys(itemTemplate).filter(k => retainProps.indexOf(k) < 0);
1414
+ common.deleteProps(itemTemplate, deleteProps);
1415
+ return itemTemplate;
1416
+ }
1155
1417
 
1156
- /** @license
1157
- * Copyright 2018 Esri
1158
- *
1159
- * Licensed under the Apache License, Version 2.0 (the "License");
1160
- * you may not use this file except in compliance with the License.
1161
- * You may obtain a copy of the License at
1162
- *
1163
- * http://www.apache.org/licenses/LICENSE-2.0
1164
- *
1165
- * Unless required by applicable law or agreed to in writing, software
1166
- * distributed under the License is distributed on an "AS IS" BASIS,
1167
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1168
- * See the License for the specific language governing permissions and
1169
- * limitations under the License.
1170
- */
1171
- // NOTE: Moved to separate file to allow stubbing in main deploySolution tests
1172
- function deploySolutionFromTemplate(templateSolutionId, solutionTemplateBase, solutionTemplateData, authentication, options) {
1173
- options.storageVersion = common.extractSolutionVersion(solutionTemplateData);
1174
- return new Promise(function (resolve, reject) {
1175
- var _a;
1176
- // It is possible to provide a separate authentication for the source
1177
- var storageAuthentication = options.storageAuthentication
1178
- ? options.storageAuthentication
1179
- : authentication;
1180
- // Replacement dictionary and high-level deployment ids for cleanup
1181
- // TODO: Extract all templateDictionary prep into a separate function
1182
- var templateDictionary = (_a = options.templateDictionary) !== null && _a !== void 0 ? _a : {};
1183
- var deployedFolderId;
1184
- var deployedSolutionId;
1185
- _applySourceToDeployOptions(options, solutionTemplateBase, templateDictionary, authentication);
1186
- if (options.additionalTypeKeywords) {
1187
- solutionTemplateBase.typeKeywords = [].concat(solutionTemplateBase.typeKeywords, options.additionalTypeKeywords);
1188
- }
1189
- // Get the thumbnail file
1190
- var thumbFilename = "thumbnail";
1191
- var thumbDef = Promise.resolve(null);
1192
- if (!options.thumbnail && options.thumbnailurl) {
1193
- // Figure out the thumbnail's filename
1194
- thumbFilename =
1195
- common.getFilenameFromUrl(options.thumbnailurl) || thumbFilename;
1196
- var thumbnailurl = common.appendQueryParam(options.thumbnailurl, "w=400");
1197
- delete options.thumbnailurl;
1198
- // Fetch the thumbnail
1199
- thumbDef = common.getBlobAsFile(thumbnailurl, thumbFilename, storageAuthentication, [400]);
1200
- }
1201
- _replaceParamVariables(solutionTemplateData, templateDictionary);
1202
- // Get information about deployment environment
1203
- Promise.all([
1204
- common.getPortal("", authentication),
1205
- common.getUser(authentication),
1206
- common.getFoldersAndGroups(authentication),
1207
- thumbDef
1208
- ])
1209
- .then(function (responses) {
1210
- var _a = __read(responses, 4), portalResponse = _a[0], userResponse = _a[1], foldersAndGroupsResponse = _a[2], thumbnailFile = _a[3];
1211
- if (!options.thumbnail && thumbnailFile) {
1212
- options.thumbnail = thumbnailFile;
1213
- }
1214
- // update template items with source-itemId type keyword
1215
- solutionTemplateData.templates = solutionTemplateData.templates.map(function (template) {
1216
- var sourceId = "source-" + template.itemId;
1217
- /* istanbul ignore else */
1218
- if (template.item) {
1219
- /* istanbul ignore else */
1220
- if (template.item.typeKeywords) {
1221
- template.item.typeKeywords.push(sourceId);
1222
- }
1223
- /* istanbul ignore else */
1224
- if (template.item.tags &&
1225
- common.getProp(template, "item.type") === "Group") {
1226
- template.item.tags.push(sourceId);
1227
- }
1228
- }
1229
- return template;
1230
- });
1231
- templateDictionary.isPortal = portalResponse.isPortal;
1232
- templateDictionary.organization = Object.assign(templateDictionary.organization || {}, portalResponse);
1233
- // TODO: Add more computed properties here
1234
- // portal: portalResponse
1235
- // orgextent as bbox for assignment onto items
1236
- // more info in #266 https://github.com/Esri/solution.js/issues/266
1237
- templateDictionary.portalBaseUrl = _getPortalBaseUrl(portalResponse, authentication);
1238
- templateDictionary.user = userResponse;
1239
- templateDictionary.user.folders = foldersAndGroupsResponse.folders;
1240
- templateDictionary.user.groups = foldersAndGroupsResponse.groups.filter(function (group) {
1241
- return group.owner === templateDictionary.user.username;
1242
- });
1243
- // Create a folder to hold the deployed solution. We use the solution name, appending a sequential
1244
- // suffix if the folder exists, e.g.,
1245
- // * Manage Right of Way Activities
1246
- // * Manage Right of Way Activities 1
1247
- // * Manage Right of Way Activities 2
1248
- var folderPromise = common.createUniqueFolder(solutionTemplateBase.title, templateDictionary, authentication);
1249
- // Apply the portal extents to the solution
1250
- var portalExtent = portalResponse.defaultExtent;
1251
- var extentsPromise = common.convertExtentWithFallback(portalExtent, undefined, { wkid: 4326 }, portalResponse.helperServices.geometry.url, authentication);
1252
- // Await completion of async actions: folder creation & extents conversion
1253
- return Promise.all([folderPromise, extentsPromise]);
1254
- })
1255
- .then(function (responses) {
1256
- var _a = __read(responses, 2), folderResponse = _a[0], wgs84Extent = _a[1];
1257
- deployedFolderId = folderResponse.folder.id;
1258
- templateDictionary.folderId = deployedFolderId;
1259
- templateDictionary.solutionItemExtent =
1260
- wgs84Extent.xmin +
1261
- "," +
1262
- wgs84Extent.ymin +
1263
- "," +
1264
- wgs84Extent.xmax +
1265
- "," +
1266
- wgs84Extent.ymax;
1267
- // Hub Solutions depend on organization defaultExtentBBox as a nested array not a string
1268
- templateDictionary.organization.defaultExtentBBox = [
1269
- [wgs84Extent.xmin, wgs84Extent.ymin],
1270
- [wgs84Extent.xmax, wgs84Extent.ymax]
1271
- ];
1272
- // Create a deployed Solution item
1273
- var createSolutionItemBase = __assign(__assign({}, common.sanitizeJSONAndReportChanges(solutionTemplateBase)), { type: "Solution", typeKeywords: ["Solution"] });
1274
- if (options.additionalTypeKeywords) {
1275
- createSolutionItemBase.typeKeywords = ["Solution"].concat(options.additionalTypeKeywords);
1276
- }
1277
- // Create deployed solution item
1278
- createSolutionItemBase.thumbnail = options.thumbnail;
1279
- return common.createItemWithData(createSolutionItemBase, {}, authentication, deployedFolderId);
1280
- })
1281
- .then(function (createSolutionResponse) {
1282
- deployedSolutionId = createSolutionResponse.id;
1283
- // Protect the solution item
1284
- var protectOptions = {
1285
- id: deployedSolutionId,
1286
- authentication: authentication
1287
- };
1288
- return portal.protectItem(protectOptions);
1289
- })
1290
- .then(function () {
1291
- // TODO: Attach the whole solution model so we can
1292
- // have stuff like `{{solution.item.title}}
1293
- templateDictionary.solutionItemId = deployedSolutionId;
1294
- solutionTemplateBase.id = deployedSolutionId;
1295
- solutionTemplateBase.tryitUrl = _checkedReplaceAll(solutionTemplateBase.tryitUrl, templateSolutionId, deployedSolutionId);
1296
- solutionTemplateBase.url = _checkedReplaceAll(solutionTemplateBase.url, templateSolutionId, deployedSolutionId);
1297
- // Handle the contained item templates
1298
- return deploySolutionItems(storageAuthentication.portal, templateSolutionId, solutionTemplateData.templates, storageAuthentication, templateDictionary, deployedSolutionId, authentication, options);
1299
- })
1300
- .then(function (clonedSolutionsResponse) {
1301
- solutionTemplateData.templates = solutionTemplateData.templates.map(function (itemTemplate) {
1302
- // Update ids present in template dictionary
1303
- itemTemplate.itemId = common.getProp(templateDictionary, itemTemplate.itemId + ".itemId");
1304
- // Update the dependencies hash to point to the new item ids
1305
- itemTemplate.dependencies = itemTemplate.dependencies.map(function (id) {
1306
- return hubCommon.getWithDefault(templateDictionary, id + ".itemId", id);
1307
- });
1308
- return itemTemplate;
1309
- });
1310
- // Sort the templates into build order, which is provided by clonedSolutionsResponse
1311
- sortTemplates(solutionTemplateData.templates, clonedSolutionsResponse.map(function (response) { return response.id; }));
1312
- // Wrap up with post-processing, in which we deal with groups and cycle remnants
1313
- return postProcess(deployedSolutionId, solutionTemplateData.templates, clonedSolutionsResponse, authentication, templateDictionary);
1314
- })
1315
- .then(function () {
1316
- // Update solution item using internal representation & and the updated data JSON
1317
- solutionTemplateBase.typeKeywords = [].concat(solutionTemplateBase.typeKeywords, ["Deployed"]);
1318
- var iTemplateKeyword = solutionTemplateBase.typeKeywords.indexOf("Template");
1319
- /* istanbul ignore else */
1320
- if (iTemplateKeyword >= 0) {
1321
- solutionTemplateBase.typeKeywords.splice(iTemplateKeyword, 1);
1322
- }
1323
- solutionTemplateData.templates = solutionTemplateData.templates.map(function (itemTemplate) {
1324
- return _purgeTemplateProperties(itemTemplate);
1325
- });
1326
- solutionTemplateData.templates = _updateGroupReferences(solutionTemplateData.templates, templateDictionary);
1327
- // Update solution items data using template dictionary, and then update the
1328
- // itemId & dependencies in each item template
1329
- solutionTemplateBase.data = common.replaceInTemplate(solutionTemplateData, templateDictionary);
1330
- // Write any user defined params to the solution
1331
- /* istanbul ignore else */
1332
- if (templateDictionary.params) {
1333
- solutionTemplateBase.data.params = templateDictionary.params;
1334
- }
1335
- return common.updateItem(solutionTemplateBase, authentication, deployedFolderId);
1336
- })
1337
- .then(function () { return resolve(solutionTemplateBase.id); }, reject);
1338
- });
1339
- }
1340
- /**
1341
- * Update the deployOptions with the group properties
1342
- *
1343
- * @param deployOptions
1344
- * @param sourceInfo
1345
- * @param authentication
1346
- * @param isGroup Boolean to indicate if the files are associated with a group or item
1347
- * @internal
1348
- */
1349
- function _applySourceToDeployOptions(deployOptions, solutionTemplateBase, templateDictionary, authentication) {
1350
- // Deploy a solution from the template's contents,
1351
- // using the template's information as defaults for the deployed solution item
1352
- ["title", "snippet", "description", "tags"].forEach(function (prop) {
1353
- var _a;
1354
- deployOptions[prop] = (_a = deployOptions[prop]) !== null && _a !== void 0 ? _a : solutionTemplateBase[prop];
1355
- if (deployOptions[prop]) {
1356
- solutionTemplateBase[prop] = deployOptions[prop];
1357
- // carry these options forward on the templateDict
1358
- templateDictionary[prop] = deployOptions[prop];
1359
- }
1360
- });
1361
- if (!deployOptions.thumbnailurl && solutionTemplateBase.thumbnail) {
1362
- // Get the full path to the thumbnail
1363
- deployOptions.thumbnailurl = common.generateSourceThumbnailUrl(authentication.portal, solutionTemplateBase.id, solutionTemplateBase.thumbnail);
1364
- delete solutionTemplateBase.thumbnail;
1365
- }
1366
- return deployOptions;
1367
- }
1368
- function _replaceParamVariables(solutionTemplateData, templateDictionary) {
1369
- // a custom params object can be passed in with the options to deploy a solution
1370
- // in most cases we can defer to the item type handlers to use these values
1371
- // for variable replacement
1372
- // for spatial reference specifically we need to replace up front so the default extent
1373
- // logic can execute as expected
1374
- solutionTemplateData.templates = solutionTemplateData.templates.map(function (template) {
1375
- // can't do this as it causes other values that don't exist in the dict yet to revert to defaults they may have defined
1376
- // return common.replaceInTemplate(template, templateDictionary);
1377
- /* istanbul ignore else */
1378
- if (template.type === "Feature Service") {
1379
- var paramsLookup = "params.";
1380
- var wkidItemPath = "item.spatialReference.wkid";
1381
- template = _updateProp(template, wkidItemPath, paramsLookup, templateDictionary);
1382
- var wkidServicePath = "properties.service.spatialReference.wkid";
1383
- template = _updateProp(template, wkidServicePath, paramsLookup, templateDictionary);
1384
- }
1385
- return template;
1386
- });
1387
- }
1388
- function _updateProp(template, path, lookup, templateDictionary) {
1389
- var wkid = common.getProp(template, path);
1390
- /* istanbul ignore else */
1391
- if (wkid && typeof wkid === "string" && wkid.indexOf(lookup) > -1) {
1392
- common.setProp(template, path, common.replaceInTemplate(wkid, templateDictionary));
1393
- }
1394
- return template;
1395
- }
1396
- function _checkedReplaceAll(template, oldValue, newValue) {
1397
- var newTemplate;
1398
- if (template && template.indexOf(oldValue) > -1) {
1399
- var re = new RegExp(oldValue, "g");
1400
- newTemplate = template.replace(re, newValue);
1401
- }
1402
- else {
1403
- newTemplate = template;
1404
- }
1405
- return newTemplate;
1406
- }
1407
- function _getPortalBaseUrl(portalResponse, authentication) {
1408
- // As of Spring 2020, only HTTPS (see
1409
- // https://www.esri.com/arcgis-blog/products/product/administration/2019-arcgis-transport-security-improvements/)
1410
- var scheme = "https"; // portalResponse.allSSL ? "https" : "http";
1411
- var urlKey = common.getProp(portalResponse, "urlKey");
1412
- var customBaseUrl = common.getProp(portalResponse, "customBaseUrl");
1413
- var enterpriseBaseUrl = common.getProp(portalResponse, "portalHostname");
1414
- return urlKey && customBaseUrl
1415
- ? scheme + "://" + urlKey + "." + customBaseUrl
1416
- : enterpriseBaseUrl
1417
- ? scheme + "://" + enterpriseBaseUrl
1418
- : authentication.portal.replace("/sharing/rest", "");
1419
- }
1420
- function _updateGroupReferences(itemTemplates, templateDictionary) {
1421
- var groupIds = itemTemplates.reduce(function (result, t) {
1422
- if (t.type === "Group") {
1423
- result.push(t.itemId);
1424
- }
1425
- return result;
1426
- }, []);
1427
- Object.keys(templateDictionary).forEach(function (k) {
1428
- var newId = templateDictionary[k].itemId;
1429
- if (groupIds.indexOf(newId) > -1) {
1430
- itemTemplates.forEach(function (t) {
1431
- t.groups = t.groups.map(function (id) { return (id === k ? newId : id); });
1432
- });
1433
- }
1434
- });
1435
- return itemTemplates;
1436
- }
1437
- function _purgeTemplateProperties(itemTemplate) {
1438
- var retainProps = ["itemId", "type", "dependencies", "groups"];
1439
- var deleteProps = Object.keys(itemTemplate).filter(function (k) { return retainProps.indexOf(k) < 0; });
1440
- common.deleteProps(itemTemplate, deleteProps);
1441
- return itemTemplate;
1442
- }
1418
+ /** @license
1419
+ * Copyright 2018 Esri
1420
+ *
1421
+ * Licensed under the Apache License, Version 2.0 (the "License");
1422
+ * you may not use this file except in compliance with the License.
1423
+ * You may obtain a copy of the License at
1424
+ *
1425
+ * http://www.apache.org/licenses/LICENSE-2.0
1426
+ *
1427
+ * Unless required by applicable law or agreed to in writing, software
1428
+ * distributed under the License is distributed on an "AS IS" BASIS,
1429
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1430
+ * See the License for the specific language governing permissions and
1431
+ * limitations under the License.
1432
+ */
1433
+ /**
1434
+ * Given an itemId or an object, either fetch the item or
1435
+ * resolve using the object, if it is structured as expected
1436
+ *
1437
+ * @param idOrObject string || object like `{item:{...}, data: {...}}`
1438
+ * @param authentication UserSession
1439
+ */
1440
+ function getSolutionTemplateItem(idOrObject, authentication) {
1441
+ if (typeof idOrObject === "string") {
1442
+ // get the item + data
1443
+ return Promise.all([
1444
+ common.getItemBase(idOrObject, authentication),
1445
+ common.getItemDataAsJson(idOrObject, authentication)
1446
+ ]).then(([item, data]) => {
1447
+ // format into a model and migrate the schema
1448
+ return common.migrateSchema({
1449
+ item,
1450
+ data
1451
+ });
1452
+ });
1453
+ }
1454
+ else {
1455
+ // check if it is a "Model"
1456
+ if (_isModel(idOrObject)) {
1457
+ // run migrations
1458
+ return common.migrateSchema(idOrObject);
1459
+ }
1460
+ else {
1461
+ return Promise.reject(common.fail(`getSolutionTemplateItem must be passed an item id or a model object`));
1462
+ }
1463
+ }
1464
+ }
1465
+ /**
1466
+ * Update the Deploy Options with information from the
1467
+ * Solution Template item
1468
+ *
1469
+ * @param deployOptions
1470
+ * @param item
1471
+ * @param authentication
1472
+ */
1473
+ function updateDeployOptions(deployOptions, item, authentication) {
1474
+ deployOptions.jobId = deployOptions.jobId ?? item.id;
1475
+ deployOptions.title = deployOptions.title ?? item.title;
1476
+ deployOptions.snippet = deployOptions.snippet ?? item.snippet;
1477
+ deployOptions.description = deployOptions.description ?? item.description;
1478
+ deployOptions.tags = deployOptions.tags ?? item.tags;
1479
+ // add the thumbnail url
1480
+ deployOptions.thumbnailurl = item.thumbnail
1481
+ ? common.getItemThumbnailUrl(item.id, item.thumbnail, false, authentication)
1482
+ : null;
1483
+ return deployOptions;
1484
+ }
1485
+ /**
1486
+ * Check if an object is an Model
1487
+ *
1488
+ * @param obj any object
1489
+ */
1490
+ function _isModel(obj) {
1491
+ let result = false;
1492
+ // TODO Hoist into common?
1493
+ const isNotStringOrArray = (v) => v != null &&
1494
+ typeof v !== "string" &&
1495
+ !Array.isArray(v) &&
1496
+ typeof v === "object";
1497
+ if (isNotStringOrArray(obj)) {
1498
+ result = ["item", "data"].reduce((acc, prop) => {
1499
+ if (acc) {
1500
+ acc = isNotStringOrArray(obj[prop]);
1501
+ }
1502
+ return acc;
1503
+ }, true);
1504
+ }
1505
+ return result;
1506
+ }
1507
+ /**
1508
+ * Does the item have the correct type and keywords
1509
+ * to be a Solution Template item?
1510
+ *
1511
+ * @param item IItem
1512
+ */
1513
+ function isSolutionTemplateItem(item) {
1514
+ const kwds = item.typeKeywords;
1515
+ // Solution items
1516
+ let result = false;
1517
+ if (item.type === "Solution") {
1518
+ if (kwds.indexOf("Solution") > -1 &&
1519
+ (kwds.indexOf("Template") > -1 || kwds.indexOf("solutionTemplate") > -1)) {
1520
+ result = true;
1521
+ }
1522
+ }
1523
+ // Older Hub Solutions used Web Mapping Application items
1524
+ if (item.type === "Web Mapping Application") {
1525
+ if (kwds.indexOf("hubSolutionTemplate") > -1) {
1526
+ result = true;
1527
+ }
1528
+ }
1529
+ return result;
1530
+ }
1443
1531
 
1444
- /** @license
1445
- * Copyright 2018 Esri
1446
- *
1447
- * Licensed under the Apache License, Version 2.0 (the "License");
1448
- * you may not use this file except in compliance with the License.
1449
- * You may obtain a copy of the License at
1450
- *
1451
- * http://www.apache.org/licenses/LICENSE-2.0
1452
- *
1453
- * Unless required by applicable law or agreed to in writing, software
1454
- * distributed under the License is distributed on an "AS IS" BASIS,
1455
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1456
- * See the License for the specific language governing permissions and
1457
- * limitations under the License.
1458
- */
1459
- /**
1460
- * Given an itemId or an object, either fetch the item or
1461
- * resolve using the object, if it is structured as expected
1462
- *
1463
- * @param idOrObject string || object like `{item:{...}, data: {...}}`
1464
- * @param authentication UserSession
1465
- */
1466
- function getSolutionTemplateItem(idOrObject, authentication) {
1467
- if (typeof idOrObject === "string") {
1468
- // get the item + data
1469
- return Promise.all([
1470
- common.getItemBase(idOrObject, authentication),
1471
- common.getItemDataAsJson(idOrObject, authentication)
1472
- ]).then(function (_a) {
1473
- var _b = __read(_a, 2), item = _b[0], data = _b[1];
1474
- // format into a model and migrate the schema
1475
- return common.migrateSchema({
1476
- item: item,
1477
- data: data
1478
- });
1479
- });
1480
- }
1481
- else {
1482
- // check if it is a "Model"
1483
- if (_isModel(idOrObject)) {
1484
- // run migrations
1485
- return common.migrateSchema(idOrObject);
1486
- }
1487
- else {
1488
- return Promise.reject(common.fail("getSolutionTemplateItem must be passed an item id or a model object"));
1489
- }
1490
- }
1491
- }
1492
- /**
1493
- * Update the Deploy Options with information from the
1494
- * Solution Template item
1495
- *
1496
- * @param deployOptions
1497
- * @param item
1498
- * @param authentication
1499
- */
1500
- function updateDeployOptions(deployOptions, item, authentication) {
1501
- var _a, _b, _c, _d, _e;
1502
- deployOptions.jobId = (_a = deployOptions.jobId) !== null && _a !== void 0 ? _a : item.id;
1503
- deployOptions.title = (_b = deployOptions.title) !== null && _b !== void 0 ? _b : item.title;
1504
- deployOptions.snippet = (_c = deployOptions.snippet) !== null && _c !== void 0 ? _c : item.snippet;
1505
- deployOptions.description = (_d = deployOptions.description) !== null && _d !== void 0 ? _d : item.description;
1506
- deployOptions.tags = (_e = deployOptions.tags) !== null && _e !== void 0 ? _e : item.tags;
1507
- // add the thumbnail url
1508
- deployOptions.thumbnailurl = item.thumbnail
1509
- ? common.getItemThumbnailUrl(item.id, item.thumbnail, false, authentication)
1510
- : null;
1511
- return deployOptions;
1512
- }
1513
- /**
1514
- * Check if an object is an Model
1515
- *
1516
- * @param obj any object
1517
- */
1518
- function _isModel(obj) {
1519
- var result = false;
1520
- // TODO Hoist into common?
1521
- var isNotStringOrArray = function (v) {
1522
- return v != null &&
1523
- typeof v !== "string" &&
1524
- !Array.isArray(v) &&
1525
- typeof v === "object";
1526
- };
1527
- if (isNotStringOrArray(obj)) {
1528
- result = ["item", "data"].reduce(function (acc, prop) {
1529
- if (acc) {
1530
- acc = isNotStringOrArray(obj[prop]);
1531
- }
1532
- return acc;
1533
- }, true);
1534
- }
1535
- return result;
1536
- }
1537
- /**
1538
- * Does the item have the correct type and keywords
1539
- * to be a Solution Template item?
1540
- *
1541
- * @param item IItem
1542
- */
1543
- function isSolutionTemplateItem(item) {
1544
- var kwds = item.typeKeywords;
1545
- // Solution items
1546
- var result = false;
1547
- if (item.type === "Solution") {
1548
- if (kwds.indexOf("Solution") > -1 &&
1549
- (kwds.indexOf("Template") > -1 || kwds.indexOf("solutionTemplate") > -1)) {
1550
- result = true;
1551
- }
1552
- }
1553
- // Older Hub Solutions used Web Mapping Application items
1554
- if (item.type === "Web Mapping Application") {
1555
- if (kwds.indexOf("hubSolutionTemplate") > -1) {
1556
- result = true;
1557
- }
1558
- }
1559
- return result;
1560
- }
1532
+ /** @license
1533
+ * Copyright 2018 Esri
1534
+ *
1535
+ * Licensed under the Apache License, Version 2.0 (the "License");
1536
+ * you may not use this file except in compliance with the License.
1537
+ * You may obtain a copy of the License at
1538
+ *
1539
+ * http://www.apache.org/licenses/LICENSE-2.0
1540
+ *
1541
+ * Unless required by applicable law or agreed to in writing, software
1542
+ * distributed under the License is distributed on an "AS IS" BASIS,
1543
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1544
+ * See the License for the specific language governing permissions and
1545
+ * limitations under the License.
1546
+ */
1547
+ /**
1548
+ * Deploy a Solution
1549
+ *
1550
+ * Pass in either the item id or an IModel (`{item:{}, model:{}}`)
1551
+ * of a Solution Template, and this will generate the Solution
1552
+ *
1553
+ * @param maybeModel Item Id or IModel
1554
+ * @param authentication Credentials for the destination organization
1555
+ * @param options Options to override deployed information and to provide additional credentials
1556
+ * @return The id of the created deployed solution item
1557
+ */
1558
+ function deploySolution(maybeModel, authentication, options) {
1559
+ // if we are not passed the maybeModel, reject
1560
+ if (!maybeModel) {
1561
+ return Promise.reject(common.fail("The Solution Template id is missing"));
1562
+ }
1563
+ let deployOptions = options || {};
1564
+ /* istanbul ignore else */
1565
+ if (deployOptions.progressCallback) {
1566
+ deployOptions.progressCallback(1, deployOptions.jobId); // let the caller know that we've started
1567
+ }
1568
+ // It is possible to provide a separate authentication for the source
1569
+ const storageAuthentication = deployOptions.storageAuthentication
1570
+ ? deployOptions.storageAuthentication
1571
+ : authentication;
1572
+ // deal with maybe getting an item or an id
1573
+ return getSolutionTemplateItem(maybeModel, storageAuthentication)
1574
+ .then(model => {
1575
+ if (!isSolutionTemplateItem(model.item)) {
1576
+ return Promise.reject(common.fail(`${model.item.id} is not a Solution Template`));
1577
+ }
1578
+ else {
1579
+ // fetch the metadata if the model's id is a GUID and pass the item & data forward
1580
+ return Promise.all([
1581
+ Promise.resolve(model.item),
1582
+ Promise.resolve(model.data)
1583
+ ]);
1584
+ }
1585
+ })
1586
+ .then(responses => {
1587
+ // extract responses
1588
+ const [itemBase, itemData] = responses;
1589
+ // sanitize all the things
1590
+ const sanitizer = new common.Sanitizer();
1591
+ const item = common.sanitizeJSONAndReportChanges(itemBase, sanitizer);
1592
+ // TODO: we should delegate data sanization to the type-specific modules
1593
+ const data = itemData;
1594
+ // get the item id before it is deleted
1595
+ const itemId = item.id;
1596
+ // apply item props to deployOptions
1597
+ deployOptions = updateDeployOptions(deployOptions, item, storageAuthentication);
1598
+ // Clone before mutating? This was messing me up in some testing...
1599
+ common.deleteItemProps(item);
1600
+ return deploySolutionFromTemplate(itemId, item, data, authentication, deployOptions);
1601
+ })
1602
+ .then(createdSolutionId => {
1603
+ /* istanbul ignore else */
1604
+ if (deployOptions.progressCallback) {
1605
+ deployOptions.progressCallback(100, deployOptions.jobId); // we're done
1606
+ }
1607
+ return createdSolutionId;
1608
+ }, error => {
1609
+ // Error deploying solution
1610
+ /* istanbul ignore else */
1611
+ if (deployOptions.progressCallback) {
1612
+ deployOptions.progressCallback(1, deployOptions.jobId);
1613
+ }
1614
+ return Promise.reject(error);
1615
+ })
1616
+ .catch(ex => {
1617
+ throw ex;
1618
+ });
1619
+ }
1561
1620
 
1562
- /** @license
1563
- * Copyright 2018 Esri
1564
- *
1565
- * Licensed under the Apache License, Version 2.0 (the "License");
1566
- * you may not use this file except in compliance with the License.
1567
- * You may obtain a copy of the License at
1568
- *
1569
- * http://www.apache.org/licenses/LICENSE-2.0
1570
- *
1571
- * Unless required by applicable law or agreed to in writing, software
1572
- * distributed under the License is distributed on an "AS IS" BASIS,
1573
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1574
- * See the License for the specific language governing permissions and
1575
- * limitations under the License.
1576
- */
1577
- /**
1578
- * Deploy a Solution
1579
- *
1580
- * Pass in either the item id or an IModel (`{item:{}, model:{}}`)
1581
- * of a Solution Template, and this will generate the Solution
1582
- *
1583
- * @param maybeModel Item Id or IModel
1584
- * @param authentication Credentials for the destination organization
1585
- * @param options Options to override deployed information and to provide additional credentials
1586
- * @return The id of the created deployed solution item
1587
- */
1588
- function deploySolution(maybeModel, authentication, options) {
1589
- // if we are not passed the maybeModel, reject
1590
- if (!maybeModel) {
1591
- return Promise.reject(common.fail("The Solution Template id is missing"));
1592
- }
1593
- var deployOptions = options || {};
1594
- /* istanbul ignore else */
1595
- if (deployOptions.progressCallback) {
1596
- deployOptions.progressCallback(1, deployOptions.jobId); // let the caller know that we've started
1597
- }
1598
- // It is possible to provide a separate authentication for the source
1599
- var storageAuthentication = deployOptions.storageAuthentication
1600
- ? deployOptions.storageAuthentication
1601
- : authentication;
1602
- // deal with maybe getting an item or an id
1603
- return getSolutionTemplateItem(maybeModel, storageAuthentication)
1604
- .then(function (model) {
1605
- if (!isSolutionTemplateItem(model.item)) {
1606
- return Promise.reject(common.fail(model.item.id + " is not a Solution Template"));
1607
- }
1608
- else {
1609
- // fetch the metadata if the model's id is a GUID and pass the item & data forward
1610
- return Promise.all([
1611
- Promise.resolve(model.item),
1612
- Promise.resolve(model.data)
1613
- ]);
1614
- }
1615
- })
1616
- .then(function (responses) {
1617
- // extract responses
1618
- var _a = __read(responses, 2), itemBase = _a[0], itemData = _a[1];
1619
- // sanitize all the things
1620
- var sanitizer = new common.Sanitizer();
1621
- var item = common.sanitizeJSONAndReportChanges(itemBase, sanitizer);
1622
- // TODO: we should delegate data sanization to the type-specific modules
1623
- var data = itemData;
1624
- // get the item id before it is deleted
1625
- var itemId = item.id;
1626
- // apply item props to deployOptions
1627
- deployOptions = updateDeployOptions(deployOptions, item, storageAuthentication);
1628
- // Clone before mutating? This was messing me up in some testing...
1629
- common.deleteItemProps(item);
1630
- return deploySolutionFromTemplate(itemId, item, data, authentication, deployOptions);
1631
- })
1632
- .then(function (createdSolutionId) {
1633
- /* istanbul ignore else */
1634
- if (deployOptions.progressCallback) {
1635
- deployOptions.progressCallback(100, deployOptions.jobId); // we're done
1636
- }
1637
- return createdSolutionId;
1638
- }, function (error) {
1639
- // Error deploying solution
1640
- /* istanbul ignore else */
1641
- if (deployOptions.progressCallback) {
1642
- deployOptions.progressCallback(1, deployOptions.jobId);
1643
- }
1644
- return Promise.reject(error);
1645
- })
1646
- .catch(function (ex) {
1647
- throw ex;
1648
- });
1649
- }
1621
+ exports.UNSUPPORTED = UNSUPPORTED;
1622
+ exports._createItemFromTemplateWhenReady = _createItemFromTemplateWhenReady;
1623
+ exports._estimateDeploymentCost = _estimateDeploymentCost;
1624
+ exports._evaluateSharedViewSources = _evaluateSharedViewSources;
1625
+ exports._findExistingItem = _findExistingItem;
1626
+ exports._findExistingItemByKeyword = _findExistingItemByKeyword;
1627
+ exports._flagPatchItemsForPostProcessing = _flagPatchItemsForPostProcessing;
1628
+ exports._getGroupUpdates = _getGroupUpdates;
1629
+ exports._getViewHash = _getViewHash;
1630
+ exports._getViews = _getViews;
1631
+ exports._handleExistingItems = _handleExistingItems;
1632
+ exports._isModel = _isModel;
1633
+ exports._reuseDeployedItems = _reuseDeployedItems;
1634
+ exports._setFields = _setFields;
1635
+ exports._setTypekeywordForExisting = _setTypekeywordForExisting;
1636
+ exports._updateTemplateDictionary = _updateTemplateDictionary;
1637
+ exports._updateTemplateDictionaryById = _updateTemplateDictionaryById;
1638
+ exports._updateTemplateDictionaryForError = _updateTemplateDictionaryForError;
1639
+ exports._updateViewTemplates = _updateViewTemplates;
1640
+ exports._useExistingItems = _useExistingItems;
1641
+ exports.deploySolution = deploySolution;
1642
+ exports.deploySolutionItems = deploySolutionItems;
1643
+ exports.getSolutionTemplateItem = getSolutionTemplateItem;
1644
+ exports.isSolutionTemplateItem = isSolutionTemplateItem;
1645
+ exports.moduleMap = moduleMap;
1646
+ exports.updateDeployOptions = updateDeployOptions;
1650
1647
 
1651
- exports.UNSUPPORTED = UNSUPPORTED;
1652
- exports._createItemFromTemplateWhenReady = _createItemFromTemplateWhenReady;
1653
- exports._estimateDeploymentCost = _estimateDeploymentCost;
1654
- exports._evaluateSharedViewSources = _evaluateSharedViewSources;
1655
- exports._findExistingItem = _findExistingItem;
1656
- exports._findExistingItemByKeyword = _findExistingItemByKeyword;
1657
- exports._flagPatchItemsForPostProcessing = _flagPatchItemsForPostProcessing;
1658
- exports._getGroupUpdates = _getGroupUpdates;
1659
- exports._getViewHash = _getViewHash;
1660
- exports._getViews = _getViews;
1661
- exports._handleExistingItems = _handleExistingItems;
1662
- exports._isModel = _isModel;
1663
- exports._reuseDeployedItems = _reuseDeployedItems;
1664
- exports._setFields = _setFields;
1665
- exports._setTypekeywordForExisting = _setTypekeywordForExisting;
1666
- exports._updateTemplateDictionary = _updateTemplateDictionary;
1667
- exports._updateTemplateDictionaryById = _updateTemplateDictionaryById;
1668
- exports._updateTemplateDictionaryForError = _updateTemplateDictionaryForError;
1669
- exports._updateViewTemplates = _updateViewTemplates;
1670
- exports._useExistingItems = _useExistingItems;
1671
- exports.deploySolution = deploySolution;
1672
- exports.deploySolutionItems = deploySolutionItems;
1673
- exports.getSolutionTemplateItem = getSolutionTemplateItem;
1674
- exports.isSolutionTemplateItem = isSolutionTemplateItem;
1675
- exports.moduleMap = moduleMap;
1676
- exports.updateDeployOptions = updateDeployOptions;
1677
-
1678
- Object.defineProperty(exports, '__esModule', { value: true });
1648
+ Object.defineProperty(exports, '__esModule', { value: true });
1679
1649
 
1680
1650
  })));
1681
1651
  //# sourceMappingURL=deployer.umd.js.map