@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.
Files changed (99) hide show
  1. package/dist/core-utils-chrono.d.ts +8 -0
  2. package/dist/core-utils-chrono.d.ts.map +1 -0
  3. package/dist/core-utils-chrono.js +16 -0
  4. package/dist/core-utils-comparator.d.ts +11 -0
  5. package/dist/core-utils-comparator.d.ts.map +1 -0
  6. package/dist/core-utils-comparator.js +22 -0
  7. package/dist/core-utils-file.d.ts +10 -0
  8. package/dist/core-utils-file.d.ts.map +1 -0
  9. package/dist/core-utils-file.js +1 -0
  10. package/dist/core-utils-filesystem.d.ts +69 -0
  11. package/dist/core-utils-filesystem.d.ts.map +1 -0
  12. package/dist/core-utils-filesystem.js +156 -0
  13. package/dist/core-utils-fqn.d.ts +11 -0
  14. package/dist/core-utils-fqn.d.ts.map +1 -0
  15. package/dist/core-utils-fqn.js +19 -0
  16. package/dist/core-utils-pathway-resolver.d.ts +20 -0
  17. package/dist/core-utils-pathway-resolver.d.ts.map +1 -0
  18. package/dist/core-utils-pathway-resolver.js +31 -0
  19. package/dist/core-utils-pathway.d.ts +84 -0
  20. package/dist/core-utils-pathway.d.ts.map +1 -0
  21. package/dist/core-utils-pathway.js +206 -0
  22. package/dist/core-utils-registry.d.ts +7 -0
  23. package/dist/core-utils-registry.d.ts.map +1 -0
  24. package/dist/core-utils-registry.js +22 -0
  25. package/dist/core-utils-resolver.d.ts +33 -0
  26. package/dist/core-utils-resolver.d.ts.map +1 -0
  27. package/dist/core-utils-resolver.js +65 -0
  28. package/dist/core-utils-stack.d.ts +20 -0
  29. package/dist/core-utils-stack.d.ts.map +1 -0
  30. package/dist/core-utils-stack.js +47 -0
  31. package/dist/core-utils-types-hkt.d.ts +12 -0
  32. package/dist/core-utils-types-hkt.d.ts.map +1 -0
  33. package/dist/core-utils-types-hkt.js +1 -0
  34. package/dist/core-utils-types.d.ts +83 -0
  35. package/dist/core-utils-types.d.ts.map +1 -0
  36. package/dist/core-utils-types.js +39 -0
  37. package/dist/core-utils-validations.d.ts +21 -0
  38. package/dist/core-utils-validations.d.ts.map +1 -0
  39. package/dist/core-utils-validations.js +18 -0
  40. package/dist/core-utils.d.ts +39 -0
  41. package/dist/core-utils.d.ts.map +1 -0
  42. package/dist/core-utils.js +113 -0
  43. package/dist/es2015/core-utils-chrono.js +16 -0
  44. package/dist/es2015/core-utils-comparator.js +22 -0
  45. package/dist/es2015/core-utils-file.js +1 -0
  46. package/dist/es2015/core-utils-filesystem.js +157 -0
  47. package/dist/es2015/core-utils-fqn.js +19 -0
  48. package/dist/es2015/core-utils-pathway-resolver.js +31 -0
  49. package/dist/es2015/core-utils-pathway.js +206 -0
  50. package/dist/es2015/core-utils-registry.js +22 -0
  51. package/dist/es2015/core-utils-resolver.js +68 -0
  52. package/dist/es2015/core-utils-stack.js +47 -0
  53. package/dist/es2015/core-utils-types-hkt.js +1 -0
  54. package/dist/es2015/core-utils-types.js +39 -0
  55. package/dist/es2015/core-utils-validations.js +18 -0
  56. package/dist/es2015/core-utils.js +113 -0
  57. package/dist/es2015/index.js +24 -0
  58. package/dist/es2015/itinerary/hyper-layer-node.js +21 -0
  59. package/dist/es2015/itinerary/itinerary.js +276 -0
  60. package/dist/es2015/itinerary/stack.js +47 -0
  61. package/dist/index.d.ts +19 -0
  62. package/dist/index.d.ts.map +1 -0
  63. package/dist/index.js +24 -0
  64. package/dist/itinerary/hyper-layer-node.d.ts +12 -0
  65. package/dist/itinerary/hyper-layer-node.d.ts.map +1 -0
  66. package/dist/itinerary/hyper-layer-node.js +21 -0
  67. package/dist/itinerary/itinerary.d.ts +86 -0
  68. package/dist/itinerary/itinerary.d.ts.map +1 -0
  69. package/dist/itinerary/itinerary.js +275 -0
  70. package/dist/itinerary/stack.d.ts +20 -0
  71. package/dist/itinerary/stack.d.ts.map +1 -0
  72. package/dist/itinerary/stack.js +47 -0
  73. package/package.json +41 -0
  74. package/src/core-utils-chrono.ts +21 -0
  75. package/src/core-utils-comparator.ts +27 -0
  76. package/src/core-utils-file.ts +10 -0
  77. package/src/core-utils-filesystem.spec.ts +63 -0
  78. package/src/core-utils-filesystem.ts +232 -0
  79. package/src/core-utils-fqn.ts +17 -0
  80. package/src/core-utils-pathway-resolver.ts +36 -0
  81. package/src/core-utils-pathway.ts +232 -0
  82. package/src/core-utils-registry.ts +23 -0
  83. package/src/core-utils-resolver.ts +75 -0
  84. package/src/core-utils-stack.spec.ts +42 -0
  85. package/src/core-utils-stack.ts +62 -0
  86. package/src/core-utils-types-hkt.ts +9 -0
  87. package/src/core-utils-types.ts +127 -0
  88. package/src/core-utils-validations.ts +36 -0
  89. package/src/core-utils.spec.ts +56 -0
  90. package/src/core-utils.ts +139 -0
  91. package/src/index.ts +34 -0
  92. package/src/itinerary/hyper-layer-node.ts +25 -0
  93. package/src/itinerary/itinerary.spec.ts +388 -0
  94. package/src/itinerary/itinerary.ts +363 -0
  95. package/src/itinerary/stack.spec.ts +46 -0
  96. package/src/itinerary/stack.ts +62 -0
  97. package/tsconfig.es2015.json +24 -0
  98. package/tsconfig.json +19 -0
  99. package/vitest.config.ts +8 -0
