tshex-cli 1.0.18 → 1.0.20

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/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "tshex-cli",
3
- "version": "1.0.18",
3
+ "version": "1.0.20",
4
4
  "author": "https://github.com/virtualitems/",
5
+ "license": "MIT",
5
6
  "description": "Typescript Hexagonal Architecture CLI",
6
7
  "type": "module",
7
8
  "main": "./build/main.js",
@@ -0,0 +1,15 @@
1
+ import { DataManager } from './managers.js'
2
+
3
+ /**
4
+ * @description Declares the connection contract with a data source driver.
5
+ * It connects to the source, returns an enabled data manager, and disconnects when the work is done.
6
+ * This declaration belongs to the application layer as a contract,
7
+ * while its concrete implementation belongs to the adapters layer.
8
+ */
9
+ export abstract class DriverAdapter<M extends DataManager = DataManager> {
10
+ [property: string]: unknown
11
+
12
+ public abstract connect(...args: unknown[]): Promise<M>
13
+
14
+ public abstract disconnect(): Promise<unknown>
15
+ } //:: class
@@ -0,0 +1,81 @@
1
+ /**
2
+ * @description Declares a filtering operation over plain source records.
3
+ */
4
+ export interface Filterable<S = Record<string, unknown>> {
5
+ filter(selector: S): Promise<Array<S>>
6
+ }
7
+
8
+ /**
9
+ * @description Declares a sorting operation over plain source records.
10
+ */
11
+ export interface Sortable<S = Record<string, unknown>> {
12
+ sort(selector: S): Promise<Array<S>>
13
+ }
14
+
15
+ /**
16
+ * @description Declares a creation operation for plain source records.
17
+ */
18
+ export interface Creatable<D = Record<string, unknown>> {
19
+ create(data: D): Promise<unknown>
20
+ }
21
+
22
+ /**
23
+ * @description Declares an update operation that selects source records and applies new plain data.
24
+ */
25
+ export interface Updatable<S = Record<string, unknown>, D = Record<string, unknown>> {
26
+ update(selector: S, data: D): Promise<unknown>
27
+ }
28
+
29
+ /**
30
+ * @description Declares a deletion operation over source records selected by plain criteria.
31
+ */
32
+ export interface Deletable<S = Record<string, unknown>> {
33
+ delete(selector: S): Promise<unknown>
34
+ }
35
+
36
+ /**
37
+ * @description Declares an aggregation operation over source records.
38
+ */
39
+ export interface Aggregatable<S = Record<string, unknown>> {
40
+ aggregate(selector: S): Promise<S>
41
+ }
42
+
43
+ /**
44
+ * @description Declares operations for selecting or preloading relationships from a data source.
45
+ */
46
+ export interface Relatable {
47
+ selectRelated(...args: unknown[]): unknown
48
+
49
+ prefetchRelated(...args: unknown[]): unknown
50
+ }
51
+
52
+ /**
53
+ * @description Operates on a data source using plain objects and arrays.
54
+ * It exposes the raw data without transforming it.
55
+ */
56
+ export abstract class DataManager<T = Record<string, unknown>> {
57
+ [property: string]: unknown
58
+
59
+ public none(): Array<T> {
60
+ return []
61
+ }
62
+
63
+ public abstract all(): Promise<Array<T>>
64
+ } //:: class
65
+
66
+ /**
67
+ * @description Extends a data manager with set operations over data collections.
68
+ */
69
+ export abstract class DatasetManager<T = Record<string, unknown>> extends DataManager<T> {
70
+ [property: string]: unknown
71
+
72
+ public abstract union(other: Array<T>): Promise<Array<T>>
73
+
74
+ public abstract intersection(other: Array<T>): Promise<Array<T>>
75
+
76
+ public abstract difference(other: Array<T>): Promise<Array<T>>
77
+
78
+ public abstract symmetricDifference(other: Array<T>): Promise<Array<T>>
79
+
80
+ public abstract complement(other: Array<T>): Promise<Array<T>>
81
+ } //:: class
@@ -0,0 +1,29 @@
1
+ import { type DataManager } from './managers.js'
2
+ import { type DriverAdapter } from './drivers.js'
3
+
4
+ /**
5
+ * @description Acts as an intermediary between plain source data and domain objects.
6
+ * It transforms records into domain representations and can translate them back when needed.
7
+ */
8
+ export abstract class Repository<
9
+ DataShape extends Record<string, unknown> = Record<string, unknown>,
10
+ EntityShape extends Record<string, unknown> = Record<string, unknown>
11
+ > {
12
+ [property: string]: unknown
13
+
14
+ public constructor(public readonly driver: DriverAdapter<DataManager<DataShape>>) {}
15
+
16
+ public async all(): Promise<Array<EntityShape>> {
17
+ const connection = await this.driver.connect()
18
+ const raw = await connection.all()
19
+ const entities = this.transformList(raw)
20
+ await this.driver.disconnect()
21
+ return entities
22
+ }
23
+
24
+ protected transformList(data: Array<DataShape>): Array<EntityShape> {
25
+ return data.map(this.transform)
26
+ }
27
+
28
+ protected abstract transform(data: DataShape): EntityShape
29
+ } //:: class
@@ -1,121 +1,35 @@
1
- // Libraries
2
-
3
- // Same Layer
4
-
5
- // Lower Layers
6
-
7
- // Types
8
-
9
- // Constants
10
-
11
1
  /**
12
- * @description
2
+ * @description Represents something that occurred in the application.
3
+ * It carries the event time and its plain details.
13
4
  */
