apcore-cli 0.9.0 → 0.9.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/CHANGELOG.md CHANGED
@@ -5,6 +5,24 @@ All notable changes to apcore-cli (TypeScript SDK) will be documented in this fi
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.9.1] - 2026-05-13
9
+
10
+ ### Fixed
11
+
12
+ - **Pre-execute schema validation missing in `buildModuleCommand`** — before calling `executor.execute()`, the CLI now validates the merged input against the module's JSON Schema (required fields + scalar types). Previously, a missing required field (e.g. `--url` not supplied) propagated as `undefined` into the executor and produced an opaque `TypeError`. Now exits 45 with a human-readable message (`Validation failed: 'url' is required`) matching Python's `jsonschema.validate` and Rust's `validate_against_schema` pre-execute behaviour. Validation is skipped in `--dry-run` mode (executor preflight handles that path). `src/main.ts:177-208` (`validateInputSchema`), call site `src/main.ts:1127-1133`.
13
+ - **`SchemaValidationError` emitted `"code":"UNKNOWN"` in JSON error output** — `emitErrorJson` reads `err.code` to populate the `"code"` field; `SchemaValidationError` had no `.code` property, so exit-45 validation errors always emitted `"code":"UNKNOWN"`. Added `readonly code = "SCHEMA_VALIDATION_ERROR"` to the class. `src/errors.ts:52`.
14
+
15
+ ### Changed
16
+
17
+ - **Step comment numbering in `buildModuleCommand` action handler corrected** — inserting the schema-validation step left two "3." labels in the try block. Renumbered: 3 = schema validation, 4 = check approval, 5 = execute, 6 = format, 7 = audit. `src/main.ts`.
18
+
19
+ ### Tests
20
+
21
+ - Renamed test 4 in the pre-execute schema-validation suite from `"exits 45 with type error message when field has wrong type"` (which actually tested the required-field path) to `"exits 45 when required field is missing (integer schema)"`.
22
+ - Added test 5: `"exits 45 with type-mismatch message when integer field receives string via --input"` — supplies `{"count":"not-a-number"}` via `--input <file>` to exercise the scalar type-check branch (`validateInputSchema` lines 198-206) that had zero coverage.
23
+
24
+ ---
25
+
8
26
  ## [0.9.0] - 2026-05-13
9
27
 
10
28
  ### Fixed (2026-05-13 — cross-SDK audit D10/D11/D1)
@@ -116,6 +116,7 @@ var init_errors = __esm({
116
116
  }
117
117
  };
118
118
  SchemaValidationError = class extends Error {
119
+ code = "SCHEMA_VALIDATION_ERROR";
119
120
  constructor(message = "Schema validation failed") {
120
121
  super(message);
121
122
  this.name = "SchemaValidationError";
@@ -3783,6 +3784,37 @@ function resolveStringOption(cliValue, envValue) {
3783
3784
  }
3784
3785
  return void 0;
3785
3786
  }
3787
+ function validateInputSchema(schema, input) {
3788
+ const required = schema.required;
3789
+ if (required && Array.isArray(required)) {
3790
+ for (const field of required) {
3791
+ const val = input[field];
3792
+ if (val === null || val === void 0) {
3793
+ return `'${field}' is required`;
3794
+ }
3795
+ }
3796
+ }
3797
+ const properties = schema.properties;
3798
+ if (properties) {
3799
+ for (const [field, propSchema] of Object.entries(properties)) {
3800
+ const val = input[field];
3801
+ if (val === null || val === void 0) continue;
3802
+ const expectedType = propSchema.type;
3803
+ if (!expectedType) continue;
3804
+ const actualType = typeof val;
3805
+ if (expectedType === "string" && actualType !== "string") {
3806
+ return `'${field}' must be a string, got ${actualType}`;
3807
+ }
3808
+ if ((expectedType === "integer" || expectedType === "number") && actualType !== "number") {
3809
+ return `'${field}' must be a number, got ${actualType}`;
3810
+ }
3811
+ if (expectedType === "boolean" && actualType !== "boolean") {
3812
+ return `'${field}' must be a boolean, got ${actualType}`;
3813
+ }
3814
+ }
3815
+ }
3816
+ return null;
3817
+ }
3786
3818
  function emitErrorJson(e, exitCode) {
3787
3819
  const err = e instanceof Error ? e : new Error(String(e));
3788
3820
  const errRecord = err;
@@ -4296,6 +4328,12 @@ function buildModuleCommand(moduleDef, executor, helpTextMaxLength = 1e3, cmdNam
4296
4328
  }
4297
4329
  process.exit(preflight.valid ? 0 : firstFailedExitCode(preflight));
4298
4330
  }
4331
+ if (resolvedSchema.properties) {
4332
+ const validationErr = validateInputSchema(resolvedSchema, merged);
4333
+ if (validationErr) {
4334
+ throw new SchemaValidationError(`Validation failed: ${validationErr}`);
4335
+ }
4336
+ }
4299
4337
  if (approvalToken) {
4300
4338
  merged._approval_token = approvalToken;
4301
4339
  }