Skip to content

[Do not merge] Add JSON infrastructure sample command - #8415

Draft
gonzaloriestra wants to merge 5 commits into
gonzalo/json-schema-flagfrom
gonzalo/json-infrastructure-sample
Draft

[Do not merge] Add JSON infrastructure sample command#8415
gonzaloriestra wants to merge 5 commits into
gonzalo/json-schema-flagfrom
gonzalo/json-infrastructure-sample

Conversation

@gonzaloriestra

@gonzaloriestra gonzaloriestra commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

WHY are these changes introduced?

This disposable sample validates the finite-command infrastructure introduced by the PRs below it in the stack.

WHAT is this pull request doing?

  • Adds a hidden kitchen-sink json-output command.
  • Emits diagnostic and progress side events to stderr.
  • Prints a validated human or JSON result.
  • Exposes the result type through --json-schema and command help.
  • Adds --fail to exercise structured JSON errors.

How to test your changes?

pnpm shopify kitchen-sink json-output
pnpm shopify kitchen-sink json-output --json
pnpm shopify kitchen-sink json-output --help
pnpm shopify kitchen-sink json-output --json-schema
pnpm shopify kitchen-sink json-output --json --fail

Checklist

  • I've considered possible cross-platform impacts (Mac, Linux, Windows)
  • I've considered possible documentation changes
  • I've considered analytics changes to measure impact
  • The change is user-facing — this is a hidden, disposable sample and intentionally has no changeset

@github-actions github-actions Bot added the no-changelog This PR doesn't include a changeset entry. Is an internal only change not relevant to end users. label Aug 27, 2026
@gonzaloriestra
gonzaloriestra force-pushed the gonzalo/json-infrastructure-sample branch from 4f9109a to 9dfb8e1 Compare August 27, 2026 12:44
@gonzaloriestra
gonzaloriestra force-pushed the gonzalo/json-infrastructure-sample branch 3 times, most recently from c9c81bd to e48c0f0 Compare August 27, 2026 14:32
@gonzaloriestra
gonzaloriestra force-pushed the gonzalo/json-infrastructure-sample branch from e48c0f0 to f13770d Compare August 27, 2026 14:56
@gonzaloriestra
gonzaloriestra force-pushed the gonzalo/json-infrastructure-sample branch from f13770d to c6ab723 Compare August 27, 2026 15:10
@github-actions

Copy link
Copy Markdown
Contributor

Differences in type declarations

We 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:

  • Some seemingly private modules might be re-exported through public modules.
  • If the branch is behind main you might see odd diffs, rebase main into this branch.

New type declarations

packages/cli-kit/dist/private/node/json-error.d.ts
interface FatalErrorLike {
    type?: number;
    message?: unknown;
    formattedMessage?: unknown;
    tryMessage?: unknown;
    nextSteps?: unknown;
    customSections?: unknown;
    stack?: unknown;
    command?: unknown;
    args?: unknown;
}
/**
 * Writes the public JSON representation of a fatal error to stdout.
 *
 * The allow-list mirrors the meaningful content of the regular fatal-error renderer.
 * Arbitrary error properties remain private and are never copied to stdout.
 *
 * @param error - Fatal error to serialize.
 */
export declare function renderFatalErrorAsJson(error: FatalErrorLike): void;
export {};
packages/cli-kit/dist/public/common/command-events.d.ts
import { 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.ts
import { type CommandEvent } from '../common/command-events.js';
export declare const commandEventOutputSchema: import("./json-output-schema.js").JsonOutputSchema<import("zod").ZodDiscriminatedUnion<"type", [import("zod").ZodObject<{
    type: import("zod").ZodLiteral<"diagnostic">;
    timestamp: import("zod").ZodString;
    level: import("zod").ZodEnum<["debug", "info", "warning"]>;
    message: import("zod").ZodString;
    code: import("zod").ZodOptional<import("zod").ZodString>;
}, "strict", import("zod").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;
}>, import("zod").ZodObject<{
    type: import("zod").ZodLiteral<"progress">;
    timestamp: import("zod").ZodString;
    message: import("zod").ZodString;
    current: import("zod").ZodOptional<import("zod").ZodNumber>;
    total: import("zod").ZodOptional<import("zod").ZodNumber>;
}, "strict", import("zod").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;
}>]>>;
/**
 * 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.ts
import { 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 {};
packages/cli-kit/dist/public/node/error/index.d.ts
import { OutputMessage } from '../output.js';
import { type InlineToken, type TokenItem } from '../../../private/node/ui/components/token-item.js';
import type { AlertCustomSection } from '../ui.js';
export declare enum FatalErrorType {
    Abort = 0,
    AbortSilent = 1,
    Bug = 2
}
export declare class CancelExecution extends Error {
}
/**
 * A fatal error represents an error shouldn't be rescued and that causes the execution to terminate.
 * There shouldn't be code that catches fatal errors.
 */
