@apso/cli 0.43.2 → 0.43.4
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.
|
@@ -66,6 +66,15 @@ class Generate extends base_command_1.default {
|
|
|
66
66
|
console.log("[apso] No entities found in .apsorc — nothing to generate. Check that the file exists and defines an `entities` array.");
|
|
67
67
|
}
|
|
68
68
|
let generatedFileCount = 0;
|
|
69
|
+
// Every path this run writes. After generation, anything else under
|
|
70
|
+
// autogen/ that carries the Apso header belongs to an entity that was
|
|
71
|
+
// removed or renamed in .apsorc and gets deleted (apsoai/cli#157).
|
|
72
|
+
const generatedPaths = new Set();
|
|
73
|
+
const writeGenerated = (filePath, content) => {
|
|
74
|
+
const fullPath = path.join(autogenPath, filePath);
|
|
75
|
+
generatedPaths.add(fullPath);
|
|
76
|
+
return (0, file_system_1.createFile)(fullPath, content);
|
|
77
|
+
};
|
|
69
78
|
const generatorConfig = {
|
|
70
79
|
language,
|
|
71
80
|
rootFolder,
|
|
@@ -87,17 +96,15 @@ class Generate extends base_command_1.default {
|
|
|
87
96
|
// Generate enums
|
|
88
97
|
const enumFiles = await generator.generateEnums(entities, lowerCaseApiType);
|
|
89
98
|
for (const file of enumFiles) {
|
|
90
|
-
const fullPath = path.join(autogenPath, file.path);
|
|
91
99
|
// eslint-disable-next-line no-await-in-loop
|
|
92
|
-
await (
|
|
100
|
+
await writeGenerated(file.path, file.content);
|
|
93
101
|
}
|
|
94
102
|
generatedFileCount += enumFiles.length;
|
|
95
103
|
// Generate shared query utilities
|
|
96
104
|
const queryUtilFiles = await generator.generateQueryUtils(entities, lowerCaseApiType);
|
|
97
105
|
for (const file of queryUtilFiles) {
|
|
98
|
-
const fullPath = path.join(autogenPath, file.path);
|
|
99
106
|
// eslint-disable-next-line no-await-in-loop
|
|
100
|
-
await (
|
|
107
|
+
await writeGenerated(file.path, file.content);
|
|
101
108
|
}
|
|
102
109
|
generatedFileCount += queryUtilFiles.length;
|
|
103
110
|
// Generate per-entity files
|
|
@@ -173,9 +180,8 @@ class Generate extends base_command_1.default {
|
|
|
173
180
|
// eslint-disable-next-line no-await-in-loop
|
|
174
181
|
for (const files of allFiles) {
|
|
175
182
|
for (const file of files) {
|
|
176
|
-
const fullPath = path.join(autogenPath, file.path);
|
|
177
183
|
// eslint-disable-next-line no-await-in-loop
|
|
178
|
-
await (
|
|
184
|
+
await writeGenerated(file.path, file.content);
|
|
179
185
|
generatedFileCount += 1;
|
|
180
186
|
}
|
|
181
187
|
}
|
|
@@ -185,26 +191,30 @@ class Generate extends base_command_1.default {
|
|
|
185
191
|
// Generate guards
|
|
186
192
|
const guardFiles = await generator.generateGuards(entities, auth);
|
|
187
193
|
for (const file of guardFiles) {
|
|
188
|
-
const fullPath = path.join(autogenPath, file.path);
|
|
189
194
|
// eslint-disable-next-line no-await-in-loop
|
|
190
|
-
await (
|
|
195
|
+
await writeGenerated(file.path, file.content);
|
|
191
196
|
}
|
|
192
197
|
generatedFileCount += guardFiles.length;
|
|
193
198
|
// Generate domain-event spine (only when at least one entity opts in)
|
|
194
199
|
const domainEventFiles = await generator.generateDomainEvents(entities, lowerCaseApiType, { emitEvents });
|
|
195
200
|
for (const file of domainEventFiles) {
|
|
196
|
-
const fullPath = path.join(autogenPath, file.path);
|
|
197
201
|
// eslint-disable-next-line no-await-in-loop
|
|
198
|
-
await (
|
|
202
|
+
await writeGenerated(file.path, file.content);
|
|
199
203
|
}
|
|
200
204
|
// Generate index module
|
|
201
205
|
const indexFiles = await generator.generateIndexModule(entities, lowerCaseApiType, { emitEvents, http });
|
|
202
206
|
for (const file of indexFiles) {
|
|
203
|
-
const fullPath = path.join(autogenPath, file.path);
|
|
204
207
|
// eslint-disable-next-line no-await-in-loop
|
|
205
|
-
await (
|
|
208
|
+
await writeGenerated(file.path, file.content);
|
|
206
209
|
}
|
|
207
210
|
generatedFileCount += indexFiles.length;
|
|
211
|
+
// Skip cleanup when nothing was generated: an empty or missing .apsorc
|
|
212
|
+
// would otherwise wipe every generated file.
|
|
213
|
+
if (entities.length > 0) {
|
|
214
|
+
for (const removed of (0, file_system_1.removeStaleGeneratedFiles)(autogenPath, generatedPaths)) {
|
|
215
|
+
console.log(`[apso] Removed stale ${path.relative(process.cwd(), removed)}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
208
218
|
// Format generated files (TypeScript only) with Biome — bundled with the
|
|
209
219
|
// CLI and invoked directly, so it's a fast native pass (~ms) with no npx
|
|
210
220
|
// download and no dependence on the project having a formatter installed.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
@IsOptional({ groups: [CREATE, UPDATE] })
|
|
4
4
|
@IsBoolean({ always: true })
|
|
5
5
|
|
|
6
|
-
@Column({ type: 'boolean', nullable: <%= Boolean(field.nullable) %>, default: <%=
|
|
6
|
+
@Column({ type: 'boolean', nullable: <%= Boolean(field.nullable) %>, default: <%= field.default === true || String(field.default).toLowerCase() === 'true' %> })
|
|
7
7
|
<% if (field.index ) {%>
|
|
8
8
|
@Index()
|
|
9
9
|
<% } %>
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
export declare const createFile: (file: string, content: string) => Promise<void>;
|
|
2
|
+
/**
|
|
3
|
+
* Delete files under `dir` that carry the Apso header but are not in `keep`,
|
|
4
|
+
* i.e. files left over from entities removed or renamed in .apsorc. Files
|
|
5
|
+
* without the header (template seeds like .gitkeep, hand-written code) are
|
|
6
|
+
* never touched. Directories emptied this way are removed too. Returns the
|
|
7
|
+
* deleted paths.
|
|
8
|
+
*/
|
|
9
|
+
export declare const removeStaleGeneratedFiles: (dir: string, keep: Set<string>) => string[];
|
|
2
10
|
export declare const createDirectoryContents: (templatePath: string, newProjectPath: string, apiType: string) => void;
|
|
3
11
|
export declare function withGeneratedMeta<T extends object>(data: T): T & {
|
|
4
12
|
generatedAt: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.withGeneratedMeta = exports.createDirectoryContents = exports.createFile = void 0;
|
|
3
|
+
exports.withGeneratedMeta = exports.createDirectoryContents = exports.removeStaleGeneratedFiles = exports.createFile = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const path = tslib_1.__importStar(require("path"));
|
|
6
6
|
const fs = tslib_1.__importStar(require("fs"));
|
|
@@ -15,6 +15,36 @@ const createFile = async (file, content) => {
|
|
|
15
15
|
await fs.promises.writeFile(file, content);
|
|
16
16
|
};
|
|
17
17
|
exports.createFile = createFile;
|
|
18
|
+
// Every file the CLI generates starts with this line (see templates/header.eta).
|
|
19
|
+
const APSO_HEADER = "Generated with Apso";
|
|
20
|
+
/**
|
|
21
|
+
* Delete files under `dir` that carry the Apso header but are not in `keep`,
|
|
22
|
+
* i.e. files left over from entities removed or renamed in .apsorc. Files
|
|
23
|
+
* without the header (template seeds like .gitkeep, hand-written code) are
|
|
24
|
+
* never touched. Directories emptied this way are removed too. Returns the
|
|
25
|
+
* deleted paths.
|
|
26
|
+
*/
|
|
27
|
+
const removeStaleGeneratedFiles = (dir, keep) => {
|
|
28
|
+
if (!fs.existsSync(dir))
|
|
29
|
+
return [];
|
|
30
|
+
const removed = [];
|
|
31
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
32
|
+
const fullPath = path.join(dir, entry.name);
|
|
33
|
+
if (entry.isDirectory()) {
|
|
34
|
+
removed.push(...(0, exports.removeStaleGeneratedFiles)(fullPath, keep));
|
|
35
|
+
if (fs.readdirSync(fullPath).length === 0)
|
|
36
|
+
fs.rmdirSync(fullPath);
|
|
37
|
+
}
|
|
38
|
+
else if (entry.isFile() &&
|
|
39
|
+
!keep.has(fullPath) &&
|
|
40
|
+
fs.readFileSync(fullPath, "utf8").includes(APSO_HEADER)) {
|
|
41
|
+
fs.unlinkSync(fullPath);
|
|
42
|
+
removed.push(fullPath);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return removed;
|
|
46
|
+
};
|
|
47
|
+
exports.removeStaleGeneratedFiles = removeStaleGeneratedFiles;
|
|
18
48
|
const createDirectoryContents = (templatePath, newProjectPath, apiType) => {
|
|
19
49
|
const filesToCreate = fs.readdirSync(templatePath);
|
|
20
50
|
const CURR_DIR = process.cwd();
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apso/cli",
|
|
3
|
-
"version": "0.43.
|
|
3
|
+
"version": "0.43.4",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@apso/cli",
|
|
9
|
-
"version": "0.43.
|
|
9
|
+
"version": "0.43.4",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@apso/schema-tools": "^0.2.0",
|
package/oclif.manifest.json
CHANGED