@oscarpalmer/atoms 0.182.1 → 0.184.0

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.
@@ -0,0 +1,140 @@
1
+ import {isNonPlainObject} from '../is';
2
+ import type {GenericCallback, PlainObject} from '../models';
3
+
4
+ // #region Types
5
+
6
+ type TransformCallback<Value extends PlainObject, Key extends keyof Value> = (
7
+ key: Key,
8
+ value: Value[Key],
9
+ ) => Value[Key];
10
+
11
+ type TransformCallbacks<Value extends PlainObject> = Partial<{
12
+ [Key in keyof Value]: (value: Value[Key]) => Value[Key];
13
+ }>;
14
+
15
+ export type Transformer<Value extends PlainObject> = {
16
+ (value: Value): Value;
17
+ };
18
+
19
+ // #endregion
20
+
21
+ // #region Functions
22
+
23
+ function getTransformer<Value extends PlainObject, Key extends keyof Value>(
24
+ input: unknown,
25
+ ): TransformCallback<Value, Key> | TransformCallbacks<Value> | undefined {
26
+ if (typeof input === 'function') {
27
+ return input as GenericCallback;
28
+ }
29
+
30
+ if (isNonPlainObject(input)) {
31
+ return;
32
+ }
33
+
34
+ const keys = Object.keys(input) as Key[];
35
+ const {length} = keys;
36
+
37
+ const transformer: Partial<TransformCallbacks<Value>> = {};
38
+
39
+ for (let index = 0; index < length; index += 1) {
40
+ const key = keys[index];
41
+ const value = input[key];
42
+
43
+ if (typeof value === 'function') {
44
+ transformer[key] = value;
45
+ }
46
+ }
47
+
48
+ if (Object.keys(transformer).length > 0) {
49
+ return transformer;
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Initialize a transformer for an object with a transformer function
55
+ *
56
+ * Available as `initializeTransformer` and `transform.initialize`
57
+ * @param transform Transformer function
58
+ * @returns Transformer
59
+ */
60
+ export function initializeTransformer<Value extends PlainObject>(
61
+ transform: TransformCallback<Value, keyof Value>,
62
+ ): Transformer<Value>;
63
+
64
+ /**
65
+ * Initialize a transformer for an object with transformer functions
66
+ *
67
+ * Available as `initializeTransformer` and `transform.initialize`
68
+ * @param transformers Keyed transformer functions
69
+ * @return Transformer
70
+ */
71
+ export function initializeTransformer<Value extends PlainObject>(
72
+ transformers: TransformCallbacks<Value>,
73
+ ): Transformer<Value>;
74
+
75
+ export function initializeTransformer<Value extends PlainObject>(
76
+ transform: unknown,
77
+ ): Transformer<Value> {
78
+ const transformer = getTransformer<Value, keyof Value>(transform);
79
+
80
+ return value => transformValue(value, transformer);
81
+ }
82
+
83
+ /**
84
+ * Transform and objects properties using a transformer functior
85
+ * @param value Object to transform
86
+ * @param transform Transformer function
87
+ * @returns Transformed object
88
+ */
89
+ export function transform<Value extends PlainObject, Key extends keyof Value>(
90
+ value: Value,
91
+ transform: TransformCallback<Value, Key>,
92
+ ): Value;
93
+
94
+ /**
95
+ * Transform and objects properties using a transformer object
96
+ * @param value Object to transform
97
+ * @param transformers Keyed transformer functions
98
+ * @returns Transformed object
99
+ */
100
+ export function transform<Value extends PlainObject>(
101
+ value: Value,
102
+ transformers: TransformCallbacks<Value>,
103
+ ): Value;
104
+
105
+ export function transform<Value extends PlainObject>(value: Value, transform: unknown): Value {
106
+ return transformValue(value, getTransformer(transform));
107
+ }
108
+
109
+ transform.initialize = initializeTransformer;
110
+
111
+ function transformValue<Value extends PlainObject, Key extends keyof Value>(
112
+ value: Value,
113
+ transformer?: TransformCallback<Value, Key> | TransformCallbacks<Value>,
114
+ ): Value {
115
+ if (isNonPlainObject(value)) {
116
+ return {} as Value;
117
+ }
118
+
119
+ if (transformer == null) {
120
+ return value;
121
+ }
122
+
123
+ const keys = Object.keys(value) as Key[];
124
+ const {length} = keys;
125
+
126
+ for (let index = 0; index < length; index += 1) {
127
+ const key = keys[index];
128
+ const val = value[key];
129
+
130
+ if (typeof transformer === 'function') {
131
+ value[key] = transformer(key, val) as Value[Key];
132
+ } else {
133
+ value[key] = (transformer[key]?.(val) ?? val) as Value[Key];
134
+ }
135
+ }
136
+
137
+ return value;
138
+ }
139
+
140
+ // #endregion