export declare abstract class FatalError extends Error {
    tryMessage: TokenItem | null;
    type: FatalErrorType;
    nextSteps?: TokenItem<InlineToken>[];
    formattedMessage?: TokenItem;
    customSections?: AlertCustomSection[];
    skipOclifErrorHandling: boolean;
    /**
     * Creates a new FatalError error.
     *
     * @param message - The error message.
     * @param type - The type of fatal error.
     * @param tryMessage - The message that recommends next steps to the user.
     * You can pass a string a {@link TokenizedString} or a {@link TokenItem}
     * if you need to style the message inside the error Banner component.
     * @param nextSteps - Message to show as "next steps" with suggestions to solve the issue.
     * @param customSections - Custom sections to show in the error banner. To be used if nextSteps is not enough.
     */
    constructor(message: TokenItem | OutputMessage, type: FatalErrorType, tryMessage?: TokenItem | OutputMessage | null, nextSteps?: TokenItem<InlineToken>[], customSections?: AlertCustomSection[]);
}
/**
 * An abort error is a fatal error that shouldn't be reported as a bug.
 * Those usually represent unexpected scenarios that we can't handle and that usually require some action from the developer.
 */
export declare class AbortError extends FatalError {
    constructor(message: TokenItem | OutputMessage, tryMessage?: TokenItem | OutputMessage | null, nextSteps?: TokenItem<InlineToken>[], customSections?: AlertCustomSection[]);
}
/**
 * An external error is similar to Abort but has extra command and args attributes.
 * This is useful to represent errors coming from external commands, usually executed by execa.
 */
export declare class ExternalError extends FatalError {
    command: string;
    args: string[];
    constructor(message: OutputMessage, command: string, args: string[], tryMessage?: TokenItem | OutputMessage | null);
}
export declare class AbortSilentError extends FatalError {
    constructor();
}
/**
 * A bug error is an error that represents a bug and therefore should be reported.
 */
export declare class BugError extends FatalError {
    constructor(message: TokenItem | OutputMessage, tryMessage?: TokenItem | OutputMessage | null);
}
/**
 * A function that handles errors that blow up in the CLI.
 *
 * @param error - Error to be handled.
 * @returns A promise that resolves with the error passed.
 */
export declare function handler(error: unknown): Promise<unknown>;
/**
 * A function that maps an error to an Abort with the stack trace when coming from the CLI.
 *
 * @param error - Error to be mapped.
 * @returns A promise that resolves with the new error object.
 */
export declare function errorMapper(error: unknown): Promise<unknown>;
/**
 * A function that checks if an error should be reported as unexpected.
 *
 * @param error - Error to be checked.
 * @returns A boolean indicating if the error should be reported as unexpected.
 */
export declare function shouldReportErrorAsUnexpected(error: unknown): boolean;
/**
 * Stack traces usually have file:// - we strip that and also remove the Windows drive designation.
 *
 * @param filePath - Path to be cleaned.
 * @returns The cleaned path.
 */
