Add JSON schema to organization list - #8526
Conversation
2f2d039 to
f0e64b3
Compare
d6ce1ba to
726d67c
Compare
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/private/node/command-event-context.d.tsimport { type CommandEvent, type CommandEventChannelOptions, type CommandEventEmissionOptions, type CommandEventInput } from '../../public/common/command-events.js';
export type CommandEventOutputMode = 'text' | 'json';
interface RunWithCommandEventsOptions extends CommandEventChannelOptions<CommandEvent> {
outputMode?: CommandEventOutputMode;
}
/**
* Runs a command execution with an event channel available to all nested asynchronous work.
*
* @param options - The event sink, clock, and output mode used by the channel.
* @param execute - The command execution to run with the channel.
* @returns The result of the command execution.
*/
export declare function runWithCommandEvents<TResult>(options: RunWithCommandEventsOptions, execute: () => TResult): TResult;
/**
* Emits an event for the current command execution.
*
* Events emitted outside a command execution are ignored.
*
* @param event - The event to emit before its timestamp is added.
* @param options - Presentation details that are not included in the event.
*/
export declare function emitCommandEvent(event: CommandEventInput, options?: CommandEventEmissionOptions): void;
/**
* Returns how command events are presented for the current execution.
*
* @returns The current event output mode, or undefined outside a command event context.
*/
export declare function commandEventOutputMode(): CommandEventOutputMode | undefined;
export {};
packages/cli-kit/dist/private/node/command-event-output.d.tsimport { type CommandEvent } from '../../public/common/command-events.js';
/**
* Writes a command event as JSON without routing it back through the command event context.
*
* @param event - The event to write.
*/
export declare function outputCommandEventAsJson(event: CommandEvent): void;
packages/cli-kit/dist/private/node/json-error.d.tsinterface FatalErrorLike {
type?: number;
message?: unknown;
formattedMessage?: unknown;
tryMessage?: unknown;
nextSteps?: unknown;
customSections?: unknown;
stack?: unknown;
command?: unknown;
args?: unknown;
details?: 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.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", "error"]>;
message: z.ZodString;
code: z.ZodOptional<z.ZodString>;
}, "strict", z.ZodTypeAny, {
type: "diagnostic";
message: string;
timestamp: string;
level: "info" | "error" | "debug" | "warning";
code?: string | undefined;
}, {
type: "diagnostic";
message: string;
timestamp: string;
level: "info" | "error" | "debug" | "warning";
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;
status: z.ZodEnum<["started", "updated", "completed"]>;
operation: z.ZodString;
message: z.ZodOptional<z.ZodString>;
current: z.ZodOptional<z.ZodNumber>;
total: z.ZodOptional<z.ZodNumber>;
}, "strict", z.ZodTypeAny, {
type: "progress";
status: "started" | "updated" | "completed";
timestamp: string;
operation: string;
message?: string | undefined;
current?: number | undefined;
total?: number | undefined;
}, {
type: "progress";
status: "started" | "updated" | "completed";
timestamp: string;
operation: string;
message?: string | undefined;
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", "error"]>;
message: z.ZodString;
code: z.ZodOptional<z.ZodString>;
}, "strict", z.ZodTypeAny, {
type: "diagnostic";
message: string;
timestamp: string;
level: "info" | "error" | "debug" | "warning";
code?: string | undefined;
}, {
type: "diagnostic";
message: string;
timestamp: string;
level: "info" | "error" | "debug" | "warning";
code?: string | undefined;
}>, z.ZodObject<{
type: z.ZodLiteral<"progress">;
timestamp: z.ZodString;
status: z.ZodEnum<["started", "updated", "completed"]>;
operation: z.ZodString;
message: z.ZodOptional<z.ZodString>;
current: z.ZodOptional<z.ZodNumber>;
total: z.ZodOptional<z.ZodNumber>;
}, "strict", z.ZodTypeAny, {
type: "progress";
status: "started" | "updated" | "completed";
timestamp: string;
operation: string;
message?: string | undefined;
current?: number | undefined;
total?: number | undefined;
}, {
type: "progress";
status: "started" | "updated" | "completed";
timestamp: string;
operation: string;
message?: string | undefined;
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;
/** Presentation details that are not included in the emitted event. */
export interface CommandEventEmissionOptions {
/** The event is already visible in the command's text UI. */
alreadyRendered?: boolean;
}
/** Receives one timestamped event from a command execution. */
export type CommandEventSink<TEvent extends CommandEvent = CommandEvent> = (event: TEvent, options?: CommandEventEmissionOptions) => void;
/** Emits timestamped side events from one command execution. */
export interface CommandEventChannel<TEvent extends CommandEvent = CommandEvent> {
emit: (event: CommandEventInput<TEvent>, options?: CommandEventEmissionOptions) => 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.
* Adapters validate events at their output boundary; the channel preserves domain-specific event fields.
*
* @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';
export { commandEventOutputMode, emitCommandEvent, runWithCommandEvents, type CommandEventOutputMode, } from '../../private/node/command-event-context.js';
/**
* Runs the complete CLI lifecycle with the event presentation selected by its arguments.
*
* @param argv - The command arguments used to determine whether JSON output is enabled.
* @param execute - The command lifecycle to run.
* @returns The result of the command lifecycle.
*/
export declare function runWithCommandEventsForCommand<TResult>(argv: string[], execute: () => TResult): TResult;
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", "error"]>;
message: import("zod").ZodString;
code: import("zod").ZodOptional<import("zod").ZodString>;
}, "strict", import("zod").ZodTypeAny, {
type: "diagnostic";
message: string;
timestamp: string;
level: "info" | "error" | "debug" | "warning";
code?: string | undefined;
}, {
type: "diagnostic";
message: string;
timestamp: string;
level: "info" | "error" | "debug" | "warning";
code?: string | undefined;
}>, import("zod").ZodObject<{
type: import("zod").ZodLiteral<"progress">;
timestamp: import("zod").ZodString;
status: import("zod").ZodEnum<["started", "updated", "completed"]>;
operation: import("zod").ZodString;
message: import("zod").ZodOptional<import("zod").ZodString>;
current: import("zod").ZodOptional<import("zod").ZodNumber>;
total: import("zod").ZodOptional<import("zod").ZodNumber>;
}, "strict", import("zod").ZodTypeAny, {
type: "progress";
status: "started" | "updated" | "completed";
timestamp: string;
operation: string;
message?: string | undefined;
current?: number | undefined;
total?: number | undefined;
}, {
type: "progress";
status: "started" | "updated" | "completed";
timestamp: string;
operation: string;
message?: string | undefined;
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.tsimport { zodToJsonSchema } from 'zod-to-json-schema';
import type { ZodTypeAny, 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 jsonSchema: ReturnType<typeof zodToJsonSchema>;
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 JSON Schema for a command's JSON output.
*
* @param options - The root schema 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>;
export {};
packages/cli-kit/dist/public/node/error/index.d.tsimport { 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[];
/** Selected JSON-serializable data to include in JSON errors. Never attach the raw error or request. */
details?: unknown;
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.tsimport { 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">>;
details: zod.ZodOptional<zod.ZodUnknown>;
type: zod.ZodLiteral<"abort">;
}, "strict", zod.ZodTypeAny, {
type: "abort";
message: string;
nextSteps?: string[] | undefined;
customSections?: {
body: string | string[][];
title?: string | undefined;
}[] | undefined;
details?: unknown;
tryMessage?: string | undefined;
}, {
type: "abort";
message: string;
nextSteps?: string[] | undefined;
customSections?: {
body: string | string[][];
title?: string | undefined;
}[] | undefined;
details?: unknown;
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">>;
details: zod.ZodOptional<zod.ZodUnknown>;
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;
details?: unknown;
tryMessage?: string | undefined;
}, {
type: "bug";
message: string;
stack?: string | undefined;
nextSteps?: string[] | undefined;
customSections?: {
body: string | string[][];
title?: string | undefined;
}[] | undefined;
details?: unknown;
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">>;
details: zod.ZodOptional<zod.ZodUnknown>;
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;
details?: unknown;
tryMessage?: string | undefined;
}, {
type: "external";
message: string;
command: string;
args: string[];
nextSteps?: string[] | undefined;
customSections?: {
body: string | string[][];
title?: string | undefined;
}[] | undefined;
details?: unknown;
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">>;
details: zod.ZodOptional<zod.ZodUnknown>;
type: zod.ZodLiteral<"abort">;
}, "strict", zod.ZodTypeAny, {
type: "abort";
message: string;
nextSteps?: string[] | undefined;
customSections?: {
body: string | string[][];
title?: string | undefined;
}[] | undefined;
details?: unknown;
tryMessage?: string | undefined;
}, {
type: "abort";
message: string;
nextSteps?: string[] | undefined;
customSections?: {
body: string | string[][];
title?: string | undefined;
}[] | undefined;
details?: unknown;
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">>;
details: zod.ZodOptional<zod.ZodUnknown>;
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;
details?: unknown;
tryMessage?: string | undefined;
}, {
type: "bug";
message: string;
stack?: string | undefined;
nextSteps?: string[] | undefined;
customSections?: {
body: string | string[][];
title?: string | undefined;
}[] | undefined;
details?: unknown;
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">>;
details: zod.ZodOptional<zod.ZodUnknown>;
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;
details?: unknown;
tryMessage?: string | undefined;
}, {
type: "external";
message: string;
command: string;
args: string[];
nextSteps?: string[] | undefined;
customSections?: {
body: string | string[][];
title?: string | undefined;
}[] | undefined;
details?: unknown;
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">>;
details: zod.ZodOptional<zod.ZodUnknown>;
type: zod.ZodLiteral<"abort">;
}, "strict", zod.ZodTypeAny, {
type: "abort";
message: string;
nextSteps?: string[] | undefined;
customSections?: {
body: string | string[][];
title?: string | undefined;
}[] | undefined;
details?: unknown;
tryMessage?: string | undefined;
}, {
type: "abort";
message: string;
nextSteps?: string[] | undefined;
customSections?: {
body: string | string[][];
title?: string | undefined;
}[] | undefined;
details?: unknown;
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">>;
details: zod.ZodOptional<zod.ZodUnknown>;
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;
details?: unknown;
tryMessage?: string | undefined;
}, {
type: "bug";
message: string;
stack?: string | undefined;
nextSteps?: string[] | undefined;
customSections?: {
body: string | string[][];
title?: string | undefined;
}[] | undefined;
details?: unknown;
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">>;
details: zod.ZodOptional<zod.ZodUnknown>;
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;
details?: unknown;
tryMessage?: string | undefined;
}, {
type: "external";
message: string;
command: string;
args: string[];
nextSteps?: string[] | undefined;
customSections?: {
body: string | string[][];
title?: string | undefined;
}[] | undefined;
details?: unknown;
tryMessage?: string | undefined;
}>]>;
}, "strict", zod.ZodTypeAny, {
error: {
type: "abort";
message: string;
nextSteps?: string[] | undefined;
customSections?: {
body: string | string[][];
title?: string | undefined;
}[] | undefined;
details?: unknown;
tryMessage?: string | undefined;
} | {
type: "bug";
message: string;
stack?: string | undefined;
nextSteps?: string[] | undefined;
customSections?: {
body: string | string[][];
title?: string | undefined;
}[] | undefined;
details?: unknown;
tryMessage?: string | undefined;
} | {
type: "external";
message: string;
command: string;
args: string[];
nextSteps?: string[] | undefined;
customSections?: {
body: string | string[][];
title?: string | undefined;
}[] | undefined;
details?: unknown;
tryMessage?: string | undefined;
};
}, {
error: {
type: "abort";
message: string;
nextSteps?: string[] | undefined;
customSections?: {
body: string | string[][];
title?: string | undefined;
}[] | undefined;
details?: unknown;
tryMessage?: string | undefined;
} | {
type: "bug";
message: string;
stack?: string | undefined;
nextSteps?: string[] | undefined;
customSections?: {
body: string | string[][];
title?: string | undefined;
}[] | undefined;
details?: unknown;
tryMessage?: string | undefined;
} | {
type: "external";
message: string;
command: string;
args: string[];
nextSteps?: string[] | undefined;
customSections?: {
body: string | string[][];
title?: string | undefined;
}[] | undefined;
details?: unknown;
tryMessage?: string | undefined;
};
}>>;
packages/cli-kit/dist/public/node/error/types.d.tsimport type { JsonAbortErrorSchema, JsonBugErrorSchema, JsonErrorCustomSectionSchema, JsonErrorSchema, JsonExternalErrorSchema, jsonErrorOutputSchema } from './schema.js';
import type { z } from 'zod';
export type JsonErrorCustomSection = z.infer<typeof JsonErrorCustomSectionSchema>;
export type JsonAbortError = z.infer<typeof JsonAbortErrorSchema>;
export type JsonBugError = z.infer<typeof JsonBugErrorSchema>;
export type JsonExternalError = z.infer<typeof JsonExternalErrorSchema>;
export type JsonError = z.infer<typeof JsonErrorSchema>;
export type JsonErrorType = JsonError['type'];
export type JsonErrorDocument = z.infer<typeof jsonErrorOutputSchema.schema>;
Existing type declarationspackages/cli-kit/dist/public/node/base-command.d.ts@@ -1,3 +1,4 @@
+import { type JsonOutputSchema } from './json-output-schema.js';
import { Command } from '@oclif/core';
import { OutputFlags, Input, ParserOutput, FlagInput, OutputArgs } from '@oclif/core/parser';
export type ArgOutput = OutputArgs<any>;
@@ -10,17 +11,23 @@ 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 descriptionForHelp(): string | undefined;
+ /** @deprecated Use descriptionForHelp instead. */
static descriptionWithoutMarkdown(): string | undefined;
static analyticsNameOverride(): string | undefined;
static analyticsStopCommand(): string | undefined;
catch(error: Error & {
skipOclifErrorHandling: boolean;
}): Promise<void>;
+ protected _run<T>(): Promise<T>;
protected init(): Promise<unknown>;
protected showNpmFlagWarning(): void;
protected exitWithTimestampWhenEnvVariablePresent(): void;
+ protected exitWithJsonSchemaWhenRequested(): Promise<void>;
protected parse<TFlags extends FlagOutput & {
path?: string;
verbose?: boolean;
packages/cli-kit/dist/public/node/environment.d.ts@@ -42,9 +42,10 @@ export declare function getIdentityTokenInformation(): {
* Checks if the JSON output is enabled via flag (--json or -j) or environment variable (SHOPIFY_FLAG_JSON).
*
* @param environment - Process environment variables.
+ * @param argv - Command arguments to inspect for JSON flags.
* @returns True if the JSON output is enabled, false otherwise.
*/
-export declare function jsonOutputEnabled(environment?: NodeJS.ProcessEnv): boolean;
+export declare function jsonOutputEnabled(environment?: NodeJS.ProcessEnv, argv?: string[]): boolean;
/**
* If true, the CLI should not use the network level retry.
*
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
packages/cli-kit/dist/public/node/output.d.ts@@ -68,6 +68,12 @@ export declare const clearCollectedLogs: () => void;
* @param content - The content to be output to the user.
*/
export declare function outputResult(content: OutputMessage): void;
+/**
+ * Waits for queued stdout writes to reach their destination before the process exits.
+ *
+ * @returns A promise that resolves when stdout has flushed.
+ */
+export declare function flushStdout(): Promise<void>;
/**
* Logs information at the info level.
* Info messages don't get additional formatting.
|
|
/snapit |
|
🫰✨ Thanks @gonzaloriestra! Your snapshot has been published to npm. Test the snapshot by installing your package globally: pnpm i -g --@shopify:registry=https://registry.npmjs.org @shopify/cli@0.0.0-snapshot-20260915114647Caution After installing, validate the version by running |
d11c332 to
02fbf6e
Compare
Assisted-By: devx/54e07dfa-7888-4c74-92b5-c10e1b9be5ed
Assisted-By: devx/b173c0b4-2d65-4396-a5eb-d3c4d4c3a4ff
6a07888 to
bdc6432
Compare
Assisted-By: devx/8b520d2e-bc34-4a3d-b5fa-748b2fff362e
There was a problem hiding this comment.
🟢 Approval recommended
No unresolved blocking issues were identified.
Pull request overview
Adds a typed, discoverable JSON contract to shopify organization list, including public organization details while preserving table output and empty JSON behavior.
Changes:
- Adds strict JSON schema validation and generated documentation.
- Exposes organization status, shop count, and URL.
- Updates models, clients, tests, lint configuration, and changeset.
File summaries
| File | Reviewed change |
|---|---|
packages/organizations/src/index.ts |
Exports organization detail types and statuses. |
packages/organizations/src/cli/services/select.test.ts |
Updates organization fixtures. |
packages/organizations/src/cli/services/fetch.ts |
Maps public organization details. |
packages/organizations/src/cli/services/fetch.test.ts |
Tests detailed organization mapping. |
packages/organizations/src/cli/models/organization.ts |
Defines organization detail models. |
packages/organizations/src/cli/api/graphql/business-platform-destinations/queries/organizations.graphql |
Requests additional organization fields. |
packages/organizations/src/cli/api/graphql/business-platform-destinations/generated/types.d.ts |
Adds the generated status enum. |
packages/organizations/src/cli/api/graphql/business-platform-destinations/generated/organizations.ts |
Updates generated query types and document. |
packages/eslint-plugin-cli/rules/json-output-command-exceptions.js |
Removes the command’s JSON exception. |
packages/cli/README.md |
Documents the generated JSON schema. |
packages/cli/oclif.manifest.json |
Updates command metadata. |
packages/app/src/cli/utilities/developer-platform-client/app-management-client.ts |
Propagates organization details. |
packages/app/src/cli/utilities/developer-platform-client/app-management-client.test.ts |
Tests detail propagation. |
packages/app/src/cli/utilities/developer-platform-client.ts |
Updates the client interface. |
packages/app/src/cli/services/organization/list/types.ts |
Defines the strict JSON schema. |
packages/app/src/cli/services/organization/list/result.ts |
Separates JSON and table presentation. |
packages/app/src/cli/services/organization/list/result.test.ts |
Tests both output formats. |
packages/app/src/cli/services/organization/list.ts |
Returns typed organization list data. |
packages/app/src/cli/services/organization/list.test.ts |
Tests result mapping and schema validation. |
packages/app/src/cli/services/info.test.ts |
Updates organization fixtures. |
packages/app/src/cli/services/dev/fetch.ts |
Updates fetched organization types. |
packages/app/src/cli/services/dev/fetch.test.ts |
Updates fetch fixtures. |
packages/app/src/cli/services/context.test.ts |
Updates organization fixtures. |
packages/app/src/cli/services/app/env/show.test.ts |
Updates organization fixtures. |
packages/app/src/cli/services/app/config/link-service.test.ts |
Updates organization fixtures. |
packages/app/src/cli/models/organization.ts |
Adds the detailed organization type. |
packages/app/src/cli/models/app/app.test-data.ts |
Updates client test data. |
packages/app/src/cli/commands/organization/list.ts |
Integrates JSON schema and output handling. |
packages/app/src/cli/commands/organization/list.test.ts |
Tests command output and error behavior. |
.changeset/bright-organizations-list.md |
Records the user-facing feature change. |
Review details
- Files reviewed: 28/30 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
@gonzaloriestra I expanded the contract slightly per our conversation, I'd appreciate your 👁️ 👁️ on the changes before I merge. |
WHY are these changes introduced?
Expose
shopify organization list --jsonas a typed, discoverable contract. JSON consumers also need public organization data that the command can return without another API request.This PR supersedes #8516, which could not be reopened after its base branch was restacked.
Related to shop/issues-develop#23670
WHAT is this pull request doing?
OrganizationListResultschema and generated--json-schemadocumentation.id,gid,name,status,shopCount, andurlin each JSON organization.NoOrgError.Normal output remains:
The matching JSON output is:
{ "organizations": [ { "id": "123", "gid": "gid://organization/Organization/123", "name": "Test Organization", "status": "ACTIVE", "shopCount": 3, "url": "https://admin.shopify.com/organization/123" } ] }How to manually test your changes?
Confirm that
--json-schemaincludes all sixOrganizationListEntryfields. An account without accessible organizations still receives{"organizations":[]}in JSON mode.Checklist
patchfor bug fixes ·minorfor new features ·majorfor breaking changes) and added a changeset withpnpm changeset add