@esri/solution-creator 1.1.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  /* @preserve
2
- * @esri/solution-creator - v1.1.2 - Apache-2.0
2
+ * @esri/solution-creator - v1.2.0 - Apache-2.0
3
3
  * Copyright (c) 2018-2021 Esri, Inc.
4
- * Tue Aug 31 2021 00:03:15 GMT-0700 (Pacific Daylight Time)
4
+ * Thu Dec 09 2021 16:05:40 GMT-0800 (Pacific Standard 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,1281 +16,1273 @@
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/hub-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')) :
20
- typeof define === 'function' && define.amd ? define(['exports', '@esri/solution-common', '@esri/hub-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'], factory) :
21
- (global = global || self, factory(global.arcgisSolution = global.arcgisSolution || {}, global.arcgisSolution, global.arcgisHub, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution));
22
- }(this, (function (exports, solutionCommon, hubCommon, featureLayer, fileProcessor, formProcessor, group, solutionSimpleTypes, solutionStorymap, solutionVelocity, solutionWebExperience, solutionHubTypes) { 'use strict';
19
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@esri/solution-common'), require('@esri/hub-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')) :
20
+ typeof define === 'function' && define.amd ? define(['exports', '@esri/solution-common', '@esri/hub-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'], factory) :
21
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.arcgisSolution = global.arcgisSolution || {}, global.arcgisSolution, global.arcgisHub, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution, global.arcgisSolution));
22
+ })(this, (function (exports, solutionCommon, hubCommon, featureLayer, fileProcessor, formProcessor, group, solutionSimpleTypes, solutionStorymap, solutionVelocity, solutionWebExperience, solutionHubTypes) { '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
- };
24
+ function _interopNamespace(e) {
25
+ if (e && e.__esModule) return e;
26
+ var n = Object.create(null);
27
+ if (e) {
28
+ Object.keys(e).forEach(function (k) {
29
+ if (k !== 'default') {
30
+ var d = Object.getOwnPropertyDescriptor(e, k);
31
+ Object.defineProperty(n, k, d.get ? d : {
32
+ enumerable: true,
33
+ get: function () { return e[k]; }
34
+ });
35
+ }
36
+ });
37
+ }
38
+ n["default"] = e;
39
+ return Object.freeze(n);
40
+ }
49
41
 
50
- /** @license
51
- * Copyright 2020 Esri
52
- *
53
- * Licensed under the Apache License, Version 2.0 (the "License");
54
- * you may not use this file except in compliance with the License.
55
- * You may obtain a copy of the License at
56
- *
57
- * http://www.apache.org/licenses/LICENSE-2.0
58
- *
59
- * Unless required by applicable law or agreed to in writing, software
60
- * distributed under the License is distributed on an "AS IS" BASIS,
61
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
62
- * See the License for the specific language governing permissions and
63
- * limitations under the License.
64
- */
65
- var UNSUPPORTED = null;
66
- /**
67
- * Mapping from item type to module with type-specific template-handling code.
68
- * AGO types come from a blend of arcgis-portal-app\src\js\arcgisonline\pages\item\_Info.js and
69
- * arcgis-portal-app\src\js\arcgis-components\src\_utils\metadata\item\displayName.ts
70
- */
71
- var moduleMap = {
72
- ////////////////////////////////////////////////////////
73
- // Group type
74
- Group: group,
75
- ////////////////////////////////////////////////////////
76
- // Layer types
77
- "Big Data Analytic": solutionVelocity.VelocityProcessor,
78
- "Feature Collection": solutionSimpleTypes.simpleTypes,
79
- "Feature Service": featureLayer,
80
- Feed: solutionVelocity.VelocityProcessor,
81
- "Geocoding Service": undefined,
82
- "Geodata Service": undefined,
83
- "Geometry Service": undefined,
84
- "Geoprocessing Service": undefined,
85
- "Globe Service": undefined,
86
- "Image Service": undefined,
87
- KML: undefined,
88
- "Map Service": featureLayer,
89
- "Network Analysis Service": undefined,
90
- "Real Time Analytic": solutionVelocity.VelocityProcessor,
91
- "Relational Database Connection": undefined,
92
- "Scene Service": undefined,
93
- "Stream Service": undefined,
94
- Tool: undefined,
95
- "Vector Tile Service": undefined,
96
- WFS: undefined,
97
- WMS: undefined,
98
- WMTS: undefined,
99
- "Workflow Manager Service": undefined,
100
- ////////////////////////////////////////////////////////
101
- // Map types
102
- "3D Web Scene": undefined,
103
- "Web Map": solutionSimpleTypes.simpleTypes,
104
- "Web Scene": solutionSimpleTypes.simpleTypes,
105
- ////////////////////////////////////////////////////////
106
- // App types
107
- Application: undefined,
108
- Dashboard: solutionSimpleTypes.simpleTypes,
109
- "Data Store": undefined,
110
- "Desktop Application": undefined,
111
- "Excalibur Imagery Project": undefined,
112
- Form: formProcessor,
113
- "Hub Initiative": UNSUPPORTED,
114
- "Hub Page": solutionHubTypes.HubPageProcessor,
115
- "Hub Site Application": solutionHubTypes.HubSiteProcessor,
116
- "Insights Model": solutionSimpleTypes.simpleTypes,
117
- "Insights Page": undefined,
118
- "Insights Theme": undefined,
119
- "Insights Workbook": undefined,
120
- Mission: undefined,
121
- "Mobile Application": undefined,
122
- Notebook: solutionSimpleTypes.notebookProcessor,
123
- "Oriented Imagery Catalog": solutionSimpleTypes.simpleTypes,
124
- "Ortho Mapping Project": undefined,
125
- "QuickCapture Project": solutionSimpleTypes.quickcaptureProcessor,
126
- "Site Application": solutionHubTypes.HubSiteProcessor,
127
- "Site Page": solutionHubTypes.HubPageProcessor,
128
- Solution: UNSUPPORTED,
129
- StoryMap: solutionStorymap.StoryMapProcessor,
130
- "Urban Model": undefined,
131
- "Web Experience Template": undefined,
132
- "Web Experience": solutionWebExperience.WebExperienceProcessor,
133
- "Web Mapping Application": solutionSimpleTypes.simpleTypes,
134
- "Workforce Project": solutionSimpleTypes.simpleTypes,
135
- ////////////////////////////////////////////////////////
136
- // File types
137
- "360 VR Experience": fileProcessor,
138
- "AppBuilder Extension": fileProcessor,
139
- "AppBuilder Widget Package": fileProcessor,
140
- "Application Configuration": fileProcessor,
141
- "ArcGIS Pro Add In": fileProcessor,
142
- "ArcGIS Pro Configuration": fileProcessor,
143
- "ArcPad Package": fileProcessor,
144
- "Basemap Package": fileProcessor,
145
- "CAD Drawing": fileProcessor,
146
- "CityEngine Web Scene": fileProcessor,
147
- "Code Attachment": UNSUPPORTED,
148
- "Code Sample": fileProcessor,
149
- "Color Set": fileProcessor,
150
- "Compact Tile Package": fileProcessor,
151
- "CSV Collection": fileProcessor,
152
- CSV: fileProcessor,
153
- "Deep Learning Package": fileProcessor,
154
- "Desktop Add In": fileProcessor,
155
- "Desktop Application Template": fileProcessor,
156
- "Desktop Style": fileProcessor,
157
- "Document Link": fileProcessor,
158
- "Explorer Add In": fileProcessor,
159
- "Explorer Layer": fileProcessor,
160
- "Explorer Map": fileProcessor,
161
- "Feature Collection Template": fileProcessor,
162
- "File Geodatabase": fileProcessor,
163
- GeoJson: fileProcessor,
164
- GeoPackage: fileProcessor,
165
- "Geoprocessing Package": fileProcessor,
166
- "Geoprocessing Sample": fileProcessor,
167
- "Globe Document": fileProcessor,
168
- "Image Collection": fileProcessor,
169
- Image: fileProcessor,
170
- "iWork Keynote": fileProcessor,
171
- "iWork Numbers": fileProcessor,
172
- "iWork Pages": fileProcessor,
173
- "KML Collection": fileProcessor,
174
- "Layer Package": fileProcessor,
175
- "Layer Template": fileProcessor,
176
- Layer: fileProcessor,
177
- Layout: fileProcessor,
178
- "Locator Package": fileProcessor,
179
- "Map Document": fileProcessor,
180
- "Map Package": fileProcessor,
181
- "Map Template": fileProcessor,
182
- "Microsoft Excel": fileProcessor,
183
- "Microsoft Powerpoint": fileProcessor,
184
- "Microsoft Word": fileProcessor,
185
- "Mobile Basemap Package": fileProcessor,
186
- "Mobile Map Package": fileProcessor,
187
- "Mobile Scene Package": fileProcessor,
188
- "Native Application": fileProcessor,
189
- "Native Application Installer": fileProcessor,
190
- "Native Application Template": fileProcessor,
191
- netCDF: fileProcessor,
192
- "Operation View": fileProcessor,
193
- "Operations Dashboard Add In": fileProcessor,
194
- "Operations Dashboard Extension": fileProcessor,
195
- PDF: fileProcessor,
196
- "Pro Layer Package": fileProcessor,
197
- "Pro Layer": fileProcessor,
198
- "Pro Map Package": fileProcessor,
199
- "Pro Map": fileProcessor,
200
- "Pro Report": fileProcessor,
201
- "Project Package": fileProcessor,
202
- "Project Template": fileProcessor,
203
- "Published Map": fileProcessor,
204
- "Raster function template": fileProcessor,
205
- "Report Template": fileProcessor,
206
- "Rule Package": fileProcessor,
207
- "Scene Document": fileProcessor,
208
- "Scene Package": fileProcessor,
209
- "Service Definition": fileProcessor,
210
- Shapefile: fileProcessor,
211
- "Statistical Data Collection": fileProcessor,
212
- Style: fileProcessor,
213
- "Survey123 Add In": fileProcessor,
214
- "Symbol Set": fileProcessor,
215
- "Task File": fileProcessor,
216
- "Tile Package": fileProcessor,
217
- "Toolbox Package": fileProcessor,
218
- "Vector Tile Package": fileProcessor,
219
- "Viewer Configuration": fileProcessor,
220
- "Visio Document": fileProcessor,
221
- "Window Mobile Package": fileProcessor,
222
- "Windows Mobile Package": fileProcessor,
223
- "Windows Viewer Add In": fileProcessor,
224
- "Windows Viewer Configuration": fileProcessor,
225
- "Workflow Manager Package": fileProcessor,
226
- ////////////////////////////////////////////////////////
227
- // Testing "types"
228
- Undefined: undefined,
229
- Unsupported: UNSUPPORTED
230
- };
42
+ var featureLayer__namespace = /*#__PURE__*/_interopNamespace(featureLayer);
43
+ var fileProcessor__namespace = /*#__PURE__*/_interopNamespace(fileProcessor);
44
+ var formProcessor__namespace = /*#__PURE__*/_interopNamespace(formProcessor);
45
+ var group__namespace = /*#__PURE__*/_interopNamespace(group);
231
46
 
