@esri/solution-creator 6.4.0-next.20250925 → 6.4.0-next.20250926

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.
@@ -13,7 +13,7 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { ICreateSolutionOptions, IItemTemplate, TPossibleSourceFile, UserSession } from "@esri/solution-common";
16
+ import { ICreateSolutionOptions, IItemTemplate, TPossibleSourceFile, ISourceFile, UserSession } from "@esri/solution-common";
17
17
  /**
18
18
  * Adds a list of AGO item ids to a solution item.
19
19
  *
@@ -65,6 +65,18 @@ export declare function _getSolutionItemUrls(templates: IItemTemplate[]): string
65
65
  * @private
66
66
  */
67
67
  export declare function _getTemplateVariables(text: string): string[];
68
+ /**
69
+ * Update the tasks-configuration resource file if it exists
70
+ *
71
+ * @param templates List of Solution's templates
72
+ * @param resourceItemFiles Resources for the item; these resources are modified as needed
73
+ * @param templateDictionary templateDictionary Hash of facts: folder id, org URL, adlib replacements
74
+ * @param srcAuthentication Credentials for requests to source items
75
+ *
76
+ * @returns A promise that resolves with the resource files
77
+ * @internal
78
+ */
79
+ export declare function _postProcessTaskResource(templates: IItemTemplate[], resourceItemFiles: ISourceFile[], templateDictionary: any, srcAuthentication: UserSession): Promise<ISourceFile[]>;
68
80
  /**
69
81
  * Update the items dependencies and groups arrays
70
82
  *
@@ -15,7 +15,7 @@
15
15
  * limitations under the License.
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports._templatizeWorkflowConfig = exports._templatizeSolutionIds = exports._templatizeOrgUrl = exports._simplifyUrlsInItemDescriptions = exports._restoreDataFilesToTemplates = exports._replaceRemainingIdsInString = exports._replaceRemainingIdsInObject = exports._replaceDictionaryItemsInObject = exports._getDataFilesFromTemplates = exports._postProcessIgnoredItems = exports._postProcessGroupDependencies = exports._getTemplateVariables = exports._getSolutionItemUrls = exports._getOrgUrl = exports._getIdsOutOfTemplateVariables = exports._getDependencies = exports.addContentToSolution = void 0;
18
+ exports._templatizeWorkflowConfig = exports._templatizeSolutionIds = exports._templatizeOrgUrl = exports._simplifyUrlsInItemDescriptions = exports._restoreDataFilesToTemplates = exports._replaceRemainingIdsInString = exports._replaceRemainingIdsInObject = exports._replaceDictionaryItemsInObject = exports._getDataFilesFromTemplates = exports._postProcessIgnoredItems = exports._postProcessGroupDependencies = exports._postProcessTaskResource = exports._getTemplateVariables = exports._getSolutionItemUrls = exports._getOrgUrl = exports._getIdsOutOfTemplateVariables = exports._getDependencies = exports.addContentToSolution = void 0;
19
19
  const tslib_1 = require("tslib");
20
20
  const solution_common_1 = require("@esri/solution-common");
21
21
  const hub_common_1 = require("@esri/hub-common");
@@ -133,6 +133,7 @@ function addContentToSolution(solutionItemId, options, srcAuthentication, destAu
133
133
  resourceItemFiles = resourceItemFiles.concat((0, template_1.getDataFilesFromTemplates)(solutionTemplates));
134
134
  // Coalesce the resource file paths from the created templates
135
135
  resourceItemFiles = resourceItemFiles.filter((file) => templateIds.includes(file.itemId));
136
+ resourceItemFiles = await _postProcessTaskResource(solutionTemplates, resourceItemFiles, templateDictionary, srcAuthentication);
136
137
  // Send the accumulated resources to the solution item
137
138
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
138
139
  (0, solution_common_1.copyFilesToStorageItem)(resourceItemFiles, solutionItemId, destAuthentication).then(() => {
@@ -269,6 +270,116 @@ function _getTemplateVariables(text) {
269
270
  .map((variable) => variable.substring(2, variable.length - 2)); // remove "{{" & "}}"
270
271
  }
271
272
  exports._getTemplateVariables = _getTemplateVariables;
273
+ /**
274
+ * Update the tasks-configuration resource file if it exists
275
+ *
276
+ * @param templates List of Solution's templates
277
+ * @param resourceItemFiles Resources for the item; these resources are modified as needed
278
+ * @param templateDictionary templateDictionary Hash of facts: folder id, org URL, adlib replacements
279
+ * @param srcAuthentication Credentials for requests to source items
280
+ *
281
+ * @returns A promise that resolves with the resource files
282
+ * @internal
283
+ */
284
+ async function _postProcessTaskResource(templates, resourceItemFiles, templateDictionary, srcAuthentication) {
285
+ const taskConfigName = solution_common_1.TASK_CONFIG;
286
+ const taskResources = resourceItemFiles.reduce((prev, cur) => {
287
+ if (cur.filename === taskConfigName) {
288
+ prev[cur.itemId] = cur;
289
+ }
290
+ return prev;
291
+ }, {});
292
+ const taskKeys = Object.keys(taskResources);
293
+ if (taskKeys.length < 1) {
294
+ return Promise.resolve(resourceItemFiles);
295
+ }
296
+ const itemIds = templates.reduce((prev, cur) => {
297
+ // key is the source id and the value is the variable
298
+ // example { "31980e6ad7xxxc60b756e712b69d1344": "{{31980e6ad7xxxc60b756e712b69d1344.itemId}}" }
299
+ prev[cur.itemId] = cur.item.id;
300
+ return prev;
301
+ }, {});
302
+ const featureServiceWithLayerUrls = [];
303
+ const featureServerUrls = [];
304
+ const otherUrls = [];
305
+ // we want to first process feature service urls that conain a layer number, then general feature service urls then all other urls, finally the portal base url
306
+ let arrayToUse;
307
+ const urlVarHash = Object.keys(templateDictionary).reduce((prev, cur) => {
308
+ if (cur.indexOf("http://") > -1 || cur.indexOf("https://") > -1) {
309
+ // key is the source url and the value is the variable
310
+ // example { "http://example": "{{31980e6ad7xxxc60b756e712b69d1344.url}}" }
311
+ const encoded = encodeURIComponent(cur);
312
+ prev[cur] = templateDictionary[cur];
313
+ prev[encoded] = templateDictionary[cur].replace("}}", ":encode}}");
314
+ arrayToUse = /FeatureServer\/\d+/g.test(cur)
315
+ ? featureServiceWithLayerUrls
316
+ : cur.endsWith("FeatureServer")
317
+ ? featureServerUrls
318
+ : otherUrls;
319
+ // sorted
320
+ arrayToUse.push(cur);
321
+ arrayToUse.push(encoded);
322
+ }
323
+ return prev;
324
+ }, {});
325
+ // Add the portal base urls at the end so we will search for them last
326
+ // and not accidentially replace part of a service url
327
+ const portalBaseUrl = templateDictionary.portalBaseUrl;
328
+ const encodedPortalBaseUrl = encodeURIComponent(portalBaseUrl);
329
+ urlVarHash[portalBaseUrl] = "{{portalBaseUrl}}";
330
+ urlVarHash[encodedPortalBaseUrl] = "{{portalBaseUrl:encode}}";
331
+ const orderedUrls = [...featureServiceWithLayerUrls, ...featureServerUrls, ...otherUrls];
332
+ orderedUrls.push(portalBaseUrl);
333
+ orderedUrls.push(encodedPortalBaseUrl);
334
+ const requestOptions = {
335
+ httpMethod: "GET",
336
+ authentication: srcAuthentication,
337
+ params: {
338
+ f: "json",
339
+ },
340
+ headers: {
341
+ "Accept": "application/json",
342
+ "Authorization": `Bearer ${srcAuthentication.token}`,
343
+ "Content-Type": "application/json",
344
+ "X-Esri-Authorization": `Bearer ${srcAuthentication.token}`,
345
+ },
346
+ };
347
+ const resourcePromises = taskKeys.map((k) => {
348
+ return (0, solution_common_1.request)((0, solution_common_1.generateSourceResourceUrl)(`${templateDictionary.portalBaseUrl}/sharing/rest`, taskResources[k].itemId, taskResources[k].filename), requestOptions);
349
+ });
350
+ await Promise.all(resourcePromises).then(async (r) => {
351
+ let resourceString = JSON.stringify(r);
352
+ // replace urls first
353
+ orderedUrls.forEach((url) => {
354
+ // TypeScript for es2015 doesn't have a definition for `replaceAll`
355
+ resourceString = resourceString.replaceAll(url, urlVarHash[url]);
356
+ });
357
+ // replace any item ids that aren't already variables
358
+ Object.keys(itemIds).forEach((k) => {
359
+ let pattern = new RegExp(`(?<!\\{\\{)${k}`, "g");
360
+ // TypeScript for es2015 doesn't have a definition for `replaceAll`
361
+ resourceString = resourceString.replaceAll(pattern, itemIds[k]);
362
+ });
363
+ // all urls and item ids should now be replaced with variables that contain the item ids
364
+ // we need to add any ids that are not currently marked as dependencies to the webmap dependencies and update the resource
365
+ const ids = (0, solution_common_1.uniqueStringList)(resourceString.match((0, solution_common_1.getAgoIdRegEx)()));
366
+ resourceItemFiles = resourceItemFiles.map((file) => {
367
+ if (file.filename === taskConfigName) {
368
+ file.file = (0, solution_common_1.jsonToFile)(JSON.parse(resourceString), file.filename);
369
+ // add any ids that we found to the source webmap
370
+ templates.some((t) => {
371
+ if (t.itemId === file.itemId) {
372
+ t.dependencies = [...new Set([...t.dependencies, ...ids])];
373
+ return true;
374
+ }
375
+ });
376
+ }
377
+ return file;
378
+ });
379
+ });
380
+ return Promise.resolve(resourceItemFiles);
381
+ }
382
+ exports._postProcessTaskResource = _postProcessTaskResource;
272
383
  /**
273
384
  * Update the items dependencies and groups arrays
274
385
  *
@@ -13,7 +13,7 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { ICreateSolutionOptions, IItemTemplate, TPossibleSourceFile, UserSession } from "@esri/solution-common";
16
+ import { ICreateSolutionOptions, IItemTemplate, TPossibleSourceFile, ISourceFile, UserSession } from "@esri/solution-common";
17
17
  /**
18
18
  * Adds a list of AGO item ids to a solution item.
19
19
  *
@@ -65,6 +65,18 @@ export declare function _getSolutionItemUrls(templates: IItemTemplate[]): string
65
65
  * @private
66
66
  */