14
5
  export abstract class Event {
15
6
  [property: string]: unknown
16
7
 
17
- // public ATTRIBUTES
18
-
19
- // protected ATTRIBUTES
20
-
21
- // private ATTRIBUTES
22
-
23
- // public static ATTRIBUTES
24
-
25
- // protected static ATTRIBUTES
26
-
27
- // private static ATTRIBUTES
28
-
29
- // Constructor, Getters, Setters
30
-
31
8
  public constructor(
32
9
  public readonly timestamp: number = Date.now(),
33
10
  public readonly details: Record<string, unknown> = {}
34
11
  ) {}
35
-
36
- // public METHODS
37
-
38
- // protected METHODS
39
-
40
- // private METHODS
41
-
42
- // public static METHODS
43
-
44
- // protected static METHODS
45
-
46
- // private static METHODS
47
12
  } //:: class
48
13
 
49
14
  /**
50
- * @description
15
+ * @description Represents a reaction to an application event.
51
16
  */
52
17
  export abstract class EventHandler {
53
18
  [property: string]: unknown
54
19
 
55
- // public ATTRIBUTES
56
-
57
- // protected ATTRIBUTES
58
-
59
- // private ATTRIBUTES
60
-
61
- // public static ATTRIBUTES
62
-
63
- // protected static ATTRIBUTES
64
-
65
- // private static ATTRIBUTES
66
-
67
- // Constructor, Getters, Setters
68
-
69
- // public METHODS
70
-
71
20
  public abstract handle(event: Event): Promise<void>
72
-
73
- // protected METHODS
74
-
75
- // private METHODS
76
-
77
- // public static METHODS
78
-
79
- // protected static METHODS
80
-
81
- // private static METHODS
82
21
  } //:: class
83
22
 
84
23
  /**
85
- * @description
24
+ * @description Declares the interaction contract with an event bus.
25
+ * It subscribes handlers, removes subscriptions, and dispatches events.
86
26
  */
87
27
  export abstract class EventDispatcher {
88
28
  [property: string]: unknown
89
29
 
90
- // public ATTRIBUTES
91
-
92
- // protected ATTRIBUTES
93
-
94
- // private ATTRIBUTES
95
-
96
- // public static ATTRIBUTES
97
-
98
- // protected static ATTRIBUTES
99
-
100
- // private static ATTRIBUTES
101
-
102
- // Constructor, Getters, Setters
103
-
104
- // public METHODS
105
-
106
30
  public abstract subscribe(key: unknown, handler: EventHandler): void
107
31
 
108
32
  public abstract unsubscribe(key: unknown, handler: EventHandler): void
109
33
 
110
34
  public abstract dispatch(event: Event): void
111
-
112
- // protected METHODS
113
-
114
- // private METHODS
115
-
116
- // public static METHODS
117
-
118
- // protected static METHODS
119
-
120
- // private static METHODS
121
35
  } //:: class
@@ -12,7 +12,6 @@ export interface HttpResponse {}
12
12
  * @description
13
13
  */
14
14
  export interface HttpResponseBody {
15
- [property: string]: unknown
16
15
  readonly data: Record<string, unknown> | null
17
16
  readonly errors: string[] | null
18
17
  readonly links: Record<string, URL> | null
@@ -9,7 +9,8 @@ export const ERROR = 40
9
9
  export const CRITICAL = 50
10
10
 
11
11
  /**
12
- * @description
12
+ * @description Declares the logging contract used by the application layer.
13
+ * Adapters implement this abstraction to send logs to external systems.
13
14
  */
14
15
  export abstract class Logger {
15
16
  [property: string]: unknown
@@ -1,43 +1,7 @@
1
- // Libraries
2
-
3
- // Same Layer
4
-
5
- // Lower Layers
6
-
7
- // Types
8
-
9
- // Constants
10
-
11
1
  /**
12
- * @description
13
- * function arguments are Entity
2
+ * @description Represents an application use case.
3
+ * A service coordinates domain capabilities and collaborators to complete a process that fulfills a system purpose.
14
4
  */
15
5
  export abstract class Service {
16
6
  [property: string]: unknown
17
-
18
- // public ATTRIBUTES
19
-
20
- // protected ATTRIBUTES
21
-
22
- // private ATTRIBUTES
23
-
24
- // public static ATTRIBUTES
25
-
26
- // protected static ATTRIBUTES
27
-
28
- // private static ATTRIBUTES
29
-
30
- // Constructor, Getters, Setters
31
-
32
- // public METHODS
33
-
34
- // protected METHODS
35
-
36
- // private METHODS
37
-
38
- // public static METHODS
39
-
40
- // protected static METHODS
41
-
42
- // private static METHODS
43
7
  } //:: class
@@ -2,9 +2,5 @@
2
2
  * @description
3
3
  */
4
4
  export interface Validatable {
5
- [property: string]: unknown
6
-
7
5
  isValid(): boolean
8
-
9
- validate(): unknown
10
6
  }
@@ -1,44 +1,7 @@
1
- // Libraries
2
-
3
- // Same Layer
4
-
5
- // Lower Layers
6
-
7
- // Types
8
-
9
- // Constants
10
-
11
1
  /**
12
- * @description An Aggregate is a class that contains business logic that doesn't belong to any entity.
13
- * It is used to perform operations that don't fit into an entity or involve multiple entities.
14
- * Normally, method arguments are entities.
2
+ * @description Represents a logical unit that groups multiple entities.
3
+ * Its operations depend on the identities and collaboration of the entities that compose that unit.
15
4
  */
16
5
  export abstract class Aggregate {
17
6
  [property: string]: unknown
18
-
19
- // public ATTRIBUTES
20
-
21
- // protected ATTRIBUTES
22
-
23
- // private ATTRIBUTES
24
-
25
- // public static ATTRIBUTES
26
-
27
- // protected static ATTRIBUTES
28
-
29
- // private static ATTRIBUTES
30
-
31
- // Constructor, Getters, Setters
32
-
33
- // public METHODS
34
-
35
- // protected METHODS
36
-
37
- // private METHODS
38
-
39
- // public static METHODS
40
-
41
- // protected static METHODS
42
-
43
- // private static METHODS
44
7
  } //:: class
@@ -1,46 +1,17 @@
1
- // Libraries
2
-
3
- // Same Layer
4
-
5
- // Lower Layers
6
-
7
- // Types
8
-
9
- // Constants
10
-
11
1
  /**
12
- * @description An Entity is a class that represents a domain concept or element.
2
+ * @description Represents a domain concept with its own identity.
3
+ * Two instances describe the same element when they share that identity.
13
4
  */
14
5
  export abstract class Entity {
15
6
  [property: string]: unknown
16
7
 
17
- // public ATTRIBUTES
18
-
19
- // protected ATTRIBUTES
20
-
21
- // private ATTRIBUTES
22
-
23
- // public static ATTRIBUTES
24
-
25
- // protected static ATTRIBUTES
26
-
27
- // private static ATTRIBUTES
28
-
29
- // Constructor, Getters, Setters
30
-
31
- // public METHODS
32
-
33
8
  public abstract equals(other: Entity): boolean
34
9
 
35
- public abstract toJSON(): Record<string, unknown>
36
-
37
- // protected METHODS
38
-
39
- // private METHODS
40
-
41
- // public static METHODS
42
-
43
- // protected static METHODS
10
+ public toJSON(): Record<string, unknown> {
11
+ return this
12
+ }
44
13
 
45
- // private static METHODS
14
+ public toString(): string {
15
+ return String(this.constructor.name)
16
+ }
46
17
  } //:: class
@@ -1,46 +1,10 @@
1
- // Libraries
2
-
3
- // Same Layer
4
-
5
- // Lower Layers
6
-
7
- // Types
8
-
9
- // Constants
10
-
11
1
  /**
12
- * @description
2
+ * @description Represents a received value that does not satisfy the rule expected by a domain concept.
13
3
  */
14
4
  export class ValueError extends Error {
15
5
  [property: string]: unknown
16
6
 
17
- // public ATTRIBUTES
18
-
19
- // protected ATTRIBUTES
20
-
21
- // private ATTRIBUTES
22
-
23
- // public static ATTRIBUTES
24
-
25
- // protected static ATTRIBUTES
26
-
27
- // private static ATTRIBUTES
28
-
29
- // Constructor, Getters, Setters
30
-
31
7
  public constructor(received: string, expected: string) {
32
8
  super(`Invalid value ${received} for ${expected}.`)
33
9
  }
34
-
35
- // public METHODS
36
-
37
- // protected METHODS
38
-
39
- // private METHODS
40
-
41
- // public static METHODS
42
-
43
- // protected static METHODS
44
-
45
- // private static METHODS
46
10
  } //:: class
@@ -1,15 +1,5 @@
1
- // Libraries
2
-
3
- // Same Layer
4
-
5
1
  import { ValueError } from './errors.js'
6
2
 
7
- // Lower Layers
8
-
9
- // Types
10
-
11
- // Constants
12
-
13
3
  /**
14
4
  * @see https://emailregex.com/
15
5
  */
@@ -17,40 +7,23 @@ const VALID_EMAIL_REGEX =
17
7
  /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
18
8
 
19
9
  /**
20
- * @description
10
+ * @description Represents a domain concept whose identity is determined by its value.
11
+ * It centralizes the rules, semantics, and behavior that belong to that value.
21
12
  */
22
13
  export abstract class ValueObject<T = unknown> {
23
14
  [property: string]: unknown
24
15
 
25
- // public ATTRIBUTES
26
-
27
16
  public abstract readonly value: T
28
17
 
29
- // protected ATTRIBUTES
30
-
31
- // private ATTRIBUTES
32
-
33
- // public static ATTRIBUTES
34
-
35
- // protected static ATTRIBUTES
36
-
37
- // private static ATTRIBUTES
38
-
39
- // Constructor, Getters, Setters
40
-
41
- // public METHODS
42
-
43
18
  public toString(): string {
44
19
  return String(this.value)
45
20
  }
46
21
 
47
- public abstract equals(other: ValueObject<T> | null | undefined): boolean
48
-
49
- // protected METHODS
50
-
51
- // private METHODS
22
+ public toJSON(): T {
23
+ return this.value
24
+ }
52
25
 
53
- // public static METHODS
26
+ public abstract equals(other: ValueObject<T> | null | undefined): boolean
54
27
 
55
28
  public static isValid(value: unknown): boolean {
56
29
  return (
@@ -59,41 +32,22 @@ export abstract class ValueObject<T = unknown> {
59
32
  Object.is(value, NaN) === false
60
33
  )
61
34
  }
62
-
63
- // protected static METHODS
64
-
65
- // private static METHODS
66
35
  } //:: class
67
36
 
68
37
  /**
69
- * @description
38
+ * @description Models a Boolean state that can be true, false, or null.
39
+ * It adds explicit behavior for the indeterminate state.
70
40
  */
71
41
  export class NullableBoolean extends ValueObject<boolean | null> {
72
42
  [property: string]: unknown
73
43
 
74
- // public ATTRIBUTES
75
-
76
44
  public override readonly value: boolean | null
77
45
 
78
- // protected ATTRIBUTES
79
-
80
- // private ATTRIBUTES
81
-
82
- // public static ATTRIBUTES
83
-
84
- // protected static ATTRIBUTES
85
-
86
- // private static ATTRIBUTES
87
-
88
- // Constructor, Getters, Setters
89
-
90
46
  protected constructor(value: boolean | null) {
91
47
  super()
92
48
  this.value = value
93
49
  }
94
50
 
95
- // public METHODS
96
-
97
51
  public override equals(other: NullableBoolean | null | undefined): boolean {
98
52
  if (other === null || other === undefined) return false
99
53
  return this.value === other.value
@@ -103,43 +57,19 @@ export class NullableBoolean extends ValueObject<boolean | null> {
103
57
  return this.value === null
104
58
  }
105
59
 
106
- // protected METHODS
107
-
108
- // private METHODS
109
-
110
- // public static METHODS
111
-
112
60
  public static from(value: boolean | null): NullableBoolean {
113
61
  return new this(value)
114
62
  }
115
-
116
- // protected static METHODS
117
-
118
- // private static METHODS
119
63
  } //:: class
120
64
 
121
65
  /**
122
- * @description
66
+ * @description Represents an email address as a value object with validation and email-specific operations.
123
67
  */
124
68
  export class Email extends ValueObject<string> {
125
69
  [property: string]: unknown
126
70
 
127
- // public ATTRIBUTES
128
-
129
71
  public override readonly value: string
130
72
 
131
- // protected ATTRIBUTES
132
-
133
- // private ATTRIBUTES
134
-
135
- // public static ATTRIBUTES
136
-
137
- // protected static ATTRIBUTES
138
-
139
- // private static ATTRIBUTES
140
-
141
- // Constructor, Getters, Setters
142
-
143
73
  protected constructor(value: string) {
144
74
  super()
145
75
  this.value = value
@@ -157,8 +87,6 @@ export class Email extends ValueObject<string> {
157
87
  return this.domain?.split('.').pop()
158
88
  }
159
89
 
160
- // public METHODS
161
-
162
90
  public override equals(other: Email | null | undefined): boolean {
163
91
  if (other === null || other === undefined) {
164
92
  return false
@@ -167,12 +95,6 @@ export class Email extends ValueObject<string> {
167
95
  return this.value === other.value
168
96
  }
169
97
 
170
- // protected METHODS
171
-
172
- // private METHODS
173
-
174
- // public static METHODS
175
-
176
98
  public static override isValid(value: unknown): boolean {
177
99
  if (super.isValid(value) === false) return false
178
100
 
@@ -187,8 +109,4 @@ export class Email extends ValueObject<string> {
187
109
 
188
110
  return new this(value)
189
111
  }
190
-
191
- // protected static METHODS
192
-
193
- // private static METHODS
194
112
  } //:: class