archstone 1.0.3 → 1.0.4

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 (2) hide show
  1. package/README.md +96 -48
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,20 +1,51 @@
1
1
  <div align="center">
2
2
 
3
- # archstone
3
+ # Archstone
4
4
 
5
- **TypeScript architecture foundation for backend services.**
6
- Stop re-implementing DDD boilerplate. Focus on your domain.
5
+ ### The TypeScript foundation for serious backend services.
7
6
 
8
- [![npm](https://img.shields.io/npm/v/archstone?style=flat-square&color=black)](https://www.npmjs.com/package/archstone)
9
- [![license](https://img.shields.io/badge/license-MIT-black?style=flat-square)](./LICENSE)
10
- [![typescript](https://img.shields.io/badge/TypeScript-5-black?style=flat-square&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
11
- [![bun](https://img.shields.io/badge/Bun-runtime-black?style=flat-square&logo=bun)](https://bun.sh)
7
+ Build on Domain-Driven Design and Clean Architecture — without writing the same boilerplate on every project.
8
+
9
+ <br />
10
+
11
+ [![npm version](https://img.shields.io/npm/v/archstone?style=for-the-badge&logo=npm&color=CB3837&logoColor=white)](https://www.npmjs.com/package/archstone)
12
+ [![license](https://img.shields.io/badge/license-MIT-22C55E?style=for-the-badge)](./LICENSE)
13
+ [![typescript](https://img.shields.io/badge/TypeScript-5-3178C6?style=for-the-badge&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
14
+ [![bun](https://img.shields.io/badge/Bun-ready-F9F1E1?style=for-the-badge&logo=bun&logoColor=black)](https://bun.sh)
15
+
16
+ <br />
12
17
 
13
18
  </div>
14
19
 
15
20
  ---
16
21
 
17
- Archstone gives you the structural pieces of **Domain-Driven Design** and **Clean Architecture** — entities, value objects, aggregates, domain events, use cases, and repository contracts — so every project starts from a solid, consistent foundation.
22
+ ## Why archstone?
23
+
24
+ Every backend project in DDD needs the same structural pieces — and most teams rewrite them from scratch each time. Archstone gives you a **battle-tested, zero-dependency set of base classes and contracts** so you can skip the boilerplate and go straight to modeling your domain.
25
+
26
+ ```ts
27
+ // ❌ Before — scattered, inconsistent, no error contract
28
+ class User { id: string }
29
+ function createUser() { throw new Error('not found') }
30
+
31
+ // ✅ After — structured, predictable, type-safe
32
+ class User extends AggregateRoot<UserProps> { ... }
33
+ async function createUser(): Promise<Either<NotFoundError, User>> { ... }
34
+ ```
35
+
36
+ ---
37
+
38
+ ## Features
39
+
40
+ - **`Either`** — functional error handling; use cases never throw
41
+ - **`Entity` / `AggregateRoot`** — identity-based domain objects with built-in event support
42
+ - **`ValueObject`** — equality by value, not reference
43
+ - **`UniqueEntityId`** — UUID v7 identity, consistent across your entire domain
44
+ - **`WatchedList`** — track additions and removals in collections without overwriting persistence
45
+ - **`UseCase`** — typed contract for application logic
46
+ - **Repository contracts** — define your interface in the domain; implement in infrastructure
47
+
48
+ ---
18
49
 
19
50
  ## Install
20
51
 
@@ -24,43 +55,39 @@ bun add archstone
24
55
  npm install archstone
25
56
  ```
26
57
 
27
- ## At a Glance
58
+ > Zero runtime dependencies. Pure TypeScript.
28
59
 
29
- | Building block | What it does |
30
- |---|---|
31
- | `Entity` / `AggregateRoot` | Identity-based domain objects; aggregates raise domain events |
32
- | `ValueObject` | Equality by value, not reference |
33
- | `UniqueEntityId` | UUID v7 identity wrapper |
34
- | `WatchedList` | Tracks additions and removals in a collection |
35
- | `Either` | Functional error handling — no throwing in use cases |
36
- | `UseCase` | Contract for application use cases returning `Either` |
37
- | `Repository` | CRUD interface contracts — implementations live in infra |
60
+ ---
38
61
 
39
62
  ## Usage
40
63
 
41
- ### Either — handle errors without throwing
64
+ ### `Either`stop throwing, start returning
42
65
 
43
66
  ```ts
44
67
  import { Either, left, right } from 'archstone/core'
45
68
 
46
- type Result = Either<UserNotFoundError, User>
69
+ type FindUserResult = Either<UserNotFoundError, User>
47
70
 
48
- async function findUser(id: string): Promise<Result> {
71
+ async function findUser(id: string): Promise<FindUserResult> {
49
72
  const user = await repo.findById(id)
73
+
50
74
  if (!user) return left(new UserNotFoundError(id))
51
75
  return right(user)
52
76
  }
53
77
 
78
+ // The caller always handles both cases — no surprises
54
79
  const result = await findUser('123')
55
80
 
56
81
  if (result.isLeft()) {
57
82
  console.error(result.value) // UserNotFoundError
58
83
  } else {
59
- console.log(result.value) // User
84
+ console.log(result.value) // User
60
85
  }
61
86
  ```
62
87
 
63
- ### Entity & AggregateRoot — model your domain
88
+ ---
89
+
90
+ ### `Entity` & `AggregateRoot` — model your domain
64
91
 
65
92
  ```ts
66
93
  import { AggregateRoot } from 'archstone/domain/enterprise'
@@ -81,13 +108,17 @@ class Order extends AggregateRoot<OrderProps> {
81
108
  ...props,
82
109
  createdAt: props.createdAt ?? new Date(),
83
110
  })
111
+
112
+ // Raise domain events from inside the aggregate
84
113
  order.addDomainEvent(new OrderCreatedEvent(order))
85
114
  return order
86
115
  }
87
116
  }
88
117
  ```
89
118
 
90
- ### ValueObject — equality by value
119
+ ---
120
+
121
+ ### `ValueObject` — equality that makes sense
91
122
 
92
123
  ```ts
93
124
  import { ValueObject } from 'archstone/core'
@@ -105,10 +136,13 @@ class Email extends ValueObject<EmailProps> {
105
136
 
106
137
  const a = Email.create('user@example.com')
107
138
  const b = Email.create('user@example.com')
108
- a.equals(b) // true
139
+
140
+ a.equals(b) // ✅ true — compared by value, not reference
109
141
  ```
110
142
 
111
- ### WatchedList — track collection changes
143
+ ---
144
+
145
+ ### `WatchedList` — persist only what changed
112
146
 
113
147
  ```ts
114
148
  import { WatchedList } from 'archstone/core'
@@ -121,62 +155,74 @@ const tags = new TagList([existingTag])
121
155
  tags.add(newTag)
122
156
  tags.remove(existingTag)
123
157
 
124
- tags.getNewItems() // [newTag]
125
- tags.getRemovedItems() // [existingTag]
158
+ // Send only the diff to your repository — not the whole list
159
+ tags.getNewItems() // [newTag]
160
+ tags.getRemovedItems() // → [existingTag]
126
161
  ```
127
162
 
163
+ ---
164
+
128
165
  ### Domain Events — decouple side effects
129
166
 
130
167
  ```ts
131
168
  import { DomainEvents } from 'archstone/domain/enterprise'
132
169
 
133
- // Register a handler
170
+ // Register handlers anywhere in your infrastructure layer
134
171
  DomainEvents.register(
135
172
  (event) => sendWelcomeEmail(event as UserCreatedEvent),
136
173
  UserCreatedEvent.name,
137
174
  )
138
175
 
139
- // Dispatch after persisting the aggregate
176
+ // Dispatch after persistence — events stay inside the aggregate until then
140
177
  await userRepository.create(user)
141
178
  DomainEvents.dispatchEventsForAggregate(user.id)
142
179
  ```
143
180
 
144
- ### Repository Contracts — keep infra out of your domain
181
+ ---
182
+
183
+ ### Repository Contracts — keep infrastructure out of your domain
145
184
 
146
185
  ```ts
147
186
  import { Repository, Creatable } from 'archstone/domain/application'
148
187
 
149
- // Compose the interface you need
188
+ // Define your contract in the application layer
150
189
  export interface UserRepository extends Repository<User> {
151
190
  findByEmail(email: string): Promise<User | null>
152
191
  }
153
192
 
154
- // Or only what you need
193
+ // Compose only what you need
155
194
  export interface AuditRepository extends Creatable<AuditLog> {}
195
+
196
+ // Implement anywhere in infrastructure — domain stays clean
156
197
  ```
157
198
 
199
+ ---
200
+
158
201
  ## Package Exports
159
202
 
160
- ```
161
- archstone/core → Either, ValueObject, UniqueEntityId, WatchedList, Optional
162
- archstone/domain → all domain exports
163
- archstone/domain/enterprise Entity, AggregateRoot, DomainEvent, DomainEvents, EventHandler
164
- archstone/domain/application UseCase, UseCaseError, repository contracts
165
- ```
203
+ | Import | Contents |
204
+ |---|---|
205
+ | `archstone/core` | `Either`, `ValueObject`, `UniqueEntityId`, `WatchedList`, `Optional` |
206
+ | `archstone/domain` | All domain exports |
207
+ | `archstone/domain/enterprise` | `Entity`, `AggregateRoot`, `DomainEvent`, `DomainEvents`, `EventHandler` |
208
+ | `archstone/domain/application` | `UseCase`, `UseCaseError`, repository contracts |
209
+
210
+ ---
166
211
 
167
- ## Layer Architecture
212
+ ## Architecture
168
213
 
169
214
  ```
170
215
  src/
171
- ├── core/ # Zero domain knowledge — pure utilities
172
- │ ├── either.ts
173
- │ ├── value-object.ts
174
- │ ├── unique-entity-id.ts
175
- │ ├── watched-list.ts
176
- │ └── types/optional.ts
216
+ ├── core/ # Zero domain knowledge — pure language utilities
217
+ │ ├── either.ts # Left / Right functional result type
218
+ │ ├── value-object.ts # Value equality base class
219
+ │ ├── unique-entity-id.ts # UUID v7 identity wrapper
220
+ │ ├── watched-list.ts # Change-tracked collection
221
+ │ └── types/
222
+ │ └── optional.ts # Optional<T, K> helper type
177
223
 
178
224
  └── domain/
179
- ├── enterprise/ # Pure domain model — no framework deps
225
+ ├── enterprise/ # Pure domain model — zero framework dependencies
180
226
  │ ├── entities/
181
227
  │ │ ├── entity.ts
182
228
  │ │ └── aggregate-root.ts
@@ -185,7 +231,7 @@ src/
185
231
  │ ├── domain-events.ts
186
232
  │ └── event-handler.ts
187
233
 
188
- └── application/ # Use cases & repository contracts
234
+ └── application/ # Orchestration — use cases & repository contracts
189
235
  ├── use-cases/
190
236
  │ ├── use-case.ts
191
237
  │ └── use-case.error.ts
@@ -201,6 +247,8 @@ src/
201
247
 
202
248
  <div align="center">
203
249
 
250
+ **Built with care for the TypeScript community.**
251
+
204
252
  [Contributing](./CONTRIBUTING.md) · [Code of Conduct](./CODE_OF_CONDUCT.md) · [MIT License](./LICENSE)
205
253
 
206
254
  </div>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "archstone",
3
3
  "description": "TypeScript architecture foundation for backend services based on Domain-Driven Design and Clean Architecture",
4
- "version": "1.0.3",
4
+ "version": "1.0.4",
5
5
  "type": "module",
6
6
  "private": false,
7
7
  "files": [