tshex-cli 1.0.17 → 1.0.19

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.
@@ -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
package/readme.md DELETED
@@ -1,217 +0,0 @@
1
- # Hexagonal Architecture CLI
2
-
3
- This CLI will help you to generate a hexagonal architecture structure.
4
-
5
- # Why?
6
-
7
- Hexagonal architecture is a software design pattern that separates the internal domain of the application from the external dependencies. This separation is achieved by dividing the application into layers. Each layer has a specific responsibility and interacts with the other layers in a specific way.
8
-
9
- The goal is to separate the domain code from installed dependencies. A Hexagonal Architecture _framework_ would work against that goal, since it couples the domain code to the framework itself. That is why this CLI exists: it scaffolds the structure for you, using your own codebase instead of a framework.
10
-
11
- # Note
12
-
13
- This tool and its templates are in constant development, so be aware that some changes may occur and be careful when updating the tool.
14
-
15
- If you have any suggestions or improvements, please let me know.
16
-
17
- https://github.com/virtualitems/tshex-cli/issues
18
-
19
- # Getting started
20
-
21
- `tshex` scaffolds folders and files for a hexagonal architecture project. It does not write business logic for you; it only generates the structure, so you can fill it in with your own code.
22
-
23
- There are four things you can generate:
24
-
25
- - A **library** (`--lib`): the shared foundation of a project. It contains the domain and application contracts (entities, value objects, services, etc.) that the rest of the code depends on.
26
- - A **context** (`--ctx`): a specific business area (e.g. `users`, `billing`, `orders`). It contains the `domain/`, `application/`, and `adapters/` folders where you implement that area's logic.
27
- - A **React context** (`--react-context`): a React-ready context scaffold.
28
-
29
- A typical project has one library and one or more contexts inside it.
30
-
31
- ## Install
32
-
33
- Install the CLI globally:
34
-
35
- ```bash
36
- npm install -g tshex-cli
37
- ```
38
-
39
- Check the installation:
40
-
41
- ```bash
42
- tshex --version
43
- ```
44
-
45
- Show the command options:
46
-
47
- ```bash
48
- tshex --help
49
- ```
50
-
51
- ## Usage
52
-
53
- ```bash
54
- tshex [--lib <name>] [--ctx <name>] [--react-context <name>] [--dir <path>]
55
- ```
56
-
57
- | Option | Purpose |
58
- | -------------- | ------------------------------------------------------------------- |
59
- | `--lib <name>` | Generate a library called `<name>`, based on `templates/lib`. |
60
- | `--ctx <name>` | Generate a context called `<name>`, based on `templates/ctx`. |
61
- | `--react-context <name>` | Generate a React context called `<name>`, based on `templates/react-context`. |
62
- | `--dir <path>` | Parent directory where the library/context will be created. Defaults to the current directory. |
63
- | `--help` | Show the command options. |
64
- | `--version` | Show the installed version. |
65
-
66
- `--lib`, `--ctx`, and `--react-context` can be used together in a single command. Running `tshex` without any options just prints the help text — it does not generate anything.
67
-
68
- ## Create a library
69
-
70
- Use this when you are starting a new project and need the shared contracts that the rest of your code will build on:
71
-
72
- ```bash
73
- tshex --lib core
74
- ```
75
-
76
- This generates a `core/` folder in the current directory:
77
-
78
- ```text
79
- core/
80
- ├── index.d.ts
81
- ├── main.ts
82
- └── shared/
83
- ├── application/
84
- │ ├── databases.ts
85
- │ ├── events.ts
86
- │ ├── http.ts
87
- │ ├── loggers.ts
88
- │ └── services.ts
89
- └── domain/
90
- ├── aggregates.ts
91
- ├── entities.ts
92
- ├── errors.ts
93
- └── value-objects.ts
94
- ```
95
-
96
- What each file is for:
97
-
98
- | File | Purpose |
99
- | ------------------ | --------------------------------------------- |
100
- | `index.d.ts` | Declare library types. |
101
- | `main.ts` | Export the library API. |
102
- | `entities.ts` | Define entity contracts. |
103
- | `value-objects.ts` | Define value objects and validation. |
104
- | `aggregates.ts` | Define aggregate contracts. |
105
- | `errors.ts` | Define domain errors. |
106
- | `services.ts` | Define application service contracts. |
107
- | `databases.ts` | Define data manager and repository contracts. |
108
- | `events.ts` | Define event contracts. |
109
- | `http.ts` | Define HTTP response contracts. |
110
- | `loggers.ts` | Define logger contracts. |
111
-
112
- `main.ts` is generated with a placeholder `throw new Error('Not implemented yet')`, so the library fails loudly if you try to use it before filling it in. To start using it, open `main.ts`, remove that line, and export your own code, built on top of the shared contracts. For example:
113
-
114
- ```ts
115
- export { Entity } from './shared/domain/entities.js'
116
- export { ValueObject, Email } from './shared/domain/value-objects.js'
117
-
118
- class User extends Entity {
119
- constructor(public readonly email: Email) {
120
- super()
121
- }
122
- }
123
- ```
124
-
125
- ## Create a context
126
-
127
- Use this to scaffold a specific business area, such as `users`, inside an existing library (or on its own):
128
-
129
- ```bash
130
- tshex --ctx users
131
- ```
132
-
133
- This generates a `users/` folder in the current directory:
134
-
135
- ```text
136
- users/
137
- ├── adapters/
138
- ├── application/
139
- ├── domain/
140
- └── index.ts
141
- ```
142
-
143
- What each part is for:
144
-
145
- | Path | Purpose |
146
- | -------------- | ---------------------------------------------------------------- |
147
- | `domain/` | Entities, value objects, aggregates, and domain errors. |
148
- | `application/` | Use cases, services, DTOs, and contracts. |
149
- | `adapters/` | Database, HTTP, event, file, and service implementations. |
150
- | `index.ts` | Export or compose the context's public API. |
151
-
152
- ## Choose the destination folder
153
-
154
- By default, `tshex` creates files in your current directory. Use `--dir` to choose a different parent directory instead.
155
-
156
- Create a library inside `./src`:
157
-
158
- ```bash
159
- tshex --lib core --dir ./src
160
- ```
161
-
162
- This generates the library at:
163
-
164
- ```text
165
- ./src/core
166
- ```
167
-
168
- Create a context inside that library:
169
-
170
- ```bash
171
- tshex --ctx users --dir ./src/core
172
- ```
173
-
174
- This generates the context at:
175
-
176
- ```text
177
- ./src/core/users
178
- ```
179
-
180
- You can also use an absolute path:
181
-
182
- ```bash
183
- tshex --ctx users --dir /workspace/project/src
184
- ```
185
-
186
- ## Create a library and a context together
187
-
188
- You can generate both in a single command. `tshex` creates the library first, then creates the context inside it:
189
-
190
- ```bash
191
- tshex --dir ./src --lib core --ctx users
192
- ```
193
-
194
- Result:
195
-
196
- ```text
197
- src/
198
- └── core/
199
- ├── index.d.ts
200
- ├── main.ts
201
- ├── shared/
202
- └── users/
203
- ├── adapters/
204
- ├── application/
205
- ├── domain/
206
- └── index.ts
207
- ```
208
-
209
- ## Create a React context
210
-
211
- Use this when you want only the React context scaffold:
212
-
213
- ```bash
214
- tshex --react-context users
215
- ```
216
-
217
- This generates a `users/` folder in the current directory.
@@ -1,102 +0,0 @@
1
- type Generic<T = unknown> = Record<string, T>
2
-
3
- /**
4
- * @description
5
- */
6
- export interface Filterable<S = Generic> {
7
- filter(selector: S): Promise<Array<S>>
8
- }
9
-
10
- /**
11
- * @description
12
- */
13
- export interface Sortable<S = Generic> {
14
- sort(selector: S): Promise<Array<S>>
15
- }
16
-
17
- /**
18
- * @description
19
- */
20
- export interface Creatable<D = Generic> {
21
- create(data: D): Promise<unknown>
22
- }
23
-
24
- /**
25
- * @description
26
- */
27
- export interface Updatable<S = Generic, D = Generic> {
28
- update(selector: S, data: D): Promise<unknown>
29
- }
30
-
31
- /**
32
- * @description
33
- */
34
- export interface Deletable<S = Generic> {
35
- delete(selector: S): Promise<unknown>
36
- }
37
-
38
- /**
39
- * @description
40
- */
41
- export interface Aggregatable<S = Generic> {
42
- aggregate(selector: S): Promise<S>
43
- }
44
-
45
- /**
46
- * @description
47
- */
48
- export interface Relatable {
49
- selectRelated(...args: unknown[]): unknown
50
-
51
- prefetchRelated(...args: unknown[]): unknown
52
- }
53
-
54
- /**
55
- * @description
56
- */
57
- export abstract class DataManager<T = Generic> {
58
- [property: string]: unknown
59
-
60
- public abstract all(): Promise<Array<T>>
61
-
62
- public abstract none(): Array<T>
63
- } //:: class
64
-
65
- /**
66
- * @description
67
- */
68
- export abstract class DatasetManager<T = Generic> extends DataManager<T> {
69
- [property: string]: unknown
70
-
71
- public abstract union(other: Array<T>): Promise<Array<T>>
72
-
73
- public abstract intersection(other: Array<T>): Promise<Array<T>>
74
-
75
- public abstract difference(other: Array<T>): Promise<Array<T>>
76
-
77
- public abstract symmetric_difference(other: Array<T>): Promise<Array<T>>
78
-
79
- public abstract complement(other: Array<T>): Promise<Array<T>>
80
- } //:: class
81
-
82
- /**
83
- * @description
84
- */
85
- export abstract class DriverManager<M extends DataManager = DataManager> {
86
- [property: string]: unknown
87
-
88
- public abstract connect(...args: unknown[]): Promise<M>
89
-
90
- public abstract disconnect(): Promise<unknown>
91
- } //:: class
92
-
93
- /**
94
- * @description Represents a data source.
95
- */
96
- export abstract class Repository<M extends DriverManager = DriverManager> {
97
- [property: string]: unknown
98
-
99
- public constructor(public readonly manager: M) {}
100
-
101
- protected abstract transform<T = Generic>(data: Generic): T
102
- } //:: class