@alevnyacow/nzmt 0.15.12 → 0.15.13

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 (3) hide show
  1. package/README.md +63 -30
  2. package/bin/cli.js +7 -8
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -17,7 +17,9 @@ Next Zod Modules Toolkit. Next.js tools you actually missed + a scaffolder for s
17
17
 
18
18
  # Quick start with Prisma
19
19
 
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
+ Assuming you have a Next.js project with a generated Prisma client, and configured `@tanstack/react-query`:
21
+
22
+ ## Setup phase
21
23
 
22
24
  ```bash
23
25
  # 1. Install NZMT and dependencies
@@ -31,15 +33,21 @@ npm i inversify zod reflect-metadata @alevnyacow/nzmt
31
33
  # }
32
34
  # }
33
35
 
34
- # 3. Initialize NZMT (once)
35
- npx nzmt init prismaClientPath:@/app/generated/prisma/client
36
- # it scaffolded `nzmt.config.json`, infrastructure, client utils, etc.
36
+ # 3. Initialize NZMT with the absolute Prisma client path as a parameter
37
+ npx nzmt init prismaClientPath:@/generated/prisma/client
38
+ ```
39
+
40
+ After NZMT some basic infrastructure and config file were scaffolded. Open scaffolded file `/server/infrastructure/prisma/client.ts`, then import and set up the necessary Prisma adapter. Now you’re ready to use NZMT!
41
+
42
+ ## Example 1. CRUD for `User` entity with API route handlers and react queries
43
+
44
+ Assuming you have `User` prisma schema.
37
45
 
38
- # 4. Scaffold CRUD API for `User` entity
46
+ ```bash
39
47
  npx nzmt crud-api user
40
48
  ```
41
49
 
42
- Let's break down what's been scaffolded after `npx nzmt crud-api user` command:
50
+ Let's break down what's been scaffolded after this command:
43
51
 
44
52
  ### 1. Scaffolded `UserEntity`
45
53
 
@@ -70,7 +78,7 @@ export class User {
70
78
  }
71
79
  ```
72
80
 
73
- 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..
81
+ 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 (including ones in client-side queries), so contracts update automatically. **Every scaffolded source file is fully editable**, so you're in full control - you can add fields, methods, etc..
74
82
 
75
83
  ### 2. Scaffolded `UserStore` contract with `RAM` (in-memory) and `Prisma` implementations
76
84
 
@@ -141,26 +149,7 @@ const mappers = {
141
149
 
142
150
  };
143
151
  },
144
- toListModel: (source: Prisma.UserGetPayload<{}>): Types['listModel'] => {
145
- return {
146
-
147
- };
148
- },
149
- toDetails: (source: Prisma.UserGetPayload<{ include: { } }>): Types['details'] => {
150
- return {
151
-
152
- };
153
- },
154
- toCreatePayload: (source: Types['createPayload']): Prisma.UserCreateInput => {
155
- return {
156
-
157
- };
158
- },
159
- toUpdatePayload: (source: Types['updatePayload']): Prisma.UserUpdateInput => {
160
- return {
161
-
162
- };
163
- }
152
+ ... few other mappers
164
153
  }
165
154
 
166
155
  @injectable()
@@ -197,7 +186,7 @@ type Method = UserAPI['endpoints']['GET']
197
186
 
198
187
  const endpoint = '/api/user-controller'
199
188
 
200
- export const useUserController_GET = (payload: Method['payload']) => {
189
+ export const useUserAPI_GET = (payload: Method['payload']) => {
201
190
  return useQuery<Method['response'], Method['error']>({
202
191
  queryKey: [endpoint, payload],
203
192
  queryFn: () => apiRequest(endpoint, 'GET')(payload)
@@ -208,6 +197,50 @@ export const useUserController_GET = (payload: Method['payload']) => {
208
197
  - Fully typed and ready for client-side use.
209
198
  - `apiRequest` handles endpoint, method, and payload conveniently (also scaffolded and editable).
210
199
 
211
- **All code is editable - you stay in full control! 🔨⚙️**
200
+ And once again - **all code is editable - you stay in full control! 🔨⚙️**
201
+
202
+ Now you can start building your domain logic — NZMT handles the boilerplate for you. 🪄
203
+
204
+ ## Example 2. CRUD for `Product` entity with only server actions
205
+
206
+ Assuming you have `Product` prisma schema.
207
+
208
+ ```bash
209
+ npx nzmt crud-service product
210
+ ```
211
+
212
+ Command `crud-service` is a lot like the `crud-api` command, but it stops after generating service. So, you need to:
213
+
214
+ - describe `Product` entity (`/shared/entities/product/product.entity.ts`)
215
+ - tweak the Product store schemas if needed (`/server/stores/product/product.store.ts`)
216
+ - write Prisma store mappers (`/server/stores/product/product.store.prisma.ts`) as in previous example.
217
+
218
+ `Services` can be used in Server Actions. So, when you make `crud-api`, this generated service can also be used in Server Actions. Using it is very simple, you need `fromDI` function, which was scaffolded when you initialized NMZT. Let's take a look at combined example with two services we've just created:
219
+
220
+ ```tsx
221
+ 'use server'
212
222
 
213
- Now you can start building your domain logic — NZMT handles the boilerplate for you. 🪄
223
+ import { fromDI } from "@/server/di"
224
+ import type { UserService } from "@/server/services/user"
225
+ import type { ProductService } from "@/server/services/product"
226
+
227
+ export default async function() {
228
+ // keys in fromDI function are strongly typed
229
+ const userService = fromDI<UserService>('UserService')
230
+ const productService = fromDI<ProductService>('ProductService')
231
+
232
+ const driver8 = await userService.getDetails({
233
+ filter: { id: 'driver-8' }
234
+ })
235
+ const allProducts = await productService.getList({
236
+ filter: { }
237
+ })
238
+
239
+ return <div>
240
+ Take a break, {JSON.stringify(driver8)}
241
+ {JSON.stringify(driver8)}, take a break
242
+
243
+ Also we've got some products: {JSON.stringify(allProducts)}
244
+ </div>
245
+ }
246
+ ```
package/bin/cli.js CHANGED
@@ -322,12 +322,11 @@ function initPrisma() {
322
322
  fs.mkdirSync(prismaFolder, { recursive: true })
323
323
 
324
324
  fs.writeFileSync(path.resolve(prismaFolder, 'client.ts'), [
325
- `import { PrismaPg } from '@prisma/adapter-pg'`,
325
+ '/** ! import required Prisma adapter */',
326
326
  `import { PrismaClient } from '${prismaClientPath}'`,
327
327
  ``,
328
- `const adapter = new PrismaPg({`,
329
- `\tconnectionString: process.env.DATABASE_URL`,
330
- `})`,
328
+ 'const connectionString = `${process.env.DATABASE_URL}`',
329
+ `const adapter = /** ! instanse of the adapter */`,
331
330
  ``,
332
331
  `export const prismaClient = new PrismaClient({ adapter })`
333
332
  ].join('\n'))
@@ -1105,7 +1104,7 @@ function generateQueries(lowerCase, upperCase) {
1105
1104
  ``,
1106
1105
  rootMethod === 'GET'
1107
1106
  ? [
1108
- `export const use${upperCase}Controller_${rootMethod} = (payload: Method['payload']) => {`,
1107
+ `export const use${upperCase}API_${rootMethod} = (payload: Method['payload']) => {`,
1109
1108
  `\treturn useQuery<Method['response'], Method['error']>({`,
1110
1109
  `\t\tqueryKey: [endpoint, payload],`,
1111
1110
  `\t\tqueryFn: () => apiRequest(endpoint, 'GET')(payload)`,
@@ -1113,7 +1112,7 @@ function generateQueries(lowerCase, upperCase) {
1113
1112
  `}`
1114
1113
  ].join('\n')
1115
1114
  : [
1116
- `export const use${upperCase}Controller_${rootMethod} = () => {`,
1115
+ `export const use${upperCase}API_${rootMethod} = () => {`,
1117
1116
  `\treturn useMutation<Method['response'], Method['error'], Method['payload']>({`,
1118
1117
  `\t\tmutationFn: apiRequest(endpoint, '${rootMethod}')`,
1119
1118
  `\t})`,
@@ -1141,7 +1140,7 @@ function generateQueries(lowerCase, upperCase) {
1141
1140
  ``,
1142
1141
  method === 'GET'
1143
1142
  ? [
1144
- `export const use${upperCase}Controller_${fullMethodName} = (payload: Method['payload']) => {`,
1143
+ `export const use${upperCase}API_${fullMethodName} = (payload: Method['payload']) => {`,
1145
1144
  `\treturn useQuery<Method['response'], Method['error']>({`,
1146
1145
  `\t\tqueryKey: [endpoint, payload],`,
1147
1146
  `\t\tqueryFn: () => apiRequest(endpoint, 'GET')(payload)`,
@@ -1149,7 +1148,7 @@ function generateQueries(lowerCase, upperCase) {
1149
1148
  `}`
1150
1149
  ].join('\n')
1151
1150
  : [
1152
- `export const use${upperCase}Controller_${fullMethodName} = () => {`,
1151
+ `export const use${upperCase}API_${fullMethodName} = () => {`,
1153
1152
  `\treturn useMutation<Method['response'], Method['error'], Method['payload']>({`,
1154
1153
  `\t\tmutationFn: apiRequest(endpoint, '${method}')`,
1155
1154
  `\t})`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alevnyacow/nzmt",
3
- "version": "0.15.12",
3
+ "version": "0.15.13",
4
4
  "description": "Next Zod Modules Toolkit",
5
5
  "repository": {
6
6
  "type": "git",