UNPKG

esi-cap

Version:

Enterprise System Integration Based on SAP CAP

484 lines (325 loc) 15.1 kB
# esi-cap Utilities API Reference > **Module:** `src/lib/utils/index.js` > **Purpose:** Core utility belt for the esi-cap framework date validation, XML parsing, JSON manipulation, array operations, and UUID generation/parsing. --- ## Table of Contents - [Dependencies](#dependencies) - [Exports](#exports) - [Namespace: `date`](#namespace-date) - [date.isValid(sDate)](#dateisvalidsdate) - [Namespace: `xml`](#namespace-xml) - [xml.isValid(oXML)](#xmlisvalidoxml) - [Namespace: `json`](#namespace-json) - [json.isValid(oJson)](#jsonisvalidojson) - [json.copy(oJson)](#jsoncopyojson) - [json.replace(oJson, sOldValue, sNewValue, oEvaluate?)](#jsonreplaceojson-soldvalue-snewvalue-oevaluate) - [json.getValue(oJson, sPropertyPath)](#jsongetvalueojson-spropertypath) - [json.unique(oNestedArray)](#jsonuniqueonnestedarray) - [json.order(oJson, oKeyOrder)](#jsonorderojson-okeyorder) - [json.projection(oJson, oColumns, bHasAssociattion?)](#jsonprojectionojson-ocolumns-bhasassociattion) - [json.map(oJson, oMap)](#jsonmapojson-omap) - [json.merge(oJson1, oJson2)](#jsonmergeojson1-ojson2) - [json.flat(oJson, sFlattenedProperty)](#jsonflatojson-sflattenedproperty) - [json.stripUndefined(oSourceJson)](#jsonstripundefinedosourcejson) - [Namespace: `array`](#namespace-array) - [array.add(oArray, oItem)](#arrayaddoarray-oitem) - [array.topN(oSortedArray, iTop)](#arraytopnosortedarray-itop) - [array.flat(oArray, sFlattenedProperty)](#arrayflatoarray-sflattenedproperty) - [array.unique(oArray)](#arrayuniqueoarray) - [array.order(oArray, oOrder)](#arrayorderoarray-oorder) - [array.projection(oArray, oColumns, bHasAssociattion?)](#arrayprojectionoarray-ocolumns-bhasassociattion) - [array.map(oArray, oMap)](#arraymapoarray-omap) - [array.sort(oArray, oOrderBy)](#arraysortoarray-oorderby) - [array.filter(oArray, oFilterCondition)](#arrayfilteroarray-ofiltercondition) - [array.hasElement(oArray, oElement)](#arrayhaselementoarray-oelement) - [array.toArray(oArray)](#arraytoarrayoarray) - [array.toDisArray(oArray)](#arraytodisarrayoarray) - [array.toInterleavedArray(oArray, oElement)](#arraytointerleavedarray-oarray-oelement) - [array.toArrayProjection(oArray, sProjectionFieldName)](#arraytoarrayprojectionoarray-sprojectionfieldname) - [array.findProperty(oArray, sProjectionFieldName)](#arrayfindpropertyoarray-sprojectionfieldname) - [array.toGroupByPropertyName(oArray, sPropertyName)](#arraytogroupbypropertynameoarray-spropertyname) - [array.toGroupByPropertyList(oArray, oPropertyList)](#arraytogroupbypropertylistoarray-opropertylist) - [Class: `UUID`](#class-uuid) - [constructor()](#constructor) - [converse(oJsonData)](#converseoJsondata) - [inverse(sUUID)](#inversesuuid) --- ## Dependencies | Package | Purpose | |----------|-------------------------------------------------| | `xml2js` | XML string parsing and validation | | `uuid` | UUID format validation | | `lodash` | Deep merge, orderBy, uniqWith, and isEqual | | `../_interface` | Internal logger and `_LOG` constant | --- ## Exports ```js module.exports = { date, xml, json, array, UUID, _LOG }; ``` --- ## Namespace: `date` Date-related validation helpers. ### `date.isValid(sDate)` | Parameter | Type | Description | |-----------|----------|--------------------------------------| | `sDate` | `string` | Date string to validate | | **Returns** | `Promise<boolean>` | `true` if valid date | **Behavior:** Parses the string via `new Date()` and verifies the result is a real Date (not `NaN`). Logs errors via the framework logger. ```js await date.isValid("2026-04-20"); // true await date.isValid("not-a-date"); // false ``` --- ## Namespace: `xml` XML parsing and validation helpers. ### `xml.isValid(oXML)` | Parameter | Type | Description | |-----------|------------------|-----------------------------| | `oXML` | `string\|object` | XML content to validate | | **Returns** | `Promise<boolean>` | `true` if well-formed XML | **Behavior:** Uses `xml2js.Parser.parseStringPromise` to attempt parsing. Logs the parsed result on success and errors on failure. ```js await xml.isValid("<root><item>val</item></root>"); // true await xml.isValid("not xml"); // false ``` --- ## Namespace: `json` Comprehensive JSON/object manipulation utilities. ### `json.isValid(oJson)` Checks if the input can be parsed as JSON via `JSON.parse`. | Parameter | Type | Returns | |-----------|------------------|------------| | `oJson` | `string\|object` | `boolean` | --- ### `json.copy(oJson)` Creates a deep clone using `structuredClone`. Falls back to returning the original reference if the input isn't valid JSON. | Parameter | Type | Returns | |-----------|----------|----------| | `oJson` | `object` | `object` | --- ### `json.replace(oJson, sOldValue, sNewValue, oEvaluate?)` Recursively walks objects and arrays, replacing all string occurrences of `sOldValue` with `sNewValue`. **Mutates the input in place.** | Parameter | Type | Default | Description | |-------------|----------|-------------|----------------------------------------------------------| | `oJson` | `object\|Array` | | Target structure | | `sOldValue` | `string` | | Substring to find | | `sNewValue` | `string` | | Replacement substring | | `oEvaluate` | `object` | `undefined` | Optional context; when set, resolved string is evaluated as a property path via `json.getValue` | ```js const data = { msg: "Hello {{name}}", nested: { msg: "Hi {{name}}" } }; json.replace(data, "{{name}}", "World"); // data { msg: "Hello World", nested: { msg: "Hi World" } } ``` --- ### `json.getValue(oJson, sPropertyPath)` Resolves a dot-separated property path to its value. | Parameter | Type | Returns | |-----------------|----------|---------| | `oJson` | `object` | `*` | | `sPropertyPath` | `string` | Value or `undefined` | ```js json.getValue({ a: { b: { c: 42 } } }, "a.b.c"); // 42 json.getValue({ a: 1 }, "x.y"); // undefined ``` --- ### `json.unique(oNestedArray)` Flattens a nested array and removes duplicates using JSON serialization for deep equality. | Parameter | Type | Returns | |----------------|---------|---------| | `oNestedArray` | `any[]` | `any[]` | --- ### `json.order(oJson, oKeyOrder)` Returns a new object with keys reordered: specified keys first, then the rest. | Parameter | Type | Returns | |------------|------------|----------| | `oJson` | `object` | `object` | | `oKeyOrder` | `string[]` | | ```js json.order({ c: 3, a: 1, b: 2 }, ["a", "b"]); // { a: 1, b: 2, c: 3 } ``` --- ### `json.projection(oJson, oColumns, bHasAssociattion?)` Filters an object to include only the specified properties. | Parameter | Type | Default | Description | |-------------------|------------|---------|----------------------------------------------| | `oJson` | `object` | | Source object | | `oColumns` | `string[]` | | Property names to keep | | `bHasAssociattion` | `boolean` | `false` | Also include keys prefixed with column names | --- ### `json.map(oJson, oMap)` Creates a new object by mapping source properties via a definition object. | Parameter | Type | Description | |-----------|----------|-------------------------------------------------------| | `oJson` | `object` | Source data | | `oMap` | `object` | `{ targetKey: "source.path" }` mapping definition | ```js json.map({ user: { name: "John" } }, { fullName: "user.name" }); // { fullName: "John" } ``` --- ### `json.merge(oJson1, oJson2)` Deep-merges two objects using Lodash `_.merge`. Returns `{}` if either argument is not an object. --- ### `json.flat(oJson, sFlattenedProperty)` Promotes a nested property's contents to the top level of the object. ```js json.flat({ id: 1, details: { name: "A", desc: "B" } }, "details"); // { id: 1, name: "A", desc: "B" } ``` --- ### `json.stripUndefined(oSourceJson)` Removes properties where the value is `undefined`, `null`, or an empty string. --- ## Namespace: `array` Array operations with automatic fallback to `json` namespace for single-object inputs. ### `array.add(oArray, oItem)` Appends item(s) to an array. Accepts single values or arrays. --- ### `array.topN(oSortedArray, iTop)` Returns the first `iTop` elements via `Array.slice`. --- ### `array.flat(oArray, sFlattenedProperty)` Flattens a nested property for each element. Delegates to `json.flat` for single objects. --- ### `array.unique(oArray)` Deduplicates using Lodash `_.uniqWith` with `_.isEqual` for deep comparison. --- ### `array.order(oArray, oOrder)` Reorders keys for every object in the array per the specified key order. --- ### `array.projection(oArray, oColumns, bHasAssociattion?)` Projects each element to only contain the listed columns. --- ### `array.map(oArray, oMap)` Applies a property mapping to every element in the array. --- ### `array.sort(oArray, oOrderBy)` Multi-column sort with type coercion support. | `oOrderBy` entry | Property | Type | Description | |---|---|---|---| | `ref` | `string[]` | Required | Column path | | `sort` | `'asc'\|'desc'` | Optional (default `'asc'`) | Sort direction | | `function` | `'Date'\|'parseFloat'` | Optional | Value coercion | ```js array.sort(items, [ { ref: ["date"], sort: "desc", function: "Date" }, { ref: ["price"], sort: "asc", function: "parseFloat" } ]); ``` --- ### `array.filter(oArray, oFilterCondition)` Filters array elements based on a list of filter conditions (AND logic). **FilterCondition:** | Property | Type | Description | |---|---|---| | `name` | `string` | Property name to filter by | | `op` | `'='\|'!='\|'>'\|'<'\|'>='\|'<='` | Comparison operator | | `value` | `string\|number\|boolean` | Value to compare against | ```js array.filter(employees, [ { name: "age", op: ">=", value: 30 }, { name: "dept", op: "=", value: "Engineering" } ]); ``` --- ### `array.hasElement(oArray, oElement)` Returns `true` if the element is found (strict `===` via `Array.includes`). --- ### `array.toArray(value)` Normalizes any value into an array: `undefined` `[]`, non-array `[value]`, array as-is. --- ### `array.toDisArray(oArray)` Unwraps a single-element array to its value. Multi-element arrays pass through. --- ### `array.toInterleavedArray(oArray, oElement)` Inserts a separator element between consecutive items. ```js array.toInterleavedArray(["a", "b", "c"], "|"); // ["a", ["|"], "b", ["|"], "c"] ``` --- ### `array.toArrayProjection(oArray, sProjectionFieldName)` Extracts a single field from each element into a flat array. ```js array.toArrayProjection([{ id: 1 }, { id: 2 }], "id"); // [1, 2] ``` --- ### `array.findProperty(oArray, sProjectionFieldName)` Recursively searches nested structures for all values of a named property. Returns a deduplicated array. --- ### `array.toGroupByPropertyName(oArray, sPropertyName)` Groups elements into an object keyed by a single property's value. ```js array.toGroupByPropertyName( [{ type: "A", v: 1 }, { type: "B", v: 2 }, { type: "A", v: 3 }], "type" ); // { A: [{...}, {...}], B: [{...}] } ``` --- ### `array.toGroupByPropertyList(oArray, oPropertyList)` Groups elements by a composite key derived from multiple properties (joined with `##`). Supports dot-notation paths and recursive deep property lookup. ```js array.toGroupByPropertyList(data, ["region", "details.category"]); // { "US##Electronics": [...], "EU##Clothing": [...] } ``` --- ## Class: `UUID` Singleton class for deterministic UUID generation and parsing based on a fixed field configuration. Encodes/decodes structured business data (CompanyCode, PersonWorkAgreementExternalID, TimeSheetRecord) into RFC-4122-compliant UUIDs. ### Constructor ```js const uuidHelper = new UUID(); ``` Creates a singleton instance. Subsequent `new UUID()` calls return the same instance. **Internal field configuration:** | Field | Order | Format (Regex) | Description | |---|---|---|---| | `CompanyCode` | 1 | `/^[A-Za-z]{2}\d{2}$/` | 2 letters + 2 digits | | `PersonWorkAgreementExternalID` | 2 | `/^[Ii]\d{7}$\|^\d{1,9}$/` | I-number or numeric ID | | `TimeSheetRecord` | 3 | `/^\d{12}$/` | 12-digit record number | --- ### `converse(oJsonData)` Encodes structured JSON data into a deterministic UUID. | Parameter | Type | Description | |------------|----------|-------------------------------------------| | `oJsonData` | `object` | Object with `CompanyCode`, `PersonWorkAgreementExternalID`, `TimeSheetRecord` | | **Returns** | `string` | A valid UUID string | | **Throws** | `Error` | If any field has an invalid format or the generated UUID fails validation | ```js const uid = new UUID(); uid.converse({ CompanyCode: "AB12", PersonWorkAgreementExternalID: "I1234567", TimeSheetRecord: "000000012345" }); // Returns a valid UUID string e.g., "c0656612-2e12-4345-8670-000000012345" ``` --- ### `inverse(sUUID)` Decodes a previously generated UUID back into its original structured data. | Parameter | Type | Description | |-----------|----------|------------------------------------| | `sUUID` | `string` | A UUID previously created by `converse` | | **Returns** | `object` | `{ CompanyCode, PersonWorkAgreementExternalID, TimeSheetRecord }` or `{}` if invalid | ```js const uid = new UUID(); uid.inverse("c0656612-2e12-4345-8670-000000012345"); // { CompanyCode: "AB12", PersonWorkAgreementExternalID: "I1234567", TimeSheetRecord: "000000012345" } ``` --- ## Quick Usage Examples ```js const { date, xml, json, array, UUID } = require('./src/lib/utils'); // Validate & transform const valid = await date.isValid("2026-04-20"); const items = [{ id: 1, name: "A" }, { id: 2, name: "B" }]; // Project, sort, filter const names = array.toArrayProjection(items, "name"); // ["A", "B"] const sorted = array.sort(items, [{ ref: ["id"], sort: "desc" }]); const filtered = array.filter(items, [{ name: "id", op: ">", value: 1 }]); // Group & merge const grouped = array.toGroupByPropertyName(items, "name"); const merged = json.merge({ a: 1 }, { b: 2 }); // { a: 1, b: 2 } // UUID round-trip const uid = new UUID(); const uuidStr = uid.converse({ CompanyCode: "AB12", PersonWorkAgreementExternalID: "I1234567", TimeSheetRecord: "000000012345" }); const original = uid.inverse(uuidStr); ```