232
- /** @license
233
- * Copyright 2018 Esri
234
- *
235
- * Licensed under the Apache License, Version 2.0 (the "License");
236
- * you may not use this file except in compliance with the License.
237
- * You may obtain a copy of the License at
238
- *
239
- * http://www.apache.org/licenses/LICENSE-2.0
240
- *
241
- * Unless required by applicable law or agreed to in writing, software
242
- * distributed under the License is distributed on an "AS IS" BASIS,
243
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
244
- * See the License for the specific language governing permissions and
245
- * limitations under the License.
246
- */
247
- // ------------------------------------------------------------------------------------------------------------------ //
248
- /**
249
- * Creates template for an AGO item and its dependencies
250
- *
251
- * @param solutionItemId The solution to contain the item
252
- * @param itemId AGO id string
253
- * @param templateDictionary Hash of facts
254
- * @param srcAuthentication Credentials for requests to source items
255
- * @param destAuthentication Authentication for requesting information from AGO about items to be included in solution item
256
- * @param existingTemplates A collection of AGO item templates that can be referenced by newly-created templates
257
- * @return A promise which resolves with an array of resources for the item and its dependencies
258
- * @protected
259
- */
260
- function createItemTemplate(solutionItemId, itemId, templateDictionary, srcAuthentication, destAuthentication, existingTemplates, itemProgressCallback) {
261
- return new Promise(function (resolve) {
262
- // Check if item and its dependents are already in list or are queued
263
- if (solutionCommon.findTemplateInList(existingTemplates, itemId)) {
264
- resolve([]);
265
- }
266
- else {
267
- // Add the id as a placeholder to show that it is being fetched
268
- existingTemplates.push(solutionCommon.createPlaceholderTemplate(itemId));
269
- itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Started, 0);
270
- // Fetch the item
271
- solutionCommon.getItemBase(itemId, srcAuthentication)
272
- .catch(function () {
273
- // If item query fails, try fetching item as a group
274
- // Change its placeholder from an empty type to the Group type so that we can later distinguish
275
- // between items and groups (the base info for a group doesn't include a type property)
276
- solutionCommon.replaceTemplate(existingTemplates, itemId, solutionCommon.createPlaceholderTemplate(itemId, "Group"));
277
- return solutionCommon.getGroupBase(itemId, srcAuthentication);
278
- })
279
- .then(function (itemInfo) {
280
- itemInfo = solutionCommon.sanitizeJSONAndReportChanges(itemInfo);
281
- // Save the URL as a symbol
282
- if (itemInfo.url) {
283
- templateDictionary[itemInfo.url] = "{{" + itemInfo.id + ".url}}";
284
- itemInfo.origUrl = itemInfo.url;
285
- }
286
- var idTest = /^source-[0-9A-F]{32}/i;
287
- // Remove any source-itemId type keywords
288
- if (Array.isArray(itemInfo.typeKeywords)) {
289
- itemInfo.typeKeywords = itemInfo.typeKeywords.filter(function (v) {
290
- return idTest.test(v) ? false : true;
291
- });
292
- }
293
- // Remove any source-itemId tags
294
- /* istanbul ignore else */
295
- if (Array.isArray(itemInfo.tags)) {
296
- itemInfo.tags = itemInfo.tags.filter(function (v) {
297
- return idTest.test(v) ? false : true;
298
- });
299
- }
300
- var placeholder = solutionCommon.findTemplateInList(existingTemplates, itemId);
301
- var itemType = placeholder.type;
302
- if (!itemType) {
303
- // Groups have this defined when their placeholder is created
304
- itemType = itemInfo.type;
305
- placeholder.type = itemType;
306
- }
307
- if (!itemInfo.type) {
308
- itemInfo.type = itemType; // Groups don't have this property, so we'll patch it in
309
- }
310
- placeholder.item = __assign({}, itemInfo);
311
- // Interrupt process if progress callback returns `false`
312
- if (!itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Created, 1)) {
313
- itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Cancelled, 1);
314
- resolve(solutionCommon.fail("Cancelled"));
315
- return;
316
- }
317
- var itemHandler = moduleMap[itemType];
318
- if (!itemHandler || itemHandler === UNSUPPORTED) {
319
- if (itemHandler === UNSUPPORTED) {
320
- itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Ignored, 1);
321
- resolve([]);
322
- }
323
- else {
324
- itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Failed, 1);
325
- placeholder.properties["failed"] = true;
326
- solutionCommon.replaceTemplate(existingTemplates, itemId, placeholder);
327
- resolve(solutionCommon.fail("The type of AGO item " +
328
- itemId +
329
- " ('" +
330
- itemType +
331
- "') is not supported at this time"));
332
- }
333
- }
334
- else {
335
- // Handle original Story Maps with next-gen Story Maps
336
- /* istanbul ignore else */
337
- /* Not yet supported
338
- if (storyMap.isAStoryMap(itemType, itemInfo.url)) {
339
- itemHandler = storyMap;
340
- } */
341
- // Delegate the creation of the item to the handler
342
- itemHandler
343
- .convertItemToTemplate(solutionItemId, itemInfo, destAuthentication, templateDictionary)
344
- .then(function (itemTemplate) {
345
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
346
- solutionCommon.getItemResourcesPaths(itemTemplate, solutionItemId, srcAuthentication, solutionCommon.SolutionTemplateFormatVersion).then(function (resourceItemFilePaths) {
347
- itemTemplate.item.thumbnail = null; // not needed in this property; handled as a resource
348
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
349
- solutionCommon.getItemResourcesFilesFromPaths(resourceItemFilePaths, srcAuthentication).then(function (resourceItemFiles) {
350
- // update the template's resources
351
- itemTemplate.resources = itemTemplate.resources.concat(resourceItemFiles.map(function (file) {
352
- return file.folder + "/" + file.filename;
353
- }));
354
- // Set the value keyed by the id to the created template, replacing the placeholder template
355
- solutionCommon.replaceTemplate(existingTemplates, itemTemplate.itemId, itemTemplate);
356
- // Trace item dependencies
357
- if (itemTemplate.dependencies.length === 0) {
358
- itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Finished, 1);
359
- resolve(resourceItemFiles);
360
- }
361
- else {
362
- // Get its dependencies, asking each to get its dependents via
363
- // recursive calls to this function
364
- var dependentDfds_1 = [];
365
- itemTemplate.dependencies.forEach(function (dependentId) {
366
- if (!solutionCommon.findTemplateInList(existingTemplates, dependentId)) {
367
- dependentDfds_1.push(createItemTemplate(solutionItemId, dependentId, templateDictionary, srcAuthentication, destAuthentication, existingTemplates, itemProgressCallback));
368
- }
369
- });
370
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
371
- Promise.all(dependentDfds_1).then(function (dependentResourceItemFiles) {
372
- // Templatization of item and its dependencies done
373
- itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Finished, 1);
374
- resourceItemFiles = dependentResourceItemFiles.reduce(function (accumulator, currentValue) {
375
- return accumulator.concat(currentValue);
376
- }, resourceItemFiles);
377
- resolve(resourceItemFiles);
378
- });
379
- }
380
- });
381
- });
382
- }, function (error) {
383
- placeholder.properties["error"] = JSON.stringify(error);
384
- solutionCommon.replaceTemplate(existingTemplates, itemId, placeholder);
385
- itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Failed, 1);
386
- resolve([]);
387
- });
388
- }
389
- },
390
- // Id not found or item is not accessible
391
- function () {
392
- itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Failed, 1);
393
- itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Failed, 1);
394
- resolve([]);
395
- });
396
- }
397
- });
398
- }
399
- /**
400
- * Templatizes field references within specific template types.
401
- * Currently only handles web applications
402
- *
403
- * @param templates List of solution templates
404
- * @return A list of templates that have templatized field references
405
- */
406
- function postProcessFieldReferences(templates) {
407
- var datasourceInfos = _getDatasourceInfos(templates);
408
- var templateTypeHash = _getTemplateTypeHash(templates);
409
- return templates.map(function (template) {
410
- /* istanbul ignore else */
411
- if (template.type === "Web Mapping Application" ||
412
- template.type === "Dashboard" ||
413
- template.type === "Web Map") {
414
- var webMapFSDependencies = _getWebMapFSDependencies(template, templateTypeHash);
415
- var itemHandler = moduleMap[template.item.type];
416
- /* istanbul ignore else */
417
- if (itemHandler) {
418
- var dependencies_1 = webMapFSDependencies.concat(template.dependencies);
419
- var dependantDatasources = datasourceInfos.filter(function (ds) {
420
- if (dependencies_1.indexOf(ds.itemId) > -1) {
421
- return ds;
422
- }
423
- });
424
- dependantDatasources = _addMapLayerIds(dependantDatasources, templateTypeHash);
425
- if (dependantDatasources.length > 0) {
426
- template = itemHandler.postProcessFieldReferences(template, dependantDatasources, template.item.type);
427
- }
428
- }
429
- }
430
- return template;
431
- });
432
- }
433
- // ------------------------------------------------------------------------------------------------------------------ //
434
- /**
435
- * Get common properties that will support the templatization of field references
436
- *
437
- * @param templates List of solution templates
438
- * @return A list of IDataSourceInfo objects with key properties
439
- */
440
- function _getDatasourceInfos(templates) {
441
- var datasourceInfos = [];
442
- templates.forEach(function (t) {
443
- if (t.type === "Feature Service") {
444
- var layers = hubCommon.getProp(t, "properties.layers") || [];
445
- var tables = hubCommon.getProp(t, "properties.tables") || [];
446
- var layersAndTables = layers.concat(tables);
447
- layersAndTables.forEach(function (obj) {
448
- /* istanbul ignore else */
449
- if (!solutionCommon.hasDatasource(datasourceInfos, t.itemId, obj.id)) {
450
- datasourceInfos.push({
451
- itemId: t.itemId,
452
- layerId: obj.id,
453
- fields: obj.fields,
454
- basePath: t.itemId + ".layer" + obj.id + ".fields",
455
- url: hubCommon.getProp(t, "item.url"),
456
- ids: [],
457
- relationships: obj.relationships || [],
458
- adminLayerInfo: obj.adminLayerInfo || {}
459
- });
460
- }
461
- });
462
- }
463
- });
464
- return datasourceInfos;
465
- }
466
- /**
467
- * Creates a simple lookup object to quickly understand an items type and dependencies
468
- * and associated web map layer ids based on itemId
469
- *
470
- * @param templates List of solution templates
471
- * @return The lookup object with type, dependencies, and webmap layer info
472
- */
473
- function _getTemplateTypeHash(templates) {
474
- var templateTypeHash = {};
475
- templates.forEach(function (template) {
476
- templateTypeHash[template.itemId] = {
477
- type: template.type,
478
- dependencies: template.dependencies
479
- };
480
- if (template.type === "Web Map") {
481
- _updateWebMapHashInfo(template, templateTypeHash[template.itemId]);
482
- }
483
- });
484
- return templateTypeHash;
485
- }
486
- /**
487
- * Updates the lookup object with webmap layer info
488
- * so we can know the id used within a map for a given feature service
489
- *
490
- * @param template A webmap solution template
491
- * @return The lookup object with webmap layer info added
492
- */
493
- function _updateWebMapHashInfo(template, hashItem) {
494
- var operationalLayers = hubCommon.getProp(template, "data.operationalLayers") || [];
495
- var tables = hubCommon.getProp(template, "data.tables") || [];
496
- var layersAndTables = operationalLayers.concat(tables);
497
- if (layersAndTables && layersAndTables.length > 0) {
498
- hashItem.layersAndTables = [];
499
- layersAndTables.forEach(function (layer) {
500
- var obj = {};
501
- var itemId;
502
- /* istanbul ignore else */
503
- if (layer.itemId) {
504
- itemId = layer.itemId;
505
- }
506
- /* istanbul ignore else */
507
- if (itemId) {
508
- obj[solutionCommon.cleanLayerBasedItemId(itemId)] = {
509
- id: layer.id,
510
- url: layer.url
511
- };
512
- hashItem.layersAndTables.push(obj);
513
- }
514
- });
515
- }
516
- }
517
- /**
518
- * Updates a templatized datasource URL with a layer id.
519
- *
520
- * @param dataSourceUrl Templatized datasource URL
521
- * @param layerId Layer id
522
- * @return string Amended datasource URL
523
- */
524
- function _addLayerIdToDatasourceUrl(datasourceUrl, layerId) {
525
- return datasourceUrl && !isNaN(layerId)
526
- ? datasourceUrl.replace(/[.]/, ".layer" + layerId + ".")
527
- : "";
528
- }
529
- /**
530
- * Updates the datasource info objects by passing the webmap layer IDs from the lookup hash
531
- * to the underlying feature service datasource infos
532
- *
533
- * @param datasourceInfos A webmap solution template
534
- * @param templateTypeHash A simple lookup object populated with key item info
535
- * @return The updated datasource infos
536
- */
537
- function _addMapLayerIds(datasourceInfos, templateTypeHash) {
538
- var webMapIds = Object.keys(templateTypeHash).filter(function (k) {
539
- if (templateTypeHash[k].type === "Web Map") {
540
- return templateTypeHash[k];
541
- }
542
- });
543
- return datasourceInfos.map(function (ds) {
544
- webMapIds.forEach(function (webMapId) {
545
- templateTypeHash[webMapId].layersAndTables.forEach(function (opLayer) {
546
- var opLayerInfo = opLayer[ds.itemId];
547
- var url = _addLayerIdToDatasourceUrl(ds.url, ds.layerId);
548
- if (opLayerInfo &&
549
- url === opLayerInfo.url &&
550
- ds.ids.indexOf(opLayerInfo.id) < 0) {
551
- ds.ids.push(opLayerInfo.id);
552
- }
553
- });
554
- });
555
- return ds;
556
- });
557
- }
558
- /**
559
- * Get feature service item IDs from applications webmaps
560
- * As they are not explict dependencies of the application but are needed for field references
561
- *
562
- * @param template A webmap solution template
563
- * @param templateTypeHash A simple lookup object populated with key item info
564
- * @return A lsit of feature service item IDs
565
- */
566
- function _getWebMapFSDependencies(template, templateTypeHash) {
567
- var webMapFSDependencies = [];
568
- template.dependencies.forEach(function (dep) {
569
- var depObj = templateTypeHash[dep];
570
- if (depObj.type === "Web Map") {
571
- depObj.dependencies.forEach(function (depObjDependency) {
572
- /* istanbul ignore else */
573
- if (templateTypeHash[depObjDependency].type === "Feature Service") {
574
- webMapFSDependencies.push(depObjDependency);
575
- }
576
- });
577
- }
578
- });
579
- return webMapFSDependencies;
580
- }
47
+ /** @license
48
+ * Copyright 2020 Esri
49
+ *
50
+ * Licensed under the Apache License, Version 2.0 (the "License");
51
+ * you may not use this file except in compliance with the License.
52
+ * You may obtain a copy of the License at
53
+ *
54
+ * http://www.apache.org/licenses/LICENSE-2.0
55
+ *
56
+ * Unless required by applicable law or agreed to in writing, software
57
+ * distributed under the License is distributed on an "AS IS" BASIS,
58
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
59
+ * See the License for the specific language governing permissions and
60
+ * limitations under the License.
61
+ */
62
+ const UNSUPPORTED = null;
63
+ /**
64
+ * Mapping from item type to module with type-specific template-handling code.
65
+ * AGO types come from a blend of arcgis-portal-app\src\js\arcgisonline\pages\item\_Info.js and
66
+ * arcgis-portal-app\src\js\arcgis-components\src\_utils\metadata\item\displayName.ts
67
+ */
68
+ const moduleMap = {
69
+ ////////////////////////////////////////////////////////
70
+ // Group type
71
+ Group: group__namespace,
72
+ ////////////////////////////////////////////////////////
73
+ // Layer types
74
+ "Big Data Analytic": solutionVelocity.VelocityProcessor,
75
+ "Feature Collection": solutionSimpleTypes.simpleTypes,
76
+ "Feature Service": featureLayer__namespace,
77
+ Feed: solutionVelocity.VelocityProcessor,
78
+ "Geocoding Service": undefined,
79
+ "Geodata Service": undefined,
80
+ "Geometry Service": undefined,
81
+ "Geoprocessing Service": undefined,
82
+ "Globe Service": undefined,
83
+ "Image Service": undefined,
84
+ KML: undefined,
85
+ "Map Service": featureLayer__namespace,
86
+ "Network Analysis Service": undefined,
87
+ "Real Time Analytic": solutionVelocity.VelocityProcessor,
88
+ "Relational Database Connection": undefined,
89
+ "Scene Service": undefined,
90
+ "Stream Service": undefined,
91
+ Tool: undefined,
92
+ "Vector Tile Service": undefined,
93
+ WFS: undefined,
94
+ WMS: undefined,
95
+ WMTS: undefined,
96
+ "Workflow Manager Service": undefined,
97
+ ////////////////////////////////////////////////////////
98
+ // Map types
99
+ "3D Web Scene": undefined,
100
+ "Web Map": solutionSimpleTypes.simpleTypes,
101
+ "Web Scene": solutionSimpleTypes.simpleTypes,
102
+ ////////////////////////////////////////////////////////
103
+ // App types
104
+ Application: undefined,
105
+ Dashboard: solutionSimpleTypes.simpleTypes,
106
+ "Data Store": undefined,
107
+ "Desktop Application": undefined,
108
+ "Excalibur Imagery Project": undefined,
109
+ Form: formProcessor__namespace,
110
+ "Hub Initiative": UNSUPPORTED,
111
+ "Hub Page": solutionHubTypes.HubPageProcessor,
112
+ "Hub Site Application": solutionHubTypes.HubSiteProcessor,
113
+ "Insights Model": solutionSimpleTypes.simpleTypes,
114
+ "Insights Page": undefined,
115
+ "Insights Theme": undefined,
116
+ "Insights Workbook": undefined,
117
+ Mission: undefined,
118
+ "Mobile Application": undefined,
119
+ Notebook: solutionSimpleTypes.notebookProcessor,
120
+ "Oriented Imagery Catalog": solutionSimpleTypes.simpleTypes,
121
+ "Ortho Mapping Project": undefined,
122
+ "QuickCapture Project": solutionSimpleTypes.quickcaptureProcessor,
123
+ "Site Application": solutionHubTypes.HubSiteProcessor,
124
+ "Site Page": solutionHubTypes.HubPageProcessor,
125
+ Solution: UNSUPPORTED,
126
+ StoryMap: solutionStorymap.StoryMapProcessor,
127
+ "Urban Model": undefined,
128
+ "Web Experience Template": undefined,
129
+ "Web Experience": solutionWebExperience.WebExperienceProcessor,
130
+ "Web Mapping Application": solutionSimpleTypes.simpleTypes,
131
+ "Workforce Project": solutionSimpleTypes.simpleTypes,
132
+ ////////////////////////////////////////////////////////
133
+ // File types
134
+ "360 VR Experience": fileProcessor__namespace,
135
+ "AppBuilder Extension": fileProcessor__namespace,
136
+ "AppBuilder Widget Package": fileProcessor__namespace,
137
+ "Application Configuration": fileProcessor__namespace,
138
+ "ArcGIS Pro Add In": fileProcessor__namespace,
139
+ "ArcGIS Pro Configuration": fileProcessor__namespace,
140
+ "ArcPad Package": fileProcessor__namespace,
141
+ "Basemap Package": fileProcessor__namespace,
142
+ "CAD Drawing": fileProcessor__namespace,
143
+ "CityEngine Web Scene": fileProcessor__namespace,
144
+ "Code Attachment": UNSUPPORTED,
145
+ "Code Sample": fileProcessor__namespace,
146
+ "Color Set": fileProcessor__namespace,
147
+ "Compact Tile Package": fileProcessor__namespace,
148
+ "CSV Collection": fileProcessor__namespace,
149
+ CSV: fileProcessor__namespace,
150
+ "Deep Learning Package": fileProcessor__namespace,
151
+ "Desktop Add In": fileProcessor__namespace,
152
+ "Desktop Application Template": fileProcessor__namespace,
153
+ "Desktop Style": fileProcessor__namespace,
154
+ "Document Link": fileProcessor__namespace,
155
+ "Explorer Add In": fileProcessor__namespace,
156
+ "Explorer Layer": fileProcessor__namespace,
157
+ "Explorer Map": fileProcessor__namespace,
158
+ "Feature Collection Template": fileProcessor__namespace,
159
+ "File Geodatabase": fileProcessor__namespace,
160
+ GeoJson: fileProcessor__namespace,
161
+ GeoPackage: fileProcessor__namespace,
162
+ "Geoprocessing Package": fileProcessor__namespace,
163
+ "Geoprocessing Sample": fileProcessor__namespace,
164
+ "Globe Document": fileProcessor__namespace,
165
+ "Image Collection": fileProcessor__namespace,
166
+ Image: fileProcessor__namespace,
167
+ "iWork Keynote": fileProcessor__namespace,
168
+ "iWork Numbers": fileProcessor__namespace,
169
+ "iWork Pages": fileProcessor__namespace,
170
+ "KML Collection": fileProcessor__namespace,
171
+ "Layer Package": fileProcessor__namespace,
172
+ "Layer Template": fileProcessor__namespace,
173
+ Layer: fileProcessor__namespace,
174
+ Layout: fileProcessor__namespace,
175
+ "Locator Package": fileProcessor__namespace,
176
+ "Map Document": fileProcessor__namespace,
177
+ "Map Package": fileProcessor__namespace,
178
+ "Map Template": fileProcessor__namespace,
179
+ "Microsoft Excel": fileProcessor__namespace,
180
+ "Microsoft Powerpoint": fileProcessor__namespace,
181
+ "Microsoft Word": fileProcessor__namespace,
182
+ "Mobile Basemap Package": fileProcessor__namespace,
183
+ "Mobile Map Package": fileProcessor__namespace,
184
+ "Mobile Scene Package": fileProcessor__namespace,
185
+ "Native Application": fileProcessor__namespace,
186
+ "Native Application Installer": fileProcessor__namespace,
187
+ "Native Application Template": fileProcessor__namespace,
188
+ netCDF: fileProcessor__namespace,
189
+ "Operation View": fileProcessor__namespace,
190
+ "Operations Dashboard Add In": fileProcessor__namespace,
191
+ "Operations Dashboard Extension": fileProcessor__namespace,
192
+ PDF: fileProcessor__namespace,
193
+ "Pro Layer Package": fileProcessor__namespace,
194
+ "Pro Layer": fileProcessor__namespace,
195
+ "Pro Map Package": fileProcessor__namespace,
196
+ "Pro Map": fileProcessor__namespace,
197
+ "Pro Report": fileProcessor__namespace,
198
+ "Project Package": fileProcessor__namespace,
199
+ "Project Template": fileProcessor__namespace,
200
+ "Published Map": fileProcessor__namespace,
201
+ "Raster function template": fileProcessor__namespace,
202
+ "Report Template": fileProcessor__namespace,
203
+ "Rule Package": fileProcessor__namespace,
204
+ "Scene Document": fileProcessor__namespace,
205
+ "Scene Package": fileProcessor__namespace,
206
+ "Service Definition": fileProcessor__namespace,
207
+ Shapefile: fileProcessor__namespace,
208
+ "Statistical Data Collection": fileProcessor__namespace,
209
+ Style: fileProcessor__namespace,
210
+ "Survey123 Add In": fileProcessor__namespace,
211
+ "Symbol Set": fileProcessor__namespace,
212
+ "Task File": fileProcessor__namespace,
213
+ "Tile Package": fileProcessor__namespace,
214
+ "Toolbox Package": fileProcessor__namespace,
215
+ "Vector Tile Package": fileProcessor__namespace,
216
+ "Viewer Configuration": fileProcessor__namespace,
217
+ "Visio Document": fileProcessor__namespace,
218
+ "Window Mobile Package": fileProcessor__namespace,
219
+ "Windows Mobile Package": fileProcessor__namespace,
220
+ "Windows Viewer Add In": fileProcessor__namespace,
221
+ "Windows Viewer Configuration": fileProcessor__namespace,
222
+ "Workflow Manager Package": fileProcessor__namespace,
223
+ ////////////////////////////////////////////////////////
224
+ // Testing "types"
225
+ Undefined: undefined,
226
+ Unsupported: UNSUPPORTED
227
+ };
581
228
 