67
67
  export declare function _getTemplateVariables(text: string): string[];
68
+ /**
69
+ * Update the tasks-configuration resource file if it exists
70
+ *
71
+ * @param templates List of Solution's templates
72
+ * @param resourceItemFiles Resources for the item; these resources are modified as needed
73
+ * @param templateDictionary templateDictionary Hash of facts: folder id, org URL, adlib replacements
74
+ * @param srcAuthentication Credentials for requests to source items
75
+ *
76
+ * @returns A promise that resolves with the resource files
77
+ * @internal
78
+ */
79
+ export declare function _postProcessTaskResource(templates: IItemTemplate[], resourceItemFiles: ISourceFile[], templateDictionary: any, srcAuthentication: UserSession): Promise<ISourceFile[]>;
68
80
  /**
69
81
  * Update the items dependencies and groups arrays
70
82
  *
@@ -13,7 +13,7 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { SolutionTemplateFormatVersion, EItemProgressStatus, dedupe, failWithIds, getAgoIdRegEx, getIDs, getPortal, getTemplateById, globalStringReplace, isWorkforceProject, removeTemplate, replaceInTemplate, SItemProgressStatus, copyFilesToStorageItem, postProcessWebToolReferences, postProcessWorkforceTemplates, UNREACHABLE, updateItem, } from "@esri/solution-common";
16
+ import { SolutionTemplateFormatVersion, EItemProgressStatus, dedupe, failWithIds, getAgoIdRegEx, getIDs, getPortal, getTemplateById, globalStringReplace, isWorkforceProject, generateSourceResourceUrl, jsonToFile, removeTemplate, replaceInTemplate, request, SItemProgressStatus, copyFilesToStorageItem, postProcessWebToolReferences, postProcessWorkforceTemplates, TASK_CONFIG, uniqueStringList, UNREACHABLE, updateItem, } from "@esri/solution-common";
17
17
  import { getProp, getWithDefault } from "@esri/hub-common";
18
18
  import { createItemTemplate, postProcessFieldReferences } from "../createItemTemplate";
19
19
  import * as form from "@esri/solution-form";
@@ -129,6 +129,7 @@ export function addContentToSolution(solutionItemId, options, srcAuthentication,
129
129
  resourceItemFiles = resourceItemFiles.concat(getDataFilesFromTemplates(solutionTemplates));
130
130
  // Coalesce the resource file paths from the created templates
131
131
  resourceItemFiles = resourceItemFiles.filter((file) => templateIds.includes(file.itemId));
132
+ resourceItemFiles = await _postProcessTaskResource(solutionTemplates, resourceItemFiles, templateDictionary, srcAuthentication);
132
133
  // Send the accumulated resources to the solution item
133
134
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
134
135
  copyFilesToStorageItem(resourceItemFiles, solutionItemId, destAuthentication).then(() => {
@@ -259,6 +260,115 @@ export function _getTemplateVariables(text) {
259
260
  return (text.match(/{{[a-z0-9.]*}}/gi) || []) // find variable
260
261
  .map((variable) => variable.substring(2, variable.length - 2)); // remove "{{" & "}}"
261
262
  }
263
+ /**
264
+ * Update the tasks-configuration resource file if it exists
265
+ *
266
+ * @param templates List of Solution's templates
267
+ * @param resourceItemFiles Resources for the item; these resources are modified as needed
268
+ * @param templateDictionary templateDictionary Hash of facts: folder id, org URL, adlib replacements
269
+ * @param srcAuthentication Credentials for requests to source items
270
+ *
271
+ * @returns A promise that resolves with the resource files
272
+ * @internal
273
+ */
274
+ export async function _postProcessTaskResource(templates, resourceItemFiles, templateDictionary, srcAuthentication) {
275
+ const taskConfigName = TASK_CONFIG;
276
+ const taskResources = resourceItemFiles.reduce((prev, cur) => {
277
+ if (cur.filename === taskConfigName) {
278
+ prev[cur.itemId] = cur;
279
+ }
280
+ return prev;
281
+ }, {});
282
+ const taskKeys = Object.keys(taskResources);
283
+ if (taskKeys.length < 1) {
284
+ return Promise.resolve(resourceItemFiles);
285
+ }
286
+ const itemIds = templates.reduce((prev, cur) => {
287
+ // key is the source id and the value is the variable
288
+ // example { "31980e6ad7xxxc60b756e712b69d1344": "{{31980e6ad7xxxc60b756e712b69d1344.itemId}}" }
289
+ prev[cur.itemId] = cur.item.id;
290
+ return prev;
291
+ }, {});
292
+ const featureServiceWithLayerUrls = [];
293
+ const featureServerUrls = [];
294
+ const otherUrls = [];
295
+ // we want to first process feature service urls that conain a layer number, then general feature service urls then all other urls, finally the portal base url
296
+ let arrayToUse;
297
+ const urlVarHash = Object.keys(templateDictionary).reduce((prev, cur) => {
298
+ if (cur.indexOf("http://") > -1 || cur.indexOf("https://") > -1) {
299
+ // key is the source url and the value is the variable
300
+ // example { "http://example": "{{31980e6ad7xxxc60b756e712b69d1344.url}}" }
301
+ const encoded = encodeURIComponent(cur);
302
+ prev[cur] = templateDictionary[cur];
303
+ prev[encoded] = templateDictionary[cur].replace("}}", ":encode}}");
304
+ arrayToUse = /FeatureServer\/\d+/g.test(cur)
305
+ ? featureServiceWithLayerUrls
306
+ : cur.endsWith("FeatureServer")
307
+ ? featureServerUrls
308
+ : otherUrls;
309
+ // sorted
310
+ arrayToUse.push(cur);
311
+ arrayToUse.push(encoded);
312
+ }
313
+ return prev;
314
+ }, {});
315
+ // Add the portal base urls at the end so we will search for them last
316
+ // and not accidentially replace part of a service url
317
+ const portalBaseUrl = templateDictionary.portalBaseUrl;
318
+ const encodedPortalBaseUrl = encodeURIComponent(portalBaseUrl);
319
+ urlVarHash[portalBaseUrl] = "{{portalBaseUrl}}";
320
+ urlVarHash[encodedPortalBaseUrl] = "{{portalBaseUrl:encode}}";
321
+ const orderedUrls = [...featureServiceWithLayerUrls, ...featureServerUrls, ...otherUrls];
322
+ orderedUrls.push(portalBaseUrl);
323
+ orderedUrls.push(encodedPortalBaseUrl);
324
+ const requestOptions = {
325
+ httpMethod: "GET",
326
+ authentication: srcAuthentication,
327
+ params: {
328
+ f: "json",
329
+ },
330
+ headers: {
331
+ "Accept": "application/json",
332
+ "Authorization": `Bearer ${srcAuthentication.token}`,
333
+ "Content-Type": "application/json",
334
+ "X-Esri-Authorization": `Bearer ${srcAuthentication.token}`,
335
+ },
336
+ };
337
+ const resourcePromises = taskKeys.map((k) => {
338
+ return request(generateSourceResourceUrl(`${templateDictionary.portalBaseUrl}/sharing/rest`, taskResources[k].itemId, taskResources[k].filename), requestOptions);
339
+ });
340
+ await Promise.all(resourcePromises).then(async (r) => {
341
+ let resourceString = JSON.stringify(r);
342
+ // replace urls first
343
+ orderedUrls.forEach((url) => {
344
+ // TypeScript for es2015 doesn't have a definition for `replaceAll`
345
+ resourceString = resourceString.replaceAll(url, urlVarHash[url]);
346
+ });
347
+ // replace any item ids that aren't already variables
348
+ Object.keys(itemIds).forEach((k) => {
349
+ let pattern = new RegExp(`(?<!\\{\\{)${k}`, "g");
350
+ // TypeScript for es2015 doesn't have a definition for `replaceAll`
351
+ resourceString = resourceString.replaceAll(pattern, itemIds[k]);
352
+ });
353
+ // all urls and item ids should now be replaced with variables that contain the item ids
354
+ // we need to add any ids that are not currently marked as dependencies to the webmap dependencies and update the resource
355
+ const ids = uniqueStringList(resourceString.match(getAgoIdRegEx()));
356
+ resourceItemFiles = resourceItemFiles.map((file) => {
357
+ if (file.filename === taskConfigName) {
358
+ file.file = jsonToFile(JSON.parse(resourceString), file.filename);
359
+ // add any ids that we found to the source webmap
360
+ templates.some((t) => {
361
+ if (t.itemId === file.itemId) {
362
+ t.dependencies = [...new Set([...t.dependencies, ...ids])];
363
+ return true;
364
+ }
365
+ });
366
+ }
367
+ return file;
368
+ });
369
+ });
370
+ return Promise.resolve(resourceItemFiles);
371
+ }
262
372
  /**
263
373
  * Update the items dependencies and groups arrays
264
374
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@esri/solution-creator",
3
- "version": "6.4.0-next.20250925",
3
+ "version": "6.4.0-next.20250926",
4
4
  "description": "Manages the creation of a Solution item for @esri/solution.js.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -25,18 +25,18 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@esri/hub-common": "^17.0.2",
28
- "@esri/solution-common": "^6.4.0-next.20250925",
29
- "@esri/solution-feature-layer": "^6.4.0-next.20250925",
30
- "@esri/solution-file": "^6.4.0-next.20250925",
31
- "@esri/solution-form": "^6.4.0-next.20250925",
32
- "@esri/solution-group": "^6.4.0-next.20250925",
33
- "@esri/solution-hub-types": "^6.4.0-next.20250925",
34
- "@esri/solution-simple-types": "^6.4.0-next.20250925",
35
- "@esri/solution-storymap": "^6.4.0-next.20250925",
36
- "@esri/solution-velocity": "^6.4.0-next.20250925",
37
- "@esri/solution-web-experience": "^6.4.0-next.20250925",
38
- "@esri/solution-web-tool": "^6.4.0-next.20250925",
39
- "@esri/solution-workflow": "^6.4.0-next.20250925",
28
+ "@esri/solution-common": "^6.4.0-next.20250926",
29
+ "@esri/solution-feature-layer": "^6.4.0-next.20250926",
30
+ "@esri/solution-file": "^6.4.0-next.20250926",
31
+ "@esri/solution-form": "^6.4.0-next.20250926",
32
+ "@esri/solution-group": "^6.4.0-next.20250926",
33
+ "@esri/solution-hub-types": "^6.4.0-next.20250926",
34
+ "@esri/solution-simple-types": "^6.4.0-next.20250926",
35
+ "@esri/solution-storymap": "^6.4.0-next.20250926",
36
+ "@esri/solution-velocity": "^6.4.0-next.20250926",
37
+ "@esri/solution-web-experience": "^6.4.0-next.20250926",
38
+ "@esri/solution-web-tool": "^6.4.0-next.20250926",
39
+ "@esri/solution-workflow": "^6.4.0-next.20250926",
40
40
  "tslib": "1.14.1"
41
41
  },
42
42
  "scripts": {
@@ -91,5 +91,5 @@
91
91
  "esri",
92
92
  "ES6"
93
93
  ],
94
- "gitHead": "0092f8c76afb3b4d94d2a89353313a3b42cf2d77"
94
+ "gitHead": "f8b6ad1803cd5c2f67b317b6ea7390dad77ada61"
95
95
  }