UNPKG

dynamics-web-api

Version:

DynamicsWebApi is a Microsoft Dataverse Web API helper library

1,257 lines (1,243 loc) 111 kB
/*! dynamics-web-api v2.2.1 (c) 2025 Aleksandr Rogov. License: MIT */ var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __esm = (fn, res) => function __init() { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/helpers/Crypto.ts function getCrypto() { return true ? window.crypto : null.getCrypto(); } var init_Crypto = __esm({ "src/helpers/Crypto.ts"() { "use strict"; } }); // src/helpers/Regex.ts function isUuid(value) { const match = UUID_REGEX.exec(value); return !!match; } function extractUuid(value) { const match = EXTRACT_UUID_REGEX.exec(value); return match ? match[1] : null; } function extractUuidFromUrl(url) { if (!url) return null; const match = EXTRACT_UUID_FROM_URL_REGEX.exec(url); return match ? match[1] : null; } function removeCurlyBracketsFromUuid(value) { return value.replace(REMOVE_BRACKETS_FROM_UUID_REGEX, (_match, p1) => p1); } function safelyRemoveCurlyBracketsFromUrl(url) { const parts = url.split(QUOTATION_MARK_REGEX); return parts.map((part, index) => { if (index % 2 === 0) { return removeCurlyBracketsFromUuid(part); } return part; }).join(""); } function convertToReferenceObject(responseData) { const result = ENTITY_UUID_REGEX.exec(responseData["@odata.id"]); return { id: result[2], collection: result[1], oDataContext: responseData["@odata.context"] }; } function parsePagingCookie(pagingCookie) { const info = PAGING_COOKIE_REGEX.exec(pagingCookie); if (!info) return null; const page = parseInt(info[2], 10); const sanitizedCookie = sanitizeCookie(info[1]); return { page, sanitizedCookie }; } function sanitizeCookie(cookie) { const characterMap = { "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" // Use numeric reference for single quote to avoid confusion }; return cookie.replace(SPECIAL_CHARACTER_REGEX, (char) => characterMap[char]); } function removeLeadingSlash(value) { return value.replace(LEADING_SLASH_REGEX, ""); } function escapeUnicodeSymbols(value) { return value.replace(UNICODE_SYMBOLS_REGEX, (chr) => `\\u${("0000" + chr.charCodeAt(0).toString(16)).slice(-4)}`); } function removeDoubleQuotes(value) { return value.replace(DOUBLE_QUOTE_REGEX, ""); } function getUpdateMethod(collection) { return SPECIAL_COLLECTION_FOR_UPDATE_REGEX.test(collection ?? "") ? "PUT" : "PATCH"; } var UUID, UUID_REGEX, EXTRACT_UUID_REGEX, EXTRACT_UUID_FROM_URL_REGEX, REMOVE_BRACKETS_FROM_UUID_REGEX, ENTITY_UUID_REGEX, QUOTATION_MARK_REGEX, PAGING_COOKIE_REGEX, SPECIAL_CHARACTER_REGEX, LEADING_SLASH_REGEX, UNICODE_SYMBOLS_REGEX, DOUBLE_QUOTE_REGEX, BATCH_RESPONSE_HEADERS_REGEX, HTTP_STATUS_REGEX, CONTENT_TYPE_PLAIN_REGEX, ODATA_ENTITYID_REGEX, TEXT_REGEX, LINE_ENDING_REGEX, SEARCH_FOR_ENTITY_NAME_REGEX, SPECIAL_COLLECTION_FOR_UPDATE_REGEX, FETCH_XML_TOP_REGEX, FETCH_XML_PAGE_REGEX, FETCH_XML_REPLACE_REGEX, DATE_FORMAT_REGEX; var init_Regex = __esm({ "src/helpers/Regex.ts"() { "use strict"; UUID = "[0-9a-fA-F]{8}[-]?([0-9a-fA-F]{4}[-]?){3}[0-9a-fA-F]{12}"; UUID_REGEX = new RegExp(UUID, "i"); EXTRACT_UUID_REGEX = new RegExp("^{?(" + UUID + ")}?$", "i"); EXTRACT_UUID_FROM_URL_REGEX = new RegExp("(" + UUID + ")\\)$", "i"); REMOVE_BRACKETS_FROM_UUID_REGEX = new RegExp(`{(${UUID})}`, "g"); ENTITY_UUID_REGEX = new RegExp(`\\/(\\w+)\\((${UUID})`, "i"); QUOTATION_MARK_REGEX = /(["'].*?["'])/; PAGING_COOKIE_REGEX = /pagingcookie="(<cookie page="(\d+)".+<\/cookie>)/; SPECIAL_CHARACTER_REGEX = /[<>"']/g; LEADING_SLASH_REGEX = /^\//; UNICODE_SYMBOLS_REGEX = /[\u007F-\uFFFF]/g; DOUBLE_QUOTE_REGEX = /"/g; BATCH_RESPONSE_HEADERS_REGEX = /^([^()<>@,;:\\"\/[\]?={} \t]+)\s?:\s?(.*)/; HTTP_STATUS_REGEX = /HTTP\/?\s*[\d.]*\s+(\d{3})\s+([\w\s]*)$/m; CONTENT_TYPE_PLAIN_REGEX = /Content-Type: text\/plain/i; ODATA_ENTITYID_REGEX = /OData-EntityId.+/i; TEXT_REGEX = /\w+$/g; LINE_ENDING_REGEX = /\r?\n/; SEARCH_FOR_ENTITY_NAME_REGEX = /(\w+)(\([\d\w-]+\))$/; SPECIAL_COLLECTION_FOR_UPDATE_REGEX = /EntityDefinitions|RelationshipDefinitions|GlobalOptionSetDefinitions/; FETCH_XML_TOP_REGEX = /^<fetch.+top=/; FETCH_XML_PAGE_REGEX = /^<fetch.+page=/; FETCH_XML_REPLACE_REGEX = /^(<fetch)/; DATE_FORMAT_REGEX = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:Z|[-+]\d{2}:\d{2})$/; } }); // src/utils/Utility.ts function formatParameterValue(value) { if (value == null) return ""; if (typeof value === "string" && !value.startsWith("Microsoft.Dynamics.CRM") && !isUuid(value)) { return `'${value}'`; } else if (typeof value === "object") { return JSON.stringify(value); } return value.toString(); } function processParameters(parameters) { const parameterNames = Object.keys(parameters); const functionParams = []; const urlQuery = []; parameterNames.forEach((parameterName, index) => { let value = parameters[parameterName]; if (value == null) return; value = formatParameterValue(value); const paramIndex = index + 1; functionParams.push(`${parameterName}=@p${paramIndex}`); urlQuery.push(`@p${paramIndex}=${extractUuid(value) || value}`); }); return { key: `(${functionParams.join(",")})`, queryParams: urlQuery }; } function hasHeader(headers, name) { return headers.hasOwnProperty(name) || headers.hasOwnProperty(name.toLowerCase()); } function getHeader(headers, name) { if (headers[name]) return headers[name]; return headers[name.toLowerCase()]; } var downloadChunkSize, _Utility, Utility; var init_Utility = __esm({ "src/utils/Utility.ts"() { "use strict"; init_Crypto(); init_Regex(); downloadChunkSize = 4194304; _Utility = class _Utility { /** * Builds parametes for a funciton. Returns '()' (if no parameters) or '([params])?[query]' * * @param {Object} [parameters] - Function's input parameters. Example: { param1: "test", param2: 3 }. * @returns {string} */ static buildFunctionParameters(parameters) { return parameters ? processParameters(parameters) : { key: "()" }; } /** * Parses a paging cookie returned in response * * @param {string} pageCookies - Page cookies returned in @Microsoft.Dynamics.CRM.fetchxmlpagingcookie. * @param {number} currentPageNumber - A current page number. Fix empty paging-cookie for complex fetch xmls. * @returns {{cookie: "", number: 0, next: 1}} */ static getFetchXmlPagingCookie(pageCookies = "", currentPageNumber = 1) { pageCookies = decodeURIComponent(decodeURIComponent(pageCookies)); const result = parsePagingCookie(pageCookies); return { cookie: result?.sanitizedCookie || "", page: result?.page || currentPageNumber, nextPage: result?.page ? result.page + 1 : currentPageNumber + 1 }; } /** * Checks whether the value is JS Null. * @param {Object} value * @returns {boolean} */ static isNull(value) { return typeof value === "undefined" || value == null; } /** Generates UUID */ static generateUUID() { return getCrypto().randomUUID(); } static getXrmContext() { if (typeof GetGlobalContext !== "undefined") { return GetGlobalContext(); } else { if (typeof Xrm !== "undefined") { if (!_Utility.isNull(Xrm.Utility) && !_Utility.isNull(Xrm.Utility.getGlobalContext)) { return Xrm.Utility.getGlobalContext(); } else if (!_Utility.isNull(Xrm.Page) && !_Utility.isNull(Xrm.Page.context)) { return Xrm.Page.context; } } } throw new Error( "Xrm Context is not available. In most cases, it can be resolved by adding a reference to a ClientGlobalContext.js.aspx. Please refer to MSDN documentation for more details." ); } // static getXrmUtility(): any { // return typeof Xrm !== "undefined" ? Xrm.Utility : null; // } static getClientUrl() { const context = _Utility.getXrmContext(); let clientUrl = context.getClientUrl(); if (clientUrl.match(/\/$/)) { clientUrl = clientUrl.substring(0, clientUrl.length - 1); } return clientUrl; } /** * Checks whether the app is currently running in a Dynamics Portals Environment. * * In that case we switch to the Web API for Dynamics Portals. * @returns {boolean} */ static isRunningWithinPortals() { return true ? !!window.shell : false; } static isObject(obj) { return typeof obj === "object" && !!obj && !Array.isArray(obj) && Object.prototype.toString.call(obj) !== "[object Date]"; } static copyObject(src, excludeProps) { let target = {}; for (let prop in src) { if (src.hasOwnProperty(prop) && !excludeProps?.includes(prop)) { if (_Utility.isObject(src[prop])) { target[prop] = _Utility.copyObject(src[prop]); } else if (Array.isArray(src[prop])) { target[prop] = src[prop].slice(); } else { target[prop] = src[prop]; } } } return target; } static copyRequest(src, excludeProps = []) { if (!excludeProps.includes("signal")) excludeProps.push("signal"); const result = _Utility.copyObject(src, excludeProps); result.signal = src.signal; return result; } static setFileChunk(request, fileBuffer, chunkSize, offset) { offset = offset || 0; const count = offset + chunkSize > fileBuffer.length ? fileBuffer.length % chunkSize : chunkSize; let content; if (true) { content = new Uint8Array(count); for (let i = 0; i < count; i++) { content[i] = fileBuffer[offset + i]; } } else { content = fileBuffer.slice(offset, offset + count); } request.data = content; request.contentRange = "bytes " + offset + "-" + (offset + count - 1) + "/" + fileBuffer.length; } static convertToFileBuffer(binaryString) { if (false) return Buffer.from(binaryString, "binary"); const bytes = new Uint8Array(binaryString.length); for (var i = 0; i < binaryString.length; i++) { bytes[i] = binaryString.charCodeAt(i); } return bytes; } }; // static isNodeEnv = isNodeEnv; _Utility.downloadChunkSize = downloadChunkSize; Utility = _Utility; } }); // src/helpers/ErrorHelper.ts function throwParameterError(functionName, parameterName, type) { throw new Error( type ? `${functionName} requires a ${parameterName} parameter to be of type ${type}.` : `${functionName} requires a ${parameterName} parameter.` ); } var ErrorHelper; var init_ErrorHelper = __esm({ "src/helpers/ErrorHelper.ts"() { "use strict"; init_Regex(); ErrorHelper = class _ErrorHelper { static handleErrorResponse(req) { throw new Error(`Error: ${req.status}: ${req.message}`); } static parameterCheck(parameter, functionName, parameterName, type) { if (typeof parameter === "undefined" || parameter === null || parameter === "") { throwParameterError(functionName, parameterName, type); } } static stringParameterCheck(parameter, functionName, parameterName) { if (typeof parameter !== "string") { throwParameterError(functionName, parameterName, "String"); } } static maxLengthStringParameterCheck(parameter, functionName, parameterName, maxLength) { if (!parameter) return; if (parameter.length > maxLength) { throw new Error(`${parameterName} has a ${maxLength} character limit.`); } } static arrayParameterCheck(parameter, functionName, parameterName) { if (parameter.constructor !== Array) { throwParameterError(functionName, parameterName, "Array"); } } static stringOrArrayParameterCheck(parameter, functionName, parameterName) { if (parameter.constructor !== Array && typeof parameter !== "string") { throwParameterError(functionName, parameterName, "String or Array"); } } static numberParameterCheck(parameter, functionName, parameterName) { if (typeof parameter != "number") { if (typeof parameter === "string" && parameter) { if (!isNaN(parseInt(parameter))) { return; } } throwParameterError(functionName, parameterName, "Number"); } } static batchIsEmpty() { return [ new Error( "Payload of the batch operation is empty. Please make that you have other operations in between startBatch() and executeBatch() to successfuly build a batch payload." ) ]; } static handleHttpError(parsedError, parameters) { const error = new Error(); Object.keys(parsedError).forEach((k) => { error[k] = parsedError[k]; }); if (parameters) { Object.keys(parameters).forEach((k) => { error[k] = parameters[k]; }); } return error; } static boolParameterCheck(parameter, functionName, parameterName) { if (typeof parameter != "boolean") { throwParameterError(functionName, parameterName, "Boolean"); } } /** * Private function used to check whether required parameter is a valid GUID * @param parameter The GUID parameter to check * @param functionName * @param parameterName * @returns */ static guidParameterCheck(parameter, functionName, parameterName) { const match = extractUuid(parameter); if (!match) throwParameterError(functionName, parameterName, "GUID String"); return match; } static keyParameterCheck(parameter, functionName, parameterName) { try { _ErrorHelper.stringParameterCheck(parameter, functionName, parameterName); const match = extractUuid(parameter); if (match) return match; const alternateKeys = parameter.split(","); if (alternateKeys.length) { for (let i = 0; i < alternateKeys.length; i++) { alternateKeys[i] = alternateKeys[i].trim().replace(/"/g, "'"); /^[\w\d\_]+\=(.+)$/i.exec(alternateKeys[i])[0]; } } return alternateKeys.join(","); } catch (error) { throwParameterError(functionName, parameterName, "String representing GUID or Alternate Key"); } } static callbackParameterCheck(callbackParameter, functionName, parameterName) { if (typeof callbackParameter != "function") { throwParameterError(functionName, parameterName, "Function"); } } static throwBatchIncompatible(functionName, isBatch) { if (isBatch) { isBatch = false; throw new Error(functionName + " cannot be used in a BATCH request."); } } static throwBatchNotStarted(isBatch) { if (!isBatch) { throw new Error( "Batch operation has not been started. Please call a DynamicsWebApi.startBatch() function prior to calling DynamicsWebApi.executeBatch() to perform a batch request correctly." ); } } }; } }); // src/dwa.ts var _a, _b, _DWA, DWA; var init_dwa = __esm({ "src/dwa.ts"() { "use strict"; _DWA = class _DWA { }; _DWA.Prefer = (_b = class { static get(annotation) { return `${_DWA.Prefer.IncludeAnnotations}="${annotation}"`; } }, _b.ReturnRepresentation = "return=representation", _b.Annotations = (_a = class { }, _a.AssociatedNavigationProperty = "Microsoft.Dynamics.CRM.associatednavigationproperty", _a.LookupLogicalName = "Microsoft.Dynamics.CRM.lookuplogicalname", _a.All = "*", _a.FormattedValue = "OData.Community.Display.V1.FormattedValue", _a.FetchXmlPagingCookie = "Microsoft.Dynamics.CRM.fetchxmlpagingcookie", _a), _b.IncludeAnnotations = "odata.include-annotations", _b); DWA = _DWA; } }); // src/client/helpers/dateReviver.ts function dateReviver(key, value) { if (typeof value === "string") { const a = DATE_FORMAT_REGEX.exec(value); if (a) { return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6])); } } return value; } var init_dateReviver = __esm({ "src/client/helpers/dateReviver.ts"() { "use strict"; init_Regex(); } }); // src/client/helpers/parseBatchResponse.ts function parseBatchHeaders(text) { const ctx = { position: 0 }; const headers = {}; let parts; let line; let pos; do { pos = ctx.position; line = readLine(text, ctx); if (!line) break; parts = BATCH_RESPONSE_HEADERS_REGEX.exec(line); if (parts !== null) { headers[parts[1].toLowerCase()] = parts[2]; } else { ctx.position = pos; } } while (line && parts); return headers; } function readLine(text, ctx) { return readTo(text, ctx, LINE_ENDING_REGEX); } function readTo(text, ctx, searchRegTerm) { const start = ctx.position || 0; const slicedText = text.slice(start); const match = searchRegTerm.exec(slicedText); if (!match) { return null; } const end = start + match.index; ctx.position = end + match[0].length; return text.substring(start, end); } function getHttpStatus(response) { const parts = HTTP_STATUS_REGEX.exec(response); return { httpStatusString: parts[0], httpStatus: parseInt(parts[1]), httpStatusMessage: parts[2].trim() }; } function getPlainContent(response) { HTTP_STATUS_REGEX.lastIndex = 0; const textReg = TEXT_REGEX.exec(response.trim()); return textReg?.length ? textReg[0] : void 0; } function handlePlainContent(batchResponse, parseParams, requestNumber) { const plainContent = getPlainContent(batchResponse); return handlePlainResponse(plainContent); } function handleEmptyContent(batchResponse, parseParams, requestNumber) { if (parseParams?.[requestNumber]?.valueIfEmpty !== void 0) { return parseParams[requestNumber].valueIfEmpty; } else { const entityUrl = ODATA_ENTITYID_REGEX.exec(batchResponse); return extractUuidFromUrl(entityUrl?.[0]) ?? void 0; } } function processBatchPart(batchResponse, parseParams, requestNumber) { const { httpStatusString, httpStatus, httpStatusMessage } = getHttpStatus(batchResponse); const responseData = batchResponse.substring(batchResponse.indexOf("{"), batchResponse.lastIndexOf("}") + 1); if (!responseData) { if (CONTENT_TYPE_PLAIN_REGEX.test(batchResponse)) { return handlePlainContent(batchResponse, parseParams, requestNumber); } return handleEmptyContent(batchResponse, parseParams, requestNumber); } const parsedResponse = handleJsonResponse(responseData, parseParams, requestNumber); if (httpStatus < 400) { return parsedResponse; } const responseHeaders = parseBatchHeaders( batchResponse.substring(batchResponse.indexOf(httpStatusString) + httpStatusString.length + 1, batchResponse.indexOf("{")) ); return ErrorHelper.handleHttpError(parsedResponse, { status: httpStatus, statusText: httpStatusMessage, statusMessage: httpStatusMessage, headers: responseHeaders }); } function parseBatchResponse(response, parseParams, requestNumber = 0) { const delimiter = response.substring(0, response.search(LINE_ENDING_REGEX)); const batchResponseParts = response.split(delimiter); batchResponseParts.shift(); batchResponseParts.pop(); let result = []; for (let part of batchResponseParts) { if (part.indexOf("--changesetresponse_") === -1) { result.push(processBatchPart(part, parseParams, requestNumber++)); continue; } part = part.trim(); const batchToProcess = part.substring(part.search(LINE_ENDING_REGEX) + 1).trim(); result = result.concat(parseBatchResponse(batchToProcess, parseParams, requestNumber++)); } return result; } var init_parseBatchResponse = __esm({ "src/client/helpers/parseBatchResponse.ts"() { "use strict"; init_ErrorHelper(); init_Regex(); init_parseResponse(); } }); // src/client/helpers/parseResponse.ts function getFormattedKeyValue(keyName, value) { let newKey = null; if (keyName.indexOf("@") !== -1) { const format = keyName.split("@"); switch (format[1]) { case "odata.context": newKey = "oDataContext"; break; case "odata.count": newKey = "oDataCount"; value = value != null ? parseInt(value) : 0; break; case "odata.nextLink": newKey = "oDataNextLink"; break; case "odata.deltaLink": newKey = "oDataDeltaLink"; break; case DWA.Prefer.Annotations.FormattedValue: newKey = format[0] + "_Formatted"; break; case DWA.Prefer.Annotations.AssociatedNavigationProperty: newKey = format[0] + "_NavigationProperty"; break; case DWA.Prefer.Annotations.LookupLogicalName: newKey = format[0] + "_LogicalName"; break; } } return [newKey, value]; } function parseData(object, parseParams) { if (parseParams) { if (parseParams.isRef && object["@odata.id"] != null) { return convertToReferenceObject(object); } if (parseParams.toCount) { return getFormattedKeyValue("@odata.count", object["@odata.count"])[1] || 0; } } for (const currentKey in object) { if (object[currentKey] != null) { if (Array.isArray(object[currentKey])) { for (var j = 0; j < object[currentKey].length; j++) { object[currentKey][j] = parseData(object[currentKey][j]); } } else if (typeof object[currentKey] === "object") { parseData(object[currentKey]); } } let formattedKeyValue = getFormattedKeyValue(currentKey, object[currentKey]); if (formattedKeyValue[0]) { object[formattedKeyValue[0]] = formattedKeyValue[1]; } if (currentKey.indexOf("_x002e_") !== -1) { const aliasKeys = currentKey.split("_x002e_"); if (!object.hasOwnProperty(aliasKeys[0])) { object[aliasKeys[0]] = { _dwaType: "alias" }; } else if (typeof object[aliasKeys[0]] !== "object" || typeof object[aliasKeys[0]] === "object" && !object[aliasKeys[0]].hasOwnProperty("_dwaType")) { throw new Error("The alias name of the linked entity must be unique!"); } object[aliasKeys[0]][aliasKeys[1]] = object[currentKey]; formattedKeyValue = getFormattedKeyValue(aliasKeys[1], object[currentKey]); if (formattedKeyValue[0]) { object[aliasKeys[0]][formattedKeyValue[0]] = formattedKeyValue[1]; } } } if (parseParams) { if (parseParams.hasOwnProperty("pageNumber") && object["@" + DWA.Prefer.Annotations.FetchXmlPagingCookie] != null) { object.PagingInfo = Utility.getFetchXmlPagingCookie(object["@" + DWA.Prefer.Annotations.FetchXmlPagingCookie], parseParams.pageNumber); } } return object; } function base64ToString(base64) { return true ? window.atob(base64) : Buffer.from(base64, "base64").toString("binary"); } function parseFileResponse(response, responseHeaders, parseParams) { let data = response; if (parseParams?.hasOwnProperty("parse")) { data = JSON.parse(data).value; data = base64ToString(data); } const parseResult = { value: data }; if (responseHeaders["x-ms-file-name"]) parseResult.fileName = responseHeaders["x-ms-file-name"]; if (responseHeaders["x-ms-file-size"]) parseResult.fileSize = parseInt(responseHeaders["x-ms-file-size"]); const location = getHeader(responseHeaders, "Location"); if (location) parseResult.location = location; return parseResult; } function isBatchResponse(response) { return response.indexOf("--batchresponse_") > -1; } function isFileResponse(responseHeaders) { return hasHeader(responseHeaders, "Content-Disposition"); } function isJsonResponse(responseHeaders) { const contentType = getHeader(responseHeaders, "Content-Type"); return contentType?.startsWith("application/json") == true; } function handleBatchResponse(response, parseParams) { const batch = parseBatchResponse(response, parseParams); return parseParams?.[0].convertedToBatch ? batch[0] : batch; } function handleFileResponse(response, responseHeaders, parseParams) { return parseFileResponse(response, responseHeaders, parseParams[0]); } function handleJsonResponse(response, parseParams, requestNumber = 0) { return parseData(JSON.parse(response, dateReviver), parseParams[requestNumber]); } function handlePlainResponse(response) { const numberResponse = Number(response); return isFinite(numberResponse) ? numberResponse : response; } function handleEmptyResponse(responseHeaders, parseParams) { if (parseParams?.[0]?.valueIfEmpty !== void 0) { return parseParams[0].valueIfEmpty; } const entityUrl = getHeader(responseHeaders, "OData-EntityId"); if (entityUrl) { return extractUuidFromUrl(entityUrl) ?? void 0; } const location = getHeader(responseHeaders, "Location"); if (location) { const result = { location }; if (responseHeaders["x-ms-chunk-size"]) { result.chunkSize = parseInt(responseHeaders["x-ms-chunk-size"]); } return result; } } function parseResponse(response, responseHeaders, parseParams) { if (!response.length) { return handleEmptyResponse(responseHeaders, parseParams); } if (isBatchResponse(response)) { return handleBatchResponse(response, parseParams); } if (isFileResponse(responseHeaders)) { return handleFileResponse(response, responseHeaders, parseParams); } if (isJsonResponse(responseHeaders)) { return handleJsonResponse(response, parseParams); } return handlePlainResponse(response); } var init_parseResponse = __esm({ "src/client/helpers/parseResponse.ts"() { "use strict"; init_dwa(); init_Utility(); init_dateReviver(); init_Regex(); init_parseBatchResponse(); } }); // src/client/helpers/parseResponseHeaders.ts function parseResponseHeaders(headerStr) { const headers = {}; if (!headerStr) { return headers; } const headerPairs = headerStr.split("\r\n"); for (let i = 0, ilen = headerPairs.length; i < ilen; i++) { const headerPair = headerPairs[i]; const index = headerPair.indexOf(": "); if (index > 0) { headers[headerPair.substring(0, index)] = headerPair.substring(index + 2); } } return headers; } var init_parseResponseHeaders = __esm({ "src/client/helpers/parseResponseHeaders.ts"() { "use strict"; } }); // src/client/xhr.ts var xhr_exports = {}; __export(xhr_exports, { XhrWrapper: () => XhrWrapper, executeRequest: () => executeRequest }); function executeRequest(options) { return new Promise((resolve, reject) => { _executeRequest(options, resolve, reject); }); } function _executeRequest(options, successCallback, errorCallback) { const data = options.data; const headers = options.headers; const responseParams = options.responseParams; const signal = options.abortSignal; if (signal?.aborted) { errorCallback( ErrorHelper.handleHttpError({ name: "AbortError", code: 20, message: "The user aborted a request." }) ); return; } let request = new XMLHttpRequest(); request.open(options.method, options.uri, options.isAsync || false); for (let key in headers) { request.setRequestHeader(key, headers[key]); } request.onreadystatechange = function() { if (request.readyState === 4) { if (signal) signal.removeEventListener("abort", abort); switch (request.status) { case 200: // Success with content returned in response body. case 201: // Success with content returned in response body. case 204: // Success with no content returned in response body. case 206: // Success with partial content. case 304: { const responseHeaders = parseResponseHeaders(request.getAllResponseHeaders()); const responseData = parseResponse(request.responseText, responseHeaders, responseParams[options.requestId]); const response = { data: responseData, headers: responseHeaders, status: request.status }; request = null; successCallback(response); break; } case 0: break; //response will be handled by onerror default: if (!request) break; let error; let headers2; try { headers2 = parseResponseHeaders(request.getAllResponseHeaders()); const errorParsed = parseResponse(request.responseText, headers2, responseParams[options.requestId]); if (Array.isArray(errorParsed)) { errorCallback(errorParsed); break; } error = errorParsed.error; } catch (e) { if (request.response.length > 0) { error = { message: request.response }; } else { error = { message: "Unexpected Error" }; } } const errorParameters = { status: request.status, statusText: request.statusText, headers: headers2 }; request = null; errorCallback(ErrorHelper.handleHttpError(error, errorParameters)); break; } } }; if (options.timeout) { request.timeout = options.timeout; } request.onerror = function() { const headers2 = parseResponseHeaders(request.getAllResponseHeaders()); errorCallback( ErrorHelper.handleHttpError({ status: request.status, statusText: request.statusText, message: request.responseText || "Network Error", headers: headers2 }) ); request = null; }; request.ontimeout = function() { const headers2 = parseResponseHeaders(request.getAllResponseHeaders()); errorCallback( ErrorHelper.handleHttpError({ name: "TimeoutError", status: request.status, statusText: request.statusText, message: request.responseText || "Request Timed Out", headers: headers2 }) ); request = null; }; request.onabort = function() { if (!request) return; const headers2 = parseResponseHeaders(request.getAllResponseHeaders()); errorCallback( ErrorHelper.handleHttpError({ status: request.status, statusText: request.statusText, message: "Request aborted", headers: headers2 }) ); request = null; }; const abort = () => { if (!request) return; const headers2 = parseResponseHeaders(request.getAllResponseHeaders()); errorCallback( ErrorHelper.handleHttpError({ name: "AbortError", code: 20, status: request.status, statusText: request.statusText, message: "The user aborted a request.", headers: headers2 }) ); request.abort(); request = null; }; if (signal) { signal.addEventListener("abort", abort); } data ? request.send(data) : request.send(); if (XhrWrapper.afterSendEvent) XhrWrapper.afterSendEvent(); } var XhrWrapper; var init_xhr = __esm({ "src/client/xhr.ts"() { "use strict"; init_ErrorHelper(); init_parseResponse(); init_parseResponseHeaders(); XhrWrapper = class { }; } }); // src/utils/Config.ts init_Utility(); init_ErrorHelper(); var getApiUrl = (serverUrl, apiConfig) => { if (Utility.isRunningWithinPortals()) { return new URL("_api", window.location.origin).toString() + "/"; } else { if (!serverUrl) serverUrl = Utility.getClientUrl(); return new URL(`api/${apiConfig.path}/v${apiConfig.version}`, serverUrl).toString() + "/"; } }; var mergeApiConfigs = (apiConfig, apiType, internalConfig) => { const internalApiConfig = internalConfig[apiType]; if (apiConfig?.version) { ErrorHelper.stringParameterCheck(apiConfig.version, "DynamicsWebApi.setConfig", `config.${apiType}.version`); internalApiConfig.version = apiConfig.version; } if (apiConfig?.path) { ErrorHelper.stringParameterCheck(apiConfig.path, "DynamicsWebApi.setConfig", `config.${apiType}.path`); internalApiConfig.path = apiConfig.path; } internalApiConfig.url = getApiUrl(internalConfig.serverUrl, internalApiConfig); }; var ConfigurationUtility = class { static merge(internalConfig, config) { if (config?.serverUrl) { ErrorHelper.stringParameterCheck(config.serverUrl, "DynamicsWebApi.setConfig", "config.serverUrl"); internalConfig.serverUrl = config.serverUrl; } mergeApiConfigs(config?.dataApi, "dataApi", internalConfig); mergeApiConfigs(config?.searchApi, "searchApi", internalConfig); if (config?.impersonate) { internalConfig.impersonate = ErrorHelper.guidParameterCheck(config.impersonate, "DynamicsWebApi.setConfig", "config.impersonate"); } if (config?.impersonateAAD) { internalConfig.impersonateAAD = ErrorHelper.guidParameterCheck(config.impersonateAAD, "DynamicsWebApi.setConfig", "config.impersonateAAD"); } if (config?.onTokenRefresh) { ErrorHelper.callbackParameterCheck(config.onTokenRefresh, "DynamicsWebApi.setConfig", "config.onTokenRefresh"); internalConfig.onTokenRefresh = config.onTokenRefresh; } if (config?.includeAnnotations) { ErrorHelper.stringParameterCheck(config.includeAnnotations, "DynamicsWebApi.setConfig", "config.includeAnnotations"); internalConfig.includeAnnotations = config.includeAnnotations; } if (config?.timeout) { ErrorHelper.numberParameterCheck(config.timeout, "DynamicsWebApi.setConfig", "config.timeout"); internalConfig.timeout = config.timeout; } if (config?.maxPageSize) { ErrorHelper.numberParameterCheck(config.maxPageSize, "DynamicsWebApi.setConfig", "config.maxPageSize"); internalConfig.maxPageSize = config.maxPageSize; } if (config?.returnRepresentation) { ErrorHelper.boolParameterCheck(config.returnRepresentation, "DynamicsWebApi.setConfig", "config.returnRepresentation"); internalConfig.returnRepresentation = config.returnRepresentation; } if (config?.useEntityNames) { ErrorHelper.boolParameterCheck(config.useEntityNames, "DynamicsWebApi.setConfig", "config.useEntityNames"); internalConfig.useEntityNames = config.useEntityNames; } if (config?.headers) { internalConfig.headers = config.headers; } if (false) { ErrorHelper.parameterCheck(config.proxy, "DynamicsWebApi.setConfig", "config.proxy"); if (config.proxy.url) { ErrorHelper.stringParameterCheck(config.proxy.url, "DynamicsWebApi.setConfig", "config.proxy.url"); if (config.proxy.auth) { ErrorHelper.parameterCheck(config.proxy.auth, "DynamicsWebApi.setConfig", "config.proxy.auth"); ErrorHelper.stringParameterCheck(config.proxy.auth.username, "DynamicsWebApi.setConfig", "config.proxy.auth.username"); ErrorHelper.stringParameterCheck(config.proxy.auth.password, "DynamicsWebApi.setConfig", "config.proxy.auth.password"); } } internalConfig.proxy = config.proxy; } } static default() { return { serverUrl: null, impersonate: null, impersonateAAD: null, onTokenRefresh: null, includeAnnotations: null, maxPageSize: null, returnRepresentation: null, proxy: null, dataApi: { path: "data", version: "9.2", url: "" }, searchApi: { path: "search", version: "1.0", url: "" } }; } }; ConfigurationUtility.mergeApiConfigs = mergeApiConfigs; // src/dynamics-web-api.ts init_Utility(); init_ErrorHelper(); // src/client/RequestClient.ts init_Utility(); // src/utils/Request.ts init_Utility(); init_ErrorHelper(); init_Regex(); var entityNames = null; var setEntityNames = (newEntityNames) => { entityNames = newEntityNames; }; var compose = (request, config) => { request.path = request.path || ""; request.functionName = request.functionName || ""; if (!request.url) { if (!request._isUnboundRequest && !request.contentId && !request.collection) { ErrorHelper.parameterCheck(request.collection, `DynamicsWebApi.${request.functionName}`, "request.collection"); } if (request.collection != null) { ErrorHelper.stringParameterCheck(request.collection, `DynamicsWebApi.${request.functionName}`, "request.collection"); request.path = request.collection; if (request.key) { request.key = ErrorHelper.keyParameterCheck(request.key, `DynamicsWebApi.${request.functionName}`, "request.key"); request.path += `(${request.key})`; } } if (request.contentId) { ErrorHelper.stringParameterCheck(request.contentId, `DynamicsWebApi.${request.functionName}`, "request.contentId"); if (request.contentId.startsWith("$")) { request.path = request.path ? `${request.contentId}/${request.path}` : request.contentId; } } if (request.addPath) { if (request.path) { request.path += "/"; } request.path += request.addPath; } request.path = composeUrl(request, config, request.path); if (request.fetchXml) { ErrorHelper.stringParameterCheck(request.fetchXml, `DynamicsWebApi.${request.functionName}`, "request.fetchXml"); let join = request.path.indexOf("?") === -1 ? "?" : "&"; request.path += `${join}fetchXml=${encodeURIComponent(request.fetchXml)}`; } } else { ErrorHelper.stringParameterCheck(request.url, `DynamicsWebApi.${request.functionName}`, "request.url"); request.path = request.url.replace(config.dataApi.url, ""); } if (request.hasOwnProperty("async") && request.async != null) { ErrorHelper.boolParameterCheck(request.async, `DynamicsWebApi.${request.functionName}`, "request.async"); } else { request.async = true; } request.headers = composeHeaders(request, config); return request; }; var composeUrl = (request, config, url = "", joinSymbol = "&") => { const queryArray = []; if (request) { if (request.navigationProperty) { ErrorHelper.stringParameterCheck(request.navigationProperty, `DynamicsWebApi.${request.functionName}`, "request.navigationProperty"); url += "/" + request.navigationProperty; if (request.navigationPropertyKey) { let navigationKey = ErrorHelper.keyParameterCheck( request.navigationPropertyKey, `DynamicsWebApi.${request.functionName}`, "request.navigationPropertyKey" ); url += "(" + navigationKey + ")"; } if (request.navigationProperty === "Attributes") { if (request.metadataAttributeType) { ErrorHelper.stringParameterCheck(request.metadataAttributeType, `DynamicsWebApi.${request.functionName}`, "request.metadataAttributeType"); url += "/" + request.metadataAttributeType; } } } if (request.select?.length) { ErrorHelper.arrayParameterCheck(request.select, `DynamicsWebApi.${request.functionName}`, "request.select"); if (request.functionName == "retrieve" && request.select.length == 1 && request.select[0].endsWith("/$ref")) { url += "/" + request.select[0]; } else { if (request.select[0].startsWith("/") && request.functionName == "retrieve") { if (request.navigationProperty == null) { url += request.select.shift(); } else { request.select.shift(); } } if (request.select.length) { queryArray.push("$select=" + request.select.join(",")); } } } if (request.filter) { ErrorHelper.stringParameterCheck(request.filter, `DynamicsWebApi.${request.functionName}`, "request.filter"); const filterResult = safelyRemoveCurlyBracketsFromUrl(request.filter); queryArray.push("$filter=" + encodeURIComponent(filterResult)); } if (request.fieldName) { ErrorHelper.stringParameterCheck(request.fieldName, `DynamicsWebApi.${request.functionName}`, "request.fieldName"); if (!request.property) request.property = request.fieldName; delete request.fieldName; } if (request.property) { ErrorHelper.stringParameterCheck(request.property, `DynamicsWebApi.${request.functionName}`, "request.property"); url += "/" + request.property; } if (request.savedQuery) { queryArray.push("savedQuery=" + ErrorHelper.guidParameterCheck(request.savedQuery, `DynamicsWebApi.${request.functionName}`, "request.savedQuery")); } if (request.userQuery) { queryArray.push("userQuery=" + ErrorHelper.guidParameterCheck(request.userQuery, `DynamicsWebApi.${request.functionName}`, "request.userQuery")); } if (request.apply) { ErrorHelper.stringParameterCheck(request.apply, `DynamicsWebApi.${request.functionName}`, "request.apply"); queryArray.push("$apply=" + request.apply); } if (request.count) { ErrorHelper.boolParameterCheck(request.count, `DynamicsWebApi.${request.functionName}`, "request.count"); queryArray.push("$count=" + request.count); } if (request.top && request.top > 0) { ErrorHelper.numberParameterCheck(request.top, `DynamicsWebApi.${request.functionName}`, "request.top"); queryArray.push("$top=" + request.top); } if (request.orderBy != null && request.orderBy.length) { ErrorHelper.arrayParameterCheck(request.orderBy, `DynamicsWebApi.${request.functionName}`, "request.orderBy"); queryArray.push("$orderby=" + request.orderBy.join(",")); } if (request.partitionId) { ErrorHelper.stringParameterCheck(request.partitionId, `DynamicsWebApi.${request.functionName}`, "request.partitionId"); queryArray.push("partitionid='" + request.partitionId + "'"); } if (request.downloadSize) { ErrorHelper.stringParameterCheck(request.downloadSize, `DynamicsWebApi.${request.functionName}`, "request.downloadSize"); queryArray.push("size=" + request.downloadSize); } if (request.queryParams?.length) { ErrorHelper.arrayParameterCheck(request.queryParams, `DynamicsWebApi.${request.functionName}`, "request.queryParams"); queryArray.push(request.queryParams.join("&")); } if (request.fileName) { ErrorHelper.stringParameterCheck(request.fileName, `DynamicsWebApi.${request.functionName}`, "request.fileName"); queryArray.push("x-ms-file-name=" + request.fileName); } if (request.data) { ErrorHelper.parameterCheck(request.data, `DynamicsWebApi.${request.functionName}`, "request.data"); } if (request.isBatch) { ErrorHelper.boolParameterCheck(request.isBatch, `DynamicsWebApi.${request.functionName}`, "request.isBatch"); } if (!Utility.isNull(request.inChangeSet)) { ErrorHelper.boolParameterCheck(request.inChangeSet, `DynamicsWebApi.${request.functionName}`, "request.inChangeSet"); } if (request.isBatch && Utility.isNull(request.inChangeSet)) request.inChangeSet = true; if (request.timeout) { ErrorHelper.numberParameterCheck(request.timeout, `DynamicsWebApi.${request.functionName}`, "request.timeout"); } if (request.expand?.length) { ErrorHelper.stringOrArrayParameterCheck(request.expand, `DynamicsWebApi.${request.functionName}`, "request.expand"); if (typeof request.expand === "string") { queryArray.push("$expand=" + request.expand); } else { const expandQueryArray = []; for (const { property, ...expand } of request.expand) { if (!property) continue; const expandRequest = { functionName: `${request.functionName} $expand`, ...expand }; let expandConverted = composeUrl(expandRequest, config, "", ";"); if (expandConverted) { expandConverted = `(${expandConverted.slice(1)})`; } expandQueryArray.push(property + expandConverted); } if (expandQueryArray.length) { queryArray.push("$expand=" + expandQueryArray.join(",")); } } } } return !queryArray.length ? url : url + "?" + queryArray.join(joinSymbol); }; var composeHeaders = (request, config) => { const headers = { ...config.headers, ...request.userHeaders }; const prefer = composePreferHeader(request, config); if (prefer.length) { headers["Prefer"] = prefer; } if (request.collection === "$metadata") { headers["Accept"] = "application/xml"; } if (request.transferMode) { headers["x-ms-transfer-mode"] = request.transferMode; } if (request.ifmatch != null && request.ifnonematch != null) { throw new Error( `DynamicsWebApi.${request.functionName}. Either one of request.ifmatch or request.ifnonematch parameters should be used in a call, not both.` ); } if (request.ifmatch) { ErrorHelper.stringParameterCheck(request.ifmatch, `DynamicsWebApi.${request.functionName}`, "request.ifmatch"); headers["If-Match"] = request.ifmatch; } if (request.ifnonematch) { ErrorHelper.stringParameterCheck(request.ifnonematch, `DynamicsWebApi.${request.functionName}`, "request.ifnonematch"); headers["If-None-Match"] = request.ifnonematch; } if (request.impersonate) { ErrorHelper.stringParameterCheck(request.impersonate, `DynamicsWebApi.${request.functionName}`, "request.impersonate"); headers["MSCRMCallerID"] = ErrorHelper.guidParameterCheck(request.impersonate, `DynamicsWebApi.${request.functionName}`, "request.impersonate"); } if (request.impersonateAAD) { ErrorHelper.stringParameterCheck(request.impersonateAAD, `DynamicsWebApi.${request.functionName}`, "request.impersonateAAD"); headers["CallerObjectId"] = ErrorHelper.guidParameterCheck(request.impersonateAAD, `DynamicsWebApi.${request.functionName}`, "request.impersonateAAD"); } if (request.token) { ErrorHelper.stringParameterCheck(request.token, `DynamicsWebApi.${request.functionName}`, "request.token"); headers["Authorization"] = "Bearer " + request.token; } if (request.duplicateDetection) { ErrorHelper.boolParameterCheck(request.duplicateDetection, `DynamicsWebApi.${request.functionName}`, "request.duplicateDetection"); headers["MSCRM.SuppressDuplicateDetection"] = "false"; } if (request.bypassCustomPluginExecution) { ErrorHelper.boolParameterCheck(request.bypassCustomPluginExecution, `DynamicsWebApi.${request.functionName}`, "request.bypassCustomPluginExecution"); headers["MSCRM.BypassCustomPluginExecution"] = "true"; } if (request.noCache) { ErrorHelper.boolParameterCheck(request.noCache, `DynamicsWebApi.${request.functionName}`, "request.noCache"); headers["Cache-Control"] = "no-cache"; } if (request.mergeLabels) { ErrorHelper.boolParameterCheck(request.mergeLabels, `DynamicsWebApi.${request.functionName}`, "request.mergeLabels"); headers["MSCRM.MergeLabels"] = "true"; } if (request.contentId) { ErrorHelper.stringParameterCheck(request.contentId, `DynamicsWebApi.${request.functionName}`, "request.contentId"); if (!request.contentId.startsWith("$")) { headers["Content-ID"] = request.contentId; } } if (request.contentRange) { ErrorHelper.stringParameterCheck(request.contentRange, `DynamicsWebApi.${request.functionName}`, "request.contentRange"); headers["Content-Range"] = request.contentRange; } if (request.range) { ErrorHelper.stringParameterCheck(request.range, `DynamicsWebApi.${request.functionName}`, "r