582
- /** @license
583
- * Copyright 2020 Esri
584
- *
585
- * Licensed under the Apache License, Version 2.0 (the "License");
586
- * you may not use this file except in compliance with the License.
587
- * You may obtain a copy of the License at
588
- *
589
- * http://www.apache.org/licenses/LICENSE-2.0
590
- *
591
- * Unless required by applicable law or agreed to in writing, software
592
- * distributed under the License is distributed on an "AS IS" BASIS,
593
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
594
- * See the License for the specific language governing permissions and
595
- * limitations under the License.
596
- */
597
- /**
598
- * Adds a list of AGO item ids to a solution item.
599
- *
600
- * @param solutionItemId AGO id of solution to receive items
601
- * @param options Customizations for creating the solution
602
- * @param srcAuthentication Credentials for requests to source items
603
- * @param destAuthentication Credentials for the requests to destination solution
604
- * @return A promise that resolves with the AGO id of the updated solution
605
- * @internal
606
- */
607
- function addContentToSolution(solutionItemId, options, srcAuthentication, destAuthentication) {
608
- return new Promise(function (resolve, reject) {
609
- var _a;
610
- if (!options.itemIds || options.itemIds.length === 0) {
611
- resolve(solutionItemId);
612
- return;
613
- }
614
- // Prepare feedback mechanism
615
- var totalEstimatedCost = 2 * options.itemIds.length + 1; // solution items, plus avoid divide by 0
616
- var percentDone = 16; // allow for previous creation work
617
- var progressPercentStep = (95 - percentDone) / totalEstimatedCost; // leave some % for caller for wrapup
618
- var failedItemIds = [];
619
- var totalExpended = 0;
620
- var statusOK = true;
621
- var itemProgressCallback = function (itemId, status, costUsed) {
622
- var _a;
623
- // ---------------------------------------------------------------------------------------------------------------
624
- if (options.itemIds.indexOf(itemId) < 0) {
625
- // New item--a dependency that wasn't in the supplied list of itemIds; add it to the list
626
- // and recalculate the progress percent step based on how much progress remains to be done
627
- options.itemIds.push(itemId);
628
- totalEstimatedCost += 2;
629
- progressPercentStep =
630
- (95 - percentDone) / (totalEstimatedCost - totalExpended);
631
- }
632
- totalExpended += costUsed;
633
- percentDone += progressPercentStep * costUsed;
634
- if (options.progressCallback) {
635
- options.progressCallback(Math.round(percentDone), options.jobId);
636
- }
637
- /* istanbul ignore if */
638
- if (options.consoleProgress) {
639
- console.log(Date.now(), itemId, (_a = options.jobId) !== null && _a !== void 0 ? _a : "", solutionCommon.SItemProgressStatus[status], percentDone.toFixed(0) + "%", costUsed);
640
- }
641
- if (status === solutionCommon.EItemProgressStatus.Failed) {
642
- var error_1 = "";
643
- solutionTemplates.some(function (t) {
644
- /* istanbul ignore else */
645
- if (t.itemId === itemId) {
646
- /* istanbul ignore else */
647
- if (hubCommon.getProp(t, "properties.error")) {
648
- error_1 = t.properties.error;
649
- try {
650
- // parse for better console logging if we can
651
- error_1 = JSON.parse(error_1);
652
- }
653
- catch (e) {
654
- /* istanbul ignore next */
655
- // do nothing and show the error as is
656
- }
657
- }
658
- return true;
659
- }
660
- });
661
- solutionCommon.removeTemplate(solutionTemplates, itemId);
662
- if (failedItemIds.indexOf(itemId) < 0) {
663
- failedItemIds.push(itemId);
664
- }
665
- statusOK = false;
666
- }
667
- else if (status === solutionCommon.EItemProgressStatus.Ignored) {
668
- solutionCommon.removeTemplate(solutionTemplates, itemId);
669
- }
670
- return statusOK;
671
- // ---------------------------------------------------------------------------------------------------------------
672
- };
673
- // Replacement dictionary and created templates
674
- var templateDictionary = (_a = options.templateDictionary) !== null && _a !== void 0 ? _a : {};
675
- var solutionTemplates = [];
676
- // Handle a list of one or more AGO ids by stepping through the list
677
- // and calling this function recursively
678
- var getItemsPromise = [];
679
- options.itemIds.forEach(function (itemId) {
680
- var createDef = createItemTemplate(solutionItemId, itemId, templateDictionary, srcAuthentication, destAuthentication, solutionTemplates, itemProgressCallback);
681
- getItemsPromise.push(createDef);
682
- });
683
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
684
- Promise.all(getItemsPromise).then(function (multipleResourceItemFiles) {
685
- if (failedItemIds.length > 0) {
686
- reject(solutionCommon.failWithIds(failedItemIds, "One or more items cannot be converted into templates"));
687
- }
688
- else {
689
- if (solutionTemplates.length > 0) {
690
- // Coalesce the resource file paths from the created templates
691
- var resourceItemFiles = multipleResourceItemFiles.reduce(function (accumulator, currentValue) { return accumulator.concat(currentValue); }, []);
692
- // test for and update group dependencies and other post-processing
693
- solutionTemplates = _postProcessGroupDependencies(solutionTemplates);
694
- solutionTemplates = solutionCommon.postProcessWorkforceTemplates(solutionTemplates);
695
- // Filter out any resources from items that have been removed from the templates, such as
696
- // Living Atlas layers
697
- solutionTemplates = _postProcessIgnoredItems(solutionTemplates);
698
- var templateIds_1 = solutionTemplates.map(function (template) { return template.itemId; });
699
- // Coalesce the resource file paths from the created templates
700
- resourceItemFiles = resourceItemFiles.filter(function (file) {
701
- return templateIds_1.includes(file.itemId);
702
- });
703
- // Send the accumulated resources to the solution item
704
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
705
- solutionCommon.copyFilesToStorageItem(resourceItemFiles, solutionItemId, destAuthentication).then(function () {
706
- _templatizeSolutionIds(solutionTemplates);
707
- _simplifyUrlsInItemDescriptions(solutionTemplates);
708
- _replaceDictionaryItemsInObject(templateDictionary, solutionTemplates);
709
- _templatizeOrgUrl(solutionTemplates, destAuthentication).then(function (solutionTemplates2) {
710
- // Update solution item with its data JSON
711
- var solutionData = {
712
- metadata: { version: solutionCommon.SolutionTemplateFormatVersion },
713
- templates: options.templatizeFields
714
- ? postProcessFieldReferences(solutionTemplates2)
715
- : solutionTemplates2
716
- };
717
- var itemInfo = {
718
- id: solutionItemId,
719
- text: solutionData
720
- };
721
- solutionCommon.updateItem(itemInfo, destAuthentication).then(function () {
722
- resolve(solutionItemId);
723
- }, reject);
724
- }, reject);
725
- });
726
- }
727
- else {
728
- resolve(solutionItemId);
729
- }
730
- }
731
- });
732
- });
733
- }
734
- // ------------------------------------------------------------------------------------------------------------------ //
735
- /**
736
- * Gets the dependencies of an item by merging its dependencies list with item references in template variables.
737
- *
738
- * @param template Template to examine
739
- * @return List of dependency ids
740
- * @private
741
- */
742
- function _getDependencies(template) {
743
- // Get all dependencies
744
- var deps = template.dependencies.concat(_getIdsOutOfTemplateVariables(_getTemplateVariables(JSON.stringify(template.data))));
745
- // Remove duplicates and self-references
746
- deps.sort();
747
- deps = deps.filter(function (elem, index, array) {
748
- if (elem === template.itemId) {
749
- return false;
750
- }
751
- else if (index > 0) {
752
- return elem !== array[index - 1];
753
- }
754
- else {
755
- return true;
756
- }
757
- });
758
- return deps;
759
- }
760
- /**
761
- * Extracts AGO ids out of template variables.
762
- *
763
- * @param variables List of template variables to examine
764
- * @return List of AGO ids referenced in `variables`
765
- * @private
766
- */
767
- function _getIdsOutOfTemplateVariables(variables) {
768
- return variables
769
- .map(function (variable) {
770
- var idList = variable.match(/[0-9A-F]{32}/i); // is it a guid?
771
- if (idList) {
772
- return idList[0];
773
- }
774
- else {
775
- return null;
776
- }
777
- })
778
- .filter(function (variable) { return !!variable; });
779
- }
780
- /**
781
- * Creates a list of item URLs.
782
- *
783
- * @param templates Templates to check for URLs
784
- * @return List of URLs
785
- * @private
786
- */
787
- function _getSolutionItemUrls(templates) {
788
- var solutionUrls = [];
789
- templates.forEach(function (template) {
790
- /* istanbul ignore else */
791
- if (template.item.origUrl) {
792
- solutionUrls.push([template.itemId, template.item.origUrl]);
793
- }
794
- });
795
- return solutionUrls;
796
- }
797
- /**
798
- * Extracts template variables out of a string.
799
- *
800
- * @param text String to examine
801
- * @return List of template variables found in string
802
- * @private
803
- */
804
- function _getTemplateVariables(text) {
805
- return (text.match(/{{[a-z0-9.]*}}/gi) || []) // find variable
806
- .map(function (variable) { return variable.substring(2, variable.length - 2); }); // remove "{{" & "}}"
807
- }
808
- /**
809
- * Update the items dependencies and groups arrays
810
- *
811
- * @param templates The array of templates to evaluate
812
- * @return Updated version of the templates
813
- * @private
814
- */
815
- function _postProcessGroupDependencies(templates) {
816
- return templates.map(function (template) {
817
- if (template.type === "Group") {
818
- var id_1 = template.itemId;
819
- // remove group dependencies if we find a circular dependency with one of its items
820
- var removeDependencies_1 = false;
821
- // before we remove update each dependants groups array
822
- template.dependencies.forEach(function (dependencyId) {
823
- var dependantTemplate = solutionCommon.getTemplateById(templates, dependencyId);
824
- // Not all items shared to the group will exist in the templates array
825
- // i.e. Hub Initiative items or any other unsupported types
826
- if (dependantTemplate) {
827
- // check if the group is in the dependantTemplate's list of dependencies
828
- var gIndex = hubCommon.getWithDefault(dependantTemplate, "dependencies", []).indexOf(id_1);
829
- /* istanbul ignore else */
830
- if (gIndex > -1) {
831
- removeDependencies_1 = true;
832
- }
833
- // if the dependant template does not have the group id
834
- // in it's groups array, add it
835
- var groups = hubCommon.getWithDefault(dependantTemplate, "groups", []);
836
- if (groups.indexOf(id_1) === -1) {
837
- groups.push(id_1);
838
- dependantTemplate.groups = groups;
839
- }
840
- }
841
- });
842
- if (removeDependencies_1) {
843
- template.dependencies = [];
844
- }
845
- }
846
- return template;
847
- });
848
- }
849
- /**
850
- * Check for feature service items that have been flagged for invalid designations.
851
- * Remove templates that have invalid designations from the solution item and other item dependencies.
852
- * Clean up any references to items with invalid designations in the other templates.
853
- *
854
- * @param templates The array of templates to evaluate
855
- * @return Updated version of the templates
856
- * @private
857
- */
858
- function _postProcessIgnoredItems(templates) {
859
- // replace in template
860
- var updateDictionary = templates.reduce(function (result, template) {
861
- return template.properties.hasInvalidDesignations
862
- ? Object.assign(result, template.data)
863
- : result;
864
- }, {});
865
- Object.keys(updateDictionary).forEach(function (k) {
866
- solutionCommon.removeTemplate(templates, k);
867
- templates = templates.map(function (t) {
868
- t.dependencies = t.dependencies.filter(function (id) { return id !== k; });
869
- return solutionCommon.replaceInTemplate(t, updateDictionary);
870
- });
871
- });
872
- return templates;
873
- }
874
- /**
875
- * Recursively runs through an object to find and replace any strings found in a dictionary.
876
- *
877
- * @param templateDictionary Hash of things to be replaced
878
- * @param obj Object to be examined
879
- * @private
880
- */
881
- function _replaceDictionaryItemsInObject(hash, obj) {
882
- /* istanbul ignore else */
883
- if (obj) {
884
- Object.keys(obj).forEach(function (prop) {
885
- var propObj = obj[prop];
886
- if (propObj) {
887
- if (typeof propObj === "object") {
888
- _replaceDictionaryItemsInObject(hash, propObj);
889
- }
890
- else if (typeof propObj === "string") {
891
- obj[prop] = hash[propObj] || propObj;
892
- }
893
- }
894
- });
895
- }
896
- return obj;
897
- }
898
- /**
899
- * Recursively runs through an object to find and templatize any remaining references to solution's items.
900
- *
901
- * @param ids Ids to be replaced in strings found in object
902
- * @param obj Object to be examined
903
- * @private
904
- */
905
- function _replaceRemainingIdsInObject(ids, obj) {
906
- /* istanbul ignore else */
907
- if (obj) {
908
- Object.keys(obj).forEach(function (prop) {
909
- var propObj = obj[prop];
910
- if (propObj) {
911
- if (typeof propObj === "object") {
912
- _replaceRemainingIdsInObject(ids, propObj);
913
- }
914
- else if (typeof propObj === "string") {
915
- obj[prop] = _replaceRemainingIdsInString(ids, propObj);
916
- }
917
- }
918
- });
919
- }
920
- return obj;
921
- }
922
- /**
923
- * Templatizes ids from a list in a string if they're not already templatized.
924
- *
925
- * @param ids Ids to be replaced in source string
926
- * @param str Source string to be examined
927
- * @return A copy of the source string with any templatization changes
928
- * @private
929
- */
930
- function _replaceRemainingIdsInString(ids, str) {
931
- var updatedStr = str;
932
- var untemplatizedIds = solutionCommon.getIDs(str);
933
- if (untemplatizedIds.length > 0) {
934
- untemplatizedIds.forEach(function (id) {
935
- if (ids.includes(id)) {
936
- var re = new RegExp("({*)" + id, "gi");
937
- updatedStr = updatedStr.replace(re, function (match) {
938
- return match.indexOf("{{") < 0
939
- ? "{{" + id.replace("{", "") + ".itemId}}"
940
- : match;
941
- });
942
- }
943
- });
944
- }
945
- return updatedStr;
946
- }
947
- /**
948
- * Finds and templatizes any URLs in solution items' descriptions.
949
- *
950
- * @param templates The array of templates to evaluate, modified in place
951
- * @private
952
- */
953
- function _simplifyUrlsInItemDescriptions(templates) {
954
- // Get the urls in the solution along with their item ids & convert the id into the form
955
- // "{{fcb2bf2837a6404ebb418a1f805f976a.url}}"
956
- var solutionUrls = _getSolutionItemUrls(templates).map(function (idUrl) { return [
957
- "{{" + idUrl[0] + ".url}}",
958
- idUrl[1]
959
- ]; });
960
- /* istanbul ignore else */
961
- if (solutionUrls.length > 0) {
962
- // Make the replacements
963
- templates.forEach(function (template) {
964
- solutionUrls.forEach(
965
- // TypeScript for es2015 doesn't have a definition for `replaceAll`
966
- function (idUrl) {
967
- /* istanbul ignore else */
968
- if (template.item.description) {
969
- template.item.description = template.item
970
- .description.replaceAll(idUrl[1], idUrl[0]);
971
- }
972
- });
973
- });
974
- }
975
- }
976
- /**
977
- * Templatizes occurrences of the URL to the user's organization in the `item` and `data` template sections.
978
- *
979
- * @param templates The array of templates to evaluate; templates is modified in place
980
- * @param destAuthentication Credentials for request organization info
981
- * @return Promise resolving with `templates`
982
- * @private
983
- */
984
- function _templatizeOrgUrl(templates, destAuthentication) {
985
- return new Promise(function (resolve, reject) {
986
- // Get the org's URL
987
- solutionCommon.getPortal(null, destAuthentication).then(function (org) {
988
- var orgUrl = "https://" + org.urlKey + "." + org.customBaseUrl;
989
- var templatizedOrgUrl = "{{portalBaseUrl}}";
990
- // Cycle through each of the items in the template and scan the `item` and `data` sections of each for replacements
991
- templates.forEach(function (template) {
992
- solutionCommon.globalStringReplace(template.item, new RegExp(orgUrl, "gi"), templatizedOrgUrl);
993
- solutionCommon.globalStringReplace(template.data, new RegExp(orgUrl, "gi"), templatizedOrgUrl);
994
- });
995
- resolve(templates);
996
- }, reject);
997
- });
998
- }
999
- /**
1000
- * Finds and templatizes any references to solution's items.
1001
- *
1002
- * @param templates The array of templates to evaluate, modified in place
1003
- * @private
1004
- */
1005
- function _templatizeSolutionIds(templates) {
1006
- // Get the ids in the solution
1007
- var solutionIds = templates.map(function (template) { return template.itemId; });
1008
- // Cycle through each of the items in the template and
1009
- // 1. templatize untemplatized ids in our solution in the `item` and `data` sections;
1010
- // 2. update the `dependencies` section
1011
- templates.forEach(function (template) {
1012
- _replaceRemainingIdsInObject(solutionIds, template.item);
1013
- _replaceRemainingIdsInObject(solutionIds, template.data);
1014
- /* istanbul ignore else */
1015
- if (template.type !== "Group" && !solutionCommon.isWorkforceProject(template)) {
1016
- template.dependencies = _getDependencies(template);
1017
- }
1018
- });
1019
- }
229
+ /** @license
230
+ * Copyright 2018 Esri
231
+ *
232
+ * Licensed under the Apache License, Version 2.0 (the "License");
233
+ * you may not use this file except in compliance with the License.
234
+ * You may obtain a copy of the License at
235
+ *
236
+ * http://www.apache.org/licenses/LICENSE-2.0
237
+ *
238
+ * Unless required by applicable law or agreed to in writing, software
239
+ * distributed under the License is distributed on an "AS IS" BASIS,
240
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
241
+ * See the License for the specific language governing permissions and
242
+ * limitations under the License.
243
+ */
244
+ // ------------------------------------------------------------------------------------------------------------------ //
245
+ /**
246
+ * Creates template for an AGO item and its dependencies
247
+ *
248
+ * @param solutionItemId The solution to contain the item
249
+ * @param itemId AGO id string
250
+ * @param templateDictionary Hash of facts
251
+ * @param srcAuthentication Credentials for requests to source items
252
+ * @param destAuthentication Authentication for requesting information from AGO about items to be included in solution item
253
+ * @param existingTemplates A collection of AGO item templates that can be referenced by newly-created templates
254
+ * @return A promise which resolves with an array of resources for the item and its dependencies
255
+ * @protected
256
+ */
257
+ function createItemTemplate(solutionItemId, itemId, templateDictionary, srcAuthentication, destAuthentication, existingTemplates, itemProgressCallback) {
258
+ return new Promise(resolve => {
259
+ // Check if item and its dependents are already in list or are queued
260
+ if (solutionCommon.findTemplateInList(existingTemplates, itemId)) {
261
+ resolve([]);
262
+ }
263
+ else {
264
+ // Add the id as a placeholder to show that it is being fetched
265
+ existingTemplates.push(solutionCommon.createPlaceholderTemplate(itemId));
266
+ itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Started, 0);
267
+ // Fetch the item
268
+ solutionCommon.getItemBase(itemId, srcAuthentication)
269
+ .catch(() => {
270
+ // If item query fails, try fetching item as a group
271
+ // Change its placeholder from an empty type to the Group type so that we can later distinguish
272
+ // between items and groups (the base info for a group doesn't include a type property)
273
+ solutionCommon.replaceTemplate(existingTemplates, itemId, solutionCommon.createPlaceholderTemplate(itemId, "Group"));
274
+ return solutionCommon.getGroupBase(itemId, srcAuthentication);
275
+ })
276
+ .then(itemInfo => {
277
+ itemInfo = solutionCommon.sanitizeJSONAndReportChanges(itemInfo);
278
+ // Save the URL as a symbol
279
+ if (itemInfo.url) {
280
+ templateDictionary[itemInfo.url] = "{{" + itemInfo.id + ".url}}";
281
+ itemInfo.origUrl = itemInfo.url;
282
+ }
283
+ const idTest = /^source-[0-9A-F]{32}/i;
284
+ // Remove any source-itemId type keywords
285
+ if (Array.isArray(itemInfo.typeKeywords)) {
286
+ itemInfo.typeKeywords = itemInfo.typeKeywords.filter(v => idTest.test(v) ? false : true);
287
+ }
288
+ // Remove any source-itemId tags
289
+ /* istanbul ignore else */
290
+ if (Array.isArray(itemInfo.tags)) {
291
+ itemInfo.tags = itemInfo.tags.filter(v => idTest.test(v) ? false : true);
292
+ }
293
+ const placeholder = solutionCommon.findTemplateInList(existingTemplates, itemId);
294
+ let itemType = placeholder.type;
295
+ if (!itemType) {
296
+ // Groups have this defined when their placeholder is created
297
+ itemType = itemInfo.type;
298
+ placeholder.type = itemType;
299
+ }
300
+ if (!itemInfo.type) {
301
+ itemInfo.type = itemType; // Groups don't have this property, so we'll patch it in
302
+ }
303
+ placeholder.item = {
304
+ ...itemInfo
305
+ };
306
+ // Interrupt process if progress callback returns `false`
307
+ if (!itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Created, 1)) {
308
+ itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Cancelled, 1);
309
+ resolve(solutionCommon.fail("Cancelled"));
310
+ return;
311
+ }
312
+ const itemHandler = moduleMap[itemType];
313
+ if (!itemHandler || itemHandler === UNSUPPORTED) {
314
+ if (itemHandler === UNSUPPORTED) {
315
+ itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Ignored, 1);
316
+ resolve([]);
317
+ }
318
+ else {
319
+ itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Failed, 1);
320
+ placeholder.properties["failed"] = true;
321
+ solutionCommon.replaceTemplate(existingTemplates, itemId, placeholder);
322
+ resolve(solutionCommon.fail("The type of AGO item " +
323
+ itemId +
324
+ " ('" +
325
+ itemType +
326
+ "') is not supported at this time"));
327
+ }
328
+ }
329
+ else {
330
+ // Handle original Story Maps with next-gen Story Maps
331
+ /* istanbul ignore else */
332
+ /* Not yet supported
333
+ if (storyMap.isAStoryMap(itemType, itemInfo.url)) {
334
+ itemHandler = storyMap;
335
+ } */
336
+ // Delegate the creation of the item to the handler
337
+ itemHandler
338
+ .convertItemToTemplate(solutionItemId, itemInfo, destAuthentication, srcAuthentication, templateDictionary)
339
+ .then(itemTemplate => {
340
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
341
+ solutionCommon.getItemResourcesPaths(itemTemplate, solutionItemId, srcAuthentication, solutionCommon.SolutionTemplateFormatVersion).then((resourceItemFilePaths) => {
342
+ itemTemplate.item.thumbnail = null; // not needed in this property; handled as a resource
343
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
344
+ solutionCommon.getItemResourcesFilesFromPaths(resourceItemFilePaths, srcAuthentication).then((resourceItemFiles) => {
345
+ // update the template's resources
346
+ itemTemplate.resources = itemTemplate.resources.concat(resourceItemFiles.map((file) => file.folder + "/" + file.filename));
347
+ // Set the value keyed by the id to the created template, replacing the placeholder template
348
+ solutionCommon.replaceTemplate(existingTemplates, itemTemplate.itemId, itemTemplate);
349
+ // Trace item dependencies
350
+ if (itemTemplate.dependencies.length === 0) {
351
+ itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Finished, 1);
352
+ resolve(resourceItemFiles);
353
+ }
354
+ else {
355
+ // Get its dependencies, asking each to get its dependents via
356
+ // recursive calls to this function
357
+ const dependentDfds = [];
358
+ itemTemplate.dependencies.forEach(dependentId => {
359
+ if (!solutionCommon.findTemplateInList(existingTemplates, dependentId)) {
360
+ dependentDfds.push(createItemTemplate(solutionItemId, dependentId, templateDictionary, srcAuthentication, destAuthentication, existingTemplates, itemProgressCallback));
361
+ }
362
+ });
363
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
364
+ Promise.all(dependentDfds).then((dependentResourceItemFiles) => {
365
+ // Templatization of item and its dependencies done
366
+ itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Finished, 1);
367
+ resourceItemFiles = dependentResourceItemFiles.reduce((accumulator, currentValue) => accumulator.concat(currentValue), resourceItemFiles);
368
+ resolve(resourceItemFiles);
369
+ });
370
+ }
371
+ });
372
+ });
373
+ }, error => {
374
+ placeholder.properties["error"] = JSON.stringify(error);
375
+ solutionCommon.replaceTemplate(existingTemplates, itemId, placeholder);
376
+ itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Failed, 1);
377
+ resolve([]);
378
+ });
379
+ }
380
+ },
381
+ // Id not found or item is not accessible
382
+ () => {
383
+ itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Failed, 1);
384
+ itemProgressCallback(itemId, solutionCommon.EItemProgressStatus.Failed, 1);
385
+ resolve([]);
386
+ });
387
+ }
388
+ });
389
+ }
390
+ /**
391
+ * Templatizes field references within specific template types.
392
+ * Currently only handles web applications
393
+ *
394
+ * @param templates List of solution templates
395
+ * @return A list of templates that have templatized field references
396
+ */
397
+ function postProcessFieldReferences(templates) {
398
+ const datasourceInfos = _getDatasourceInfos(templates);
399
+ const templateTypeHash = _getTemplateTypeHash(templates);
400
+ return templates.map(template => {
401
+ /* istanbul ignore else */
402
+ if (template.type === "Web Mapping Application" ||
403
+ template.type === "Dashboard" ||
404
+ template.type === "Web Map") {
405
+ const webMapFSDependencies = _getWebMapFSDependencies(template, templateTypeHash);
406
+ const itemHandler = moduleMap[template.item.type];
407
+ /* istanbul ignore else */
408
+ if (itemHandler) {
409
+ const dependencies = webMapFSDependencies.concat(template.dependencies);
410
+ let dependantDatasources = datasourceInfos.filter(ds => {
411
+ if (dependencies.indexOf(ds.itemId) > -1) {
412
+ return ds;
413
+ }
414
+ });
415
+ dependantDatasources = _addMapLayerIds(dependantDatasources, templateTypeHash);
416
+ if (dependantDatasources.length > 0) {
417
+ template = itemHandler.postProcessFieldReferences(template, dependantDatasources, template.item.type);
418
+ }
419
+ }
420
+ }
421
+ return template;
422
+ });
423
+ }
424
+ // ------------------------------------------------------------------------------------------------------------------ //
425
+ /**
426
+ * Get common properties that will support the templatization of field references
427
+ *
428
+ * @param templates List of solution templates
429
+ * @return A list of IDataSourceInfo objects with key properties
430
+ */
431
+ function _getDatasourceInfos(templates) {
432
+ const datasourceInfos = [];
433
+ templates.forEach(t => {
434
+ if (t.type === "Feature Service") {
435
+ const layers = hubCommon.getProp(t, "properties.layers") || [];
436
+ const tables = hubCommon.getProp(t, "properties.tables") || [];
437
+ const layersAndTables = layers.concat(tables);
438
+ layersAndTables.forEach(obj => {
439
+ /* istanbul ignore else */
440
+ if (!solutionCommon.hasDatasource(datasourceInfos, t.itemId, obj.id)) {
441
+ datasourceInfos.push({
442
+ itemId: t.itemId,
443
+ layerId: obj.id,
444
+ fields: obj.fields,
445
+ basePath: t.itemId + ".layer" + obj.id + ".fields",
446
+ url: hubCommon.getProp(t, "item.url"),
447
+ ids: [],
448
+ relationships: obj.relationships || [],
449
+ adminLayerInfo: obj.adminLayerInfo || {}
450
+ });
451
+ }
452
+ });
453
+ }
454
+ });
455
+ return datasourceInfos;
456
+ }
457
+ /**
458
+ * Creates a simple lookup object to quickly understand an items type and dependencies
459
+ * and associated web map layer ids based on itemId
460
+ *
461
+ * @param templates List of solution templates
462
+ * @return The lookup object with type, dependencies, and webmap layer info
463
+ */
464
+ function _getTemplateTypeHash(templates) {
465
+ const templateTypeHash = {};
466
+ templates.forEach(template => {
467
+ templateTypeHash[template.itemId] = {
468
+ type: template.type,
469
+ dependencies: template.dependencies
470
+ };
471
+ if (template.type === "Web Map") {
472
+ _updateWebMapHashInfo(template, templateTypeHash[template.itemId]);
473
+ }
474
+ });
475
+ return templateTypeHash;
476
+ }
477
+ /**
478
+ * Updates the lookup object with webmap layer info
479
+ * so we can know the id used within a map for a given feature service
480
+ *
481
+ * @param template A webmap solution template
482
+ * @return The lookup object with webmap layer info added
483
+ */
484
+ function _updateWebMapHashInfo(template, hashItem) {
485
+ const operationalLayers = hubCommon.getProp(template, "data.operationalLayers") || [];
486
+ const tables = hubCommon.getProp(template, "data.tables") || [];
487
+ const layersAndTables = operationalLayers.concat(tables);
488
+ if (layersAndTables && layersAndTables.length > 0) {
489
+ hashItem.layersAndTables = [];
490
+ layersAndTables.forEach(layer => {
491
+ const obj = {};
492
+ let itemId;
493
+ /* istanbul ignore else */
494
+ if (layer.itemId) {
495
+ itemId = layer.itemId;
496
+ }
497
+ /* istanbul ignore else */
498
+ if (itemId) {
499
+ obj[solutionCommon.cleanLayerBasedItemId(itemId)] = {
500
+ id: layer.id,
501
+ url: layer.url
502
+ };
503
+ hashItem.layersAndTables.push(obj);
504
+ }
505
+ });
506
+ }
507
+ }
508
+ /**
509
+ * Updates a templatized datasource URL with a layer id.
510
+ *
511
+ * @param dataSourceUrl Templatized datasource URL
512
+ * @param layerId Layer id
513
+ * @return string Amended datasource URL
514
+ */
515
+ function _addLayerIdToDatasourceUrl(datasourceUrl, layerId) {
516
+ return datasourceUrl && !isNaN(layerId)
517
+ ? datasourceUrl.replace(/[.]/, ".layer" + layerId + ".")
518
+ : "";
519
+ }
520
+ /**
521
+ * Updates the datasource info objects by passing the webmap layer IDs from the lookup hash
522
+ * to the underlying feature service datasource infos
523
+ *
524
+ * @param datasourceInfos A webmap solution template
525
+ * @param templateTypeHash A simple lookup object populated with key item info
526
+ * @return The updated datasource infos
527
+ */
528
+ function _addMapLayerIds(datasourceInfos, templateTypeHash) {
529
+ const webMapIds = Object.keys(templateTypeHash).filter(k => {
530
+ if (templateTypeHash[k].type === "Web Map") {
531
+ return templateTypeHash[k];
532
+ }
533
+ });
534
+ return datasourceInfos.map(ds => {
535
+ webMapIds.forEach(webMapId => {
536
+ templateTypeHash[webMapId].layersAndTables.forEach((opLayer) => {
537
+ const opLayerInfo = opLayer[ds.itemId];
538
+ const url = _addLayerIdToDatasourceUrl(ds.url, ds.layerId);
539
+ if (opLayerInfo &&
540
+ url === opLayerInfo.url &&
541
+ ds.ids.indexOf(opLayerInfo.id) < 0) {
542
+ ds.ids.push(opLayerInfo.id);
543
+ }
544
+ });
545
+ });
546
+ return ds;
547
+ });
548
+ }
549
+ /**
550
+ * Get feature service item IDs from applications webmaps
551
+ * As they are not explict dependencies of the application but are needed for field references
552
+ *
553
+ * @param template A webmap solution template
554
+ * @param templateTypeHash A simple lookup object populated with key item info
555
+ * @return A lsit of feature service item IDs
556
+ */
557
+ function _getWebMapFSDependencies(template, templateTypeHash) {
558
+ const webMapFSDependencies = [];
559
+ template.dependencies.forEach(dep => {
560
+ const depObj = templateTypeHash[dep];
561
+ if (depObj.type === "Web Map") {
562
+ depObj.dependencies.forEach((depObjDependency) => {
563
+ /* istanbul ignore else */
564
+ if (templateTypeHash[depObjDependency].type === "Feature Service") {
565
+ webMapFSDependencies.push(depObjDependency);
566
+ }
567
+ });
568
+ }
569
+ });
570
+ return webMapFSDependencies;
571
+ }
1020
572
 
