@neohm/nh-cli 1.1.0 → 1.1.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/README.md +3 -4
- package/package.json +1 -1
- package/src/commands/gen.js +1 -8
- package/src/lib/templates.js +20 -43
package/README.md
CHANGED
|
@@ -67,7 +67,6 @@ shape/
|
|
|
67
67
|
es6.classes.ts # barrel of controllers/services/jobs/subscribers
|
|
68
68
|
controllers/shape.controller.ts
|
|
69
69
|
dtos/add.shape.data.dto.ts
|
|
70
|
-
dtos/shape.list.filter.dto.ts
|
|
71
70
|
entities/shape.entity.ts
|
|
72
71
|
libraries/shape.data.processor.ts
|
|
73
72
|
libraries/shape.list.processor.ts
|
|
@@ -91,14 +90,14 @@ created spreading `baseJobConstants` / `baseEntityConstants` /
|
|
|
91
90
|
Generated artifacts extend the `@neohm/nestend` base classes:
|
|
92
91
|
|
|
93
92
|
- Entity → `CommonEntity` (with an empty `attributes` jsonb column)
|
|
94
|
-
- DTO → `
|
|
93
|
+
- DTO → `CommonDataDto`
|
|
95
94
|
- Data processor → `CommonDataProcessor` (`process()` → `validate()` → `set()`)
|
|
96
|
-
-
|
|
97
|
-
- Listing processor → `CommonListProcessor` (column allowlist config, `id` default sort, and an example custom filter)
|
|
95
|
+
- Listing processor → `CommonListProcessor` (column allowlist config, `id` default sort). It takes `CommonListFilterDto` directly — no per-list DTO is generated, since paging, sorting, filters and free-text search all live on the base DTO and the filterable columns are declared in the processor's `columns` config.
|
|
98
96
|
|
|
99
97
|
When both a controller and a listing processor are generated, the controller
|
|
100
98
|
ships with a `POST list` endpoint that runs the listing processor (with
|
|
101
99
|
`SqlService` injected via the constructor).
|
|
100
|
+
|
|
102
101
|
- Migration → `MigrationUtility`
|
|
103
102
|
- Seed → `SeederUtility`
|
|
104
103
|
|
package/package.json
CHANGED
package/src/commands/gen.js
CHANGED
|
@@ -194,7 +194,7 @@ async function gen() {
|
|
|
194
194
|
report(writeFile(procPath, tpl.processor(entityName)), procPath, paths.root);
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
// 6. Optional: listing processor (
|
|
197
|
+
// 6. Optional: listing processor (takes CommonListFilterDto directly) ------
|
|
198
198
|
const { listProcessor } = await inquirer.prompt([
|
|
199
199
|
{
|
|
200
200
|
type: "confirm",
|
|
@@ -205,13 +205,6 @@ async function gen() {
|
|
|
205
205
|
]);
|
|
206
206
|
|
|
207
207
|
if (listProcessor) {
|
|
208
|
-
const listDtoPath = path.join(moduleDir, "dtos", n.listFilterDtoFile);
|
|
209
|
-
report(
|
|
210
|
-
writeFile(listDtoPath, tpl.listFilterDto(entityName)),
|
|
211
|
-
listDtoPath,
|
|
212
|
-
paths.root,
|
|
213
|
-
);
|
|
214
|
-
|
|
215
208
|
const listProcPath = path.join(moduleDir, "libraries", n.listProcessorFile);
|
|
216
209
|
report(
|
|
217
210
|
writeFile(listProcPath, tpl.listProcessor(entityName, tableName)),
|
package/src/lib/templates.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
|
-
const {
|
|
3
|
+
const {
|
|
4
|
+
toDotCase,
|
|
5
|
+
toPascalCase,
|
|
6
|
+
toKebabCase,
|
|
7
|
+
toCamelCase,
|
|
8
|
+
} = require("./naming");
|
|
4
9
|
|
|
5
10
|
/**
|
|
6
11
|
* Code templates. All generated code imports shared base classes from the
|
|
7
12
|
* published library `@neohm/nestend` (verified exports: CommonEntity,
|
|
8
|
-
*
|
|
13
|
+
* CommonDataDto, CommonDataProcessor, MigrationUtility, SeederUtility, etc.)
|
|
9
14
|
* and matches the dot.separated filename / PascalCase class conventions used
|
|
10
15
|
* across nestjs-boilerplate.
|
|
11
16
|
*/
|
|
@@ -30,8 +35,6 @@ function names(base) {
|
|
|
30
35
|
dtoFile: `add.${dot}.data.dto.ts`,
|
|
31
36
|
processorClass: `${pascal}DataProcessor`,
|
|
32
37
|
processorFile: `${dot}.data.processor.ts`,
|
|
33
|
-
listFilterDtoClass: `${pascal}ListFilterDto`,
|
|
34
|
-
listFilterDtoFile: `${dot}.list.filter.dto.ts`,
|
|
35
38
|
listProcessorClass: `${pascal}ListProcessor`,
|
|
36
39
|
listProcessorFile: `${dot}.list.processor.ts`,
|
|
37
40
|
subscriberClass: `${pascal}Subscriber`,
|
|
@@ -78,8 +81,7 @@ export class ${n.controllerClass} {
|
|
|
78
81
|
}
|
|
79
82
|
return `import { Body, Controller, Post } from '@nestjs/common';
|
|
80
83
|
import { ApiTags } from '@nestjs/swagger';
|
|
81
|
-
import { SqlService } from '@neohm/nestend';
|
|
82
|
-
import { ${n.listFilterDtoClass} } from '../dtos/${n.dot}.list.filter.dto';
|
|
84
|
+
import { CommonListFilterDto, SqlService } from '@neohm/nestend';
|
|
83
85
|
import { ${n.listProcessorClass} } from '../libraries/${n.dot}.list.processor';
|
|
84
86
|
|
|
85
87
|
@ApiTags('${n.kebab}')
|
|
@@ -88,7 +90,7 @@ export class ${n.controllerClass} {
|
|
|
88
90
|
constructor(private readonly sqlService: SqlService) {}
|
|
89
91
|
|
|
90
92
|
@Post('list')
|
|
91
|
-
async list(@Body() body:
|
|
93
|
+
async list(@Body() body: CommonListFilterDto) {
|
|
92
94
|
return new ${n.listProcessorClass}(this.sqlService).process(body);
|
|
93
95
|
}
|
|
94
96
|
}
|
|
@@ -97,9 +99,9 @@ export class ${n.controllerClass} {
|
|
|
97
99
|
|
|
98
100
|
function dto(base) {
|
|
99
101
|
const n = names(base);
|
|
100
|
-
return `import {
|
|
102
|
+
return `import { CommonDataDto } from '@neohm/nestend';
|
|
101
103
|
|
|
102
|
-
export class ${n.dtoClass} extends
|
|
104
|
+
export class ${n.dtoClass} extends CommonDataDto {
|
|
103
105
|
// TODO: declare validated payload fields for ${n.pascal}.
|
|
104
106
|
}
|
|
105
107
|
`;
|
|
@@ -123,7 +125,7 @@ export class ${n.processorClass} extends CommonDataProcessor {
|
|
|
123
125
|
|
|
124
126
|
private async validate() {
|
|
125
127
|
// TODO: collect validation errors via this.addErrors({ column: 'message' }).
|
|
126
|
-
this.
|
|
128
|
+
this.raiseExceptionOnValidationFailure();
|
|
127
129
|
}
|
|
128
130
|
|
|
129
131
|
private async set() {
|
|
@@ -133,31 +135,21 @@ export class ${n.processorClass} extends CommonDataProcessor {
|
|
|
133
135
|
`;
|
|
134
136
|
}
|
|
135
137
|
|
|
136
|
-
function listFilterDto(base) {
|
|
137
|
-
const n = names(base);
|
|
138
|
-
return `import { CommonListFilterDto } from '@neohm/nestend';
|
|
139
|
-
import { Expose } from 'class-transformer';
|
|
140
|
-
import { IsOptional, IsString } from 'class-validator';
|
|
141
|
-
|
|
142
|
-
export class ${n.listFilterDtoClass} extends CommonListFilterDto {
|
|
143
|
-
@Expose()
|
|
144
|
-
@IsOptional()
|
|
145
|
-
@IsString()
|
|
146
|
-
custom_filter?: string;
|
|
147
|
-
}
|
|
148
|
-
`;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
138
|
function listProcessor(base, tableName) {
|
|
152
139
|
const n = names(base);
|
|
153
140
|
return `import {
|
|
154
141
|
CommonListFilterConfig,
|
|
142
|
+
CommonListFilterDto,
|
|
155
143
|
CommonListProcessor,
|
|
156
144
|
SortDirection,
|
|
157
145
|
SqlService,
|
|
158
146
|
} from '@neohm/nestend';
|
|
159
|
-
import { ${n.listFilterDtoClass} } from '../dtos/${n.dot}.list.filter.dto';
|
|
160
147
|
|
|
148
|
+
/**
|
|
149
|
+
* Lists / filters ${n.pascal}. The \`columns\` config below is the allowlist:
|
|
150
|
+
* an identifier must appear here before a caller can filter or sort on it.
|
|
151
|
+
* Mark a column \`searchable: true\` to include it in the free-text \`str\` sweep.
|
|
152
|
+
*/
|
|
161
153
|
export class ${n.listProcessorClass} extends CommonListProcessor {
|
|
162
154
|
protected config: CommonListFilterConfig = {
|
|
163
155
|
query: '${tableName} a',
|
|
@@ -173,25 +165,11 @@ export class ${n.listProcessorClass} extends CommonListProcessor {
|
|
|
173
165
|
super();
|
|
174
166
|
}
|
|
175
167
|
|
|
176
|
-
async process(payload:
|
|
168
|
+
async process(payload: CommonListFilterDto) {
|
|
177
169
|
this.payload = payload;
|
|
178
170
|
|
|
179
|
-
this.applyCustomFilters(payload);
|
|
180
|
-
|
|
181
171
|
return this.handle();
|
|
182
172
|
}
|
|
183
|
-
|
|
184
|
-
private async applyCustomFilters(payload: ${n.listFilterDtoClass}) {
|
|
185
|
-
this.applyCustomFilter(payload.custom_filter);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
private async applyCustomFilter(custom_filter: string) {
|
|
189
|
-
if (!custom_filter) return;
|
|
190
|
-
|
|
191
|
-
// Example of a hand-rolled condition beyond the config-driven filters.
|
|
192
|
-
// TODO: replace test_column with a real filterable column of ${n.pascal}.
|
|
193
|
-
this.conditions.push(\`test_column ilike '%\${custom_filter}%'\`);
|
|
194
|
-
}
|
|
195
173
|
}
|
|
196
174
|
`;
|
|
197
175
|
}
|
|
@@ -403,7 +381,6 @@ module.exports = {
|
|
|
403
381
|
controller,
|
|
404
382
|
dto,
|
|
405
383
|
processor,
|
|
406
|
-
listFilterDto,
|
|
407
384
|
listProcessor,
|
|
408
385
|
subscriber,
|
|
409
386
|
job,
|