Add JSON result schema infrastructure - #8404
Draft
gonzaloriestra wants to merge 2 commits into
Draft
Conversation
This was referenced Aug 26, 2026
gonzaloriestra
marked this pull request as ready for review
August 27, 2026 11:42
gonzaloriestra
marked this pull request as draft
August 27, 2026 11:47
gonzaloriestra
force-pushed
the
gonzalo/json-result-schema-infrastructure
branch
from
August 27, 2026 11:55
9541c57 to
e8c7210
Compare
gonzaloriestra
force-pushed
the
gonzalo/json-result-schema-infrastructure
branch
from
August 27, 2026 12:43
e8c7210 to
e5133a5
Compare
gonzaloriestra
changed the base branch from
main
to
gonzalo/json-side-events-infrastructure
August 27, 2026 12:43
gonzaloriestra
force-pushed
the
gonzalo/json-result-schema-infrastructure
branch
from
August 27, 2026 12:44
e5133a5 to
91a047b
Compare
gonzaloriestra
force-pushed
the
gonzalo/json-result-schema-infrastructure
branch
2 times, most recently
from
August 27, 2026 14:32
86a0e21 to
fa0dbc1
Compare
gonzaloriestra
force-pushed
the
gonzalo/json-result-schema-infrastructure
branch
from
August 27, 2026 14:56
fa0dbc1 to
0e3dfaf
Compare
Contributor
Differences in type declarationsWe detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:
New type declarationspackages/cli-kit/dist/public/common/command-events.d.tsimport { z } from 'zod';
/** Schema for a diagnostic emitted while a command executes. */
export declare const commandDiagnosticEventSchema: z.ZodObject<{
type: z.ZodLiteral<"diagnostic">;
timestamp: z.ZodString;
level: z.ZodEnum<["debug", "info", "warning"]>;
message: z.ZodString;
code: z.ZodOptional<z.ZodString>;
}, "strict", z.ZodTypeAny, {
type: "diagnostic";
message: string;
timestamp: string;
level: "info" | "warning" | "debug";
code?: string | undefined;
}, {
type: "diagnostic";
message: string;
timestamp: string;
level: "info" | "warning" | "debug";
code?: string | undefined;
}>;
/** Schema for a progress update emitted while a command executes. */
export declare const commandProgressEventSchema: z.ZodObject<{
type: z.ZodLiteral<"progress">;
timestamp: z.ZodString;
message: z.ZodString;
current: z.ZodOptional<z.ZodNumber>;
total: z.ZodOptional<z.ZodNumber>;
}, "strict", z.ZodTypeAny, {
type: "progress";
message: string;
timestamp: string;
current?: number | undefined;
total?: number | undefined;
}, {
type: "progress";
message: string;
timestamp: string;
current?: number | undefined;
total?: number | undefined;
}>;
/** Schema for side events emitted while a command executes. */
export declare const commandEventSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
type: z.ZodLiteral<"diagnostic">;
timestamp: z.ZodString;
level: z.ZodEnum<["debug", "info", "warning"]>;
message: z.ZodString;
code: z.ZodOptional<z.ZodString>;
}, "strict", z.ZodTypeAny, {
type: "diagnostic";
message: string;
timestamp: string;
level: "info" | "warning" | "debug";
code?: string | undefined;
}, {
type: "diagnostic";
message: string;
timestamp: string;
level: "info" | "warning" | "debug";
code?: string | undefined;
}>, z.ZodObject<{
type: z.ZodLiteral<"progress">;
timestamp: z.ZodString;
message: z.ZodString;
current: z.ZodOptional<z.ZodNumber>;
total: z.ZodOptional<z.ZodNumber>;
}, "strict", z.ZodTypeAny, {
type: "progress";
message: string;
timestamp: string;
current?: number | undefined;
total?: number | undefined;
}, {
type: "progress";
message: string;
timestamp: string;
current?: number | undefined;
total?: number | undefined;
}>]>;
/** A diagnostic emitted while a command executes. */
export type CommandDiagnosticEvent = z.infer<typeof commandDiagnosticEventSchema>;
/** A progress update emitted while a command executes. */
export type CommandProgressEvent = z.infer<typeof commandProgressEventSchema>;
/** A side event emitted while a command executes. */
export type CommandEvent = z.infer<typeof commandEventSchema>;
/** An event before its emission timestamp is added. */
export type CommandEventInput<TEvent extends CommandEvent = CommandEvent> = TEvent extends unknown ? Omit<TEvent, 'timestamp'> : never;
/** Receives one timestamped event from a command execution. */
export type CommandEventSink<TEvent extends CommandEvent = CommandEvent> = (event: TEvent) => void;
/** Emits timestamped side events from one command execution. */
export interface CommandEventChannel<TEvent extends CommandEvent = CommandEvent> {
emit: (event: CommandEventInput<TEvent>) => void;
}
/** Supplies the current time when an event is emitted. */
export type CommandEventClock = () => Date;
/** Options for a command event channel. */
export interface CommandEventChannelOptions<TEvent extends CommandEvent> {
sink?: CommandEventSink<TEvent>;
clock?: CommandEventClock;
}
/**
* Creates a synchronous, execution-scoped channel for command side events.
*
* @param options - The event sink and clock used by the channel.
* @returns A channel that adds an ISO timestamp before synchronously delivering each event.
*/
export declare function createCommandEventChannel<TEvent extends CommandEvent = CommandEvent>(options?: CommandEventChannelOptions<TEvent>): CommandEventChannel<TEvent>;
packages/cli-kit/dist/public/node/command-events.d.tsimport type { CommandEvent } from '../common/command-events.js';
/**
* Renders a command side event to stderr using the existing CLI output behavior.
*
* @param event - The event to render.
*/
export declare function renderCommandEvent(event: CommandEvent): void;
/**
* Renders a command side event as compact JSON to stderr.
*
* @param event - The event to render.
*/
export declare function renderCommandEventAsJson(event: CommandEvent): void;
packages/cli-kit/dist/public/node/json-output-schema.d.tsimport { ZodTypeAny, type z } from 'zod';
interface JsonOutputSchemaDefinition<TSchema extends ZodTypeAny = ZodTypeAny> {
readonly name: string;
readonly schema: TSchema;
readonly definitions: Readonly<Record<string, ZodTypeAny>>;
}
export interface JsonOutputSchema<TSchema extends ZodTypeAny = ZodTypeAny> extends JsonOutputSchemaDefinition<TSchema> {
readonly typescript: string;
validate(value: unknown): z.output<TSchema>;
encode(value: z.input<TSchema>): string;
}
export type InferJsonOutputSchema<TOutputSchema extends JsonOutputSchema> = z.output<TOutputSchema['schema']>;
interface DefineJsonOutputSchemaOptions<TSchema extends ZodTypeAny> {
name: string;
schema: TSchema;
definitions?: Readonly<Record<string, ZodTypeAny>>;
}
/**
* Defines the runtime validator, encoder, and documented TypeScript type for a command's JSON output.
*
* @param options - The root type name, its Zod schema, and any named nested schemas.
* @returns The complete JSON output contract.
*/
export declare function defineJsonOutputSchema<TSchema extends ZodTypeAny>(options: DefineJsonOutputSchemaOptions<TSchema>): JsonOutputSchema<TSchema>;
/**
* Renders the named schemas in a JSON output contract as TypeScript declarations.
*
* @param outputSchema - The root schema and its named nested schemas.
* @returns TypeScript declarations suitable for command help.
*/
export declare function renderJsonOutputSchema(outputSchema: JsonOutputSchemaDefinition): string;
export {};
Existing type declarationspackages/cli-kit/dist/public/node/base-command.d.ts@@ -1,5 +1,6 @@
import { Command } from '@oclif/core';
import { OutputFlags, Input, ParserOutput, FlagInput, OutputArgs } from '@oclif/core/parser';
+import type { JsonOutputSchema } from './json-output-schema.js';
export type ArgOutput = OutputArgs<any>;
export type FlagOutput = OutputFlags<any>;
export interface NonTTYFlagRequirement {
@@ -10,6 +11,8 @@ export interface NonTTYFlagRequirement {
}
declare abstract class BaseCommand extends Command {
static baseFlags: FlagInput<{}>;
+ static descriptionWithMarkdown?: string;
+ static get jsonOutputSchema(): JsonOutputSchema | undefined;
static get requiresSyncAnalytics(): boolean;
static nonTTYFlagRequirements(_flags: FlagOutput): NonTTYFlagRequirement[];
static descriptionWithoutMarkdown(): string | undefined;
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
WHY are these changes introduced?
Closes shop/issues-develop#23660
Finite commands need one typed contract for validating JSON results and documenting them in command help.
Based on these prototypes:
WHAT is this pull request doing?
BaseCommandand generated command help.Checklist