@alevnyacow/nzmt 0.12.2 → 0.13.0
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 +46 -29
- package/bin/cli.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,59 +9,76 @@
|
|
|
9
9
|
NZMT is a toolkit for building structured Next.js full-stack applications.
|
|
10
10
|
|
|
11
11
|
It combines dependency injection, Zod validation and a DDD-inspired architecture,
|
|
12
|
-
while removing most of the boilerplate through code generation.
|
|
12
|
+
while removing most of the boilerplate through code generation out of the box.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
Batteries included!
|
|
15
|
+
|
|
16
|
+
## Why NZMT?
|
|
17
|
+
|
|
18
|
+
- You want to focus on domain logic without full DDD complexity
|
|
19
|
+
- You’re tired of rewriting CRUD, data layer logic, DTOs, and validation
|
|
20
|
+
- You want to follow best practices without overengineering or repetitive boilerplate
|
|
21
|
+
- You want your application to be runtime-safe
|
|
22
|
+
- You want to move fast without losing predictability
|
|
23
|
+
- You want a backend that can evolve into a full-stack solution
|
|
24
|
+
|
|
25
|
+
You focus on business logic; NZMT handles the infrastructure.
|
|
17
26
|
|
|
18
27
|
# Quick start with Prisma
|
|
19
28
|
|
|
20
|
-
|
|
29
|
+
Assuming you have a Next.js project with a generated Prisma client and a `User` Prisma model:
|
|
21
30
|
|
|
22
31
|
1. Install required peer dependencies and the toolkit itself.
|
|
23
32
|
```bash
|
|
24
33
|
npm install inversify zod reflect-metadata @alevnyacow/nzmt
|
|
25
34
|
```
|
|
35
|
+
|
|
26
36
|
2. Enable `Experimental decorators` and `Emit Decorator Metadata` options in your `tsconfig.json`.
|
|
37
|
+
```json
|
|
38
|
+
// tsconfig.json
|
|
39
|
+
{
|
|
40
|
+
"compilerOptions": {
|
|
41
|
+
"experimentalDecorators": true,
|
|
42
|
+
"emitDecoratorMetadata": true
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
27
46
|
|
|
28
47
|
3. Initialize NZMT. This will set up all required infrastructure and configuration for you:
|
|
29
48
|
```bash
|
|
30
49
|
npx nzmt init prismaClientPath:@/app/generated/prisma/client
|
|
31
50
|
```
|
|
32
51
|
|
|
33
|
-
4.
|
|
52
|
+
4. Now you can scaffold everything you need for `User` entity CRUD API in one CLI command:
|
|
34
53
|
```bash
|
|
35
|
-
|
|
36
|
-
npx nzmt entity product f:title-string,price-int.positive
|
|
54
|
+
npx nzmt crud-api user
|
|
37
55
|
```
|
|
38
|
-
This will generate the entity, its Zod schema and related types.
|
|
39
56
|
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
# product store (with Prisma implementation, RAM implementation and DI)
|
|
43
|
-
npx nzmt store product
|
|
44
|
-
# product service proxying all product store methods (with DI)
|
|
45
|
-
npx nzmt service product p:ProductStore
|
|
46
|
-
# shop controller with injected product service and logger (with DI)
|
|
47
|
-
npx nzmt controller shop i:Logger,ProductService
|
|
48
|
-
```
|
|
49
|
-
Now you have scaffolded structure for `ProductStore`, `ProductService` and `ShopController` and all of them are registered in the DI container. You can now implement your logic inside these modules and expose it via controllers.
|
|
57
|
+
This will generate:
|
|
50
58
|
|
|
51
|
-
|
|
59
|
+
- `User` entity
|
|
60
|
+
- `UserStore` contract, `UserRAMStore` and `UserPrismaStore` implementation
|
|
61
|
+
- `UserService` proxying all `UserStore` methods
|
|
62
|
+
- `UserController` proxying all `UserService` methods.
|
|
52
63
|
|
|
53
|
-
|
|
54
|
-
// app/api/shop/route.ts
|
|
64
|
+
All code is editable - you stay in full control.
|
|
55
65
|
|
|
56
|
-
|
|
57
|
-
|
|
66
|
+
5. **Describe entity properties and validation rules using Zod** for the `User` entity in the scaffolded file `/shared/entities/user/user.entity.ts`.
|
|
67
|
+
|
|
68
|
+
6. **Implement Prisma mappers** in `/server/stores/user/user.store.prisma.ts`.
|
|
69
|
+
All methods and contracts are already scaffolded; you only need to describe the mappers themselves.
|
|
58
70
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
71
|
+
7. Use generated controller in `app/api/user/route.ts` file via DI.
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import type { UserController } from "@/server/controllers/user"
|
|
75
|
+
import { fromDI } from "@/server/di"
|
|
62
76
|
|
|
63
|
-
//
|
|
64
|
-
|
|
77
|
+
// Get a fully typed controller instance from the DI container.
|
|
78
|
+
// Key is fully typed too, of course.
|
|
79
|
+
const controller = fromDI<UserController>('UserController')
|
|
80
|
+
// Use controller method as a route method.
|
|
81
|
+
export const GET = controller.GET
|
|
65
82
|
```
|
|
66
83
|
|
|
67
84
|
# Design principles
|
package/bin/cli.js
CHANGED
|
@@ -886,7 +886,7 @@ function generateController(upperCase, lowerCase, crudService) {
|
|
|
886
886
|
fs.writeFileSync(path.resolve(folder, `${entityName}.controller.metadata.ts`), [
|
|
887
887
|
crudService ? `import z from 'zod'` : undefined,
|
|
888
888
|
`import { Controller, ValueObjects } from '@alevnyacow/nzmt'`,
|
|
889
|
-
crudService ? `import { ${crudServiceLowercase}Metadata } from '@${config.paths.services}/${toKebabFromPascal(crudService).slice(0, -'-service'.length)}'` : undefined
|
|
889
|
+
crudService ? `import { ${crudServiceLowercase}Metadata } from '@${config.paths.services}/${toKebabFromPascal(crudService).slice(0, -'-service'.length)}'` : undefined,
|
|
890
890
|
``,
|
|
891
891
|
`export const ${lowerCase}ControllerMetadata = {`,
|
|
892
892
|
`\tname: '${upperCase}Controller',`,
|