@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.
@@ -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
- // Format generated files (TypeScript only)
151
- if (language === "typescript" && !skipFormat) {
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
- await this.runNpmCommand(["run", "format", "src/autogen/**/*.ts", "src/guards/**/*.ts"], true);
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", "json",
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();
@@ -1,4 +1,5 @@
1
1
  import { Command } from "@oclif/core";
2
2
  export default abstract class BaseCommand extends Command {
3
+ runCommand(command: string, args: string[], silent?: boolean): Promise<void>;
3
4
  runNpmCommand(args: string[], silent?: boolean): Promise<void>;
4
5
  }
@@ -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 runNpmCommand(args, silent = false) {
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 command = isWindows ? "npm.cmd" : "npm";
11
+ const resolvedCommand = isWindows ? `${command}.cmd` : command;
12
12
  const stdio = silent ? "ignore" : "inherit";
13
- const cmdStr = `${command} ${args.join(" ")}`;
13
+ const cmdStr = `${resolvedCommand} ${args.join(" ")}`;
14
14
  this.log(`Running: ${cmdStr}`);
15
- const child = (0, child_process_1.spawn)(command, args, {
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;
@@ -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",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@apso/cli",
3
- "version": "0.15.3",
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.15.3",
9
+ "version": "0.16.1",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "@electric-sql/pglite": "^0.2.17",
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.15.3",
2
+ "version": "0.16.1",
3
3
  "commands": {
4
4
  "config": {
5
5
  "id": "config",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apso/cli",
3
- "version": "0.15.3",
3
+ "version": "0.16.1",
4
4
  "mcpName": "io.github.apsoai/apso",
5
5
  "description": "Apso CLI",
6
6
  "author": "Apso by Mavric - @mavric",