1021
- /** @license
1022
- * Copyright 2018 Esri
1023
- *
1024
- * Licensed under the Apache License, Version 2.0 (the "License");
1025
- * you may not use this file except in compliance with the License.
1026
- * You may obtain a copy of the License at
1027
- *
1028
- * http://www.apache.org/licenses/LICENSE-2.0
1029
- *
1030
- * Unless required by applicable law or agreed to in writing, software
1031
- * distributed under the License is distributed on an "AS IS" BASIS,
1032
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1033
- * See the License for the specific language governing permissions and
1034
- * limitations under the License.
1035
- */
1036
- // Simple no-op to clean up progressCallback management
1037
- var noOp = function () { };
1038
- /**
1039
- * Creates a solution item.
1040
- *
1041
- * @param sourceId AGO id of group whose contents are to be added to solution or of an item to convert into a solution
1042
- * @param srcAuthentication Credentials for requests to source items
1043
- * @param destAuthentication Credentials for the requests to destination solution
1044
- * @param options Customizations for creating the solution
1045
- * @return A promise that resolves with the AGO id of the new solution
1046
- */
1047
- function createSolution(sourceId, srcAuthentication, destAuthentication, options) {
1048
- var createOptions = options || {};
1049
- var progressCb = createOptions.progressCallback || noOp;
1050
- createOptions.templateDictionary = Object.assign({}, createOptions.templateDictionary);
1051
- progressCb(1); // let the caller know that we've started
1052
- // Assume that source is a group and try to get group's information
1053
- return Promise.all([
1054
- solutionCommon.getGroupBase(sourceId, srcAuthentication),
1055
- solutionCommon.getGroupContents(sourceId, srcAuthentication),
1056
- solutionCommon.getVelocityUrlBase(srcAuthentication, createOptions.templateDictionary)
1057
- ])
1058
- .then(
1059
- // Group fetches worked; assumption was correct
1060
- function (responses) {
1061
- createOptions.itemIds = responses[1];
1062
- progressCb(15);
1063
- return new Promise(function (resolve) {
1064
- // Update the createOptions with values from the group
1065
- resolve(_applySourceToCreateOptions(createOptions, responses[0], srcAuthentication, true));
1066
- });
1067
- },
1068
- // Assumption incorrect; try source as an item
1069
- function () {
1070
- return new Promise(function (resolve, reject) {
1071
- createOptions.itemIds = [sourceId];
1072
- solutionCommon.getItemBase(sourceId, srcAuthentication).then(
1073
- // Update the createOptions with values from the item
1074
- function (itemBase) {
1075
- return resolve(_applySourceToCreateOptions(createOptions, itemBase, srcAuthentication, false));
1076
- }, reject);
1077
- });
1078
- })
1079
- .then(
1080
- // Use a copy of the thumbnail rather than a URL to it
1081
- function (createOptions) {
1082
- return _addThumbnailFileToCreateOptions(createOptions, srcAuthentication);
1083
- })
1084
- .then(
1085
- // Create a solution
1086
- function (createOptions) {
1087
- return _createSolutionFromItemIds(createOptions, srcAuthentication, destAuthentication);
1088
- })
1089
- .then(
1090
- // Successfully created solution
1091
- function (createdSolutionId) {
1092
- progressCb(100); // finished
1093
- return createdSolutionId;
1094
- },
1095
- // Error fetching group, group contents, or item, or error creating solution from ids
1096
- function (error) {
1097
- progressCb(1);
1098
- console.error(error);
1099
- throw error;
1100
- });
1101
- }
1102
- /**
1103
- * Update the createOptions with the group properties
1104
- *
1105
- * @param createOptions
1106
- * @param sourceInfo
1107
- * @param authentication
1108
- * @param isGroup Boolean to indicate if the files are associated with a group or item
1109
- * @internal
1110
- */
1111
- function _applySourceToCreateOptions(createOptions, sourceInfo, srcAuthentication, isGroup) {
1112
- if (isGroup === void 0) { isGroup = false; }
1113
- // Create a solution from the group's or item's contents,
1114
- // using the group's or item's information as defaults for the solution item
1115
- ["title", "snippet", "description", "tags"].forEach(function (prop) {
1116
- var _a;
1117
- createOptions[prop] = (_a = createOptions[prop]) !== null && _a !== void 0 ? _a : sourceInfo[prop];
1118
- });
1119
- if (!createOptions.thumbnailurl && sourceInfo.thumbnail) {
1120
- // Get the full path to the thumbnail
1121
- createOptions.thumbnailurl = solutionCommon.generateSourceThumbnailUrl(srcAuthentication.portal, sourceInfo.id, sourceInfo.thumbnail, isGroup);
1122
- delete sourceInfo.thumbnail;
1123
- }
1124
- return createOptions;
1125
- }
1126
- /**
1127
- * Update the createOptions with the thumbnail file
1128
- *
1129
- * @param createOptions
1130
- * @param srcAuthentication
1131
- * @internal
1132
- */
1133
- function _addThumbnailFileToCreateOptions(createOptions, srcAuthentication) {
1134
- return new Promise(function (resolve) {
1135
- if (!createOptions.thumbnail && createOptions.thumbnailurl) {
1136
- // Figure out the thumbnail's filename
1137
- var filename = solutionCommon.getFilenameFromUrl(createOptions.thumbnailurl) || "thumbnail";
1138
- var thumbnailurl = solutionCommon.appendQueryParam(createOptions.thumbnailurl, "w=400");
1139
- delete createOptions.thumbnailurl;
1140
- // Fetch the thumbnail
1141
- solutionCommon.getBlobAsFile(thumbnailurl, filename, srcAuthentication).then(function (thumbnail) {
1142
- createOptions.thumbnail = thumbnail;
1143
- resolve(createOptions);
1144
- }, function () {
1145
- resolve(createOptions);
1146
- });
1147
- }
1148
- else {
1149
- resolve(createOptions);
1150
- }
1151
- });
1152
- }
1153
- /**
1154
- * Creates a solution item using a list of AGO item ids.
1155
- *
1156
- * @param options Customizations for creating the solution
1157
- * @param srcAuthentication Credentials for requests to source items
1158
- * @param destAuthentication Credentials for the requests to destination solution
1159
- * @return A promise that resolves with the AGO id of the new solution; solution item is deleted if its
1160
- * there is a problem updating it
1161
- * @internal
1162
- */
1163
- function _createSolutionFromItemIds(options, srcAuthentication, destAuthentication) {
1164
- var solutionId = "";
1165
- // Create a solution from the list of items
1166
- return _createSolutionItem(destAuthentication, options)
1167
- .then(function (id) {
1168
- solutionId = id;
1169
- // Add list of items to the new solution
1170
- return addContentToSolution(solutionId, options, srcAuthentication, destAuthentication);
1171
- })
1172
- .catch(function (addError) {
1173
- // If the solution item got created, delete it
1174
- if (solutionId) {
1175
- var failSafeRemove = hubCommon.failSafe(solutionCommon.removeItem, { success: true });
1176
- return failSafeRemove(solutionId, destAuthentication).then(function () {
1177
- throw addError;
1178
- });
1179
- }
1180
- else {
1181
- throw addError;
1182
- }
1183
- });
1184
- }
1185
- /**
1186
- * Creates an empty solution item.
1187
- *
1188
- * @param authentication Credentials for the request
1189
- * @param options Customizations for creating the solution
1190
- * @return A promise that resolves with the AGO id of the new solution; solution item is deleted if its
1191
- * there is a problem updating its thumbnail
1192
- * @internal
1193
- */
1194
- function _createSolutionItem(authentication, options) {
1195
- var model = _createSolutionItemModel(options);
1196
- // Create new solution item
1197
- delete model.item.thumbnailurl;
1198
- model.item.thumbnail = options === null || options === void 0 ? void 0 : options.thumbnail;
1199
- return solutionCommon.createItemWithData(model.item, model.data, authentication, options === null || options === void 0 ? void 0 : options.folderId).then(function (createResponse) {
1200
- return Promise.resolve(createResponse.id);
1201
- });
1202
- }
1203
- /**
1204
- * Create the Solution Item model to be used to create
1205
- * the Solution Item itself
1206
- *
1207
- * @param options
1208
- * @internal
1209
- */
1210
- function _createSolutionItemModel(options) {
1211
- var _a, _b, _c, _d, _e;
1212
- // Solution uses all supplied tags but for deploy.* tags; that information goes into properties
1213
- var creationTags = (_a = options === null || options === void 0 ? void 0 : options.tags) !== null && _a !== void 0 ? _a : [];
1214
- var solutionItem = {
1215
- type: "Solution",
1216
- title: (_b = options === null || options === void 0 ? void 0 : options.title) !== null && _b !== void 0 ? _b : solutionCommon.createShortId(),
1217
- snippet: (_c = options === null || options === void 0 ? void 0 : options.snippet) !== null && _c !== void 0 ? _c : "",
1218
- description: (_d = options === null || options === void 0 ? void 0 : options.description) !== null && _d !== void 0 ? _d : "",
1219
- properties: {
1220
- schemaVersion: solutionCommon.CURRENT_SCHEMA_VERSION
1221
- },
1222
- thumbnailurl: (_e = options === null || options === void 0 ? void 0 : options.thumbnailurl) !== null && _e !== void 0 ? _e : "",
1223
- tags: creationTags.filter(function (tag) { return !tag.startsWith("deploy."); }),
1224
- typeKeywords: ["Solution", "Template"].concat(_getDeploymentProperties(creationTags))
1225
- };
1226
- // ensure that snippet and description are not nefarious
1227
- var sanitizedItem = solutionCommon.sanitizeJSONAndReportChanges(solutionItem);
1228
- var addlKeywords = (options === null || options === void 0 ? void 0 : options.additionalTypeKeywords) || [];
1229
- sanitizedItem.typeKeywords = [].concat(solutionItem.typeKeywords, addlKeywords);
1230
- var solutionData = {
1231
- metadata: {},
1232
- templates: []
1233
- };
1234
- return {
1235
- item: sanitizedItem,
1236
- data: solutionData
1237
- };
1238
- }
1239
- /**
1240
- * Gets the deploy.id and deploy.version tag values.
1241
- *
1242
- * @param tags A list of item tags
1243
- * @return A list containing the two values found in the tags, or defaulting to a new GUID and "1.0", respectively,
1244
- * as needed
1245
- * @internal
1246
- */
1247
- function _getDeploymentProperties(tags) {
1248
- var _a, _b;
1249
- return [
1250
- "solutionid-" +
1251
- ((_a = _getDeploymentProperty("deploy.id.", tags)) !== null && _a !== void 0 ? _a : solutionCommon.createLongId()),
1252
- "solutionversion-" +
1253
- ((_b = _getDeploymentProperty("deploy.version.", tags)) !== null && _b !== void 0 ? _b : "1.0")
1254
- ];
1255
- }
1256
- /**
1257
- * Searches for a tag that has the specified prefix and returns the rest of the tag following that prefix.
1258
- *
1259
- * @param desiredTagPrefix Tag prefix to look for
1260
- * @param tags A list of item tags
1261
- * @return The extracted value of the first matching tag or null if a tag with the specified prefix is not found
1262
- * @internal
1263
- */
1264
- function _getDeploymentProperty(desiredTagPrefix, tags) {
1265
- var foundTagAsList = tags.filter(function (tag) { return tag.startsWith(desiredTagPrefix); });
1266
- if (foundTagAsList.length > 0) {
1267
- return foundTagAsList[0].substr(desiredTagPrefix.length);
1268
- }
1269
- else {
1270
- return null;
1271
- }
1272
- }
573
+ /** @license
574
+ * Copyright 2020 Esri
575
+ *
576
+ * Licensed under the Apache License, Version 2.0 (the "License");
577
+ * you may not use this file except in compliance with the License.
578
+ * You may obtain a copy of the License at
579
+ *
580
+ * http://www.apache.org/licenses/LICENSE-2.0
581
+ *
582
+ * Unless required by applicable law or agreed to in writing, software
583
+ * distributed under the License is distributed on an "AS IS" BASIS,
584
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
585
+ * See the License for the specific language governing permissions and
586
+ * limitations under the License.
587
+ */
588
+ /**
589
+ * Adds a list of AGO item ids to a solution item.
590
+ *
591
+ * @param solutionItemId AGO id of solution to receive items
592
+ * @param options Customizations for creating the solution
593
+ * @param srcAuthentication Credentials for requests to source items
594
+ * @param destAuthentication Credentials for the requests to destination solution
595
+ * @return A promise that resolves with the AGO id of the updated solution
596
+ * @internal
597
+ */
598
+ function addContentToSolution(solutionItemId, options, srcAuthentication, destAuthentication) {
599
+ return new Promise((resolve, reject) => {
600
+ if (!options.itemIds || options.itemIds.length === 0) {
601
+ resolve(solutionItemId);
602
+ return;
603
+ }
604
+ // Prepare feedback mechanism
605
+ let totalEstimatedCost = 2 * options.itemIds.length + 1; // solution items, plus avoid divide by 0
606
+ let percentDone = 16; // allow for previous creation work
607
+ let progressPercentStep = (95 - percentDone) / totalEstimatedCost; // leave some % for caller for wrapup
608
+ const failedItemIds = [];
609
+ let totalExpended = 0;
610
+ let statusOK = true;
611
+ const itemProgressCallback = (itemId, status, costUsed) => {
612
+ // ---------------------------------------------------------------------------------------------------------------
613
+ if (options.itemIds.indexOf(itemId) < 0) {
614
+ // New item--a dependency that wasn't in the supplied list of itemIds; add it to the list
615
+ // and recalculate the progress percent step based on how much progress remains to be done
616
+ options.itemIds.push(itemId);
617
+ totalEstimatedCost += 2;
618
+ progressPercentStep =
619
+ (95 - percentDone) / (totalEstimatedCost - totalExpended);
620
+ }
621
+ totalExpended += costUsed;
622
+ percentDone += progressPercentStep * costUsed;
623
+ if (options.progressCallback) {
624
+ options.progressCallback(Math.round(percentDone), options.jobId);
625
+ }
626
+ /* istanbul ignore if */
627
+ if (options.consoleProgress) {
628
+ console.log(Date.now(), itemId, options.jobId ?? "", solutionCommon.SItemProgressStatus[status], percentDone.toFixed(0) + "%", costUsed);
629
+ }
630
+ if (status === solutionCommon.EItemProgressStatus.Failed) {
631
+ let error = "";
632
+ solutionTemplates.some(t => {
633
+ /* istanbul ignore else */
634
+ if (t.itemId === itemId) {
635
+ /* istanbul ignore else */
636
+ if (hubCommon.getProp(t, "properties.error")) {
637
+ error = t.properties.error;
638
+ try {
639
+ // parse for better console logging if we can
640
+ error = JSON.parse(error);
641
+ }
642
+ catch (e) {
643
+ /* istanbul ignore next */
644
+ // do nothing and show the error as is
645
+ }
646
+ }
647
+ return true;
648
+ }
649
+ });
650
+ solutionCommon.removeTemplate(solutionTemplates, itemId);
651
+ if (failedItemIds.indexOf(itemId) < 0) {
652
+ failedItemIds.push(itemId);
653
+ }
654
+ statusOK = false;
655
+ }
656
+ else if (status === solutionCommon.EItemProgressStatus.Ignored) {
657
+ solutionCommon.removeTemplate(solutionTemplates, itemId);
658
+ }
659
+ return statusOK;
660
+ // ---------------------------------------------------------------------------------------------------------------
661
+ };
662
+ // Replacement dictionary and created templates
663
+ const templateDictionary = options.templateDictionary ?? {};
664
+ let solutionTemplates = [];
665
+ // Handle a list of one or more AGO ids by stepping through the list
666
+ // and calling this function recursively
667
+ const getItemsPromise = [];
668
+ options.itemIds.forEach(itemId => {
669
+ const createDef = createItemTemplate(solutionItemId, itemId, templateDictionary, srcAuthentication, destAuthentication, solutionTemplates, itemProgressCallback);
670
+ getItemsPromise.push(createDef);
671
+ });
672
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
673
+ Promise.all(getItemsPromise).then((multipleResourceItemFiles) => {
674
+ if (failedItemIds.length > 0) {
675
+ reject(solutionCommon.failWithIds(failedItemIds, "One or more items cannot be converted into templates"));
676
+ }
677
+ else {
678
+ if (solutionTemplates.length > 0) {
679
+ // Coalesce the resource file paths from the created templates
680
+ let resourceItemFiles = multipleResourceItemFiles.reduce((accumulator, currentValue) => accumulator.concat(currentValue), []);
681
+ // test for and update group dependencies and other post-processing
682
+ solutionTemplates = _postProcessGroupDependencies(solutionTemplates);
683
+ solutionTemplates = solutionCommon.postProcessWorkforceTemplates(solutionTemplates);
684
+ // Filter out any resources from items that have been removed from the templates, such as
685
+ // Living Atlas layers
686
+ solutionTemplates = _postProcessIgnoredItems(solutionTemplates);
687
+ const templateIds = solutionTemplates.map(template => template.itemId);
688
+ // Coalesce the resource file paths from the created templates
689
+ resourceItemFiles = resourceItemFiles.filter(file => templateIds.includes(file.itemId));
690
+ // Send the accumulated resources to the solution item
691
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
692
+ solutionCommon.copyFilesToStorageItem(resourceItemFiles, solutionItemId, destAuthentication).then(() => {
693
+ _templatizeSolutionIds(solutionTemplates);
694
+ _simplifyUrlsInItemDescriptions(solutionTemplates);
695
+ _replaceDictionaryItemsInObject(templateDictionary, solutionTemplates);
696
+ _templatizeOrgUrl(solutionTemplates, destAuthentication).then(solutionTemplates2 => {
697
+ // Update solution item with its data JSON
698
+ const solutionData = {
699
+ metadata: { version: solutionCommon.SolutionTemplateFormatVersion },
700
+ templates: options.templatizeFields
701
+ ? postProcessFieldReferences(solutionTemplates2)
702
+ : solutionTemplates2
703
+ };
704
+ const itemInfo = {
705
+ id: solutionItemId,
706
+ text: solutionData
707
+ };
708
+ solutionCommon.updateItem(itemInfo, destAuthentication).then(() => {
709
+ resolve(solutionItemId);
710
+ }, reject);
711
+ }, reject);
712
+ });
713
+ }
714
+ else {
715
+ resolve(solutionItemId);
716
+ }
717
+ }
718
+ });
719
+ });
720
+ }
721
+ // ------------------------------------------------------------------------------------------------------------------ //
722
+ /**
723
+ * Gets the dependencies of an item by merging its dependencies list with item references in template variables.
724
+ *
725
+ * @param template Template to examine
726
+ * @return List of dependency ids
727
+ * @private
728
+ */
729
+ function _getDependencies(template) {
730
+ // Get all dependencies
731
+ let deps = template.dependencies.concat(_getIdsOutOfTemplateVariables(_getTemplateVariables(JSON.stringify(template.data))));
732
+ // Remove duplicates and self-references
733
+ deps.sort();
734
+ deps = deps.filter((elem, index, array) => {
735
+ if (elem === template.itemId) {
736
+ return false;
737
+ }
738
+ else if (index > 0) {
739
+ return elem !== array[index - 1];
740
+ }
741
+ else {
742
+ return true;
743
+ }
744
+ });
745
+ return deps;
746
+ }
747
+ /**
748
+ * Extracts AGO ids out of template variables.
749
+ *
750
+ * @param variables List of template variables to examine
751
+ * @return List of AGO ids referenced in `variables`
752
+ * @private
753
+ */
754
+ function _getIdsOutOfTemplateVariables(variables) {
755
+ return variables
756
+ .map(variable => {
757
+ const idList = variable.match(/[0-9A-F]{32}/i); // is it a guid?
758
+ if (idList) {
759
+ return idList[0];
760
+ }
761
+ else {
762
+ return null;
763
+ }
764
+ })
765
+ .filter(variable => !!variable);
766
+ }
767
+ /**
768
+ * Creates a list of item URLs.
769
+ *
770
+ * @param templates Templates to check for URLs
771
+ * @return List of URLs
772
+ * @private
773
+ */
774
+ function _getSolutionItemUrls(templates) {
775
+ const solutionUrls = [];
776
+ templates.forEach(template => {
777
+ /* istanbul ignore else */
778
+ if (template.item.origUrl) {
779
+ solutionUrls.push([template.itemId, template.item.origUrl]);
780
+ }
781
+ });
782
+ return solutionUrls;
783
+ }
784
+ /**
785
+ * Extracts template variables out of a string.
786
+ *
787
+ * @param text String to examine
788
+ * @return List of template variables found in string
789
+ * @private
790
+ */
791
+ function _getTemplateVariables(text) {
792
+ return (text.match(/{{[a-z0-9.]*}}/gi) || []) // find variable
793
+ .map(variable => variable.substring(2, variable.length - 2)); // remove "{{" & "}}"
794
+ }
795
+ /**
796
+ * Update the items dependencies and groups arrays
797
+ *
798
+ * @param templates The array of templates to evaluate
799
+ * @return Updated version of the templates
800
+ * @private
801
+ */
802
+ function _postProcessGroupDependencies(templates) {
803
+ return templates.map((template) => {
804
+ if (template.type === "Group") {
805
+ const id = template.itemId;
806
+ // remove group dependencies if we find a circular dependency with one of its items
807
+ let removeDependencies = false;
808
+ // before we remove update each dependants groups array
809
+ template.dependencies.forEach(dependencyId => {
810
+ const dependantTemplate = solutionCommon.getTemplateById(templates, dependencyId);
811
+ // Not all items shared to the group will exist in the templates array
812
+ // i.e. Hub Initiative items or any other unsupported types
813
+ if (dependantTemplate) {
814
+ // check if the group is in the dependantTemplate's list of dependencies
815
+ const gIndex = hubCommon.getWithDefault(dependantTemplate, "dependencies", []).indexOf(id);
816
+ /* istanbul ignore else */
817
+ if (gIndex > -1) {
818
+ removeDependencies = true;
819
+ }
820
+ // if the dependant template does not have the group id
821
+ // in it's groups array, add it
822
+ const groups = hubCommon.getWithDefault(dependantTemplate, "groups", []);
823
+ if (groups.indexOf(id) === -1) {
824
+ groups.push(id);
825
+ dependantTemplate.groups = groups;
826
+ }
827
+ }
828
+ });
829
+ if (removeDependencies) {
830
+ template.dependencies = [];
831
+ }
832
+ }
833
+ return template;
834
+ });
835
+ }
836
+ /**
837
+ * Check for feature service items that have been flagged for invalid designations.
838
+ * Remove templates that have invalid designations from the solution item and other item dependencies.
839
+ * Clean up any references to items with invalid designations in the other templates.
840
+ *
841
+ * @param templates The array of templates to evaluate
842
+ * @return Updated version of the templates
843
+ * @private
844
+ */
845
+ function _postProcessIgnoredItems(templates) {
846
+ // replace in template
847
+ const updateDictionary = templates.reduce((result, template) => {
848
+ return template.properties.hasInvalidDesignations
849
+ ? Object.assign(result, template.data)
850
+ : result;
851
+ }, {});
852
+ Object.keys(updateDictionary).forEach(k => {
853
+ solutionCommon.removeTemplate(templates, k);
854
+ templates = templates.map(t => {
855
+ t.dependencies = t.dependencies.filter(id => id !== k);
856
+ return solutionCommon.replaceInTemplate(t, updateDictionary);
857
+ });
858
+ });
859
+ return templates;
860
+ }
861
+ /**
862
+ * Recursively runs through an object to find and replace any strings found in a dictionary.
863
+ *
864
+ * @param templateDictionary Hash of things to be replaced
865
+ * @param obj Object to be examined
866
+ * @private
867
+ */
868
+ function _replaceDictionaryItemsInObject(hash, obj) {
869
+ /* istanbul ignore else */
870
+ if (obj) {
871
+ Object.keys(obj).forEach(prop => {
872
+ const propObj = obj[prop];
873
+ if (propObj) {
874
+ if (typeof propObj === "object") {
875
+ _replaceDictionaryItemsInObject(hash, propObj);
876
+ }
877
+ else if (typeof propObj === "string") {
878
+ obj[prop] = hash[propObj] || propObj;
879
+ }
880
+ }
881
+ });
882
+ }
883
+ return obj;
884
+ }
885
+ /**
886
+ * Recursively runs through an object to find and templatize any remaining references to solution's items.
887
+ *
888
+ * @param ids Ids to be replaced in strings found in object
889
+ * @param obj Object to be examined
890
+ * @private
891
+ */
892
+ function _replaceRemainingIdsInObject(ids, obj) {
893
+ /* istanbul ignore else */
894
+ if (obj) {
895
+ Object.keys(obj).forEach(prop => {
896
+ const propObj = obj[prop];
897
+ if (propObj) {
898
+ if (typeof propObj === "object") {
899
+ _replaceRemainingIdsInObject(ids, propObj);
900
+ }
901
+ else if (typeof propObj === "string") {
902
+ obj[prop] = _replaceRemainingIdsInString(ids, propObj);
903
+ }
904
+ }
905
+ });
906
+ }
907
+ return obj;
908
+ }
909
+ /**
910
+ * Templatizes ids from a list in a string if they're not already templatized.
911
+ *
912
+ * @param ids Ids to be replaced in source string
913
+ * @param str Source string to be examined
914
+ * @return A copy of the source string with any templatization changes
915
+ * @private
916
+ */
917
+ function _replaceRemainingIdsInString(ids, str) {
918
+ let updatedStr = str;
919
+ const untemplatizedIds = solutionCommon.getIDs(str);
920
+ if (untemplatizedIds.length > 0) {
921
+ untemplatizedIds.forEach(id => {
922
+ if (ids.includes(id)) {
923
+ const re = new RegExp("({*)" + id, "gi");
924
+ updatedStr = updatedStr.replace(re, match => match.indexOf("{{") < 0
925
+ ? "{{" + id.replace("{", "") + ".itemId}}"
926
+ : match);
927
+ }
928
+ });
929
+ }
930
+ return updatedStr;
931
+ }
932
+ /**
933
+ * Finds and templatizes any URLs in solution items' descriptions.
934
+ *
935
+ * @param templates The array of templates to evaluate, modified in place
936
+ * @private
937
+ */
938
+ function _simplifyUrlsInItemDescriptions(templates) {
939
+ // Get the urls in the solution along with their item ids & convert the id into the form
940
+ // "{{fcb2bf2837a6404ebb418a1f805f976a.url}}"
941
+ const solutionUrls = _getSolutionItemUrls(templates).map(idUrl => [
942
+ "{{" + idUrl[0] + ".url}}",
943
+ idUrl[1]
944
+ ]);
945
+ /* istanbul ignore else */
946
+ if (solutionUrls.length > 0) {
947
+ // Make the replacements
948
+ templates.forEach(template => {
949
+ solutionUrls.forEach(
950
+ // TypeScript for es2015 doesn't have a definition for `replaceAll`
951
+ idUrl => {
952
+ /* istanbul ignore else */
953
+ if (template.item.description) {
954
+ template.item.description = template.item
955
+ .description.replaceAll(idUrl[1], idUrl[0]);
956
+ }
957
+ });
958
+ });
959
+ }
960
+ }
961
+ /**
962
+ * Templatizes occurrences of the URL to the user's organization in the `item` and `data` template sections.
963
+ *
964
+ * @param templates The array of templates to evaluate; templates is modified in place
965
+ * @param destAuthentication Credentials for request organization info
966
+ * @return Promise resolving with `templates`
967
+ * @private
968
+ */
969
+ function _templatizeOrgUrl(templates, destAuthentication) {
970
+ return new Promise((resolve, reject) => {
971
+ // Get the org's URL
972
+ solutionCommon.getPortal(null, destAuthentication).then(org => {
973
+ const orgUrl = "https://" + org.urlKey + "." + org.customBaseUrl;
974
+ const templatizedOrgUrl = "{{portalBaseUrl}}";
975
+ // Cycle through each of the items in the template and scan the `item` and `data` sections of each for replacements
976
+ templates.forEach((template) => {
977
+ solutionCommon.globalStringReplace(template.item, new RegExp(orgUrl, "gi"), templatizedOrgUrl);
978
+ solutionCommon.globalStringReplace(template.data, new RegExp(orgUrl, "gi"), templatizedOrgUrl);
979
+ });
980
+ resolve(templates);
981
+ }, reject);
982
+ });
983
+ }
984
+ /**
985
+ * Finds and templatizes any references to solution's items.
986
+ *
987
+ * @param templates The array of templates to evaluate, modified in place
988
+ * @private
989
+ */
990
+ function _templatizeSolutionIds(templates) {
991
+ // Get the ids in the solution
992
+ const solutionIds = templates.map((template) => template.itemId);
993
+ // Cycle through each of the items in the template and
994
+ // 1. templatize untemplatized ids in our solution in the `item` and `data` sections;
995
+ // 2. update the `dependencies` section
996
+ templates.forEach((template) => {
997
+ _replaceRemainingIdsInObject(solutionIds, template.item);
998
+ _replaceRemainingIdsInObject(solutionIds, template.data);
999
+ /* istanbul ignore else */
1000
+ if (template.type !== "Group" && !solutionCommon.isWorkforceProject(template)) {
1001
+ template.dependencies = _getDependencies(template);
1002
+ }
1003
+ });
1004
+ }
1005
+
1006
+ /** @license
1007
+ * Copyright 2018 Esri
1008
+ *
1009
+ * Licensed under the Apache License, Version 2.0 (the "License");
1010
+ * you may not use this file except in compliance with the License.
1011
+ * You may obtain a copy of the License at
1012
+ *
1013
+ * http://www.apache.org/licenses/LICENSE-2.0
1014
+ *
1015
+ * Unless required by applicable law or agreed to in writing, software
1016
+ * distributed under the License is distributed on an "AS IS" BASIS,
1017
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1018
+ * See the License for the specific language governing permissions and
1019
+ * limitations under the License.
1020
+ */
1021
+ // Simple no-op to clean up progressCallback management
1022
+ const noOp = () => { };
1023
+ /**
1024
+ * Creates a solution item.
1025
+ *
1026
+ * @param sourceId AGO id of group whose contents are to be added to solution or of an item to convert into a solution
1027
+ * @param srcAuthentication Credentials for requests to source items
1028
+ * @param destAuthentication Credentials for the requests to destination solution
1029
+ * @param options Customizations for creating the solution
1030
+ * @return A promise that resolves with the AGO id of the new solution
1031
+ */
1032
+ function createSolution(sourceId, srcAuthentication, destAuthentication, options) {
1033
+ const createOptions = options || {};
1034
+ const progressCb = createOptions.progressCallback || noOp;
1035
+ createOptions.templateDictionary = Object.assign({}, createOptions.templateDictionary);
1036
+ progressCb(1); // let the caller know that we've started
1037
+ // Assume that source is a group and try to get group's information
1038
+ return Promise.all([
1039
+ solutionCommon.getGroupBase(sourceId, srcAuthentication),
1040
+ solutionCommon.getGroupContents(sourceId, srcAuthentication),
1041
+ solutionCommon.getVelocityUrlBase(srcAuthentication, createOptions.templateDictionary)
1042
+ ])
1043
+ .then(
1044
+ // Group fetches worked; assumption was correct
1045
+ responses => {
1046
+ createOptions.itemIds = responses[1];
1047
+ progressCb(15);
1048
+ return new Promise(resolve => {
1049
+ // Update the createOptions with values from the group
1050
+ resolve(_applySourceToCreateOptions(createOptions, responses[0], srcAuthentication, true));
1051
+ });
1052
+ },
1053
+ // Assumption incorrect; try source as an item
1054
+ () => {
1055
+ return new Promise((resolve, reject) => {
1056
+ createOptions.itemIds = [sourceId];
1057
+ solutionCommon.getItemBase(sourceId, srcAuthentication).then(
1058
+ // Update the createOptions with values from the item
1059
+ itemBase => resolve(_applySourceToCreateOptions(createOptions, itemBase, srcAuthentication, false)), reject);
1060
+ });
1061
+ })
1062
+ .then(createOptions => {
1063
+ return new Promise((resolve, reject) => {
1064
+ Promise.all([
1065
+ solutionCommon.getPortal("", srcAuthentication),
1066
+ solutionCommon.getUser(srcAuthentication)
1067
+ ]).then(responses => {
1068
+ // check tracking
1069
+ const [portalResponse, userResponse] = responses;
1070
+ solutionCommon.setLocationTrackingEnabled(portalResponse, userResponse, createOptions.templateDictionary);
1071
+ resolve(createOptions);
1072
+ }, reject);
1073
+ });
1074
+ })
1075
+ .then(
1076
+ // Use a copy of the thumbnail rather than a URL to it
1077
+ createOptions => {
1078
+ return _addThumbnailFileToCreateOptions(createOptions, srcAuthentication);
1079
+ })
1080
+ .then(
1081
+ // Create a solution
1082
+ createOptions => {
1083
+ return _createSolutionFromItemIds(createOptions, srcAuthentication, destAuthentication);
1084
+ })
1085
+ .then(
1086
+ // Successfully created solution
1087
+ createdSolutionId => {
1088
+ progressCb(100); // finished
1089
+ return createdSolutionId;
1090
+ },
1091
+ // Error fetching group, group contents, or item, or error creating solution from ids
1092
+ error => {
1093
+ progressCb(1);
1094
+ console.error(error);
1095
+ throw error;
1096
+ });
1097
+ }
1098
+ /**
1099
+ * Update the createOptions with the group properties
1100
+ *
1101
+ * @param createOptions
1102
+ * @param sourceInfo
1103
+ * @param authentication
1104
+ * @param isGroup Boolean to indicate if the files are associated with a group or item
1105
+ * @internal
1106
+ */
1107
+ function _applySourceToCreateOptions(createOptions, sourceInfo, srcAuthentication, isGroup = false) {
1108
+ // Create a solution from the group's or item's contents,
1109
+ // using the group's or item's information as defaults for the solution item
1110
+ ["title", "snippet", "description", "tags"].forEach(prop => {
1111
+ createOptions[prop] = createOptions[prop] ?? sourceInfo[prop];
1112
+ });
1113
+ if (!createOptions.thumbnailurl && sourceInfo.thumbnail) {
1114
+ // Get the full path to the thumbnail
1115
+ createOptions.thumbnailurl = solutionCommon.generateSourceThumbnailUrl(srcAuthentication.portal, sourceInfo.id, sourceInfo.thumbnail, isGroup);
1116
+ delete sourceInfo.thumbnail;
1117
+ }
1118
+ return createOptions;
1119
+ }
1120
+ /**
1121
+ * Update the createOptions with the thumbnail file
1122
+ *
1123
+ * @param createOptions
1124
+ * @param srcAuthentication
1125
+ * @internal
1126
+ */
1127
+ function _addThumbnailFileToCreateOptions(createOptions, srcAuthentication) {
1128
+ return new Promise(resolve => {
1129
+ if (!createOptions.thumbnail && createOptions.thumbnailurl) {
1130
+ // Figure out the thumbnail's filename
1131
+ const filename = solutionCommon.getFilenameFromUrl(createOptions.thumbnailurl) || "thumbnail";
1132
+ const thumbnailurl = solutionCommon.appendQueryParam(createOptions.thumbnailurl, "w=400");
1133
+ delete createOptions.thumbnailurl;
1134
+ // Fetch the thumbnail
1135
+ solutionCommon.getBlobAsFile(thumbnailurl, filename, srcAuthentication).then(thumbnail => {
1136
+ createOptions.thumbnail = thumbnail;
1137
+ resolve(createOptions);
1138
+ }, () => {
1139
+ resolve(createOptions);
1140
+ });
1141
+ }
1142
+ else {
1143
+ resolve(createOptions);
1144
+ }
1145
+ });
1146
+ }
1147
+ /**
1148
+ * Creates a solution item using a list of AGO item ids.
1149
+ *
1150
+ * @param options Customizations for creating the solution
1151
+ * @param srcAuthentication Credentials for requests to source items
1152
+ * @param destAuthentication Credentials for the requests to destination solution
1153
+ * @return A promise that resolves with the AGO id of the new solution; solution item is deleted if its
1154
+ * there is a problem updating it
1155
+ * @internal
1156
+ */
1157
+ function _createSolutionFromItemIds(options, srcAuthentication, destAuthentication) {
1158
+ let solutionId = "";
1159
+ // Create a solution from the list of items
1160
+ return _createSolutionItem(destAuthentication, options)
1161
+ .then(id => {
1162
+ solutionId = id;
1163
+ // Add list of items to the new solution
1164
+ return addContentToSolution(solutionId, options, srcAuthentication, destAuthentication);
1165
+ })
1166
+ .catch(addError => {
1167
+ // If the solution item got created, delete it
1168
+ if (solutionId) {
1169
+ const failSafeRemove = hubCommon.failSafe(solutionCommon.removeItem, { success: true });
1170
+ return failSafeRemove(solutionId, destAuthentication).then(() => {
1171
+ throw addError;
1172
+ });
1173
+ }
1174
+ else {
1175
+ throw addError;
1176
+ }
1177
+ });
1178
+ }
1179
+ /**
1180
+ * Creates an empty solution item.
1181
+ *
1182
+ * @param authentication Credentials for the request
1183
+ * @param options Customizations for creating the solution
1184
+ * @return A promise that resolves with the AGO id of the new solution; solution item is deleted if its
1185
+ * there is a problem updating its thumbnail
1186
+ * @internal
1187
+ */
1188
+ function _createSolutionItem(authentication, options) {
1189
+ const model = _createSolutionItemModel(options);
1190
+ // Create new solution item
1191
+ delete model.item.thumbnailurl;
1192
+ model.item.thumbnail = options?.thumbnail;
1193
+ return solutionCommon.createItemWithData(model.item, model.data, authentication, options?.folderId).then(createResponse => {
1194
+ return Promise.resolve(createResponse.id);
1195
+ });
1196
+ }
1197
+ /**
1198
+ * Create the Solution Item model to be used to create
1199
+ * the Solution Item itself
1200
+ *
1201
+ * @param options
1202
+ * @internal
1203
+ */
1204
+ function _createSolutionItemModel(options) {
1205
+ // Solution uses all supplied tags but for deploy.* tags; that information goes into properties
1206
+ const creationTags = options?.tags ?? [];
1207
+ const solutionItem = {
1208
+ type: "Solution",
1209
+ title: options?.title ?? solutionCommon.createShortId(),
1210
+ snippet: options?.snippet ?? "",
1211
+ description: options?.description ?? "",
1212
+ properties: {
1213
+ schemaVersion: solutionCommon.CURRENT_SCHEMA_VERSION
1214
+ },
1215
+ thumbnailurl: options?.thumbnailurl ?? "",
1216
+ tags: creationTags.filter((tag) => !tag.startsWith("deploy.")),
1217
+ typeKeywords: ["Solution", "Template"].concat(_getDeploymentProperties(creationTags))
1218
+ };
1219
+ // ensure that snippet and description are not nefarious
1220
+ const sanitizedItem = solutionCommon.sanitizeJSONAndReportChanges(solutionItem);
1221
+ const addlKeywords = options?.additionalTypeKeywords || [];
1222
+ sanitizedItem.typeKeywords = [].concat(solutionItem.typeKeywords, addlKeywords);
1223
+ const solutionData = {
1224
+ metadata: {},
1225
+ templates: []
1226
+ };
1227
+ return {
1228
+ item: sanitizedItem,
1229
+ data: solutionData
1230
+ };
1231
+ }
1232
+ /**
1233
+ * Gets the deploy.id and deploy.version tag values.
1234
+ *
1235
+ * @param tags A list of item tags
1236
+ * @return A list containing the two values found in the tags, or defaulting to a new GUID and "1.0", respectively,
1237
+ * as needed
1238
+ * @internal
1239
+ */
1240
+ function _getDeploymentProperties(tags) {
1241
+ return [
1242
+ "solutionid-" +
1243
+ (_getDeploymentProperty("deploy.id.", tags) ?? solutionCommon.createLongId()),
1244
+ "solutionversion-" +
1245
+ (_getDeploymentProperty("deploy.version.", tags) ?? "1.0")
1246
+ ];
1247
+ }
1248
+ /**
1249
+ * Searches for a tag that has the specified prefix and returns the rest of the tag following that prefix.
1250
+ *
1251
+ * @param desiredTagPrefix Tag prefix to look for
1252
+ * @param tags A list of item tags
1253
+ * @return The extracted value of the first matching tag or null if a tag with the specified prefix is not found
1254
+ * @internal
1255
+ */
1256
+ function _getDeploymentProperty(desiredTagPrefix, tags) {
1257
+ const foundTagAsList = tags.filter(tag => tag.startsWith(desiredTagPrefix));
1258
+ if (foundTagAsList.length > 0) {
1259
+ return foundTagAsList[0].substr(desiredTagPrefix.length);
1260
+ }
1261
+ else {
1262
+ return null;
1263
+ }
1264
+ }
1273
1265
 
