@alevnyacow/nzmt 0.15.4 → 0.15.6

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 +179 -81
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -4,121 +4,219 @@
4
4
  ![NPM License](https://img.shields.io/npm/l/%40alevnyacow%2Fnzmt)
5
5
  ![npm bundle size (scoped)](https://img.shields.io/bundlephobia/minzip/%40alevnyacow/nzmt)
6
6
 
7
- # About
7
+ # What
8
8
 
9
- **Not** a framework. Seriously, we have enough of those. NZMT is just the tools you always wanted in Next.js, plus a scaffolder that spins up server logic and client queries. Full-stack, the Next.js way!
9
+ Next.js tools you actually missed + a scaffolder for server logic & client queries. Not a framework. Full-stack, batteries included.
10
10
 
11
- Think: dependency injection + Zod validation + DDD vibes... but without drowning in boilerplate. You write the fun stuff; NZMT handles the boring stuff.
11
+ # Why
12
12
 
13
- Batteries included.
13
+ - ☕ Keep using plain Next.js — just faster and cleaner. Skip the moment when some “helpful” framework fights you, making you wonder if coding it yourself would’ve been easier.
14
+ - 🧙 Focus on your domain logic without drowning in full-blown DDD.
15
+ - ✨ DI, Zod validation, project structure & API controllers out of the box.
16
+ - 🪄 Services, controllers, client queries, and other programmer stuff appear at the snap of a finger — and yes, it’s fun. (Well, not *literally* at the snap of a finger — that’s just marketing, to be honest. You still need to run one CLI command.)
14
17
 
15
- ## Why NZMT?
18
+ # Quick start with Prisma
16
19
 
17
- - Focus on your domain logic without drowning in full-blown DDD.
18
- - Keep using plain Next.js, just faster and cleaner — no extra framework required.
19
- - Watch entities, stores, services, controllers, handlers, and client-side queries appear automatically (and yes, it’s actually fun).
20
+ Example with CRUD API for User entity with react queries (assuming you have a Next.js project with a generated Prisma client, `User` prisma schema, and configured `@tanstack/react-query`).
20
21
 
21
- # Quick start (Prisma + client-side queries)
22
+ ```bash
23
+ # 1. Install NZMT and dependencies
24
+ npm i inversify zod reflect-metadata @alevnyacow/nzmt
25
+
26
+ # 2. Enable decorators in tsconfig.json
27
+ # {
28
+ # "compilerOptions": {
29
+ # "experimentalDecorators": true,
30
+ # "emitDecoratorMetadata": true
31
+ # }
32
+ # }
33
+
34
+ # 3. Initialize NZMT (once)
35
+ npx nzmt init prismaClientPath:@/app/generated/prisma/client
22
36
 
23
- Assuming you have a Next.js project with a generated Prisma client, `User` Prisma model and configured `@tanstack/react-query`:
37
+ # 4. Scaffold CRUD API for `User` entity
38
+ npx nzmt crud-api user
39
+ ```
24
40
 
25
- ## Initialization
41
+ Let's break down what's been scaffolded.
42
+
43
+ ### 1. Scaffolded `UserEntity`
44
+
45
+ ```ts
46
+ /** /shared/entities/user/user.entity.ts **/
47
+
48
+ import z from 'zod'
49
+ import { ValueObjects } from '@alevnyacow/nzmt'
50
+
51
+ export type UserModel = z.infer<typeof User.schema>
52
+
53
+ export class User {
54
+ static schema = z.object({
55
+ id: ValueObjects.Identifier.schema,
56
+
57
+ })
58
+
59
+ private constructor(private readonly data: UserModel) {}
60
+
61
+ static create = (data: UserModel) => {
62
+ const parsedModel = User.schema.parse(data)
63
+ return new User(parsedModel)
64
+ }
65
+
66
+ get model(): UserModel {
67
+ return this.data
68
+ }
69
+ }
70
+ ```
26
71
 
27
- 1. Install required dependencies and NZMT itself:
72
+ All that’s left is to define the entity’s structure and validation in the static field `schema` (Zod). All related types are already derived, so contracts update automatically. Every scaffolded source file is fully editable, so you're in full control - you can add fields, methods, etc..
28
73
 
29
- ```bash
30
- npm install inversify zod reflect-metadata @alevnyacow/nzmt
31
- ```
74
+ ### 2. Scaffolded `UserStore` contract with `RAM` (in-memory) and `Prisma` implementations
32
75
 
33
- 2. Enable `Experimental decorators` and `Emit Decorator Metadata` options in your `tsconfig.json`.
76
+ We'll cover two of generated files that need your attention. First is a general user store description.
34
77
 
35
- ```json
36
- {
37
- "compilerOptions": {
38
- "experimentalDecorators": true,
39
- "emitDecoratorMetadata": true
40
- }
41
- }
42
- ```
78
+ ```ts
79
+ /** /server/stores/users/user.store.ts **/
43
80
 
44
- 3. Initialize NZMT (must be done once). This will set up all required infrastructure and configuration for you:
81
+ import { Store } from '@alevnyacow/nzmt'
82
+ import { User } from '@/shared/entities/user'
45
83
 
46
- ```bash
47
- npx nzmt init prismaClientPath:@/app/generated/prisma/client
48
- ```
84
+ export const userStoreMetadata = {
85
+ models: {
86
+ list: User.schema,
87
+ details: User.schema,
88
+ },
49
89
 
50
- ## Scaffolding
90
+ searchPayload: {
91
+ list: User.schema.omit({ id: true }),
92
+ specific: User.schema.pick({ id: true }),
93
+ },
51
94
 
52
- Now you can scaffold everything you need for `User` entity CRUD API in one CLI command:
95
+ actionsPayload: {
96
+ create: User.schema.omit({ id: true }),
97
+ update: User.schema.omit({ id: true }).partial(),
98
+ },
53
99
 
54
- ```bash
55
- npx nzmt crud-api user
100
+ name: 'UserStore'
101
+ } satisfies Store.Metadata
102
+
103
+ export const { schemas: userStoreSchemas } = Store.toModuleMetadata(userStoreMetadata)
104
+
105
+ export type UserStore = Store.Contract<typeof userStoreMetadata>
56
106
  ```
57
107
 
58
- This will generate:
108
+ Contracts are pretty self-explainatory, but let's break this down anyway.
109
+
110
+ Models:
111
+
112
+ - `models.list` - list model, `list` method will return list of those entities
113
+ - `models.details` - details model, `details` will return this entity
114
+
115
+ Search payload:
116
+
117
+ - `searchPayload.list` - how to filter data in `list` method
118
+ - `searchPayload.specific` - how to find one specific entity in `details` method
119
+
120
+ Actions payload:
121
+
122
+ - `actionsPayload.create` - what is needed to create a new entity
123
+ - `actionsPayload.update` - what is needed to update an entity. Note: only update payload must be here, filters will be used from `searchPayload`
124
+
125
+ All of these schemas can be modified. They don’t even have to be derived from the entity’s schema, but doing so is strongly recommended for consistency.
126
+
127
+ Second file is a `Prisma` implementation:
128
+
129
+ ```ts
130
+ /** /server/stores/users/user.store.prisma */
131
+
132
+ import type { Prisma, PrismaClient } from '@/app/generated/prisma/client'
133
+ import { DITokens } from '@/server/di'
134
+ import { injectable, inject } from 'inversify'
135
+ import { Store } from '@alevnyacow/nzmt'
136
+ import { type UserStore, userStoreMetadata } from './user.store'
137
+
138
+ type Types = Store.Types<UserStore>
139
+
140
+ const mappers = {
141
+ toFindOnePayload: (source: Types['findOnePayload']): Prisma.UserWhereUniqueInput => {
142
+ return {
143
+
144
+ };
145
+ },
146
+ toFindListPayload: (source: Types['findListPayload']): Prisma.UserWhereInput => {
147
+ return {
148
+
149
+ };
150
+ },
151
+ toListModel: (source: Prisma.UserGetPayload<{}>): Types['listModel'] => {
152
+ return {
153
+
154
+ };
155
+ },
156
+ toDetails: (source: Prisma.UserGetPayload<{ include: { } }>): Types['details'] => {
157
+ return {
158
+
159
+ };
160
+ },
161
+ toCreatePayload: (source: Types['createPayload']): Prisma.UserCreateInput => {
162
+ return {
163
+
164
+ };
165
+ },
166
+ toUpdatePayload: (source: Types['updatePayload']): Prisma.UserUpdateInput => {
167
+ return {
168
+
169
+ };
170
+ }
171
+ }
172
+
173
+ @injectable()
174
+ export class UserPrismaStore implements UserStore {
175
+ ..scaffolded implementation goes here
176
+ ```
59
177
 
60
- - `User` entity
61
- - `UserStore` contract with `RAM` and `Prisma` implementations
62
- - `UserService` with all business methods
63
- - `UserController` with ready-to-use API endpoints
64
- - Fully typed `UserAPI` contract (endpoints + DTOs) for client usage
65
- - API `route handlers` inside your `app` folder
66
- - `React queries`. Fully typed and ready to be used in your client-side code!
178
+ Pretty cool, right? All you need to do is implementing `mappers` and in the vast majority of cases it's enough to have working `Prisma` store. And even more - `RAM` implementation works out of the box! ✨
67
179
 
68
- **All code is editable - you stay in full control!**
180
+ ### 3. Scaffolded `UserService` with all business methods
69
181
 
70
- So, only two things left to do:
182
+ Works out of the box.
71
183
 
72
- - Describe entity properties and validation rules using Zod for the `User` entity in the scaffolded file `/shared/entities/user/user.entity.ts`.
184
+ ### 4. Scaffolded `UserController` with ready-to-use API endpoints
73
185
 
74
- - Implement Prisma mappers in `/server/stores/user/user.store.prisma.ts`.
75
- All methods and contracts are already scaffolded; you only need to describe the mappers themselves. RAM store implementation works out of the box.
186
+ Works out of the box.
76
187
 
77
- # Design principles
188
+ ### 5. Scaffolded infrastructure helpers as `PrismaClient`, `Logger` and client util for handy requests.
78
189
 
79
- ## Core idea
190
+ ### 6. Scaffolded `Route handlers` in `/app/api`
80
191
 
81
- DDD is powerful, but it truly shines in large-scale systems with large teams. In practice, developers often face a trade-off:
82
- either adopt heavy architectural concepts or build with little to no structure at all. **Mature engineering is about trade-offs. A good tool should help you make them intentionally.**
192
+ Works out of the box.
83
193
 
84
- That’s what this toolkit is designed for. It brings the benefits of DDD without unnecessary complexity that can slow down early development — and adds scaffolding to move even faster. **Automate what’s routine. Stay flexible for what’s complex.**
194
+ ### 7. Scaffolded `React queries` for all controller methods
85
195
 
86
- ## Server-side layer
196
+ Also works out of the box! ✨
87
197
 
88
- Server-side logic is structured into four core modules: *Stores*, *Services*, *Controllers*, and *Providers*.
198
+ Let's take a look at `client/shared/queries/user-controller/GET.ts` for example:
89
199
 
90
- - **Stores** encapsulate Data Layer logic with no business rules.
91
- - **Services** define business logic and use-case flows.
92
- - **Controllers** handle API requests and delegate work to services.
93
- - **Providers** manage integrations with external systems (e.g. email, third-party APIs).
200
+ ```ts
201
+ import { useQuery } from '@tanstack/react-query'
202
+ import type { UserAPI } from '@/server/controllers/user'
203
+ import { apiRequest } from '@/client/shared/utils'
94
204
 
95
- ## Shared layer
205
+ type Method = UserAPI['endpoints']['GET']
96
206
 
97
- There are also two building blocks shared across server and client: Entities and Value Objects.
207
+ const endpoint = '/api/user-controller'
98
208
 
99
- - **Entities** represent domain objects used throughout the application. They don’t include data access or business flow logic, but may contain pure domain logic, contracts and invariants (e.g. User, Product).
100
- - **Value Objects** define reusable, strongly-typed invariants for meaningful concepts such as Pagination or Identifier.
209
+ export const useUserController_GET = (payload: Method['payload']) => {
210
+ return useQuery<Method['response'], Method['error']>({
211
+ queryKey: [endpoint, payload],
212
+ queryFn: () => apiRequest(endpoint, 'GET')(payload)
213
+ })
214
+ }
215
+ ```
101
216
 
217
+ - Fully typed and ready for client-side use.
218
+ - `apiRequest` handles endpoint, method, and payload conveniently (also scaffolded and editable).
102
219
 
103
- # Package API
220
+ **All code is editable - you stay in full control! 🔨⚙️**
104
221
 
105
- - Module
106
- - `methods` function
107
- - `Metadata` type
108
- - `DTOs` type
109
- - `Methods` type
110
- - `Config` type
111
- - Controller
112
- - `endpoints` function
113
- - `DefaultErrorCodes` enum
114
- - `Guard` type
115
- - `OnErrorHandler` type
116
- - `SharedConfig` type
117
- - `Metadata` type
118
- - `Contract` type
119
- - Store
120
- - `methods` function
121
- - `InRAM` class generator
122
- - `Types` type
123
- - `Metadata` type
124
- - `Contract` type
222
+ Now you can start building your domain logic — NZMT handles the boilerplate for you. 🪄
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alevnyacow/nzmt",
3
- "version": "0.15.4",
3
+ "version": "0.15.6",
4
4
  "description": "Next Zod Modules Toolkit",
5
5
  "repository": {
6
6
  "type": "git",