export declare function cleanSingleStackTracePath(filePath: string): string;
packages/cli-kit/dist/public/node/error/schema.d.ts
import { zod } from '../schema.js';
export declare const JsonErrorCustomSectionSchema: zod.ZodObject<{
    title: zod.ZodOptional<zod.ZodString>;
    body: zod.ZodUnion<[zod.ZodString, zod.ZodArray<zod.ZodArray<zod.ZodString, "many">, "many">]>;
}, "strict", zod.ZodTypeAny, {
    body: string | string[][];
    title?: string | undefined;
}, {
    body: string | string[][];
    title?: string | undefined;
}>;
export declare const JsonAbortErrorSchema: zod.ZodObject<{
    message: zod.ZodString;
    tryMessage: zod.ZodOptional<zod.ZodString>;
    nextSteps: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
    customSections: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
        title: zod.ZodOptional<zod.ZodString>;
        body: zod.ZodUnion<[zod.ZodString, zod.ZodArray<zod.ZodArray<zod.ZodString, "many">, "many">]>;
    }, "strict", zod.ZodTypeAny, {
        body: string | string[][];
        title?: string | undefined;
    }, {
        body: string | string[][];
        title?: string | undefined;
    }>, "many">>;
    type: zod.ZodLiteral<"abort">;
}, "strict", zod.ZodTypeAny, {
    type: "abort";
    message: string;
    nextSteps?: string[] | undefined;
    customSections?: {
        body: string | string[][];
        title?: string | undefined;
    }[] | undefined;
    tryMessage?: string | undefined;
}, {
    type: "abort";
    message: string;
    nextSteps?: string[] | undefined;
    customSections?: {
        body: string | string[][];
        title?: string | undefined;
    }[] | undefined;
    tryMessage?: string | undefined;
}>;
export declare const JsonBugErrorSchema: zod.ZodObject<{
    stack: zod.ZodOptional<zod.ZodString>;
    message: zod.ZodString;
    tryMessage: zod.ZodOptional<zod.ZodString>;
    nextSteps: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
    customSections: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
        title: zod.ZodOptional<zod.ZodString>;
        body: zod.ZodUnion<[zod.ZodString, zod.ZodArray<zod.ZodArray<zod.ZodString, "many">, "many">]>;
    }, "strict", zod.ZodTypeAny, {
        body: string | string[][];
        title?: string | undefined;
    }, {
        body: string | string[][];
        title?: string | undefined;
    }>, "many">>;
    type: zod.ZodLiteral<"bug">;
}, "strict", zod.ZodTypeAny, {
    type: "bug";
    message: string;
    stack?: string | undefined;
    nextSteps?: string[] | undefined;
    customSections?: {
        body: string | string[][];
        title?: string | undefined;
    }[] | undefined;
    tryMessage?: string | undefined;
}, {
    type: "bug";
    message: string;
    stack?: string | undefined;
    nextSteps?: string[] | undefined;
    customSections?: {
        body: string | string[][];
        title?: string | undefined;
    }[] | undefined;
    tryMessage?: string | undefined;
}>;
export declare const JsonExternalErrorSchema: zod.ZodObject<{
    command: zod.ZodString;
    args: zod.ZodArray<zod.ZodString, "many">;
    message: zod.ZodString;
    tryMessage: zod.ZodOptional<zod.ZodString>;
    nextSteps: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
    customSections: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
        title: zod.ZodOptional<zod.ZodString>;
        body: zod.ZodUnion<[zod.ZodString, zod.ZodArray<zod.ZodArray<zod.ZodString, "many">, "many">]>;
    }, "strict", zod.ZodTypeAny, {
        body: string | string[][];
        title?: string | undefined;
    }, {
        body: string | string[][];
        title?: string | undefined;
    }>, "many">>;
    type: zod.ZodLiteral<"external">;
}, "strict", zod.ZodTypeAny, {
    type: "external";
    message: string;
    command: string;
    args: string[];
    nextSteps?: string[] | undefined;
    customSections?: {
        body: string | string[][];
        title?: string | undefined;
    }[] | undefined;
    tryMessage?: string | undefined;
}, {
    type: "external";
    message: string;
    command: string;
    args: string[];
    nextSteps?: string[] | undefined;
    customSections?: {
        body: string | string[][];
        title?: string | undefined;
    }[] | undefined;
    tryMessage?: string | undefined;
}>;
export declare const JsonErrorSchema: zod.ZodUnion<[zod.ZodObject<{
    message: zod.ZodString;
    tryMessage: zod.ZodOptional<zod.ZodString>;
    nextSteps: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
    customSections: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
        title: zod.ZodOptional<zod.ZodString>;
        body: zod.ZodUnion<[zod.ZodString, zod.ZodArray<zod.ZodArray<zod.ZodString, "many">, "many">]>;
    }, "strict", zod.ZodTypeAny, {
        body: string | string[][];
        title?: string | undefined;
    }, {
        body: string | string[][];
        title?: string | undefined;
    }>, "many">>;
    type: zod.ZodLiteral<"abort">;
}, "strict", zod.ZodTypeAny, {
    type: "abort";
    message: string;
    nextSteps?: string[] | undefined;
    customSections?: {
        body: string | string[][];
        title?: string | undefined;
    }[] | undefined;
    tryMessage?: string | undefined;
}, {
    type: "abort";
    message: string;
    nextSteps?: string[] | undefined;
    customSections?: {
        body: string | string[][];
        title?: string | undefined;
    }[] | undefined;
    tryMessage?: string | undefined;
}>, zod.ZodObject<{
    stack: zod.ZodOptional<zod.ZodString>;
    message: zod.ZodString;
    tryMessage: zod.ZodOptional<zod.ZodString>;
    nextSteps: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
    customSections: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
        title: zod.ZodOptional<zod.ZodString>;
        body: zod.ZodUnion<[zod.ZodString, zod.ZodArray<zod.ZodArray<zod.ZodString, "many">, "many">]>;
    }, "strict", zod.ZodTypeAny, {
        body: string | string[][];
        title?: string | undefined;
    }, {
        body: string | string[][];
        title?: string | undefined;
    }>, "many">>;
    type: zod.ZodLiteral<"bug">;
}, "strict", zod.ZodTypeAny, {
    type: "bug";
    message: string;
    stack?: string | undefined;
    nextSteps?: string[] | undefined;
    customSections?: {
        body: string | string[][];
        title?: string | undefined;
    }[] | undefined;
    tryMessage?: string | undefined;
}, {
    type: "bug";
    message: string;
    stack?: string | undefined;
    nextSteps?: string[] | undefined;
    customSections?: {
        body: string | string[][];
        title?: string | undefined;
    }[] | undefined;
    tryMessage?: string | undefined;
}>, zod.ZodObject<{
    command: zod.ZodString;
    args: zod.ZodArray<zod.ZodString, "many">;
    message: zod.ZodString;
    tryMessage: zod.ZodOptional<zod.ZodString>;
    nextSteps: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
    customSections: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
        title: zod.ZodOptional<zod.ZodString>;
        body: zod.ZodUnion<[zod.ZodString, zod.ZodArray<zod.ZodArray<zod.ZodString, "many">, "many">]>;
    }, "strict", zod.ZodTypeAny, {
        body: string | string[][];
        title?: string | undefined;
    }, {
        body: string | string[][];
        title?: string | undefined;
    }>, "many">>;
    type: zod.ZodLiteral<"external">;
}, "strict", zod.ZodTypeAny, {
    type: "external";
    message: string;
    command: string;
    args: string[];
    nextSteps?: string[] | undefined;
    customSections?: {
        body: string | string[][];
        title?: string | undefined;
    }[] | undefined;
    tryMessage?: string | undefined;
}, {
    type: "external";
    message: string;
    command: string;
    args: string[];
    nextSteps?: string[] | undefined;
    customSections?: {
        body: string | string[][];
        title?: string | undefined;
    }[] | undefined;
    tryMessage?: string | undefined;
}>]>;
export declare const jsonErrorOutputSchema: import("../json-output-schema.js").JsonOutputSchema<zod.ZodObject<{
    error: zod.ZodUnion<[zod.ZodObject<{
        message: zod.ZodString;
        tryMessage: zod.ZodOptional<zod.ZodString>;
        nextSteps: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
        customSections: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
            title: zod.ZodOptional<zod.ZodString>;
            body: zod.ZodUnion<[zod.ZodString, zod.ZodArray<zod.ZodArray<zod.ZodString, "many">, "many">]>;
        }, "strict", zod.ZodTypeAny, {
            body: string | string[][];
            title?: string | undefined;
        }, {
            body: string | string[][];
            title?: string | undefined;
        }>, "many">>;
        type: zod.ZodLiteral<"abort">;
    }, "strict", zod.ZodTypeAny, {
        type: "abort";
        message: string;
        nextSteps?: string[] | undefined;
        customSections?: {
            body: string | string[][];
            title?: string | undefined;
        }[] | undefined;
        tryMessage?: string | undefined;
    }, {
        type: "abort";
        message: string;
        nextSteps?: string[] | undefined;
        customSections?: {
            body: string | string[][];
            title?: string | undefined;
        }[] | undefined;
        tryMessage?: string | undefined;
    }>, zod.ZodObject<{
        stack: zod.ZodOptional<zod.ZodString>;
        message: zod.ZodString;
        tryMessage: zod.ZodOptional<zod.ZodString>;
        nextSteps: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
        customSections: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
            title: zod.ZodOptional<zod.ZodString>;
            body: zod.ZodUnion<[zod.ZodString, zod.ZodArray<zod.ZodArray<zod.ZodString, "many">, "many">]>;
        }, "strict", zod.ZodTypeAny, {
            body: string | string[][];
            title?: string | undefined;
        }, {
            body: string | string[][];
            title?: string | undefined;
        }>, "many">>;
        type: zod.ZodLiteral<"bug">;
    }, "strict", zod.ZodTypeAny, {
        type: "bug";
        message: string;
        stack?: string | undefined;
        nextSteps?: string[] | undefined;
        customSections?: {
            body: string | string[][];
            title?: string | undefined;
        }[] | undefined;
        tryMessage?: string | undefined;
    }, {
        type: "bug";
        message: string;
        stack?: string | undefined;
        nextSteps?: string[] | undefined;
        customSections?: {
            body: string | string[][];
            title?: string | undefined;
        }[] | undefined;
        tryMessage?: string | undefined;
    }>, zod.ZodObject<{
        command: zod.ZodString;
        args: zod.ZodArray<zod.ZodString, "many">;
        message: zod.ZodString;
        tryMessage: zod.ZodOptional<zod.ZodString>;
        nextSteps: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
        customSections: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
            title: zod.ZodOptional<zod.ZodString>;
            body: zod.ZodUnion<[zod.ZodString, zod.ZodArray<zod.ZodArray<zod.ZodString, "many">, "many">]>;
        }, "strict", zod.ZodTypeAny, {
            body: string | string[][];
            title?: string | undefined;
        }, {
            body: string | string[][];
            title?: string | undefined;
        }>, "many">>;
        type: zod.ZodLiteral<"external">;
    }, "strict", zod.ZodTypeAny, {
        type: "external";
        message: string;
        command: string;
        args: string[];
        nextSteps?: string[] | undefined;
        customSections?: {
            body: string | string[][];
            title?: string | undefined;
        }[] | undefined;
        tryMessage?: string | undefined;
    }, {
        type: "external";
        message: string;
        command: string;
        args: string[];
        nextSteps?: string[] | undefined;
        customSections?: {
            body: string | string[][];
            title?: string | undefined;
        }[] | undefined;
        tryMessage?: string | undefined;
    }>]>;
}, "strict", zod.ZodTypeAny, {
    error: {
        type: "abort";
        message: string;
        nextSteps?: string[] | undefined;
        customSections?: {
            body: string | string[][];
            title?: string | undefined;
        }[] | undefined;
        tryMessage?: string | undefined;
    } | {
        type: "bug";
        message: string;
        stack?: string | undefined;
        nextSteps?: string[] | undefined;
        customSections?: {
            body: string | string[][];
            title?: string | undefined;
        }[] | undefined;
        tryMessage?: string | undefined;
    } | {
        type: "external";
        message: string;
        command: string;
        args: string[];
        nextSteps?: string[] | undefined;
        customSections?: {
            body: string | string[][];
            title?: string | undefined;
        }[] | undefined;
        tryMessage?: string | undefined;
    };
}, {
    error: {
        type: "abort";
        message: string;
        nextSteps?: string[] | undefined;
        customSections?: {
            body: string | string[][];
            title?: string | undefined;
        }[] | undefined;
        tryMessage?: string | undefined;
    } | {
        type: "bug";
        message: string;
        stack?: string | undefined;
        nextSteps?: string[] | undefined;
        customSections?: {
            body: string | string[][];
            title?: string | undefined;
        }[] | undefined;
        tryMessage?: string | undefined;
    } | {
        type: "external";
        message: string;
        command: string;
        args: string[];
        nextSteps?: string[] | undefined;
        customSections?: {
            body: string | string[][];
            title?: string | undefined;
        }[] | undefined;
        tryMessage?: string | undefined;
    };
}>>;
packages/cli-kit/dist/public/node/error/types.d.ts
export type JsonErrorType = 'abort' | 'bug' | 'external';
export interface JsonErrorCustomSection {
    title?: string;
    body: string | string[][];
}
interface JsonErrorBase {
    message: string;
    tryMessage?: string;
    nextSteps?: string[];
    customSections?: JsonErrorCustomSection[];
}
export interface JsonAbortError extends JsonErrorBase {
    type: 'abort';
}
export interface JsonBugError extends JsonErrorBase {
    type: 'bug';
    stack?: string;
}
export interface JsonExternalError extends JsonErrorBase {
    type: 'external';
    command: string;
    args: string[];
}
export type JsonError = JsonAbortError | JsonBugError | JsonExternalError;
export interface JsonErrorDocument {
    error: JsonError;
}
export {};