1274
- exports.UNSUPPORTED = UNSUPPORTED;
1275
- exports._addLayerIdToDatasourceUrl = _addLayerIdToDatasourceUrl;
1276
- exports._addMapLayerIds = _addMapLayerIds;
1277
- exports._addThumbnailFileToCreateOptions = _addThumbnailFileToCreateOptions;
1278
- exports._applySourceToCreateOptions = _applySourceToCreateOptions;
1279
- exports._createSolutionFromItemIds = _createSolutionFromItemIds;
1280
- exports._createSolutionItem = _createSolutionItem;
1281
- exports._createSolutionItemModel = _createSolutionItemModel;
1282
- exports._getDatasourceInfos = _getDatasourceInfos;
1283
- exports._getDeploymentProperties = _getDeploymentProperties;
1284
- exports._getDeploymentProperty = _getDeploymentProperty;
1285
- exports._getTemplateTypeHash = _getTemplateTypeHash;
1286
- exports._getWebMapFSDependencies = _getWebMapFSDependencies;
1287
- exports._updateWebMapHashInfo = _updateWebMapHashInfo;
1288
- exports.createItemTemplate = createItemTemplate;
1289
- exports.createSolution = createSolution;
1290
- exports.moduleMap = moduleMap;
1291
- exports.postProcessFieldReferences = postProcessFieldReferences;
1266
+ exports.UNSUPPORTED = UNSUPPORTED;
1267
+ exports._addLayerIdToDatasourceUrl = _addLayerIdToDatasourceUrl;
1268
+ exports._addMapLayerIds = _addMapLayerIds;
1269
+ exports._addThumbnailFileToCreateOptions = _addThumbnailFileToCreateOptions;
1270
+ exports._applySourceToCreateOptions = _applySourceToCreateOptions;
1271
+ exports._createSolutionFromItemIds = _createSolutionFromItemIds;
1272
+ exports._createSolutionItem = _createSolutionItem;
1273
+ exports._createSolutionItemModel = _createSolutionItemModel;
1274
+ exports._getDatasourceInfos = _getDatasourceInfos;
1275
+ exports._getDeploymentProperties = _getDeploymentProperties;
1276
+ exports._getDeploymentProperty = _getDeploymentProperty;
1277
+ exports._getTemplateTypeHash = _getTemplateTypeHash;
1278
+ exports._getWebMapFSDependencies = _getWebMapFSDependencies;
1279
+ exports._updateWebMapHashInfo = _updateWebMapHashInfo;
1280
+ exports.createItemTemplate = createItemTemplate;
1281
+ exports.createSolution = createSolution;
1282
+ exports.moduleMap = moduleMap;
1283
+ exports.postProcessFieldReferences = postProcessFieldReferences;
1292
1284
 
1293
- Object.defineProperty(exports, '__esModule', { value: true });
1285
+ Object.defineProperty(exports, '__esModule', { value: true });
1294
1286
 
1295
- })));
1287
+ }));
1296
1288
  //# sourceMappingURL=creator.umd.js.map