@manulz/nest-tools 1.1.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 +169 -0
- package/dist/cli/index.d.mts +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +569 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/index.mjs +546 -0
- package/dist/cli/index.mjs.map +1 -0
- package/dist/index.d.mts +141 -0
- package/dist/index.d.ts +141 -0
- package/dist/index.js +568 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +520 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +75 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,568 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
30
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
31
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
32
|
+
if (decorator = decorators[i])
|
|
33
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
34
|
+
if (kind && result) __defProp(target, key, result);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// src/index.ts
|
|
39
|
+
var src_exports = {};
|
|
40
|
+
__export(src_exports, {
|
|
41
|
+
CurrentUser: () => CurrentUser,
|
|
42
|
+
DEFAULT_CONFIG: () => DEFAULT_CONFIG,
|
|
43
|
+
IS_PUBLIC_KEY: () => IS_PUBLIC_KEY,
|
|
44
|
+
PaginationQueryDto: () => PaginationQueryDto,
|
|
45
|
+
Public: () => Public,
|
|
46
|
+
TransformResponseInterceptor: () => TransformResponseInterceptor,
|
|
47
|
+
createDefaultConfig: () => createDefaultConfig,
|
|
48
|
+
createPaginatedResponse: () => createPaginatedResponse,
|
|
49
|
+
generateCleanArchitecture: () => generateCleanArchitecture,
|
|
50
|
+
generateResource: () => generateResource,
|
|
51
|
+
loadConfig: () => loadConfig,
|
|
52
|
+
logger: () => logger,
|
|
53
|
+
runCommand: () => runCommand,
|
|
54
|
+
runDoctor: () => runDoctor,
|
|
55
|
+
toCamelCase: () => toCamelCase,
|
|
56
|
+
toKebabCase: () => toKebabCase,
|
|
57
|
+
toPascalCase: () => toPascalCase
|
|
58
|
+
});
|
|
59
|
+
module.exports = __toCommonJS(src_exports);
|
|
60
|
+
|
|
61
|
+
// src/core/runner/command-runner.ts
|
|
62
|
+
var import_node_child_process = require("child_process");
|
|
63
|
+
var import_node_util = require("util");
|
|
64
|
+
|
|
65
|
+
// src/utils/logger.ts
|
|
66
|
+
var import_picocolors = __toESM(require("picocolors"));
|
|
67
|
+
var logger = {
|
|
68
|
+
info: (msg) => console.log(import_picocolors.default.cyan("\u2139 ") + msg),
|
|
69
|
+
success: (msg) => console.log(import_picocolors.default.green("\u2714 ") + import_picocolors.default.bold(msg)),
|
|
70
|
+
warn: (msg) => console.log(import_picocolors.default.yellow("\u26A0 ") + msg),
|
|
71
|
+
error: (msg) => console.error(import_picocolors.default.red("\u2716 ") + import_picocolors.default.bold(msg)),
|
|
72
|
+
step: (step, detail) => {
|
|
73
|
+
console.log(import_picocolors.default.blue("\u25B6 ") + import_picocolors.default.bold(step) + (detail ? import_picocolors.default.dim(` (${detail})`) : ""));
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// src/core/runner/command-runner.ts
|
|
78
|
+
var execAsync = (0, import_node_util.promisify)(import_node_child_process.exec);
|
|
79
|
+
async function runCommand(command, options = {}) {
|
|
80
|
+
const { cwd = process.cwd(), dryRun = false, silent = false } = options;
|
|
81
|
+
if (dryRun) {
|
|
82
|
+
logger.info(`[dry-run] Would execute: ${command}`);
|
|
83
|
+
return { stdout: "", stderr: "" };
|
|
84
|
+
}
|
|
85
|
+
if (!silent) {
|
|
86
|
+
logger.step(command);
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const result = await execAsync(command, { cwd });
|
|
90
|
+
return result;
|
|
91
|
+
} catch (error) {
|
|
92
|
+
const message = error.stderr || error.message || "Command failed";
|
|
93
|
+
throw new Error(`Failed to execute: "${command}"
|
|
94
|
+
${message}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// src/core/config/index.ts
|
|
99
|
+
var import_promises = __toESM(require("fs/promises"));
|
|
100
|
+
var import_node_path = __toESM(require("path"));
|
|
101
|
+
var DEFAULT_CONFIG = {
|
|
102
|
+
spec: false,
|
|
103
|
+
flat: false,
|
|
104
|
+
architecture: "standard",
|
|
105
|
+
packageManager: "npm"
|
|
106
|
+
};
|
|
107
|
+
var CONFIG_FILENAMES = ["nest-tools.json", ".nesttoolsrc", ".nesttoolsrc.json"];
|
|
108
|
+
async function loadConfig(cwd = process.cwd()) {
|
|
109
|
+
for (const filename of CONFIG_FILENAMES) {
|
|
110
|
+
const configPath = import_node_path.default.join(cwd, filename);
|
|
111
|
+
try {
|
|
112
|
+
const data = await import_promises.default.readFile(configPath, "utf-8");
|
|
113
|
+
const parsed = JSON.parse(data);
|
|
114
|
+
return { ...DEFAULT_CONFIG, ...parsed };
|
|
115
|
+
} catch {
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return DEFAULT_CONFIG;
|
|
119
|
+
}
|
|
120
|
+
async function createDefaultConfig(cwd = process.cwd()) {
|
|
121
|
+
const targetPath = import_node_path.default.join(cwd, "nest-tools.json");
|
|
122
|
+
const content = JSON.stringify(DEFAULT_CONFIG, null, 2) + "\n";
|
|
123
|
+
await import_promises.default.writeFile(targetPath, content, "utf-8");
|
|
124
|
+
return targetPath;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// src/utils/strings.ts
|
|
128
|
+
function toKebabCase(str) {
|
|
129
|
+
return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
|
|
130
|
+
}
|
|
131
|
+
function toPascalCase(str) {
|
|
132
|
+
return toKebabCase(str).split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
|
|
133
|
+
}
|
|
134
|
+
function toCamelCase(str) {
|
|
135
|
+
const pascal = toPascalCase(str);
|
|
136
|
+
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/core/generator/generate-resource.ts
|
|
140
|
+
async function generateResource(options) {
|
|
141
|
+
const config = await loadConfig(options.cwd);
|
|
142
|
+
const rawName = options.name.trim();
|
|
143
|
+
const name = toKebabCase(rawName);
|
|
144
|
+
const spec = options.spec ?? config.spec ?? false;
|
|
145
|
+
const flat = options.flat ?? config.flat ?? false;
|
|
146
|
+
const dryRun = options.dryRun ?? false;
|
|
147
|
+
const cwd = options.cwd ?? process.cwd();
|
|
148
|
+
const specFlag = spec ? "" : "--no-spec";
|
|
149
|
+
const flatFlag = flat ? "--flat" : "";
|
|
150
|
+
const commands = [
|
|
151
|
+
`nest g mo ${name} ${flatFlag}`.trim(),
|
|
152
|
+
`nest g co ${name} ${specFlag} ${flatFlag}`.trim(),
|
|
153
|
+
`nest g s ${name} ${specFlag} ${flatFlag}`.trim()
|
|
154
|
+
];
|
|
155
|
+
logger.info(`Generating resource "${name}" (spec: ${spec ? "yes" : "no"}, flat: ${flat ? "yes" : "no"})...`);
|
|
156
|
+
for (const cmd of commands) {
|
|
157
|
+
await runCommand(cmd, { cwd, dryRun });
|
|
158
|
+
}
|
|
159
|
+
logger.success(`Resource "${name}" generated successfully.`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// src/core/generator/generate-clean-architecture.ts
|
|
163
|
+
var import_promises2 = __toESM(require("fs/promises"));
|
|
164
|
+
var import_node_path2 = __toESM(require("path"));
|
|
165
|
+
async function generateCleanArchitecture(options) {
|
|
166
|
+
const { dryRun = false, cwd = process.cwd() } = options;
|
|
167
|
+
const rawName = options.name.trim();
|
|
168
|
+
const kebab = toKebabCase(rawName);
|
|
169
|
+
const pascal = toPascalCase(rawName);
|
|
170
|
+
const camel = toCamelCase(rawName);
|
|
171
|
+
const baseDir = import_node_path2.default.join(cwd, "src", kebab);
|
|
172
|
+
const files = [
|
|
173
|
+
// 1. Domain Entity
|
|
174
|
+
{
|
|
175
|
+
filePath: import_node_path2.default.join(baseDir, "domain", "entities", `${kebab}.entity.ts`),
|
|
176
|
+
content: `export class ${pascal}Entity {
|
|
177
|
+
id!: string;
|
|
178
|
+
name!: string;
|
|
179
|
+
createdAt!: Date;
|
|
180
|
+
updatedAt!: Date;
|
|
181
|
+
|
|
182
|
+
constructor(partial: Partial<${pascal}Entity>) {
|
|
183
|
+
Object.assign(this, partial);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
`
|
|
187
|
+
},
|
|
188
|
+
// 2. Domain Repository Interface & Token
|
|
189
|
+
{
|
|
190
|
+
filePath: import_node_path2.default.join(baseDir, "domain", "repositories", `${kebab}.repository.interface.ts`),
|
|
191
|
+
content: `import { ${pascal}Entity } from '../entities/${kebab}.entity';
|
|
192
|
+
|
|
193
|
+
export const ${pascal.toUpperCase()}_REPOSITORY = Symbol('${pascal.toUpperCase()}_REPOSITORY');
|
|
194
|
+
|
|
195
|
+
export interface ${pascal}Repository {
|
|
196
|
+
findById(id: string): Promise<${pascal}Entity | null>;
|
|
197
|
+
findAll(): Promise<${pascal}Entity[]>;
|
|
198
|
+
create(data: Partial<${pascal}Entity>): Promise<${pascal}Entity>;
|
|
199
|
+
delete(id: string): Promise<void>;
|
|
200
|
+
}
|
|
201
|
+
`
|
|
202
|
+
},
|
|
203
|
+
// 3. Application DTOs
|
|
204
|
+
{
|
|
205
|
+
filePath: import_node_path2.default.join(baseDir, "application", "dtos", `create-${kebab}.dto.ts`),
|
|
206
|
+
content: `export class Create${pascal}Dto {
|
|
207
|
+
name!: string;
|
|
208
|
+
}
|
|
209
|
+
`
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
filePath: import_node_path2.default.join(baseDir, "application", "dtos", `update-${kebab}.dto.ts`),
|
|
213
|
+
content: `export class Update${pascal}Dto {
|
|
214
|
+
name?: string;
|
|
215
|
+
}
|
|
216
|
+
`
|
|
217
|
+
},
|
|
218
|
+
// 4. Application Use Cases
|
|
219
|
+
{
|
|
220
|
+
filePath: import_node_path2.default.join(baseDir, "application", "use-cases", `create-${kebab}.use-case.ts`),
|
|
221
|
+
content: `import { Inject, Injectable } from '@nestjs/common';
|
|
222
|
+
import {
|
|
223
|
+
${pascal}Repository,
|
|
224
|
+
${pascal.toUpperCase()}_REPOSITORY,
|
|
225
|
+
} from '../../domain/repositories/${kebab}.repository.interface';
|
|
226
|
+
import { ${pascal}Entity } from '../../domain/entities/${kebab}.entity';
|
|
227
|
+
import { Create${pascal}Dto } from '../dtos/create-${kebab}.dto';
|
|
228
|
+
|
|
229
|
+
@Injectable()
|
|
230
|
+
export class Create${pascal}UseCase {
|
|
231
|
+
constructor(
|
|
232
|
+
@Inject(${pascal.toUpperCase()}_REPOSITORY)
|
|
233
|
+
private readonly repository: ${pascal}Repository
|
|
234
|
+
) {}
|
|
235
|
+
|
|
236
|
+
async execute(dto: Create${pascal}Dto): Promise<${pascal}Entity> {
|
|
237
|
+
return this.repository.create({
|
|
238
|
+
name: dto.name,
|
|
239
|
+
createdAt: new Date(),
|
|
240
|
+
updatedAt: new Date(),
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
`
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
filePath: import_node_path2.default.join(baseDir, "application", "use-cases", `find-${kebab}.use-case.ts`),
|
|
248
|
+
content: `import { Inject, Injectable, NotFoundException } from '@nestjs/common';
|
|
249
|
+
import {
|
|
250
|
+
${pascal}Repository,
|
|
251
|
+
${pascal.toUpperCase()}_REPOSITORY,
|
|
252
|
+
} from '../../domain/repositories/${kebab}.repository.interface';
|
|
253
|
+
import { ${pascal}Entity } from '../../domain/entities/${kebab}.entity';
|
|
254
|
+
|
|
255
|
+
@Injectable()
|
|
256
|
+
export class Find${pascal}UseCase {
|
|
257
|
+
constructor(
|
|
258
|
+
@Inject(${pascal.toUpperCase()}_REPOSITORY)
|
|
259
|
+
private readonly repository: ${pascal}Repository
|
|
260
|
+
) {}
|
|
261
|
+
|
|
262
|
+
async execute(id: string): Promise<${pascal}Entity> {
|
|
263
|
+
const item = await this.repository.findById(id);
|
|
264
|
+
if (!item) {
|
|
265
|
+
throw new NotFoundException(\`${pascal} with id "\${id}" not found\`);
|
|
266
|
+
}
|
|
267
|
+
return item;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
`
|
|
271
|
+
},
|
|
272
|
+
// 5. Infrastructure In-Memory Repository
|
|
273
|
+
{
|
|
274
|
+
filePath: import_node_path2.default.join(
|
|
275
|
+
baseDir,
|
|
276
|
+
"infrastructure",
|
|
277
|
+
"repositories",
|
|
278
|
+
`in-memory-${kebab}.repository.ts`
|
|
279
|
+
),
|
|
280
|
+
content: `import { Injectable } from '@nestjs/common';
|
|
281
|
+
import {
|
|
282
|
+
${pascal}Repository,
|
|
283
|
+
} from '../../domain/repositories/${kebab}.repository.interface';
|
|
284
|
+
import { ${pascal}Entity } from '../../domain/entities/${kebab}.entity';
|
|
285
|
+
|
|
286
|
+
@Injectable()
|
|
287
|
+
export class InMemory${pascal}Repository implements ${pascal}Repository {
|
|
288
|
+
private readonly items: Map<string, ${pascal}Entity> = new Map();
|
|
289
|
+
|
|
290
|
+
async findById(id: string): Promise<${pascal}Entity | null> {
|
|
291
|
+
return this.items.get(id) || null;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async findAll(): Promise<${pascal}Entity[]> {
|
|
295
|
+
return Array.from(this.items.values());
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
async create(data: Partial<${pascal}Entity>): Promise<${pascal}Entity> {
|
|
299
|
+
const id = (this.items.size + 1).toString();
|
|
300
|
+
const entity = new ${pascal}Entity({
|
|
301
|
+
id,
|
|
302
|
+
name: data.name ?? 'Untitled',
|
|
303
|
+
createdAt: data.createdAt ?? new Date(),
|
|
304
|
+
updatedAt: data.updatedAt ?? new Date(),
|
|
305
|
+
});
|
|
306
|
+
this.items.set(id, entity);
|
|
307
|
+
return entity;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
async delete(id: string): Promise<void> {
|
|
311
|
+
this.items.delete(id);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
`
|
|
315
|
+
},
|
|
316
|
+
// 6. Infrastructure Controller
|
|
317
|
+
{
|
|
318
|
+
filePath: import_node_path2.default.join(baseDir, "infrastructure", "controllers", `${kebab}.controller.ts`),
|
|
319
|
+
content: `import { Body, Controller, Get, Param, Post } from '@nestjs/common';
|
|
320
|
+
import { Create${pascal}UseCase } from '../../application/use-cases/create-${kebab}.use-case';
|
|
321
|
+
import { Find${pascal}UseCase } from '../../application/use-cases/find-${kebab}.use-case';
|
|
322
|
+
import { Create${pascal}Dto } from '../../application/dtos/create-${kebab}.dto';
|
|
323
|
+
|
|
324
|
+
@Controller('${kebab}')
|
|
325
|
+
export class ${pascal}Controller {
|
|
326
|
+
constructor(
|
|
327
|
+
private readonly createUseCase: Create${pascal}UseCase,
|
|
328
|
+
private readonly findUseCase: Find${pascal}UseCase
|
|
329
|
+
) {}
|
|
330
|
+
|
|
331
|
+
@Post()
|
|
332
|
+
create(@Body() dto: Create${pascal}Dto) {
|
|
333
|
+
return this.createUseCase.execute(dto);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
@Get(':id')
|
|
337
|
+
findOne(@Param('id') id: string) {
|
|
338
|
+
return this.findUseCase.execute(id);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
`
|
|
342
|
+
},
|
|
343
|
+
// 7. NestJS Module
|
|
344
|
+
{
|
|
345
|
+
filePath: import_node_path2.default.join(baseDir, `${kebab}.module.ts`),
|
|
346
|
+
content: `import { Module } from '@nestjs/common';
|
|
347
|
+
import { ${pascal}Controller } from './infrastructure/controllers/${kebab}.controller';
|
|
348
|
+
import { Create${pascal}UseCase } from './application/use-cases/create-${kebab}.use-case';
|
|
349
|
+
import { Find${pascal}UseCase } from './application/use-cases/find-${kebab}.use-case';
|
|
350
|
+
import { ${pascal.toUpperCase()}_REPOSITORY } from './domain/repositories/${kebab}.repository.interface';
|
|
351
|
+
import { InMemory${pascal}Repository } from './infrastructure/repositories/in-memory-${kebab}.repository';
|
|
352
|
+
|
|
353
|
+
@Module({
|
|
354
|
+
controllers: [${pascal}Controller],
|
|
355
|
+
providers: [
|
|
356
|
+
Create${pascal}UseCase,
|
|
357
|
+
Find${pascal}UseCase,
|
|
358
|
+
{
|
|
359
|
+
provide: ${pascal.toUpperCase()}_REPOSITORY,
|
|
360
|
+
useClass: InMemory${pascal}Repository,
|
|
361
|
+
},
|
|
362
|
+
],
|
|
363
|
+
exports: [Create${pascal}UseCase, Find${pascal}UseCase, ${pascal.toUpperCase()}_REPOSITORY],
|
|
364
|
+
})
|
|
365
|
+
export class ${pascal}Module {}
|
|
366
|
+
`
|
|
367
|
+
}
|
|
368
|
+
];
|
|
369
|
+
logger.info(`Generating Clean Architecture module for "${kebab}" at ${baseDir}...`);
|
|
370
|
+
for (const file of files) {
|
|
371
|
+
if (dryRun) {
|
|
372
|
+
logger.info(`[dry-run] Would create: ${import_node_path2.default.relative(cwd, file.filePath)}`);
|
|
373
|
+
} else {
|
|
374
|
+
await import_promises2.default.mkdir(import_node_path2.default.dirname(file.filePath), { recursive: true });
|
|
375
|
+
await import_promises2.default.writeFile(file.filePath, file.content, "utf-8");
|
|
376
|
+
logger.step(`Created ${import_node_path2.default.relative(cwd, file.filePath)}`);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
logger.success(`Clean Architecture structure for "${pascal}Module" generated!`);
|
|
380
|
+
logger.info(`Remember to import ${pascal}Module in your AppModule.`);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// src/core/diagnostics/doctor.ts
|
|
384
|
+
var import_promises3 = __toESM(require("fs/promises"));
|
|
385
|
+
var import_node_path3 = __toESM(require("path"));
|
|
386
|
+
var import_picocolors2 = __toESM(require("picocolors"));
|
|
387
|
+
async function runDoctor(cwd = process.cwd()) {
|
|
388
|
+
const report = {
|
|
389
|
+
isNestProject: false,
|
|
390
|
+
issues: [],
|
|
391
|
+
recommendations: []
|
|
392
|
+
};
|
|
393
|
+
logger.info("Running nest-tools doctor diagnostics...\n");
|
|
394
|
+
const pkgPath = import_node_path3.default.join(cwd, "package.json");
|
|
395
|
+
let pkg = null;
|
|
396
|
+
try {
|
|
397
|
+
const pkgRaw = await import_promises3.default.readFile(pkgPath, "utf-8");
|
|
398
|
+
pkg = JSON.parse(pkgRaw);
|
|
399
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
400
|
+
if (deps["@nestjs/core"] || deps["@nestjs/common"]) {
|
|
401
|
+
report.isNestProject = true;
|
|
402
|
+
console.log(import_picocolors2.default.green("\u2714") + " NestJS dependencies detected in package.json");
|
|
403
|
+
} else {
|
|
404
|
+
report.issues.push("Could not find @nestjs/core or @nestjs/common in package.json.");
|
|
405
|
+
}
|
|
406
|
+
} catch {
|
|
407
|
+
report.issues.push("No package.json found in current working directory.");
|
|
408
|
+
}
|
|
409
|
+
try {
|
|
410
|
+
await import_promises3.default.access(import_node_path3.default.join(cwd, "nest-cli.json"));
|
|
411
|
+
console.log(import_picocolors2.default.green("\u2714") + " nest-cli.json configuration found");
|
|
412
|
+
} catch {
|
|
413
|
+
report.recommendations.push('nest-cli.json is missing. Consider generating one with "nest new".');
|
|
414
|
+
}
|
|
415
|
+
try {
|
|
416
|
+
await import_promises3.default.access(import_node_path3.default.join(cwd, "tsconfig.json"));
|
|
417
|
+
console.log(import_picocolors2.default.green("\u2714") + " tsconfig.json found");
|
|
418
|
+
} catch {
|
|
419
|
+
report.issues.push("tsconfig.json is missing in project root.");
|
|
420
|
+
}
|
|
421
|
+
try {
|
|
422
|
+
await import_promises3.default.access(import_node_path3.default.join(cwd, ".env"));
|
|
423
|
+
try {
|
|
424
|
+
await import_promises3.default.access(import_node_path3.default.join(cwd, ".env.example"));
|
|
425
|
+
console.log(import_picocolors2.default.green("\u2714") + " .env and .env.example are present");
|
|
426
|
+
} catch {
|
|
427
|
+
report.recommendations.push(
|
|
428
|
+
".env exists but .env.example is missing. It is recommended to commit an example file."
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
} catch {
|
|
432
|
+
}
|
|
433
|
+
try {
|
|
434
|
+
const appModulePath = import_node_path3.default.join(cwd, "src", "app.module.ts");
|
|
435
|
+
const appModuleContent = await import_promises3.default.readFile(appModulePath, "utf-8");
|
|
436
|
+
const srcDir = import_node_path3.default.join(cwd, "src");
|
|
437
|
+
const entries = await import_promises3.default.readdir(srcDir, { withFileTypes: true });
|
|
438
|
+
for (const entry of entries) {
|
|
439
|
+
if (entry.isDirectory()) {
|
|
440
|
+
const potentialModule = `${entry.name}.module.ts`;
|
|
441
|
+
const moduleFilePath = import_node_path3.default.join(srcDir, entry.name, potentialModule);
|
|
442
|
+
try {
|
|
443
|
+
await import_promises3.default.access(moduleFilePath);
|
|
444
|
+
if (!appModuleContent.includes(potentialModule.replace(".ts", "")) && !appModuleContent.includes(entry.name)) {
|
|
445
|
+
report.recommendations.push(
|
|
446
|
+
`Module "${entry.name}" was found at src/${entry.name}/${potentialModule}, but might not be imported in app.module.ts.`
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
} catch {
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
} catch {
|
|
454
|
+
}
|
|
455
|
+
console.log("");
|
|
456
|
+
if (report.issues.length > 0) {
|
|
457
|
+
logger.error(`Found ${report.issues.length} issue(s):`);
|
|
458
|
+
for (const issue of report.issues) {
|
|
459
|
+
console.log(import_picocolors2.default.red(" \u2716 ") + issue);
|
|
460
|
+
}
|
|
461
|
+
} else {
|
|
462
|
+
logger.success("No critical issues found!");
|
|
463
|
+
}
|
|
464
|
+
if (report.recommendations.length > 0) {
|
|
465
|
+
logger.warn(`Found ${report.recommendations.length} recommendation(s):`);
|
|
466
|
+
for (const rec of report.recommendations) {
|
|
467
|
+
console.log(import_picocolors2.default.yellow(" \u279C ") + rec);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
return report;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// src/runtime/decorators/public.decorator.ts
|
|
474
|
+
var import_common = require("@nestjs/common");
|
|
475
|
+
var IS_PUBLIC_KEY = "isPublic";
|
|
476
|
+
var Public = () => (0, import_common.SetMetadata)(IS_PUBLIC_KEY, true);
|
|
477
|
+
|
|
478
|
+
// src/runtime/decorators/current-user.decorator.ts
|
|
479
|
+
var import_common2 = require("@nestjs/common");
|
|
480
|
+
var CurrentUser = (0, import_common2.createParamDecorator)(
|
|
481
|
+
(data, ctx) => {
|
|
482
|
+
const request = ctx.switchToHttp().getRequest();
|
|
483
|
+
const user = request.user;
|
|
484
|
+
if (!user) {
|
|
485
|
+
return null;
|
|
486
|
+
}
|
|
487
|
+
return data ? user[data] : user;
|
|
488
|
+
}
|
|
489
|
+
);
|
|
490
|
+
|
|
491
|
+
// src/runtime/interceptors/transform-response.interceptor.ts
|
|
492
|
+
var import_common3 = require("@nestjs/common");
|
|
493
|
+
var import_operators = require("rxjs/operators");
|
|
494
|
+
var TransformResponseInterceptor = class {
|
|
495
|
+
intercept(context, next) {
|
|
496
|
+
const ctx = context.switchToHttp();
|
|
497
|
+
const response = ctx.getResponse();
|
|
498
|
+
const statusCode = response?.statusCode ?? 200;
|
|
499
|
+
return next.handle().pipe(
|
|
500
|
+
(0, import_operators.map)((data) => ({
|
|
501
|
+
statusCode,
|
|
502
|
+
success: statusCode >= 200 && statusCode < 400,
|
|
503
|
+
data,
|
|
504
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
505
|
+
}))
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
TransformResponseInterceptor = __decorateClass([
|
|
510
|
+
(0, import_common3.Injectable)()
|
|
511
|
+
], TransformResponseInterceptor);
|
|
512
|
+
|
|
513
|
+
// src/runtime/pagination/pagination.dto.ts
|
|
514
|
+
var PaginationQueryDto = class {
|
|
515
|
+
page = 1;
|
|
516
|
+
limit = 10;
|
|
517
|
+
sortBy;
|
|
518
|
+
order = "ASC";
|
|
519
|
+
search;
|
|
520
|
+
get skip() {
|
|
521
|
+
const p = Number(this.page) || 1;
|
|
522
|
+
const l = Number(this.limit) || 10;
|
|
523
|
+
return (Math.max(p, 1) - 1) * Math.max(l, 1);
|
|
524
|
+
}
|
|
525
|
+
get take() {
|
|
526
|
+
return Math.max(Number(this.limit) || 10, 1);
|
|
527
|
+
}
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
// src/runtime/pagination/pagination.helper.ts
|
|
531
|
+
function createPaginatedResponse(items, totalItems, page = 1, limit = 10) {
|
|
532
|
+
const safePage = Math.max(Number(page) || 1, 1);
|
|
533
|
+
const safeLimit = Math.max(Number(limit) || 10, 1);
|
|
534
|
+
const totalPages = Math.ceil(totalItems / safeLimit) || 1;
|
|
535
|
+
return {
|
|
536
|
+
data: items,
|
|
537
|
+
meta: {
|
|
538
|
+
itemCount: items.length,
|
|
539
|
+
totalItems,
|
|
540
|
+
itemsPerPage: safeLimit,
|
|
541
|
+
totalPages,
|
|
542
|
+
currentPage: safePage,
|
|
543
|
+
hasNextPage: safePage < totalPages,
|
|
544
|
+
hasPreviousPage: safePage > 1
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
549
|
+
0 && (module.exports = {
|
|
550
|
+
CurrentUser,
|
|
551
|
+
DEFAULT_CONFIG,
|
|
552
|
+
IS_PUBLIC_KEY,
|
|
553
|
+
PaginationQueryDto,
|
|
554
|
+
Public,
|
|
555
|
+
TransformResponseInterceptor,
|
|
556
|
+
createDefaultConfig,
|
|
557
|
+
createPaginatedResponse,
|
|
558
|
+
generateCleanArchitecture,
|
|
559
|
+
generateResource,
|
|
560
|
+
loadConfig,
|
|
561
|
+
logger,
|
|
562
|
+
runCommand,
|
|
563
|
+
runDoctor,
|
|
564
|
+
toCamelCase,
|
|
565
|
+
toKebabCase,
|
|
566
|
+
toPascalCase
|
|
567
|
+
});
|
|
568
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/core/runner/command-runner.ts","../src/utils/logger.ts","../src/core/config/index.ts","../src/utils/strings.ts","../src/core/generator/generate-resource.ts","../src/core/generator/generate-clean-architecture.ts","../src/core/diagnostics/doctor.ts","../src/runtime/decorators/public.decorator.ts","../src/runtime/decorators/current-user.decorator.ts","../src/runtime/interceptors/transform-response.interceptor.ts","../src/runtime/pagination/pagination.dto.ts","../src/runtime/pagination/pagination.helper.ts"],"sourcesContent":["// Core Generators\nexport {\n generateResource,\n type GenerateResourceOptions,\n} from './core/generator/generate-resource';\nexport {\n generateCleanArchitecture,\n type GenerateCleanArchitectureOptions,\n} from './core/generator/generate-clean-architecture';\n\n// Runner & Utils\nexport { runCommand, type RunCommandOptions } from './core/runner/command-runner';\nexport { logger } from './utils/logger';\nexport * from './utils/strings';\n\n// Config\nexport {\n loadConfig,\n createDefaultConfig,\n type NestToolsConfig,\n DEFAULT_CONFIG,\n} from './core/config';\n\n// Diagnostics\nexport { runDoctor, type DoctorReport } from './core/diagnostics/doctor';\n\n// Runtime Decorators\nexport { Public, IS_PUBLIC_KEY } from './runtime/decorators/public.decorator';\nexport { CurrentUser } from './runtime/decorators/current-user.decorator';\n\n// Runtime Interceptors\nexport {\n TransformResponseInterceptor,\n type StandardApiResponse,\n} from './runtime/interceptors/transform-response.interceptor';\n\n// Runtime Pagination\nexport { PaginationQueryDto, type SortOrder } from './runtime/pagination/pagination.dto';\nexport {\n createPaginatedResponse,\n type PaginatedResult,\n type PaginationMeta,\n} from './runtime/pagination/pagination.helper';\n","import { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { logger } from '../../utils/logger';\n\nconst execAsync = promisify(exec);\n\nexport interface RunCommandOptions {\n cwd?: string;\n dryRun?: boolean;\n silent?: boolean;\n}\n\nexport async function runCommand(\n command: string,\n options: RunCommandOptions = {}\n): Promise<{ stdout: string; stderr: string }> {\n const { cwd = process.cwd(), dryRun = false, silent = false } = options;\n\n if (dryRun) {\n logger.info(`[dry-run] Would execute: ${command}`);\n return { stdout: '', stderr: '' };\n }\n\n if (!silent) {\n logger.step(command);\n }\n\n try {\n const result = await execAsync(command, { cwd });\n return result;\n } catch (error: any) {\n const message = error.stderr || error.message || 'Command failed';\n throw new Error(`Failed to execute: \"${command}\"\\n${message}`);\n }\n}\n","import pc from 'picocolors';\n\nexport const logger = {\n info: (msg: string) => console.log(pc.cyan('ℹ ') + msg),\n success: (msg: string) => console.log(pc.green('✔ ') + pc.bold(msg)),\n warn: (msg: string) => console.log(pc.yellow('⚠ ') + msg),\n error: (msg: string) => console.error(pc.red('✖ ') + pc.bold(msg)),\n step: (step: string, detail?: string) => {\n console.log(pc.blue('▶ ') + pc.bold(step) + (detail ? pc.dim(` (${detail})`) : ''));\n },\n};\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nexport interface NestToolsConfig {\n spec?: boolean;\n flat?: boolean;\n architecture?: 'standard' | 'clean';\n packageManager?: 'npm' | 'yarn' | 'pnpm';\n}\n\nexport const DEFAULT_CONFIG: NestToolsConfig = {\n spec: false,\n flat: false,\n architecture: 'standard',\n packageManager: 'npm',\n};\n\nconst CONFIG_FILENAMES = ['nest-tools.json', '.nesttoolsrc', '.nesttoolsrc.json'];\n\nexport async function loadConfig(cwd = process.cwd()): Promise<NestToolsConfig> {\n for (const filename of CONFIG_FILENAMES) {\n const configPath = path.join(cwd, filename);\n try {\n const data = await fs.readFile(configPath, 'utf-8');\n const parsed = JSON.parse(data);\n return { ...DEFAULT_CONFIG, ...parsed };\n } catch {\n // Continue searching\n }\n }\n\n return DEFAULT_CONFIG;\n}\n\nexport async function createDefaultConfig(cwd = process.cwd()): Promise<string> {\n const targetPath = path.join(cwd, 'nest-tools.json');\n const content = JSON.stringify(DEFAULT_CONFIG, null, 2) + '\\n';\n await fs.writeFile(targetPath, content, 'utf-8');\n return targetPath;\n}\n","export function toKebabCase(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .replace(/[\\s_]+/g, '-')\n .toLowerCase();\n}\n\nexport function toPascalCase(str: string): string {\n return toKebabCase(str)\n .split('-')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join('');\n}\n\nexport function toCamelCase(str: string): string {\n const pascal = toPascalCase(str);\n return pascal.charAt(0).toLowerCase() + pascal.slice(1);\n}\n","import { runCommand } from '../runner/command-runner';\nimport { loadConfig } from '../config';\nimport { logger } from '../../utils/logger';\nimport { toKebabCase } from '../../utils/strings';\n\nexport interface GenerateResourceOptions {\n name: string;\n spec?: boolean;\n flat?: boolean;\n dryRun?: boolean;\n cwd?: string;\n}\n\nexport async function generateResource(options: GenerateResourceOptions): Promise<void> {\n const config = await loadConfig(options.cwd);\n const rawName = options.name.trim();\n const name = toKebabCase(rawName);\n\n const spec = options.spec ?? config.spec ?? false;\n const flat = options.flat ?? config.flat ?? false;\n const dryRun = options.dryRun ?? false;\n const cwd = options.cwd ?? process.cwd();\n\n const specFlag = spec ? '' : '--no-spec';\n const flatFlag = flat ? '--flat' : '';\n\n const commands = [\n `nest g mo ${name} ${flatFlag}`.trim(),\n `nest g co ${name} ${specFlag} ${flatFlag}`.trim(),\n `nest g s ${name} ${specFlag} ${flatFlag}`.trim(),\n ];\n\n logger.info(`Generating resource \"${name}\" (spec: ${spec ? 'yes' : 'no'}, flat: ${flat ? 'yes' : 'no'})...`);\n\n for (const cmd of commands) {\n await runCommand(cmd, { cwd, dryRun });\n }\n\n logger.success(`Resource \"${name}\" generated successfully.`);\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { logger } from '../../utils/logger';\nimport { toCamelCase, toKebabCase, toPascalCase } from '../../utils/strings';\n\nexport interface GenerateCleanArchitectureOptions {\n name: string;\n dryRun?: boolean;\n cwd?: string;\n}\n\nexport async function generateCleanArchitecture(\n options: GenerateCleanArchitectureOptions\n): Promise<void> {\n const { dryRun = false, cwd = process.cwd() } = options;\n const rawName = options.name.trim();\n const kebab = toKebabCase(rawName);\n const pascal = toPascalCase(rawName);\n const camel = toCamelCase(rawName);\n\n const baseDir = path.join(cwd, 'src', kebab);\n\n const files: { filePath: string; content: string }[] = [\n // 1. Domain Entity\n {\n filePath: path.join(baseDir, 'domain', 'entities', `${kebab}.entity.ts`),\n content: `export class ${pascal}Entity {\n id!: string;\n name!: string;\n createdAt!: Date;\n updatedAt!: Date;\n\n constructor(partial: Partial<${pascal}Entity>) {\n Object.assign(this, partial);\n }\n}\n`,\n },\n // 2. Domain Repository Interface & Token\n {\n filePath: path.join(baseDir, 'domain', 'repositories', `${kebab}.repository.interface.ts`),\n content: `import { ${pascal}Entity } from '../entities/${kebab}.entity';\n\nexport const ${pascal.toUpperCase()}_REPOSITORY = Symbol('${pascal.toUpperCase()}_REPOSITORY');\n\nexport interface ${pascal}Repository {\n findById(id: string): Promise<${pascal}Entity | null>;\n findAll(): Promise<${pascal}Entity[]>;\n create(data: Partial<${pascal}Entity>): Promise<${pascal}Entity>;\n delete(id: string): Promise<void>;\n}\n`,\n },\n // 3. Application DTOs\n {\n filePath: path.join(baseDir, 'application', 'dtos', `create-${kebab}.dto.ts`),\n content: `export class Create${pascal}Dto {\n name!: string;\n}\n`,\n },\n {\n filePath: path.join(baseDir, 'application', 'dtos', `update-${kebab}.dto.ts`),\n content: `export class Update${pascal}Dto {\n name?: string;\n}\n`,\n },\n // 4. Application Use Cases\n {\n filePath: path.join(baseDir, 'application', 'use-cases', `create-${kebab}.use-case.ts`),\n content: `import { Inject, Injectable } from '@nestjs/common';\nimport {\n ${pascal}Repository,\n ${pascal.toUpperCase()}_REPOSITORY,\n} from '../../domain/repositories/${kebab}.repository.interface';\nimport { ${pascal}Entity } from '../../domain/entities/${kebab}.entity';\nimport { Create${pascal}Dto } from '../dtos/create-${kebab}.dto';\n\n@Injectable()\nexport class Create${pascal}UseCase {\n constructor(\n @Inject(${pascal.toUpperCase()}_REPOSITORY)\n private readonly repository: ${pascal}Repository\n ) {}\n\n async execute(dto: Create${pascal}Dto): Promise<${pascal}Entity> {\n return this.repository.create({\n name: dto.name,\n createdAt: new Date(),\n updatedAt: new Date(),\n });\n }\n}\n`,\n },\n {\n filePath: path.join(baseDir, 'application', 'use-cases', `find-${kebab}.use-case.ts`),\n content: `import { Inject, Injectable, NotFoundException } from '@nestjs/common';\nimport {\n ${pascal}Repository,\n ${pascal.toUpperCase()}_REPOSITORY,\n} from '../../domain/repositories/${kebab}.repository.interface';\nimport { ${pascal}Entity } from '../../domain/entities/${kebab}.entity';\n\n@Injectable()\nexport class Find${pascal}UseCase {\n constructor(\n @Inject(${pascal.toUpperCase()}_REPOSITORY)\n private readonly repository: ${pascal}Repository\n ) {}\n\n async execute(id: string): Promise<${pascal}Entity> {\n const item = await this.repository.findById(id);\n if (!item) {\n throw new NotFoundException(\\`${pascal} with id \"\\${id}\" not found\\`);\n }\n return item;\n }\n}\n`,\n },\n // 5. Infrastructure In-Memory Repository\n {\n filePath: path.join(\n baseDir,\n 'infrastructure',\n 'repositories',\n `in-memory-${kebab}.repository.ts`\n ),\n content: `import { Injectable } from '@nestjs/common';\nimport {\n ${pascal}Repository,\n} from '../../domain/repositories/${kebab}.repository.interface';\nimport { ${pascal}Entity } from '../../domain/entities/${kebab}.entity';\n\n@Injectable()\nexport class InMemory${pascal}Repository implements ${pascal}Repository {\n private readonly items: Map<string, ${pascal}Entity> = new Map();\n\n async findById(id: string): Promise<${pascal}Entity | null> {\n return this.items.get(id) || null;\n }\n\n async findAll(): Promise<${pascal}Entity[]> {\n return Array.from(this.items.values());\n }\n\n async create(data: Partial<${pascal}Entity>): Promise<${pascal}Entity> {\n const id = (this.items.size + 1).toString();\n const entity = new ${pascal}Entity({\n id,\n name: data.name ?? 'Untitled',\n createdAt: data.createdAt ?? new Date(),\n updatedAt: data.updatedAt ?? new Date(),\n });\n this.items.set(id, entity);\n return entity;\n }\n\n async delete(id: string): Promise<void> {\n this.items.delete(id);\n }\n}\n`,\n },\n // 6. Infrastructure Controller\n {\n filePath: path.join(baseDir, 'infrastructure', 'controllers', `${kebab}.controller.ts`),\n content: `import { Body, Controller, Get, Param, Post } from '@nestjs/common';\nimport { Create${pascal}UseCase } from '../../application/use-cases/create-${kebab}.use-case';\nimport { Find${pascal}UseCase } from '../../application/use-cases/find-${kebab}.use-case';\nimport { Create${pascal}Dto } from '../../application/dtos/create-${kebab}.dto';\n\n@Controller('${kebab}')\nexport class ${pascal}Controller {\n constructor(\n private readonly createUseCase: Create${pascal}UseCase,\n private readonly findUseCase: Find${pascal}UseCase\n ) {}\n\n @Post()\n create(@Body() dto: Create${pascal}Dto) {\n return this.createUseCase.execute(dto);\n }\n\n @Get(':id')\n findOne(@Param('id') id: string) {\n return this.findUseCase.execute(id);\n }\n}\n`,\n },\n // 7. NestJS Module\n {\n filePath: path.join(baseDir, `${kebab}.module.ts`),\n content: `import { Module } from '@nestjs/common';\nimport { ${pascal}Controller } from './infrastructure/controllers/${kebab}.controller';\nimport { Create${pascal}UseCase } from './application/use-cases/create-${kebab}.use-case';\nimport { Find${pascal}UseCase } from './application/use-cases/find-${kebab}.use-case';\nimport { ${pascal.toUpperCase()}_REPOSITORY } from './domain/repositories/${kebab}.repository.interface';\nimport { InMemory${pascal}Repository } from './infrastructure/repositories/in-memory-${kebab}.repository';\n\n@Module({\n controllers: [${pascal}Controller],\n providers: [\n Create${pascal}UseCase,\n Find${pascal}UseCase,\n {\n provide: ${pascal.toUpperCase()}_REPOSITORY,\n useClass: InMemory${pascal}Repository,\n },\n ],\n exports: [Create${pascal}UseCase, Find${pascal}UseCase, ${pascal.toUpperCase()}_REPOSITORY],\n})\nexport class ${pascal}Module {}\n`,\n },\n ];\n\n logger.info(`Generating Clean Architecture module for \"${kebab}\" at ${baseDir}...`);\n\n for (const file of files) {\n if (dryRun) {\n logger.info(`[dry-run] Would create: ${path.relative(cwd, file.filePath)}`);\n } else {\n await fs.mkdir(path.dirname(file.filePath), { recursive: true });\n await fs.writeFile(file.filePath, file.content, 'utf-8');\n logger.step(`Created ${path.relative(cwd, file.filePath)}`);\n }\n }\n\n logger.success(`Clean Architecture structure for \"${pascal}Module\" generated!`);\n logger.info(`Remember to import ${pascal}Module in your AppModule.`);\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport pc from 'picocolors';\nimport { logger } from '../../utils/logger';\n\nexport interface DoctorReport {\n isNestProject: boolean;\n issues: string[];\n recommendations: string[];\n}\n\nexport async function runDoctor(cwd = process.cwd()): Promise<DoctorReport> {\n const report: DoctorReport = {\n isNestProject: false,\n issues: [],\n recommendations: [],\n };\n\n logger.info('Running nest-tools doctor diagnostics...\\n');\n\n // 1. Check package.json\n const pkgPath = path.join(cwd, 'package.json');\n let pkg: any = null;\n try {\n const pkgRaw = await fs.readFile(pkgPath, 'utf-8');\n pkg = JSON.parse(pkgRaw);\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n if (deps['@nestjs/core'] || deps['@nestjs/common']) {\n report.isNestProject = true;\n console.log(pc.green('✔') + ' NestJS dependencies detected in package.json');\n } else {\n report.issues.push('Could not find @nestjs/core or @nestjs/common in package.json.');\n }\n } catch {\n report.issues.push('No package.json found in current working directory.');\n }\n\n // 2. Check nest-cli.json\n try {\n await fs.access(path.join(cwd, 'nest-cli.json'));\n console.log(pc.green('✔') + ' nest-cli.json configuration found');\n } catch {\n report.recommendations.push('nest-cli.json is missing. Consider generating one with \"nest new\".');\n }\n\n // 3. Check tsconfig.json\n try {\n await fs.access(path.join(cwd, 'tsconfig.json'));\n console.log(pc.green('✔') + ' tsconfig.json found');\n } catch {\n report.issues.push('tsconfig.json is missing in project root.');\n }\n\n // 4. Check .env and .env.example\n try {\n await fs.access(path.join(cwd, '.env'));\n try {\n await fs.access(path.join(cwd, '.env.example'));\n console.log(pc.green('✔') + ' .env and .env.example are present');\n } catch {\n report.recommendations.push(\n '.env exists but .env.example is missing. It is recommended to commit an example file.'\n );\n }\n } catch {\n // No .env, ignore\n }\n\n // 5. Module check (look for orphan modules)\n try {\n const appModulePath = path.join(cwd, 'src', 'app.module.ts');\n const appModuleContent = await fs.readFile(appModulePath, 'utf-8');\n\n const srcDir = path.join(cwd, 'src');\n const entries = await fs.readdir(srcDir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n const potentialModule = `${entry.name}.module.ts`;\n const moduleFilePath = path.join(srcDir, entry.name, potentialModule);\n try {\n await fs.access(moduleFilePath);\n if (!appModuleContent.includes(potentialModule.replace('.ts', '')) &&\n !appModuleContent.includes(entry.name)) {\n report.recommendations.push(\n `Module \"${entry.name}\" was found at src/${entry.name}/${potentialModule}, but might not be imported in app.module.ts.`\n );\n }\n } catch {\n // not a module dir\n }\n }\n }\n } catch {\n // app.module.ts doesn't exist or isn't accessible\n }\n\n console.log('');\n if (report.issues.length > 0) {\n logger.error(`Found ${report.issues.length} issue(s):`);\n for (const issue of report.issues) {\n console.log(pc.red(' ✖ ') + issue);\n }\n } else {\n logger.success('No critical issues found!');\n }\n\n if (report.recommendations.length > 0) {\n logger.warn(`Found ${report.recommendations.length} recommendation(s):`);\n for (const rec of report.recommendations) {\n console.log(pc.yellow(' ➜ ') + rec);\n }\n }\n\n return report;\n}\n","import { SetMetadata } from '@nestjs/common';\n\nexport const IS_PUBLIC_KEY = 'isPublic';\n\n/**\n * Decorator to mark routes as public, skipping global authentication guards.\n *\n * @example\n * ```typescript\n * @Public()\n * @Get('health')\n * checkHealth() {\n * return { status: 'ok' };\n * }\n * ```\n */\nexport const Public = () => SetMetadata(IS_PUBLIC_KEY, true);\n","import { createParamDecorator, ExecutionContext } from '@nestjs/common';\n\n/**\n * Parameter decorator to easily retrieve the authenticated user from the Request object.\n *\n * @example\n * ```typescript\n * @Get('profile')\n * getProfile(@CurrentUser() user: UserEntity) {\n * return user;\n * }\n *\n * @Get('id')\n * getId(@CurrentUser('id') userId: string) {\n * return userId;\n * }\n * ```\n */\nexport const CurrentUser = createParamDecorator(\n (data: string | undefined, ctx: ExecutionContext) => {\n const request = ctx.switchToHttp().getRequest();\n const user = request.user;\n\n if (!user) {\n return null;\n }\n\n return data ? user[data] : user;\n }\n);\n","import {\n Injectable,\n NestInterceptor,\n ExecutionContext,\n CallHandler,\n} from '@nestjs/common';\nimport { Observable } from 'rxjs';\nimport { map } from 'rxjs/operators';\n\nexport interface StandardApiResponse<T> {\n statusCode: number;\n success: boolean;\n data: T;\n timestamp: string;\n}\n\n/**\n * Global or controller interceptor that wraps successful responses in a standard JSON envelope.\n *\n * @example\n * ```typescript\n * // In main.ts\n * app.useGlobalInterceptors(new TransformResponseInterceptor());\n * ```\n */\n@Injectable()\nexport class TransformResponseInterceptor<T>\n implements NestInterceptor<T, StandardApiResponse<T>>\n{\n intercept(\n context: ExecutionContext,\n next: CallHandler\n ): Observable<StandardApiResponse<T>> {\n const ctx = context.switchToHttp();\n const response = ctx.getResponse();\n const statusCode = response?.statusCode ?? 200;\n\n return next.handle().pipe(\n map((data) => ({\n statusCode,\n success: statusCode >= 200 && statusCode < 400,\n data,\n timestamp: new Date().toISOString(),\n }))\n );\n }\n}\n","export type SortOrder = 'ASC' | 'DESC' | 'asc' | 'desc';\n\nexport class PaginationQueryDto {\n page?: number = 1;\n limit?: number = 10;\n sortBy?: string;\n order?: SortOrder = 'ASC';\n search?: string;\n\n get skip(): number {\n const p = Number(this.page) || 1;\n const l = Number(this.limit) || 10;\n return (Math.max(p, 1) - 1) * Math.max(l, 1);\n }\n\n get take(): number {\n return Math.max(Number(this.limit) || 10, 1);\n }\n}\n","export interface PaginationMeta {\n itemCount: number;\n totalItems: number;\n itemsPerPage: number;\n totalPages: number;\n currentPage: number;\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n}\n\nexport interface PaginatedResult<T> {\n data: T[];\n meta: PaginationMeta;\n}\n\n/**\n * Creates a paginated response object with calculated metadata.\n */\nexport function createPaginatedResponse<T>(\n items: T[],\n totalItems: number,\n page = 1,\n limit = 10\n): PaginatedResult<T> {\n const safePage = Math.max(Number(page) || 1, 1);\n const safeLimit = Math.max(Number(limit) || 10, 1);\n const totalPages = Math.ceil(totalItems / safeLimit) || 1;\n\n return {\n data: items,\n meta: {\n itemCount: items.length,\n totalItems,\n itemsPerPage: safeLimit,\n totalPages,\n currentPage: safePage,\n hasNextPage: safePage < totalPages,\n hasPreviousPage: safePage > 1,\n },\n };\n}\n"],"mappings":"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","names":["pc","path","fs","import_promises","import_node_path","path","fs","import_promises","import_node_path","import_picocolors","path","fs","pc","import_common","import_common"]}
|