Existing type declarations

packages/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;
@@ -21,6 +24,7 @@ declare abstract class BaseCommand extends Command {
     protected init(): Promise<unknown>;
     protected showNpmFlagWarning(): void;
     protected exitWithTimestampWhenEnvVariablePresent(): void;
+    protected exitWithJsonSchemaWhenRequested(): void;
     protected parse<TFlags extends FlagOutput & {
         path?: string;
         verbose?: boolean;
packages/cli-kit/dist/public/node/error.d.ts
@@ -1,87 +1 @@
-import { OutputMessage } from './output.js';
-import { type InlineToken, type TokenItem } from '../../private/node/ui/components/token-item.js';
-import type { AlertCustomSection } from './ui.js';
-export declare enum FatalErrorType {
-    Abort = 0,
-    AbortSilent = 1,
-    Bug = 2
-}
-export declare class CancelExecution extends Error {
-}
-/**
- * A fatal error represents an error shouldn't be rescued and that causes the execution to terminate.
- * There shouldn't be code that catches fatal errors.
- */
-export declare abstract class FatalError extends Error {
-    tryMessage: TokenItem | null;
-    type: FatalErrorType;
-    nextSteps?: TokenItem<InlineToken>[];
-    formattedMessage?: TokenItem;
-    customSections?: AlertCustomSection[];
-    skipOclifErrorHandling: boolean;
-    /**
-     * Creates a new FatalError error.
-     *
-     * @param message - The error message.
-     * @param type - The type of fatal error.
-     * @param tryMessage - The message that recommends next steps to the user.
-     * You can pass a string a {@link TokenizedString} or a {@link TokenItem}
-     * if you need to style the message inside the error Banner component.
-     * @param nextSteps - Message to show as "next steps" with suggestions to solve the issue.
-     * @param customSections - Custom sections to show in the error banner. To be used if nextSteps is not enough.
-     */
-    constructor(message: TokenItem | OutputMessage, type: FatalErrorType, tryMessage?: TokenItem | OutputMessage | null, nextSteps?: TokenItem<InlineToken>[], customSections?: AlertCustomSection[]);
-}
-/**
- * An abort error is a fatal error that shouldn't be reported as a bug.
- * Those usually represent unexpected scenarios that we can't handle and that usually require some action from the developer.
- */
-export declare class AbortError extends FatalError {
-    constructor(message: TokenItem | OutputMessage, tryMessage?: TokenItem | OutputMessage | null, nextSteps?: TokenItem<InlineToken>[], customSections?: AlertCustomSection[]);
-}
-/**
- * An external error is similar to Abort but has extra command and args attributes.
- * This is useful to represent errors coming from external commands, usually executed by execa.
- */
-export declare class ExternalError extends FatalError {
-    command: string;
-    args: string[];
-    constructor(message: OutputMessage, command: string, args: string[], tryMessage?: TokenItem | OutputMessage | null);
-}
-export declare class AbortSilentError extends FatalError {
-    constructor();
-}
-/**
- * A bug error is an error that represents a bug and therefore should be reported.
- */
-export declare class BugError extends FatalError {
-    constructor(message: TokenItem | OutputMessage, tryMessage?: TokenItem | OutputMessage | null);
-}
-/**
- * A function that handles errors that blow up in the CLI.
- *
- * @param error - Error to be handled.
- * @returns A promise that resolves with the error passed.
- */
-export declare function handler(error: unknown): Promise<unknown>;
-/**
- * A function that maps an error to an Abort with the stack trace when coming from the CLI.
- *
- * @param error - Error to be mapped.
- * @returns A promise that resolves with the new error object.
- */
-export declare function errorMapper(error: unknown): Promise<unknown>;
-/**
- * A function that checks if an error should be reported as unexpected.
- *
- * @param error - Error to be checked.
- * @returns A boolean indicating if the error should be reported as unexpected.
- */
-export declare function shouldReportErrorAsUnexpected(error: unknown): boolean;
-/**
- * Stack traces usually have file:// - we strip that and also remove the Windows drive designation.
- *
- * @param filePath - Path to be cleaned.
- * @returns The cleaned path.
- */
-export declare function cleanSingleStackTracePath(filePath: string): string;
\ No newline at end of file
+export * from './error/index.js';
\ No newline at end of file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-changelog This PR doesn't include a changeset entry. Is an internal only change not relevant to end users.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant