@hamak/shared-utils 0.4.1
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.
- package/dist/core-utils-chrono.d.ts +8 -0
- package/dist/core-utils-chrono.d.ts.map +1 -0
- package/dist/core-utils-chrono.js +16 -0
- package/dist/core-utils-comparator.d.ts +11 -0
- package/dist/core-utils-comparator.d.ts.map +1 -0
- package/dist/core-utils-comparator.js +22 -0
- package/dist/core-utils-file.d.ts +10 -0
- package/dist/core-utils-file.d.ts.map +1 -0
- package/dist/core-utils-file.js +1 -0
- package/dist/core-utils-filesystem.d.ts +69 -0
- package/dist/core-utils-filesystem.d.ts.map +1 -0
- package/dist/core-utils-filesystem.js +156 -0
- package/dist/core-utils-fqn.d.ts +11 -0
- package/dist/core-utils-fqn.d.ts.map +1 -0
- package/dist/core-utils-fqn.js +19 -0
- package/dist/core-utils-pathway-resolver.d.ts +20 -0
- package/dist/core-utils-pathway-resolver.d.ts.map +1 -0
- package/dist/core-utils-pathway-resolver.js +31 -0
- package/dist/core-utils-pathway.d.ts +84 -0
- package/dist/core-utils-pathway.d.ts.map +1 -0
- package/dist/core-utils-pathway.js +206 -0
- package/dist/core-utils-registry.d.ts +7 -0
- package/dist/core-utils-registry.d.ts.map +1 -0
- package/dist/core-utils-registry.js +22 -0
- package/dist/core-utils-resolver.d.ts +33 -0
- package/dist/core-utils-resolver.d.ts.map +1 -0
- package/dist/core-utils-resolver.js +65 -0
- package/dist/core-utils-stack.d.ts +20 -0
- package/dist/core-utils-stack.d.ts.map +1 -0
- package/dist/core-utils-stack.js +47 -0
- package/dist/core-utils-types-hkt.d.ts +12 -0
- package/dist/core-utils-types-hkt.d.ts.map +1 -0
- package/dist/core-utils-types-hkt.js +1 -0
- package/dist/core-utils-types.d.ts +83 -0
- package/dist/core-utils-types.d.ts.map +1 -0
- package/dist/core-utils-types.js +39 -0
- package/dist/core-utils-validations.d.ts +21 -0
- package/dist/core-utils-validations.d.ts.map +1 -0
- package/dist/core-utils-validations.js +18 -0
- package/dist/core-utils.d.ts +39 -0
- package/dist/core-utils.d.ts.map +1 -0
- package/dist/core-utils.js +113 -0
- package/dist/es2015/core-utils-chrono.js +16 -0
- package/dist/es2015/core-utils-comparator.js +22 -0
- package/dist/es2015/core-utils-file.js +1 -0
- package/dist/es2015/core-utils-filesystem.js +157 -0
- package/dist/es2015/core-utils-fqn.js +19 -0
- package/dist/es2015/core-utils-pathway-resolver.js +31 -0
- package/dist/es2015/core-utils-pathway.js +206 -0
- package/dist/es2015/core-utils-registry.js +22 -0
- package/dist/es2015/core-utils-resolver.js +68 -0
- package/dist/es2015/core-utils-stack.js +47 -0
- package/dist/es2015/core-utils-types-hkt.js +1 -0
- package/dist/es2015/core-utils-types.js +39 -0
- package/dist/es2015/core-utils-validations.js +18 -0
- package/dist/es2015/core-utils.js +113 -0
- package/dist/es2015/index.js +24 -0
- package/dist/es2015/itinerary/hyper-layer-node.js +21 -0
- package/dist/es2015/itinerary/itinerary.js +276 -0
- package/dist/es2015/itinerary/stack.js +47 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/itinerary/hyper-layer-node.d.ts +12 -0
- package/dist/itinerary/hyper-layer-node.d.ts.map +1 -0
- package/dist/itinerary/hyper-layer-node.js +21 -0
- package/dist/itinerary/itinerary.d.ts +86 -0
- package/dist/itinerary/itinerary.d.ts.map +1 -0
- package/dist/itinerary/itinerary.js +275 -0
- package/dist/itinerary/stack.d.ts +20 -0
- package/dist/itinerary/stack.d.ts.map +1 -0
- package/dist/itinerary/stack.js +47 -0
- package/package.json +41 -0
- package/src/core-utils-chrono.ts +21 -0
- package/src/core-utils-comparator.ts +27 -0
- package/src/core-utils-file.ts +10 -0
- package/src/core-utils-filesystem.spec.ts +63 -0
- package/src/core-utils-filesystem.ts +232 -0
- package/src/core-utils-fqn.ts +17 -0
- package/src/core-utils-pathway-resolver.ts +36 -0
- package/src/core-utils-pathway.ts +232 -0
- package/src/core-utils-registry.ts +23 -0
- package/src/core-utils-resolver.ts +75 -0
- package/src/core-utils-stack.spec.ts +42 -0
- package/src/core-utils-stack.ts +62 -0
- package/src/core-utils-types-hkt.ts +9 -0
- package/src/core-utils-types.ts +127 -0
- package/src/core-utils-validations.ts +36 -0
- package/src/core-utils.spec.ts +56 -0
- package/src/core-utils.ts +139 -0
- package/src/index.ts +34 -0
- package/src/itinerary/hyper-layer-node.ts +25 -0
- package/src/itinerary/itinerary.spec.ts +388 -0
- package/src/itinerary/itinerary.ts +363 -0
- package/src/itinerary/stack.spec.ts +46 -0
- package/src/itinerary/stack.ts +62 -0
- package/tsconfig.es2015.json +24 -0
- package/tsconfig.json +19 -0
- package/vitest.config.ts +8 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export function head(value) {
|
|
2
|
+
return { value };
|
|
3
|
+
}
|
|
4
|
+
export function push(head, value) {
|
|
5
|
+
return { value, parent: head };
|
|
6
|
+
}
|
|
7
|
+
export function concat(tail, stack) {
|
|
8
|
+
if (tail === undefined)
|
|
9
|
+
return stack;
|
|
10
|
+
if (stack === undefined)
|
|
11
|
+
return tail;
|
|
12
|
+
const { parent, value } = stack;
|
|
13
|
+
return { value, parent: concat(tail, parent) };
|
|
14
|
+
}
|
|
15
|
+
export function fromArray(t) {
|
|
16
|
+
return t === null || t === void 0 ? void 0 : t.reduce((acc, t) => push(acc, t), undefined);
|
|
17
|
+
}
|
|
18
|
+
export function reduce(head, reducer, initial) {
|
|
19
|
+
if (head === undefined) {
|
|
20
|
+
return initial;
|
|
21
|
+
}
|
|
22
|
+
const { parent, value } = head;
|
|
23
|
+
const acc = reduce(parent, reducer, initial);
|
|
24
|
+
return reducer(acc, value);
|
|
25
|
+
}
|
|
26
|
+
function equal(a, b) {
|
|
27
|
+
// Not equal if both are nullish
|
|
28
|
+
if (a === undefined || a === null || b === undefined || b === null) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
while (a !== undefined && b !== undefined) {
|
|
32
|
+
if (a.value !== b.value) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
a = a.parent;
|
|
36
|
+
b = b.parent;
|
|
37
|
+
}
|
|
38
|
+
// Equal if traversed all stack at both side
|
|
39
|
+
if ((a === undefined || a === null) && (b === undefined || b === null)) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const stack = { push, head, concat, reduce, fromArray, equal };
|
|
47
|
+
export default stack;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export function holder(value) {
|
|
2
|
+
return { value };
|
|
3
|
+
}
|
|
4
|
+
export function hyper(data, children) {
|
|
5
|
+
return { data, children };
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Utility function that create Overlay which mirror original object
|
|
9
|
+
* @param o
|
|
10
|
+
*/
|
|
11
|
+
export function hyperReflect(o) {
|
|
12
|
+
if (o === null || o === undefined) {
|
|
13
|
+
return hyper(o);
|
|
14
|
+
}
|
|
15
|
+
else if (Array.isArray(o)) {
|
|
16
|
+
return hyper(o, o.map(e => hyperReflect(e)));
|
|
17
|
+
}
|
|
18
|
+
else if (typeof o === "object") {
|
|
19
|
+
return hyper(o, Object.entries(o).reduce((acc, [k, v]) => (Object.assign(Object.assign({}, acc), { [k]: hyperReflect(v) })), {}));
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
return hyper(o);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Mainly used to prevent re-entrant navitation
|
|
27
|
+
*/
|
|
28
|
+
export class ExplorationContext {
|
|
29
|
+
constructor(parent, values) {
|
|
30
|
+
this.parent = parent;
|
|
31
|
+
this.values = values;
|
|
32
|
+
}
|
|
33
|
+
explored(t) {
|
|
34
|
+
return this.values.includes(t);
|
|
35
|
+
}
|
|
36
|
+
newChild(values) {
|
|
37
|
+
return new ExplorationContext(this, values);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class NoteUtils {
|
|
2
|
+
add(nv, ...notes) {
|
|
3
|
+
return Object.assign(Object.assign({}, (nv !== null && nv !== void 0 ? nv : { type: "core:node-validation" })), { notes });
|
|
4
|
+
}
|
|
5
|
+
of(...notes) {
|
|
6
|
+
return { type: "core:node-validation", notes };
|
|
7
|
+
}
|
|
8
|
+
info(key, message, params) {
|
|
9
|
+
return { severity: "info", key, message, params };
|
|
10
|
+
}
|
|
11
|
+
warning(key, message, params) {
|
|
12
|
+
return { severity: "warning", key, message, params };
|
|
13
|
+
}
|
|
14
|
+
error(key, message, params) {
|
|
15
|
+
return { severity: "error", key, message, params };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export const notes = new NoteUtils();
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
function includes(arr, t) {
|
|
2
|
+
return arr === undefined ? false : arr.includes(t);
|
|
3
|
+
}
|
|
4
|
+
export function isNonNullObject(data) {
|
|
5
|
+
if (data === null || data === undefined) {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
const dataType = typeof data;
|
|
9
|
+
return dataType === 'object' && !Array.isArray(data);
|
|
10
|
+
}
|
|
11
|
+
function isBlank(s) {
|
|
12
|
+
return s === null || s === undefined || s.trim() === "";
|
|
13
|
+
}
|
|
14
|
+
function isDefined(data) {
|
|
15
|
+
return data !== null && data !== undefined;
|
|
16
|
+
}
|
|
17
|
+
function isNotDefined(data) {
|
|
18
|
+
return !isDefined(data);
|
|
19
|
+
}
|
|
20
|
+
export function isNullish(o) {
|
|
21
|
+
return o === null || o === undefined;
|
|
22
|
+
}
|
|
23
|
+
export function isEmptyObject(object) {
|
|
24
|
+
for (const property in object) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
export function equalSet(a, b) {
|
|
30
|
+
return a.size === b.size && [...a].every((x) => b.has(x));
|
|
31
|
+
}
|
|
32
|
+
export const DEFAULT_EQUAL_FN = (a, b) => a === b;
|
|
33
|
+
export function areSameDefined(a, b, equalFn) {
|
|
34
|
+
if (a === undefined || b === undefined) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
if (a === null || b === null) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
return a === b || (equalFn ? equalFn(a, b) : false);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Warning: non performant O(n2)
|
|
44
|
+
* @param arr
|
|
45
|
+
* @param equals
|
|
46
|
+
*/
|
|
47
|
+
export function removeDuplicates(arr, equals = DEFAULT_EQUAL_FN) {
|
|
48
|
+
return arr.filter((item, index) => arr.findIndex((e, i) => i < index && equals(item, e)) === -1);
|
|
49
|
+
}
|
|
50
|
+
// export function removeDuplicatesAndUndefined<T>(arr : (T|undefined)[], equals : EqualFn<T> = DEFAULT_EQUAL_FN) : T[] {
|
|
51
|
+
// return arr.filter((item, index) : item is T => item !== undefined && arr.findIndex((e,i) => i < index && equals(item, e)) === -1)
|
|
52
|
+
// }
|
|
53
|
+
function intersection(o1, o2) {
|
|
54
|
+
return Object.keys(o1).filter({}.hasOwnProperty.bind(o2));
|
|
55
|
+
}
|
|
56
|
+
function deepEqual(obj1, obj2) {
|
|
57
|
+
if (obj1 === obj2) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
if (obj1 === null || obj2 === null || typeof obj1 !== 'object' || typeof obj2 !== 'object') {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
if (Array.isArray(obj1) !== Array.isArray(obj2)) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
const keys1 = Object.keys(obj1);
|
|
67
|
+
const keys2 = Object.keys(obj2);
|
|
68
|
+
if (keys1.length !== keys2.length) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
for (const key of keys1) {
|
|
72
|
+
if (!keys2.includes(key)) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
if (!deepEqual(obj1[key], obj2[key])) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
function escapeForXPath(input) {
|
|
82
|
+
if (input.includes("'")) {
|
|
83
|
+
if (input.includes('"')) {
|
|
84
|
+
// Si la chaîne contient à la fois des guillemets simples et doubles
|
|
85
|
+
const parts = input.split("'");
|
|
86
|
+
return "concat(" + parts.map(part => `'${part}'`).join(", \"'\", ") + ")";
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
// Si la chaîne ne contient que des guillemets simples
|
|
90
|
+
return `"${input}"`;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
// Si la chaîne ne contient que des guillemets doubles ou aucun guillemet
|
|
95
|
+
return `'${input}'`;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// TODO rename this function
|
|
99
|
+
function cascadeFilter(arr, fns) {
|
|
100
|
+
if (arr.length === 0) {
|
|
101
|
+
return arr;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
for (const filterFn of fns) {
|
|
105
|
+
const filtered = arr.filter(filterFn);
|
|
106
|
+
if (filtered.length > 0) {
|
|
107
|
+
return filtered;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return arr;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
export const utils = { includes, isNonNullObject, isEmptyObject, equalSet, isDefined, isBlank, isNotDefined, removeDuplicates, areSameDefined, intersection, deepEqual, escapeForXPath, cascadeFilter };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Type utilities
|
|
2
|
+
export * from './core-utils-types-hkt';
|
|
3
|
+
export * from './core-utils-types';
|
|
4
|
+
export { default } from './core-utils-stack';
|
|
5
|
+
// Core utilities
|
|
6
|
+
export { utils, DEFAULT_EQUAL_FN, removeDuplicates, areSameDefined } from './core-utils';
|
|
7
|
+
// Resolvers
|
|
8
|
+
export * from './core-utils-resolver';
|
|
9
|
+
// Path and navigation utilities
|
|
10
|
+
export * from './core-utils-pathway';
|
|
11
|
+
export * from './core-utils-pathway-resolver';
|
|
12
|
+
// Itinerary utilities
|
|
13
|
+
export * from './itinerary/itinerary';
|
|
14
|
+
export * from './itinerary/stack';
|
|
15
|
+
// Note: HyperLayerNode is exported from core-utils-types (more complete version with HKT)
|
|
16
|
+
// Filesystem utilities
|
|
17
|
+
export * from './core-utils-filesystem';
|
|
18
|
+
// Other utilities
|
|
19
|
+
export * from './core-utils-file';
|
|
20
|
+
export * from './core-utils-registry';
|
|
21
|
+
export * from './core-utils-chrono';
|
|
22
|
+
export * from './core-utils-comparator';
|
|
23
|
+
export * from './core-utils-fqn';
|
|
24
|
+
export * from './core-utils-validations';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function hyper(data, children) {
|
|
2
|
+
return { data, children };
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Utility function that create Overlay which mirror original object
|
|
6
|
+
* @param o
|
|
7
|
+
*/
|
|
8
|
+
export function hyperReflect(o) {
|
|
9
|
+
if (o === null || o === undefined) {
|
|
10
|
+
return hyper(o);
|
|
11
|
+
}
|
|
12
|
+
else if (Array.isArray(o)) {
|
|
13
|
+
return hyper(o, o.map(e => hyperReflect(e)));
|
|
14
|
+
}
|
|
15
|
+
else if (typeof o === "object") {
|
|
16
|
+
return hyper(o, Object.entries(o).reduce((acc, [k, v]) => (Object.assign(Object.assign({}, acc), { [k]: hyperReflect(v) })), {}));
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
return hyper(o);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import stack from "./stack";
|
|
2
|
+
export function constructiveItinerary(steps) {
|
|
3
|
+
const segments = [];
|
|
4
|
+
const prototypes = [];
|
|
5
|
+
for (let i = 0; i < steps.length; i += 2) {
|
|
6
|
+
const segment = steps[i];
|
|
7
|
+
const prototype = steps[i + 1];
|
|
8
|
+
switch (typeof segment) {
|
|
9
|
+
case "string":
|
|
10
|
+
case "number":
|
|
11
|
+
{
|
|
12
|
+
const step = typeof segment === "number" ? positionStep(segment) : propertyStep(segment);
|
|
13
|
+
switch (typeof prototype) {
|
|
14
|
+
case "object":
|
|
15
|
+
{ // including Array
|
|
16
|
+
segments.push(segment);
|
|
17
|
+
prototypes.push(prototype);
|
|
18
|
+
}
|
|
19
|
+
break;
|
|
20
|
+
default: {
|
|
21
|
+
throw new Error(`Expecting array or object but got : '${typeof prototype}'`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
break;
|
|
26
|
+
default: {
|
|
27
|
+
throw new Error(`Expecting string or number but gor : '${typeof segment}'`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
itinerary: itineraryOf(...segments),
|
|
33
|
+
prototypes: stack.fromArray(prototypes)
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function areSameItineraryStep(step1, step2) {
|
|
37
|
+
var _a, _b, _c;
|
|
38
|
+
if (step1 == undefined || step2 == undefined) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
else if (step1.type !== step2.type) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
switch (step1.type) {
|
|
46
|
+
case "property": return step2.type === "property" && step1.propertyName === step2.propertyName;
|
|
47
|
+
case "position": return step2.type === "position" && step1.position === step2.position;
|
|
48
|
+
case "lookup": {
|
|
49
|
+
return step2.type === "lookup"
|
|
50
|
+
&& ((_a = step1.keys) === null || _a === void 0 ? void 0 : _a.length) === ((_b = step2.keys) === null || _b === void 0 ? void 0 : _b.length)
|
|
51
|
+
&& ((_c = step1.keys) === null || _c === void 0 ? void 0 : _c.every(pv1 => step2.keys.some(pv2 => areSamePropertyValuePair(pv1, pv2))));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function areSamePropertyValuePair(p1, p2) {
|
|
57
|
+
return p1.propertyName === p2.propertyName
|
|
58
|
+
&& p1.propertyValue === p2.propertyValue;
|
|
59
|
+
}
|
|
60
|
+
export function itineraryOf(...args) {
|
|
61
|
+
return args.reduce((parent, e) => {
|
|
62
|
+
const value = typeof e === 'string' ? propertyStep(e) : positionStep(e);
|
|
63
|
+
return { parent, value };
|
|
64
|
+
}, undefined);
|
|
65
|
+
}
|
|
66
|
+
const dataStep = propertyStep("data");
|
|
67
|
+
const childrenStep = propertyStep("children");
|
|
68
|
+
export function itineraryOverlay(it) {
|
|
69
|
+
return { value: dataStep, parent: itineraryOverlayInner(it) };
|
|
70
|
+
}
|
|
71
|
+
function itineraryOverlayInner(it) {
|
|
72
|
+
if (it === undefined) {
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
const { value, parent } = it;
|
|
77
|
+
return { value, parent: { value: childrenStep, parent: itineraryOverlayInner(parent) } };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
export function itineraryToStepArray(itinerary) {
|
|
81
|
+
let itn = itinerary;
|
|
82
|
+
const result = [];
|
|
83
|
+
while (itn !== undefined) {
|
|
84
|
+
result.push(itn.value);
|
|
85
|
+
itn = itn.parent;
|
|
86
|
+
}
|
|
87
|
+
return result.reverse();
|
|
88
|
+
}
|
|
89
|
+
export function propertyStep(propertyName) {
|
|
90
|
+
return { type: "property", propertyName };
|
|
91
|
+
}
|
|
92
|
+
export function positionStep(position) {
|
|
93
|
+
return { type: "position", position };
|
|
94
|
+
}
|
|
95
|
+
export function lookupStep(criteria) {
|
|
96
|
+
return { type: "lookup", keys: Object.entries(criteria).map(([k, v]) => ({ propertyName: k, propertyValue: v })) };
|
|
97
|
+
}
|
|
98
|
+
export function xpathFromStack(path) {
|
|
99
|
+
if (path === undefined) {
|
|
100
|
+
return ''; // TODO may need to return '.' here, to be checked
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
const { value, parent } = path;
|
|
104
|
+
const parentXPath = xpathFromStack(parent);
|
|
105
|
+
switch (value.type) {
|
|
106
|
+
case 'property': {
|
|
107
|
+
return `${parentXPath}/${value.propertyName}`;
|
|
108
|
+
}
|
|
109
|
+
case 'position': {
|
|
110
|
+
return `${parentXPath}/*[${value.position + 1}]`;
|
|
111
|
+
}
|
|
112
|
+
case 'lookup': {
|
|
113
|
+
const predicate = value.keys.map(({ propertyName, propertyValue }) => `${propertyName}=$${propertyName}`).join(' and ');
|
|
114
|
+
return `${parentXPath}/*[${predicate}]`;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export function navigate(from, itinerary, prototype) {
|
|
120
|
+
if (from === undefined) {
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
if (itinerary === undefined) {
|
|
124
|
+
return from;
|
|
125
|
+
}
|
|
126
|
+
const { parent, value: step } = itinerary;
|
|
127
|
+
const current = navigate(from, parent, prototype === null || prototype === void 0 ? void 0 : prototype.parent);
|
|
128
|
+
return navigateStep(current, step, prototype === null || prototype === void 0 ? void 0 : prototype.value);
|
|
129
|
+
}
|
|
130
|
+
export function navigateStep(from, step, prototype) {
|
|
131
|
+
if (from === undefined) {
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
if (step === undefined) {
|
|
135
|
+
return from;
|
|
136
|
+
}
|
|
137
|
+
if (Array.isArray(from)) {
|
|
138
|
+
if (step.type === 'lookup') {
|
|
139
|
+
const stp = step;
|
|
140
|
+
const result = from.find(e => e !== undefined && stp.keys.every(({ propertyName, propertyValue }) => e[propertyName] === propertyValue));
|
|
141
|
+
if (result === undefined && prototype !== undefined) {
|
|
142
|
+
from.push(prototype);
|
|
143
|
+
return prototype;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else if (step.type === 'position') {
|
|
150
|
+
const result = from[step.position];
|
|
151
|
+
if (result === undefined && prototype !== undefined) {
|
|
152
|
+
from[step.position] = prototype;
|
|
153
|
+
return prototype;
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
return result;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
else if (typeof from === 'object') {
|
|
161
|
+
if (step.type === 'property') {
|
|
162
|
+
const result = from === null ? undefined : from[step.propertyName];
|
|
163
|
+
if (result === undefined && prototype !== undefined && from !== null && from !== undefined) {
|
|
164
|
+
from[step.propertyName] = prototype;
|
|
165
|
+
return prototype;
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
return result;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return undefined;
|
|
173
|
+
}
|
|
174
|
+
export function navigationDepth(from, itinerary, originalPath = xpathFromStack(itinerary)) {
|
|
175
|
+
if (from === undefined || from === null) {
|
|
176
|
+
return { value: undefined, path: '', originalPath };
|
|
177
|
+
}
|
|
178
|
+
if (itinerary === undefined) {
|
|
179
|
+
return { value: from, path: '', originalPath };
|
|
180
|
+
}
|
|
181
|
+
const { parent, value: step } = itinerary;
|
|
182
|
+
const current = navigationDepth(from, parent, originalPath);
|
|
183
|
+
if (current.value === undefined || current.value === null) {
|
|
184
|
+
return current;
|
|
185
|
+
}
|
|
186
|
+
const next = navigateStep(current.value, step);
|
|
187
|
+
if (next === undefined || next === null) {
|
|
188
|
+
return { value: current.value, path: xpathFromStack(parent), originalPath };
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
return { value: next, path: xpathFromStack(itinerary), originalPath };
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
class OverlayNavigator {
|
|
195
|
+
navigate(from, itinerary) {
|
|
196
|
+
if (from === undefined) {
|
|
197
|
+
return undefined;
|
|
198
|
+
}
|
|
199
|
+
if (itinerary === undefined) {
|
|
200
|
+
return from;
|
|
201
|
+
}
|
|
202
|
+
const { parent, value: step } = itinerary;
|
|
203
|
+
const current = this.navigate(from, parent);
|
|
204
|
+
return current === undefined ? undefined : this.navigateStep(current, step);
|
|
205
|
+
}
|
|
206
|
+
navigateStep(from, step) {
|
|
207
|
+
if (from === undefined) {
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
if (step === undefined) {
|
|
211
|
+
return from;
|
|
212
|
+
}
|
|
213
|
+
if (Array.isArray(from.children)) {
|
|
214
|
+
if (step.type === 'lookup') {
|
|
215
|
+
const stp = step;
|
|
216
|
+
const result = from.children.find(e => e !== undefined && stp.keys.every(({ propertyName, propertyValue }) => { var _a; return ((_a = e.keys) === null || _a === void 0 ? void 0 : _a[propertyName]) === propertyValue; }));
|
|
217
|
+
return result;
|
|
218
|
+
}
|
|
219
|
+
else if (step.type === 'position') {
|
|
220
|
+
const result = from.children[step.position];
|
|
221
|
+
return result;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
else if (from.children !== null && typeof from.children === 'object') {
|
|
225
|
+
if (step.type === 'property') {
|
|
226
|
+
const result = from === null ? undefined : from.children[step.propertyName];
|
|
227
|
+
return result;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return undefined;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
export const overlayNavigator = new OverlayNavigator();
|
|
234
|
+
/**
|
|
235
|
+
* Same as {navigate} but try to path missing data node using prototype parameter
|
|
236
|
+
* @param from
|
|
237
|
+
* @param itinerary
|
|
238
|
+
* @param prototype
|
|
239
|
+
*/
|
|
240
|
+
export function ensurePath(from, itinerary, prototype) {
|
|
241
|
+
return navigate(from, itinerary, prototype);
|
|
242
|
+
}
|
|
243
|
+
class AbstractPointerBuilder {
|
|
244
|
+
constructor() {
|
|
245
|
+
this.itinerary = [];
|
|
246
|
+
}
|
|
247
|
+
child(propertyName) {
|
|
248
|
+
this.itinerary.push({ type: "property", propertyName });
|
|
249
|
+
return this;
|
|
250
|
+
}
|
|
251
|
+
lookup(...criterion) {
|
|
252
|
+
criterion.forEach(([propertyName, propertyValue]) => {
|
|
253
|
+
this.itinerary.push({ type: "lookup", keys: [{ propertyName, propertyValue }] });
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
class RelativePointerBuilder extends AbstractPointerBuilder {
|
|
258
|
+
constructor(originUuid) {
|
|
259
|
+
super();
|
|
260
|
+
this.originUuid = originUuid;
|
|
261
|
+
this.type = "relative";
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
class AbsolutePointerBuilder extends AbstractPointerBuilder {
|
|
265
|
+
constructor() {
|
|
266
|
+
super();
|
|
267
|
+
this.type = "absolute";
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
export function pointer(fromId) {
|
|
271
|
+
if (fromId === undefined) {
|
|
272
|
+
return new AbsolutePointerBuilder();
|
|
273
|
+
}
|
|
274
|
+
return new RelativePointerBuilder(fromId);
|
|
275
|
+
}
|
|
276
|
+
export const ROOT = Object.freeze({ type: "absolute", itinerary: [] });
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export function head(value) {
|
|
2
|
+
return { value };
|
|
3
|
+
}
|
|
4
|
+
export function push(head, value) {
|
|
5
|
+
return { value, parent: head };
|
|
6
|
+
}
|
|
7
|
+
export function concat(tail, stack) {
|
|
8
|
+
if (tail === undefined)
|
|
9
|
+
return stack;
|
|
10
|
+
if (stack === undefined)
|
|
11
|
+
return tail;
|
|
12
|
+
const { parent, value } = stack;
|
|
13
|
+
return { value, parent: concat(tail, parent) };
|
|
14
|
+
}
|
|
15
|
+
export function fromArray(t) {
|
|
16
|
+
return t === null || t === void 0 ? void 0 : t.reduce((acc, t) => push(acc, t), undefined);
|
|
17
|
+
}
|
|
18
|
+
export function reduce(head, reducer, initial) {
|
|
19
|
+
if (head === undefined) {
|
|
20
|
+
return initial;
|
|
21
|
+
}
|
|
22
|
+
const { parent, value } = head;
|
|
23
|
+
const acc = reduce(parent, reducer, initial);
|
|
24
|
+
return reducer(acc, value);
|
|
25
|
+
}
|
|
26
|
+
function equal(a, b) {
|
|
27
|
+
// Not equal if both are nullish
|
|
28
|
+
if (a === undefined || a === null || b === undefined || b === null) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
while (a !== undefined && b !== undefined) {
|
|
32
|
+
if (a.value !== b.value) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
a = a.parent;
|
|
36
|
+
b = b.parent;
|
|
37
|
+
}
|
|
38
|
+
// Equal if traversed all stack at both side
|
|
39
|
+
if ((a === undefined || a === null) && (b === undefined || b === null)) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const stack = { push, head, concat, reduce, fromArray, equal };
|
|
47
|
+
export default stack;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export * from './core-utils-types-hkt';
|
|
2
|
+
export * from './core-utils-types';
|
|
3
|
+
export type { StackElement } from './core-utils-stack';
|
|
4
|
+
export { default } from './core-utils-stack';
|
|
5
|
+
export { utils, DEFAULT_EQUAL_FN, removeDuplicates, areSameDefined } from './core-utils';
|
|
6
|
+
export type { EqualFn } from './core-utils';
|
|
7
|
+
export * from './core-utils-resolver';
|
|
8
|
+
export * from './core-utils-pathway';
|
|
9
|
+
export * from './core-utils-pathway-resolver';
|
|
10
|
+
export * from './itinerary/itinerary';
|
|
11
|
+
export * from './itinerary/stack';
|
|
12
|
+
export * from './core-utils-filesystem';
|
|
13
|
+
export * from './core-utils-file';
|
|
14
|
+
export * from './core-utils-registry';
|
|
15
|
+
export * from './core-utils-chrono';
|
|
16
|
+
export * from './core-utils-comparator';
|
|
17
|
+
export * from './core-utils-fqn';
|
|
18
|
+
export * from './core-utils-validations';
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AAGnC,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAG7C,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACzF,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAG5C,cAAc,uBAAuB,CAAC;AAGtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,+BAA+B,CAAC;AAG9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAIlC,cAAc,yBAAyB,CAAC;AAGxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Type utilities
|
|
2
|
+
export * from './core-utils-types-hkt';
|
|
3
|
+
export * from './core-utils-types';
|
|
4
|
+
export { default } from './core-utils-stack';
|
|
5
|
+
// Core utilities
|
|
6
|
+
export { utils, DEFAULT_EQUAL_FN, removeDuplicates, areSameDefined } from './core-utils';
|
|
7
|
+
// Resolvers
|
|
8
|
+
export * from './core-utils-resolver';
|
|
9
|
+
// Path and navigation utilities
|
|
10
|
+
export * from './core-utils-pathway';
|
|
11
|
+
export * from './core-utils-pathway-resolver';
|
|
12
|
+
// Itinerary utilities
|
|
13
|
+
export * from './itinerary/itinerary';
|
|
14
|
+
export * from './itinerary/stack';
|
|
15
|
+
// Note: HyperLayerNode is exported from core-utils-types (more complete version with HKT)
|
|
16
|
+
// Filesystem utilities
|
|
17
|
+
export * from './core-utils-filesystem';
|
|
18
|
+
// Other utilities
|
|
19
|
+
export * from './core-utils-file';
|
|
20
|
+
export * from './core-utils-registry';
|
|
21
|
+
export * from './core-utils-chrono';
|
|
22
|
+
export * from './core-utils-comparator';
|
|
23
|
+
export * from './core-utils-fqn';
|
|
24
|
+
export * from './core-utils-validations';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface HyperLayerNode<T> {
|
|
2
|
+
keys?: Record<PropertyKey, any>;
|
|
3
|
+
data?: T;
|
|
4
|
+
children?: Record<string, HyperLayerNode<T>> | Array<HyperLayerNode<T>>;
|
|
5
|
+
}
|
|
6
|
+
export declare function hyper<T>(data: T, children?: Record<string, HyperLayerNode<T>> | Array<HyperLayerNode<T>>): HyperLayerNode<T>;
|
|
7
|
+
/**
|
|
8
|
+
* Utility function that create Overlay which mirror original object
|
|
9
|
+
* @param o
|
|
10
|
+
*/
|
|
11
|
+
export declare function hyperReflect(o: any): HyperLayerNode<any>;
|
|
12
|
+
//# sourceMappingURL=hyper-layer-node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hyper-layer-node.d.ts","sourceRoot":"","sources":["../../src/itinerary/hyper-layer-node.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC,WAAW,EAAE,GAAG,CAAC,CAAA;IAC/B,IAAI,CAAC,EAAG,CAAC,CAAA;IACT,QAAQ,CAAC,EAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAA;CACzE;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,IAAI,EAAG,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAI,cAAc,CAAC,CAAC,CAAC,CAE9H;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAG,GAAG,GAAI,cAAc,CAAC,GAAG,CAAC,CAU1D"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function hyper(data, children) {
|
|
2
|
+
return { data, children };
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Utility function that create Overlay which mirror original object
|
|
6
|
+
* @param o
|
|
7
|
+
*/
|
|
8
|
+
export function hyperReflect(o) {
|
|
9
|
+
if (o === null || o === undefined) {
|
|
10
|
+
return hyper(o);
|
|
11
|
+
}
|
|
12
|
+
else if (Array.isArray(o)) {
|
|
13
|
+
return hyper(o, o.map(e => hyperReflect(e)));
|
|
14
|
+
}
|
|
15
|
+
else if (typeof o === "object") {
|
|
16
|
+
return hyper(o, Object.entries(o).reduce((acc, [k, v]) => ({ ...acc, [k]: hyperReflect(v) }), {}));
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
return hyper(o);
|
|
20
|
+
}
|
|
21
|
+
}
|