@esri/solution-deployer 0.23.1 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/deploySolutionFromTemplate.js +77 -74
- package/dist/esm/deploySolutionFromTemplate.js.map +1 -1
- package/dist/esm/deploySolutionItems.d.ts +25 -1
- package/dist/esm/deploySolutionItems.js +239 -151
- package/dist/esm/deploySolutionItems.js.map +1 -1
- package/dist/esm/deployer.js +16 -17
- package/dist/esm/deployer.js.map +1 -1
- package/dist/esm/deployerUtils.js +17 -22
- package/dist/esm/deployerUtils.js.map +1 -1
- package/dist/esm/helpers/post-process.js +13 -18
- package/dist/esm/helpers/post-process.js.map +1 -1
- package/dist/esm/helpers/share-templates-to-groups.js +29 -6
- package/dist/esm/helpers/share-templates-to-groups.js.map +1 -1
- package/dist/esm/helpers/sortTemplates.js +2 -4
- package/dist/esm/helpers/sortTemplates.js.map +1 -1
- package/dist/esm/module-map.js +7 -6
- package/dist/esm/module-map.js.map +1 -1
- package/dist/node/deploySolutionFromTemplate.js +83 -80
- package/dist/node/deploySolutionFromTemplate.js.map +1 -1
- package/dist/node/deploySolutionItems.d.ts +25 -1
- package/dist/node/deploySolutionItems.js +244 -154
- package/dist/node/deploySolutionItems.js.map +1 -1
- package/dist/node/deployer.js +23 -24
- package/dist/node/deployer.js.map +1 -1
- package/dist/node/deployerUtils.js +18 -23
- package/dist/node/deployerUtils.js.map +1 -1
- package/dist/node/helpers/post-process.js +18 -23
- package/dist/node/helpers/post-process.js.map +1 -1
- package/dist/node/helpers/share-templates-to-groups.js +30 -7
- package/dist/node/helpers/share-templates-to-groups.js.map +1 -1
- package/dist/node/helpers/sortTemplates.js +2 -4
- package/dist/node/helpers/sortTemplates.js.map +1 -1
- package/dist/node/index.js +5 -5
- package/dist/node/index.js.map +1 -1
- package/dist/node/module-map.js +13 -12
- package/dist/node/module-map.js.map +1 -1
- package/dist/umd/deploySolutionItems.d.ts +25 -1
- package/dist/umd/deployer.umd.js +1622 -1550
- package/dist/umd/deployer.umd.js.map +1 -1
- package/dist/umd/deployer.umd.min.js +3 -3
- package/dist/umd/deployer.umd.min.js.map +1 -1
- package/package.json +31 -30
|
@@ -15,15 +15,15 @@
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports._getGroupUpdates = exports._estimateDeploymentCost = exports._createItemFromTemplateWhenReady = exports._findExistingItem = exports._findExistingItemByKeyword = exports._updateTemplateDictionaryById = exports._handleExistingItems = exports._updateTemplateDictionaryForError = exports._updateTemplateDictionary = exports._useExistingItems = exports._reuseDeployedItems = exports._getViews = exports._getViewHash = exports._updateViewTemplates = exports._evaluateSharedViewSources = exports._flagPatchItemsForPostProcessing = exports.deploySolutionItems = void 0;
|
|
18
|
+
exports._getGroupUpdates = exports._estimateDeploymentCost = exports._createItemFromTemplateWhenReady = exports._findExistingItem = exports._findExistingItemByKeyword = exports._updateTemplateDictionaryById = exports._handleExistingItems = exports._updateTemplateDictionaryForError = exports._setFields = exports._updateTemplateDictionary = exports._setTypekeywordForExisting = exports._useExistingItems = exports._reuseDeployedItems = exports._getViews = exports._getViewHash = exports._updateViewTemplates = exports._evaluateSharedViewSources = exports._flagPatchItemsForPostProcessing = exports.deploySolutionItems = void 0;
|
|
19
19
|
/**
|
|
20
20
|
* Manages deployment of items via the REST API.
|
|
21
21
|
*
|
|
22
22
|
* @module deployItems
|
|
23
23
|
*/
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
const common = require("@esri/solution-common");
|
|
25
|
+
const module_map_1 = require("./module-map");
|
|
26
|
+
const UNSUPPORTED = null;
|
|
27
27
|
// ------------------------------------------------------------------------------------------------------------------ //
|
|
28
28
|
/**
|
|
29
29
|
* Deploys a set of items defined by templates.
|
|
@@ -33,33 +33,32 @@ var UNSUPPORTED = null;
|
|
|
33
33
|
* @param templates A collection of AGO item templates
|
|
34
34
|
* @param storageAuthentication Credentials for the organization with the source items
|
|
35
35
|
* @param templateDictionary Hash of facts: org URL, adlib replacements
|
|
36
|
+
* @param deployedSolutionId Id of deployed Solution item
|
|
36
37
|
* @param destinationAuthentication Credentials for the destination organization
|
|
37
38
|
* @param options Options to tune deployment
|
|
38
39
|
* @return A promise that will resolve with the list of information about the created items
|
|
39
40
|
*/
|
|
40
|
-
function deploySolutionItems(portalSharingUrl, storageItemId, templates, storageAuthentication, templateDictionary, destinationAuthentication, options) {
|
|
41
|
-
return new Promise(
|
|
42
|
-
var _a;
|
|
41
|
+
function deploySolutionItems(portalSharingUrl, storageItemId, templates, storageAuthentication, templateDictionary, deployedSolutionId, destinationAuthentication, options) {
|
|
42
|
+
return new Promise((resolve, reject) => {
|
|
43
43
|
// Prepare feedback mechanism
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
const totalEstimatedCost = _estimateDeploymentCost(templates) + 1; // solution items, plus avoid divide by 0
|
|
45
|
+
let percentDone = 10; // allow for previous deployment work
|
|
46
|
+
const progressPercentStep = (99 - percentDone) / totalEstimatedCost; // leave some % for caller for wrapup
|
|
47
|
+
const failedTemplateItemIds = [];
|
|
48
|
+
const deployedItemIds = [];
|
|
49
|
+
let statusOK = true;
|
|
50
50
|
// TODO: move to separate fn
|
|
51
|
-
|
|
52
|
-
) {
|
|
53
|
-
var _a;
|
|
51
|
+
const itemProgressCallback = (itemId, status, costUsed, createdItemId // supplied when status is EItemProgressStatus.Created or .Finished
|
|
52
|
+
) => {
|
|
54
53
|
percentDone += progressPercentStep * costUsed;
|
|
55
54
|
/* istanbul ignore else */
|
|
56
55
|
if (options.progressCallback) {
|
|
57
56
|
if (status === common.EItemProgressStatus.Finished) {
|
|
58
|
-
|
|
57
|
+
const event = {
|
|
59
58
|
event: common.SItemProgressStatus[status],
|
|
60
59
|
data: itemId
|
|
61
60
|
};
|
|
62
|
-
options.progressCallback(Math.round(percentDone), options.jobId,
|
|
61
|
+
options.progressCallback(Math.round(percentDone), options.jobId, event);
|
|
63
62
|
}
|
|
64
63
|
else {
|
|
65
64
|
options.progressCallback(Math.round(percentDone), options.jobId);
|
|
@@ -67,7 +66,7 @@ function deploySolutionItems(portalSharingUrl, storageItemId, templates, storage
|
|
|
67
66
|
}
|
|
68
67
|
/* istanbul ignore if */
|
|
69
68
|
if (options.consoleProgress) {
|
|
70
|
-
console.log(Date.now(), itemId,
|
|
69
|
+
console.log(Date.now(), itemId, options.jobId ?? "", common.SItemProgressStatus[status], percentDone.toFixed(0) + "%", costUsed, createdItemId ? "==> " + createdItemId : "");
|
|
71
70
|
}
|
|
72
71
|
if (status === common.EItemProgressStatus.Created) {
|
|
73
72
|
deployedItemIds.push(createdItemId);
|
|
@@ -87,27 +86,27 @@ function deploySolutionItems(portalSharingUrl, storageItemId, templates, storage
|
|
|
87
86
|
// Create an ordered graph of the templates so that dependencies are created before the items that need them.
|
|
88
87
|
// Because cycles are permitted, we also keep track of items that need to be patched later because their
|
|
89
88
|
// dependencies are necessarily created after they are created.
|
|
90
|
-
|
|
89
|
+
const { buildOrder, itemsToBePatched } = common.topologicallySortItems(templates);
|
|
91
90
|
// For each item in order from no dependencies to dependent on other items,
|
|
92
91
|
// * replace template symbols using template dictionary
|
|
93
92
|
// * create item in destination group
|
|
94
93
|
// * add created item's id into the template dictionary
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
const awaitAllItems = [];
|
|
95
|
+
const reuseItemsDef = _reuseDeployedItems(templates, options.enableItemReuse ?? false, templateDictionary, destinationAuthentication);
|
|
97
96
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
98
|
-
reuseItemsDef.then(
|
|
99
|
-
|
|
97
|
+
reuseItemsDef.then(() => {
|
|
98
|
+
const useExistingItemsDef = _useExistingItems(templates, common.getProp(templateDictionary, "params.useExisting"), templateDictionary, destinationAuthentication);
|
|
100
99
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
101
|
-
useExistingItemsDef.then(
|
|
100
|
+
useExistingItemsDef.then(() => {
|
|
102
101
|
templates = common.setNamesAndTitles(templates, templateDictionary.solutionItemId);
|
|
103
|
-
buildOrder.forEach(
|
|
102
|
+
buildOrder.forEach((id) => {
|
|
104
103
|
// Get the item's template out of the list of templates
|
|
105
|
-
|
|
104
|
+
const template = common.findTemplateInList(templates, id);
|
|
106
105
|
awaitAllItems.push(_createItemFromTemplateWhenReady(template, common.generateStorageFilePaths(portalSharingUrl, storageItemId, template.resources, options.storageVersion), storageAuthentication, templateDictionary, destinationAuthentication, itemProgressCallback));
|
|
107
106
|
});
|
|
108
107
|
// Wait until all items have been created
|
|
109
108
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
110
|
-
Promise.all(awaitAllItems).then(
|
|
109
|
+
Promise.all(awaitAllItems).then((clonedSolutionItems) => {
|
|
111
110
|
if (failedTemplateItemIds.length === 0) {
|
|
112
111
|
// Do we have any items to be patched (i.e., they refer to dependencies using the template id rather
|
|
113
112
|
// than the cloned id because the item had to be created before the dependency)? Flag these items
|
|
@@ -117,16 +116,17 @@ function deploySolutionItems(portalSharingUrl, storageItemId, templates, storage
|
|
|
117
116
|
}
|
|
118
117
|
else {
|
|
119
118
|
// Delete created items
|
|
119
|
+
const progressOptions = {
|
|
120
|
+
consoleProgress: true
|
|
121
|
+
};
|
|
120
122
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
121
123
|
common
|
|
122
|
-
.
|
|
123
|
-
.then(
|
|
124
|
-
return reject(common.failWithIds(failedTemplateItemIds));
|
|
125
|
-
});
|
|
124
|
+
.deleteSolutionByComponents(deployedSolutionId, deployedItemIds, templates, templateDictionary, destinationAuthentication, progressOptions)
|
|
125
|
+
.then(() => reject(common.failWithIds(failedTemplateItemIds)));
|
|
126
126
|
}
|
|
127
127
|
});
|
|
128
128
|
});
|
|
129
|
-
},
|
|
129
|
+
}, e => {
|
|
130
130
|
console.error(e);
|
|
131
131
|
reject(common.fail(e));
|
|
132
132
|
});
|
|
@@ -141,13 +141,13 @@ exports.deploySolutionItems = deploySolutionItems;
|
|
|
141
141
|
* @param templates A collection of AGO item templates
|
|
142
142
|
*/
|
|
143
143
|
function _flagPatchItemsForPostProcessing(itemsToBePatched, templateDictionary, templates) {
|
|
144
|
-
|
|
144
|
+
let itemIdsToBePatched = Object.keys(itemsToBePatched);
|
|
145
145
|
/* istanbul ignore else */
|
|
146
146
|
if (itemIdsToBePatched.length > 0) {
|
|
147
147
|
// Replace the ids of the items to be patched (which are template ids) with their cloned versions
|
|
148
|
-
itemIdsToBePatched = itemIdsToBePatched.map(
|
|
148
|
+
itemIdsToBePatched = itemIdsToBePatched.map(id => templateDictionary[id].itemId);
|
|
149
149
|
// Make sure that the items to be patched are flagged for post processing
|
|
150
|
-
templates.forEach(
|
|
150
|
+
templates.forEach(item => {
|
|
151
151
|
/* istanbul ignore else */
|
|
152
152
|
if (itemIdsToBePatched.includes(item.id)) {
|
|
153
153
|
item.postProcess = true;
|
|
@@ -169,16 +169,16 @@ exports._flagPatchItemsForPostProcessing = _flagPatchItemsForPostProcessing;
|
|
|
169
169
|
function _evaluateSharedViewSources(templates) {
|
|
170
170
|
// update the templates so we can defer the deployment when more than one view shares the same source
|
|
171
171
|
// these are not classic dependencies but are in some ways similar
|
|
172
|
-
|
|
172
|
+
const views = _getViews(templates);
|
|
173
173
|
_updateViewTemplates(templates, views);
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
Object.keys(viewHash).forEach(
|
|
178
|
-
|
|
179
|
-
_views.forEach(
|
|
180
|
-
|
|
181
|
-
|
|
174
|
+
const viewHash = _getViewHash(views);
|
|
175
|
+
let processed = [];
|
|
176
|
+
const visited = [];
|
|
177
|
+
Object.keys(viewHash).forEach(k => {
|
|
178
|
+
const _views = viewHash[k];
|
|
179
|
+
_views.forEach(cv => {
|
|
180
|
+
const template = common.findTemplateInList(templates, cv);
|
|
181
|
+
const syncViews = common.getProp(template, "properties.syncViews");
|
|
182
182
|
/* istanbul ignore else */
|
|
183
183
|
if (visited.indexOf(template.itemId) > -1) {
|
|
184
184
|
processed = processed.concat(syncViews);
|
|
@@ -214,9 +214,9 @@ exports._evaluateSharedViewSources = _evaluateSharedViewSources;
|
|
|
214
214
|
*
|
|
215
215
|
*/
|
|
216
216
|
function _updateViewTemplates(templates, views) {
|
|
217
|
-
views.forEach(
|
|
218
|
-
v.dependencies.forEach(
|
|
219
|
-
templates = templates.map(
|
|
217
|
+
views.forEach(v => {
|
|
218
|
+
v.dependencies.forEach((id) => {
|
|
219
|
+
templates = templates.map(t => {
|
|
220
220
|
/* istanbul ignore else */
|
|
221
221
|
if (common.getProp(t, "properties.service.isView") &&
|
|
222
222
|
t.dependencies.indexOf(id) > -1 &&
|
|
@@ -248,9 +248,9 @@ exports._updateViewTemplates = _updateViewTemplates;
|
|
|
248
248
|
* @protected
|
|
249
249
|
*/
|
|
250
250
|
function _getViewHash(views) {
|
|
251
|
-
|
|
252
|
-
views.forEach(
|
|
253
|
-
v.dependencies.forEach(
|
|
251
|
+
const viewHash = {};
|
|
252
|
+
views.forEach(v => {
|
|
253
|
+
v.dependencies.forEach((d) => {
|
|
254
254
|
/* istanbul ignore else */
|
|
255
255
|
if (Object.keys(viewHash).indexOf(d) < 0) {
|
|
256
256
|
viewHash[d] = [v.id];
|
|
@@ -273,7 +273,7 @@ exports._getViewHash = _getViewHash;
|
|
|
273
273
|
* @protected
|
|
274
274
|
*/
|
|
275
275
|
function _getViews(templates) {
|
|
276
|
-
return templates.reduce(
|
|
276
|
+
return templates.reduce((acc, v) => {
|
|
277
277
|
/* istanbul ignore else */
|
|
278
278
|
if (common.getProp(v, "properties.service.isView")) {
|
|
279
279
|
acc.push({
|
|
@@ -298,17 +298,17 @@ exports._getViews = _getViews;
|
|
|
298
298
|
* @protected
|
|
299
299
|
*/
|
|
300
300
|
function _reuseDeployedItems(templates, reuseItems, templateDictionary, authentication) {
|
|
301
|
-
return new Promise(
|
|
301
|
+
return new Promise((resolve, reject) => {
|
|
302
302
|
if (reuseItems) {
|
|
303
|
-
|
|
304
|
-
Promise.all(existingItemsByKeyword).then(
|
|
305
|
-
|
|
306
|
-
Promise.all(existingItemsByTag).then(
|
|
303
|
+
const existingItemsByKeyword = _findExistingItemByKeyword(templates, templateDictionary, authentication);
|
|
304
|
+
Promise.all(existingItemsByKeyword).then((existingItemsByKeywordResponse) => {
|
|
305
|
+
const existingItemsByTag = _handleExistingItems(existingItemsByKeywordResponse, templateDictionary, authentication, true);
|
|
306
|
+
Promise.all(existingItemsByTag).then(existingItemsByTagResponse => {
|
|
307
307
|
_handleExistingItems(existingItemsByTagResponse, templateDictionary, authentication, false);
|
|
308
308
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
309
309
|
_updateTemplateDictionary(templates, templateDictionary, authentication).then(resolve);
|
|
310
|
-
},
|
|
311
|
-
},
|
|
310
|
+
}, e => reject(common.fail(e)));
|
|
311
|
+
}, e => reject(common.fail(e)));
|
|
312
312
|
}
|
|
313
313
|
else {
|
|
314
314
|
resolve(null);
|
|
@@ -337,22 +337,31 @@ exports._reuseDeployedItems = _reuseDeployedItems;
|
|
|
337
337
|
* @protected
|
|
338
338
|
*/
|
|
339
339
|
function _useExistingItems(templates, useExisting, templateDictionary, authentication) {
|
|
340
|
-
return new Promise(
|
|
340
|
+
return new Promise(resolve => {
|
|
341
341
|
if (useExisting) {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
342
|
+
const itemDefs = [];
|
|
343
|
+
const sourceIdHash = {};
|
|
344
|
+
const itemIds = [];
|
|
345
|
+
Object.keys(templateDictionary.params).forEach(k => {
|
|
346
|
+
const v = templateDictionary.params[k];
|
|
345
347
|
/* istanbul ignore else */
|
|
346
|
-
if (v.itemId &&
|
|
347
|
-
_updateTemplateDictionaryById(templateDictionary,
|
|
348
|
+
if (v.itemId && /[0-9A-F]{32}/i.test(k)) {
|
|
349
|
+
_updateTemplateDictionaryById(templateDictionary, k, v.itemId, v);
|
|
350
|
+
// need to check and set the typeKeyword if it doesn't exist on this service yet
|
|
351
|
+
// when the user has passed in an itemId that does not come from a previous deployment
|
|
352
|
+
itemDefs.push(common.getItemBase(v.itemId, authentication));
|
|
353
|
+
sourceIdHash[v.itemId] = k;
|
|
348
354
|
/* istanbul ignore else */
|
|
349
|
-
if (
|
|
350
|
-
|
|
355
|
+
if (itemIds.indexOf(k) < 0) {
|
|
356
|
+
itemIds.push(k);
|
|
351
357
|
}
|
|
352
358
|
}
|
|
353
359
|
});
|
|
354
360
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
355
|
-
|
|
361
|
+
_setTypekeywordForExisting(itemDefs, sourceIdHash, authentication).then(() => {
|
|
362
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
363
|
+
_updateTemplateDictionary(itemIds.map(id => common.getTemplateById(templates, id)), templateDictionary, authentication).then(resolve);
|
|
364
|
+
});
|
|
356
365
|
}
|
|
357
366
|
else {
|
|
358
367
|
resolve(null);
|
|
@@ -360,6 +369,51 @@ function _useExistingItems(templates, useExisting, templateDictionary, authentic
|
|
|
360
369
|
});
|
|
361
370
|
}
|
|
362
371
|
exports._useExistingItems = _useExistingItems;
|
|
372
|
+
/**
|
|
373
|
+
* Verify if the existing item has the source-<itemId> typeKeyword and set it if not
|
|
374
|
+
* This allows items that did not come from deployment to be found for reuse after they
|
|
375
|
+
* have been used once via a custom itemId param
|
|
376
|
+
*
|
|
377
|
+
* @param itemDefs
|
|
378
|
+
* @param sourceIdHash key value pairs..actual itemId is the key and the source itemId is the value
|
|
379
|
+
* @param authentication credentials for the requests
|
|
380
|
+
*
|
|
381
|
+
* @return a promise to indicate when the requests are complete
|
|
382
|
+
*/
|
|
383
|
+
function _setTypekeywordForExisting(itemDefs, sourceIdHash, authentication) {
|
|
384
|
+
return new Promise(resolve => {
|
|
385
|
+
if (itemDefs.length > 0) {
|
|
386
|
+
Promise.all(itemDefs).then(results => {
|
|
387
|
+
const itemUpdateDefs = [];
|
|
388
|
+
results.forEach(result => {
|
|
389
|
+
const sourceId = sourceIdHash[result.id];
|
|
390
|
+
/* istanbul ignore else */
|
|
391
|
+
if (result && sourceId && result.typeKeywords) {
|
|
392
|
+
const sourceKeyword = `source-${sourceId}`;
|
|
393
|
+
const typeKeywords = result.typeKeywords;
|
|
394
|
+
/* istanbul ignore else */
|
|
395
|
+
if (typeKeywords.indexOf(sourceKeyword) < 0) {
|
|
396
|
+
typeKeywords.push(sourceKeyword);
|
|
397
|
+
const itemUpdate = { id: result.id, typeKeywords };
|
|
398
|
+
itemUpdateDefs.push(common.updateItem(itemUpdate, authentication));
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
// wait for updates to finish before we resolve
|
|
403
|
+
if (itemUpdateDefs.length > 0) {
|
|
404
|
+
Promise.all(itemUpdateDefs).then(resolve, () => resolve(undefined));
|
|
405
|
+
}
|
|
406
|
+
else {
|
|
407
|
+
resolve(undefined);
|
|
408
|
+
}
|
|
409
|
+
}, () => resolve(undefined));
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
resolve(undefined);
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
exports._setTypekeywordForExisting = _setTypekeywordForExisting;
|
|
363
417
|
/**
|
|
364
418
|
* Update the templateDictionary with key details by item type
|
|
365
419
|
*
|
|
@@ -369,18 +423,19 @@ exports._useExistingItems = _useExistingItems;
|
|
|
369
423
|
* @protected
|
|
370
424
|
*/
|
|
371
425
|
function _updateTemplateDictionary(templates, templateDictionary, authentication) {
|
|
372
|
-
return new Promise(
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
templates.forEach(
|
|
378
|
-
|
|
426
|
+
return new Promise(resolve => {
|
|
427
|
+
const defs = [];
|
|
428
|
+
const urls = [];
|
|
429
|
+
const types = [];
|
|
430
|
+
const ids = [];
|
|
431
|
+
templates.forEach(t => {
|
|
432
|
+
const templateInfo = templateDictionary[t.itemId];
|
|
379
433
|
/* istanbul ignore else */
|
|
380
434
|
if (templateInfo && templateInfo.url && templateInfo.itemId) {
|
|
381
435
|
/* istanbul ignore else */
|
|
382
436
|
if (t.item.type === "Feature Service") {
|
|
383
|
-
|
|
437
|
+
const enterpriseIDMapping = common.getProp(templateDictionary, `params.${t.itemId}.enterpriseIDMapping`);
|
|
438
|
+
Object.assign(templateDictionary[t.itemId], common.getLayerSettings(common.getLayersAndTables(t), templateInfo.url, templateInfo.itemId, enterpriseIDMapping));
|
|
384
439
|
// if the service has veiws keep track of the fields so we can use them to
|
|
385
440
|
// compare with the view fields
|
|
386
441
|
/* istanbul ignore else */
|
|
@@ -395,7 +450,7 @@ function _updateTemplateDictionary(templates, templateDictionary, authentication
|
|
|
395
450
|
/* istanbul ignore else */
|
|
396
451
|
if (urls.indexOf(templateInfo.url) < 0) {
|
|
397
452
|
defs.push(t.item.type === "Feature Service"
|
|
398
|
-
? common.rest_request(templateInfo.url, { authentication
|
|
453
|
+
? common.rest_request(templateInfo.url, { authentication })
|
|
399
454
|
: common.getItemBase(templateInfo.itemId, authentication));
|
|
400
455
|
urls.push(templateInfo.url);
|
|
401
456
|
types.push(t.item.type);
|
|
@@ -405,23 +460,23 @@ function _updateTemplateDictionary(templates, templateDictionary, authentication
|
|
|
405
460
|
});
|
|
406
461
|
if (defs.length > 0) {
|
|
407
462
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
408
|
-
Promise.all(defs.map(
|
|
463
|
+
Promise.all(defs.map(p => p.catch(e => e))).then(results => {
|
|
409
464
|
/* istanbul ignore else */
|
|
410
465
|
if (Array.isArray(results) && results.length > 0) {
|
|
411
|
-
|
|
412
|
-
results.forEach(
|
|
466
|
+
const fieldDefs = [];
|
|
467
|
+
results.forEach((r, i) => {
|
|
413
468
|
// a feature service result will contain a serviceItemId if it was successfully fetched
|
|
414
469
|
if (r.serviceItemId && types[i] === "Feature Service") {
|
|
415
|
-
Object.keys(templateDictionary).forEach(
|
|
416
|
-
|
|
470
|
+
Object.keys(templateDictionary).forEach(k => {
|
|
471
|
+
const v = templateDictionary[k];
|
|
417
472
|
/* istanbul ignore else */
|
|
418
473
|
if (v.itemId && v.itemId === r.serviceItemId) {
|
|
419
474
|
common.setDefaultSpatialReference(templateDictionary, k, r.spatialReference);
|
|
420
475
|
// keep the extent values from these responses as well
|
|
421
|
-
common.setCreateProp(templateDictionary, k
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
476
|
+
common.setCreateProp(templateDictionary, `${k}.defaultExtent`, r.fullExtent || r.initialExtent);
|
|
477
|
+
const layerIds = (r.layers || []).map((l) => l.id);
|
|
478
|
+
const tablesIds = (r.tables || []).map((t) => t.id);
|
|
479
|
+
fieldDefs.push(common.getExistingLayersAndTables(urls[i], layerIds.concat(tablesIds), authentication));
|
|
425
480
|
}
|
|
426
481
|
});
|
|
427
482
|
}
|
|
@@ -434,18 +489,33 @@ function _updateTemplateDictionary(templates, templateDictionary, authentication
|
|
|
434
489
|
}
|
|
435
490
|
}
|
|
436
491
|
});
|
|
437
|
-
if (
|
|
492
|
+
if (fieldDefs.length > 0) {
|
|
438
493
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
439
|
-
Promise.all(
|
|
440
|
-
layerTableResult.forEach(
|
|
441
|
-
l.forEach(
|
|
442
|
-
Object.keys(templateDictionary).forEach(
|
|
494
|
+
Promise.all(fieldDefs).then(layerTableResult => {
|
|
495
|
+
layerTableResult.forEach(l => {
|
|
496
|
+
l.forEach((ll) => {
|
|
497
|
+
Object.keys(templateDictionary).forEach(k => {
|
|
443
498
|
/* istanbul ignore else */
|
|
444
499
|
if (templateDictionary[k].itemId === ll.serviceItemId) {
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
500
|
+
let sourceId = "";
|
|
501
|
+
Object.keys(templateDictionary).some(_k => {
|
|
502
|
+
/* istanbul ignore else */
|
|
503
|
+
if (templateDictionary[_k].itemId === ll.serviceItemId) {
|
|
504
|
+
sourceId = _k;
|
|
505
|
+
return true;
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
const enterpriseIDMapping = common.getProp(templateDictionary, `params.${sourceId}.enterpriseIDMapping`);
|
|
509
|
+
if (enterpriseIDMapping) {
|
|
510
|
+
Object.keys(enterpriseIDMapping).forEach(id => {
|
|
511
|
+
if (enterpriseIDMapping[id].toString() ===
|
|
512
|
+
ll.id.toString()) {
|
|
513
|
+
_setFields(templateDictionary, k, id, ll.fields);
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
else {
|
|
518
|
+
_setFields(templateDictionary, k, ll.id, ll.fields);
|
|
449
519
|
}
|
|
450
520
|
}
|
|
451
521
|
});
|
|
@@ -469,6 +539,24 @@ function _updateTemplateDictionary(templates, templateDictionary, authentication
|
|
|
469
539
|
});
|
|
470
540
|
}
|
|
471
541
|
exports._updateTemplateDictionary = _updateTemplateDictionary;
|
|
542
|
+
/**
|
|
543
|
+
* Add the fields from the source layer to the template dictionary for any required replacements
|
|
544
|
+
*
|
|
545
|
+
* @param templateDictionary Hash of facts: org URL, adlib replacements, deferreds for dependencies
|
|
546
|
+
* @param itemId the id for the item
|
|
547
|
+
* @param layerId the id for the layer
|
|
548
|
+
* @param fields the fields to transfer
|
|
549
|
+
*
|
|
550
|
+
* @protected
|
|
551
|
+
*/
|
|
552
|
+
function _setFields(templateDictionary, itemId, layerId, fields) {
|
|
553
|
+
const layerInfo = common.getProp(templateDictionary, `${itemId}.layer${layerId}`);
|
|
554
|
+
/* istanbul ignore else */
|
|
555
|
+
if (layerInfo && fields) {
|
|
556
|
+
layerInfo.fields = fields;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
exports._setFields = _setFields;
|
|
472
560
|
/**
|
|
473
561
|
* In some cases an item id search will return a stale item reference
|
|
474
562
|
* it will subsequently fail when we try to fetch the underlying service.
|
|
@@ -484,17 +572,17 @@ exports._updateTemplateDictionary = _updateTemplateDictionary;
|
|
|
484
572
|
function _updateTemplateDictionaryForError(templateDictionary, itemId) {
|
|
485
573
|
/* istanbul ignore else */
|
|
486
574
|
if (itemId) {
|
|
487
|
-
|
|
488
|
-
Object.keys(templateDictionary).some(
|
|
575
|
+
let removeKey = "";
|
|
576
|
+
Object.keys(templateDictionary).some(k => {
|
|
489
577
|
/* istanbul ignore else */
|
|
490
578
|
if (templateDictionary[k].itemId === itemId) {
|
|
491
|
-
|
|
579
|
+
removeKey = k;
|
|
492
580
|
return true;
|
|
493
581
|
}
|
|
494
582
|
});
|
|
495
583
|
/* istanbul ignore else */
|
|
496
|
-
if (
|
|
497
|
-
delete templateDictionary[
|
|
584
|
+
if (removeKey !== "") {
|
|
585
|
+
delete templateDictionary[removeKey];
|
|
498
586
|
}
|
|
499
587
|
}
|
|
500
588
|
return templateDictionary;
|
|
@@ -512,30 +600,28 @@ exports._updateTemplateDictionaryForError = _updateTemplateDictionaryForError;
|
|
|
512
600
|
*/
|
|
513
601
|
function _handleExistingItems(existingItemsResponse, templateDictionary, authentication, addTagQuery) {
|
|
514
602
|
// if items are not found by type keyword search by tag
|
|
515
|
-
|
|
603
|
+
const existingItemsByTag = [Promise.resolve(null)];
|
|
516
604
|
/* istanbul ignore else */
|
|
517
605
|
if (existingItemsResponse && Array.isArray(existingItemsResponse)) {
|
|
518
|
-
existingItemsResponse.forEach(
|
|
606
|
+
existingItemsResponse.forEach(existingItem => {
|
|
519
607
|
/* istanbul ignore else */
|
|
520
|
-
if (Array.isArray(existingItem
|
|
521
|
-
|
|
522
|
-
|
|
608
|
+
if (Array.isArray(existingItem?.results)) {
|
|
609
|
+
let result;
|
|
610
|
+
const results = existingItem.results;
|
|
523
611
|
if (results.length === 1) {
|
|
524
612
|
result = results[0];
|
|
525
613
|
}
|
|
526
614
|
else if (results.length > 1) {
|
|
527
|
-
result = results.reduce(
|
|
528
|
-
return a.created > b.created ? a : b;
|
|
529
|
-
});
|
|
615
|
+
result = results.reduce((a, b) => a.created > b.created ? a : b);
|
|
530
616
|
}
|
|
531
617
|
else {
|
|
532
618
|
if (addTagQuery && existingItem.query) {
|
|
533
|
-
|
|
619
|
+
const tagQuery = existingItem.query.replace("typekeywords", "tags");
|
|
534
620
|
existingItemsByTag.push(_findExistingItem(tagQuery, authentication));
|
|
535
621
|
}
|
|
536
622
|
}
|
|
537
623
|
if (result) {
|
|
538
|
-
|
|
624
|
+
const sourceId = existingItem.query
|
|
539
625
|
? existingItem.query.match(/[0-9A-F]{32}/i)[0]
|
|
540
626
|
: existingItem.sourceId;
|
|
541
627
|
/* istanbul ignore else */
|
|
@@ -552,7 +638,7 @@ exports._handleExistingItems = _handleExistingItems;
|
|
|
552
638
|
function _updateTemplateDictionaryById(templateDictionary, sourceId, itemId, v) {
|
|
553
639
|
templateDictionary[sourceId] = Object.assign(templateDictionary[sourceId] || {}, {
|
|
554
640
|
def: Promise.resolve(common.generateEmptyCreationResponse(v.type, itemId)),
|
|
555
|
-
itemId
|
|
641
|
+
itemId,
|
|
556
642
|
name: v.name,
|
|
557
643
|
title: v.title,
|
|
558
644
|
url: v.url
|
|
@@ -568,17 +654,16 @@ exports._updateTemplateDictionaryById = _updateTemplateDictionaryById;
|
|
|
568
654
|
* @protected
|
|
569
655
|
*/
|
|
570
656
|
function _findExistingItemByKeyword(templates, templateDictionary, authentication) {
|
|
571
|
-
|
|
572
|
-
templates.forEach(
|
|
573
|
-
var _a;
|
|
657
|
+
const existingItemsDefs = [];
|
|
658
|
+
templates.forEach(template => {
|
|
574
659
|
if (template.item.type === "Group") {
|
|
575
|
-
|
|
660
|
+
const userGroups = templateDictionary.user?.groups;
|
|
576
661
|
/* istanbul ignore else */
|
|
577
662
|
if (Array.isArray(userGroups)) {
|
|
578
663
|
existingItemsDefs.push(Promise.resolve({
|
|
579
664
|
results: userGroups
|
|
580
|
-
.filter(
|
|
581
|
-
.map(
|
|
665
|
+
.filter(g => g.tags.indexOf(`source-${template.itemId}`) > -1)
|
|
666
|
+
.map(g => {
|
|
582
667
|
g.type = "Group";
|
|
583
668
|
return g;
|
|
584
669
|
}),
|
|
@@ -587,7 +672,7 @@ function _findExistingItemByKeyword(templates, templateDictionary, authenticatio
|
|
|
587
672
|
}
|
|
588
673
|
}
|
|
589
674
|
else {
|
|
590
|
-
existingItemsDefs.push(_findExistingItem(
|
|
675
|
+
existingItemsDefs.push(_findExistingItem(`typekeywords:source-${template.itemId} type:${template.item.type} owner:${templateDictionary.user.username}`, authentication));
|
|
591
676
|
}
|
|
592
677
|
});
|
|
593
678
|
return existingItemsDefs;
|
|
@@ -602,7 +687,7 @@ exports._findExistingItemByKeyword = _findExistingItemByKeyword;
|
|
|
602
687
|
* @protected
|
|
603
688
|
*/
|
|
604
689
|
function _findExistingItem(query, authentication) {
|
|
605
|
-
|
|
690
|
+
const searchOptions = {
|
|
606
691
|
q: query,
|
|
607
692
|
authentication: authentication,
|
|
608
693
|
pagingParam: { start: 1, num: 100 }
|
|
@@ -629,16 +714,16 @@ function _createItemFromTemplateWhenReady(template, resourceFilePaths, storageAu
|
|
|
629
714
|
// or if we have a basic entry without the deferred request for its creation, add it
|
|
630
715
|
if (!templateDictionary.hasOwnProperty(template.itemId) ||
|
|
631
716
|
!common.getProp(templateDictionary[template.itemId], "def")) {
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
717
|
+
let createResponse;
|
|
718
|
+
let statusCode = common.EItemProgressStatus.Unknown;
|
|
719
|
+
let itemHandler;
|
|
635
720
|
templateDictionary[template.itemId] =
|
|
636
721
|
templateDictionary[template.itemId] || {};
|
|
637
722
|
// Save the deferred for the use of items that depend on this item being created first
|
|
638
|
-
templateDictionary[template.itemId].def = new Promise(
|
|
723
|
+
templateDictionary[template.itemId].def = new Promise(resolve => {
|
|
639
724
|
// Wait until all of the item's dependencies are deployed
|
|
640
|
-
|
|
641
|
-
|
|
725
|
+
const _awaitDependencies = template.dependencies.reduce((acc, id) => {
|
|
726
|
+
const def = common.getProp(templateDictionary, `${id}.def`);
|
|
642
727
|
// can't use maybePush as that clones the object, which does not work for Promises
|
|
643
728
|
/* istanbul ignore else */
|
|
644
729
|
if (def) {
|
|
@@ -646,10 +731,10 @@ function _createItemFromTemplateWhenReady(template, resourceFilePaths, storageAu
|
|
|
646
731
|
}
|
|
647
732
|
return acc;
|
|
648
733
|
}, []);
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
? syncViews.reduce(
|
|
652
|
-
|
|
734
|
+
const syncViews = common.getProp(template, "properties.syncViews");
|
|
735
|
+
const awaitDependencies = syncViews && syncViews.length > 0
|
|
736
|
+
? syncViews.reduce((acc, v) => {
|
|
737
|
+
const def = common.getProp(templateDictionary, `${v}.def`);
|
|
653
738
|
/* istanbul ignore else */
|
|
654
739
|
if (def) {
|
|
655
740
|
acc.push(def);
|
|
@@ -658,50 +743,55 @@ function _createItemFromTemplateWhenReady(template, resourceFilePaths, storageAu
|
|
|
658
743
|
}, _awaitDependencies)
|
|
659
744
|
: _awaitDependencies;
|
|
660
745
|
Promise.all(awaitDependencies)
|
|
661
|
-
.then(
|
|
746
|
+
.then(() => {
|
|
662
747
|
// Find the conversion handler for this item type
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
if (!
|
|
666
|
-
if (
|
|
667
|
-
|
|
748
|
+
const templateType = template.type;
|
|
749
|
+
itemHandler = module_map_1.moduleMap[templateType];
|
|
750
|
+
if (!itemHandler || itemHandler === UNSUPPORTED) {
|
|
751
|
+
if (itemHandler === UNSUPPORTED) {
|
|
752
|
+
statusCode = common.EItemProgressStatus.Ignored;
|
|
668
753
|
throw new Error();
|
|
669
754
|
}
|
|
670
755
|
else {
|
|
671
|
-
|
|
756
|
+
statusCode = common.EItemProgressStatus.Failed;
|
|
672
757
|
throw new Error();
|
|
673
758
|
}
|
|
674
759
|
}
|
|
675
760
|
// Get the item's thumbnail
|
|
676
761
|
return common.getThumbnailFromStorageItem(storageAuthentication, resourceFilePaths);
|
|
677
762
|
})
|
|
678
|
-
.then(
|
|
763
|
+
.then(thumbnail => {
|
|
679
764
|
template.item.thumbnail = thumbnail;
|
|
680
765
|
// Delegate the creation of the item to the handler
|
|
681
766
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
682
|
-
return
|
|
767
|
+
return itemHandler.createItemFromTemplate(template, templateDictionary, destinationAuthentication, itemProgressCallback);
|
|
683
768
|
})
|
|
684
|
-
.then(
|
|
769
|
+
.then((response) => {
|
|
685
770
|
if (response.id === "") {
|
|
686
|
-
|
|
771
|
+
statusCode = common.EItemProgressStatus.Failed;
|
|
687
772
|
throw new Error("handled"); // fails to create item
|
|
688
773
|
}
|
|
689
774
|
/* istanbul ignore else */
|
|
690
|
-
|
|
691
|
-
if (
|
|
692
|
-
common.setCreateProp(templateDictionary, template.itemId + ".url",
|
|
775
|
+
createResponse = response;
|
|
776
|
+
if (createResponse.item.item.url) {
|
|
777
|
+
common.setCreateProp(templateDictionary, template.itemId + ".url", createResponse.item.item.url);
|
|
778
|
+
}
|
|
779
|
+
if (resourceFilePaths.length > 0) {
|
|
780
|
+
// Copy resources, metadata, form
|
|
781
|
+
return common.copyFilesFromStorageItem(storageAuthentication, resourceFilePaths, templateDictionary.folderId, createResponse.id, destinationAuthentication, createResponse.item);
|
|
782
|
+
}
|
|
783
|
+
else {
|
|
784
|
+
return Promise.resolve(null);
|
|
693
785
|
}
|
|
694
|
-
// Copy resources, metadata, form
|
|
695
|
-
return common.copyFilesFromStorageItem(storageAuthentication, resourceFilePaths, templateDictionary.folderId, createResponse_1.id, destinationAuthentication, createResponse_1.item);
|
|
696
786
|
})
|
|
697
|
-
.then(
|
|
698
|
-
resolve(
|
|
787
|
+
.then(() => {
|
|
788
|
+
resolve(createResponse);
|
|
699
789
|
})
|
|
700
|
-
.catch(
|
|
790
|
+
.catch(error => {
|
|
701
791
|
if (!error || error.message !== "handled") {
|
|
702
|
-
itemProgressCallback(template.itemId,
|
|
792
|
+
itemProgressCallback(template.itemId, statusCode === common.EItemProgressStatus.Unknown
|
|
703
793
|
? common.EItemProgressStatus.Failed
|
|
704
|
-
:
|
|
794
|
+
: statusCode, 0);
|
|
705
795
|
}
|
|
706
796
|
// Item type not supported or fails to get item dependencies
|
|
707
797
|
resolve(common.generateEmptyCreationResponse(template.type));
|
|
@@ -719,16 +809,16 @@ exports._createItemFromTemplateWhenReady = _createItemFromTemplateWhenReady;
|
|
|
719
809
|
* @protected
|
|
720
810
|
*/
|
|
721
811
|
function _estimateDeploymentCost(templates) {
|
|
722
|
-
return templates.reduce(
|
|
812
|
+
return templates.reduce((accumulatedEstimatedCost, template) => {
|
|
723
813
|
return (accumulatedEstimatedCost + (template.estimatedDeploymentCostFactor || 1));
|
|
724
814
|
}, 0);
|
|
725
815
|
}
|
|
726
816
|
exports._estimateDeploymentCost = _estimateDeploymentCost;
|
|
727
817
|
// TODO: Return a Promise vs array of promises
|
|
728
818
|
function _getGroupUpdates(template, authentication, templateDictionary) {
|
|
729
|
-
|
|
730
|
-
return groups.map(
|
|
731
|
-
return common.shareItem(templateDictionary[sourceGroupId].itemId, template.itemId, authentication);
|
|
819
|
+
const groups = template.groups || [];
|
|
820
|
+
return groups.map((sourceGroupId) => {
|
|
821
|
+
return common.shareItem(templateDictionary[sourceGroupId].itemId, template.itemId, authentication, common.isTrackingViewTemplate(template) ? templateDictionary.locationTracking.owner : undefined);
|
|
732
822
|
});
|
|
733
823
|
}
|
|
734
824
|
exports._getGroupUpdates = _getGroupUpdates;
|