@apso/cli 0.15.3 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/generate.js +20 -4
- package/dist/commands/mcp/serve.js +2 -2
- package/dist/lib/base-command.d.ts +1 -0
- package/dist/lib/base-command.js +7 -4
- package/dist/lib/doctor/checks.js +1 -1
- package/dist/lib/types/field.d.ts +1 -1
- package/dist/lib/utils/field.js +4 -0
- package/npm-shrinkwrap.json +2 -2
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
|
@@ -52,6 +52,10 @@ class Generate extends base_command_1.default {
|
|
|
52
52
|
const autogenPath = path.join(rootPath, "autogen");
|
|
53
53
|
const lowerCaseApiType = apiType.toLowerCase();
|
|
54
54
|
console.log(`[apso] Generating ${language} code for ${entities.length} entities...`);
|
|
55
|
+
if (entities.length === 0) {
|
|
56
|
+
console.log("[apso] No entities found in .apsorc — nothing to generate. Check that the file exists and defines an `entities` array.");
|
|
57
|
+
}
|
|
58
|
+
let generatedFileCount = 0;
|
|
55
59
|
const generatorConfig = {
|
|
56
60
|
language,
|
|
57
61
|
rootFolder,
|
|
@@ -75,6 +79,7 @@ class Generate extends base_command_1.default {
|
|
|
75
79
|
// eslint-disable-next-line no-await-in-loop
|
|
76
80
|
await (0, file_system_1.createFile)(fullPath, file.content);
|
|
77
81
|
}
|
|
82
|
+
generatedFileCount += enumFiles.length;
|
|
78
83
|
// Generate shared query utilities
|
|
79
84
|
const queryUtilFiles = await generator.generateQueryUtils(entities, lowerCaseApiType);
|
|
80
85
|
for (const file of queryUtilFiles) {
|
|
@@ -82,6 +87,7 @@ class Generate extends base_command_1.default {
|
|
|
82
87
|
// eslint-disable-next-line no-await-in-loop
|
|
83
88
|
await (0, file_system_1.createFile)(fullPath, file.content);
|
|
84
89
|
}
|
|
90
|
+
generatedFileCount += queryUtilFiles.length;
|
|
85
91
|
// Generate per-entity files
|
|
86
92
|
for (const entity of entities) {
|
|
87
93
|
console.log(`[apso] Building... ${entity.name}`);
|
|
@@ -128,6 +134,7 @@ class Generate extends base_command_1.default {
|
|
|
128
134
|
const fullPath = path.join(autogenPath, file.path);
|
|
129
135
|
// eslint-disable-next-line no-await-in-loop
|
|
130
136
|
await (0, file_system_1.createFile)(fullPath, file.content);
|
|
137
|
+
generatedFileCount += 1;
|
|
131
138
|
}
|
|
132
139
|
}
|
|
133
140
|
const entityBuildTime = perf_hooks_1.performance.now() - entityBuildStart;
|
|
@@ -140,6 +147,7 @@ class Generate extends base_command_1.default {
|
|
|
140
147
|
// eslint-disable-next-line no-await-in-loop
|
|
141
148
|
await (0, file_system_1.createFile)(fullPath, file.content);
|
|
142
149
|
}
|
|
150
|
+
generatedFileCount += guardFiles.length;
|
|
143
151
|
// Generate index module
|
|
144
152
|
const indexFiles = await generator.generateIndexModule(entities, lowerCaseApiType);
|
|
145
153
|
for (const file of indexFiles) {
|
|
@@ -147,17 +155,25 @@ class Generate extends base_command_1.default {
|
|
|
147
155
|
// eslint-disable-next-line no-await-in-loop
|
|
148
156
|
await (0, file_system_1.createFile)(fullPath, file.content);
|
|
149
157
|
}
|
|
150
|
-
|
|
151
|
-
|
|
158
|
+
generatedFileCount += indexFiles.length;
|
|
159
|
+
// Format generated files (TypeScript only).
|
|
160
|
+
// Run prettier directly against the generated output directory so we never
|
|
161
|
+
// reformat hand-written code elsewhere in the project tree (the project's
|
|
162
|
+
// `npm run format` script targets a broad glob like `{src,test}/**/*.ts`).
|
|
163
|
+
if (language === "typescript" && !skipFormat && generatedFileCount > 0) {
|
|
152
164
|
const formatStart = perf_hooks_1.performance.now();
|
|
153
|
-
console.log("[apso] Formatting files...");
|
|
154
|
-
|
|
165
|
+
console.log("[apso] Formatting generated files...");
|
|
166
|
+
const formatGlob = path.join(autogenPath, "**", "*.ts");
|
|
167
|
+
await this.runCommand("npx", ["prettier", "--write", formatGlob], true);
|
|
155
168
|
const formatTime = perf_hooks_1.performance.now() - formatStart;
|
|
156
169
|
console.log(`[apso] Finished formatting in ${formatTime.toFixed(2)} ms`);
|
|
157
170
|
}
|
|
158
171
|
else if (skipFormat) {
|
|
159
172
|
console.log("[apso] Skipping formatting (--skip-format flag set)");
|
|
160
173
|
}
|
|
174
|
+
else if (generatedFileCount === 0) {
|
|
175
|
+
console.log("[apso] Skipping formatting (no files were generated)");
|
|
176
|
+
}
|
|
161
177
|
const totalBuildTime = perf_hooks_1.performance.now() - totalBuildStart;
|
|
162
178
|
console.log(`[apso] Finished building all entities in ${totalBuildTime.toFixed(2)} ms`);
|
|
163
179
|
}
|
|
@@ -851,8 +851,8 @@ function validateSchemaObject(schema) {
|
|
|
851
851
|
}
|
|
852
852
|
const validFieldTypes = [
|
|
853
853
|
"text", "string", "varchar", "integer", "float", "decimal", "numeric",
|
|
854
|
-
"boolean", "date", "timestamp", "datetime", "uuid", "enum",
|
|
855
|
-
"json-plain", "array",
|
|
854
|
+
"boolean", "date", "timestamptz", "timestamp", "datetime", "uuid", "enum",
|
|
855
|
+
"json", "json-plain", "array",
|
|
856
856
|
];
|
|
857
857
|
const validRelTypes = ["OneToMany", "ManyToOne", "ManyToMany", "OneToOne"];
|
|
858
858
|
const entityNames = new Set();
|
package/dist/lib/base-command.js
CHANGED
|
@@ -5,14 +5,14 @@ const core_1 = require("@oclif/core");
|
|
|
5
5
|
const child_process_1 = require("child_process");
|
|
6
6
|
const os_1 = tslib_1.__importDefault(require("os"));
|
|
7
7
|
class BaseCommand extends core_1.Command {
|
|
8
|
-
async
|
|
8
|
+
async runCommand(command, args, silent = false) {
|
|
9
9
|
return new Promise((resolve, reject) => {
|
|
10
10
|
const isWindows = os_1.default.platform() === "win32";
|
|
11
|
-
const
|
|
11
|
+
const resolvedCommand = isWindows ? `${command}.cmd` : command;
|
|
12
12
|
const stdio = silent ? "ignore" : "inherit";
|
|
13
|
-
const cmdStr = `${
|
|
13
|
+
const cmdStr = `${resolvedCommand} ${args.join(" ")}`;
|
|
14
14
|
this.log(`Running: ${cmdStr}`);
|
|
15
|
-
const child = (0, child_process_1.spawn)(
|
|
15
|
+
const child = (0, child_process_1.spawn)(resolvedCommand, args, {
|
|
16
16
|
stdio,
|
|
17
17
|
shell: isWindows,
|
|
18
18
|
});
|
|
@@ -28,5 +28,8 @@ class BaseCommand extends core_1.Command {
|
|
|
28
28
|
});
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
|
+
async runNpmCommand(args, silent = false) {
|
|
32
|
+
return this.runCommand("npm", args, silent);
|
|
33
|
+
}
|
|
31
34
|
}
|
|
32
35
|
exports.default = BaseCommand;
|
|
@@ -133,7 +133,7 @@ function checkFieldTypeMismatch(ctx) {
|
|
|
133
133
|
severity: "error",
|
|
134
134
|
message: `Entity "${entity.name}", field "${field.name}": type "${field.type}" is not recognized by the generator`,
|
|
135
135
|
entity: entity.name,
|
|
136
|
-
suggestion: `Valid types: text, integer, float, decimal, numeric, boolean, date, enum, json, json-plain, array, uuid`,
|
|
136
|
+
suggestion: `Valid types: text, integer, float, decimal, numeric, boolean, date, timestamptz, timestamp, datetime, enum, json, json-plain, array, uuid`,
|
|
137
137
|
});
|
|
138
138
|
}
|
|
139
139
|
// Enum fields must have values
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type FieldType = "text" | "boolean" | "array" | "enum" | "integer" | "float" | "decimal" | "numeric" | "date" | "json" | "json-plain";
|
|
1
|
+
export type FieldType = "text" | "boolean" | "array" | "enum" | "integer" | "float" | "decimal" | "numeric" | "date" | "timestamptz" | "timestamp" | "datetime" | "json" | "json-plain";
|
|
2
2
|
export interface Field {
|
|
3
3
|
name: string;
|
|
4
4
|
type: FieldType;
|
package/dist/lib/utils/field.js
CHANGED
|
@@ -28,6 +28,7 @@ exports.fieldTypeToColumnType = {
|
|
|
28
28
|
date: "date",
|
|
29
29
|
timestamp: "timestamp",
|
|
30
30
|
timestamptz: "timestamptz",
|
|
31
|
+
datetime: "timestamp",
|
|
31
32
|
time: "time",
|
|
32
33
|
timetz: "timetz",
|
|
33
34
|
json: "json",
|
|
@@ -66,6 +67,8 @@ const fieldTypeNormalizationMap = {
|
|
|
66
67
|
"time with time zone": "timetz",
|
|
67
68
|
"timestamp without time zone": "timestamp",
|
|
68
69
|
"timestamp with time zone": "timestamptz",
|
|
70
|
+
// `datetime` is a user-facing alias for a naive timestamp (instant-in-time).
|
|
71
|
+
datetime: "timestamp",
|
|
69
72
|
};
|
|
70
73
|
/**
|
|
71
74
|
* Normalize a field type to its template-compatible name.
|
|
@@ -102,6 +105,7 @@ const typeToJsType = {
|
|
|
102
105
|
date: "string",
|
|
103
106
|
timestamp: "string",
|
|
104
107
|
timestamptz: "string",
|
|
108
|
+
datetime: "string",
|
|
105
109
|
timetz: "string",
|
|
106
110
|
tsvector: "string",
|
|
107
111
|
string: "string",
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apso/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@apso/cli",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.16.1",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@electric-sql/pglite": "^0.2.17",
|
package/oclif.manifest.json
CHANGED