@esri/solution-deployer 3.0.0 → 3.1.0

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