@esri/solution-common 5.2.3 → 5.2.5

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 (190) hide show
  1. package/dist/cjs/completeItem.d.ts +29 -0
  2. package/dist/cjs/completeItem.js +92 -0
  3. package/dist/cjs/completeItem.js.map +1 -0
  4. package/dist/cjs/create-hub-request-options.d.ts +29 -0
  5. package/dist/cjs/create-hub-request-options.js +64 -0
  6. package/dist/cjs/create-hub-request-options.js.map +1 -0
  7. package/dist/cjs/deleteHelpers/deleteEmptyGroups.d.ts +24 -0
  8. package/dist/cjs/deleteHelpers/deleteEmptyGroups.js +42 -0
  9. package/dist/cjs/deleteHelpers/deleteEmptyGroups.js.map +1 -0
  10. package/dist/cjs/deleteHelpers/deleteGroupIfEmpty.d.ts +27 -0
  11. package/dist/cjs/deleteHelpers/deleteGroupIfEmpty.js +97 -0
  12. package/dist/cjs/deleteHelpers/deleteGroupIfEmpty.js.map +1 -0
  13. package/dist/cjs/deleteHelpers/deleteSolutionContents.d.ts +38 -0
  14. package/dist/cjs/deleteHelpers/deleteSolutionContents.js +130 -0
  15. package/dist/cjs/deleteHelpers/deleteSolutionContents.js.map +1 -0
  16. package/dist/cjs/deleteHelpers/deleteSolutionFolder.d.ts +29 -0
  17. package/dist/cjs/deleteHelpers/deleteSolutionFolder.js +79 -0
  18. package/dist/cjs/deleteHelpers/deleteSolutionFolder.js.map +1 -0
  19. package/dist/cjs/deleteHelpers/deleteSolutionItem.d.ts +30 -0
  20. package/dist/cjs/deleteHelpers/deleteSolutionItem.js +54 -0
  21. package/dist/cjs/deleteHelpers/deleteSolutionItem.js.map +1 -0
  22. package/dist/cjs/deleteHelpers/index.d.ts +22 -0
  23. package/dist/cjs/deleteHelpers/index.js +26 -0
  24. package/dist/cjs/deleteHelpers/index.js.map +1 -0
  25. package/dist/cjs/deleteHelpers/reconstructBuildOrderIds.d.ts +27 -0
  26. package/dist/cjs/deleteHelpers/reconstructBuildOrderIds.js +34 -0
  27. package/dist/cjs/deleteHelpers/reconstructBuildOrderIds.js.map +1 -0
  28. package/dist/cjs/deleteHelpers/removeItems.d.ts +34 -0
  29. package/dist/cjs/deleteHelpers/removeItems.js +112 -0
  30. package/dist/cjs/deleteHelpers/removeItems.js.map +1 -0
  31. package/dist/cjs/deleteHelpers/reportProgress.d.ts +27 -0
  32. package/dist/cjs/deleteHelpers/reportProgress.js +46 -0
  33. package/dist/cjs/deleteHelpers/reportProgress.js.map +1 -0
  34. package/dist/cjs/deleteSolution.d.ts +55 -0
  35. package/dist/cjs/deleteSolution.js +107 -0
  36. package/dist/cjs/deleteSolution.js.map +1 -0
  37. package/dist/cjs/dependencies.d.ts +26 -0
  38. package/dist/cjs/dependencies.js +171 -0
  39. package/dist/cjs/dependencies.js.map +1 -0
  40. package/dist/cjs/featureServiceHelpers.d.ts +799 -0
  41. package/dist/cjs/featureServiceHelpers.js +2438 -0
  42. package/dist/cjs/featureServiceHelpers.js.map +1 -0
  43. package/dist/cjs/formHelpers.d.ts +41 -0
  44. package/dist/cjs/formHelpers.js +78 -0
  45. package/dist/cjs/formHelpers.js.map +1 -0
  46. package/dist/cjs/generalHelpers.d.ts +433 -0
  47. package/dist/cjs/generalHelpers.js +925 -0
  48. package/dist/cjs/generalHelpers.js.map +1 -0
  49. package/dist/cjs/get-subscription-info.d.ts +27 -0
  50. package/dist/cjs/get-subscription-info.js +39 -0
  51. package/dist/cjs/get-subscription-info.js.map +1 -0
  52. package/dist/cjs/getDeletableSolutionInfo.d.ts +29 -0
  53. package/dist/cjs/getDeletableSolutionInfo.js +53 -0
  54. package/dist/cjs/getDeletableSolutionInfo.js.map +1 -0
  55. package/dist/cjs/getItemTypeAbbrev.d.ts +19 -0
  56. package/dist/cjs/getItemTypeAbbrev.js +186 -0
  57. package/dist/cjs/getItemTypeAbbrev.js.map +1 -0
  58. package/dist/cjs/getSolutionSummary.d.ts +27 -0
  59. package/dist/cjs/getSolutionSummary.js +101 -0
  60. package/dist/cjs/getSolutionSummary.js.map +1 -0
  61. package/dist/cjs/index.d.ts +46 -0
  62. package/dist/cjs/index.js +50 -0
  63. package/dist/cjs/index.js.map +1 -0
  64. package/dist/cjs/interfaces.d.ts +1362 -0
  65. package/dist/cjs/interfaces.js +77 -0
  66. package/dist/cjs/interfaces.js.map +1 -0
  67. package/dist/cjs/libConnectors.d.ts +73 -0
  68. package/dist/cjs/libConnectors.js +115 -0
  69. package/dist/cjs/libConnectors.js.map +1 -0
  70. package/dist/cjs/migrations/apply-schema.d.ts +24 -0
  71. package/dist/cjs/migrations/apply-schema.js +36 -0
  72. package/dist/cjs/migrations/apply-schema.js.map +1 -0
  73. package/dist/cjs/migrations/is-legacy-solution.d.ts +24 -0
  74. package/dist/cjs/migrations/is-legacy-solution.js +40 -0
  75. package/dist/cjs/migrations/is-legacy-solution.js.map +1 -0
  76. package/dist/cjs/migrations/upgrade-three-dot-one.d.ts +27 -0
  77. package/dist/cjs/migrations/upgrade-three-dot-one.js +49 -0
  78. package/dist/cjs/migrations/upgrade-three-dot-one.js.map +1 -0
  79. package/dist/cjs/migrations/upgrade-three-dot-zero.d.ts +27 -0
  80. package/dist/cjs/migrations/upgrade-three-dot-zero.js +43 -0
  81. package/dist/cjs/migrations/upgrade-three-dot-zero.js.map +1 -0
  82. package/dist/cjs/migrations/upgrade-two-dot-five.d.ts +24 -0
  83. package/dist/cjs/migrations/upgrade-two-dot-five.js +73 -0
  84. package/dist/cjs/migrations/upgrade-two-dot-five.js.map +1 -0
  85. package/dist/cjs/migrations/upgrade-two-dot-four.d.ts +24 -0
  86. package/dist/cjs/migrations/upgrade-two-dot-four.js +72 -0
  87. package/dist/cjs/migrations/upgrade-two-dot-four.js.map +1 -0
  88. package/dist/cjs/migrations/upgrade-two-dot-one.d.ts +7 -0
  89. package/dist/cjs/migrations/upgrade-two-dot-one.js +39 -0
  90. package/dist/cjs/migrations/upgrade-two-dot-one.js.map +1 -0
  91. package/dist/cjs/migrations/upgrade-two-dot-seven.d.ts +23 -0
  92. package/dist/cjs/migrations/upgrade-two-dot-seven.js +58 -0
  93. package/dist/cjs/migrations/upgrade-two-dot-seven.js.map +1 -0
  94. package/dist/cjs/migrations/upgrade-two-dot-six.d.ts +27 -0
  95. package/dist/cjs/migrations/upgrade-two-dot-six.js +61 -0
  96. package/dist/cjs/migrations/upgrade-two-dot-six.js.map +1 -0
  97. package/dist/cjs/migrations/upgrade-two-dot-three.d.ts +23 -0
  98. package/dist/cjs/migrations/upgrade-two-dot-three.js +55 -0
  99. package/dist/cjs/migrations/upgrade-two-dot-three.js.map +1 -0
  100. package/dist/cjs/migrations/upgrade-two-dot-two.d.ts +23 -0
  101. package/dist/cjs/migrations/upgrade-two-dot-two.js +58 -0
  102. package/dist/cjs/migrations/upgrade-two-dot-two.js.map +1 -0
  103. package/dist/cjs/migrations/upgrade-two-dot-zero.d.ts +44 -0
  104. package/dist/cjs/migrations/upgrade-two-dot-zero.js +95 -0
  105. package/dist/cjs/migrations/upgrade-two-dot-zero.js.map +1 -0
  106. package/dist/cjs/migrator.d.ts +25 -0
  107. package/dist/cjs/migrator.js +77 -0
  108. package/dist/cjs/migrator.js.map +1 -0
  109. package/dist/cjs/resourceHelpers.d.ts +191 -0
  110. package/dist/cjs/resourceHelpers.js +384 -0
  111. package/dist/cjs/resourceHelpers.js.map +1 -0
  112. package/dist/cjs/resources/add-resource-from-blob.d.ts +26 -0
  113. package/dist/cjs/resources/add-resource-from-blob.js +52 -0
  114. package/dist/cjs/resources/add-resource-from-blob.js.map +1 -0
  115. package/dist/cjs/resources/addMetadataFromBlob.d.ts +25 -0
  116. package/dist/cjs/resources/addMetadataFromBlob.js +43 -0
  117. package/dist/cjs/resources/addMetadataFromBlob.js.map +1 -0
  118. package/dist/cjs/resources/convert-item-resource-to-storage-resource.d.ts +32 -0
  119. package/dist/cjs/resources/convert-item-resource-to-storage-resource.js +70 -0
  120. package/dist/cjs/resources/convert-item-resource-to-storage-resource.js.map +1 -0
  121. package/dist/cjs/resources/convert-storage-resource-to-item-resource.d.ts +29 -0
  122. package/dist/cjs/resources/convert-storage-resource-to-item-resource.js +70 -0
  123. package/dist/cjs/resources/convert-storage-resource-to-item-resource.js.map +1 -0
  124. package/dist/cjs/resources/copyAssociatedFiles.d.ts +67 -0
  125. package/dist/cjs/resources/copyAssociatedFiles.js +304 -0
  126. package/dist/cjs/resources/copyAssociatedFiles.js.map +1 -0
  127. package/dist/cjs/resources/copyDataIntoItem.d.ts +33 -0
  128. package/dist/cjs/resources/copyDataIntoItem.js +62 -0
  129. package/dist/cjs/resources/copyDataIntoItem.js.map +1 -0
  130. package/dist/cjs/resources/copyMetadataIntoItem.d.ts +26 -0
  131. package/dist/cjs/resources/copyMetadataIntoItem.js +46 -0
  132. package/dist/cjs/resources/copyMetadataIntoItem.js.map +1 -0
  133. package/dist/cjs/resources/copyResourceIntoZip.d.ts +33 -0
  134. package/dist/cjs/resources/copyResourceIntoZip.js +78 -0
  135. package/dist/cjs/resources/copyResourceIntoZip.js.map +1 -0
  136. package/dist/cjs/resources/copyZipIntoItem.d.ts +25 -0
  137. package/dist/cjs/resources/copyZipIntoItem.js +54 -0
  138. package/dist/cjs/resources/copyZipIntoItem.js.map +1 -0
  139. package/dist/cjs/resources/createCopyResults.d.ts +25 -0
  140. package/dist/cjs/resources/createCopyResults.js +36 -0
  141. package/dist/cjs/resources/createCopyResults.js.map +1 -0
  142. package/dist/cjs/resources/get-blob.d.ts +26 -0
  143. package/dist/cjs/resources/get-blob.js +27 -0
  144. package/dist/cjs/resources/get-blob.js.map +1 -0
  145. package/dist/cjs/resources/getItemResourcesFilesFromPaths.d.ts +24 -0
  146. package/dist/cjs/resources/getItemResourcesFilesFromPaths.js +49 -0
  147. package/dist/cjs/resources/getItemResourcesFilesFromPaths.js.map +1 -0
  148. package/dist/cjs/resources/getItemResourcesPaths.d.ts +26 -0
  149. package/dist/cjs/resources/getItemResourcesPaths.js +76 -0
  150. package/dist/cjs/resources/getItemResourcesPaths.js.map +1 -0
  151. package/dist/cjs/resources/index.d.ts +29 -0
  152. package/dist/cjs/resources/index.js +33 -0
  153. package/dist/cjs/resources/index.js.map +1 -0
  154. package/dist/cjs/resources/solution-resource.d.ts +35 -0
  155. package/dist/cjs/resources/solution-resource.js +31 -0
  156. package/dist/cjs/resources/solution-resource.js.map +1 -0
  157. package/dist/cjs/resources/transform-resource-paths-to-solution-resources.d.ts +56 -0
  158. package/dist/cjs/resources/transform-resource-paths-to-solution-resources.js +146 -0
  159. package/dist/cjs/resources/transform-resource-paths-to-solution-resources.js.map +1 -0
  160. package/dist/cjs/restHelpers.d.ts +607 -0
  161. package/dist/cjs/restHelpers.js +1954 -0
  162. package/dist/cjs/restHelpers.js.map +1 -0
  163. package/dist/cjs/restHelpersGet.d.ts +288 -0
  164. package/dist/cjs/restHelpersGet.js +804 -0
  165. package/dist/cjs/restHelpersGet.js.map +1 -0
  166. package/dist/cjs/sharing/index.d.ts +16 -0
  167. package/dist/cjs/sharing/index.js +20 -0
  168. package/dist/cjs/sharing/index.js.map +1 -0
  169. package/dist/cjs/sharing/share-item-to-groups.d.ts +26 -0
  170. package/dist/cjs/sharing/share-item-to-groups.js +44 -0
  171. package/dist/cjs/sharing/share-item-to-groups.js.map +1 -0
  172. package/dist/cjs/templatization.d.ts +139 -0
  173. package/dist/cjs/templatization.js +316 -0
  174. package/dist/cjs/templatization.js.map +1 -0
  175. package/dist/cjs/trackingHelpers.d.ts +116 -0
  176. package/dist/cjs/trackingHelpers.js +217 -0
  177. package/dist/cjs/trackingHelpers.js.map +1 -0
  178. package/dist/cjs/velocityHelpers.d.ts +57 -0
  179. package/dist/cjs/velocityHelpers.js +135 -0
  180. package/dist/cjs/velocityHelpers.js.map +1 -0
  181. package/dist/cjs/workflowHelpers.d.ts +37 -0
  182. package/dist/cjs/workflowHelpers.js +77 -0
  183. package/dist/cjs/workflowHelpers.js.map +1 -0
  184. package/dist/cjs/workforceHelpers.d.ts +115 -0
  185. package/dist/cjs/workforceHelpers.js +749 -0
  186. package/dist/cjs/workforceHelpers.js.map +1 -0
  187. package/dist/cjs/zip-utils.d.ts +76 -0
  188. package/dist/cjs/zip-utils.js +142 -0
  189. package/dist/cjs/zip-utils.js.map +1 -0
  190. package/package.json +2 -2
@@ -0,0 +1,2438 @@
1
+ "use strict";
2
+ /** @license
3
+ * Copyright 2019 Esri
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports._templatizeAdminLayerInfo = exports._templatizeLayerFieldReferences = exports._validateEditFieldsInfo = exports._validateTypesTemplates = exports._validateTemplatesFields = exports._validateIndexes = exports._validateDisplayField = exports._validateFields = exports._templatizeLayer = exports._templatizeProperty = exports._templatize = exports.updatePopupInfo = exports.postProcessFields = exports.updateLayerFieldReferences = exports.validateSpatialReferenceAndExtent = exports.setDefaultSpatialReference = exports._updateTemplateDictionaryFields = exports._updateGeomFieldName = exports._updateSourceLayerFields = exports._updateItemFields = exports._getDynamicFieldNames = exports._getFieldNames = exports._updateForPortal = exports.removeLayerOptimization = exports._isSelfReferential = exports._updateAddOptions = exports._updateOrder = exports.addFeatureServiceDefinition = exports.addFeatureServiceLayersAndTables = exports.getExistingLayersAndTables = exports.getLayersAndTables = exports.deTemplatizeFieldInfos = exports.processContingentValues = exports.updateTemplateForInvalidDesignations = exports.updateSettingsFieldInfos = exports.setNamesAndTitles = exports.getLayerSettings = exports._updateTypeKeywords = exports.updateTemplate = exports.cacheLayerInfo = exports._cachePopupInfo = exports.cachePopupInfos = exports._cacheFieldInfo = exports.cacheContingentValues = exports.cacheFieldInfos = exports.deleteViewProps = exports.templatize = exports.getFeatureServiceRelatedRecords = exports.rest_addFeatures = exports.rest_queryFeatures = void 0;
19
+ exports._getLayerChunkSize = exports._getNameMapping = exports._templatizeDefinitionQuery = exports._templatizeTimeInfo = exports._templatizeKeys = exports._templatizeTypeTemplates = exports._templatizeTemplates = exports._templatizeLabelingInfo = exports._templatizeArcadeExpressions = exports._templatizeAuthoringInfo = exports._templatizeTemporalRenderer = exports._templatizeGenRenderer = exports._templatizeRenderer = exports._templatizeDrawingInfo = exports._templatizeSimpleName = exports._templatizeDefinitionExpression = exports._templatizeDefinitionEditor = exports._templatizeMediaInfos = exports._templatizePopupElements = exports._templatizeExpressionInfos = exports._templatizeFieldName = exports._templatizePopupInfoFieldInfos = exports._templatizeName = exports._templatizePopupInfo = exports._templatizeRelationshipFields = exports._templatizeTopFilter = exports._templatizeAdminSourceLayerFields = exports._getDependantItemId = exports._templatizeAdminLayerInfoFields = exports._templatizeSourceServiceName = exports._processAdminObject = void 0;
20
+ /**
21
+ * Provides general helper functions.
22
+ *
23
+ * @module featureServiceHelpers
24
+ */
25
+ // ------------------------------------------------------------------------------------------------------------------ //
26
+ var arcgis_rest_feature_layer_1 = require("@esri/arcgis-rest-feature-layer");
27
+ Object.defineProperty(exports, "rest_queryFeatures", { enumerable: true, get: function () { return arcgis_rest_feature_layer_1.queryFeatures; } });
28
+ Object.defineProperty(exports, "rest_addFeatures", { enumerable: true, get: function () { return arcgis_rest_feature_layer_1.addFeatures; } });
29
+ //#region Imports -------------------------------------------------------------------------------------------------------//
30
+ const interfaces_1 = require("./interfaces");
31
+ const generalHelpers_1 = require("./generalHelpers");
32
+ const templatization_1 = require("./templatization");
33
+ const restHelpers_1 = require("./restHelpers");
34
+ const trackingHelpers_1 = require("./trackingHelpers");
35
+ const arcgis_rest_feature_layer_2 = require("@esri/arcgis-rest-feature-layer");
36
+ //#endregion ------------------------------------------------------------------------------------------------------------//
37
+ //#region Public functions ----------------------------------------------------------------------------------------------//
38
+ /**
39
+ * Get the related records for a feature service.
40
+ *
41
+ * @param url Feature service's URL, e.g., layer.url
42
+ * @param relationshipId Id of relationship
43
+ * @param objectIds Objects in the feature service whose related records are sought
44
+ */
45
+ function getFeatureServiceRelatedRecords(url, relationshipId, objectIds) {
46
+ const options = {
47
+ url: url + `/${relationshipId}`,
48
+ relationshipId,
49
+ objectIds
50
+ };
51
+ return (0, arcgis_rest_feature_layer_2.queryRelated)(options);
52
+ }
53
+ exports.getFeatureServiceRelatedRecords = getFeatureServiceRelatedRecords;
54
+ /**
55
+ * Templatize the ID, url, field references ect
56
+ *
57
+ * @param itemTemplate Template for feature service item
58
+ * @param dependencies Array of IDependency for name mapping
59
+ * @param templatizeFieldReferences Templatize all field references within a layer
60
+ * @param templateDictionary Hash mapping property names to replacement values
61
+ * @returns A promise that will resolve when template has been updated
62
+ * @private
63
+ */
64
+ function templatize(itemTemplate, dependencies, templatizeFieldReferences, templateDictionary) {
65
+ templateDictionary = templateDictionary || {};
66
+ // Common templatizations
67
+ const id = itemTemplate.item.id;
68
+ const fsUrl = itemTemplate.item.url;
69
+ itemTemplate.item = {
70
+ ...itemTemplate.item,
71
+ id: (0, templatization_1.templatizeTerm)(id, id, ".itemId"),
72
+ url: _templatize(id, "url"),
73
+ typeKeywords: (0, templatization_1.templatizeIds)(itemTemplate.item.typeKeywords)
74
+ };
75
+ // special handeling if we are dealing with a tracker view
76
+ (0, trackingHelpers_1.templatizeTracker)(itemTemplate);
77
+ // added for issue #928
78
+ (0, generalHelpers_1.deleteProp)(itemTemplate, "properties.service.size");
79
+ const jsonLayers = itemTemplate.properties.layers || [];
80
+ const jsonTables = itemTemplate.properties.tables || [];
81
+ const jsonItems = jsonLayers.concat(jsonTables);
82
+ const data = itemTemplate.data || {};
83
+ const layers = data.layers || [];
84
+ const tables = data.tables || [];
85
+ const _items = layers.concat(tables);
86
+ // Set up symbols for the URL of the feature service and its layers and tables
87
+ templateDictionary[fsUrl] = itemTemplate.item.url; // map FS URL to its templatized form
88
+ jsonItems.concat(_items).forEach(layer => {
89
+ templateDictionary[fsUrl + "/" + layer.id] = _templatize(id, "layer" + layer.id + ".url");
90
+ });
91
+ // templatize the service references serviceItemId
92
+ itemTemplate.properties.service.serviceItemId = (0, templatization_1.templatizeTerm)(itemTemplate.properties.service.serviceItemId, itemTemplate.properties.service.serviceItemId, ".itemId");
93
+ const initialExtent = (0, generalHelpers_1.getProp)(itemTemplate, "properties.service.initialExtent");
94
+ /* istanbul ignore else */
95
+ if (initialExtent) {
96
+ itemTemplate.properties.service.initialExtent = (0, templatization_1.templatizeTerm)(id, id, ".solutionExtent");
97
+ }
98
+ const fullExtent = (0, generalHelpers_1.getProp)(itemTemplate, "properties.service.fullExtent");
99
+ /* istanbul ignore else */
100
+ if (fullExtent) {
101
+ itemTemplate.properties.service.fullExtent = (0, templatization_1.templatizeTerm)(id, id, ".solutionExtent");
102
+ }
103
+ // this default extent will be used in cases where it does not make sense to apply the orgs
104
+ // extent to a service with a local spatial reference
105
+ itemTemplate.properties.defaultExtent = initialExtent || fullExtent;
106
+ // in some cases a service does not have a spatial reference defined
107
+ // added for issue #699
108
+ if (!(0, generalHelpers_1.getProp)(itemTemplate, "properties.service.spatialReference") &&
109
+ (0, generalHelpers_1.getProp)(itemTemplate, "properties.defaultExtent.spatialReference")) {
110
+ (0, generalHelpers_1.setCreateProp)(itemTemplate, "properties.service.spatialReference", itemTemplate.properties.defaultExtent.spatialReference);
111
+ }
112
+ // if any layer hasZ enabled then we need to set
113
+ // enableZDefaults and zDefault to deploy to enterprise
114
+ let hasZ = false;
115
+ jsonItems.forEach((jsonItem) => {
116
+ // get the source service json for the given data item
117
+ const matchingItems = _items.filter(item => {
118
+ return jsonItem.id === item.id;
119
+ });
120
+ // templatize the source service json
121
+ const _item = matchingItems.length === 1 ? matchingItems[0] : undefined;
122
+ _templatizeLayer(_item, jsonItem, itemTemplate, dependencies, templatizeFieldReferences, templateDictionary);
123
+ hasZ = jsonItem.hasZ || (_item && _item.hasZ) ? true : hasZ;
124
+ });
125
+ if (hasZ) {
126
+ itemTemplate.properties.service.enableZDefaults = true;
127
+ itemTemplate.properties.service.zDefault = 0;
128
+ }
129
+ return itemTemplate;
130
+ }
131
+ exports.templatize = templatize;
132
+ /**
133
+ * Delete key properties that are system managed
134
+ *
135
+ * @param layer The data layer instance with field name references within
136
+ */
137
+ function deleteViewProps(layer) {
138
+ const props = ["definitionQuery"];
139
+ props.forEach(prop => {
140
+ (0, generalHelpers_1.deleteProp)(layer, prop);
141
+ });
142
+ }
143
+ exports.deleteViewProps = deleteViewProps;
144
+ /**
145
+ * Cache properties that contain field references
146
+ *
147
+ * removeProp added for issue #644
148
+ * setting all props on add for online now
149
+ * investigating if we can also just allow them to be set during add for portal
150
+ *
151
+ * @param layer The data layer instance with field name references within
152
+ * @param fieldInfos the object that stores the cached field infos
153
+ * @returns An updated instance of the fieldInfos
154
+ */
155
+ function cacheFieldInfos(layer, fieldInfos) {
156
+ // cache the source fields as they are in the original source
157
+ if (layer && layer.fields) {
158
+ fieldInfos[layer.id] = {
159
+ sourceFields: JSON.parse(JSON.stringify(layer.fields)),
160
+ type: layer.type,
161
+ id: layer.id
162
+ };
163
+ }
164
+ // cache each of these properties as they each can contain field references
165
+ // and will have associated updateDefinition calls when deploying to portal
166
+ // as well as online for relationships...as relationships added with addToDef will cause failure
167
+ const props = {
168
+ editFieldsInfo: false,
169
+ types: false,
170
+ templates: false,
171
+ relationships: true,
172
+ drawingInfo: false,
173
+ timeInfo: false,
174
+ viewDefinitionQuery: false
175
+ };
176
+ Object.keys(props).forEach(k => {
177
+ _cacheFieldInfo(layer, k, fieldInfos, props[k]);
178
+ });
179
+ return fieldInfos;
180
+ }
181
+ exports.cacheFieldInfos = cacheFieldInfos;
182
+ /**
183
+ * Cache the stored contingent values so we can add them in subsequent addToDef calls
184
+ *
185
+ * @param id The layer id for the associated values to be stored with
186
+ * @param fieldInfos The object that stores the cached field infos
187
+ * @param itemTemplate The current itemTemplate being processed
188
+ * @returns An updated instance of the fieldInfos
189
+ */
190
+ function cacheContingentValues(id, fieldInfos, itemTemplate) {
191
+ const contingentValues = (0, generalHelpers_1.getProp)(itemTemplate, 'properties.contingentValues');
192
+ if (contingentValues && contingentValues[id]) {
193
+ fieldInfos[id]['contingentValues'] = contingentValues[id];
194
+ }
195
+ return fieldInfos;
196
+ }
197
+ exports.cacheContingentValues = cacheContingentValues;
198
+ /**
199
+ * Helper function to cache a single property into the fieldInfos object
200
+ * This property will be removed from the layer instance.
201
+ *
202
+ * @param layer the data layer being cloned
203
+ * @param prop the property name used to cache
204
+ * @param fieldInfos the object that will store the cached property
205
+ * @private
206
+ */
207
+ function _cacheFieldInfo(layer, prop, fieldInfos, removeProp) {
208
+ /* istanbul ignore else */
209
+ if (layer &&
210
+ layer.hasOwnProperty(prop) &&
211
+ fieldInfos &&
212
+ fieldInfos.hasOwnProperty(layer.id)) {
213
+ fieldInfos[layer.id][prop] = layer[prop];
214
+ // editFieldsInfo does not come through unless its with the layer
215
+ // when it's being added
216
+ /* istanbul ignore else */
217
+ if (removeProp) {
218
+ layer[prop] = null;
219
+ }
220
+ }
221
+ }
222
+ exports._cacheFieldInfo = _cacheFieldInfo;
223
+ /**
224
+ * Cache popup info that can contain field references
225
+ *
226
+ * @param data The items data property
227
+ * @returns An updated instance of the popupInfos
228
+ */
229
+ function cachePopupInfos(data) {
230
+ // store any popupInfo so we can update after any potential name changes
231
+ const popupInfos = {
232
+ layers: {},
233
+ tables: {}
234
+ };
235
+ if (data && data.layers && data.layers.length > 0) {
236
+ _cachePopupInfo(popupInfos, "layers", data.layers);
237
+ }
238
+ if (data && data.tables && data.tables.length > 0) {
239
+ _cachePopupInfo(popupInfos, "tables", data.tables);
240
+ }
241
+ return popupInfos;
242
+ }
243
+ exports.cachePopupInfos = cachePopupInfos;
244
+ /**
245
+ * Helper function to cache a single popupInfo
246
+ * This property will be reset on the layer
247
+ *
248
+ * @param popupInfos object to store the cahced popupInfo
249
+ * @param type is it a layer or table
250
+ * @param _items list or either layers or tables
251
+ * @private
252
+ */
253
+ function _cachePopupInfo(popupInfos, type, _items) {
254
+ _items.forEach((item) => {
255
+ if (item && item.hasOwnProperty("popupInfo")) {
256
+ popupInfos[type][item.id] = item.popupInfo;
257
+ item.popupInfo = {};
258
+ }
259
+ });
260
+ }
261
+ exports._cachePopupInfo = _cachePopupInfo;
262
+ /**
263
+ * Store basic layer information for potential replacement if we are unable to access a given service
264
+ * added for issue #859
265
+ *
266
+ * @param layerId the id for the layer
267
+ * @param itemId the id for the item
268
+ * @param url the url for the layer
269
+ * @param templateDictionary Hash of key details used for variable replacement
270
+ * @returns templatized itemTemplate
271
+ */
272
+ function cacheLayerInfo(layerId, itemId, url, templateDictionary) {
273
+ if (layerId) {
274
+ const layerIdVar = `layer${layerId}`;
275
+ // need to structure these differently so they are not used for standard replacement calls
276
+ // this now adds additional vars that are not needing replacement unless we fail to fetch the service
277
+ const newVars = (0, generalHelpers_1.getProp)(templateDictionary, `${interfaces_1.UNREACHABLE}.${itemId}`) || {
278
+ itemId
279
+ };
280
+ newVars[layerIdVar] = (0, generalHelpers_1.getProp)(newVars, layerIdVar) || {
281
+ layerId,
282
+ itemId
283
+ };
284
+ if (url !== "") {
285
+ newVars[layerIdVar]["url"] = url;
286
+ }
287
+ const unreachableVars = {};
288
+ unreachableVars[itemId] = newVars;
289
+ templateDictionary[interfaces_1.UNREACHABLE] = {
290
+ ...templateDictionary[interfaces_1.UNREACHABLE],
291
+ ...unreachableVars
292
+ };
293
+ }
294
+ }
295
+ exports.cacheLayerInfo = cacheLayerInfo;
296
+ /**
297
+ * Creates an item in a specified folder (except for Group item type).
298
+ *
299
+ * @param itemTemplate Item to be created; n.b.: this item is modified
300
+ * @param templateDictionary Hash mapping property names to replacement values
301
+ * @param createResponse Response from create service
302
+ * @returns An updated instance of the template
303
+ * @private
304
+ */
305
+ function updateTemplate(itemTemplate, templateDictionary, createResponse) {
306
+ // Update the item with any typeKeywords that were added on create
307
+ _updateTypeKeywords(itemTemplate, createResponse);
308
+ // Add the new item to the template dictionary
309
+ templateDictionary[itemTemplate.itemId] = Object.assign(templateDictionary[itemTemplate.itemId] || {}, {
310
+ itemId: createResponse.serviceItemId,
311
+ url: (0, generalHelpers_1.checkUrlPathTermination)(createResponse.serviceurl),
312
+ name: createResponse.name
313
+ });
314
+ // Update the item template now that the new service has been created
315
+ itemTemplate.itemId = createResponse.serviceItemId;
316
+ return (0, templatization_1.replaceInTemplate)(itemTemplate, templateDictionary);
317
+ }
318
+ exports.updateTemplate = updateTemplate;
319
+ /**
320
+ * Updates the items typeKeywords to include any typeKeywords that
321
+ * were added by the create service request
322
+ *
323
+ * @param itemTemplate Item to be created; n.b.: this item is modified
324
+ * @param createResponse Response from create service
325
+ * @returns An updated instance of the template
326
+ * @private
327
+ */
328
+ function _updateTypeKeywords(itemTemplate, createResponse) {
329
+ // https://github.com/Esri/solution.js/issues/589
330
+ const iKwords = (0, generalHelpers_1.getProp)(itemTemplate, "item.typeKeywords");
331
+ const cKwords = (0, generalHelpers_1.getProp)(createResponse, "typeKeywords");
332
+ if (iKwords && cKwords) {
333
+ (0, generalHelpers_1.setProp)(itemTemplate, "item.typeKeywords", iKwords.concat(cKwords.filter(k => iKwords.indexOf(k) < 0)));
334
+ }
335
+ return itemTemplate;
336
+ }
337
+ exports._updateTypeKeywords = _updateTypeKeywords;
338
+ /**
339
+ * Create the name mapping object that will allow for all templatized field
340
+ * references to be de-templatized.
341
+ * This also removes the stored sourceFields and newFields arrays from fieldInfos.
342
+ *
343
+ * @example
344
+ * \{ layer0: \{ fields: \{ lowerCaseSourceFieldName: newFieldNameAfterDeployment \} \} \}
345
+ *
346
+ * @param layerInfos The object that stores the cached layer properties and name mapping
347
+ * @returns The settings object that will be used to de-templatize the field references.
348
+ */
349
+ function getLayerSettings(layerInfos, url, itemId, enterpriseIDMapping) {
350
+ const settings = {};
351
+ const ids = Object.keys(layerInfos);
352
+ ids.forEach((id) => {
353
+ const _layerId = (0, generalHelpers_1.getProp)(layerInfos[id], "item.id");
354
+ const isNum = parseInt(_layerId, 10) > -1;
355
+ const layerId = isNum && enterpriseIDMapping
356
+ ? enterpriseIDMapping[_layerId]
357
+ : isNum
358
+ ? _layerId
359
+ : id;
360
+ settings[`layer${isNum ? _layerId : id}`] = {
361
+ fields: _getNameMapping(layerInfos, id),
362
+ url: (0, generalHelpers_1.checkUrlPathTermination)(url) + layerId,
363
+ layerId,
364
+ itemId
365
+ };
366
+ (0, generalHelpers_1.deleteProp)(layerInfos[id], "newFields");
367
+ (0, generalHelpers_1.deleteProp)(layerInfos[id], "sourceFields");
368
+ });
369
+ return settings;
370
+ }
371
+ exports.getLayerSettings = getLayerSettings;
372
+ /**
373
+ * Set the names and titles for all feature services.
374
+ *
375
+ * This function will ensure that we have unique feature service names.
376
+ * The feature service name will have the solution item id appended.
377
+ *
378
+ * @param templates A collection of AGO item templates.
379
+ * @param solutionItemId The item id for the deployed solution item.
380
+ * @returns An updated collection of AGO templates with unique feature service names.
381
+ */
382
+ function setNamesAndTitles(templates, solutionItemId) {
383
+ const names = [];
384
+ return templates.map(t => {
385
+ /* istanbul ignore else */
386
+ if (t.item.type === "Feature Service") {
387
+ // Retain the existing title but swap with name if it's missing
388
+ t.item.title = t.item.title || t.item.name;
389
+ /* istanbul ignore else */
390
+ if (!(0, trackingHelpers_1.isTrackingViewTemplate)(t)) {
391
+ // Need to set the service name: name + "_" + newItemId
392
+ let baseName = t.item.name || t.item.title;
393
+ // If the name already contains a GUID remove it
394
+ baseName = baseName.replace(/_[0-9A-F]{32}/gi, "");
395
+ // The name length limit is 98
396
+ // Limit the baseName to 50 characters before the _<guid>
397
+ const name = baseName.substring(0, 50) + "_" + solutionItemId;
398
+ // If the name + GUID already exists then append "_occurrenceCount"
399
+ t.item.name =
400
+ names.indexOf(name) === -1
401
+ ? name
402
+ : `${name}_${names.filter(n => n === name).length}`;
403
+ names.push(name);
404
+ }
405
+ }
406
+ return t;
407
+ });
408
+ }
409
+ exports.setNamesAndTitles = setNamesAndTitles;
410
+ /**
411
+ * This is used when deploying views.
412
+ * We need to update fields referenced in adminLayerInfo for relationships prior to deploying the view.
413
+ * This moves the fieldInfos for the views source layers from the item settings for the source layer
414
+ * to the item settings for the view.
415
+ *
416
+ * @param itemTemplate The current itemTemplate being processed.
417
+ * @param settings The settings object used to de-templatize the various templates within the item.
418
+ */
419
+ function updateSettingsFieldInfos(itemTemplate, settings) {
420
+ const dependencies = itemTemplate.dependencies;
421
+ const id = itemTemplate.itemId;
422
+ const settingsKeys = Object.keys(settings);
423
+ settingsKeys.forEach((k) => {
424
+ if (id === settings[k].itemId) {
425
+ dependencies.forEach((d) => {
426
+ settingsKeys.forEach((_k) => {
427
+ /* istanbul ignore else */
428
+ if (d === _k) {
429
+ // combine for multi-source views
430
+ const fieldInfos = {};
431
+ fieldInfos[d] = (0, generalHelpers_1.getProp)(settings[_k], "fieldInfos");
432
+ settings[k]["sourceServiceFields"] = settings[k]["sourceServiceFields"]
433
+ ? { ...settings[k]["sourceServiceFields"], ...fieldInfos }
434
+ : fieldInfos;
435
+ const layerKeys = Object.keys(settings[_k]);
436
+ layerKeys.forEach(layerKey => {
437
+ /* istanbul ignore else */
438
+ if (layerKey.startsWith("layer")) {
439
+ settings[k][layerKey] = settings[_k][layerKey];
440
+ }
441
+ });
442
+ }
443
+ });
444
+ });
445
+ }
446
+ });
447
+ }
448
+ exports.updateSettingsFieldInfos = updateSettingsFieldInfos;
449
+ /**
450
+ * Add flag to indicate item should be ignored.
451
+ * Construct template dictionary to detemplatize any references to this item by other items.
452
+ *
453
+ * @param template Template for feature service item
454
+ * @param authentication Credentials for the request
455
+ * @returns A promise that will resolve when template has been updated
456
+ * @private
457
+ */
458
+ function updateTemplateForInvalidDesignations(template, authentication) {
459
+ return new Promise((resolve, reject) => {
460
+ template.properties.hasInvalidDesignations = true;
461
+ if (template.item.url) {
462
+ // get the admin URL
463
+ const url = template.item.url;
464
+ (0, restHelpers_1.rest_request)(url + "?f=json", {
465
+ authentication: authentication
466
+ }).then(serviceData => {
467
+ const layerInfos = {};
468
+ const layersAndTables = (serviceData.layers || []).concat(serviceData.tables || []);
469
+ layersAndTables.forEach((l) => {
470
+ /* istanbul ignore else */
471
+ if (l && l.hasOwnProperty("id")) {
472
+ layerInfos[l.id] = l;
473
+ }
474
+ });
475
+ template.data[template.itemId] = Object.assign({
476
+ itemId: template.itemId
477
+ }, getLayerSettings(layerInfos, url, template.itemId));
478
+ resolve(template);
479
+ }, e => reject((0, generalHelpers_1.fail)(e)));
480
+ }
481
+ else {
482
+ resolve(template);
483
+ }
484
+ });
485
+ }
486
+ exports.updateTemplateForInvalidDesignations = updateTemplateForInvalidDesignations;
487
+ /**
488
+ * Get the contingent values for each layer in the service.
489
+ * Remove key props that cannot be included with the addToDef call on deploy.
490
+ * Store the values alongside other key feature service properties in the template
491
+ *
492
+ * @param properties the current feature services properties
493
+ * @param adminUrl the current feature service url
494
+ * @param authentication Credentials for the request to AGOL
495
+ * @returns A promise that will resolve when the contingent values have been fetched.
496
+ * This function will update the provided properties argument when contingent values are found.
497
+ */
498
+ function processContingentValues(properties, adminUrl, authentication) {
499
+ return new Promise((resolve, reject) => {
500
+ if ((0, generalHelpers_1.getProp)(properties, 'service.isView')) {
501
+ // views will inherit from the source service
502
+ resolve();
503
+ }
504
+ else {
505
+ const layersAndTables = (properties.layers || []).concat(properties.tables || []);
506
+ const layerIds = [];
507
+ const contingentValuePromises = layersAndTables.reduce((prev, cur) => {
508
+ /* istanbul ignore else */
509
+ if (cur.hasContingentValuesDefinition) {
510
+ prev.push((0, restHelpers_1.rest_request)(`${adminUrl}/${cur['id']}/contingentValues?f=json`, { authentication }));
511
+ layerIds.push(cur['id']);
512
+ }
513
+ return prev;
514
+ }, []);
515
+ if (contingentValuePromises.length > 0) {
516
+ Promise.all(contingentValuePromises).then((results) => {
517
+ const contingentValues = {};
518
+ results.forEach((r, i) => {
519
+ (0, generalHelpers_1.deleteProp)(r, 'typeCodes');
520
+ /* istanbul ignore else */
521
+ if ((0, generalHelpers_1.getProp)(r, 'stringDicts') && (0, generalHelpers_1.getProp)(r, 'contingentValuesDefinition')) {
522
+ r.contingentValuesDefinition['stringDicts'] = r.stringDicts;
523
+ (0, generalHelpers_1.deleteProp)(r, 'stringDicts');
524
+ }
525
+ (0, generalHelpers_1.deleteProps)((0, generalHelpers_1.getProp)(r, 'contingentValuesDefinition'), ['layerID', 'layerName', 'geometryType', 'hasSubType']);
526
+ contingentValues[layerIds[i]] = r;
527
+ });
528
+ properties.contingentValues = contingentValues;
529
+ resolve();
530
+ }, reject);
531
+ }
532
+ else {
533
+ resolve();
534
+ }
535
+ }
536
+ });
537
+ }
538
+ exports.processContingentValues = processContingentValues;
539
+ /**
540
+ * Replace the field name reference templates with the new field names after deployment.
541
+ *
542
+ * @param fieldInfos The object that stores the cached layer properties and name mapping
543
+ * @param popupInfos The object from the popupInfo property for the layer
544
+ * @param adminLayerInfos The object from the adminLayerInfo property for the layer
545
+ * @param settings The settings object that has all of the mappings for de-templatizing.
546
+ * @returns An object that contains updated instances of popupInfos, fieldInfos, and adminLayerInfos
547
+ */
548
+ function deTemplatizeFieldInfos(fieldInfos, popupInfos, adminLayerInfos, settings) {
549
+ const fieldInfoKeys = Object.keys(fieldInfos);
550
+ fieldInfoKeys.forEach(id => {
551
+ if (fieldInfos[id].hasOwnProperty("templates")) {
552
+ fieldInfos[id].templates = JSON.parse((0, templatization_1.replaceInTemplate)(JSON.stringify(fieldInfos[id].templates), settings));
553
+ }
554
+ if (fieldInfos[id].hasOwnProperty("adminLayerInfo")) {
555
+ adminLayerInfos[id].viewLayerDefinition.table.relatedTables =
556
+ fieldInfos[id].adminLayerInfo;
557
+ (0, generalHelpers_1.deleteProp)(fieldInfos[id], "adminLayerInfo");
558
+ }
559
+ if (fieldInfos[id].hasOwnProperty("types")) {
560
+ fieldInfos[id].types = JSON.parse((0, templatization_1.replaceInTemplate)(JSON.stringify(fieldInfos[id].types), settings));
561
+ }
562
+ });
563
+ return {
564
+ popupInfos: (0, templatization_1.replaceInTemplate)(popupInfos, settings),
565
+ fieldInfos: (0, templatization_1.replaceInTemplate)(fieldInfos, settings),
566
+ adminLayerInfos: (0, templatization_1.replaceInTemplate)(adminLayerInfos, settings)
567
+ };
568
+ }
569
+ exports.deTemplatizeFieldInfos = deTemplatizeFieldInfos;
570
+ /**
571
+ * This is used when deploying views.
572
+ * We need to update fields referenced in adminLayerInfo for relationships prior to deploying the view.
573
+ * This moves the fieldInfos for the views source layers from the item settings for the source layer
574
+ * to the item settings for the view.
575
+ *
576
+ * @param itemTemplate The current itemTemplate being processed.
577
+ * @returns array of layers and tables
578
+ */
579
+ function getLayersAndTables(itemTemplate) {
580
+ const properties = itemTemplate.properties;
581
+ const layersAndTables = [];
582
+ (properties.layers || []).forEach(function (layer) {
583
+ layersAndTables.push({
584
+ item: layer,
585
+ type: "layer"
586
+ });
587
+ });
588
+ (properties.tables || []).forEach(function (table) {
589
+ layersAndTables.push({
590
+ item: table,
591
+ type: "table"
592
+ });
593
+ });
594
+ return layersAndTables;
595
+ }
596
+ exports.getLayersAndTables = getLayersAndTables;
597
+ /**
598
+ * Fetch each layer and table from service so we can determine what fields they have.
599
+ * This is leveraged when we are using existing services so we can determine if we need to
600
+ * remove any fields from views that depend on these layers and tables.
601
+ *
602
+ * @param url Feature service endpoint
603
+ * @param ids layer and table ids
604
+ * @param authentication Credentials for the request
605
+ * @returns A promise that will resolve an array of promises with either a failure or the data
606
+ * @private
607
+ */
608
+ function getExistingLayersAndTables(url, ids, authentication) {
609
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
610
+ return new Promise(resolve => {
611
+ const defs = ids.map(id => {
612
+ return (0, restHelpers_1.rest_request)((0, generalHelpers_1.checkUrlPathTermination)(url) + id, {
613
+ authentication
614
+ });
615
+ });
616
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
617
+ Promise.all(defs.map(p => p.catch(e => e))).then(resolve);
618
+ });
619
+ }
620
+ exports.getExistingLayersAndTables = getExistingLayersAndTables;
621
+ /**
622
+ * Adds the layers and tables of a feature service to it and restores their relationships.
623
+ *
624
+ * @param itemTemplate Feature service
625
+ * @param templateDictionary Hash mapping Solution source id to id of its clone (and name & URL for feature
626
+ * service)
627
+ * @param popupInfos the cached popup info from the layers
628
+ * @param authentication Credentials for the request
629
+ * @returns A promise that will resolve when all layers and tables have been added
630
+ * @private
631
+ */
632
+ function addFeatureServiceLayersAndTables(itemTemplate, templateDictionary, popupInfos, authentication) {
633
+ return new Promise((resolve, reject) => {
634
+ if ((0, trackingHelpers_1.isTrackingViewTemplate)(itemTemplate)) {
635
+ resolve(null);
636
+ }
637
+ else {
638
+ // Create a hash of various properties that contain field references
639
+ const fieldInfos = {};
640
+ const adminLayerInfos = {};
641
+ // Add the service's layers and tables to it
642
+ const layersAndTables = getLayersAndTables(itemTemplate);
643
+ if (layersAndTables.length > 0) {
644
+ addFeatureServiceDefinition(itemTemplate.item.url || "", layersAndTables, templateDictionary, authentication, itemTemplate.key, adminLayerInfos, fieldInfos, itemTemplate).then(() => {
645
+ // Detemplatize field references and update the layer properties
646
+ // Only failure path is handled by addFeatureServiceDefinition
647
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
648
+ updateLayerFieldReferences(itemTemplate, fieldInfos, popupInfos, adminLayerInfos, templateDictionary).then(r => {
649
+ // Update relationships and layer definitions
650
+ const updates = (0, restHelpers_1.getLayerUpdates)({
651
+ message: "updated layer definition",
652
+ objects: r.layerInfos.fieldInfos,
653
+ itemTemplate: r.itemTemplate,
654
+ authentication
655
+ }, templateDictionary.isPortal);
656
+ // Process the updates sequentially
657
+ updates
658
+ .reduce((prev, update) => {
659
+ return prev.then(() => {
660
+ return (0, restHelpers_1.getRequest)(update);
661
+ });
662
+ }, Promise.resolve(null))
663
+ .then(() => resolve(null), (e) => reject((0, generalHelpers_1.fail)(e)) // getRequest
664
+ );
665
+ });
666
+ }, e => reject((0, generalHelpers_1.fail)(e)) // addFeatureServiceDefinition
667
+ );
668
+ }
669
+ else {
670
+ resolve(null);
671
+ }
672
+ }
673
+ });
674
+ }
675
+ exports.addFeatureServiceLayersAndTables = addFeatureServiceLayersAndTables;
676
+ /**
677
+ * Updates a feature service with a list of layers and/or tables.
678
+ *
679
+ * @param serviceUrl URL of feature service
680
+ * @param listToAdd List of layers and/or tables to add
681
+ * @param templateDictionary Hash mapping Solution source id to id of its clone (and name & URL for feature
682
+ * service)
683
+ * @param authentication Credentials for the request
684
+ * @param key
685
+ * @param adminLayerInfos Hash map of a layers adminLayerInfo
686
+ * @param fieldInfos Hash map of properties that contain field references
687
+ * @param itemTemplate
688
+ * @returns A promise that will resolve when the feature service has been updated
689
+ * @private
690
+ */
691
+ function addFeatureServiceDefinition(serviceUrl, listToAdd, templateDictionary, authentication, key, adminLayerInfos, fieldInfos, itemTemplate) {
692
+ return new Promise((resolve, reject) => {
693
+ if ((0, trackingHelpers_1.isTrackingViewTemplate)(itemTemplate)) {
694
+ resolve(null);
695
+ }
696
+ else {
697
+ let options = {
698
+ layers: [],
699
+ tables: [],
700
+ authentication
701
+ };
702
+ // if the service has veiws keep track of the fields so we can use them to
703
+ // compare with the view fields
704
+ /* istanbul ignore else */
705
+ if ((0, generalHelpers_1.getProp)(itemTemplate, "properties.service.hasViews")) {
706
+ _updateTemplateDictionaryFields(itemTemplate, templateDictionary);
707
+ }
708
+ const isSelfReferential = _isSelfReferential(listToAdd);
709
+ listToAdd = _updateOrder(listToAdd, isSelfReferential);
710
+ const chunkSize = _getLayerChunkSize();
711
+ const layerChunks = [];
712
+ listToAdd.forEach((toAdd, i) => {
713
+ let item = toAdd.item;
714
+ const originalId = item.id;
715
+ fieldInfos = cacheFieldInfos(item, fieldInfos);
716
+ // cache the values to be added in seperate addToDef calls
717
+ fieldInfos = cacheContingentValues(item.id, fieldInfos, itemTemplate);
718
+ /* istanbul ignore else */
719
+ if (item.isView) {
720
+ deleteViewProps(item);
721
+ }
722
+ // when the item is a view we need to grab the supporting fieldInfos
723
+ /* istanbul ignore else */
724
+ if (itemTemplate.properties.service.isView) {
725
+ _updateGeomFieldName(item.adminLayerInfo, templateDictionary);
726
+ adminLayerInfos[originalId] = item.adminLayerInfo;
727
+ // need to update adminLayerInfo before adding to the service def
728
+ // bring over the fieldInfos from the source layer
729
+ updateSettingsFieldInfos(itemTemplate, templateDictionary);
730
+ // update adminLayerInfo before add to definition with view source fieldInfo settings
731
+ item.adminLayerInfo = (0, templatization_1.replaceInTemplate)(item.adminLayerInfo, templateDictionary);
732
+ /* istanbul ignore else */
733
+ if (fieldInfos && fieldInfos.hasOwnProperty(item.id)) {
734
+ Object.keys(templateDictionary).some(k => {
735
+ if (templateDictionary[k].itemId === itemTemplate.itemId) {
736
+ fieldInfos[item.id]["sourceServiceFields"] =
737
+ templateDictionary[k].sourceServiceFields;
738
+ return true;
739
+ }
740
+ else {
741
+ return false;
742
+ }
743
+ });
744
+ }
745
+ }
746
+ /* istanbul ignore else */
747
+ if (templateDictionary.isPortal) {
748
+ item = _updateForPortal(item, itemTemplate, templateDictionary);
749
+ }
750
+ removeLayerOptimization(item);
751
+ // this can still chunk layers
752
+ options = _updateAddOptions(itemTemplate, options, layerChunks, isSelfReferential, authentication);
753
+ if (item.type === "Feature Layer") {
754
+ options.layers.push(item);
755
+ }
756
+ else {
757
+ options.tables.push(item);
758
+ }
759
+ // In general we are switching to not use chunking. Rather if we exceed the defined chunk size
760
+ // we will use an async request.
761
+ // Currently the only case that should chunk the requests is when we have a multisource view
762
+ // handled in _updateAddOptions above
763
+ /* istanbul ignore else */
764
+ if (i + 1 === listToAdd.length) {
765
+ layerChunks.push(Object.assign({}, options));
766
+ options = {
767
+ layers: [],
768
+ tables: [],
769
+ authentication
770
+ };
771
+ }
772
+ });
773
+ // will use async by default rather than chunk the layer requests when we have more layers
774
+ // than the defined chunk size
775
+ const useAsync = listToAdd.length > chunkSize;
776
+ layerChunks
777
+ .reduce((prev, curr) => prev.then(() => (0, restHelpers_1.addToServiceDefinition)(serviceUrl, curr, false, useAsync)), Promise.resolve(null))
778
+ .then(() => resolve(null), (e) => reject((0, generalHelpers_1.fail)(e)));
779
+ }
780
+ });
781
+ }
782
+ exports.addFeatureServiceDefinition = addFeatureServiceDefinition;
783
+ /**
784
+ * When a view is a multi service view sort based on the id
785
+ * https://github.com/Esri/solution.js/issues/1048
786
+ *
787
+ * @param layersAndTables The list of layers and tables for the current template
788
+ * @param isSelfReferential Indicates if any layers or tables have relationships with other layers or tables in the same service
789
+ *
790
+ * @returns Sorted list of layers and tables when using a multi-service view
791
+ * @private
792
+ */
793
+ function _updateOrder(layersAndTables, isSelfReferential) {
794
+ return isSelfReferential ? layersAndTables.sort((a, b) => a.item.id - b.item.id) : layersAndTables;
795
+ }
796
+ exports._updateOrder = _updateOrder;
797
+ /**
798
+ * When a view is a multi service view add each layer separately
799
+ * https://github.com/Esri/solution.js/issues/871
800
+ *
801
+ * @param itemTemplate The current itemTemplate being processed
802
+ * @param options Add to service definition options
803
+ * @param layerChunks Groups of layers or tables to add to the service
804
+ * @param isSelfReferential Indicates if any layers or tables have relationships with other layers or tables in the same service
805
+ * @param authentication Credentials for the request
806
+ *
807
+ * @returns Add to service definition options
808
+ * @private
809
+ */
810
+ function _updateAddOptions(itemTemplate, options, layerChunks, isSelfReferential, authentication) {
811
+ const isMsView = (0, generalHelpers_1.getProp)(itemTemplate, "properties.service.isMultiServicesView") || false;
812
+ /* istanbul ignore else */
813
+ if (isMsView || isSelfReferential) {
814
+ // if we already have some layers or tables add them first
815
+ /* istanbul ignore else */
816
+ if (options.layers.length > 0 || options.tables.length > 0) {
817
+ layerChunks.push(Object.assign({}, options));
818
+ options = {
819
+ layers: [],
820
+ tables: [],
821
+ authentication
822
+ };
823
+ }
824
+ }
825
+ return options;
826
+ }
827
+ exports._updateAddOptions = _updateAddOptions;
828
+ /**
829
+ * Determine if any layer or table within the service references
830
+ * other layers or tables within the same service
831
+ *
832
+ * @param layersAndTables the list of layers and tables from the service
833
+ *
834
+ * @returns true when valid internal references are found
835
+ * @private
836
+ */
837
+ function _isSelfReferential(layersAndTables) {
838
+ const names = layersAndTables.map(l => l.item.name);
839
+ const srcTables = {};
840
+ return layersAndTables.some(l => {
841
+ const table = l.item.adminLayerInfo?.viewLayerDefinition?.table;
842
+ if (table) {
843
+ const name = table.sourceServiceName;
844
+ const id = table.sourceLayerId;
845
+ if (name && id > -1) {
846
+ if (Object.keys(srcTables).indexOf(name) > -1) {
847
+ if (srcTables[name].indexOf(id) > -1) {
848
+ return true;
849
+ }
850
+ else {
851
+ srcTables[name].push(id);
852
+ }
853
+ }
854
+ else {
855
+ srcTables[name] = [id];
856
+ }
857
+ }
858
+ return (table.relatedTables || []).some(r => names.indexOf(r.name) > -1);
859
+ }
860
+ });
861
+ }
862
+ exports._isSelfReferential = _isSelfReferential;
863
+ /**
864
+ * Remove "multiScaleGeometryInfo" for issue #526 to prevent invalid enablement of layer optimization
865
+ *
866
+ * @param layer the layer to evaluate
867
+ * @private
868
+ */
869
+ function removeLayerOptimization(layer) {
870
+ /* istanbul ignore else */
871
+ if (layer.multiScaleGeometryInfo) {
872
+ (0, generalHelpers_1.deleteProp)(layer, "multiScaleGeometryInfo");
873
+ }
874
+ }
875
+ exports.removeLayerOptimization = removeLayerOptimization;
876
+ /**
877
+ * Handle portal specific updates to the item
878
+ *
879
+ * @param item the item to update
880
+ * @param itemTemplate the item template
881
+ * @param templateDictionary Hash mapping Solution source id to id of its clone
882
+ *
883
+ * @returns the updated item
884
+ * @private
885
+ */
886
+ function _updateForPortal(item, itemTemplate, templateDictionary) {
887
+ // When deploying to portal we need to adjust the uniquie ID field up front
888
+ /* istanbul ignore else */
889
+ if (item.uniqueIdField && item.uniqueIdField.name) {
890
+ item.uniqueIdField.name = String(item.uniqueIdField.name).toLocaleLowerCase();
891
+ }
892
+ // Portal will fail if the geometryField is null
893
+ if (item.type === "Table" && item.adminLayerInfo) {
894
+ (0, generalHelpers_1.deleteProp)(item.adminLayerInfo, "geometryField");
895
+ }
896
+ // Portal will fail if the sourceFields in the viewLayerDef contain fields that are not in the source service
897
+ /* istanbul ignore else */
898
+ if (item.isView) {
899
+ const viewLayerDefTable = (0, generalHelpers_1.getProp)(item, "adminLayerInfo.viewLayerDefinition.table");
900
+ let fieldNames = [];
901
+ if (viewLayerDefTable) {
902
+ const tableFieldNames = _getFieldNames(viewLayerDefTable, itemTemplate, templateDictionary);
903
+ fieldNames = fieldNames.concat(tableFieldNames);
904
+ const dynamicFieldNames = _getDynamicFieldNames(viewLayerDefTable);
905
+ fieldNames = fieldNames.concat(dynamicFieldNames);
906
+ (0, generalHelpers_1.setProp)(item, "adminLayerInfo.viewLayerDefinition.table", _updateSourceLayerFields(viewLayerDefTable, fieldNames));
907
+ // Handle related also
908
+ /* istanbul ignore else */
909
+ if (Array.isArray(viewLayerDefTable.relatedTables)) {
910
+ viewLayerDefTable.relatedTables.map((relatedTable) => {
911
+ const relatedTableFieldNames = _getFieldNames(relatedTable, itemTemplate, templateDictionary);
912
+ fieldNames = fieldNames.concat(relatedTableFieldNames);
913
+ const dynamicRelatedFieldNames = _getDynamicFieldNames(relatedTable);
914
+ fieldNames = fieldNames.concat(dynamicRelatedFieldNames);
915
+ return _updateSourceLayerFields(relatedTable, [...relatedTableFieldNames, ...dynamicRelatedFieldNames]);
916
+ });
917
+ }
918
+ }
919
+ else {
920
+ Object.keys(templateDictionary).some(k => {
921
+ /* istanbul ignore else */
922
+ if (templateDictionary[k].itemId === item.serviceItemId) {
923
+ const layerInfo = templateDictionary[k][`layer${item.id}`];
924
+ /* istanbul ignore else */
925
+ if (layerInfo && layerInfo.fields) {
926
+ if (Array.isArray(layerInfo.fields)) {
927
+ fieldNames = layerInfo.fields.map((f) => f.name);
928
+ }
929
+ else {
930
+ fieldNames = Object.keys(layerInfo.fields);
931
+ }
932
+ }
933
+ return true;
934
+ }
935
+ });
936
+ }
937
+ item = _updateItemFields(item, fieldNames);
938
+ }
939
+ // not allowed to set sourceSchemaChangesAllowed or isView for portal
940
+ // these are set when you create the service
941
+ (0, generalHelpers_1.deleteProp)(item, "isView");
942
+ return item;
943
+ }
944
+ exports._updateForPortal = _updateForPortal;
945
+ /**
946
+ * Get a list of the source layer field names
947
+ *
948
+ * @param table the table instance to compare
949
+ * @param itemTemplate the item template
950
+ * @param templateDictionary Hash mapping Solution source id to id of its clone
951
+ *
952
+ * @returns an array of the source layers fields
953
+ * @private
954
+ */
955
+ function _getFieldNames(table, itemTemplate, templateDictionary) {
956
+ let sourceLayerFields = [];
957
+ const viewSourceLayerId = table.sourceLayerId;
958
+ /* istanbul ignore else */
959
+ if (typeof viewSourceLayerId === "number") {
960
+ // need to make sure these actually exist in the source..
961
+ itemTemplate.dependencies.forEach(d => {
962
+ const layerInfo = templateDictionary[d][`layer${viewSourceLayerId}`];
963
+ /* istanbul ignore else */
964
+ if (layerInfo &&
965
+ layerInfo.fields &&
966
+ templateDictionary[d].name === table.sourceServiceName) {
967
+ if (Array.isArray(layerInfo.fields)) {
968
+ sourceLayerFields = sourceLayerFields.concat(layerInfo.fields.map((f) => f.name));
969
+ }
970
+ else {
971
+ sourceLayerFields = sourceLayerFields.concat(Object.keys(layerInfo.fields));
972
+ }
973
+ }
974
+ });
975
+ return sourceLayerFields;
976
+ }
977
+ }
978
+ exports._getFieldNames = _getFieldNames;
979
+ /**
980
+ * Get a list of any dynamically calculated fields
981
+ * These fields are still valid but will not exist in the source service
982
+ *
983
+ * @param table the table instance to compare
984
+ *
985
+ * @returns an array of field names
986
+ * @private
987
+ */
988
+ function _getDynamicFieldNames(table) {
989
+ const fieldNames = table.sourceLayerFields.reduce((prev, cur) => {
990
+ if (cur.statisticType) {
991
+ prev.push(cur.name);
992
+ }
993
+ return prev;
994
+ }, []);
995
+ return [...new Set(fieldNames)];
996
+ }
997
+ exports._getDynamicFieldNames = _getDynamicFieldNames;
998
+ /**
999
+ * Remove fields references from fields and indexes that do not exist in the source service
1000
+ *
1001
+ * @param item Layer or table
1002
+ * @param templateDictionary Hash mapping Solution source id to id of its clone
1003
+ *
1004
+ * @returns updated layer or table
1005
+ * @private
1006
+ */
1007
+ function _updateItemFields(item, fieldNames) {
1008
+ /* istanbul ignore else */
1009
+ if (fieldNames.length > 0) {
1010
+ /* istanbul ignore else */
1011
+ if (item.fields) {
1012
+ item.fields = item.fields.filter((f) => fieldNames.indexOf(f.name) > -1);
1013
+ }
1014
+ /* istanbul ignore else */
1015
+ if (item.indexes) {
1016
+ item.indexes = item.indexes.filter((f) => fieldNames.indexOf(f.fields) > -1);
1017
+ }
1018
+ }
1019
+ return item;
1020
+ }
1021
+ exports._updateItemFields = _updateItemFields;
1022
+ /**
1023
+ * Filter the sourceLayerFields for the table
1024
+ *
1025
+ * @param table the table instance to evaluate
1026
+ * @param sourceLayerFields array of fields from the source service
1027
+ * @returns Updated instance of the table
1028
+ * @private
1029
+ */
1030
+ function _updateSourceLayerFields(table, sourceLayerFields) {
1031
+ /* istanbul ignore else */
1032
+ if (Array.isArray(table.sourceLayerFields) &&
1033
+ table.sourceLayerFields.length > 0) {
1034
+ // need to make sure these actually exist in the source..
1035
+ /* istanbul ignore else */
1036
+ if (sourceLayerFields.length > 0) {
1037
+ (0, generalHelpers_1.setProp)(table, "sourceLayerFields", table.sourceLayerFields.filter((f) => sourceLayerFields.indexOf(f.source.toLowerCase()) > -1));
1038
+ }
1039
+ }
1040
+ return table;
1041
+ }
1042
+ exports._updateSourceLayerFields = _updateSourceLayerFields;
1043
+ /**
1044
+ * When the itemm is a view with a geometry field update the value to
1045
+ * use the table name from the view layer def
1046
+ *
1047
+ * @param item the item details from the current template
1048
+ * @param templateDictionary Hash mapping property names to replacement values
1049
+ * @private
1050
+ */
1051
+ function _updateGeomFieldName(adminLayerInfo, templateDictionary) {
1052
+ // issue #471
1053
+ const tableName = (0, generalHelpers_1.getProp)(adminLayerInfo, "viewLayerDefinition.table.name");
1054
+ const fieldName = (0, generalHelpers_1.getProp)(adminLayerInfo, "geometryField.name");
1055
+ /* istanbul ignore else */
1056
+ if (fieldName && tableName) {
1057
+ const geomName = templateDictionary.isPortal
1058
+ ? `${tableName}.shape`
1059
+ : `${tableName}.Shape`;
1060
+ (0, generalHelpers_1.setProp)(adminLayerInfo, "geometryField.name", geomName);
1061
+ }
1062
+ else if (!fieldName && (0, generalHelpers_1.getProp)(adminLayerInfo, "geometryField")) {
1063
+ // null geom field will cause failure to deploy in portal
1064
+ // this is also checked and removed on deploy for older solutions
1065
+ (0, generalHelpers_1.deleteProp)(adminLayerInfo, "geometryField");
1066
+ }
1067
+ }
1068
+ exports._updateGeomFieldName = _updateGeomFieldName;
1069
+ /**
1070
+ * Add the fields to the templateDictionary when a service has views
1071
+ * these are used to compare with fields from the view when domains are involved
1072
+ * when a view field has a domain that differs from that of the source service
1073
+ * the definition needs to be modified in an update call rather than when it is first added.
1074
+ * This should only happen when the domain differs.
1075
+ *
1076
+ * @param itemTemplate
1077
+ * @param templateDictionary Hash mapping Solution source id to id of its clone (and name & URL for feature service)
1078
+ * @private
1079
+ */
1080
+ function _updateTemplateDictionaryFields(itemTemplate, templateDictionary, compareItemId = true) {
1081
+ const layers = itemTemplate.properties.layers;
1082
+ const tables = itemTemplate.properties.tables;
1083
+ const layersAndTables = layers.concat(tables);
1084
+ const fieldInfos = {};
1085
+ layersAndTables.forEach(layerOrTable => {
1086
+ fieldInfos[layerOrTable.id] = layerOrTable.fields;
1087
+ });
1088
+ Object.keys(templateDictionary).some(k => {
1089
+ if (compareItemId
1090
+ ? templateDictionary[k].itemId === itemTemplate.itemId
1091
+ : k === itemTemplate.itemId) {
1092
+ templateDictionary[k].fieldInfos = fieldInfos;
1093
+ return true;
1094
+ }
1095
+ else {
1096
+ return false;
1097
+ }
1098
+ });
1099
+ }
1100
+ exports._updateTemplateDictionaryFields = _updateTemplateDictionaryFields;
1101
+ /**
1102
+ * Set the defaultSpatialReference variable with the services spatial reference.
1103
+ * If this item is a Feature Service that has child views then we will use this value
1104
+ * if one or more of the child views spatial reference differs from that of its parent.
1105
+ *
1106
+ * @param templateDictionary Hash mapping Solution source id to id of its clone (and name & URL for feature service)
1107
+ * @param itemId The source id for the item
1108
+ * @param spatialReference \{ wkid: 102100 \} for example
1109
+ * @private
1110
+ */
1111
+ function setDefaultSpatialReference(templateDictionary, itemId, spatialReference) {
1112
+ /* istanbul ignore else */
1113
+ if (spatialReference) {
1114
+ (0, generalHelpers_1.setCreateProp)(templateDictionary, `${itemId}.defaultSpatialReference`, spatialReference);
1115
+ }
1116
+ }
1117
+ exports.setDefaultSpatialReference = setDefaultSpatialReference;
1118
+ /**
1119
+ * Compare the spatial reference of the current item against its dependencies.
1120
+ * The spatial reference of a view cannot differ from its source service.
1121
+ * If the view has a different spatial reference from its source use the source spatial reference.
1122
+ *
1123
+ * @param serviceInfo Basic service information
1124
+ * @param itemTemplate The current template to process
1125
+ * @param templateDictionary Hash mapping Solution source id to id of its clone (and name & URL for feature service)
1126
+ * @private
1127
+ */
1128
+ function validateSpatialReferenceAndExtent(serviceInfo, itemTemplate, templateDictionary) {
1129
+ /* istanbul ignore else */
1130
+ if ((0, generalHelpers_1.getProp)(serviceInfo, "service.isView")) {
1131
+ let sourceSR;
1132
+ let sourceExt;
1133
+ itemTemplate.dependencies.some(id => {
1134
+ const source = templateDictionary[id];
1135
+ const sr = (0, generalHelpers_1.getProp)(source, "defaultSpatialReference");
1136
+ /* istanbul ignore else */
1137
+ if (!sourceSR && sr) {
1138
+ sourceSR = sr;
1139
+ }
1140
+ const ext = (0, generalHelpers_1.getProp)(source, "defaultExtent");
1141
+ /* istanbul ignore else */
1142
+ if (!sourceExt && ext) {
1143
+ sourceExt = ext;
1144
+ }
1145
+ return sourceSR && sourceExt;
1146
+ });
1147
+ const sourceWkid = (0, generalHelpers_1.getProp)(sourceSR, "wkid");
1148
+ const viewWkid = (0, generalHelpers_1.getProp)(serviceInfo, "service.spatialReference.wkid");
1149
+ /* istanbul ignore else */
1150
+ if (sourceWkid && viewWkid && sourceWkid !== viewWkid) {
1151
+ (0, generalHelpers_1.setCreateProp)(serviceInfo, "service.spatialReference", sourceSR);
1152
+ }
1153
+ const viewExt = (0, generalHelpers_1.getProp)(serviceInfo, "service.fullExtent");
1154
+ /* istanbul ignore else */
1155
+ if (sourceExt &&
1156
+ viewExt &&
1157
+ JSON.stringify(sourceExt) !== JSON.stringify(viewExt)) {
1158
+ (0, generalHelpers_1.setCreateProp)(serviceInfo, "defaultExtent", sourceExt);
1159
+ }
1160
+ }
1161
+ }
1162
+ exports.validateSpatialReferenceAndExtent = validateSpatialReferenceAndExtent;
1163
+ /**
1164
+ * Updates a feature service with a list of layers and/or tables.
1165
+ *
1166
+ * @param itemTemplate
1167
+ * @param fieldInfos Hash map of properties that contain field references
1168
+ * @param popupInfos Hash map of a layers popupInfo
1169
+ * @param adminLayerInfos Hash map of a layers adminLayerInfo
1170
+ * @param templateDictionary Hash mapping Solution source id to id of its clone (and name & URL for feature service)
1171
+ * @param authentication Credentials for the request
1172
+ * @returns A promise that will resolve when the feature service has been updated
1173
+ * @private
1174
+ */
1175
+ function updateLayerFieldReferences(itemTemplate, fieldInfos, popupInfos, adminLayerInfos, templateDictionary) {
1176
+ return new Promise((resolveFn, rejectFn) => {
1177
+ // Will need to do some post processing for fields
1178
+ // to handle any potential field name changes when deploying to portal
1179
+ postProcessFields(itemTemplate, fieldInfos, popupInfos, adminLayerInfos, templateDictionary).then((layerInfos) => {
1180
+ // Update the items text with detemplatized popupInfo
1181
+ updatePopupInfo(itemTemplate, layerInfos.popupInfos);
1182
+ resolveFn({
1183
+ itemTemplate,
1184
+ layerInfos
1185
+ });
1186
+ }, e => rejectFn((0, generalHelpers_1.fail)(e)));
1187
+ });
1188
+ }
1189
+ exports.updateLayerFieldReferences = updateLayerFieldReferences;
1190
+ /**
1191
+ * Update the names of fields for each layer or table after it has been
1192
+ * added to the definition
1193
+ *
1194
+ * @param itemTemplate Item to be created
1195
+ * @param layerInfos Hash map of properties that contain field references and various layer info
1196
+ * @param popupInfos Hash map of a layers popupInfo
1197
+ * @param adminLayerInfos Hash map of a layers adminLayerInfo
1198
+ * @param templateDictionary
1199
+ * @param authentication Credentials for the request
1200
+ * @returns An object with detemplatized field references
1201
+ * @private
1202
+ */
1203
+ function postProcessFields(itemTemplate, layerInfos, popupInfos, adminLayerInfos, templateDictionary) {
1204
+ return new Promise((resolveFn, rejectFn) => {
1205
+ if (!itemTemplate.item.url) {
1206
+ rejectFn((0, generalHelpers_1.fail)("Feature layer " + itemTemplate.itemId + " does not have a URL"));
1207
+ }
1208
+ else {
1209
+ const id = itemTemplate.itemId;
1210
+ const settingsKeys = Object.keys(templateDictionary);
1211
+ let templateInfo;
1212
+ settingsKeys.some(k => {
1213
+ if (templateDictionary[k].itemId === id) {
1214
+ templateInfo = templateDictionary[k];
1215
+ return true;
1216
+ }
1217
+ else {
1218
+ return false;
1219
+ }
1220
+ });
1221
+ // concat any layers and tables to process
1222
+ const layers = itemTemplate.properties.layers;
1223
+ const tables = itemTemplate.properties.tables;
1224
+ const layersAndTables = layers.concat(tables);
1225
+ // Set the newFields property for the layerInfos...this will contain all fields
1226
+ // as they are after being added to the definition.
1227
+ // This allows us to handle any potential field name changes after deploy to portal
1228
+ layersAndTables.forEach((item) => {
1229
+ // when deploying to portal "isView" is only set for create service and will fail when
1230
+ // present on addToDef so this property is removed from item and we should check the templates service info
1231
+ const isView = item.isView || itemTemplate.properties.service.isView;
1232
+ /* istanbul ignore else */
1233
+ if (layerInfos && layerInfos.hasOwnProperty(item.id)) {
1234
+ const layerInfo = layerInfos[item.id];
1235
+ layerInfo["isView"] = item.isView;
1236
+ layerInfo["newFields"] = item.fields;
1237
+ layerInfo["sourceSchemaChangesAllowed"] =
1238
+ item.sourceSchemaChangesAllowed;
1239
+ /* istanbul ignore else */
1240
+ if (item.editFieldsInfo) {
1241
+ // more than case change when deployed to protal so keep track of the new names
1242
+ layerInfo["newEditFieldsInfo"] = JSON.parse(JSON.stringify(item.editFieldsInfo));
1243
+ }
1244
+ /* istanbul ignore else */
1245
+ if (isView && templateInfo && templateDictionary.isPortal) {
1246
+ // when the item is a view bring over the source service fields so we can compare the domains
1247
+ layerInfo["sourceServiceFields"] = templateInfo.sourceServiceFields;
1248
+ }
1249
+ }
1250
+ });
1251
+ // Add the layerInfos to the settings object to be used while detemplatizing
1252
+ settingsKeys.forEach((k) => {
1253
+ if (id === templateDictionary[k].itemId) {
1254
+ templateDictionary[k] = Object.assign(templateDictionary[k], getLayerSettings(layerInfos, templateDictionary[k].url, id));
1255
+ }
1256
+ });
1257
+ // update the layerInfos object with current field names
1258
+ resolveFn(deTemplatizeFieldInfos(layerInfos, popupInfos, adminLayerInfos, templateDictionary));
1259
+ }
1260
+ });
1261
+ }
1262
+ exports.postProcessFields = postProcessFields;
1263
+ /**
1264
+ * Add popup info back to the layer item
1265
+ *
1266
+ * @param itemTemplate
1267
+ * @param popupInfos popup info to be added back to the layer
1268
+ * @private
1269
+ */
1270
+ function updatePopupInfo(itemTemplate, popupInfos) {
1271
+ ["layers", "tables"].forEach(type => {
1272
+ const _items = (0, generalHelpers_1.getProp)(itemTemplate, "data." + type);
1273
+ /* istanbul ignore else */
1274
+ if (_items && Array.isArray(_items)) {
1275
+ _items.forEach((item) => {
1276
+ item.popupInfo = (0, generalHelpers_1.getProp)(popupInfos, type + "." + item.id) || {};
1277
+ });
1278
+ }
1279
+ });
1280
+ }
1281
+ exports.updatePopupInfo = updatePopupInfo;
1282
+ //#endregion
1283
+ //#region Private helper functions --------------------------------------------------//
1284
+ /**
1285
+ * Helper function to templatize value and make sure its converted to lowercase
1286
+ *
1287
+ * @param basePath path used to de-templatize while deploying
1288
+ * @param value to be converted to lower case for lookup while deploying
1289
+ * @private
1290
+ */
1291
+ function _templatize(basePath, value, suffix) {
1292
+ if (value.startsWith("{{")) {
1293
+ return value;
1294
+ }
1295
+ else {
1296
+ return String((0, templatization_1.templatizeTerm)(basePath, basePath, "." + String(value).toLowerCase() + (suffix ? "." + suffix : "")));
1297
+ }
1298
+ }
1299
+ exports._templatize = _templatize;
1300
+ /**
1301
+ * templatize an objects property
1302
+ *
1303
+ * @param object the object with the property to templatize
1304
+ * @param property the property of the object to templatize
1305
+ * @param basePath path used to de-templatize while deploying
1306
+ * @private
1307
+ */
1308
+ function _templatizeProperty(object, property, basePath, suffix) {
1309
+ if (object && object.hasOwnProperty(property) && object[property]) {
1310
+ object[property] = _templatize(basePath, object[property], suffix);
1311
+ }
1312
+ }
1313
+ exports._templatizeProperty = _templatizeProperty;
1314
+ /**
1315
+ * Templatize field references, serviceItemId, and adminLayerInfo for a layer
1316
+ *
1317
+ * @param dataItem from the items data property
1318
+ * @param adminItem from the services admin api
1319
+ * @param itemTemplate Template for feature service item
1320
+ * @param dependencies Array of IDependency for name mapping
1321
+ * @param templatizeFieldReferences Templatize all field references within a layer
1322
+ * @returns A promise that will resolve when template has been updated
1323
+ * @private
1324
+ */
1325
+ function _templatizeLayer(dataItem, adminItem, itemTemplate, dependencies, templatizeFieldReferences, templateDictionary) {
1326
+ // check for and repair common field issues
1327
+ _validateFields(adminItem);
1328
+ // Templatize all properties that contain field references
1329
+ /* istanbul ignore else */
1330
+ if (templatizeFieldReferences) {
1331
+ _templatizeLayerFieldReferences(dataItem, itemTemplate.itemId, adminItem, dependencies);
1332
+ }
1333
+ const updates = [adminItem];
1334
+ if (dataItem) {
1335
+ updates.push(dataItem);
1336
+ }
1337
+ updates.forEach(update => {
1338
+ if (update.hasOwnProperty("name")) {
1339
+ // templatize the name but leave the current name as the optional default
1340
+ update.name = (0, templatization_1.templatizeTerm)(update["serviceItemId"] + ".layer" + update.id, update["serviceItemId"] + ".layer" + update.id, ".name||" + update.name);
1341
+ }
1342
+ if (update.hasOwnProperty("extent")) {
1343
+ update.extent = (0, templatization_1.templatizeTerm)(update["serviceItemId"], update["serviceItemId"], ".solutionExtent");
1344
+ }
1345
+ if (update.hasOwnProperty("serviceItemId")) {
1346
+ update["serviceItemId"] = (0, templatization_1.templatizeTerm)(update["serviceItemId"], update["serviceItemId"], ".itemId");
1347
+ }
1348
+ if (update.hasOwnProperty("adminLayerInfo")) {
1349
+ update.adminLayerInfo = _templatizeAdminLayerInfo(update, dependencies, templateDictionary);
1350
+ }
1351
+ });
1352
+ }
1353
+ exports._templatizeLayer = _templatizeLayer;
1354
+ /**
1355
+ * Repair common issues that can occur with feature service field references.
1356
+ * This function will mutate the input item if any of the common issues have occured.
1357
+ *
1358
+ * @param adminItem layer or table from the service
1359
+ */
1360
+ function _validateFields(adminItem) {
1361
+ const fieldNames = (adminItem.fields || []).map((f) => f.name);
1362
+ // Update primary display field if field isn't in the layer.
1363
+ _validateDisplayField(adminItem, fieldNames);
1364
+ // Remove indexes on fields that don't exist in the layer.
1365
+ // Remove duplicate indexes on the same field.
1366
+ _validateIndexes(adminItem, fieldNames);
1367
+ // Remove field references in templates when field doesn't exist in the layer.
1368
+ _validateTemplatesFields(adminItem, fieldNames);
1369
+ _validateTypesTemplates(adminItem, fieldNames);
1370
+ // Repair editFieldsInfo if field referenced doesn't exist in the layer
1371
+ _validateEditFieldsInfo(adminItem, fieldNames);
1372
+ }
1373
+ exports._validateFields = _validateFields;
1374
+ /**
1375
+ * Update primary display field if casing doesn't match.
1376
+ * Update primary display field to the first non OID or GlobalId if the field isn't in the layer.
1377
+ *
1378
+ * @param adminItem layer or table from the service
1379
+ * @param fieldNames string list of fields names
1380
+ * @private
1381
+ */
1382
+ function _validateDisplayField(adminItem, fieldNames) {
1383
+ const displayField = adminItem.displayField || "";
1384
+ let i = -1;
1385
+ if (fieldNames.some(name => {
1386
+ i += 1;
1387
+ return name === displayField || name === displayField.toLowerCase();
1388
+ })) {
1389
+ adminItem.displayField = fieldNames[i];
1390
+ }
1391
+ else {
1392
+ // use the first non-OID non-globalId field we find
1393
+ const skipFields = [];
1394
+ const oidField = (0, generalHelpers_1.getProp)(adminItem, "uniqueIdField.name");
1395
+ /* istanbul ignore else */
1396
+ if (oidField) {
1397
+ skipFields.push(oidField);
1398
+ }
1399
+ const globalIdField = (0, generalHelpers_1.getProp)(adminItem, "globalIdField");
1400
+ /* istanbul ignore else */
1401
+ if (globalIdField) {
1402
+ skipFields.push(globalIdField);
1403
+ }
1404
+ fieldNames.some(name => {
1405
+ if (skipFields.indexOf(name) === -1) {
1406
+ adminItem.displayField = name;
1407
+ return true;
1408
+ }
1409
+ else {
1410
+ return false;
1411
+ }
1412
+ });
1413
+ }
1414
+ }
1415
+ exports._validateDisplayField = _validateDisplayField;
1416
+ /**
1417
+ * Remove indexes on fields that don't exist in the layer.
1418
+ * Remove duplicate indexes on the same field.
1419
+ *
1420
+ * @param adminItem layer or table from the service
1421
+ * @param fieldNames string list of fields names
1422
+ * @private
1423
+ */
1424
+ function _validateIndexes(adminItem, fieldNames) {
1425
+ const indexes = adminItem.indexes;
1426
+ /* istanbul ignore else */
1427
+ if (indexes) {
1428
+ const indexedFields = [];
1429
+ adminItem.indexes = indexes.reduce((filtered, index) => {
1430
+ const indexFields = index.fields.split(",");
1431
+ const verifiedFields = [];
1432
+ indexFields.forEach(indexField => {
1433
+ /* istanbul ignore else */
1434
+ if (indexedFields.indexOf(indexField) === -1) {
1435
+ indexedFields.push(indexField);
1436
+ // this is the first index with this field and it should be added if the field exists
1437
+ /* istanbul ignore else */
1438
+ if (fieldNames.indexOf(indexField) > -1) {
1439
+ verifiedFields.push(indexField);
1440
+ }
1441
+ }
1442
+ // else the field has more than one index associated and should not be returned
1443
+ });
1444
+ /* istanbul ignore else */
1445
+ if (verifiedFields.length > 0) {
1446
+ index.fields = verifiedFields.join(",");
1447
+ filtered.push(index);
1448
+ }
1449
+ return filtered;
1450
+ }, []);
1451
+ }
1452
+ }
1453
+ exports._validateIndexes = _validateIndexes;
1454
+ /**
1455
+ * Remove field references from templates that no longer exist.
1456
+ *
1457
+ * @param adminItem layer or table from the service
1458
+ * @param fieldNames string list of fields names
1459
+ * @private
1460
+ */
1461
+ function _validateTemplatesFields(adminItem, fieldNames) {
1462
+ const templates = adminItem.templates;
1463
+ /* istanbul ignore else */
1464
+ if (templates) {
1465
+ adminItem.templates = templates.map(template => {
1466
+ const attributes = (0, generalHelpers_1.getProp)(template, "prototype.attributes");
1467
+ /* istanbul ignore else */
1468
+ if (attributes) {
1469
+ Object.keys(attributes).forEach(k => {
1470
+ /* istanbul ignore else */
1471
+ if (fieldNames.indexOf(k) === -1) {
1472
+ delete attributes[k];
1473
+ }
1474
+ });
1475
+ (0, generalHelpers_1.setProp)(template, "prototype.attributes", attributes);
1476
+ }
1477
+ return template;
1478
+ });
1479
+ }
1480
+ }
1481
+ exports._validateTemplatesFields = _validateTemplatesFields;
1482
+ /**
1483
+ * Remove field references from templates that no longer exist.
1484
+ *
1485
+ * @param adminItem layer or table from the service
1486
+ * @param fieldNames string list of fields names
1487
+ * @private
1488
+ */
1489
+ function _validateTypesTemplates(adminItem, fieldNames) {
1490
+ const types = adminItem.types;
1491
+ /* istanbul ignore else */
1492
+ if (types) {
1493
+ adminItem.types = types.map(t => {
1494
+ _validateTemplatesFields(t, fieldNames);
1495
+ return t;
1496
+ });
1497
+ }
1498
+ }
1499
+ exports._validateTypesTemplates = _validateTypesTemplates;
1500
+ /**
1501
+ * Check if edit feilds exist but with lower case
1502
+ *
1503
+ * @param adminItem layer or table from the service
1504
+ * @param fieldNames string list of fields names
1505
+ * @private
1506
+ */
1507
+ function _validateEditFieldsInfo(adminItem, fieldNames) {
1508
+ const editFieldsInfo = adminItem.editFieldsInfo;
1509
+ /* istanbul ignore else */
1510
+ if (editFieldsInfo) {
1511
+ const editFieldsInfoKeys = Object.keys(editFieldsInfo);
1512
+ editFieldsInfoKeys.forEach(k => {
1513
+ const editFieldName = editFieldsInfo[k];
1514
+ /* istanbul ignore else */
1515
+ if (editFieldName) {
1516
+ fieldNames.some(name => {
1517
+ if (name === editFieldName) {
1518
+ return true;
1519
+ }
1520
+ else if (name === editFieldName.toLowerCase()) {
1521
+ editFieldsInfo[k] = name;
1522
+ return true;
1523
+ }
1524
+ else {
1525
+ return false;
1526
+ }
1527
+ });
1528
+ }
1529
+ });
1530
+ }
1531
+ }
1532
+ exports._validateEditFieldsInfo = _validateEditFieldsInfo;
1533
+ /**
1534
+ *
1535
+ * Templatize all field references within a layer
1536
+ * This is necessary to support potential field name changes when deploying to portal
1537
+ * Portal will force all field names to be lower case
1538
+ *
1539
+ * @param dataItem The data layer instance with field name references within
1540
+ * @param itemID The id for the item that contains this layer.
1541
+ * @param layer JSON return from the layer being templatized.
1542
+ * @param dependencies
1543
+ * @returns An updated instance of the layer
1544
+ * @private
1545
+ */
1546
+ function _templatizeLayerFieldReferences(dataItem, itemID, layer, dependencies) {
1547
+ // This is the value that will be used as the template for adlib replacement
1548
+ const path = itemID + ".layer" + layer.id + ".fields";
1549
+ // Get the field names for various tests
1550
+ const fieldNames = layer.fields.map((f) => f.name);
1551
+ // Update the layer from the items data property
1552
+ if (dataItem) {
1553
+ _templatizeAdminLayerInfoFields(dataItem, dependencies);
1554
+ _templatizePopupInfo(dataItem, layer, path, itemID, fieldNames);
1555
+ }
1556
+ // Update the layer
1557
+ _templatizeAdminLayerInfoFields(layer, dependencies);
1558
+ _templatizeRelationshipFields(layer, itemID);
1559
+ _templatizeDefinitionEditor(layer, path, fieldNames);
1560
+ _templatizeDefinitionExpression(layer, path, fieldNames);
1561
+ _templatizeDrawingInfo(layer, path, fieldNames);
1562
+ _templatizeTemplates(layer, path);
1563
+ _templatizeTypeTemplates(layer, path);
1564
+ _templatizeTimeInfo(layer, path);
1565
+ _templatizeDefinitionQuery(layer, path, fieldNames);
1566
+ }
1567
+ exports._templatizeLayerFieldReferences = _templatizeLayerFieldReferences;
1568
+ /**
1569
+ * Templatize a layers adminLayerInfo by removing properties that will case issues with clone.
1570
+ * Also templatizes the source service name when we are dealing with a view.
1571
+ *
1572
+ * @param layer The layer to be modified
1573
+ * @param dependencies Array of service dependencies
1574
+ * @returns A new copy of the modified adminLayerInfo for the given layer
1575
+ * @private
1576
+ */
1577
+ function _templatizeAdminLayerInfo(layer, dependencies, templateDictionary) {
1578
+ // Create new instance of adminLayerInfo to update for clone
1579
+ const adminLayerInfo = Object.assign({}, layer.adminLayerInfo);
1580
+ _updateGeomFieldName(adminLayerInfo, templateDictionary);
1581
+ (0, generalHelpers_1.deleteProp)(adminLayerInfo, "xssTrustedFields");
1582
+ (0, generalHelpers_1.deleteProp)(adminLayerInfo, "tableName");
1583
+ // Remove unnecessary properties and templatize key properties from viewLayerDefinition
1584
+ /* istanbul ignore else */
1585
+ if (adminLayerInfo.viewLayerDefinition) {
1586
+ const viewDef = Object.assign({}, adminLayerInfo.viewLayerDefinition);
1587
+ _processAdminObject(viewDef, dependencies);
1588
+ // Remove unnecessary properties and templatize key properties from viewLayerDefinition.table
1589
+ /* istanbul ignore else */
1590
+ if (viewDef.table) {
1591
+ _processAdminObject(viewDef.table, dependencies);
1592
+ /* istanbul ignore else */
1593
+ if (viewDef.table.relatedTables) {
1594
+ viewDef.table.relatedTables.forEach((table) => {
1595
+ _processAdminObject(table, dependencies);
1596
+ });
1597
+ }
1598
+ }
1599
+ adminLayerInfo.viewLayerDefinition = viewDef;
1600
+ }
1601
+ return adminLayerInfo;
1602
+ }
1603
+ exports._templatizeAdminLayerInfo = _templatizeAdminLayerInfo;
1604
+ /**
1605
+ * Remove sourceId and templatize the sourceServiceName
1606
+ *
1607
+ * @param object The layer to be modified
1608
+ * @param dependencies Array of service dependencies
1609
+ * @private
1610
+ */
1611
+ function _processAdminObject(object, dependencies) {
1612
+ (0, generalHelpers_1.deleteProp)(object, "sourceId");
1613
+ if (object.hasOwnProperty("sourceServiceName")) {
1614
+ object.sourceServiceName = _templatizeSourceServiceName(object.sourceServiceName, dependencies);
1615
+ }
1616
+ }
1617
+ exports._processAdminObject = _processAdminObject;
1618
+ /**
1619
+ * Templatize the name based on the given dependencies
1620
+ *
1621
+ * @param lookupName The current name from the source service
1622
+ * @param dependencies Array of IDependency for name mapping
1623
+ * @returns The templatized name || undefined when no matching dependency is found
1624
+ * @private
1625
+ */
1626
+ function _templatizeSourceServiceName(lookupName, dependencies) {
1627
+ const deps = dependencies.filter(dependency => dependency.name === lookupName);
1628
+ return deps.length === 1 ? _templatize(deps[0].id, "name") : undefined;
1629
+ }
1630
+ exports._templatizeSourceServiceName = _templatizeSourceServiceName;
1631
+ /**
1632
+ * templatize the fields referenced in adminLayerInfo
1633
+ *
1634
+ * @param layer the layer object with the adminLayerInfo property to templatize
1635
+ * @param basePath path used to de-templatize while deploying
1636
+ * @param itemID the id for the item that contains this layer
1637
+ * @private
1638
+ */
1639
+ function _templatizeAdminLayerInfoFields(layer, dependencies) {
1640
+ // templatize the source layer fields
1641
+ const table = (0, generalHelpers_1.getProp)(layer, "adminLayerInfo.viewLayerDefinition.table");
1642
+ if (table) {
1643
+ let id = _getDependantItemId(table.sourceServiceName, dependencies);
1644
+ const path = id + ".layer" + table.sourceLayerId + ".fields";
1645
+ _templatizeAdminSourceLayerFields(table.sourceLayerFields || [], path);
1646
+ // templatize the releated table fields
1647
+ const relatedTables = (0, generalHelpers_1.getProp)(layer, "adminLayerInfo.viewLayerDefinition.table.relatedTables") || [];
1648
+ if (relatedTables.length > 0) {
1649
+ relatedTables.forEach((t) => {
1650
+ id = _getDependantItemId(t.sourceServiceName, dependencies);
1651
+ const relatedPath = id + ".layer" + t.sourceLayerId + ".fields";
1652
+ _templatizeTopFilter(t.topFilter || {}, relatedPath);
1653
+ _templatizeAdminSourceLayerFields(t.sourceLayerFields || [], relatedPath);
1654
+ const parentKeyFields = t.parentKeyFields || [];
1655
+ t.parentKeyFields = parentKeyFields.map((f) => {
1656
+ return _templatize(path, f, "name");
1657
+ });
1658
+ const keyFields = t.keyFields || [];
1659
+ t.keyFields = keyFields.map((f) => {
1660
+ return _templatize(relatedPath, f, "name");
1661
+ });
1662
+ });
1663
+ }
1664
+ }
1665
+ }
1666
+ exports._templatizeAdminLayerInfoFields = _templatizeAdminLayerInfoFields;
1667
+ /**
1668
+ * find id based on dependency name
1669
+ *
1670
+ * @param lookupName name of dependency we want to find the id of
1671
+ * @param dependencies array of item dependencies
1672
+ * @private
1673
+ */
1674
+ function _getDependantItemId(lookupName, dependencies) {
1675
+ const deps = dependencies.filter(dependency => dependency.name === lookupName);
1676
+ return deps.length === 1 ? deps[0].id : "";
1677
+ }
1678
+ exports._getDependantItemId = _getDependantItemId;
1679
+ /**
1680
+ * templatize the sourceLayerFields referenced in adminLayerInfo
1681
+ *
1682
+ * @param fields array of sourceLayerFields to templatize
1683
+ * @param basePath path used to de-templatize while deploying
1684
+ * @private
1685
+ */
1686
+ function _templatizeAdminSourceLayerFields(fields, basePath) {
1687
+ fields.forEach(f => _templatizeProperty(f, "source", basePath, "name"));
1688
+ }
1689
+ exports._templatizeAdminSourceLayerFields = _templatizeAdminSourceLayerFields;
1690
+ /**
1691
+ * templatize the topFilter property from adminLayerInfo related tables
1692
+ *
1693
+ * @param topFilter the topFilter object to templatize
1694
+ * @param basePath path used to de-templatize while deploying
1695
+ * @private
1696
+ */
1697
+ function _templatizeTopFilter(topFilter, basePath) {
1698
+ /* istanbul ignore else */
1699
+ if (topFilter) {
1700
+ // templatize the orderByFields prop
1701
+ const orderByFields = topFilter["orderByFields"] || "";
1702
+ /* istanbul ignore else */
1703
+ if (orderByFields !== "") {
1704
+ const orderByField = orderByFields.split(" ")[0];
1705
+ topFilter.orderByFields = topFilter.orderByFields.replace(orderByField, _templatize(basePath, orderByField, "name"));
1706
+ }
1707
+ const groupByFields = topFilter["groupByFields"] || "";
1708
+ /* istanbul ignore else */
1709
+ if (groupByFields !== "") {
1710
+ const _groupByFields = groupByFields.split(",");
1711
+ /* istanbul ignore else */
1712
+ if (_groupByFields.length > 0) {
1713
+ const mappedFields = _groupByFields.map((f) => {
1714
+ return _templatize(basePath, f, "name");
1715
+ });
1716
+ topFilter.groupByFields = mappedFields.join(",");
1717
+ }
1718
+ }
1719
+ }
1720
+ }
1721
+ exports._templatizeTopFilter = _templatizeTopFilter;
1722
+ /**
1723
+ * templatize the relationships key fields using the related table id in the basePath
1724
+ *
1725
+ * @param layer the layer that has the relationships to templatize
1726
+ * @param itemID the id of the item that contains the related table
1727
+ * @private
1728
+ */
1729
+ function _templatizeRelationshipFields(layer, itemID) {
1730
+ if (layer && layer.relationships) {
1731
+ const relationships = layer.relationships;
1732
+ relationships.forEach(r => {
1733
+ /* istanbul ignore else */
1734
+ if (r.keyField) {
1735
+ const basePath = itemID + ".layer" + layer.id + ".fields";
1736
+ _templatizeProperty(r, "keyField", basePath, "name");
1737
+ }
1738
+ });
1739
+ }
1740
+ }
1741
+ exports._templatizeRelationshipFields = _templatizeRelationshipFields;
1742
+ /**
1743
+ * templatize the popupInfo
1744
+ *
1745
+ * @param layerDefinition the layerDefinition that has the popupInfo to templatize
1746
+ * @param layer the JSON for the layer being templatized
1747
+ * @param basePath path used to de-templatize while deploying
1748
+ * @param itemID the id for the item that contains this layer
1749
+ * @param fieldNames array of fieldNames
1750
+ * @private
1751
+ */
1752
+ function _templatizePopupInfo(layerDefinition, layer, basePath, itemID, fieldNames) {
1753
+ // the data layer does not have the fields...will need to get those
1754
+ // from the associated layer json
1755
+ if (fieldNames && layerDefinition.popupInfo) {
1756
+ const popupInfo = layerDefinition.popupInfo;
1757
+ _templatizeName(popupInfo, "title", fieldNames, basePath);
1758
+ _templatizeName(popupInfo, "description", fieldNames, basePath);
1759
+ const fieldInfos = popupInfo.fieldInfos || [];
1760
+ _templatizePopupInfoFieldInfos(fieldInfos, layer, itemID, basePath);
1761
+ const expressionInfos = popupInfo.expressionInfos || [];
1762
+ _templatizeExpressionInfos(expressionInfos, fieldNames, basePath);
1763
+ const popupElements = popupInfo.popupElements || [];
1764
+ _templatizePopupElements(popupElements, basePath, layer, itemID, fieldNames);
1765
+ const mediaInfos = popupInfo.mediaInfos || [];
1766
+ _templatizeMediaInfos(mediaInfos, fieldNames, basePath, layer, itemID);
1767
+ }
1768
+ }
1769
+ exports._templatizePopupInfo = _templatizePopupInfo;
1770
+ /**
1771
+ * templatize field name when referenced like this: \{\{fieldName\}\}
1772
+ * checks each field name from the layer
1773
+ *
1774
+ * @param object with the property to test for a field name
1775
+ * @param property that could have a field name referenced
1776
+ * @param fieldNames array for field names for the layer
1777
+ * @param basePath path used to de-templatize while deploying
1778
+ * @private
1779
+ */
1780
+ function _templatizeName(object, property, fieldNames, basePath) {
1781
+ if (object.hasOwnProperty(property)) {
1782
+ fieldNames.forEach(name => {
1783
+ // Only test and replace instance of the name so any enclosing characters
1784
+ // will be retained
1785
+ const regEx = new RegExp("(\\b" + name + "\\b(?![}]{2}))", "gm");
1786
+ if (regEx.test(object[property])) {
1787
+ object[property] = object[property].replace(regEx, _templatize(basePath, name, "name"));
1788
+ }
1789
+ });
1790
+ }
1791
+ }
1792
+ exports._templatizeName = _templatizeName;
1793
+ /**
1794
+ * templatize field name when referenced like this: \{\{fieldName\}\}
1795
+ * checks each field name from the layer
1796
+ *
1797
+ * @param fieldInfos object that contains the popups fieldInfos
1798
+ * @param layer json of layer being cloned
1799
+ * @param itemID id of the item that contains the current layer
1800
+ * @param basePath path used to de-templatize while deploying
1801
+ * @private
1802
+ */
1803
+ function _templatizePopupInfoFieldInfos(fieldInfos, layer, itemID, basePath) {
1804
+ fieldInfos.forEach((f) => {
1805
+ f.fieldName = _templatizeFieldName(f.fieldName, layer, itemID, basePath);
1806
+ });
1807
+ }
1808
+ exports._templatizePopupInfoFieldInfos = _templatizePopupInfoFieldInfos;
1809
+ /**
1810
+ * templatize field name when referenced like this: \{\{fieldName\}\}
1811
+ * checks each field name from the layer
1812
+ *
1813
+ * @param name the field name to templatize
1814
+ * @param layer json of layer being cloned
1815
+ * @param itemID id of the item that contains the current layer
1816
+ * @param basePath path used to de-templatize while deploying
1817
+ * @private
1818
+ */
1819
+ function _templatizeFieldName(name, layer, itemID, basePath) {
1820
+ if (name.indexOf("relationships/") > -1) {
1821
+ const rels = name.split("/");
1822
+ const relationshipId = rels[1];
1823
+ const adminRelatedTables = (0, generalHelpers_1.getProp)(layer, "adminLayerInfo.viewLayerDefinition.table.relatedTables");
1824
+ const relatedTables = layer.relationships || adminRelatedTables;
1825
+ /* istanbul ignore else */
1826
+ if (relatedTables && relatedTables.length > parseInt(relationshipId, 10)) {
1827
+ const relatedTable = relatedTables[relationshipId];
1828
+ // the layers relationships stores the property as relatedTableId
1829
+ // the layers adminLayerInfo relatedTables stores the property as sourceLayerId
1830
+ const prop = (0, generalHelpers_1.getProp)(relatedTable, "relatedTableId")
1831
+ ? "relatedTableId"
1832
+ : "sourceLayerId";
1833
+ const _basePath = itemID + ".layer" + relatedTable[prop] + ".fields";
1834
+ rels[2] = _templatize(_basePath, rels[2], "name");
1835
+ name = rels.join("/");
1836
+ }
1837
+ }
1838
+ else {
1839
+ // do not need to templatize expression references as the expression
1840
+ // itself will be templatized
1841
+ if (name.indexOf("expression/") === -1) {
1842
+ name = _templatize(basePath, name, "name");
1843
+ }
1844
+ }
1845
+ return name;
1846
+ }
1847
+ exports._templatizeFieldName = _templatizeFieldName;
1848
+ /**
1849
+ * templatize field name when referenced in expressionInfos
1850
+ *
1851
+ * @param expressionInfos the popups expressionInfos to check
1852
+ * @param fieldNames array of the layers field names
1853
+ * @param basePath path used to de-templatize while deploying
1854
+ * @private
1855
+ */
1856
+ function _templatizeExpressionInfos(expressionInfos, fieldNames, basePath) {
1857
+ return expressionInfos.map((i) => {
1858
+ fieldNames.forEach(name => {
1859
+ i.expression = _templatizeArcadeExpressions(i.expression, name, basePath);
1860
+ });
1861
+ return i;
1862
+ });
1863
+ }
1864
+ exports._templatizeExpressionInfos = _templatizeExpressionInfos;
1865
+ /**
1866
+ * templatize field name when referenced in popupElelments
1867
+ *
1868
+ * @param popupElelments the popups popupElelments to check
1869
+ * @param basePath path used to de-templatize while deploying
1870
+ * @param layer json of layer being cloned
1871
+ * @param itemID id of the item that contains the current layer
1872
+ * @param fieldNames array of field names
1873
+ * @private
1874
+ */
1875
+ function _templatizePopupElements(popupElelments, basePath, layer, itemID, fieldNames) {
1876
+ popupElelments.forEach((pe) => {
1877
+ if (pe.hasOwnProperty("fieldInfos")) {
1878
+ _templatizePopupInfoFieldInfos(pe.fieldInfos, layer, itemID, basePath);
1879
+ }
1880
+ if (pe.hasOwnProperty("mediaInfos")) {
1881
+ _templatizeMediaInfos(pe.mediaInfos, fieldNames, basePath, layer, itemID);
1882
+ }
1883
+ });
1884
+ }
1885
+ exports._templatizePopupElements = _templatizePopupElements;
1886
+ /**
1887
+ * templatize field name when referenced in mediaInfos
1888
+ *
1889
+ * @param mediaInfos the popups mediaInfos to check
1890
+ * @param fieldNames array of the layers field names
1891
+ * @param basePath path used to de-templatize while deploying
1892
+ * @param layer json of layer being cloned
1893
+ * @param itemID id of the item that contains the current layer
1894
+ * @private
1895
+ */
1896
+ function _templatizeMediaInfos(mediaInfos, fieldNames, basePath, layer, itemId) {
1897
+ // templatize various properties of mediaInfos
1898
+ const props = ["title", "caption"];
1899
+ props.forEach(p => _templatizeName(mediaInfos, p, fieldNames, basePath));
1900
+ mediaInfos.forEach((mi) => {
1901
+ /* istanbul ignore else */
1902
+ if (mi.hasOwnProperty("value")) {
1903
+ const v = mi.value;
1904
+ const vfields = v.fields || [];
1905
+ v.fields = vfields.map(f => _templatizeFieldName(f, layer, itemId, basePath));
1906
+ if (v.hasOwnProperty("normalizeField")) {
1907
+ _templatizeProperty(v, "normalizeField", basePath, "name");
1908
+ }
1909
+ /* istanbul ignore else */
1910
+ if (v.hasOwnProperty("tooltipField")) {
1911
+ v.tooltipField = _templatizeFieldName(v.tooltipField, layer, itemId, basePath);
1912
+ }
1913
+ }
1914
+ });
1915
+ }
1916
+ exports._templatizeMediaInfos = _templatizeMediaInfos;
1917
+ /**
1918
+ * templatize field names when referenced in definitionEditor
1919
+ *
1920
+ * @param layer the layer with the definition editor
1921
+ * @param basePath path used to de-templatize while deploying
1922
+ * @param fieldNames json of layer being cloned
1923
+ * @private
1924
+ */
1925
+ function _templatizeDefinitionEditor(layer, basePath, fieldNames) {
1926
+ if (layer) {
1927
+ const defEditor = layer.definitionEditor || {};
1928
+ /* istanbul ignore else */
1929
+ if (defEditor) {
1930
+ const inputs = defEditor.inputs;
1931
+ if (inputs) {
1932
+ inputs.forEach(i => {
1933
+ /* istanbul ignore else */
1934
+ if (i.parameters) {
1935
+ i.parameters.forEach((p) => {
1936
+ _templatizeProperty(p, "fieldName", basePath, "name");
1937
+ });
1938
+ }
1939
+ });
1940
+ }
1941
+ if (defEditor.hasOwnProperty("parameterizedExpression")) {
1942
+ defEditor.parameterizedExpression = _templatizeSimpleName(defEditor.parameterizedExpression || "", basePath, fieldNames, "name");
1943
+ }
1944
+ }
1945
+ }
1946
+ }
1947
+ exports._templatizeDefinitionEditor = _templatizeDefinitionEditor;
1948
+ /**
1949
+ * templatize field names when referenced in definitionExpression
1950
+ *
1951
+ * @param layer the layer with the definition editor
1952
+ * @param basePath path used to de-templatize while deploying
1953
+ * @param fieldNames array of field names
1954
+ * @private
1955
+ */
1956
+ function _templatizeDefinitionExpression(layer, basePath, fieldNames) {
1957
+ if (layer && layer.hasOwnProperty("definitionExpression")) {
1958
+ layer.definitionExpression = _templatizeSimpleName(layer.definitionExpression || "", basePath, fieldNames, "name");
1959
+ }
1960
+ }
1961
+ exports._templatizeDefinitionExpression = _templatizeDefinitionExpression;
1962
+ /**
1963
+ * Case sensitive test for field names that appear anywhere within a string
1964
+ *
1965
+ * @param expression the expression to test for field name references
1966
+ * @param basePath path used to de-templatize while deploying
1967
+ * @param fieldNames array of the layers field names
1968
+ * @private
1969
+ */
1970
+ function _templatizeSimpleName(expression, basePath, fieldNames, suffix) {
1971
+ fieldNames.forEach(name => {
1972
+ // look for the name but not if its followed by }}
1973
+ const regEx = new RegExp("\\b" + name + "\\b(?![}]{2})", "gm");
1974
+ if (expression && regEx.test(expression)) {
1975
+ expression = expression.replace(regEx, _templatize(basePath, name, suffix));
1976
+ }
1977
+ });
1978
+ return expression;
1979
+ }
1980
+ exports._templatizeSimpleName = _templatizeSimpleName;
1981
+ /**
1982
+ * Templatize field references within a layers drawingInfo
1983
+ *
1984
+ * @param layer the data layer
1985
+ * @param basePath path used to de-templatize while deploying
1986
+ * @param fieldNames array of the layers field names
1987
+ * @private
1988
+ */
1989
+ function _templatizeDrawingInfo(layer, basePath, fieldNames) {
1990
+ if (layer) {
1991
+ const drawingInfo = layer.drawingInfo;
1992
+ if (drawingInfo) {
1993
+ // templatize the renderer fields
1994
+ const renderer = drawingInfo.renderer || {};
1995
+ _templatizeRenderer(renderer, basePath, fieldNames);
1996
+ // templatize the labelingInfo
1997
+ const labelingInfo = drawingInfo.labelingInfo || [];
1998
+ _templatizeLabelingInfo(labelingInfo, basePath, fieldNames);
1999
+ }
2000
+ }
2001
+ }
2002
+ exports._templatizeDrawingInfo = _templatizeDrawingInfo;
2003
+ /**
2004
+ * Templatize field references within a layers drawingInfo
2005
+ *
2006
+ * @param renderer the layers renderer
2007
+ * @param basePath path used to de-templatize while deploying
2008
+ * @param fieldNames array of the layers field names
2009
+ * @private
2010
+ */
2011
+ function _templatizeRenderer(renderer, basePath, fieldNames) {
2012
+ switch (renderer.type) {
2013
+ case "classBreaks":
2014
+ case "uniqueValue":
2015
+ case "predominance":
2016
+ case "simple":
2017
+ case "heatmap":
2018
+ _templatizeGenRenderer(renderer, basePath, fieldNames);
2019
+ break;
2020
+ case "temporal":
2021
+ _templatizeTemporalRenderer(renderer, basePath, fieldNames);
2022
+ break;
2023
+ default:
2024
+ break;
2025
+ }
2026
+ }
2027
+ exports._templatizeRenderer = _templatizeRenderer;
2028
+ /**
2029
+ * Templatize field references within a layers renderer
2030
+ *
2031
+ * @param renderer the renderer object to check for field references
2032
+ * @param basePath path used to de-templatize while deploying
2033
+ * @param fieldNames array of field names that will be used to search expressions
2034
+ * @private
2035
+ */
2036
+ function _templatizeGenRenderer(renderer, basePath, fieldNames) {
2037
+ /* istanbul ignore else */
2038
+ if (renderer) {
2039
+ // update authoringInfo
2040
+ const authoringInfo = renderer.authoringInfo;
2041
+ if (authoringInfo) {
2042
+ _templatizeAuthoringInfo(authoringInfo, basePath, fieldNames);
2043
+ }
2044
+ const props = ["field", "normalizationField"];
2045
+ props.forEach(p => _templatizeProperty(renderer, p, basePath, "name"));
2046
+ const fieldNameProps = ["field1", "field2", "field3"];
2047
+ fieldNameProps.forEach(fnP => _templatizeProperty(renderer, fnP, basePath, "name"));
2048
+ // When an attribute name is specified, it's enclosed in square brackets
2049
+ const rExp = renderer.rotationExpression;
2050
+ if (rExp) {
2051
+ fieldNames.forEach(name => {
2052
+ const regEx = new RegExp("(\\[" + name + "\\])", "gm");
2053
+ if (regEx.test(rExp)) {
2054
+ renderer.rotationExpression = rExp.replace(regEx, "[" + _templatize(basePath, name, "name") + "]");
2055
+ }
2056
+ });
2057
+ }
2058
+ // update valueExpression
2059
+ if (renderer.valueExpression) {
2060
+ fieldNames.forEach(name => {
2061
+ renderer.valueExpression = _templatizeArcadeExpressions(renderer.valueExpression, name, basePath);
2062
+ });
2063
+ }
2064
+ // update visualVariables
2065
+ const visualVariables = renderer.visualVariables;
2066
+ if (visualVariables) {
2067
+ visualVariables.forEach(v => {
2068
+ props.forEach(p => _templatizeProperty(v, p, basePath, "name"));
2069
+ if (v.valueExpression) {
2070
+ fieldNames.forEach(name => {
2071
+ v.valueExpression = _templatizeArcadeExpressions(v.valueExpression, name, basePath);
2072
+ });
2073
+ }
2074
+ });
2075
+ }
2076
+ }
2077
+ }
2078
+ exports._templatizeGenRenderer = _templatizeGenRenderer;
2079
+ /**
2080
+ * Templatize field references within a layers renderer
2081
+ *
2082
+ * @param renderer the renderer object to check for field references
2083
+ * @param basePath path used to de-templatize while deploying
2084
+ * @param fieldNames array of field names that will be used to search expressions
2085
+ * @private
2086
+ */
2087
+ function _templatizeTemporalRenderer(renderer, basePath, fieldNames) {
2088
+ const renderers = [
2089
+ renderer.latestObservationRenderer,
2090
+ renderer.observationRenderer,
2091
+ renderer.trackRenderer
2092
+ ];
2093
+ renderers.forEach(r => {
2094
+ _templatizeRenderer(r, basePath, fieldNames);
2095
+ });
2096
+ }
2097
+ exports._templatizeTemporalRenderer = _templatizeTemporalRenderer;
2098
+ /**
2099
+ * Templatize renderers authoringInfo
2100
+ *
2101
+ * @param authoringInfo object containing metadata about the authoring process
2102
+ * @param basePath path used to de-templatize while deploying
2103
+ * @param fieldNames the name of fields from the layer
2104
+ * @private
2105
+ */
2106
+ function _templatizeAuthoringInfo(authoringInfo, basePath, fieldNames) {
2107
+ /* istanbul ignore else */
2108
+ if (authoringInfo) {
2109
+ const props = ["field", "normalizationField"];
2110
+ const field1 = authoringInfo.field1;
2111
+ props.forEach(p => _templatizeProperty(field1, p, basePath, "name"));
2112
+ const field2 = authoringInfo.field2;
2113
+ props.forEach(p => _templatizeProperty(field2, p, basePath, "name"));
2114
+ const fields = authoringInfo.fields;
2115
+ if (fields) {
2116
+ authoringInfo.fields = fields.map(f => _templatize(basePath, f, "name"));
2117
+ }
2118
+ const vProps = ["endTime", "field", "startTime"];
2119
+ const vVars = authoringInfo.visualVariables;
2120
+ if (vVars) {
2121
+ vProps.forEach(p => {
2122
+ // endTime and startTime may or may not be a field name
2123
+ if (fieldNames.indexOf(vVars[p]) > -1) {
2124
+ _templatizeProperty(vVars, p, basePath, "name");
2125
+ }
2126
+ });
2127
+ }
2128
+ }
2129
+ }
2130
+ exports._templatizeAuthoringInfo = _templatizeAuthoringInfo;
2131
+ /**
2132
+ * Templatize field references within an arcade expression
2133
+ *
2134
+ * @param text the text that contains the expression
2135
+ * @param fieldName name of the field to test for
2136
+ * @param basePath path used to de-templatize while deploying
2137
+ * @private
2138
+ */
2139
+ function _templatizeArcadeExpressions(text, fieldName, basePath) {
2140
+ const t = _templatize(basePath, fieldName, "name");
2141
+ if (text) {
2142
+ // test for $feature. notation
2143
+ // captures VOTED_DEM_2012 from $feature.VOTED_DEM_2012
2144
+ let exp = "(?:\\$feature\\.)(" + fieldName + ")\\b";
2145
+ let regEx = new RegExp(exp, "gm");
2146
+ text = regEx.test(text) ? text.replace(regEx, "$feature." + t) : text;
2147
+ // test for $feature[] notation
2148
+ // captures VOTED_DEM_2012 from $feature["VOTED_DEM_2012"]
2149
+ // captures VOTED_DEM_2012 from $feature['VOTED_DEM_2012']
2150
+ // captures VOTED_DEM_2012 from $feature[VOTED_DEM_2012]
2151
+ exp = "(?:[$]feature)(\\[\\\"?\\'?)" + fieldName + "(\\\"?\\'?\\])";
2152
+ regEx = new RegExp(exp, "gm");
2153
+ let result = regEx.exec(text);
2154
+ if (result) {
2155
+ text = text.replace(regEx, "$feature" + result[1] + t + result[2]);
2156
+ }
2157
+ // test for $feature[] with join case
2158
+ // captures VOTED_DEM_2016 from $feature["COUNTY_ID.VOTED_DEM_2016"]
2159
+ exp =
2160
+ "(?:[$]feature)(\\[\\\"?\\'?)(\\w+)[.]" + fieldName + "(\\\"?\\'?\\])";
2161
+ regEx = new RegExp(exp, "gm");
2162
+ result = regEx.exec(text);
2163
+ if (result && result.length > 3) {
2164
+ // TODO result[2] is the table name...this needs to be templatized as well
2165
+ text = text.replace(regEx, "$feature" + result[1] + result[2] + "." + t + result[3]);
2166
+ }
2167
+ // test for "fieldName"
2168
+ // captures fieldName from "var names = ["fieldName", "fieldName2"]..."
2169
+ // captures fieldName from "var names = ['fieldName', 'fieldName2']..."
2170
+ exp = "(\\\"|\\')+" + fieldName + "(\\\"|\\')+";
2171
+ regEx = new RegExp(exp, "gm");
2172
+ result = regEx.exec(text);
2173
+ if (result) {
2174
+ text = text.replace(regEx, result[1] + t + result[2]);
2175
+ }
2176
+ }
2177
+ return text;
2178
+ }
2179
+ exports._templatizeArcadeExpressions = _templatizeArcadeExpressions;
2180
+ /**
2181
+ * templatize field names when referenced in the layers labelingInfo
2182
+ *
2183
+ * @param labelingInfo the object that contains the labelingInfo
2184
+ * @param basePath path used to de-templatize while deploying
2185
+ * @param fieldNames array of the layers field names
2186
+ * @private
2187
+ */
2188
+ function _templatizeLabelingInfo(labelingInfo, basePath, fieldNames) {
2189
+ labelingInfo.forEach((li) => {
2190
+ /* istanbul ignore else */
2191
+ if (li.hasOwnProperty("fieldInfos")) {
2192
+ const fieldInfos = li.fieldInfos || [];
2193
+ fieldInfos.forEach(fi => _templatizeProperty(fi, "fieldName", basePath, "name"));
2194
+ }
2195
+ const labelExp = li.labelExpression || "";
2196
+ const labelExpInfo = li.labelExpressionInfo || {};
2197
+ fieldNames.forEach(n => {
2198
+ const t = _templatize(basePath, n, "name");
2199
+ // check for [fieldName] or ["fieldName"]
2200
+ const regExBracket = new RegExp('(\\[\\"*)+(' + n + ')(\\"*\\])+', "gm");
2201
+ let result = regExBracket.exec(labelExp);
2202
+ if (result) {
2203
+ li.labelExpression = labelExp.replace(regExBracket, result[1] + t + result[3]);
2204
+ }
2205
+ /* istanbul ignore else */
2206
+ if (labelExpInfo.value) {
2207
+ let v = labelExpInfo.value;
2208
+ // check for {fieldName}
2209
+ const regExCurly = new RegExp("(\\{" + n + "\\})", "gm");
2210
+ v = regExCurly.test(v) ? v.replace(regExCurly, "{" + t + "}") : v;
2211
+ // check for [fieldName] or ["fieldName"]
2212
+ result = regExBracket.exec(v);
2213
+ v = result ? v.replace(regExBracket, result[1] + t + result[3]) : v;
2214
+ li.labelExpressionInfo.value = v;
2215
+ }
2216
+ /* istanbul ignore else */
2217
+ if (labelExpInfo.expression) {
2218
+ li.labelExpressionInfo.expression = _templatizeArcadeExpressions(labelExpInfo.expression, n, basePath);
2219
+ }
2220
+ });
2221
+ });
2222
+ }
2223
+ exports._templatizeLabelingInfo = _templatizeLabelingInfo;
2224
+ /**
2225
+ * templatize the layers editing templates
2226
+ *
2227
+ * @param layer the data layer being cloned
2228
+ * @param basePath path used to de-templatize while deploying
2229
+ * @private
2230
+ */
2231
+ function _templatizeTemplates(layer, basePath) {
2232
+ const templates = layer.templates || [];
2233
+ templates.forEach(t => {
2234
+ const attributes = (0, generalHelpers_1.getProp)(t, "prototype.attributes");
2235
+ const _attributes = _templatizeKeys(attributes, basePath, "name");
2236
+ /* istanbul ignore else */
2237
+ if (_attributes) {
2238
+ t.prototype.attributes = _attributes;
2239
+ }
2240
+ });
2241
+ }
2242
+ exports._templatizeTemplates = _templatizeTemplates;
2243
+ /**
2244
+ * templatize the layer types and templates
2245
+ *
2246
+ * @param layer the data layer being cloned
2247
+ * @param basePath path used to de-templatize while deploying
2248
+ * @private
2249
+ */
2250
+ function _templatizeTypeTemplates(layer, basePath) {
2251
+ const types = layer.types;
2252
+ if (types && Array.isArray(types) && types.length > 0) {
2253
+ types.forEach((type) => {
2254
+ const domains = _templatizeKeys(type.domains, basePath, "name");
2255
+ /* istanbul ignore else */
2256
+ if (domains) {
2257
+ type.domains = domains;
2258
+ }
2259
+ const templates = type.templates;
2260
+ /* istanbul ignore else */
2261
+ if (templates && templates.length > 0) {
2262
+ templates.forEach((t) => {
2263
+ const attributes = (0, generalHelpers_1.getProp)(t, "prototype.attributes");
2264
+ const _attributes = _templatizeKeys(attributes, basePath, "name");
2265
+ /* istanbul ignore else */
2266
+ if (_attributes) {
2267
+ t.prototype.attributes = _attributes;
2268
+ }
2269
+ });
2270
+ }
2271
+ });
2272
+ }
2273
+ }
2274
+ exports._templatizeTypeTemplates = _templatizeTypeTemplates;
2275
+ /**
2276
+ * templatize object keys
2277
+ *
2278
+ * @param obj the object to templatize
2279
+ * @param basePath path used to de-templatize while deploying
2280
+ * @param suffix expected suffix for template variable
2281
+ * @private
2282
+ */
2283
+ function _templatizeKeys(obj, basePath, suffix) {
2284
+ let _obj;
2285
+ /* istanbul ignore else */
2286
+ if (obj) {
2287
+ _obj = {};
2288
+ const objKeys = Object.keys(obj);
2289
+ /* istanbul ignore else */
2290
+ if (objKeys && objKeys.length > 0) {
2291
+ objKeys.forEach(k => {
2292
+ _obj[_templatize(basePath, k, suffix)] = obj[k];
2293
+ });
2294
+ }
2295
+ }
2296
+ return _obj;
2297
+ }
2298
+ exports._templatizeKeys = _templatizeKeys;
2299
+ /**
2300
+ * templatize fields referenced in the layers time info
2301
+ *
2302
+ * @param layer the data layer being cloned
2303
+ * @param basePath path used to de-templatize while deploying
2304
+ * @private
2305
+ */
2306
+ function _templatizeTimeInfo(layer, basePath) {
2307
+ if (layer.timeInfo) {
2308
+ const timeInfo = layer.timeInfo;
2309
+ const timeProps = [
2310
+ "endTimeField",
2311
+ "startTimeField",
2312
+ "trackIdField"
2313
+ ];
2314
+ timeProps.forEach(t => {
2315
+ if (timeInfo[t] !== "") {
2316
+ _templatizeProperty(timeInfo, t, basePath, "name");
2317
+ }
2318
+ else {
2319
+ timeInfo[t] = null;
2320
+ }
2321
+ });
2322
+ }
2323
+ }
2324
+ exports._templatizeTimeInfo = _templatizeTimeInfo;
2325
+ /**
2326
+ * templatize the layers definition query
2327
+ *
2328
+ * @param layer the data layer being cloned
2329
+ * @param basePath path used to de-templatize while deploying
2330
+ * @param fieldNames array of the layers field names
2331
+ * @private
2332
+ */
2333
+ function _templatizeDefinitionQuery(layer, basePath, fieldNames) {
2334
+ // templatize view definition query
2335
+ if (layer && layer.hasOwnProperty("viewDefinitionQuery")) {
2336
+ layer.viewDefinitionQuery = _templatizeSimpleName(layer.viewDefinitionQuery || "", basePath, fieldNames, "name");
2337
+ }
2338
+ if (layer && layer.hasOwnProperty("definitionQuery")) {
2339
+ layer.definitionQuery = _templatizeSimpleName(layer.definitionQuery || "", basePath, fieldNames, "name");
2340
+ }
2341
+ }
2342
+ exports._templatizeDefinitionQuery = _templatizeDefinitionQuery;
2343
+ /**
2344
+ * Helper function to create the name mapping used to
2345
+ * de-templatize the field reference
2346
+ *
2347
+ * @param fieldInfos the object that stores the cached information
2348
+ * @param id the id for the current layer being processed
2349
+ * @private
2350
+ */
2351
+ function _getNameMapping(fieldInfos, id) {
2352
+ // create name mapping
2353
+ const fInfo = fieldInfos[id];
2354
+ const nameMapping = {};
2355
+ const newFields = fInfo.newFields;
2356
+ const newFieldNames = newFields
2357
+ ? newFields.map((f) => f.name)
2358
+ : [];
2359
+ const sourceFields = fInfo.sourceFields || [];
2360
+ sourceFields.forEach((field) => {
2361
+ const lName = String(field.name).toLowerCase();
2362
+ newFields.forEach((f) => {
2363
+ // Names can change more than case
2364
+ if (newFieldNames.indexOf(field.name) === -1 &&
2365
+ newFieldNames.indexOf(lName) === -1) {
2366
+ // If both new (f) and source (field) aliases are defined and are equal, map the source name to the new name
2367
+ if (f.alias && f.alias === field.alias) {
2368
+ nameMapping[lName] = {
2369
+ name: f.name,
2370
+ alias: f.alias,
2371
+ type: f.type ? f.type : ""
2372
+ };
2373
+ }
2374
+ }
2375
+ if (String(f.name).toLowerCase() === lName) {
2376
+ nameMapping[lName] = {
2377
+ name: f.name,
2378
+ alias: f.alias ? f.alias : "",
2379
+ type: f.type ? f.type : ""
2380
+ };
2381
+ }
2382
+ });
2383
+ });
2384
+ // update for editFieldsInfo
2385
+ if (fInfo.editFieldsInfo && fInfo.newEditFieldsInfo) {
2386
+ const efi = JSON.parse(JSON.stringify(fInfo.editFieldsInfo));
2387
+ const newEfi = JSON.parse(JSON.stringify(fInfo.newEditFieldsInfo));
2388
+ const nameMappingKeys = Object.keys(nameMapping);
2389
+ Object.keys(efi).forEach(k => {
2390
+ const lowerEfi = String(efi[k]).toLowerCase();
2391
+ if ((nameMappingKeys.indexOf(lowerEfi) === -1 ||
2392
+ nameMapping[lowerEfi].name !== newEfi[k]) &&
2393
+ newFieldNames.indexOf(lowerEfi) > -1) {
2394
+ // Only add delete fields if source schema changes allowed
2395
+ /* istanbul ignore else */
2396
+ if (fInfo.sourceSchemaChangesAllowed && !fInfo.isView) {
2397
+ /* istanbul ignore else */
2398
+ if (!fInfo.hasOwnProperty("deleteFields")) {
2399
+ fInfo.deleteFields = [];
2400
+ }
2401
+ // This issue only occurs on portal so we
2402
+ // need to delete the lcase version of the field
2403
+ fInfo.deleteFields.push(lowerEfi);
2404
+ }
2405
+ // editFieldsInfo only has the name and not the alias and type
2406
+ let sourceEfiField;
2407
+ fInfo.sourceFields.some((sf) => {
2408
+ if (sf.name === efi[k]) {
2409
+ sourceEfiField = sf;
2410
+ }
2411
+ return sf.name === efi[k];
2412
+ });
2413
+ nameMapping[lowerEfi] = {
2414
+ name: newEfi[k],
2415
+ alias: sourceEfiField && sourceEfiField.alias ? sourceEfiField.alias : "",
2416
+ type: sourceEfiField && sourceEfiField.type ? sourceEfiField.type : ""
2417
+ };
2418
+ }
2419
+ });
2420
+ (0, generalHelpers_1.deleteProp)(fInfo, "sourceSchemaChangesAllowed");
2421
+ (0, generalHelpers_1.deleteProp)(fInfo, "editFieldsInfo");
2422
+ (0, generalHelpers_1.deleteProp)(fInfo, "newEditFieldsInfo");
2423
+ (0, generalHelpers_1.deleteProp)(fInfo, "isView");
2424
+ }
2425
+ return nameMapping;
2426
+ }
2427
+ exports._getNameMapping = _getNameMapping;
2428
+ /**
2429
+ * Helper function to ensure same chunk size value is used in multiple locations
2430
+ *
2431
+ * @returns a number that represents how many layers should be included per addToDef call
2432
+ * @private
2433
+ */
2434
+ function _getLayerChunkSize() {
2435
+ return 20;
2436
+ }
2437
+ exports._getLayerChunkSize = _getLayerChunkSize;
2438
+ //# sourceMappingURL=featureServiceHelpers.js.map