drimion 0.1.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.
- package/LICENSE +7 -0
- package/README.md +955 -0
- package/dist/cli/index.js +1045 -0
- package/dist/cli/templates/aggregate.ts.hbs +22 -0
- package/dist/cli/templates/entity.ts.hbs +16 -0
- package/dist/cli/templates/repository.ts.hbs +24 -0
- package/dist/cli/templates/use-case.ts.hbs +20 -0
- package/dist/cli/templates/value-object.ts.hbs +16 -0
- package/dist/kernel/core/aggregate.ts +234 -0
- package/dist/kernel/core/entity.ts +348 -0
- package/dist/kernel/core/id.ts +207 -0
- package/dist/kernel/core/index.ts +5 -0
- package/dist/kernel/core/repository.ts +81 -0
- package/dist/kernel/core/value-object.ts +309 -0
- package/dist/kernel/events/browser-event-manager.ts +241 -0
- package/dist/kernel/events/domain-event.ts +76 -0
- package/dist/kernel/events/event-bus.ts +158 -0
- package/dist/kernel/events/event-context.ts +95 -0
- package/dist/kernel/events/event-manager.ts +20 -0
- package/dist/kernel/events/event-utils.ts +19 -0
- package/dist/kernel/events/index.ts +7 -0
- package/dist/kernel/events/server-event-manager.ts +169 -0
- package/dist/kernel/helpers/auto-mapper.ts +222 -0
- package/dist/kernel/helpers/domain-classes.ts +162 -0
- package/dist/kernel/helpers/domain-error.ts +52 -0
- package/dist/kernel/helpers/getters-setters.ts +385 -0
- package/dist/kernel/helpers/index.ts +7 -0
- package/dist/kernel/index.ts +73 -0
- package/dist/kernel/libs/crypto.ts +33 -0
- package/dist/kernel/libs/index.ts +5 -0
- package/dist/kernel/libs/iterator.ts +298 -0
- package/dist/kernel/libs/result.ts +252 -0
- package/dist/kernel/libs/utils.ts +260 -0
- package/dist/kernel/libs/validator.ts +353 -0
- package/dist/kernel/types/adapter.types.ts +26 -0
- package/dist/kernel/types/command.types.ts +37 -0
- package/dist/kernel/types/entity.types.ts +60 -0
- package/dist/kernel/types/event.types.ts +129 -0
- package/dist/kernel/types/index.ts +26 -0
- package/dist/kernel/types/iterator.types.ts +39 -0
- package/dist/kernel/types/result.types.ts +122 -0
- package/dist/kernel/types/uid.types.ts +18 -0
- package/dist/kernel/types/utils.types.ts +120 -0
- package/dist/kernel/types/value-object.types.ts +20 -0
- package/dist/kernel/utils/date.utils.ts +111 -0
- package/dist/kernel/utils/index.ts +32 -0
- package/dist/kernel/utils/number.utils.ts +341 -0
- package/dist/kernel/utils/object.utils.ts +61 -0
- package/dist/kernel/utils/string.utils.ts +128 -0
- package/dist/kernel/utils/type.utils.ts +33 -0
- package/package.json +59 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description
|
|
3
|
+
* Divides two numbers (`valueA` by `valueB`) with support for validation and normalization.
|
|
4
|
+
* Handles edge cases such as non-numeric inputs and applies a specified precision to the result.
|
|
5
|
+
*
|
|
6
|
+
* @param valueA The dividend (numerator). Can be a number or a value convertible to a number.
|
|
7
|
+
* @param valueB The divisor (denominator). Can be a number or a value convertible to a number.
|
|
8
|
+
* @param precision The number of decimal places to apply to the result. Defaults to 5.
|
|
9
|
+
* @returns The result of the division, normalized and adjusted to the specified precision.
|
|
10
|
+
* Returns `0` if either value is not a valid number.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* Divide(10, 2); // Returns 5
|
|
15
|
+
* Divide(10, 3, 3); // Returns 3.333
|
|
16
|
+
* Divide("10", "2"); // Returns 5 (handles string inputs)
|
|
17
|
+
* Divide(NaN, 2); // Returns 0
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export const Divide = (
|
|
21
|
+
valueA: number,
|
|
22
|
+
valueB: number,
|
|
23
|
+
precision = 5,
|
|
24
|
+
): number => {
|
|
25
|
+
const isValueOneNumber = typeof valueA === "number";
|
|
26
|
+
const isValueTwoNumber = typeof valueB === "number";
|
|
27
|
+
const isBothNumber = isValueOneNumber && isValueTwoNumber;
|
|
28
|
+
|
|
29
|
+
if (!isBothNumber) {
|
|
30
|
+
const isNaNValueA = IsNaN(valueA);
|
|
31
|
+
const isNaNValueB = IsNaN(valueB);
|
|
32
|
+
const isBothNaN = isNaNValueA && isNaNValueB;
|
|
33
|
+
|
|
34
|
+
if (isBothNaN || isNaNValueA || isNaNValueB) return 0;
|
|
35
|
+
const result = ToPrecision(
|
|
36
|
+
Float(ToLong(Float(valueA)) / ToLong(Float(valueB))),
|
|
37
|
+
precision,
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return EnsureNumber(result);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const result = ToPrecision(Float(ToLong(valueA) / ToLong(valueB)), precision);
|
|
44
|
+
return EnsureNumber(result);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @description
|
|
49
|
+
* Ensures the input is a valid number. If the input is `NaN` or `Infinity`, it returns `0`.
|
|
50
|
+
*
|
|
51
|
+
* @param value The number to validate.
|
|
52
|
+
* @returns The original number if it is valid, or `0` if the input is `NaN` or `Infinity`.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* EnsureNumber(42); // Returns 42
|
|
57
|
+
* EnsureNumber(NaN); // Returns 0
|
|
58
|
+
* EnsureNumber(Infinity); // Returns 0
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export const EnsureNumber = (value: number): number => {
|
|
62
|
+
if (Number.isNaN(value) || value === Infinity) return 0;
|
|
63
|
+
return value;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @description
|
|
68
|
+
* Normalizes a value into a floating-point number (`float`).
|
|
69
|
+
*
|
|
70
|
+
* If the value is a string representation of a number, it parses it into a `float`.
|
|
71
|
+
* If the value is already a number, it returns the value as is.
|
|
72
|
+
* If the value is invalid (`NaN` or non-numeric), it returns `0`.
|
|
73
|
+
*
|
|
74
|
+
* @param value The input value to normalize. Can be a string or a number.
|
|
75
|
+
* @returns A floating-point number representation of the input, or `0` if the input is invalid.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```typescript
|
|
79
|
+
* Float("123.45"); // Returns 123.45
|
|
80
|
+
* Float(678.90); // Returns 678.9
|
|
81
|
+
* Float("invalid"); // Returns 0
|
|
82
|
+
* Float(NaN); // Returns 0
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export const Float = (value: number): number => {
|
|
86
|
+
if (typeof value === "string" && !IsNaN(value)) return parseFloat(value);
|
|
87
|
+
if (typeof value === "number") return value;
|
|
88
|
+
return 0;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @description
|
|
93
|
+
* Checks if the provided value is `NaN` (Not-a-Number). The function attempts to parse the value into a number
|
|
94
|
+
* and determines if the result is `NaN`.
|
|
95
|
+
*
|
|
96
|
+
* @param value The value to check. Can be a string or a number.
|
|
97
|
+
* @returns `true` if the value is `NaN`, otherwise `false`.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```typescript
|
|
101
|
+
* IsNaN("123"); // Returns false (valid number)
|
|
102
|
+
* IsNaN("abc"); // Returns true (not a number)
|
|
103
|
+
* IsNaN(NaN); // Returns true
|
|
104
|
+
* IsNaN(123); // Returns false (valid number)
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
export const IsNaN = (value: string | number): boolean => {
|
|
108
|
+
return Number.isNaN(parseFloat(String(value)));
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @description
|
|
113
|
+
* Multiplies two numbers (`valueA` and `valueB`) with validation, normalization,
|
|
114
|
+
* and optional precision adjustment. Handles edge cases where the inputs are not valid numbers.
|
|
115
|
+
*
|
|
116
|
+
* @param valueA The first value to multiply. Can be a number or a value convertible to a number.
|
|
117
|
+
* @param valueB The second value to multiply. Can be a number or a value convertible to a number.
|
|
118
|
+
* @param precision The number of decimal places to apply to the result. Defaults to 5.
|
|
119
|
+
* @returns The result of the multiplication, normalized and adjusted to the specified precision.
|
|
120
|
+
* Returns `0` if either value is not a valid number.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```typescript
|
|
124
|
+
* Multiply(10, 2); // Returns 20
|
|
125
|
+
* Multiply(10, 2.5, 2); // Returns 25.00
|
|
126
|
+
* Multiply("10", "3"); // Returns 30 (handles string inputs)
|
|
127
|
+
* Multiply(NaN, 2); // Returns 0
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
export const Multiply = (
|
|
131
|
+
valueA: number,
|
|
132
|
+
valueB: number,
|
|
133
|
+
precision = 5,
|
|
134
|
+
): number => {
|
|
135
|
+
const isValueOneNumber = typeof valueA === "number";
|
|
136
|
+
const isValueTwoNumber = typeof valueB === "number";
|
|
137
|
+
const isBothNumber = isValueOneNumber && isValueTwoNumber;
|
|
138
|
+
|
|
139
|
+
if (!isBothNumber) {
|
|
140
|
+
const isNaNValueA = IsNaN(valueA);
|
|
141
|
+
const isNaNValueB = IsNaN(valueB);
|
|
142
|
+
const isBothNaN = isNaNValueA && isNaNValueB;
|
|
143
|
+
|
|
144
|
+
if (isBothNaN || isNaNValueA || isNaNValueB) return 0;
|
|
145
|
+
const result = ToPrecision(
|
|
146
|
+
ToDecimal(
|
|
147
|
+
Float(ToDecimal(ToLong(Float(valueA)) * ToLong(Float(valueB)))),
|
|
148
|
+
),
|
|
149
|
+
precision,
|
|
150
|
+
);
|
|
151
|
+
return EnsureNumber(result);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const result = ToPrecision(
|
|
155
|
+
ToDecimal(Float(ToDecimal(ToLong(valueA) * ToLong(valueB)))),
|
|
156
|
+
precision,
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
return EnsureNumber(result);
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* @description
|
|
164
|
+
* Subtracts one number (`valueB`) from another (`valueA`) with optional precision adjustment.
|
|
165
|
+
* Handles edge cases where inputs are not valid numbers by normalizing the values or returning defaults.
|
|
166
|
+
*
|
|
167
|
+
* @param valueA The first value (minuend). Can be a number or a value convertible to a number.
|
|
168
|
+
* @param valueB The second value (subtrahend). Can be a number or a value convertible to a number.
|
|
169
|
+
* @param precision The number of decimal places to apply to the result. Defaults to 5.
|
|
170
|
+
* @returns The result of the subtraction, normalized and adjusted to the specified precision.
|
|
171
|
+
* Returns `0` if both inputs are `NaN`. If one of the inputs is invalid, the valid input is returned
|
|
172
|
+
* (or negated if the second value is `NaN`).
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* ```typescript
|
|
176
|
+
* Subtract(10, 2); // Returns 8
|
|
177
|
+
* Subtract(10, "3.5", 2); // Returns 6.50
|
|
178
|
+
* Subtract(NaN, 5); // Returns -5
|
|
179
|
+
* Subtract(10, NaN); // Returns 10
|
|
180
|
+
* Subtract(NaN, NaN); // Returns 0
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export const Subtract = (
|
|
184
|
+
valueA: number,
|
|
185
|
+
valueB: number,
|
|
186
|
+
precision = 5,
|
|
187
|
+
): number => {
|
|
188
|
+
const isValueOneNumber = typeof valueA === "number";
|
|
189
|
+
const isValueTwoNumber = typeof valueB === "number";
|
|
190
|
+
const isBothNumber = isValueOneNumber && isValueTwoNumber;
|
|
191
|
+
|
|
192
|
+
if (!isBothNumber) {
|
|
193
|
+
const isNaNValueA = IsNaN(valueA);
|
|
194
|
+
const isNaNValueB = IsNaN(valueB);
|
|
195
|
+
const isBothNaN = isNaNValueA && isNaNValueB;
|
|
196
|
+
|
|
197
|
+
if (isBothNaN) return 0;
|
|
198
|
+
if (isNaNValueA) return Float(valueB) * -1;
|
|
199
|
+
if (isNaNValueB) return Float(valueA);
|
|
200
|
+
|
|
201
|
+
const result = ToPrecision(
|
|
202
|
+
Float(ToDecimal(ToLong(Float(valueA)) - ToLong(Float(valueB)))),
|
|
203
|
+
precision,
|
|
204
|
+
);
|
|
205
|
+
return EnsureNumber(result);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const result = ToPrecision(
|
|
209
|
+
Float(ToDecimal(ToLong(valueA) - ToLong(valueB))),
|
|
210
|
+
precision,
|
|
211
|
+
);
|
|
212
|
+
return EnsureNumber(result);
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* @description
|
|
217
|
+
* Adds two numbers (`valueA` and `valueB`) with optional precision adjustment.
|
|
218
|
+
* Handles edge cases where inputs are not valid numbers by normalizing the values or returning defaults.
|
|
219
|
+
*
|
|
220
|
+
* @param valueA The first value to add. Can be a number or a value convertible to a number.
|
|
221
|
+
* @param valueB The second value to add. Can be a number or a value convertible to a number.
|
|
222
|
+
* @param precision The number of decimal places to apply to the result. Defaults to 5.
|
|
223
|
+
* @returns The result of the addition, normalized and adjusted to the specified precision.
|
|
224
|
+
* Returns `0` if both inputs are `NaN`. If one of the inputs is invalid, the valid input is returned.
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* ```typescript
|
|
228
|
+
* Sum(10, 5); // Returns 15
|
|
229
|
+
* Sum(10, "3.5", 2); // Returns 13.50
|
|
230
|
+
* Sum(NaN, 5); // Returns 5
|
|
231
|
+
* Sum(10, NaN); // Returns 10
|
|
232
|
+
* Sum(NaN, NaN); // Returns 0
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
export const Sum = (valueA: number, valueB: number, precision = 5): number => {
|
|
236
|
+
const isValueOneNumber = typeof valueA === "number";
|
|
237
|
+
const isValueTwoNumber = typeof valueB === "number";
|
|
238
|
+
const isBothNumber = isValueOneNumber && isValueTwoNumber;
|
|
239
|
+
|
|
240
|
+
if (!isBothNumber) {
|
|
241
|
+
const isNaNValueA = IsNaN(valueA);
|
|
242
|
+
const isNaNValueB = IsNaN(valueB);
|
|
243
|
+
const isBothNaN = isNaNValueA && isNaNValueB;
|
|
244
|
+
|
|
245
|
+
if (isBothNaN) return 0;
|
|
246
|
+
if (isNaNValueA) return Float(valueB);
|
|
247
|
+
if (isNaNValueB) return Float(valueA);
|
|
248
|
+
|
|
249
|
+
const result = ToPrecision(
|
|
250
|
+
Float(ToDecimal(ToLong(Float(valueA)) + ToLong(Float(valueB)))),
|
|
251
|
+
precision,
|
|
252
|
+
);
|
|
253
|
+
return EnsureNumber(result);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const result = ToPrecision(
|
|
257
|
+
Float(ToDecimal(ToLong(valueA) + ToLong(valueB))),
|
|
258
|
+
precision,
|
|
259
|
+
);
|
|
260
|
+
return EnsureNumber(result);
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* @description
|
|
265
|
+
* Converts a number to its decimal equivalent by dividing it by 100.
|
|
266
|
+
* This is useful for normalizing values, such as converting percentages to decimals.
|
|
267
|
+
*
|
|
268
|
+
* @param value The input value to convert. Must be a number.
|
|
269
|
+
* @returns The decimal equivalent of the input number.
|
|
270
|
+
* If the input is not a valid number, it returns the input as is.
|
|
271
|
+
*
|
|
272
|
+
* @example
|
|
273
|
+
* ```typescript
|
|
274
|
+
* ToDecimal(500); // Returns 5
|
|
275
|
+
* ToDecimal(25); // Returns 0.25
|
|
276
|
+
* ToDecimal("100"); // Returns "100" (input not a valid number)
|
|
277
|
+
* ```
|
|
278
|
+
*/
|
|
279
|
+
export const ToDecimal = (value: number): number => {
|
|
280
|
+
const isValid = typeof value === "number";
|
|
281
|
+
if (!isValid) return value;
|
|
282
|
+
return value / 100;
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* @description
|
|
287
|
+
* Converts a number to its "long" equivalent by multiplying it by 100.
|
|
288
|
+
* This is useful for denormalizing values, such as converting decimals to percentages.
|
|
289
|
+
*
|
|
290
|
+
* @param value The input value to convert. Must be a number.
|
|
291
|
+
* @returns The "long" equivalent of the input number.
|
|
292
|
+
* If the input is not a valid number, it returns the input as is.
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* ```typescript
|
|
296
|
+
* ToLong(5); // Returns 500
|
|
297
|
+
* ToLong(0.25); // Returns 25
|
|
298
|
+
* ToLong("100"); // Returns "100" (input not a valid number)
|
|
299
|
+
* ```
|
|
300
|
+
*/
|
|
301
|
+
export const ToLong = (value: number): number => {
|
|
302
|
+
const isValid = typeof value === "number";
|
|
303
|
+
if (!isValid) return value;
|
|
304
|
+
return value * 100;
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* @description
|
|
309
|
+
* Adjusts a number or numeric string to a specified precision. The function ensures that the
|
|
310
|
+
* result maintains the desired level of precision, handling both integer and decimal parts appropriately.
|
|
311
|
+
*
|
|
312
|
+
* @param value The input value to be adjusted. Can be a number or a numeric string.
|
|
313
|
+
* @param precision The desired number of decimal places in the result.
|
|
314
|
+
* @returns A number rounded to the specified precision. If the input is a string, it is parsed and adjusted accordingly.
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* ```typescript
|
|
318
|
+
* ToPrecision(123.456789, 2); // Returns 123.46
|
|
319
|
+
* ToPrecision("987.654321", 3); // Returns 987.654
|
|
320
|
+
* ToPrecision(10.5, 1); // Returns 10.5
|
|
321
|
+
* ```
|
|
322
|
+
*/
|
|
323
|
+
export const ToPrecision = (
|
|
324
|
+
value: number | string,
|
|
325
|
+
precision: number,
|
|
326
|
+
): number => {
|
|
327
|
+
if (typeof value === "string") {
|
|
328
|
+
return parseFloat(parseFloat(String(value)).toFixed(precision));
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const int = Math.trunc(value) * 100;
|
|
332
|
+
const dec = Number(
|
|
333
|
+
((value * 100 - int) / 100)
|
|
334
|
+
.toPrecision(precision + 3)
|
|
335
|
+
.slice(0, precision + 2),
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
return Number(
|
|
339
|
+
(int / 100 + dec).toPrecision(String(int).length + 1 + precision),
|
|
340
|
+
);
|
|
341
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description
|
|
3
|
+
* Recursively freezes an object to make it immutable. This prevents any modifications to the object or its nested properties.
|
|
4
|
+
*
|
|
5
|
+
* @typeParam T - The type of the object being frozen.
|
|
6
|
+
* @param obj The object to be deeply frozen. If the input is not an object, it is returned as is.
|
|
7
|
+
* @returns The same object, but deeply frozen to prevent further modifications.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const mutableObject = { a: 1, b: { c: 2 } };
|
|
12
|
+
* const frozenObject = DeepFreeze(mutableObject);
|
|
13
|
+
*
|
|
14
|
+
* frozenObject.a = 2; // This will throw a TypeError in strict mode.
|
|
15
|
+
* frozenObject.b.c = 3; // This will also throw a TypeError.
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export const DeepFreeze = <T extends object>(obj: T): T => {
|
|
19
|
+
if (!obj || typeof obj !== "object") return obj;
|
|
20
|
+
|
|
21
|
+
Object.keys(obj).forEach((prop) => {
|
|
22
|
+
const key = prop as keyof typeof obj;
|
|
23
|
+
if (typeof obj[key] === "object" && !Object.isFrozen(obj[key]))
|
|
24
|
+
DeepFreeze(obj[key] as T);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return Object.freeze(obj) as T;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @description
|
|
32
|
+
* Stringifies values with stable object key ordering so deeply equal objects
|
|
33
|
+
* produce the same representation regardless of insertion order.
|
|
34
|
+
*/
|
|
35
|
+
export const StableStringify = (value: unknown): string => {
|
|
36
|
+
const seen = new WeakSet<object>();
|
|
37
|
+
|
|
38
|
+
const normalize = (target: unknown): unknown => {
|
|
39
|
+
if (target === null || typeof target !== "object") {
|
|
40
|
+
if (typeof target === "bigint") return target.toString();
|
|
41
|
+
if (typeof target === "symbol") return target.description;
|
|
42
|
+
if (typeof target === "function") return target.toString();
|
|
43
|
+
return target;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (target instanceof Date) return target.toISOString();
|
|
47
|
+
|
|
48
|
+
if (seen.has(target)) return "[Circular]";
|
|
49
|
+
seen.add(target);
|
|
50
|
+
|
|
51
|
+
if (Array.isArray(target)) return target.map((item) => normalize(item));
|
|
52
|
+
|
|
53
|
+
const result: Record<string, unknown> = {};
|
|
54
|
+
for (const key of Object.keys(target).sort()) {
|
|
55
|
+
result[key] = normalize((target as Record<string, unknown>)[key]);
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return JSON.stringify(normalize(value));
|
|
61
|
+
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description
|
|
3
|
+
* Removes characters from a string based on a condition defined by the provided `IsChar` function.
|
|
4
|
+
*
|
|
5
|
+
* @param target The input string from which characters will be removed.
|
|
6
|
+
* @param IsChar A callback function that determines whether a character should be removed.
|
|
7
|
+
* It receives a character as input and returns `true` if the character should be removed, or `false` otherwise.
|
|
8
|
+
|
|
9
|
+
* @returns A new string with the characters removed based on the `IsChar` condition.
|
|
10
|
+
* If the input `target` is not a string, it returns the input as is.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const isVowel = (char: string) => 'aeiou'.includes(char.toLowerCase());
|
|
15
|
+
* const result = RemoveChars("Hello, World!", isVowel);
|
|
16
|
+
* console.log(result); // "Hll, Wrld!"
|
|
17
|
+
*
|
|
18
|
+
* const isDigit = (char: string) => /\d/.test(char);
|
|
19
|
+
* const result = RemoveChars("123abc456", isDigit);
|
|
20
|
+
* console.log(result); // "abc"
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export const RemoveChars = (
|
|
24
|
+
target: string,
|
|
25
|
+
IsChar: (char: string) => boolean,
|
|
26
|
+
): string => {
|
|
27
|
+
if (typeof target !== "string") return target;
|
|
28
|
+
|
|
29
|
+
const chars = target.split("");
|
|
30
|
+
const str = chars.reduce((prev, current) => {
|
|
31
|
+
const isSpecialChar = IsChar(current);
|
|
32
|
+
if (isSpecialChar) return prev;
|
|
33
|
+
return prev + current;
|
|
34
|
+
}, "");
|
|
35
|
+
|
|
36
|
+
return str;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @description
|
|
41
|
+
* Replaces all occurrences of a specified character in a string with a given value.
|
|
42
|
+
* The replacement is performed globally (all occurrences).
|
|
43
|
+
*
|
|
44
|
+
* @param target The string in which the replacements will be made.
|
|
45
|
+
* @param char The character or substring to replace. A global regular expression will be created based on this.
|
|
46
|
+
* @param value The value to replace the `char` with. Can be a string or a number.
|
|
47
|
+
* @returns A new string with all occurrences of `char` replaced by `value`.
|
|
48
|
+
* If the inputs are not valid (e.g., `target` or `char` are not strings), the original `target` is returned unchanged.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* // Example 1: Replace a character
|
|
53
|
+
* const result = Replace("hello world", "o", "a");
|
|
54
|
+
* console.log(result); // "hella warld"
|
|
55
|
+
*
|
|
56
|
+
* // Example 2: Replace a substring
|
|
57
|
+
* const result = Replace("2024-12-15", "-", "/");
|
|
58
|
+
* console.log(result); // "2024/12/15"
|
|
59
|
+
*
|
|
60
|
+
* // Example 3: Replace with a number
|
|
61
|
+
* const result = Replace("Price: $$", "$", 100);
|
|
62
|
+
* console.log(result); // "Price: 100100"
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export const ReplaceChars = (
|
|
66
|
+
target: string,
|
|
67
|
+
char: string,
|
|
68
|
+
value: string | number,
|
|
69
|
+
): string => {
|
|
70
|
+
const pattern = RegExp(char, "g");
|
|
71
|
+
const isValidTarget = typeof target === "string";
|
|
72
|
+
const isValidChar = typeof char === "string";
|
|
73
|
+
const isValidValue = typeof value === "string" || typeof value === "number";
|
|
74
|
+
|
|
75
|
+
const isValid = isValidChar && isValidTarget && isValidValue;
|
|
76
|
+
if (!isValid) return target;
|
|
77
|
+
|
|
78
|
+
return target.replace(pattern, `${value}`);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @description Removes all spaces from a given string. It utilizes the `RemoveChars` utility function,
|
|
83
|
+
* passing a condition to identify spaces as the characters to remove.
|
|
84
|
+
*
|
|
85
|
+
* @param target The input string from which spaces will be removed.
|
|
86
|
+
* @returns A new string with all spaces removed. If the input is not a valid string, it will return the input as is.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* const result = RemoveSpaces("Hello, World!");
|
|
91
|
+
* console.log(result); // "Hello,World!"
|
|
92
|
+
*
|
|
93
|
+
* const anotherResult = RemoveSpaces(" Open AI ");
|
|
94
|
+
* console.log(anotherResult); // "OpenAI"
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export const RemoveSpaces = (target: string): string => {
|
|
98
|
+
return RemoveChars(target, (char: string) => char === " ");
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @description
|
|
103
|
+
* Converts a JavaScript value into a specialized flatted string. This method serializes
|
|
104
|
+
* complex objects, including circular references, into a flat structure.
|
|
105
|
+
*
|
|
106
|
+
* @param value The JavaScript value to be stringified.
|
|
107
|
+
* @returns A flatted string representation of the value.
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```typescript
|
|
111
|
+
* const obj = { a: 1 };
|
|
112
|
+
* obj.self = obj;
|
|
113
|
+
* const result = Stringify(obj);
|
|
114
|
+
* console.log(result); // Outputs a flatted string representing the object with circular references.
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
export const Stringify = (value: unknown): string => {
|
|
118
|
+
const seen = new WeakSet();
|
|
119
|
+
return (
|
|
120
|
+
JSON.stringify(value, (_, val) => {
|
|
121
|
+
if (typeof val === "object" && val !== null) {
|
|
122
|
+
if (seen.has(val)) return "[Circular]";
|
|
123
|
+
seen.add(val);
|
|
124
|
+
}
|
|
125
|
+
return val;
|
|
126
|
+
}) ?? "undefined"
|
|
127
|
+
);
|
|
128
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import validator from "../libs/validator";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @description
|
|
5
|
+
* Get the actual type instead of using the built-in `typeof` keyword for clearer type output.
|
|
6
|
+
*
|
|
7
|
+
* @param props The argument to check the type against.
|
|
8
|
+
|
|
9
|
+
* @returns A string representing the actual type of the props.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const type = InvalidPropsType(null)
|
|
14
|
+
* console.log(type) // "Null" instead of "object"
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export const InvalidPropsType = (props: unknown): string => {
|
|
18
|
+
if (validator.isAggregate(props)) return "Aggregate";
|
|
19
|
+
if (validator.isArray(props)) return "Array";
|
|
20
|
+
if (validator.isBoolean(props)) return "boolean";
|
|
21
|
+
if (validator.isDate(props)) return "Date";
|
|
22
|
+
if (validator.isEntity(props)) return "Entity";
|
|
23
|
+
if (validator.isFunction(props)) return "Function";
|
|
24
|
+
if (validator.isID(props)) return "ID";
|
|
25
|
+
if (validator.isNull(props)) return "Null";
|
|
26
|
+
if (validator.isNumber(props)) return "Number";
|
|
27
|
+
if (validator.isObject(props)) return "Object";
|
|
28
|
+
if (validator.isString(props)) return "String";
|
|
29
|
+
if (validator.isSymbol(props)) return "Symbol";
|
|
30
|
+
if (validator.isUndefined(props)) return "Undefined";
|
|
31
|
+
if (validator.isValueObject(props)) return "Value Object";
|
|
32
|
+
return typeof props;
|
|
33
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "drimion",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Headless DDD primitives CLI for TypeScript — own your domain",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ddd",
|
|
7
|
+
"domain-driven-design",
|
|
8
|
+
"cli",
|
|
9
|
+
"codegen",
|
|
10
|
+
"typescript",
|
|
11
|
+
"scaffold",
|
|
12
|
+
"architecture"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/bramadl/drimion.git"
|
|
18
|
+
},
|
|
19
|
+
"type": "module",
|
|
20
|
+
"private": false,
|
|
21
|
+
"bin": {
|
|
22
|
+
"drimion": "dist/cli/index.js"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist/",
|
|
26
|
+
"README.md",
|
|
27
|
+
"LICENSE"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"release:patch": "./scripts/release.sh patch",
|
|
31
|
+
"release:minor": "./scripts/release.sh minor",
|
|
32
|
+
"release:major": "./scripts/release.sh major",
|
|
33
|
+
"build": "tsup && node scripts/copy.mjs",
|
|
34
|
+
"dev": "tsup --watch",
|
|
35
|
+
"test": "bun test",
|
|
36
|
+
"lint": "biome check src/",
|
|
37
|
+
"format": "biome format src/ --write"
|
|
38
|
+
},
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=18 || >=20"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@biomejs/biome": "2.4.14",
|
|
44
|
+
"@types/bun": "latest",
|
|
45
|
+
"@types/fs-extra": "^11.0.4",
|
|
46
|
+
"tsup": "^8.5.1"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"typescript": "^5"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@inquirer/prompts": "^8.4.2",
|
|
53
|
+
"chalk": "^5.6.2",
|
|
54
|
+
"commander": "^14.0.3",
|
|
55
|
+
"fs-extra": "^11.3.4",
|
|
56
|
+
"handlebars": "^4.7.9",
|
|
57
|
+
"ora": "^9.4.0"
|
|
58
|
+
}
|
|
59
|
+
}
|