tshex-cli 1.0.20 → 1.0.21

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/README.md CHANGED
@@ -146,23 +146,23 @@ From this point on, the guide is split into dedicated documents under `docs/`.
146
146
 
147
147
  ### General
148
148
 
149
- - [Library structure](./docs/library-structure.md)
150
- - [Library types](./docs/library-types.md)
151
- - [Context ports](./docs/context-ports.md)
152
- - [Generated file reference](./docs/generated-file-reference.md)
149
+ - [Library structure](https://github.com/virtualitems/tshex-cli/blob/main/docs/library-structure.md)
150
+ - [Library types](https://github.com/virtualitems/tshex-cli/blob/main/docs/library-types.md)
151
+ - [Context ports](https://github.com/virtualitems/tshex-cli/blob/main/docs/context-ports.md)
152
+ - [Generated file reference](https://github.com/virtualitems/tshex-cli/blob/main/docs/generated-file-reference.md)
153
153
 
154
154
  ### Shared application
155
155
 
156
- - [shared/application/data](./docs/shared/application/data.md)
157
- - [shared/application/events.ts](./docs/shared/application/events.md)
158
- - [shared/application/http.ts](./docs/shared/application/http.md)
159
- - [shared/application/loggers.ts](./docs/shared/application/loggers.md)
160
- - [shared/application/services.ts](./docs/shared/application/services.md)
161
- - [shared/application/validations.ts](./docs/shared/application/validations.md)
156
+ - [shared/application/data](https://github.com/virtualitems/tshex-cli/blob/main/docs/shared/application/data.md)
157
+ - [shared/application/events.ts](https://github.com/virtualitems/tshex-cli/blob/main/docs/shared/application/events.md)
158
+ - [shared/application/http.ts](https://github.com/virtualitems/tshex-cli/blob/main/docs/shared/application/http.md)
159
+ - [shared/application/loggers.ts](https://github.com/virtualitems/tshex-cli/blob/main/docs/shared/application/loggers.md)
160
+ - [shared/application/services.ts](https://github.com/virtualitems/tshex-cli/blob/main/docs/shared/application/services.md)
161
+ - [shared/application/validations.ts](https://github.com/virtualitems/tshex-cli/blob/main/docs/shared/application/validations.md)
162
162
 
163
163
  ### Shared domain
164
164
 
165
- - [shared/domain/aggregates.ts](./docs/shared/domain/aggregates.md)
166
- - [shared/domain/entities.ts](./docs/shared/domain/entities.md)
167
- - [shared/domain/errors.ts](./docs/shared/domain/errors.md)
168
- - [shared/domain/value-objects.ts](./docs/shared/domain/value-objects.md)
165
+ - [shared/domain/aggregates.ts](https://github.com/virtualitems/tshex-cli/blob/main/docs/shared/domain/aggregates.md)
166
+ - [shared/domain/entities.ts](https://github.com/virtualitems/tshex-cli/blob/main/docs/shared/domain/entities.md)
167
+ - [shared/domain/errors.ts](https://github.com/virtualitems/tshex-cli/blob/main/docs/shared/domain/errors.md)
168
+ - [shared/domain/value-objects.ts](https://github.com/virtualitems/tshex-cli/blob/main/docs/shared/domain/value-objects.md)
@@ -0,0 +1,165 @@
1
+ ### Context Ports
2
+
3
+ Context ports define the communication available at a context boundary.
4
+ They describe what data enters the context, what data leaves it, and which
5
+ operation another system can invoke.
6
+
7
+ Ports are used to keep communication contracts explicit. An adapter imports a
8
+ port, implements that contract, and translates the external interaction into an
9
+ application process.
10
+
11
+ > **Hint**
12
+ > The generated `example-ports.ts` file is only a placeholder. Replace it when
13
+ > the first real interaction of the context becomes clear.
14
+
15
+ #### Root Port File
16
+
17
+ The generated context starts with a single root file for ports.
18
+
19
+ ```ts title="users/example-ports.ts"
20
+ export function example(): void {
21
+ // ...
22
+ }
23
+ ```
24
+
25
+ This placeholder does not define a real contract yet. Its purpose is to mark
26
+ the context root as the place where boundary-facing types and interfaces live.
27
+
28
+ #### First Contract
29
+
30
+ In the following example we replace the placeholder with a minimal contract for
31
+ creating a user.
32
+
33
+ ```ts title="users/example-ports.ts"
34
+ export type CreateUserRequest = {
35
+ user: {
36
+ id: string
37
+ email: string
38
+ active: boolean | null
39
+ }
40
+ }
41
+
42
+ export type CreateUserResponse = {
43
+ user: {
44
+ id: string
45
+ email: string
46
+ active: boolean | null
47
+ }
48
+ }
49
+
50
+ export interface CreateUserPort {
51
+ create(request: CreateUserRequest): Promise<CreateUserResponse>
52
+ }
53
+ ```
54
+
55
+ `CreateUserRequest` defines the incoming payload. `CreateUserResponse` defines
56
+ the outgoing payload. `CreateUserPort` exposes the operation available at the
57
+ boundary.
58
+
59
+ This contract says nothing about HTTP, queues, or databases. It only declares
60
+ the shape of the communication.
61
+
62
+ #### Adapter Implementation
63
+
64
+ Now that the port exists, an adapter can implement it and delegate the work to
65
+ an application service.
66
+
67
+ ```ts title="users/adapters/create-user.ts"
68
+ import type {
69
+ CreateUserPort,
70
+ CreateUserRequest,
71
+ CreateUserResponse,
72
+ } from '../example-ports.js'
73
+
74
+ type CreateUserService = {
75
+ execute(data: {
76
+ id: string
77
+ email: string
78
+ active: boolean | null
79
+ }): Promise<CreateUserResponse>
80
+ }
81
+
82
+ export class CreateUserAdapter implements CreateUserPort {
83
+ public constructor(
84
+ private readonly service: CreateUserService,
85
+ ) {}
86
+
87
+ public async create(
88
+ request: CreateUserRequest,
89
+ ): Promise<CreateUserResponse> {
90
+ return this.service.execute({
91
+ id: request.user.id,
92
+ email: request.user.email,
93
+ active: request.user.active,
94
+ })
95
+ }
96
+ }
97
+ ```
98
+
99
+ The adapter implements `CreateUserPort`, so it must provide `create()`. Inside
100
+ that method it translates the root-level request into the input expected by the
101
+ application service.
102
+
103
+ This is the normal flow of the generated structure:
104
+
105
+ ```text
106
+ external system -> adapter -> application -> domain
107
+ ```
108
+
109
+ The port belongs to the boundary. The adapter materializes the boundary. The
110
+ application process executes the use case.
111
+
112
+ #### Multiple Port Files
113
+
114
+ As the context grows, you can keep several contracts at the context root.
115
+
116
+ ```ts title="users/list-users.ts"
117
+ export type ListUsersRequest = {
118
+ active: boolean | null
119
+ }
120
+
121
+ export type ListUsersResponse = {
122
+ users: Array<{
123
+ id: string
124
+ email: string
125
+ active: boolean | null
126
+ }>
127
+ }
128
+
129
+ export interface ListUsersPort {
130
+ list(request: ListUsersRequest): Promise<ListUsersResponse>
131
+ }
132
+ ```
133
+
134
+ An adapter can then import the contract from the file that owns it.
135
+
136
+ This arrangement is useful when one context exposes several independent forms
137
+ of communication. A single file works well for a small context. Separate files
138
+ become easier to maintain when responsibilities start to diverge.
139
+
140
+ > **Warning**
141
+ > A port should define communication, not domain behavior. Avoid moving entity
142
+ > rules, repository logic, or infrastructure details into the port file.
143
+
144
+ #### Example Layout
145
+
146
+ The following structure keeps ports at the root while the implementation lives
147
+ in the generated folders.
148
+
149
+ ```text
150
+ users/
151
+ ├── example-ports.ts
152
+ ├── list-users.ts
153
+ ├── adapters/
154
+ ├── application/
155
+ └── domain/
156
+ ```
157
+
158
+ This layout keeps the context boundary visible from the top level. It also
159
+ reduces coupling between adapters because they all import the same contracts.
160
+
161
+ #### Next Step
162
+
163
+ After defining a port, implement the corresponding adapter and connect it to an
164
+ application service. The surrounding structure is described in
165
+ `library-structure.md`.
@@ -0,0 +1,88 @@
1
+ ### Generated File Reference
2
+
3
+ This reference describes the files generated by the library template.
4
+ Use it to identify where a concern belongs before adding new code.
5
+
6
+ #### Root Files
7
+
8
+ The root contains the main entry points of the generated library.
9
+
10
+ | File | Responsibility |
11
+ | --- | --- |
12
+ | `index.d.ts` | Declares root-level shared types such as `Generic<T>`. |
13
+ | `main.ts` | Starts as a placeholder for the main implementation and root exports. |
14
+
15
+ `index.d.ts` is the place for root-level type declarations. `main.ts` is the
16
+ place for the main runtime entry point when the library starts exposing shared
17
+ runtime components.
18
+
19
+ #### Shared Domain Files
20
+
21
+ The `shared/domain` directory contains foundations for domain modeling.
22
+
23
+ | File | Responsibility |
24
+ | --- | --- |
25
+ | `shared/domain/value-objects.ts` | Declares `ValueObject<T>` and provides `Email` and `NullableBoolean`. |
26
+ | `shared/domain/entities.ts` | Declares the `Entity` base class. |
27
+ | `shared/domain/aggregates.ts` | Declares the `Aggregate` base class. |
28
+ | `shared/domain/errors.ts` | Declares `ValueError`. |
29
+
30
+ These files contain reusable domain concepts whose meaning can be shared across
31
+ contexts. They are discussed in more detail in `shared/domain/*.md`.
32
+
33
+ #### Shared Application Files
34
+
35
+ The `shared/application` directory contains contracts used to coordinate use
36
+ cases and integrations.
37
+
38
+ | File | Responsibility |
39
+ | --- | --- |
40
+ | `shared/application/validations.ts` | Declares the `Validatable` contract. |
41
+ | `shared/application/services.ts` | Declares the `Service` base class for use cases. |
42
+ | `shared/application/http.ts` | Declares framework-agnostic HTTP contracts. |
43
+ | `shared/application/loggers.ts` | Declares shared log levels and the `Logger` contract. |
44
+ | `shared/application/events.ts` | Declares `Event`, `EventHandler`, and `EventDispatcher`. |
45
+
46
+ These files do not implement frameworks or transports. They define the stable
47
+ contracts that adapters and services can share.
48
+
49
+ #### Shared Data Files
50
+
51
+ The generated template also includes a small set of data-access abstractions.
52
+
53
+ | File | Responsibility |
54
+ | --- | --- |
55
+ | `shared/application/data/drivers.ts` | Declares `DriverAdapter`, the connection contract with a data source. |
56
+ | `shared/application/data/managers.ts` | Declares `DataManager`, `DatasetManager`, and plain-record operations. |
57
+ | `shared/application/data/repositories.ts` | Declares `Repository`, which transforms raw records into domain representations. |
58
+
59
+ These contracts belong to the application layer because they define how the
60
+ application coordinates data access without forcing a specific driver.
61
+
62
+ #### Context Files
63
+
64
+ Each generated context starts with a root port file and three directories.
65
+
66
+ | Path | Responsibility |
67
+ | --- | --- |
68
+ | `users/example-ports.ts` | Placeholder root file for context ports. |
69
+ | `users/domain/` | Domain capabilities and rules for the context. |
70
+ | `users/application/` | Processes that use domain capabilities to fulfill system purposes. |
71
+ | `users/adapters/` | Integrations that implement ports and connect the context to external systems. |
72
+
73
+ The `users/` path is an example context name. Your project can generate one or
74
+ more contexts with the same internal layout.
75
+
76
+ #### How To Use This Reference
77
+
78
+ Use the following sequence when deciding where new code belongs.
79
+
80
+ 1. Put reusable domain concepts in `shared/domain`.
81
+ 2. Put reusable application contracts in `shared/application`.
82
+ 3. Put context-specific rules in `<context>/domain`.
83
+ 4. Put use cases in `<context>/application`.
84
+ 5. Put boundary implementations in `<context>/adapters`.
85
+ 6. Put boundary contracts at the context root.
86
+
87
+ This reference explains placement. The architectural rationale is described in
88
+ `library-structure.md`.
@@ -0,0 +1,163 @@
1
+ ### Library Structure
2
+
3
+ The library structure organizes generated code into root files, shared
4
+ capabilities, and one or more contexts.
5
+ Each level has a distinct responsibility so that domain rules, use cases, and
6
+ integrations do not collapse into the same place.
7
+
8
+ This structure is used to keep the implementation centered on capabilities.
9
+ Shared code holds common abstractions. Contexts hold application-specific
10
+ language, rules, and operations.
11
+
12
+ #### Root
13
+
14
+ The root contains the entry points of the generated library.
15
+
16
+ ```text
17
+ index.d.ts
18
+ main.ts
19
+ shared/
20
+ users/
21
+ ```
22
+
23
+ `index.d.ts` defines root-level types. `main.ts` starts as a placeholder for
24
+ main runtime exports. The rest of the structure lives under `shared/` and one
25
+ or more context directories.
26
+
27
+ #### Shared
28
+
29
+ The `shared` directory contains concepts that can be reused by multiple
30
+ contexts.
31
+
32
+ ```text
33
+ shared/
34
+ ├── application/
35
+ └── domain/
36
+ ```
37
+
38
+ `shared/domain` contains modeling foundations such as value objects, entities,
39
+ aggregates, and errors. `shared/application` contains contracts for services,
40
+ validations, events, logging, HTTP boundaries, and data access.
41
+
42
+ Move code to `shared` only when its meaning belongs to more than one context.
43
+ Until then, keep it close to the context that owns the rule.
44
+
45
+ #### Contexts
46
+
47
+ A context groups the vocabulary, rules, and operations of one application
48
+ capability.
49
+
50
+ ```text
51
+ users/
52
+ billing/
53
+ inventory/
54
+ sales/
55
+ ```
56
+
57
+ Each context can evolve independently while still reusing the abstractions from
58
+ `shared`. This separation reduces accidental coupling between unrelated parts of
59
+ the system.
60
+
61
+ #### Context Layout
62
+
63
+ Every generated context starts with the same internal structure.
64
+
65
+ ```text
66
+ users/
67
+ ├── example-ports.ts
68
+ ├── adapters/
69
+ ├── application/
70
+ └── domain/
71
+ ```
72
+
73
+ `example-ports.ts` is the root communication surface of the context.
74
+ `domain/` contains capabilities and rules. `application/` contains processes.
75
+ `adapters/` contains boundary implementations.
76
+
77
+ #### Domain
78
+
79
+ The domain layer contains the context's capabilities.
80
+
81
+ This layer models concepts that carry business meaning: value objects, entities,
82
+ aggregates, and the rules that make them valid. The domain should not depend on
83
+ transport concerns or infrastructure details.
84
+
85
+ Typical domain responsibilities include validating an email address, identifying
86
+ an entity, changing the state of an order, or grouping related entities into a
87
+ single unit.
88
+
89
+ #### Application
90
+
91
+ The application layer contains processes that use domain capabilities to
92
+ fulfill a system purpose.
93
+
94
+ A service in this layer coordinates collaborators. It can validate input,
95
+ construct domain objects, read or write data through abstractions, publish an
96
+ event, and log the result.
97
+
98
+ The application layer is responsible for orchestration, not for owning the
99
+ business rules themselves.
100
+
101
+ #### Adapters
102
+
103
+ The adapters layer contains the integrations that connect a context to other
104
+ systems.
105
+
106
+ An adapter can expose an HTTP handler, consume a message, call a remote API,
107
+ implement a data driver, or connect to an event bus. Its role is to translate
108
+ external input or output into the contracts expected by the application layer.
109
+
110
+ #### Ports
111
+
112
+ Ports define the communication available at the context boundary.
113
+
114
+ They live at the context root because they describe how the context is used
115
+ from the outside. An adapter imports a port, implements it, and delegates the
116
+ work to an application process.
117
+
118
+ The generated template starts with `example-ports.ts`, but a larger context may
119
+ split ports across several files. The detailed guidance for that layout lives in
120
+ `context-ports.md`.
121
+
122
+ #### Dependency Direction
123
+
124
+ The normal dependency direction is the following:
125
+
126
+ ```text
127
+ adapter -> port
128
+ adapter -> application
129
+ application -> domain
130
+ ```
131
+
132
+ This direction keeps the core model isolated from transport and infrastructure
133
+ details. The deeper a layer is, the less it should know about the outside.
134
+
135
+ > **Warning**
136
+ > Avoid importing adapter-specific concerns into the domain layer. Once a domain
137
+ > object depends on HTTP, database, or framework details, the context boundary
138
+ > becomes harder to change.
139
+
140
+ #### Example Flow
141
+
142
+ The following diagram shows the runtime flow of a typical operation.
143
+
144
+ ```text
145
+ External system
146
+ |
147
+ v
148
+ Port + adapter
149
+ |
150
+ v
151
+ Application service
152
+ |
153
+ v
154
+ Domain capability
155
+ ```
156
+
157
+ The adapter receives the input, the application service coordinates the use
158
+ case, and the domain provides the rules and behavior required by that use case.
159
+
160
+ #### Next Step
161
+
162
+ Use this structure as the default layout for new code. When you need to inspect
163
+ the purpose of a generated file, consult `generated-file-reference.md`.
@@ -0,0 +1,70 @@
1
+ ### Library Types
2
+
3
+ The generated root type `Generic<T>` represents a plain object whose keys are
4
+ strings and whose values share the same type.
5
+ It provides a small common building block for code that works with object-like
6
+ data but does not need a more specific shape yet.
7
+
8
+ #### Root Declaration
9
+
10
+ The root declaration lives in `index.d.ts`.
11
+
12
+ ```ts title="index.d.ts"
13
+ type Generic<T = unknown> = Record<string, T>
14
+ ```
15
+
16
+ This alias expands to `Record<string, T>`. When no type argument is provided,
17
+ the values use `unknown`.
18
+
19
+ #### Basic Usage
20
+
21
+ In the following example we use `Generic<string>` for a set of plain filters.
22
+
23
+ ```ts
24
+ const filters: Generic<string> = {
25
+ status: 'active',
26
+ sort: 'email',
27
+ }
28
+ ```
29
+
30
+ `filters` can only store string values because the type argument fixes the
31
+ value shape for the whole object.
32
+
33
+ #### Default Type Argument
34
+
35
+ Now consider the same pattern without providing a type argument.
36
+
37
+ ```ts
38
+ const metadata: Generic = {
39
+ retries: 2,
40
+ cached: true,
41
+ }
42
+ ```
43
+
44
+ In this case the values use `unknown`. This is useful when the object is plain
45
+ and open-ended, but the caller must narrow each value before using it in a
46
+ specific way.
47
+
48
+ #### When To Use It
49
+
50
+ Use `Generic<T>` when the code needs a simple object contract and the exact set
51
+ of keys is not the main concern.
52
+
53
+ Typical uses include:
54
+
55
+ 1. filter objects;
56
+ 2. metadata objects;
57
+ 3. plain configuration maps;
58
+ 4. transport-neutral dictionaries.
59
+
60
+ When the object has a stable business meaning, prefer a named type instead of a
61
+ generic record.
62
+
63
+ > **Hint**
64
+ > `Generic<T>` is intentionally small. It should support loose object contracts,
65
+ > not replace explicit domain or application types.
66
+
67
+ #### Next Step
68
+
69
+ For the rest of the generated shared abstractions, continue with the pages in
70
+ `shared/application` and `shared/domain`.