@prismakit/cli 1.0.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/LICENSE +190 -0
- package/README.md +1 -0
- package/dist/bin.cjs +430 -0
- package/dist/bin.cjs.map +1 -0
- package/dist/bin.js +101 -0
- package/dist/bin.js.map +1 -0
- package/dist/chunk-36ZM4UZV.js +325 -0
- package/dist/chunk-36ZM4UZV.js.map +1 -0
- package/dist/index.cjs +362 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +58 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/package.json +49 -0
package/dist/bin.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
runCodegen,
|
|
4
|
+
runGenerate,
|
|
5
|
+
runValidate
|
|
6
|
+
} from "./chunk-36ZM4UZV.js";
|
|
7
|
+
|
|
8
|
+
// src/bin.ts
|
|
9
|
+
function printHelp() {
|
|
10
|
+
console.log(`prismakit \u2014 PrismaKit CLI
|
|
11
|
+
|
|
12
|
+
Usage:
|
|
13
|
+
prismakit generate <name> [--cache] [--full] [--route <path>] [--prisma-import <path>] [--dry-run]
|
|
14
|
+
prismakit codegen [--schema <path>] [--write] [--out <file>]
|
|
15
|
+
prismakit validate [--no-assert]
|
|
16
|
+
prismakit help
|
|
17
|
+
|
|
18
|
+
By default, generate writes only the repository file.
|
|
19
|
+
Pass --full for a Nest module (controller, service, types).
|
|
20
|
+
|
|
21
|
+
Examples:
|
|
22
|
+
prismakit generate product --cache
|
|
23
|
+
prismakit generate product --cache --full --route products
|
|
24
|
+
prismakit codegen --write
|
|
25
|
+
prismakit validate
|
|
26
|
+
`);
|
|
27
|
+
}
|
|
28
|
+
function parseArgs(argv) {
|
|
29
|
+
const [command = "help", ...rest] = argv;
|
|
30
|
+
const positional = [];
|
|
31
|
+
const flags = {};
|
|
32
|
+
for (let i = 0; i < rest.length; i++) {
|
|
33
|
+
const arg = rest[i];
|
|
34
|
+
if (arg.startsWith("--")) {
|
|
35
|
+
const key = arg.slice(2);
|
|
36
|
+
const next = rest[i + 1];
|
|
37
|
+
if (next && !next.startsWith("--")) {
|
|
38
|
+
flags[key] = next;
|
|
39
|
+
i++;
|
|
40
|
+
} else {
|
|
41
|
+
flags[key] = true;
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
positional.push(arg);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return { command, positional, flags };
|
|
48
|
+
}
|
|
49
|
+
function main() {
|
|
50
|
+
const { command, positional, flags } = parseArgs(process.argv.slice(2));
|
|
51
|
+
try {
|
|
52
|
+
switch (command) {
|
|
53
|
+
case "generate":
|
|
54
|
+
case "gen": {
|
|
55
|
+
const name = positional[0];
|
|
56
|
+
if (!name) {
|
|
57
|
+
console.error("Missing module name. Usage: prismakit generate <name>");
|
|
58
|
+
process.exitCode = 1;
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
runGenerate({
|
|
62
|
+
name,
|
|
63
|
+
cache: !!flags.cache,
|
|
64
|
+
full: !!flags.full,
|
|
65
|
+
route: typeof flags.route === "string" ? flags.route : void 0,
|
|
66
|
+
prismaImport: typeof flags["prisma-import"] === "string" ? flags["prisma-import"] : void 0,
|
|
67
|
+
dryRun: !!flags["dry-run"]
|
|
68
|
+
});
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
case "codegen": {
|
|
72
|
+
runCodegen({
|
|
73
|
+
schemaPath: typeof flags.schema === "string" ? flags.schema : void 0,
|
|
74
|
+
write: !!flags.write,
|
|
75
|
+
outFile: typeof flags.out === "string" ? flags.out : void 0
|
|
76
|
+
});
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
case "validate": {
|
|
80
|
+
runValidate({
|
|
81
|
+
assert: !flags["no-assert"]
|
|
82
|
+
});
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
case "help":
|
|
86
|
+
case "--help":
|
|
87
|
+
case "-h":
|
|
88
|
+
printHelp();
|
|
89
|
+
break;
|
|
90
|
+
default:
|
|
91
|
+
console.error(`Unknown command: ${command}`);
|
|
92
|
+
printHelp();
|
|
93
|
+
process.exitCode = 1;
|
|
94
|
+
}
|
|
95
|
+
} catch (err) {
|
|
96
|
+
console.error(err.message);
|
|
97
|
+
process.exitCode = 1;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
main();
|
|
101
|
+
//# sourceMappingURL=bin.js.map
|
package/dist/bin.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/bin.ts"],"sourcesContent":["import { runGenerate } from './commands/generate';\nimport { runCodegen } from './commands/codegen';\nimport { runValidate } from './commands/validate';\n\nfunction printHelp(): void {\n console.log(`prismakit — PrismaKit CLI\n\nUsage:\n prismakit generate <name> [--cache] [--full] [--route <path>] [--prisma-import <path>] [--dry-run]\n prismakit codegen [--schema <path>] [--write] [--out <file>]\n prismakit validate [--no-assert]\n prismakit help\n\nBy default, generate writes only the repository file.\nPass --full for a Nest module (controller, service, types).\n\nExamples:\n prismakit generate product --cache\n prismakit generate product --cache --full --route products\n prismakit codegen --write\n prismakit validate\n`);\n}\n\nfunction parseArgs(argv: string[]): {\n command: string;\n positional: string[];\n flags: Record<string, string | boolean>;\n} {\n const [command = 'help', ...rest] = argv;\n const positional: string[] = [];\n const flags: Record<string, string | boolean> = {};\n\n for (let i = 0; i < rest.length; i++) {\n const arg = rest[i];\n if (arg.startsWith('--')) {\n const key = arg.slice(2);\n const next = rest[i + 1];\n if (next && !next.startsWith('--')) {\n flags[key] = next;\n i++;\n } else {\n flags[key] = true;\n }\n } else {\n positional.push(arg);\n }\n }\n\n return { command, positional, flags };\n}\n\nfunction main(): void {\n const { command, positional, flags } = parseArgs(process.argv.slice(2));\n\n try {\n switch (command) {\n case 'generate':\n case 'gen': {\n const name = positional[0];\n if (!name) {\n console.error('Missing module name. Usage: prismakit generate <name>');\n process.exitCode = 1;\n return;\n }\n runGenerate({\n name,\n cache: !!flags.cache,\n full: !!flags.full,\n route:\n typeof flags.route === 'string' ? flags.route : undefined,\n prismaImport:\n typeof flags['prisma-import'] === 'string'\n ? flags['prisma-import']\n : undefined,\n dryRun: !!flags['dry-run'],\n });\n break;\n }\n case 'codegen': {\n runCodegen({\n schemaPath:\n typeof flags.schema === 'string' ? flags.schema : undefined,\n write: !!flags.write,\n outFile: typeof flags.out === 'string' ? flags.out : undefined,\n });\n break;\n }\n case 'validate': {\n runValidate({\n assert: !flags['no-assert'],\n });\n break;\n }\n case 'help':\n case '--help':\n case '-h':\n printHelp();\n break;\n default:\n console.error(`Unknown command: ${command}`);\n printHelp();\n process.exitCode = 1;\n }\n } catch (err) {\n console.error((err as Error).message);\n process.exitCode = 1;\n }\n}\n\nmain();\n"],"mappings":";;;;;;;AAIA,SAAS,YAAkB;AACzB,UAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAgBb;AACD;AAEA,SAAS,UAAU,MAIjB;AACA,QAAM,CAAC,UAAU,QAAQ,GAAG,IAAI,IAAI;AACpC,QAAM,aAAuB,CAAC;AAC9B,QAAM,QAA0C,CAAC;AAEjD,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,IAAI,WAAW,IAAI,GAAG;AACxB,YAAM,MAAM,IAAI,MAAM,CAAC;AACvB,YAAM,OAAO,KAAK,IAAI,CAAC;AACvB,UAAI,QAAQ,CAAC,KAAK,WAAW,IAAI,GAAG;AAClC,cAAM,GAAG,IAAI;AACb;AAAA,MACF,OAAO;AACL,cAAM,GAAG,IAAI;AAAA,MACf;AAAA,IACF,OAAO;AACL,iBAAW,KAAK,GAAG;AAAA,IACrB;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,YAAY,MAAM;AACtC;AAEA,SAAS,OAAa;AACpB,QAAM,EAAE,SAAS,YAAY,MAAM,IAAI,UAAU,QAAQ,KAAK,MAAM,CAAC,CAAC;AAEtE,MAAI;AACF,YAAQ,SAAS;AAAA,MACf,KAAK;AAAA,MACL,KAAK,OAAO;AACV,cAAM,OAAO,WAAW,CAAC;AACzB,YAAI,CAAC,MAAM;AACT,kBAAQ,MAAM,uDAAuD;AACrE,kBAAQ,WAAW;AACnB;AAAA,QACF;AACA,oBAAY;AAAA,UACV;AAAA,UACA,OAAO,CAAC,CAAC,MAAM;AAAA,UACf,MAAM,CAAC,CAAC,MAAM;AAAA,UACd,OACE,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;AAAA,UAClD,cACE,OAAO,MAAM,eAAe,MAAM,WAC9B,MAAM,eAAe,IACrB;AAAA,UACN,QAAQ,CAAC,CAAC,MAAM,SAAS;AAAA,QAC3B,CAAC;AACD;AAAA,MACF;AAAA,MACA,KAAK,WAAW;AACd,mBAAW;AAAA,UACT,YACE,OAAO,MAAM,WAAW,WAAW,MAAM,SAAS;AAAA,UACpD,OAAO,CAAC,CAAC,MAAM;AAAA,UACf,SAAS,OAAO,MAAM,QAAQ,WAAW,MAAM,MAAM;AAAA,QACvD,CAAC;AACD;AAAA,MACF;AAAA,MACA,KAAK,YAAY;AACf,oBAAY;AAAA,UACV,QAAQ,CAAC,MAAM,WAAW;AAAA,QAC5B,CAAC;AACD;AAAA,MACF;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACH,kBAAU;AACV;AAAA,MACF;AACE,gBAAQ,MAAM,oBAAoB,OAAO,EAAE;AAC3C,kBAAU;AACV,gBAAQ,WAAW;AAAA,IACvB;AAAA,EACF,SAAS,KAAK;AACZ,YAAQ,MAAO,IAAc,OAAO;AACpC,YAAQ,WAAW;AAAA,EACrB;AACF;AAEA,KAAK;","names":[]}
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
// src/naming.ts
|
|
2
|
+
var KEBAB_NAME_RE = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
3
|
+
function assertKebabName(name) {
|
|
4
|
+
if (!KEBAB_NAME_RE.test(name)) {
|
|
5
|
+
throw new Error(
|
|
6
|
+
`Invalid module name "${name}". Use kebab-case (e.g. product, blog-post).`
|
|
7
|
+
);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function kebabToPascal(kebab) {
|
|
11
|
+
return kebab.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
12
|
+
}
|
|
13
|
+
function kebabToCamel(kebab) {
|
|
14
|
+
const pascal = kebabToPascal(kebab);
|
|
15
|
+
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
|
16
|
+
}
|
|
17
|
+
function resolveNames(kebab, route) {
|
|
18
|
+
assertKebabName(kebab);
|
|
19
|
+
const pascal = kebabToPascal(kebab);
|
|
20
|
+
const camel = kebabToCamel(kebab);
|
|
21
|
+
return {
|
|
22
|
+
kebab,
|
|
23
|
+
camel,
|
|
24
|
+
pascal,
|
|
25
|
+
repoModel: camel,
|
|
26
|
+
route: route ?? kebab
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/templates.ts
|
|
31
|
+
function apply(template, names, extras) {
|
|
32
|
+
const replacements = {
|
|
33
|
+
"{{pascal}}": names.pascal,
|
|
34
|
+
"{{camel}}": names.camel,
|
|
35
|
+
"{{kebab}}": names.kebab,
|
|
36
|
+
"{{route}}": names.route,
|
|
37
|
+
"{{repoModel}}": names.repoModel,
|
|
38
|
+
...extras
|
|
39
|
+
};
|
|
40
|
+
let result = template;
|
|
41
|
+
for (const [key, value] of Object.entries(replacements)) {
|
|
42
|
+
result = result.split(key).join(value);
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
function renderRepository(names, cacheEnabled, prismaImport, base) {
|
|
47
|
+
const cacheBlock = cacheEnabled ? ` cache: {
|
|
48
|
+
ttl: 86400,
|
|
49
|
+
sensitiveFields: ['password'],
|
|
50
|
+
},
|
|
51
|
+
` : "";
|
|
52
|
+
const content = apply(
|
|
53
|
+
`import { Prisma } from '{{prismaImport}}';
|
|
54
|
+
import { createInjectableRepository } from '@prismakit/nestjs';
|
|
55
|
+
|
|
56
|
+
export const {{pascal}}Repository = createInjectableRepository({
|
|
57
|
+
model: '{{repoModel}}',
|
|
58
|
+
scalarFields: Prisma.{{pascal}}ScalarFieldEnum,
|
|
59
|
+
{{cacheBlock}}});
|
|
60
|
+
|
|
61
|
+
export type {{pascal}}Repository = InstanceType<typeof {{pascal}}Repository>;
|
|
62
|
+
`,
|
|
63
|
+
names,
|
|
64
|
+
{
|
|
65
|
+
"{{cacheBlock}}": cacheBlock,
|
|
66
|
+
"{{prismaImport}}": prismaImport
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
return {
|
|
70
|
+
relativePath: `${base}/repositories/${names.kebab}.repository.ts`,
|
|
71
|
+
content
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function renderModuleFiles(options) {
|
|
75
|
+
const { names, cacheEnabled, full = false } = options;
|
|
76
|
+
const prismaImport = options.prismaImport ?? "@prisma/client";
|
|
77
|
+
const base = `src/modules/${names.kebab}`;
|
|
78
|
+
const repository = renderRepository(names, cacheEnabled, prismaImport, base);
|
|
79
|
+
if (!full) {
|
|
80
|
+
return [repository];
|
|
81
|
+
}
|
|
82
|
+
const service = apply(
|
|
83
|
+
`import { Injectable } from '@nestjs/common';
|
|
84
|
+
|
|
85
|
+
import { {{pascal}}Repository } from '../repositories/{{kebab}}.repository';
|
|
86
|
+
import { get{{pascal}}Select } from '../types/select-{{kebab}}.type';
|
|
87
|
+
|
|
88
|
+
@Injectable()
|
|
89
|
+
export class {{pascal}}Service {
|
|
90
|
+
constructor(private readonly {{camel}}Repository: {{pascal}}Repository) {}
|
|
91
|
+
|
|
92
|
+
async handleGetById(id: string) {
|
|
93
|
+
return await this.{{camel}}Repository.getThrowById({
|
|
94
|
+
id,
|
|
95
|
+
select: get{{pascal}}Select('general'),
|
|
96
|
+
setCache: true,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
`,
|
|
101
|
+
names,
|
|
102
|
+
{}
|
|
103
|
+
);
|
|
104
|
+
const controller = apply(
|
|
105
|
+
`import { Controller, Get, Param } from '@nestjs/common';
|
|
106
|
+
|
|
107
|
+
import { {{pascal}}Service } from '../services/{{kebab}}.service';
|
|
108
|
+
|
|
109
|
+
@Controller('{{route}}')
|
|
110
|
+
export class {{pascal}}Controller {
|
|
111
|
+
constructor(private readonly {{camel}}Service: {{pascal}}Service) {}
|
|
112
|
+
|
|
113
|
+
@Get(':id')
|
|
114
|
+
async getById(@Param('id') id: string) {
|
|
115
|
+
return this.{{camel}}Service.handleGetById(id);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
`,
|
|
119
|
+
names,
|
|
120
|
+
{}
|
|
121
|
+
);
|
|
122
|
+
const moduleFile = apply(
|
|
123
|
+
`import { Module } from '@nestjs/common';
|
|
124
|
+
|
|
125
|
+
import { {{pascal}}Controller } from './controllers/{{kebab}}.controller';
|
|
126
|
+
import { {{pascal}}Service } from './services/{{kebab}}.service';
|
|
127
|
+
import { {{pascal}}Repository } from './repositories/{{kebab}}.repository';
|
|
128
|
+
|
|
129
|
+
@Module({
|
|
130
|
+
controllers: [{{pascal}}Controller],
|
|
131
|
+
providers: [{{pascal}}Service, {{pascal}}Repository],
|
|
132
|
+
exports: [{{pascal}}Service, {{pascal}}Repository],
|
|
133
|
+
})
|
|
134
|
+
export class {{pascal}}Module {}
|
|
135
|
+
`,
|
|
136
|
+
names,
|
|
137
|
+
{}
|
|
138
|
+
);
|
|
139
|
+
const select = apply(
|
|
140
|
+
`import { Prisma } from '{{prismaImport}}';
|
|
141
|
+
|
|
142
|
+
type {{pascal}}SelectPresetKey = keyof typeof {{camel}}SelectPresets;
|
|
143
|
+
|
|
144
|
+
export function get{{pascal}}Select<K extends {{pascal}}SelectPresetKey>(key: K) {
|
|
145
|
+
return {{camel}}SelectPresets[key];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export const {{camel}}SelectPresets = {
|
|
149
|
+
minimal: {
|
|
150
|
+
id: true,
|
|
151
|
+
} satisfies Prisma.{{pascal}}Select,
|
|
152
|
+
|
|
153
|
+
general: {
|
|
154
|
+
id: true,
|
|
155
|
+
} satisfies Prisma.{{pascal}}Select,
|
|
156
|
+
};
|
|
157
|
+
`,
|
|
158
|
+
names,
|
|
159
|
+
{ "{{prismaImport}}": prismaImport }
|
|
160
|
+
);
|
|
161
|
+
const where = apply(
|
|
162
|
+
`import { Prisma } from '{{prismaImport}}';
|
|
163
|
+
|
|
164
|
+
export function where{{pascal}}GetManyPaginate(_filter: {
|
|
165
|
+
q?: string;
|
|
166
|
+
}): {
|
|
167
|
+
where: Prisma.{{pascal}}WhereInput;
|
|
168
|
+
} {
|
|
169
|
+
return { where: {} };
|
|
170
|
+
}
|
|
171
|
+
`,
|
|
172
|
+
names,
|
|
173
|
+
{ "{{prismaImport}}": prismaImport }
|
|
174
|
+
);
|
|
175
|
+
return [
|
|
176
|
+
{ relativePath: `${base}/${names.kebab}.module.ts`, content: moduleFile },
|
|
177
|
+
{
|
|
178
|
+
relativePath: `${base}/controllers/${names.kebab}.controller.ts`,
|
|
179
|
+
content: controller
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
relativePath: `${base}/services/${names.kebab}.service.ts`,
|
|
183
|
+
content: service
|
|
184
|
+
},
|
|
185
|
+
repository,
|
|
186
|
+
{
|
|
187
|
+
relativePath: `${base}/types/select-${names.kebab}.type.ts`,
|
|
188
|
+
content: select
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
relativePath: `${base}/types/where-${names.kebab}.type.ts`,
|
|
192
|
+
content: where
|
|
193
|
+
}
|
|
194
|
+
];
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// src/commands/generate.ts
|
|
198
|
+
import * as fs from "fs";
|
|
199
|
+
import * as path from "path";
|
|
200
|
+
function runGenerate(options) {
|
|
201
|
+
const cwd = options.cwd ?? process.cwd();
|
|
202
|
+
const names = resolveNames(options.name, options.route);
|
|
203
|
+
const full = !!options.full;
|
|
204
|
+
const files = renderModuleFiles({
|
|
205
|
+
names,
|
|
206
|
+
cacheEnabled: !!options.cache,
|
|
207
|
+
full,
|
|
208
|
+
prismaImport: options.prismaImport
|
|
209
|
+
});
|
|
210
|
+
for (const file of files) {
|
|
211
|
+
const fullPath = path.join(cwd, file.relativePath);
|
|
212
|
+
if (options.dryRun) {
|
|
213
|
+
console.log(`[dry-run] would write ${file.relativePath}`);
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
if (fs.existsSync(fullPath)) {
|
|
217
|
+
console.warn(`skip (exists): ${file.relativePath}`);
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
221
|
+
const content = file.content.endsWith("\n") ? file.content : `${file.content}
|
|
222
|
+
`;
|
|
223
|
+
fs.writeFileSync(fullPath, content, "utf-8");
|
|
224
|
+
console.log(`created ${file.relativePath}`);
|
|
225
|
+
}
|
|
226
|
+
if (full) {
|
|
227
|
+
console.log(
|
|
228
|
+
`
|
|
229
|
+
Scaffolded module "${names.kebab}". Register ${names.pascal}Module in app.module.ts.`
|
|
230
|
+
);
|
|
231
|
+
} else {
|
|
232
|
+
console.log(
|
|
233
|
+
`
|
|
234
|
+
Scaffolded repository "${names.pascal}Repository". Register it in your feature module providers.`
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// src/commands/codegen.ts
|
|
240
|
+
import * as fs2 from "fs";
|
|
241
|
+
import * as path2 from "path";
|
|
242
|
+
import {
|
|
243
|
+
computeRelationAliasesFromSchema,
|
|
244
|
+
getSchemaModels
|
|
245
|
+
} from "@prismakit/core";
|
|
246
|
+
function runCodegen(options = {}) {
|
|
247
|
+
const cwd = options.cwd ?? process.cwd();
|
|
248
|
+
const schemaPath = options.schemaPath ?? path2.join(cwd, "prisma", "schema.prisma");
|
|
249
|
+
if (!fs2.existsSync(schemaPath)) {
|
|
250
|
+
throw new Error(`Prisma schema not found at ${schemaPath}`);
|
|
251
|
+
}
|
|
252
|
+
const models = getSchemaModels(schemaPath);
|
|
253
|
+
const aliases = computeRelationAliasesFromSchema(models);
|
|
254
|
+
const entries = Object.entries(aliases).sort(
|
|
255
|
+
([a], [b]) => a.localeCompare(b)
|
|
256
|
+
);
|
|
257
|
+
if (entries.length === 0) {
|
|
258
|
+
console.log(
|
|
259
|
+
"No additional relation aliases suggested (suffix rules cover all)."
|
|
260
|
+
);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
const lines = [
|
|
264
|
+
"// Suggested RELATION_MODEL_ALIASES entries (merge into your resolver config)",
|
|
265
|
+
"export const SUGGESTED_RELATION_MODEL_ALIASES = {",
|
|
266
|
+
...entries.map(([k, v]) => ` ${k}: '${v}',`),
|
|
267
|
+
"} as const;",
|
|
268
|
+
""
|
|
269
|
+
];
|
|
270
|
+
const output = lines.join("\n");
|
|
271
|
+
if (options.write) {
|
|
272
|
+
const out = options.outFile ?? path2.join(
|
|
273
|
+
cwd,
|
|
274
|
+
"src",
|
|
275
|
+
"infrastructure",
|
|
276
|
+
"prisma",
|
|
277
|
+
"suggested-relation-aliases.ts"
|
|
278
|
+
);
|
|
279
|
+
fs2.mkdirSync(path2.dirname(out), { recursive: true });
|
|
280
|
+
fs2.writeFileSync(out, output, "utf-8");
|
|
281
|
+
console.log(`wrote ${path2.relative(cwd, out)}`);
|
|
282
|
+
} else {
|
|
283
|
+
console.log(output);
|
|
284
|
+
}
|
|
285
|
+
console.log(`
|
|
286
|
+
${entries.length} alias suggestion(s).`);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// src/commands/validate.ts
|
|
290
|
+
import {
|
|
291
|
+
assertSelectComposeValid,
|
|
292
|
+
validateSelectCompose
|
|
293
|
+
} from "@prismakit/core";
|
|
294
|
+
function runValidate(options = {}) {
|
|
295
|
+
const cwd = options.cwd ?? process.cwd();
|
|
296
|
+
if (options.assert !== false) {
|
|
297
|
+
try {
|
|
298
|
+
assertSelectComposeValid(cwd);
|
|
299
|
+
console.log("Select compose validation passed.");
|
|
300
|
+
} catch (err) {
|
|
301
|
+
console.error(err.message);
|
|
302
|
+
process.exitCode = 1;
|
|
303
|
+
}
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
const issues = validateSelectCompose(cwd);
|
|
307
|
+
if (issues.length === 0) {
|
|
308
|
+
console.log("Select compose validation passed.");
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
for (const issue of issues) {
|
|
312
|
+
console.error(` - ${issue.file}: ${issue.message}`);
|
|
313
|
+
}
|
|
314
|
+
process.exitCode = 1;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
export {
|
|
318
|
+
assertKebabName,
|
|
319
|
+
resolveNames,
|
|
320
|
+
renderModuleFiles,
|
|
321
|
+
runGenerate,
|
|
322
|
+
runCodegen,
|
|
323
|
+
runValidate
|
|
324
|
+
};
|
|
325
|
+
//# sourceMappingURL=chunk-36ZM4UZV.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 /** 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 },\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 } = 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';\n\n@Injectable()\nexport class {{pascal}}Service {\n constructor(private readonly {{camel}}Repository: {{pascal}}Repository) {}\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`,\n names,\n {},\n );\n\n const controller = apply(\n `import { Controller, Get, Param } from '@nestjs/common';\n\nimport { {{pascal}}Service } from '../services/{{kebab}}.service';\n\n@Controller('{{route}}')\nexport class {{pascal}}Controller {\n constructor(private readonly {{camel}}Service: {{pascal}}Service) {}\n\n @Get(':id')\n async getById(@Param('id') id: string) {\n return this.{{camel}}Service.handleGetById(id);\n }\n}\n`,\n names,\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\n@Module({\n controllers: [{{pascal}}Controller],\n providers: [{{pascal}}Service, {{pascal}}Repository],\n exports: [{{pascal}}Service, {{pascal}}Repository],\n})\nexport class {{pascal}}Module {}\n`,\n names,\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 return { where: {} };\n}\n`,\n names,\n { '{{prismaImport}}': prismaImport },\n );\n\n return [\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","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 /** 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 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"]}
|