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.
Files changed (51) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +955 -0
  3. package/dist/cli/index.js +1045 -0
  4. package/dist/cli/templates/aggregate.ts.hbs +22 -0
  5. package/dist/cli/templates/entity.ts.hbs +16 -0
  6. package/dist/cli/templates/repository.ts.hbs +24 -0
  7. package/dist/cli/templates/use-case.ts.hbs +20 -0
  8. package/dist/cli/templates/value-object.ts.hbs +16 -0
  9. package/dist/kernel/core/aggregate.ts +234 -0
  10. package/dist/kernel/core/entity.ts +348 -0
  11. package/dist/kernel/core/id.ts +207 -0
  12. package/dist/kernel/core/index.ts +5 -0
  13. package/dist/kernel/core/repository.ts +81 -0
  14. package/dist/kernel/core/value-object.ts +309 -0
  15. package/dist/kernel/events/browser-event-manager.ts +241 -0
  16. package/dist/kernel/events/domain-event.ts +76 -0
  17. package/dist/kernel/events/event-bus.ts +158 -0
  18. package/dist/kernel/events/event-context.ts +95 -0
  19. package/dist/kernel/events/event-manager.ts +20 -0
  20. package/dist/kernel/events/event-utils.ts +19 -0
  21. package/dist/kernel/events/index.ts +7 -0
  22. package/dist/kernel/events/server-event-manager.ts +169 -0
  23. package/dist/kernel/helpers/auto-mapper.ts +222 -0
  24. package/dist/kernel/helpers/domain-classes.ts +162 -0
  25. package/dist/kernel/helpers/domain-error.ts +52 -0
  26. package/dist/kernel/helpers/getters-setters.ts +385 -0
  27. package/dist/kernel/helpers/index.ts +7 -0
  28. package/dist/kernel/index.ts +73 -0
  29. package/dist/kernel/libs/crypto.ts +33 -0
  30. package/dist/kernel/libs/index.ts +5 -0
  31. package/dist/kernel/libs/iterator.ts +298 -0
  32. package/dist/kernel/libs/result.ts +252 -0
  33. package/dist/kernel/libs/utils.ts +260 -0
  34. package/dist/kernel/libs/validator.ts +353 -0
  35. package/dist/kernel/types/adapter.types.ts +26 -0
  36. package/dist/kernel/types/command.types.ts +37 -0
  37. package/dist/kernel/types/entity.types.ts +60 -0
  38. package/dist/kernel/types/event.types.ts +129 -0
  39. package/dist/kernel/types/index.ts +26 -0
  40. package/dist/kernel/types/iterator.types.ts +39 -0
  41. package/dist/kernel/types/result.types.ts +122 -0
  42. package/dist/kernel/types/uid.types.ts +18 -0
  43. package/dist/kernel/types/utils.types.ts +120 -0
  44. package/dist/kernel/types/value-object.types.ts +20 -0
  45. package/dist/kernel/utils/date.utils.ts +111 -0
  46. package/dist/kernel/utils/index.ts +32 -0
  47. package/dist/kernel/utils/number.utils.ts +341 -0
  48. package/dist/kernel/utils/object.utils.ts +61 -0
  49. package/dist/kernel/utils/string.utils.ts +128 -0
  50. package/dist/kernel/utils/type.utils.ts +33 -0
  51. package/package.json +59 -0