@@ -0,0 +1,62 @@
1
+ export interface StackElement<T> {
2
+ value : T
3
+ parent? : StackElement<T>
4
+ }
5
+
6
+ export function head<T>(value : T) : StackElement<T> {
7
+ return {value}
8
+ }
9
+
10
+ export function push<T>(head : StackElement<T> | undefined, value : T) : StackElement<T> {
11
+ return {value, parent: head}
12
+ }
13
+
14
+ export function concat<T>(tail : StackElement<T> | undefined, stack : StackElement<T> | undefined) : StackElement<T> | undefined{
15
+ if(tail === undefined) return stack
16
+ if(stack === undefined) return tail
17
+
18
+ const {parent, value} = stack
19
+
20
+ return {value, parent:concat(tail, parent)}
21
+ }
22
+
23
+ export function fromArray<T = any>(t : T[] | undefined) : StackElement<T> | undefined {
24
+ return t?.reduce((acc, t) => push(acc, t), undefined as undefined | StackElement<T>)
25
+ }
26
+
27
+ export function reduce<T, R>(head : StackElement<T> | undefined, reducer : (r: R, t : T) => R, initial : R) : R {
28
+ if(head === undefined){
29
+ return initial
30
+ }
31
+
32
+ const {parent, value} = head
33
+ const acc = reduce(parent, reducer, initial)
34
+ return reducer(acc, value)
35
+ }
36
+
37
+ function equal<T>(a:StackElement<T> | null | undefined, b : StackElement<T> | null | undefined) : boolean {
38
+ // Not equal if both are nullish
39
+ if( a === undefined || a === null || b === undefined || b === null ){
40
+ return false
41
+ }
42
+
43
+ while (a !== undefined && b !== undefined){
44
+ if(a.value !== b.value){
45
+ return false
46
+ }
47
+
48
+ a = a.parent
49
+ b = b.parent
50
+ }
51
+
52
+ // Equal if traversed all stack at both side
53
+ if((a === undefined || a === null) && (b === undefined || b === null) ){
54
+ return true
55
+ } else {
56
+ return false
57
+ }
58
+ }
59
+
60
+ const stack = {push, head, concat, reduce, fromArray, equal}
61
+
62
+ export default stack;
@@ -0,0 +1,9 @@
1
+ export interface HKT3<Obj, Key extends PropertyKey, Value> {
2
+ _Obj: Obj;
3
+ _Key: Key;
4
+ _Value: Value;
5
+ _Result: unknown;
6
+ }
7
+
8
+ export type Apply3<F extends HKT3<any, any, any>, Obj, Key extends PropertyKey, Value> =
9
+ (F & { _Obj: Obj; _Key: Key; _Value: Value })["_Result"];
@@ -0,0 +1,127 @@
1
+ import {Apply3, HKT3} from "./core-utils-types-hkt";
2
+
3
+ export type TypedObject<T extends string = string> = {type : T}
4
+ export type AnyFunction = (...args : any[]) => any
5
+
6
+ /**
7
+ * Intended to hold value which can be undefined.
8
+ * It helps to know if a value (incl. undefined) is present or not.
9
+ */
10
+ export interface Holder<T = any>{
11
+ value:T
12
+ }
13
+ export function holder<T=any>(value : T) : Holder<T> {
14
+ return {value}
15
+ }
16
+
17
+ export interface GenericReason {
18
+ code? : string
19
+ message? : string
20
+ parameters? : Record<string, any>
21
+ }
22
+
23
+ export type GenericError = GenericReason
24
+
25
+ export type ExpressionString = string
26
+
27
+ export interface HyperLayerNode<T> {
28
+ keys?: Record<PropertyKey, any> // Keys to use for property based navigation when applicable
29
+ data? : T
30
+ children? : Record<string, HyperLayerNode<T>> | Array<HyperLayerNode<T>>
31
+ }
32
+
33
+ export function hyper<T>(data : T, children?: Record<string, HyperLayerNode<T>> | Array<HyperLayerNode<T>>) : HyperLayerNode<T> {
34
+ return {data, children}
35
+ }
36
+
37
+
38
+ /**
39
+ * Utility function that create Overlay which mirror original object
40
+ * @param o
41
+ */
42
+ export function hyperReflect(o : any) : HyperLayerNode<any> {
43
+ if(o === null || o === undefined){
44
+ return hyper(o)
45
+ } else if (Array.isArray(o)) {
46
+ return hyper(o, o.map(e => hyperReflect(e)))
47
+ } else if(typeof o === "object"){
48
+ return hyper(o, Object.entries(o).reduce((acc, [k, v]) => ({...acc, [k] : hyperReflect(v)}), {}))
49
+ } else {
50
+ return hyper(o)
51
+ }
52
+ }
53
+
54
+ export type HyperLayerNodeHKT<T, F extends HKT3<any, any, any>, Host = never, Key extends PropertyKey = never> =
55
+ T extends Array<infer U> ? {
56
+ data?: Apply3<F, Host, Key, T>;
57
+ children?: HyperLayerNodeHKT<U, F, T, never>[];
58
+ } :
59
+ T extends Record<string, any> ? {
60
+ data?: Apply3<F, Host, Key, T>;
61
+ children?: {
62
+ [K in keyof T]?: HyperLayerNodeHKT<T[K], F, T, K>;
63
+ };
64
+ } :
65
+ {
66
+ data?: Apply3<F, Host, Key, T>;
67
+ };
68
+
69
+ export interface OverlayNodeBase<A> {
70
+ type : "object" | "array" | "scalar"
71
+ annotation?: A
72
+ }
73
+
74
+
75
+ export interface ObjectOverlayNode<A> extends OverlayNodeBase<A> {
76
+ type : "object"
77
+ children : Record<string, OverlayNode<A>>
78
+ }
79
+
80
+
81
+ export interface ArrayOverlayNode<A> extends OverlayNodeBase<A> {
82
+ type : "array"
83
+ children : Array<OverlayNode<A>>
84
+ }
85
+
86
+
87
+ export interface ScalarOverlayNode<A> extends OverlayNodeBase<A> {
88
+ type : "scalar"
89
+ }
90
+
91
+ export type OverlayNode<A> = ObjectOverlayNode<A> | ArrayOverlayNode<A> | ScalarOverlayNode<A>
92
+
93
+ export interface Annotation<A> {
94
+ annotation?: A;
95
+ }
96
+
97
+ export type Overlay<T, A> =
98
+ T extends Array<infer U> ? {
99
+ type: "array";
100
+ children: Overlay<U, A>[];
101
+ } & Annotation<A> :
102
+ T extends Record<string, any> ? {
103
+ type: "object";
104
+ children: {
105
+ [K in keyof T]?: Overlay<T[K], A>
106
+ };
107
+ } & Annotation<A> :
108
+ {
109
+ type: "scalar";
110
+ } & Annotation<A>;
111
+
112
+
113
+ /**
114
+ * Mainly used to prevent re-entrant navitation
115
+ */
116
+ export class ExplorationContext<T> {
117
+ constructor(readonly parent : ExplorationContext<T> | undefined, readonly values : T[]) {
118
+ }
119
+
120
+ explored(t : T) : boolean {
121
+ return this.values.includes(t)
122
+ }
123
+
124
+ newChild(values : T[]): ExplorationContext<T>{
125
+ return new ExplorationContext<T>(this, values)
126
+ }
127
+ }
@@ -0,0 +1,36 @@
1
+ export interface NodeValidation {
2
+ type: "core:node-validation"
3
+ notes : ValidationNote[]
4
+ }
5
+
6
+ export interface ValidationNote {
7
+ uuid?: string // TODO use UUID type
8
+ severity : "info" | "warning" | "error"
9
+ key?: string
10
+ message?: string
11
+ params?: Record<string, any>
12
+ }
13
+
14
+
15
+ class NoteUtils {
16
+ add(nv : NodeValidation, ...notes : ValidationNote[]) : NodeValidation {
17
+ return {...(nv ?? {type: "core:node-validation"}), notes}
18
+ }
19
+ of(...notes : ValidationNote[]) : NodeValidation {
20
+ return {type: "core:node-validation", notes}
21
+ }
22
+ info(key?: string, message?: string, params?: Record<string, any>): ValidationNote {
23
+ return { severity: "info", key, message, params };
24
+ }
25
+
26
+ warning(key?: string, message?: string, params?: Record<string, any>): ValidationNote {
27
+ return { severity: "warning", key, message, params };
28
+ }
29
+
30
+ error(key?: string, message?: string, params?: Record<string, any>): ValidationNote {
31
+ return { severity: "error", key, message, params };
32
+ }
33
+ }
34
+
35
+
36
+ export const notes = new NoteUtils()
@@ -0,0 +1,56 @@
1
+ import {removeDuplicates} from './core-utils';
2
+ import {utils} from './core-utils'
3
+
4
+ describe('Stack', () => {
5
+ it('concat should work', () => {
6
+
7
+ expect(removeDuplicates([1,1,1])).toEqual([1]);
8
+ expect(removeDuplicates([1,1,2])).toEqual([1, 2]);
9
+ expect(removeDuplicates([1,2,1])).toEqual([1, 2]);
10
+ expect(removeDuplicates([])).toEqual([]);
11
+ });
12
+
13
+ test('Should correctly compare various cases', () => {
14
+ // Identical objects
15
+ expect(utils.deepEqual({ a: 1 }, { a: 1 })).toBe(true);
16
+
17
+ // Objects with different values
18
+ expect(utils.deepEqual({ a: 1, b: 2 }, { a: 1, b: 3 })).toBe(false);
19
+
20
+ // Deeply identical objects
21
+ expect(utils.deepEqual({ a: 1, b: { c: 2 } }, { a: 1, b: { c: 2 } })).toBe(true);
22
+
23
+ // Deeply different objects
24
+ expect(utils.deepEqual({ a: 1, b: { c: 2 } }, { a: 1, b: { c: 3 } })).toBe(false);
25
+
26
+ // Identical numbers
27
+ expect(utils.deepEqual(1, 1)).toBe(true);
28
+
29
+ // Different numbers
30
+ expect(utils.deepEqual(1, 2)).toBe(false);
31
+
32
+ // Identical strings
33
+ expect(utils.deepEqual('hello', 'hello')).toBe(true);
34
+
35
+ // Different strings
36
+ expect(utils.deepEqual('hello', 'world')).toBe(false);
37
+
38
+ // Identical booleans
39
+ expect(utils.deepEqual(true, true)).toBe(true);
40
+
41
+ // Different booleans
42
+ expect(utils.deepEqual(true, false)).toBe(false);
43
+
44
+ // Null compared to null
45
+ expect(utils.deepEqual(null, null)).toBe(true);
46
+
47
+ // Null compared to undefined
48
+ expect(utils.deepEqual(null, undefined)).toBe(false);
49
+
50
+ // Null compared to object
51
+ expect(utils.deepEqual(null, {})).toBe(false);
52
+
53
+ // Undefined compared to object
54
+ expect(utils.deepEqual(undefined, {})).toBe(false);
55
+ });
56
+ });
@@ -0,0 +1,139 @@
1
+ function includes<T extends U, U> (arr : Array<T>, t : U) : t is U {
2
+ return arr === undefined ? false : arr.includes(t as T)
3
+ }
4
+
5
+ export function isNonNullObject(data : any) : boolean {
6
+ if(data === null || data === undefined){
7
+ return false
8
+ }
9
+
10
+ const dataType = typeof data
11
+ return dataType === 'object' && !Array.isArray(data)
12
+ }
13
+
14
+
15
+ function isBlank(s : string) : boolean {
16
+ return s === null || s === undefined || s.trim() === ""
17
+ }
18
+
19
+ function isDefined(data : any) : boolean {
20
+ return data !== null && data !== undefined
21
+ }
22
+
23
+ function isNotDefined(data : any) : boolean {
24
+ return ! isDefined(data)
25
+ }
26
+
27
+ export function isNullish(o : any) : o is (null | undefined) {
28
+ return o === null || o === undefined
29
+ }
30
+
31
+ export function isEmptyObject(object : Record<any, any> ) {
32
+ for (const property in object) {
33
+ return false;
34
+ }
35
+ return true;
36
+ }
37
+
38
+ export function equalSet(a : Set<unknown>, b : Set<unknown>){
39
+ return a.size === b.size && [...a].every((x) => b.has(x));
40
+ }
41
+
42
+ export type EqualFn<T> = (a:T, b:T) => boolean
43
+ export const DEFAULT_EQUAL_FN : EqualFn<any> = (a, b) => a === b
44
+
45
+ export function areSameDefined<T>(a : T | undefined, b: T | undefined, equalFn? : EqualFn<T>) : boolean {
46
+ if(a === undefined || b === undefined){
47
+ return false
48
+ }
49
+ if(a === null || b === null){
50
+ return false
51
+ }
52
+
53
+ return a === b || (equalFn ? equalFn(a, b) : false)
54
+ }
55
+ /**
56
+ * Warning: non performant O(n2)
57
+ * @param arr
58
+ * @param equals
59
+ */
60
+ export function removeDuplicates<T>(arr : T[], equals : EqualFn<T> = DEFAULT_EQUAL_FN) : T[] {
61
+ return arr.filter((item, index) => arr.findIndex((e,i) => i < index && equals(item, e)) === -1)
62
+ }
63
+ // export function removeDuplicatesAndUndefined<T>(arr : (T|undefined)[], equals : EqualFn<T> = DEFAULT_EQUAL_FN) : T[] {
64
+ // return arr.filter((item, index) : item is T => item !== undefined && arr.findIndex((e,i) => i < index && equals(item, e)) === -1)
65
+ // }
66
+
67
+ function intersection<T>(o1 : Record<string, T>, o2 : Record<string, T>) {
68
+ return Object.keys(o1).filter({}.hasOwnProperty.bind(o2));
69
+ }
70
+
71
+ function deepEqual(obj1: any, obj2: any): boolean {
72
+ if (obj1 === obj2) {
73
+ return true;
74
+ }
75
+
76
+ if (obj1 === null || obj2 === null || typeof obj1 !== 'object' || typeof obj2 !== 'object') {
77
+ return false;
78
+ }
79
+
80
+ if (Array.isArray(obj1) !== Array.isArray(obj2)) {
81
+ return false;
82
+ }
83
+
84
+ const keys1 = Object.keys(obj1);
85
+ const keys2 = Object.keys(obj2);
86
+
87
+ if (keys1.length !== keys2.length) {
88
+ return false;
89
+ }
90
+
91
+ for (const key of keys1) {
92
+ if (!keys2.includes(key)) {
93
+ return false;
94
+ }
95
+
96
+ if (!deepEqual(obj1[key], obj2[key])) {
97
+ return false;
98
+ }
99
+ }
100
+
101
+ return true;
102
+ }
103
+
104
+ function escapeForXPath(input: string): string {
105
+ if (input.includes("'")) {
106
+ if (input.includes('"')) {
107
+ // Si la chaîne contient à la fois des guillemets simples et doubles
108
+ const parts = input.split("'");
109
+ return "concat(" + parts.map(part => `'${part}'`).join(", \"'\", ") + ")";
110
+ } else {
111
+ // Si la chaîne ne contient que des guillemets simples
112
+ return `"${input}"`;
113
+ }
114
+ } else {
115
+ // Si la chaîne ne contient que des guillemets doubles ou aucun guillemet
116
+ return `'${input}'`;
117
+ }
118
+ }
119
+
120
+ export type ArrayFilterFn<T> = (value:T, index : number, array : Array<T>) => boolean
121
+
122
+
123
+ // TODO rename this function
124
+ function cascadeFilter<T>(arr : Array<T>, fns : ArrayFilterFn<T>[]) : Array<T> {
125
+ if(arr.length === 0){
126
+ return arr
127
+ } else {
128
+ for (const filterFn of fns) {
129
+ const filtered = arr.filter(filterFn)
130
+ if(filtered.length > 0){
131
+ return filtered
132
+ }
133
+ }
134
+
135
+ return arr
136
+ }
137
+ }
138
+ export const utils = {includes, isNonNullObject, isEmptyObject, equalSet, isDefined, isBlank, isNotDefined, removeDuplicates, areSameDefined, intersection, deepEqual, escapeForXPath, cascadeFilter}
139
+
package/src/index.ts ADDED
@@ -0,0 +1,34 @@
1
+ // Type utilities
2
+ export * from './core-utils-types-hkt';
3
+ export * from './core-utils-types';
4
+
5
+ // Stack utilities
6
+ export type { StackElement } from './core-utils-stack';
7
+ export { default } from './core-utils-stack';
8
+
9
+ // Core utilities
10
+ export { utils, DEFAULT_EQUAL_FN, removeDuplicates, areSameDefined } from './core-utils';
11
+ export type { EqualFn } from './core-utils';
12
+
13
+ // Resolvers
14
+ export * from './core-utils-resolver';
15
+
16
+ // Path and navigation utilities
17
+ export * from './core-utils-pathway';
18
+ export * from './core-utils-pathway-resolver';
19
+
20
+ // Itinerary utilities
21
+ export * from './itinerary/itinerary';
22
+ export * from './itinerary/stack';
23
+ // Note: HyperLayerNode is exported from core-utils-types (more complete version with HKT)
24
+
25
+ // Filesystem utilities
26
+ export * from './core-utils-filesystem';
27
+
28
+ // Other utilities
29
+ export * from './core-utils-file';
30
+ export * from './core-utils-registry';
31
+ export * from './core-utils-chrono';
32
+ export * from './core-utils-comparator';
33
+ export * from './core-utils-fqn';
34
+ export * from './core-utils-validations';
@@ -0,0 +1,25 @@
1
+ export interface HyperLayerNode<T> {
2
+ keys?: Record<PropertyKey, any> // Keys to use for property based navigation when applicable
3
+ data? : T
4
+ children? : Record<string, HyperLayerNode<T>> | Array<HyperLayerNode<T>>
5
+ }
6
+
7
+ export function hyper<T>(data : T, children?: Record<string, HyperLayerNode<T>> | Array<HyperLayerNode<T>>) : HyperLayerNode<T> {
8
+ return {data, children}
9
+ }
10
+
11
+ /**
12
+ * Utility function that create Overlay which mirror original object
13
+ * @param o
14
+ */
15
+ export function hyperReflect(o : any) : HyperLayerNode<any> {
16
+ if(o === null || o === undefined){
17
+ return hyper(o)
18
+ } else if (Array.isArray(o)) {
19
+ return hyper(o, o.map(e => hyperReflect(e)))
20
+ } else if(typeof o === "object"){
21
+ return hyper(o, Object.entries(o).reduce((acc, [k, v]) => ({...acc, [k] : hyperReflect(v)}), {}))
22
+ } else {
23
+ return hyper(o)
24
+ }
25
+ }