Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions packages/cli/src/commands/registry/implementation/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ function isAlreadyExistsError(errorObj: any): boolean {
);
}

/**
* Adds one or more registry components to a Xano instance, attempting to install each component file and collecting success, skip, and failure outcomes.
*
* @param componentNames - Registry component names to install; if empty, the user will be prompted to select components.
* @param context - CLI context used to resolve instance, workspace, and branch configuration; defaults to an empty object.
* @returns An object with `installed` (entries with `component`, `file` path, and `response`), `failed` (entries with `component`, `file`, `error`, and optional `response`), and `skipped` (entries for items skipped because the resource already exists).
*/
async function addToXano({
componentNames,
context = {},
Expand Down Expand Up @@ -93,12 +100,11 @@ async function addToXano({
}

/**
* Installs a component file to Xano.
* Install a single component file into the configured Xano instance.
*
* @param {Object} file - The component file metadata.
* @param {Object} resolvedContext - The resolved context configs.
* @param {any} core - Core utilities.
* @returns {Promise<{ success: boolean, error?: string, body?: any }>}
* @param file - Component file metadata (e.g., `type`, `path`, `target`, and for query files `apiGroupName`) that identifies what to install and where.
* @param resolvedContext - Resolved configuration objects: `instanceConfig`, `workspaceConfig`, and `branchConfig`.
* @returns An object with `success: true` and the parsed response `body` on success; on failure `success: false` and `error` contains a human-readable message, `body` may include the raw response when available.
*/
async function installComponentToXano(file, resolvedContext, core) {
const { instanceConfig, workspaceConfig, branchConfig } = resolvedContext;
Expand Down Expand Up @@ -177,4 +183,4 @@ async function installComponentToXano(file, resolvedContext, core) {
}
}

export { addToXano, scaffoldRegistry };
export { addToXano, scaffoldRegistry };
24 changes: 15 additions & 9 deletions packages/cli/src/commands/test/implementation/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,17 @@ import {
} from '../../../utils/index';

/**
* Prints a formatted summary table of test outcomes to the log.
* Print a formatted table of test outcomes and an optional detailed warnings section to the log.
*
* Logs a header, one row per result showing status, HTTP method, path, and duration, and a final summary line with totals and aggregate duration.
* The table includes columns for status, HTTP method, path, warnings count, and duration (ms),
* followed by an aggregate summary line with total, passed, failed, and total duration.
*
* @param results - Array of test result objects. Each object should include:
* - `success` (boolean): whether the test passed,
* - `method` (string): HTTP method used,
* - `path` (string): endpoint path,
* - `duration` (number, optional): duration of the test in milliseconds
* - `success`: whether the test passed
* - `method`: HTTP method used for the test
* - `path`: endpoint path exercised by the test
* - `duration` (optional): duration of the test in milliseconds
* - `warnings` (optional): array of warning objects; each warning should include `key` and `message`
*/
function printTestSummary(results) {
// Collect all rows for sizing
Expand Down Expand Up @@ -128,9 +130,13 @@ async function loadTestConfig(testConfigPath) {
}

/**
* Runs API tests for selected API groups using a provided test configuration and writes per-group results to disk.
* Run API tests for selected API groups, write per-group JSON results to disk, and print a formatted summary.
*
* @param instance - Name or alias of the target instance
* Resolves the target instance/workspace/branch, selects API groups (optionally prompting), loads the test
* configuration, executes tests via the provided runtime `core`, writes each group's results to a timestamped
* JSON file under the configured output path, and prints a summary table and optional output directory path.
*
* @param instance - Target instance name or alias used to resolve configuration
* @param workspace - Workspace name within the instance
* @param branch - Branch label within the workspace
* @param group - Specific API group name to run; when omitted and `isAll` is false the user may be prompted
Expand Down Expand Up @@ -221,4 +227,4 @@ async function runTest({
}
}

export { runTest };
export { runTest };
12 changes: 11 additions & 1 deletion packages/cli/src/utils/feature-focused/registry/scaffold.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import { dirname, join } from 'node:path';
import { mkdir, writeFile } from 'node:fs/promises';

/**
* Ensures the parent directory for the provided file path exists, creating it recursively if needed.
*
* @param filePath - Path to the target file whose containing directory should exist
*/
async function ensureDirForFile(filePath: string) {
const dir = dirname(filePath);
await mkdir(dir, { recursive: true });
}

/**
* Creates a sample registry scaffold (components, function implementation, function definition, and index) under the specified registry root.
*
* @param registryRoot - Root directory where registry files will be written. Defaults to `'registry'`.
*/
async function scaffoldRegistry(
{ registryRoot }: { registryRoot?: string } = {
registryRoot: 'registry',
Expand Down Expand Up @@ -69,4 +79,4 @@ async function scaffoldRegistry(
await writeFile(indexPath, JSON.stringify(sampleIndex, null, 2), 'utf8');
}

export { scaffoldRegistry };
export { scaffoldRegistry };
23 changes: 19 additions & 4 deletions packages/core/src/features/testing/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,24 @@ function getByPath(obj, path) {
}

/**
* testConfig is actually an array of objects defining in what order and which
* endpoints to run, also optionally define custom asserts (either inline func, or predefined asserts)
* ApiGroupConfig allows for extra keys. In this case it should include an 'oas' key
* Execute the configured API tests across the provided API groups and return per-group results.
*
* For each group, ensures an OpenAPI spec is available (fetching and patching from the remote API if absent),
* runs the endpoints defined by `testConfig` in order, evaluates assertions (built-in or custom),
* optionally extracts runtime values from JSON responses into a shared runtime store, and records timing,
* successes, errors, and warnings for each endpoint.
*
* @param context - Execution context containing instance, workspace, and branch identifiers
* @param groups - Array of API group configurations; each group may include an `oas` property (OpenAPI) and a `canonical` identifier used to build request base URLs
* @param testConfig - Ordered array of endpoint test definitions. Each entry should include:
* - `path` and `method` for the request
* - `headers`, `queryParams`, and `requestBody` for request composition
* - optional `store` mappings [{ key, path }] to extract values from JSON responses into runtime variables
* - optional `customAsserts` to override or provide per-endpoint assertions
*
* @returns An array of objects, one per input group, each containing the original `group` and a `results` array.
* Each result includes `path`, `method`, `success` (true if no assertion errors), `errors` (or null),
* `warnings` (or null), and `duration` (milliseconds)
*/
async function testRunner({
context,
Expand Down Expand Up @@ -244,4 +259,4 @@ async function testRunner({
return finalOutput;
}

export { testRunner };
export { testRunner };