UNPKG

@esri/solution-common

Version:

Provides general helper functions for @esri/solution.js.

291 lines 9.7 kB
/** @license * Copyright 2018 Esri * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Provides common functions involving the adlib library. * * @module templatization */ import { adlib } from "adlib"; import { createShortId, getProp, uniqueStringList } from "./generalHelpers"; // ------------------------------------------------------------------------------------------------------------------ // /** * A parameterized server name to replace the organization URL in a Web Mapping Application's URL to * itself; name has to be acceptable to AGOL, otherwise it discards the URL, so substitution must be * made before attempting to create the item. * * @private */ export const SERVER_NAME = "portalBaseUrl"; /** * A parameterized geometry server name * * @private */ export const GEOMETRY_SERVER_NAME = "organization.helperServices.geometry.url"; /** * A parameterized geocode server name * * @private */ export const GEOCODE_SERVER_NAME = "organization.helperServices.geocode:getDefaultLocatorURL"; /** * A parameterized network analyst server name * * @private */ export const NA_SERVER_NAME = "organization.helperServices.route.url"; /** * A parameterized network analyst server name * * @private */ export const PRINT_SERVER_NAME = "organization.helperServices.printTask.url"; export const TRANSFORMS = { getDefaultLocatorURL(key, val) { // get the url from the template dictionary or return the default template variable when it's not present // this fallback is needed when we detemplatize living atlas layers as a part of the create process return val ? val[0].url : `{{${GEOCODE_SERVER_NAME}}}`; }, }; /** * Wraps double brackets around the supplied term. * * @param term Term to be wrapped, e.g., SERVER_NAME's "portalBaseUrl" * @returns Wrapped term, e.g., "\{\{portalBaseUrl\}\}" */ export function placeholder(term) { return "{{" + term + "}}"; } export function createInitializedGroupTemplate(itemInfo) { const itemTemplate = createPlaceholderTemplate(itemInfo.id, itemInfo.type); itemTemplate.item = { ...itemTemplate.item, description: itemInfo.description, snippet: itemInfo.snippet, tags: itemInfo.tags, typeKeywords: itemInfo.typeKeywords, title: itemInfo.title, thumbnail: itemInfo.thumbnail, }; return itemTemplate; } export function createInitializedItemTemplate(itemInfo) { const itemTemplate = createPlaceholderTemplate(itemInfo.id, itemInfo.type); itemTemplate.item = { ...itemTemplate.item, accessInformation: itemInfo.accessInformation, categories: itemInfo.categories, contentStatus: itemInfo.contentStatus, created: itemInfo.created, culture: itemInfo.culture, description: itemInfo.description, extent: getDefaultExtent(itemInfo), licenseInfo: itemInfo.licenseInfo, modified: itemInfo.modified, name: itemInfo.name, origUrl: itemInfo.origUrl, properties: itemInfo.properties, snippet: itemInfo.snippet, spatialReference: undefined, tags: itemInfo.tags, thumbnail: itemInfo.thumbnail, title: itemInfo.title, typeKeywords: itemInfo.typeKeywords, url: itemInfo.url, }; return itemTemplate; } /** * Creates an empty template. * * @param id AGO id of item * @param type AGO item type; defaults to "" * @returns Empty template containing supplied id, optional type, and a key created using the function createShortId() */ export function createPlaceholderTemplate(id, type = "") { return { itemId: id, type, key: createShortId(), item: { id, type, }, data: {}, resources: [], dependencies: [], groups: [], properties: {}, estimatedDeploymentCostFactor: 2, }; } /** * Extracts the version of a solution from its data section. * * @param itemData Data section of the solution as JSON * @returns Zero-based version number */ export function extractSolutionVersion(itemData) { let version = getProp(itemData, "metadata.version"); if (!version) { return 0; } if (typeof version === "string") { version = parseInt(itemData.metadata.version, 10); return isNaN(version) ? 0 : version; } return version; } /** * Finds index of template by id in a list of templates. * * @param templates A collection of AGO item templates to search * @param id AGO id of template to find * @returns Offset of of matching template or -1 if not found * @private */ export function findTemplateIndexInList(templates, id) { const baseId = id; return templates.findIndex((template) => { return baseId === template.itemId; }); } /** * Finds template by id in a list of templates. * * @param templates A collection of AGO item templates to search * @param id AGO id of template to find * @returns Matching template or null */ export function findTemplateInList(templates, id) { const iTemplate = findTemplateIndexInList(templates, id); return iTemplate >= 0 ? templates[iTemplate] : null; } export function hasUnresolvedVariables(data) { const getUnresolved = (v) => { return v ? JSON.stringify(v).match(/{{.+?}}/gim) || [] : []; }; return getUnresolved(data).length > 0; } export function getIdsInTemplatesList(templates) { return templates.map((template) => template.itemId); } export function getDefaultExtent(itemInfo) { const ext = itemInfo.extent; return ext === null || (Array.isArray(ext) && ext.length === 0) ? ext : "{{solutionItemExtent}}"; } /** * Removes a template entry in a list of templates. * * @param templates A collection of AGO item templates * @param id Id of item in templates list to find; if not found, no replacement is done * @private */ export function removeTemplate(templates, id) { const i = findTemplateIndexInList(templates, id); if (i >= 0) { templates.splice(i, 1); } } /** * Replaces symbols in a template. * * @param template Template to check for replacements; template is modified by this function * @param replacements Hash of facts: org URL, adlib replacements, deferreds for dependencies * @returns template is returned after updating it */ export function replaceInTemplate(template, replacements) { return adlib(template, replacements, TRANSFORMS); } /** * Replaces a template entry in a list of templates. * * @param templates A collection of AGO item templates * @param id Id of item in templates list to find; if not found, no replacement is done * @param template Replacement template * @returns True if replacement was made * @private */ export function replaceTemplate(templates, id, template) { const i = findTemplateIndexInList(templates, id); if (i >= 0) { templates[i] = template; return true; } return false; } export function templatizeTerm(context, term, suffix = "") { if (!context) { return context; } const pattern = new RegExp(term, "g"); return context.replace(pattern, "{{" + term + suffix + "}}"); } /** * Helper function to templatize value and make sure its converted to lowercase * * @param basePath path used to de-templatize while deploying * @param value to be converted to lower case for lookup while deploying */ export function templatizeToLowerCase(basePath, value) { if (value.startsWith("{{")) { return value; } else { return String(templatizeTerm(basePath, basePath, "." + String(value).toLowerCase())); } } /** * using each field from the datasource replace any occurances * of the field name with the templatized value * Needs to account for: * "NAME" * "NAME NAME2" * "NAME ASC" * "\{NAME\}" * "(NAME = value AND NAME2 = someOtherValue)" */ export function templatizeFieldReferences(obj, fields, basePath, templatizeKeys = false) { let objString = JSON.stringify(obj); fields.forEach((field) => { let expression = "\\b" + field.name + "\\b(?![.])(?![}]{2})"; if (!templatizeKeys) { expression += '(?!":)'; } objString = objString.replace( // needs to ensure that its not already been templatized // cannot be followed by .name and cannot be proceeded by fieldName. in case of {{01922837.name.name}} and cannot be followed by }} new RegExp(expression, "g"), templatizeToLowerCase(basePath, field.name + ".name")); }); return JSON.parse(objString); } export function templatizeIds(obj) { // Convert object to string let objString = JSON.stringify(obj); // Find ids const idTest = /[0-9A-F]{32}/gim; if (obj && idTest.test(objString)) { // Templatize ids const ids = uniqueStringList(objString.match(idTest)); ids.forEach((id) => { const regEx = new RegExp(id, "gm"); objString = objString.replace(regEx, "{{" + id + ".itemId}}"); }); obj = JSON.parse(objString); } return obj; } //# sourceMappingURL=templatization.js.map