@prismakit/cli 2.1.1 → 2.2.2
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/dist/bin.cjs +246 -16
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +6 -3
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-36ZM4UZV.js → chunk-7E6MWEJP.js} +242 -15
- package/dist/chunk-7E6MWEJP.js.map +1 -0
- package/dist/index.cjs +241 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +1 -1
- package/package.json +4 -3
- package/src/__tests__/naming.spec.ts +42 -0
- package/src/bin.ts +114 -0
- package/src/commands/codegen.ts +69 -0
- package/src/commands/generate.ts +63 -0
- package/src/commands/validate.ts +38 -0
- package/src/index.ts +5 -0
- package/src/naming.ts +42 -0
- package/src/templates.ts +423 -0
- package/dist/chunk-36ZM4UZV.js.map +0 -1
|
@@ -47,6 +47,7 @@ function renderRepository(names, cacheEnabled, prismaImport, base) {
|
|
|
47
47
|
const cacheBlock = cacheEnabled ? ` cache: {
|
|
48
48
|
ttl: 86400,
|
|
49
49
|
sensitiveFields: ['password'],
|
|
50
|
+
defaultSetCache: true,
|
|
50
51
|
},
|
|
51
52
|
` : "";
|
|
52
53
|
const content = apply(
|
|
@@ -72,7 +73,7 @@ export type {{pascal}}Repository = InstanceType<typeof {{pascal}}Repository>;
|
|
|
72
73
|
};
|
|
73
74
|
}
|
|
74
75
|
function renderModuleFiles(options) {
|
|
75
|
-
const { names, cacheEnabled, full = false } = options;
|
|
76
|
+
const { names, cacheEnabled, full = false, helpers = false, dto = false } = options;
|
|
76
77
|
const prismaImport = options.prismaImport ?? "@prisma/client";
|
|
77
78
|
const base = `src/modules/${names.kebab}`;
|
|
78
79
|
const repository = renderRepository(names, cacheEnabled, prismaImport, base);
|
|
@@ -84,11 +85,19 @@ function renderModuleFiles(options) {
|
|
|
84
85
|
|
|
85
86
|
import { {{pascal}}Repository } from '../repositories/{{kebab}}.repository';
|
|
86
87
|
import { get{{pascal}}Select } from '../types/select-{{kebab}}.type';
|
|
87
|
-
|
|
88
|
+
import { where{{pascal}}GetManyPaginate } from '../types/where-{{kebab}}.type';
|
|
89
|
+
{{dtoImport}}
|
|
88
90
|
@Injectable()
|
|
89
91
|
export class {{pascal}}Service {
|
|
90
92
|
constructor(private readonly {{camel}}Repository: {{pascal}}Repository) {}
|
|
91
93
|
|
|
94
|
+
async handleCreate(dto: Create{{pascal}}Dto) {
|
|
95
|
+
return await this.{{camel}}Repository.create({
|
|
96
|
+
data: { ...dto },
|
|
97
|
+
select: get{{pascal}}Select('general'),
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
92
101
|
async handleGetById(id: string) {
|
|
93
102
|
return await this.{{camel}}Repository.getThrowById({
|
|
94
103
|
id,
|
|
@@ -96,28 +105,150 @@ export class {{pascal}}Service {
|
|
|
96
105
|
setCache: true,
|
|
97
106
|
});
|
|
98
107
|
}
|
|
108
|
+
|
|
109
|
+
async handleGetManyPaginate(filter: Filter{{pascal}}Dto) {
|
|
110
|
+
const { where } = where{{pascal}}GetManyPaginate(filter);
|
|
111
|
+
return await this.{{camel}}Repository.getManyPaginate({
|
|
112
|
+
where,
|
|
113
|
+
select: get{{pascal}}Select('general'),
|
|
114
|
+
page: filter.page,
|
|
115
|
+
pageSize: filter.pageSize,
|
|
116
|
+
setCache: true,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async handleUpdateById(id: string, dto: Update{{pascal}}Dto) {
|
|
121
|
+
return await this.{{camel}}Repository.updateById({
|
|
122
|
+
id,
|
|
123
|
+
data: { ...dto },
|
|
124
|
+
select: get{{pascal}}Select('general'),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async handleDeleteById(id: string) {
|
|
129
|
+
return await this.{{camel}}Repository.deleteById({
|
|
130
|
+
id,
|
|
131
|
+
select: get{{pascal}}Select('minimal'),
|
|
132
|
+
});
|
|
133
|
+
}
|
|
99
134
|
}
|
|
100
135
|
`,
|
|
101
136
|
names,
|
|
102
|
-
{
|
|
137
|
+
{
|
|
138
|
+
"{{dtoImport}}": dto ? `import type {
|
|
139
|
+
Create{{pascal}}Dto,
|
|
140
|
+
Update{{pascal}}Dto,
|
|
141
|
+
Filter{{pascal}}Dto,
|
|
142
|
+
} from '../dto/{{kebab}}.dto';
|
|
143
|
+
` : `type Create{{pascal}}Dto = Record<string, unknown>;
|
|
144
|
+
type Update{{pascal}}Dto = Record<string, unknown>;
|
|
145
|
+
type Filter{{pascal}}Dto = { page?: number; pageSize?: number; q?: string };
|
|
146
|
+
`
|
|
147
|
+
}
|
|
103
148
|
);
|
|
104
149
|
const controller = apply(
|
|
105
|
-
`import {
|
|
150
|
+
`import {
|
|
151
|
+
Body,
|
|
152
|
+
Controller,
|
|
153
|
+
Delete,
|
|
154
|
+
Get,
|
|
155
|
+
HttpStatus,
|
|
156
|
+
Param,
|
|
157
|
+
Patch,
|
|
158
|
+
Post,
|
|
159
|
+
Query,
|
|
160
|
+
Res,
|
|
161
|
+
} from '@nestjs/common';
|
|
162
|
+
import type { Response } from 'express';
|
|
106
163
|
|
|
107
164
|
import { {{pascal}}Service } from '../services/{{kebab}}.service';
|
|
108
|
-
|
|
165
|
+
{{dtoImport}}
|
|
109
166
|
@Controller('{{route}}')
|
|
110
167
|
export class {{pascal}}Controller {
|
|
111
168
|
constructor(private readonly {{camel}}Service: {{pascal}}Service) {}
|
|
112
169
|
|
|
170
|
+
@Post()
|
|
171
|
+
async create(@Body() dto: Create{{pascal}}Dto, @Res() res: Response) {
|
|
172
|
+
try {
|
|
173
|
+
const result = await this.{{camel}}Service.handleCreate(dto);
|
|
174
|
+
return res.status(HttpStatus.CREATED).json({ data: result });
|
|
175
|
+
} catch (error) {
|
|
176
|
+
const status = (error as { statusCode?: number })?.statusCode ?? 500;
|
|
177
|
+
return res.status(status).json({
|
|
178
|
+
error: { message: (error as Error).message, httpStatus: status },
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
@Get()
|
|
184
|
+
async getMany(@Query() filter: Filter{{pascal}}Dto, @Res() res: Response) {
|
|
185
|
+
try {
|
|
186
|
+
const result = await this.{{camel}}Service.handleGetManyPaginate(filter);
|
|
187
|
+
return res.status(HttpStatus.OK).json({ data: result.data, meta: result.meta });
|
|
188
|
+
} catch (error) {
|
|
189
|
+
const status = (error as { statusCode?: number })?.statusCode ?? 500;
|
|
190
|
+
return res.status(status).json({
|
|
191
|
+
error: { message: (error as Error).message, httpStatus: status },
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
113
196
|
@Get(':id')
|
|
114
|
-
async getById(@Param('id') id: string) {
|
|
115
|
-
|
|
197
|
+
async getById(@Param('id') id: string, @Res() res: Response) {
|
|
198
|
+
try {
|
|
199
|
+
const result = await this.{{camel}}Service.handleGetById(id);
|
|
200
|
+
return res.status(HttpStatus.OK).json({ data: result });
|
|
201
|
+
} catch (error) {
|
|
202
|
+
const status = (error as { statusCode?: number })?.statusCode ?? 500;
|
|
203
|
+
return res.status(status).json({
|
|
204
|
+
error: { message: (error as Error).message, httpStatus: status },
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
@Patch(':id')
|
|
210
|
+
async update(
|
|
211
|
+
@Param('id') id: string,
|
|
212
|
+
@Body() dto: Update{{pascal}}Dto,
|
|
213
|
+
@Res() res: Response,
|
|
214
|
+
) {
|
|
215
|
+
try {
|
|
216
|
+
const result = await this.{{camel}}Service.handleUpdateById(id, dto);
|
|
217
|
+
return res.status(HttpStatus.OK).json({ data: result });
|
|
218
|
+
} catch (error) {
|
|
219
|
+
const status = (error as { statusCode?: number })?.statusCode ?? 500;
|
|
220
|
+
return res.status(status).json({
|
|
221
|
+
error: { message: (error as Error).message, httpStatus: status },
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
@Delete(':id')
|
|
227
|
+
async delete(@Param('id') id: string, @Res() res: Response) {
|
|
228
|
+
try {
|
|
229
|
+
const result = await this.{{camel}}Service.handleDeleteById(id);
|
|
230
|
+
return res.status(HttpStatus.OK).json({ data: result });
|
|
231
|
+
} catch (error) {
|
|
232
|
+
const status = (error as { statusCode?: number })?.statusCode ?? 500;
|
|
233
|
+
return res.status(status).json({
|
|
234
|
+
error: { message: (error as Error).message, httpStatus: status },
|
|
235
|
+
});
|
|
236
|
+
}
|
|
116
237
|
}
|
|
117
238
|
}
|
|
118
239
|
`,
|
|
119
240
|
names,
|
|
120
|
-
{
|
|
241
|
+
{
|
|
242
|
+
"{{dtoImport}}": dto ? `import type {
|
|
243
|
+
Create{{pascal}}Dto,
|
|
244
|
+
Update{{pascal}}Dto,
|
|
245
|
+
Filter{{pascal}}Dto,
|
|
246
|
+
} from '../dto/{{kebab}}.dto';
|
|
247
|
+
` : `type Create{{pascal}}Dto = Record<string, unknown>;
|
|
248
|
+
type Update{{pascal}}Dto = Record<string, unknown>;
|
|
249
|
+
type Filter{{pascal}}Dto = { page?: number; pageSize?: number; q?: string };
|
|
250
|
+
`
|
|
251
|
+
}
|
|
121
252
|
);
|
|
122
253
|
const moduleFile = apply(
|
|
123
254
|
`import { Module } from '@nestjs/common';
|
|
@@ -125,16 +256,21 @@ export class {{pascal}}Controller {
|
|
|
125
256
|
import { {{pascal}}Controller } from './controllers/{{kebab}}.controller';
|
|
126
257
|
import { {{pascal}}Service } from './services/{{kebab}}.service';
|
|
127
258
|
import { {{pascal}}Repository } from './repositories/{{kebab}}.repository';
|
|
128
|
-
|
|
259
|
+
{{helpersImport}}
|
|
129
260
|
@Module({
|
|
130
261
|
controllers: [{{pascal}}Controller],
|
|
131
|
-
providers: [{{pascal}}Service, {{pascal}}Repository],
|
|
262
|
+
providers: [{{pascal}}Service, {{pascal}}Repository{{helpersProviders}}],
|
|
132
263
|
exports: [{{pascal}}Service, {{pascal}}Repository],
|
|
133
264
|
})
|
|
134
265
|
export class {{pascal}}Module {}
|
|
135
266
|
`,
|
|
136
267
|
names,
|
|
137
|
-
{
|
|
268
|
+
{
|
|
269
|
+
"{{helpersImport}}": helpers ? `import { {{pascal}}ValidateHelper } from './helpers/{{kebab}}-validate.helper';
|
|
270
|
+
import { {{pascal}}MapperHelper } from './helpers/{{kebab}}-mapper.helper';
|
|
271
|
+
` : "",
|
|
272
|
+
"{{helpersProviders}}": helpers ? `, {{pascal}}ValidateHelper, {{pascal}}MapperHelper` : ""
|
|
273
|
+
}
|
|
138
274
|
);
|
|
139
275
|
const select = apply(
|
|
140
276
|
`import { Prisma } from '{{prismaImport}}';
|
|
@@ -161,18 +297,22 @@ export const {{camel}}SelectPresets = {
|
|
|
161
297
|
const where = apply(
|
|
162
298
|
`import { Prisma } from '{{prismaImport}}';
|
|
163
299
|
|
|
164
|
-
export function where{{pascal}}GetManyPaginate(
|
|
300
|
+
export function where{{pascal}}GetManyPaginate(filter: {
|
|
165
301
|
q?: string;
|
|
166
302
|
}): {
|
|
167
303
|
where: Prisma.{{pascal}}WhereInput;
|
|
168
304
|
} {
|
|
169
|
-
|
|
305
|
+
const { q } = filter;
|
|
306
|
+
const where: Prisma.{{pascal}}WhereInput = {
|
|
307
|
+
...(q ? { /* add searchable fields */ } : {}),
|
|
308
|
+
};
|
|
309
|
+
return { where };
|
|
170
310
|
}
|
|
171
311
|
`,
|
|
172
312
|
names,
|
|
173
313
|
{ "{{prismaImport}}": prismaImport }
|
|
174
314
|
);
|
|
175
|
-
|
|
315
|
+
const files = [
|
|
176
316
|
{ relativePath: `${base}/${names.kebab}.module.ts`, content: moduleFile },
|
|
177
317
|
{
|
|
178
318
|
relativePath: `${base}/controllers/${names.kebab}.controller.ts`,
|
|
@@ -192,6 +332,91 @@ export function where{{pascal}}GetManyPaginate(_filter: {
|
|
|
192
332
|
content: where
|
|
193
333
|
}
|
|
194
334
|
];
|
|
335
|
+
if (dto) {
|
|
336
|
+
files.push({
|
|
337
|
+
relativePath: `${base}/dto/${names.kebab}.dto.ts`,
|
|
338
|
+
content: apply(
|
|
339
|
+
`import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
|
340
|
+
import { IsOptional, IsString } from 'class-validator';
|
|
341
|
+
|
|
342
|
+
export class Create{{pascal}}Dto {
|
|
343
|
+
@ApiProperty({ example: 'name' })
|
|
344
|
+
@IsString()
|
|
345
|
+
name!: string;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
export class Update{{pascal}}Dto {
|
|
349
|
+
@ApiPropertyOptional({ example: 'name' })
|
|
350
|
+
@IsOptional()
|
|
351
|
+
@IsString()
|
|
352
|
+
name?: string;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
export class Filter{{pascal}}Dto {
|
|
356
|
+
@ApiPropertyOptional()
|
|
357
|
+
@IsOptional()
|
|
358
|
+
page?: number;
|
|
359
|
+
|
|
360
|
+
@ApiPropertyOptional()
|
|
361
|
+
@IsOptional()
|
|
362
|
+
pageSize?: number;
|
|
363
|
+
|
|
364
|
+
@ApiPropertyOptional()
|
|
365
|
+
@IsOptional()
|
|
366
|
+
@IsString()
|
|
367
|
+
q?: string;
|
|
368
|
+
}
|
|
369
|
+
`,
|
|
370
|
+
names,
|
|
371
|
+
{}
|
|
372
|
+
)
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
if (helpers) {
|
|
376
|
+
files.push(
|
|
377
|
+
{
|
|
378
|
+
relativePath: `${base}/helpers/${names.kebab}-validate.helper.ts`,
|
|
379
|
+
content: apply(
|
|
380
|
+
`import { Injectable } from '@nestjs/common';
|
|
381
|
+
|
|
382
|
+
import { {{pascal}}Repository } from '../repositories/{{kebab}}.repository';
|
|
383
|
+
import { get{{pascal}}Select } from '../types/select-{{kebab}}.type';
|
|
384
|
+
|
|
385
|
+
@Injectable()
|
|
386
|
+
export class {{pascal}}ValidateHelper {
|
|
387
|
+
constructor(private readonly {{camel}}Repository: {{pascal}}Repository) {}
|
|
388
|
+
|
|
389
|
+
async assertExists(id: string) {
|
|
390
|
+
return this.{{camel}}Repository.getThrowById({
|
|
391
|
+
id,
|
|
392
|
+
select: get{{pascal}}Select('minimal'),
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
`,
|
|
397
|
+
names,
|
|
398
|
+
{}
|
|
399
|
+
)
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
relativePath: `${base}/helpers/${names.kebab}-mapper.helper.ts`,
|
|
403
|
+
content: apply(
|
|
404
|
+
`import { Injectable } from '@nestjs/common';
|
|
405
|
+
|
|
406
|
+
@Injectable()
|
|
407
|
+
export class {{pascal}}MapperHelper {
|
|
408
|
+
toResponse(entity: Record<string, unknown>) {
|
|
409
|
+
return entity;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
`,
|
|
413
|
+
names,
|
|
414
|
+
{}
|
|
415
|
+
)
|
|
416
|
+
}
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
return files;
|
|
195
420
|
}
|
|
196
421
|
|
|
197
422
|
// src/commands/generate.ts
|
|
@@ -205,6 +430,8 @@ function runGenerate(options) {
|
|
|
205
430
|
names,
|
|
206
431
|
cacheEnabled: !!options.cache,
|
|
207
432
|
full,
|
|
433
|
+
helpers: !!options.helpers,
|
|
434
|
+
dto: !!options.dto,
|
|
208
435
|
prismaImport: options.prismaImport
|
|
209
436
|
});
|
|
210
437
|
for (const file of files) {
|
|
@@ -322,4 +549,4 @@ export {
|
|
|
322
549
|
runCodegen,
|
|
323
550
|
runValidate
|
|
324
551
|
};
|
|
325
|
-
//# sourceMappingURL=chunk-
|
|
552
|
+
//# sourceMappingURL=chunk-7E6MWEJP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/naming.ts","../src/templates.ts","../src/commands/generate.ts","../src/commands/codegen.ts","../src/commands/validate.ts"],"sourcesContent":["export interface ModuleNames {\n kebab: string;\n camel: string;\n pascal: string;\n repoModel: string;\n route: string;\n}\n\nconst KEBAB_NAME_RE = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;\n\nexport function assertKebabName(name: string): void {\n if (!KEBAB_NAME_RE.test(name)) {\n throw new Error(\n `Invalid module name \"${name}\". Use kebab-case (e.g. product, blog-post).`,\n );\n }\n}\n\nfunction kebabToPascal(kebab: string): string {\n return kebab\n .split('-')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join('');\n}\n\nfunction kebabToCamel(kebab: string): string {\n const pascal = kebabToPascal(kebab);\n return pascal.charAt(0).toLowerCase() + pascal.slice(1);\n}\n\nexport function resolveNames(kebab: string, route?: string): ModuleNames {\n assertKebabName(kebab);\n const pascal = kebabToPascal(kebab);\n const camel = kebabToCamel(kebab);\n return {\n kebab,\n camel,\n pascal,\n repoModel: camel,\n route: route ?? kebab,\n };\n}\n","import type { ModuleNames } from './naming';\n\nexport type GenerateOptions = {\n names: ModuleNames;\n cacheEnabled: boolean;\n /** When false (default), only emit the repository file. */\n full?: boolean;\n /** Emit validate + mapper helpers. */\n helpers?: boolean;\n /** Emit class-validator DTOs with @ApiProperty. */\n dto?: boolean;\n /** Prisma client import path (default `@prisma/client`). */\n prismaImport?: string;\n};\n\nfunction apply(template: string, names: ModuleNames, extras: Record<string, string>): string {\n const replacements: Record<string, string> = {\n '{{pascal}}': names.pascal,\n '{{camel}}': names.camel,\n '{{kebab}}': names.kebab,\n '{{route}}': names.route,\n '{{repoModel}}': names.repoModel,\n ...extras,\n };\n let result = template;\n for (const [key, value] of Object.entries(replacements)) {\n result = result.split(key).join(value);\n }\n return result;\n}\n\nexport type GeneratedFile = {\n relativePath: string;\n content: string;\n};\n\nfunction renderRepository(\n names: ModuleNames,\n cacheEnabled: boolean,\n prismaImport: string,\n base: string,\n): GeneratedFile {\n const cacheBlock = cacheEnabled\n ? ` cache: {\n ttl: 86400,\n sensitiveFields: ['password'],\n defaultSetCache: true,\n },\n`\n : '';\n\n const content = apply(\n `import { Prisma } from '{{prismaImport}}';\nimport { createInjectableRepository } from '@prismakit/nestjs';\n\nexport const {{pascal}}Repository = createInjectableRepository({\n model: '{{repoModel}}',\n scalarFields: Prisma.{{pascal}}ScalarFieldEnum,\n{{cacheBlock}}});\n\nexport type {{pascal}}Repository = InstanceType<typeof {{pascal}}Repository>;\n`,\n names,\n {\n '{{cacheBlock}}': cacheBlock,\n '{{prismaImport}}': prismaImport,\n },\n );\n\n return {\n relativePath: `${base}/repositories/${names.kebab}.repository.ts`,\n content,\n };\n}\n\nexport function renderModuleFiles(options: GenerateOptions): GeneratedFile[] {\n const { names, cacheEnabled, full = false, helpers = false, dto = false } =\n options;\n const prismaImport = options.prismaImport ?? '@prisma/client';\n const base = `src/modules/${names.kebab}`;\n\n const repository = renderRepository(names, cacheEnabled, prismaImport, base);\n\n if (!full) {\n return [repository];\n }\n\n const service = apply(\n `import { Injectable } from '@nestjs/common';\n\nimport { {{pascal}}Repository } from '../repositories/{{kebab}}.repository';\nimport { get{{pascal}}Select } from '../types/select-{{kebab}}.type';\nimport { where{{pascal}}GetManyPaginate } from '../types/where-{{kebab}}.type';\n{{dtoImport}}\n@Injectable()\nexport class {{pascal}}Service {\n constructor(private readonly {{camel}}Repository: {{pascal}}Repository) {}\n\n async handleCreate(dto: Create{{pascal}}Dto) {\n return await this.{{camel}}Repository.create({\n data: { ...dto },\n select: get{{pascal}}Select('general'),\n });\n }\n\n async handleGetById(id: string) {\n return await this.{{camel}}Repository.getThrowById({\n id,\n select: get{{pascal}}Select('general'),\n setCache: true,\n });\n }\n\n async handleGetManyPaginate(filter: Filter{{pascal}}Dto) {\n const { where } = where{{pascal}}GetManyPaginate(filter);\n return await this.{{camel}}Repository.getManyPaginate({\n where,\n select: get{{pascal}}Select('general'),\n page: filter.page,\n pageSize: filter.pageSize,\n setCache: true,\n });\n }\n\n async handleUpdateById(id: string, dto: Update{{pascal}}Dto) {\n return await this.{{camel}}Repository.updateById({\n id,\n data: { ...dto },\n select: get{{pascal}}Select('general'),\n });\n }\n\n async handleDeleteById(id: string) {\n return await this.{{camel}}Repository.deleteById({\n id,\n select: get{{pascal}}Select('minimal'),\n });\n }\n}\n`,\n names,\n {\n '{{dtoImport}}': dto\n ? `import type {\\n Create{{pascal}}Dto,\\n Update{{pascal}}Dto,\\n Filter{{pascal}}Dto,\\n} from '../dto/{{kebab}}.dto';\\n`\n : `type Create{{pascal}}Dto = Record<string, unknown>;\\ntype Update{{pascal}}Dto = Record<string, unknown>;\\ntype Filter{{pascal}}Dto = { page?: number; pageSize?: number; q?: string };\\n`,\n },\n );\n\n const controller = apply(\n `import {\n Body,\n Controller,\n Delete,\n Get,\n HttpStatus,\n Param,\n Patch,\n Post,\n Query,\n Res,\n} from '@nestjs/common';\nimport type { Response } from 'express';\n\nimport { {{pascal}}Service } from '../services/{{kebab}}.service';\n{{dtoImport}}\n@Controller('{{route}}')\nexport class {{pascal}}Controller {\n constructor(private readonly {{camel}}Service: {{pascal}}Service) {}\n\n @Post()\n async create(@Body() dto: Create{{pascal}}Dto, @Res() res: Response) {\n try {\n const result = await this.{{camel}}Service.handleCreate(dto);\n return res.status(HttpStatus.CREATED).json({ data: result });\n } catch (error) {\n const status = (error as { statusCode?: number })?.statusCode ?? 500;\n return res.status(status).json({\n error: { message: (error as Error).message, httpStatus: status },\n });\n }\n }\n\n @Get()\n async getMany(@Query() filter: Filter{{pascal}}Dto, @Res() res: Response) {\n try {\n const result = await this.{{camel}}Service.handleGetManyPaginate(filter);\n return res.status(HttpStatus.OK).json({ data: result.data, meta: result.meta });\n } catch (error) {\n const status = (error as { statusCode?: number })?.statusCode ?? 500;\n return res.status(status).json({\n error: { message: (error as Error).message, httpStatus: status },\n });\n }\n }\n\n @Get(':id')\n async getById(@Param('id') id: string, @Res() res: Response) {\n try {\n const result = await this.{{camel}}Service.handleGetById(id);\n return res.status(HttpStatus.OK).json({ data: result });\n } catch (error) {\n const status = (error as { statusCode?: number })?.statusCode ?? 500;\n return res.status(status).json({\n error: { message: (error as Error).message, httpStatus: status },\n });\n }\n }\n\n @Patch(':id')\n async update(\n @Param('id') id: string,\n @Body() dto: Update{{pascal}}Dto,\n @Res() res: Response,\n ) {\n try {\n const result = await this.{{camel}}Service.handleUpdateById(id, dto);\n return res.status(HttpStatus.OK).json({ data: result });\n } catch (error) {\n const status = (error as { statusCode?: number })?.statusCode ?? 500;\n return res.status(status).json({\n error: { message: (error as Error).message, httpStatus: status },\n });\n }\n }\n\n @Delete(':id')\n async delete(@Param('id') id: string, @Res() res: Response) {\n try {\n const result = await this.{{camel}}Service.handleDeleteById(id);\n return res.status(HttpStatus.OK).json({ data: result });\n } catch (error) {\n const status = (error as { statusCode?: number })?.statusCode ?? 500;\n return res.status(status).json({\n error: { message: (error as Error).message, httpStatus: status },\n });\n }\n }\n}\n`,\n names,\n {\n '{{dtoImport}}': dto\n ? `import type {\\n Create{{pascal}}Dto,\\n Update{{pascal}}Dto,\\n Filter{{pascal}}Dto,\\n} from '../dto/{{kebab}}.dto';\\n`\n : `type Create{{pascal}}Dto = Record<string, unknown>;\\ntype Update{{pascal}}Dto = Record<string, unknown>;\\ntype Filter{{pascal}}Dto = { page?: number; pageSize?: number; q?: string };\\n`,\n },\n );\n\n const moduleFile = apply(\n `import { Module } from '@nestjs/common';\n\nimport { {{pascal}}Controller } from './controllers/{{kebab}}.controller';\nimport { {{pascal}}Service } from './services/{{kebab}}.service';\nimport { {{pascal}}Repository } from './repositories/{{kebab}}.repository';\n{{helpersImport}}\n@Module({\n controllers: [{{pascal}}Controller],\n providers: [{{pascal}}Service, {{pascal}}Repository{{helpersProviders}}],\n exports: [{{pascal}}Service, {{pascal}}Repository],\n})\nexport class {{pascal}}Module {}\n`,\n names,\n {\n '{{helpersImport}}': helpers\n ? `import { {{pascal}}ValidateHelper } from './helpers/{{kebab}}-validate.helper';\\nimport { {{pascal}}MapperHelper } from './helpers/{{kebab}}-mapper.helper';\\n`\n : '',\n '{{helpersProviders}}': helpers\n ? `, {{pascal}}ValidateHelper, {{pascal}}MapperHelper`\n : '',\n },\n );\n\n const select = apply(\n `import { Prisma } from '{{prismaImport}}';\n\ntype {{pascal}}SelectPresetKey = keyof typeof {{camel}}SelectPresets;\n\nexport function get{{pascal}}Select<K extends {{pascal}}SelectPresetKey>(key: K) {\n return {{camel}}SelectPresets[key];\n}\n\nexport const {{camel}}SelectPresets = {\n minimal: {\n id: true,\n } satisfies Prisma.{{pascal}}Select,\n\n general: {\n id: true,\n } satisfies Prisma.{{pascal}}Select,\n};\n`,\n names,\n { '{{prismaImport}}': prismaImport },\n );\n\n const where = apply(\n `import { Prisma } from '{{prismaImport}}';\n\nexport function where{{pascal}}GetManyPaginate(filter: {\n q?: string;\n}): {\n where: Prisma.{{pascal}}WhereInput;\n} {\n const { q } = filter;\n const where: Prisma.{{pascal}}WhereInput = {\n ...(q ? { /* add searchable fields */ } : {}),\n };\n return { where };\n}\n`,\n names,\n { '{{prismaImport}}': prismaImport },\n );\n\n const files: GeneratedFile[] = [\n { relativePath: `${base}/${names.kebab}.module.ts`, content: moduleFile },\n {\n relativePath: `${base}/controllers/${names.kebab}.controller.ts`,\n content: controller,\n },\n {\n relativePath: `${base}/services/${names.kebab}.service.ts`,\n content: service,\n },\n repository,\n {\n relativePath: `${base}/types/select-${names.kebab}.type.ts`,\n content: select,\n },\n {\n relativePath: `${base}/types/where-${names.kebab}.type.ts`,\n content: where,\n },\n ];\n\n if (dto) {\n files.push({\n relativePath: `${base}/dto/${names.kebab}.dto.ts`,\n content: apply(\n `import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';\nimport { IsOptional, IsString } from 'class-validator';\n\nexport class Create{{pascal}}Dto {\n @ApiProperty({ example: 'name' })\n @IsString()\n name!: string;\n}\n\nexport class Update{{pascal}}Dto {\n @ApiPropertyOptional({ example: 'name' })\n @IsOptional()\n @IsString()\n name?: string;\n}\n\nexport class Filter{{pascal}}Dto {\n @ApiPropertyOptional()\n @IsOptional()\n page?: number;\n\n @ApiPropertyOptional()\n @IsOptional()\n pageSize?: number;\n\n @ApiPropertyOptional()\n @IsOptional()\n @IsString()\n q?: string;\n}\n`,\n names,\n {},\n ),\n });\n }\n\n if (helpers) {\n files.push(\n {\n relativePath: `${base}/helpers/${names.kebab}-validate.helper.ts`,\n content: apply(\n `import { Injectable } from '@nestjs/common';\n\nimport { {{pascal}}Repository } from '../repositories/{{kebab}}.repository';\nimport { get{{pascal}}Select } from '../types/select-{{kebab}}.type';\n\n@Injectable()\nexport class {{pascal}}ValidateHelper {\n constructor(private readonly {{camel}}Repository: {{pascal}}Repository) {}\n\n async assertExists(id: string) {\n return this.{{camel}}Repository.getThrowById({\n id,\n select: get{{pascal}}Select('minimal'),\n });\n }\n}\n`,\n names,\n {},\n ),\n },\n {\n relativePath: `${base}/helpers/${names.kebab}-mapper.helper.ts`,\n content: apply(\n `import { Injectable } from '@nestjs/common';\n\n@Injectable()\nexport class {{pascal}}MapperHelper {\n toResponse(entity: Record<string, unknown>) {\n return entity;\n }\n}\n`,\n names,\n {},\n ),\n },\n );\n }\n\n return files;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport { resolveNames } from '../naming';\nimport { renderModuleFiles } from '../templates';\n\nexport type GenerateCommandOptions = {\n name: string;\n cache?: boolean;\n route?: string;\n cwd?: string;\n dryRun?: boolean;\n /** Emit full Nest module (controller/service/types). Default: repo-only. */\n full?: boolean;\n /** Emit validate + mapper helpers. */\n helpers?: boolean;\n /** Emit class-validator DTOs. */\n dto?: boolean;\n /** Prisma client import path (default `@prisma/client`). */\n prismaImport?: string;\n};\n\nexport function runGenerate(options: GenerateCommandOptions): void {\n const cwd = options.cwd ?? process.cwd();\n const names = resolveNames(options.name, options.route);\n const full = !!options.full;\n const files = renderModuleFiles({\n names,\n cacheEnabled: !!options.cache,\n full,\n helpers: !!options.helpers,\n dto: !!options.dto,\n prismaImport: options.prismaImport,\n });\n\n for (const file of files) {\n const fullPath = path.join(cwd, file.relativePath);\n if (options.dryRun) {\n console.log(`[dry-run] would write ${file.relativePath}`);\n continue;\n }\n if (fs.existsSync(fullPath)) {\n console.warn(`skip (exists): ${file.relativePath}`);\n continue;\n }\n fs.mkdirSync(path.dirname(fullPath), { recursive: true });\n const content = file.content.endsWith('\\n')\n ? file.content\n : `${file.content}\\n`;\n fs.writeFileSync(fullPath, content, 'utf-8');\n console.log(`created ${file.relativePath}`);\n }\n\n if (full) {\n console.log(\n `\\nScaffolded module \"${names.kebab}\". Register ${names.pascal}Module in app.module.ts.`,\n );\n } else {\n console.log(\n `\\nScaffolded repository \"${names.pascal}Repository\". Register it in your feature module providers.`,\n );\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport {\n computeRelationAliasesFromSchema,\n getSchemaModels,\n} from '@prismakit/core';\n\nexport type CodegenCommandOptions = {\n cwd?: string;\n schemaPath?: string;\n write?: boolean;\n outFile?: string;\n};\n\n/**\n * Parse prisma/schema.prisma and print (or write) suggested relation aliases.\n */\nexport function runCodegen(options: CodegenCommandOptions = {}): void {\n const cwd = options.cwd ?? process.cwd();\n const schemaPath =\n options.schemaPath ?? path.join(cwd, 'prisma', 'schema.prisma');\n\n if (!fs.existsSync(schemaPath)) {\n throw new Error(`Prisma schema not found at ${schemaPath}`);\n }\n\n const models = getSchemaModels(schemaPath);\n const aliases = computeRelationAliasesFromSchema(models);\n\n const entries = Object.entries(aliases).sort(([a], [b]) =>\n a.localeCompare(b),\n );\n\n if (entries.length === 0) {\n console.log(\n 'No additional relation aliases suggested (suffix rules cover all).',\n );\n return;\n }\n\n const lines = [\n '// Suggested RELATION_MODEL_ALIASES entries (merge into your resolver config)',\n 'export const SUGGESTED_RELATION_MODEL_ALIASES = {',\n ...entries.map(([k, v]) => ` ${k}: '${v}',`),\n '} as const;',\n '',\n ];\n const output = lines.join('\\n');\n\n if (options.write) {\n const out =\n options.outFile ??\n path.join(\n cwd,\n 'src',\n 'infrastructure',\n 'prisma',\n 'suggested-relation-aliases.ts',\n );\n fs.mkdirSync(path.dirname(out), { recursive: true });\n fs.writeFileSync(out, output, 'utf-8');\n console.log(`wrote ${path.relative(cwd, out)}`);\n } else {\n console.log(output);\n }\n\n console.log(`\\n${entries.length} alias suggestion(s).`);\n}\n","import {\n assertSelectComposeValid,\n validateSelectCompose,\n} from '@prismakit/core';\n\nexport type ValidateCommandOptions = {\n cwd?: string;\n assert?: boolean;\n};\n\n/**\n * Run select-compose validation from @prismakit/core.\n */\nexport function runValidate(options: ValidateCommandOptions = {}): void {\n const cwd = options.cwd ?? process.cwd();\n\n if (options.assert !== false) {\n try {\n assertSelectComposeValid(cwd);\n console.log('Select compose validation passed.');\n } catch (err) {\n console.error((err as Error).message);\n process.exitCode = 1;\n }\n return;\n }\n\n const issues = validateSelectCompose(cwd);\n if (issues.length === 0) {\n console.log('Select compose validation passed.');\n return;\n }\n\n for (const issue of issues) {\n console.error(` - ${issue.file}: ${issue.message}`);\n }\n process.exitCode = 1;\n}\n"],"mappings":"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","names":["fs","path"]}
|