UNPKG

@kwiz/common

Version:

KWIZ common utilities and helpers for M365 platform

210 lines 10 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getNSAccuntUrlPrefix = getNSAccuntUrlPrefix; exports.getNsHost = getNsHost; exports.getBundlePage = getBundlePage; exports.nsGetErrorDetails = nsGetErrorDetails; exports.nsObjectFilter = nsObjectFilter; exports.nsIsFeaturedObject = nsIsFeaturedObject; exports.NSCountryToText = NSCountryToText; exports.TextToNSCountry = TextToNSCountry; exports.nsFormatDate = nsFormatDate; exports.nsExpandFields = nsExpandFields; const ns_common_types_1 = require("../../types/ns/ns.common.types"); const ns_countries_rest_1 = require("../../types/ns/ns.countries.rest"); const ns_countries_restlet_1 = require("../../types/ns/ns.countries.restlet"); const collections_base_1 = require("../collections.base"); const typecheckers_1 = require("../typecheckers"); const type_checkers_1 = require("./type-checkers"); const nsEndpointHosts = { suitetalk: '.suitetalk.api.netsuite.com', restlets: '.restlets.api.netsuite.com', ui: '.app.netsuite.com' }; function getNSAccuntUrlPrefix(accountId) { return accountId.replace('_', '-').toLowerCase(); } function getNsHost(accountId, host) { return `https://${getNSAccuntUrlPrefix(accountId)}${nsEndpointHosts[host]}`; } function getBundlePage(info) { if (info.type === "update") return `${getNsHost(info.accountId, "ui")}/app/bundler/previewbundleupdate.nl?fromcompid=${info.orgId}&domain=PRODUCTION&id=${info.id}`; else return `${getNsHost(info.accountId, "ui")}/app/bundler/bundledetails.nl?sourcecompanyid=${info.orgId}&domain=PRODUCTION&config=F&id=${info.id}`; } /** send in either an AxiosError that has a response.data object, or just the data object itself. */ function nsGetErrorDetails(error) { var _a; const data = (0, type_checkers_1.isnsSuiteTalkRestErrorData)(error) ? error : (0, type_checkers_1.isnsSuiteTalkRestErrorData)((_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) ? error.response.data : null; return data; } const ignoreSuffixIfDuplicate = ["WithHierarchy", "Copy", "Display"]; function nsFieldEditableCheck(field, allFields) { if ((0, typecheckers_1.isNullOrEmptyString)(field.title) || field.readOnly || ['id', 'createdDate', 'lastModifiedDate', 'externalId', 'refName'].includes(field.name)) return false; if ((0, typecheckers_1.isNotEmptyArray)(allFields)) { const ending = (0, collections_base_1.firstOrNull)(ignoreSuffixIfDuplicate, suffix => field.name.endsWith(suffix)); if ((0, typecheckers_1.isNotEmptyString)(ending) && allFields.includes(field.name.slice(0, -1 * ending.length))) //got the field without the ending return false; } return true; } function nsObjectFilter(obj) { return (0, typecheckers_1.isNotEmptyString)(obj); } function nsIsFeaturedObject(obj) { return ["account", "lead", "customer"].includes(obj); } /** returns the title of the country or empty string if none found */ function NSCountryToText(country) { var _a, _b; return ((_a = ns_countries_rest_1.nsCountriesByCode[country]) === null || _a === void 0 ? void 0 : _a.title) || ((_b = ns_countries_restlet_1.nsCountriesByEnum[country]) === null || _b === void 0 ? void 0 : _b.title) || ""; } /** returns the code and enum of the best matching country or null if not found */ function TextToNSCountry(country) { if ((0, typecheckers_1.isNullOrEmptyString)(country)) return null; let lowerWords = country.toLowerCase().split(" "); //try to find the best match, until we are left with one option let allOptions = Object.keys(ns_countries_rest_1.nsCountriesByCode); let validOptions = allOptions; for (let i = 0; i < lowerWords.length && validOptions.length > 1; i++) { let word = lowerWords[i]; let newOptions = validOptions.filter(o => ns_countries_rest_1.nsCountriesByCode[o].title.toLowerCase().split(' ').includes(word)); if (newOptions.length > 0) //not empty - use this list validOptions = newOptions; } //done my loop. if I have more than 1 option - pick the best one. if (validOptions.length === 0 || validOptions.length === allOptions.length) return null; //none found else if (validOptions.length === 1) return { code: validOptions[0], enum: ns_countries_rest_1.nsCountriesByCode[validOptions[0]].enum }; else { //if user typed "atlantis" and we have "republic of atlantis" and "atlantis", he would get "atlantis" unless he mentiones "republic" as well let option = validOptions[0]; let optionTitleSplit = ns_countries_rest_1.nsCountriesByCode[option].title.split(' '); validOptions.forEach(o => { const oTitleSplit = ns_countries_rest_1.nsCountriesByCode[o].title.split(' '); if (oTitleSplit.length < optionTitleSplit.length) { option = o; optionTitleSplit = oTitleSplit; } }); return { code: option, enum: ns_countries_rest_1.nsCountriesByCode[option].enum }; } } function nsFormatDate(date, fieldType) { if (!date || isNaN(date.getTime())) return ""; const pad = (n) => n.toString().padStart(2, '0'); const yyyy = date.getUTCFullYear(); const mm = pad(date.getUTCMonth() + 1); const dd = pad(date.getUTCDate()); const hh = pad(date.getUTCHours()); const min = pad(date.getUTCMinutes()); const ss = pad(date.getUTCSeconds()); switch (fieldType) { case 'date': // YYYY-MM-DD return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`; case 'datetime': case 'datetimetz': // YYYY-MM-DDTHH:mm:ssZ // Note: .toISOString() includes milliseconds, which is usually fine, // but this manual string ensures exact compliance. return `${yyyy}-${mm}-${dd}T${hh}:${min}:${ss}Z`; case 'time': case 'timeofday': // HH:mm:ss (NetSuite often accepts HH:mm for timeofday) return `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`; case 'mmyydate': // MM/YYYY return `${pad(date.getMonth() + 1)}/${date.getFullYear()}`; default: return date.toISOString(); } } const ghostFieldPrefixes = ['_', 'nsapi']; const systemReadOnlyFields = [ //body fields 'id', 'internalid', 'createddate', 'lastmodifieddate', 'owner', 'status', 'total', 'subtotal', 'tranid', 'wfinstances', 'entryformquerystring', //sublist fields 'line', 'linenumber', 'quantityonhand', 'quantityavailable', 'taxrate' ]; function tnsrFieldEditableCheck(field, info = {}) { return field.isVisible !== false && !systemReadOnlyFields.includes(field.id.toLowerCase()) && !(info.inSubList ? ns_common_types_1.nsReadOnlyFieldTypesForSublist : ns_common_types_1.nsReadOnlyFieldTypes).includes(field.type) //also remove system / ghost fields by prefix && !ghostFieldPrefixes.some(pre => field.id.startsWith(pre)); } /** get the REST api fields, and restlet api fields and return a full field exanded info */ function nsExpandFields(restFields, restletFields) { const expandedFields = {}; const restFieldsLower = {}; const allRestFields = Object.keys(restFields); allRestFields.map(f => restFieldsLower[f.toLowerCase()] = { ...restFields[f], name: f }); restletFields.bodyFields.forEach(bodyField => { const restField = restFieldsLower[bodyField.id]; if (restField) { delete restFieldsLower[bodyField.id]; //remove it from extra fields loop } let readOnly = !tnsrFieldEditableCheck(bodyField); expandedFields[bodyField.id] = { restId: restField === null || restField === void 0 ? void 0 : restField.name, restType: restField === null || restField === void 0 ? void 0 : restField.type, description: restField === null || restField === void 0 ? void 0 : restField.description, id: bodyField.id, label: bodyField.label || (restField === null || restField === void 0 ? void 0 : restField.title) || bodyField.id, type: bodyField.type, defaultValue: bodyField.defaultValue, options: bodyField.options, required: bodyField.isMandatory === true, readOnly }; }); if (restletFields.sublists) Object.keys(restletFields.sublists).forEach(sublist => { delete restFieldsLower[sublist]; //sublists will show up as rest fields }); Object.keys(restFieldsLower).forEach(f => { const restField = restFieldsLower[f]; switch (restField.type) { case "string": case "number": case "boolean": case "integer": expandedFields[f] = { id: f, required: restField.nullable !== true, label: restField.title, description: restField.description, type: restField.type === "string" ? "text" : restField.type === "boolean" ? "checkbox" : restField.type === "number" ? restField.format === "double" ? "currency" : restField.format === "float" ? "float" : "integer" : restField.type === "integer" ? "integer" : "text", restId: restField.name, restType: restField.type, readOnly: !nsFieldEditableCheck(restField, allRestFields) }; break; } }); return expandedFields; } //# sourceMappingURL=utilities.js.map