@@ -0,0 +1,298 @@
1
+ import type { IIterator, IIteratorConfig } from "../types/iterator.types";
2
+
3
+ /**
4
+ * @description
5
+ * The `Iterator` class provides a way to traverse through a collection of items sequentially,
6
+ * without exposing the underlying data structure. It supports both forward and backward traversal,
7
+ * optional looping behavior, and methods to manipulate the underlying collection.
8
+ */
9
+ export class Iterator<T> implements IIterator<T> {
10
+ private readonly items: Array<T>;
11
+ private readonly restartOnFinish: boolean;
12
+ private readonly returnCurrentOnReversion: boolean;
13
+ private currentIndex: number;
14
+ private lastCommand: "next" | "prev" | "none";
15
+
16
+ private constructor(config?: IIteratorConfig<T>) {
17
+ this.items = config?.initialData ?? [];
18
+ this.restartOnFinish = !!config?.restartOnFinish;
19
+ this.returnCurrentOnReversion = !!config?.returnCurrentOnReversion;
20
+ this.currentIndex = -1;
21
+ this.lastCommand = "none";
22
+ }
23
+
24
+ /**
25
+ * @description
26
+ * Creates a new `Iterator` instance from the provided configuration.
27
+ *
28
+ * @param config Optional configuration object.
29
+ * @param config.initialData An initial array of items to iterate over.
30
+ * @param config.returnCurrentOnReversion If `true`, the current item will be returned again before moving on when switching iteration direction.
31
+ * @param config.restartOnFinish If `true`, when reaching the end of the items, iteration continues from the opposite end, looping the iteration indefinitely.
32
+ *
33
+ * @returns A new `Iterator` instance.
34
+ */
35
+ public static create<U>(config?: IIteratorConfig<U>): Iterator<U> {
36
+ return new Iterator<U>(config);
37
+ }
38
+
39
+ /**
40
+ * @description
41
+ * Alias for `addToEnd` - adds a new item to the end of the collection.
42
+ *
43
+ * @param data The item to add.
44
+ * @returns The current `Iterator` instance.
45
+ */
46
+ public add(data: T): Iterator<T> {
47
+ return this.addToEnd(data);
48
+ }
49
+
50
+ /**
51
+ * @description
52
+ * Adds a new item to the end of the collection.
53
+ *
54
+ * @param data The item to add.
55
+ * @returns The current `Iterator` instance.
56
+ */
57
+ public addToEnd(data: T): Iterator<T> {
58
+ this.items.push(data);
59
+ return this;
60
+ }
61
+
62
+ /**
63
+ * @description
64
+ * Adds a new item to the start of the collection and resets the cursor to before the first element.
65
+ *
66
+ * @param data The item to add.
67
+ * @returns The current `Iterator` instance.
68
+ */
69
+ public addToStart(data: T): Iterator<T> {
70
+ this.currentIndex = -1;
71
+ this.items.unshift(data);
72
+ return this;
73
+ }
74
+
75
+ /**
76
+ * @description
77
+ * Removes all items from the collection.
78
+ *
79
+ * @returns The current `Iterator` instance.
80
+ */
81
+ public clear(): Iterator<T> {
82
+ this.items.splice(0, this.total());
83
+ this.currentIndex = -1;
84
+ return this;
85
+ }
86
+
87
+ /**
88
+ * @description
89
+ * Creates a new Iterator instance with the same configuration and current state as the existing one.
90
+ *
91
+ * @returns A cloned Iterator instance.
92
+ */
93
+ public clone(): IIterator<T> {
94
+ return Iterator.create({
95
+ initialData: this.toArray(),
96
+ restartOnFinish: this.restartOnFinish,
97
+ returnCurrentOnReversion: this.returnCurrentOnReversion,
98
+ });
99
+ }
100
+
101
+ /**
102
+ * @description
103
+ * Returns the first item in the collection without changing the current index.
104
+ *
105
+ * @returns The first item, or `undefined` if empty.
106
+ */
107
+ public first(): T {
108
+ return this.items.at(0) as T;
109
+ }
110
+
111
+ /**
112
+ * @description
113
+ * Checks if there is another item after the current position.
114
+ *
115
+ * @returns `true` if another item is available after the current index, otherwise `false`.
116
+ */
117
+ public hasNext(): boolean {
118
+ if (this.isEmpty()) return false;
119
+ return this.currentIndex + 1 < this.items.length;
120
+ }
121
+
122
+ /**
123
+ * @description
124
+ * Checks if there is another item before the current position.
125
+ *
126
+ * @returns `true` if another item is available before the current index, otherwise `false`.
127
+ */
128
+ public hasPrev(): boolean {
129
+ if (this.isEmpty()) return false;
130
+ return this.currentIndex - 1 >= 0;
131
+ }
132
+
133
+ /**
134
+ * @description
135
+ * Checks if the iterator has no items.
136
+ *
137
+ * @returns `true` if there are no items, otherwise `false`.
138
+ */
139
+ public isEmpty(): boolean {
140
+ return this.total() === 0;
141
+ }
142
+
143
+ /**
144
+ * @description
145
+ * Returns the last item in the collection without changing the current index.
146
+ *
147
+ * @returns The last item, or `undefined` if empty.
148
+ */
149
+ public last(): T {
150
+ return this.items.at(-1) as T;
151
+ }
152
+
153
+ /**
154
+ * @description
155
+ * Moves the iterator forward and returns the next item.
156
+ *
157
+ * If `restartOnFinish` is `true` and the end is reached, iteration restarts from the beginning.
158
+ * If `restartOnFinish` is `false` and the end is reached, returns `null`.
159
+ *
160
+ * @returns The next item, or `null` if no next item exists and looping is disabled.
161
+ */
162
+ public next(): T {
163
+ if (this.hasNext()) {
164
+ if (this.lastCommand === "prev" && this.currentIndex === 0) {
165
+ this.lastCommand = "next";
166
+ return this.items[this.currentIndex] as T;
167
+ }
168
+ const nextIndex = this.currentIndex + 1;
169
+ this.currentIndex = nextIndex;
170
+ this.lastCommand = this.returnCurrentOnReversion ? "next" : "none";
171
+ return this.items[nextIndex] as T;
172
+ }
173
+ if (!this.restartOnFinish) return null as unknown as T;
174
+ this.toFirst();
175
+ return this.first();
176
+ }
177
+
178
+ /**
179
+ * @description
180
+ * Moves the iterator backward and returns the previous item.
181
+ *
182
+ * If `restartOnFinish` is `true` and the beginning is reached, iteration continues from the end.
183
+ * If `restartOnFinish` is `false` and the beginning is reached, returns `null`.
184
+ *
185
+ * @returns The previous item, or `null` if no previous item exists and looping is disabled.
186
+ */
187
+ public prev(): T {
188
+ if (this.hasPrev()) {
189
+ if (
190
+ this.lastCommand === "next" &&
191
+ this.currentIndex === this.total() - 1
192
+ ) {
193
+ this.lastCommand = "prev";
194
+ return this.items[this.currentIndex] as T;
195
+ }
196
+ const prevIndex = this.currentIndex - 1;
197
+ this.currentIndex = prevIndex;
198
+ this.lastCommand = this.returnCurrentOnReversion ? "prev" : "none";
199
+ return this.items[prevIndex] as T;
200
+ }
201
+ if (!this.restartOnFinish) return null as unknown as T;
202
+ this.toLast();
203
+ return this.last();
204
+ }
205
+
206
+ /**
207
+ * @description
208
+ * Removes the first item from the collection.
209
+ *
210
+ * @returns The current `Iterator` instance.
211
+ */
212
+ public removeFirst(): Iterator<T> {
213
+ if (this.currentIndex > 0) this.currentIndex -= 1;
214
+ this.items.shift();
215
+ return this;
216
+ }
217
+
218
+ /**
219
+ * @description
220
+ * Removes a specific item from the iterator's collection.
221
+ *
222
+ * If the item is found and removed, the current index is adjusted accordingly.
223
+ *
224
+ * @param item The item to be removed.
225
+ */
226
+ public removeItem(item: T): void {
227
+ const index = this.items.findIndex(
228
+ (value) => JSON.stringify(item) === JSON.stringify(value),
229
+ );
230
+
231
+ if (index !== -1) {
232
+ this.items.splice(index, 1);
233
+ if (index >= this.currentIndex) this.prev();
234
+ }
235
+ }
236
+
237
+ /**
238
+ * @description
239
+ * Removes the last item from the collection.
240
+ *
241
+ * @returns The current `Iterator` instance.
242
+ */
243
+ public removeLast(): Iterator<T> {
244
+ if (this.currentIndex >= this.total()) this.currentIndex -= 1;
245
+ this.items.pop();
246
+ return this;
247
+ }
248
+
249
+ /**
250
+ * @description
251
+ * Returns all items in the iterator as an array.
252
+ *
253
+ * @returns A copy of the internal array of items.
254
+ */
255
+ public toArray(): Array<T> {
256
+ return [...this.items];
257
+ }
258
+
259
+ /**
260
+ * @description
261
+ * Moves the internal cursor to the start of the collection.
262
+ *
263
+ * @returns The current `Iterator` instance.
264
+ */
265
+ public toFirst(): Iterator<T> {
266
+ if (this.currentIndex === 0 || this.currentIndex === -1) {
267
+ this.currentIndex = -1;
268
+ return this;
269
+ }
270
+ this.currentIndex = 0;
271
+ return this;
272
+ }
273
+
274
+ /**
275
+ * @description
276
+ * Moves the internal cursor to the end of the collection.
277
+ *
278
+ * @returns The current `Iterator` instance.
279
+ */
280
+ public toLast(): Iterator<T> {
281
+ if (this.currentIndex === this.total() - 1 || this.currentIndex === -1) {
282
+ this.currentIndex = this.total();
283
+ return this;
284
+ }
285
+ this.currentIndex = this.total() - 1;
286
+ return this;
287
+ }
288
+
289
+ /**
290
+ * @description
291
+ * Returns the total number of items in the iterator.
292
+ *
293
+ * @returns The count of items in the underlying collection.
294
+ */
295
+ public total(): number {
296
+ return this.items.length;
297
+ }
298
+ }
@@ -0,0 +1,252 @@
1
+ import type { ICommand } from "../types/command.types";
2
+ import type { IIterator } from "../types/iterator.types";
3
+ import type {
4
+ IResult,
5
+ IResultExecuteFn,
6
+ IResultHook,
7
+ IResultObject,
8
+ IResultOption,
9
+ } from "../types/result.types";
10
+ import type { AnyObject } from "../types/utils.types";
11
+ import { Iterator } from "./iterator";
12
+
13
+ /**
14
+ * @description
15
+ * The `Result` class represents the outcome of an operation, encapsulating both the success or failure state.
16
+ *
17
+ * A `Result` instance can contain a payload (`data`), an error, and optional metadata for additional context.
18
+ * This pattern encourages explicit handling of operation success or failure, making your code more robust and expressive.
19
+ *
20
+ * @typeParam `T` - The type of the payload when the result is successful.
21
+ * @typeParam `D` - The type of the error when the result is a failure. Defaults to `string`.
22
+ * @typeParam `M` - The type of the metadata object. Defaults to an empty object `{}`.
23
+ *
24
+ */
25
+ export class Result<T = void, D = string, M = AnyObject>
26
+ implements IResult<T, D, M>
27
+ {
28
+ readonly #data: Readonly<T | null>;
29
+ readonly #error: Readonly<D | null>;
30
+ readonly #isError: Readonly<boolean>;
31
+ readonly #isSuccess: Readonly<boolean>;
32
+ readonly #metaData: Readonly<M>;
33
+
34
+ private constructor(isSuccess: boolean, data?: T, error?: D, metaData?: M) {
35
+ this.#data = data ?? null;
36
+ this.#error = error ?? null;
37
+ this.#isError = !isSuccess;
38
+ this.#isSuccess = isSuccess;
39
+ this.#metaData = metaData ?? ({} as M);
40
+ }
41
+
42
+ /**
43
+ * @description
44
+ * Creates a failure `Result` instance, optionally containing an error and metadata.
45
+ *
46
+ * @returns A `Result` instance representing failure.
47
+ */
48
+ public static error<D = string, M = AnyObject, P = void>(
49
+ error?: D,
50
+ metaData?: M,
51
+ ): IResult<P, D, M>;
52
+ public static error<D = string, M = AnyObject, T = void>(
53
+ error: D,
54
+ metaData?: M,
55
+ ): IResult<T, D, M> {
56
+ const errorMessage =
57
+ typeof error !== "undefined" && error !== null
58
+ ? error
59
+ : "void error. no message!";
60
+
61
+ const fail = new Result(
62
+ false,
63
+ null,
64
+ errorMessage,
65
+ metaData,
66
+ ) as unknown as IResult<T, D, M>;
67
+
68
+ return Object.freeze(fail) as IResult<T, D, M>;
69
+ }
70
+
71
+ /**
72
+ * @description
73
+ * Combines multiple `Result` instances into a single `Result`.
74
+ *
75
+ * If any of the provided results is a failure, the combined `Result` is a failure.
76
+ * If all results are successful, the combined `Result` is considered a success.
77
+ *
78
+ * @param results An array of `Result` instances to combine.
79
+ * @returns A `Result` instance representing the combined outcome.
80
+ */
81
+ public static combine<A = unknown, B = unknown, M = unknown>(
82
+ results: Array<IResult<unknown, unknown, unknown>>,
83
+ ): IResult<A, B, M> {
84
+ const iterator = Result.iterate(results);
85
+ if (iterator.isEmpty()) {
86
+ return Result.error(
87
+ "No results provided on combine param" as B,
88
+ ) as unknown as IResult<A, B, M>;
89
+ }
90
+
91
+ while (iterator.hasNext()) {
92
+ const currentResult = iterator.next();
93
+ if (currentResult.isError()) return currentResult as IResult<A, B, M>;
94
+ }
95
+
96
+ return iterator.first() as IResult<A, B, M>;
97
+ }
98
+
99
+ /**
100
+ * @description
101
+ * Retrieves the error of the `Result`. If the `Result` is a success, `error()` returns `null`.
102
+ *
103
+ * @returns The error `D` or `null` if the result is a success.
104
+ */
105
+ public error(): D {
106
+ return this.#error as D;
107
+ }
108
+
109
+ /**
110
+ * @description
111
+ * Executes a command based on the result state. You can specify whether the command executes on success, failure, or both.
112
+ * Optionally, you can provide data to the command if required.
113
+ *
114
+ * @param command An object implementing `ICommand` interface.
115
+ * @returns An object with methods to configure command execution based on the `Result` state.
116
+ */
117
+ public execute<X, Y>(command: ICommand<X, Y>): IResultExecuteFn<X, Y> {
118
+ return {
119
+ on: (
120
+ option: IResultOption,
121
+ ): Promise<IResult<Y, string, AnyObject>> | undefined => {
122
+ if (option === "success" && this.isSuccess())
123
+ return command.execute(undefined as unknown as X);
124
+ if (option === "error" && this.isError())
125
+ return command.execute(undefined as unknown as X);
126
+ },
127
+ withData: (data: X): IResultHook<Y> => {
128
+ return {
129
+ on: (
130
+ option: IResultOption,
131
+ ): Promise<IResult<Y, string, AnyObject>> | undefined => {
132
+ if (option === "success" && this.isSuccess())
133
+ return command.execute(data);
134
+ if (option === "error" && this.isError())
135
+ return command.execute(data);
136
+ },
137
+ };
138
+ },
139
+ };
140
+ }
141
+
142
+ /**
143
+ * @description
144
+ * Determines if the `Result` represents a failure state.
145
+ *
146
+ * @returns `true` if the result is a failure, `false` if it is a success.
147
+ */
148
+ public isError(): boolean {
149
+ return this.#isError;
150
+ }
151
+
152
+ /**
153
+ * @description
154
+ * Checks if the `Result` payload is `null`.
155
+ *
156
+ * This can be useful for confirming the presence or absence of a value before proceeding.
157
+ *
158
+ * @returns `true` if the payload is `null`, `false` otherwise.
159
+ */
160
+ public isNull(): boolean {
161
+ return this.#data === null || this.#isError;
162
+ }
163
+
164
+ /**
165
+ * @description
166
+ * Determines if the `Result` represents a success state.
167
+ *
168
+ * @returns `true` if the result is a success, `false` if it is a failure.
169
+ */
170
+ public isSuccess(): boolean {
171
+ return this.#isSuccess;
172
+ }
173
+
174
+ /**
175
+ * @description
176
+ * Creates an iterator over a collection of `Result` instances. This allows sequential processing of multiple results.
177
+ *
178
+ * @param results An array of `Result` instances.
179
+ * @returns An `Iterator` over the provided results.
180
+ */
181
+ public static iterate<A, B, M>(
182
+ results?: Array<IResult<A, B, M>>,
183
+ ): IIterator<IResult<A, B, M>> {
184
+ return Iterator.create<IResult<A, B, M>>({
185
+ initialData: results,
186
+ returnCurrentOnReversion: true,
187
+ });
188
+ }
189
+
190
+ /**
191
+ * @description
192
+ * Retrieves the metadata associated with the `Result`.
193
+ *
194
+ * @returns The metadata object `M`, or `{}` if no metadata was provided.
195
+ */
196
+ public metaData(): M {
197
+ const metaData = this.#metaData;
198
+ return Object.freeze(metaData);
199
+ }
200
+
201
+ /**
202
+ * @description
203
+ * Creates a success `Result` instance, optionally containing data and metadata.
204
+ *
205
+ * @returns A `Result` instance representing success.
206
+ */
207
+ public static success(): IResult<void>;
208
+ public static success<T, M = AnyObject, D = string>(
209
+ data: T,
210
+ metaData?: M,
211
+ ): IResult<T, D, M>;
212
+ public static success<T, M = AnyObject, D = string>(
213
+ data?: T,
214
+ metaData?: M,
215
+ ): IResult<T, D, M> {
216
+ const _data = typeof data === "undefined" ? null : data;
217
+ const ok = new Result(true, _data, null, metaData) as unknown as IResult<
218
+ T,
219
+ D,
220
+ M
221
+ >;
222
+ return Object.freeze(ok) as IResult<T, D, M>;
223
+ }
224
+
225
+ /**
226
+ * @description
227
+ * Converts the `Result` instance into a plain object for easier logging or serialization.
228
+ *
229
+ * @returns An object containing `isSuccess`, `isError`, `data`, `error`, and `metaData`.
230
+ */
231
+ public toObject(): IResultObject<T, D, M> {
232
+ const metaData = {
233
+ isSuccess: this.#isSuccess,
234
+ isError: this.#isError,
235
+ data: this.#data as T | null,
236
+ error: this.#error as D | null,
237
+ metaData: this.#metaData as M,
238
+ };
239
+
240
+ return Object.freeze(metaData);
241
+ }
242
+
243
+ /**
244
+ * @description
245
+ * Retrieves the payload of the `Result`. If the `Result` is a failure, `value()` returns `null`.
246
+ *
247
+ * @returns The payload `T` or `null` if the result is a failure.
248
+ */
249
+ public value(): T {
250
+ return this.#data as T;
251
+ }
252
+ }