/// import { z } from 'zod'; import { Evt } from 'evt'; import { T_IO_RESPONSE, T_IO_PROPS, T_IO_RETURNS, T_IO_METHOD_NAMES, T_IO_DISPLAY_METHOD_NAMES, T_IO_INPUT_METHOD_NAMES, T_IO_MULTIPLEABLE_METHOD_NAMES } from '../ioSchema'; import Logger from './Logger'; import { AnyIOComponent } from './IOComponent'; import { ExclusiveIOPromise, IOGroupPromise, IOPromiseValidator, DisplayIOPromise, InputIOPromise, MultipleableIOPromise, WithChoicesIOPromiseValidator } from './IOPromise'; import { IORenderSender, ResponseHandlerFn, MaybeOptionalGroupIOPromise, ExclusiveIOComponentFunction, IOComponentDefinition, DisplayIOComponentFunction, RequiredPropsDisplayIOComponentFunction, InputIOComponentFunction, RequiredPropsInputIOComponentFunction, GroupConfig, ChoiceButtonConfig, RequiredPropsMultipleableInputIOComponentFunction, MultipleableInputIOComponentFunction } from '../types'; interface ClientConfig { logger: Logger; send: IORenderSender; isDemo?: boolean; displayResolvesImmediately?: boolean; } export declare type IOClientRenderReturnValues = { choice?: string; returnValue: { [Idx in keyof Components]: Components[Idx] extends AnyIOComponent ? z.infer | undefined : Components[Idx]; }; }; export declare type IOClientRenderValidator = IOPromiseValidator> | WithChoicesIOPromiseValidator['returnValue']>; /** * The client class that handles IO calls for a given transaction. * * Each transaction has its own IOClient which creates the IO argument * passed to action handlers that are aware of the transaction in order * to transmit IO calls correctly. */ export declare class IOClient { logger: Logger; send: IORenderSender; isDemo: boolean; displayResolvesImmediately: boolean | undefined; previousInputGroupKey: string | undefined; onResponseHandlers: Map; inlineActionKeys: Set; isCanceled: boolean; constructor(config: ClientConfig); /** * Creates a render loop for an IO call. * * Given a list of components (potentially only one if not rendering a group) * this method is responsible for sending the initial render call and handling * responses (returns, state updates, or cancellations) from Interval. * Resolves when it receives final responses or from Interval, * or throws an IOError of kind `CANCELED` if canceled. */ renderComponents({ components, validator: groupValidator, choiceButtons, }: { components: Components; validator?: IOClientRenderValidator; choiceButtons?: ChoiceButtonConfig[]; }): Promise>; /** * Combines multiple I/O method calls into a single form. * * Individual I/O methods await within your action until user input is provided, such that each I/O method call results in a distinct step within the generated app. `io.group` allows you to group multiple I/O methods together to request input all at once in a single step. * * Custom validation can be performed on groups by chaining a `.validate()` method call to the group. * * **Usage:** * * ```typescript * const [name, email, age] = await io.group([ * io.input.text("Name"), * io.input.email("Email"), * io.input.number("Age"), * ]); * * ``` * * ```typescript * const { name, email, age } = await io.group({ * name: io.input.text("Name"), * email: io.input.email("Email"), * age: io.input.number("Age"), * }); * * ``` */ group | MaybeOptionalGroupIOPromise[]>(promises: IOPromises, props?: GroupConfig): IOGroupPromise ? IOPromises extends infer T ? { [K in keyof T]: ReturnType; } : never : IOPromises extends [MaybeOptionalGroupIOPromise, ...MaybeOptionalGroupIOPromise[]] ? import("./IOPromise").IOGroupReturnValues : unknown[]>; getPromiseProps, Output = T_IO_RETURNS, DefaultValue = Output>(methodName: MethodName, inputProps?: Props, componentDef?: IOComponentDefinition, onPropsUpdate?: Evt>): { methodName: MethodName; props: T_IO_PROPS; valueGetter: (r: T_IO_RETURNS) => Output; defaultValueGetter: (defaultValue: DefaultValue) => Output; onStateChange: ((newState: import("../ioSchema").T_IO_STATE) => Promise>) | undefined; }; createIOMethod, Output = T_IO_RETURNS>(methodName: MethodName, config?: { propsRequired?: false; componentDef?: IOComponentDefinition; }): MultipleableInputIOComponentFunction; createIOMethod, Output = T_IO_RETURNS>(methodName: MethodName, config: { propsRequired?: true; componentDef?: IOComponentDefinition; }): RequiredPropsMultipleableInputIOComponentFunction; createIOMethod, Output = T_IO_RETURNS>(methodName: MethodName, config?: { propsRequired?: false; componentDef?: IOComponentDefinition; }): DisplayIOComponentFunction; createIOMethod, Output = T_IO_RETURNS>(methodName: MethodName, config: { propsRequired?: true; componentDef?: IOComponentDefinition; }): RequiredPropsDisplayIOComponentFunction; createIOMethod, Output = T_IO_RETURNS>(methodName: MethodName, config?: { propsRequired?: false; componentDef?: IOComponentDefinition; }): InputIOComponentFunction; createIOMethod, Output = T_IO_RETURNS>(methodName: MethodName, config: { propsRequired?: true; componentDef?: IOComponentDefinition; }): RequiredPropsInputIOComponentFunction; createExclusiveIOMethod, Output = T_IO_RETURNS>(methodName: MethodName, { componentDef, demoUnsupported, }?: { componentDef?: IOComponentDefinition; demoUnsupported?: boolean; }): ExclusiveIOComponentFunction; createCredentialsIOMethod>(): (serviceName: string, props?: Props) => ExclusiveIOPromise<"CREDENTIALS", { params?: Record | undefined; }, { secret?: string | undefined; token: string; }>; /** * The namespace of I/O methods available in action handlers. */ get io(): { group: | [MaybeOptionalGroupIOPromise, ...MaybeOptionalGroupIOPromise[]] | MaybeOptionalGroupIOPromise[]>(promises: IOPromises, props?: GroupConfig | undefined) => IOGroupPromise ? IOPromises extends infer T ? { [K in keyof T]: ReturnType; } : never : IOPromises extends [MaybeOptionalGroupIOPromise, ...MaybeOptionalGroupIOPromise[]] ? import("./IOPromise").IOGroupReturnValues : unknown[]>; /** * Requests confirmation of an action using a full-screen dialog box. * * **Note:** `io.confirm` is not supported within an `io.group`. * * **Usage:** * * ```typescript * const shouldDelete = await io.confirm("Delete this user account?", { * helpText: "All of their data will be deleted immediately.", * }); * ``` */ confirm: ExclusiveIOComponentFunction<"CONFIRM", { helpText?: string | undefined; }, boolean>; /** * Requests multi-factor authentication or password confirmation of the person running the action. * * **Note:** `io.confirmIdentity` is not supported within an `io.group`. * * **Usage:** * * ```typescript * const shouldDelete = await io.confirmIdentity("This is a sensitive action."); * ``` */ confirmIdentity: ExclusiveIOComponentFunction<"CONFIRM_IDENTITY", { gracePeriodMs?: number | undefined; }, boolean>; /** * Allows searching for arbitrary results from a search box. * * **Usage:** * * ```typescript * const user = await io.search("Search for a user", { * renderResult: user => ({ * label: user.name, * description: user.email, * image: { * url: user.avatar, * size: "small", * }, * }), * onSearch: async query => { * return users.filter(user => user.name.includes(query)); * }, * }); * ``` */ search: (label: string, props: { placeholder?: string | undefined; helpText?: string | undefined; disabled?: boolean | undefined; initialResults?: Result[] | undefined; defaultValue?: Result | undefined; renderResult: (result: Result) => string | number | boolean | Date | { label: string | number | boolean | Date; description?: string | undefined; image?: { alt?: string | undefined; size?: "thumbnail" | "small" | "medium" | "large" | undefined; width?: "thumbnail" | "small" | "medium" | "large" | undefined; height?: "thumbnail" | "small" | "medium" | "large" | undefined; url: string; } | undefined; imageUrl?: string | undefined; }; onSearch: (query: string) => Promise; }) => MultipleableIOPromise<"SEARCH", { defaultValue?: string | null | undefined; disabled?: boolean | undefined; helpText?: string | undefined; placeholder?: string | undefined; results: { description?: string | null | undefined; imageUrl?: string | null | undefined; image?: { alt?: string | undefined; size?: "thumbnail" | "small" | "medium" | "large" | undefined; width?: "thumbnail" | "small" | "medium" | "large" | undefined; height?: "thumbnail" | "small" | "medium" | "large" | undefined; url: string; } | undefined; value: string; label: string | number | boolean | Date; }[]; }, Result, Result | null>; /** * The namespace for methods to collect user input. */ input: { /** * Requests a string value. * * **Usage:** * * ```typescript * const text = await io.input.text("Company name", { * placeholder: "Acme Inc.", * }); * ``` */ text: InputIOComponentFunction<"INPUT_TEXT", { defaultValue?: string | null | undefined; disabled?: boolean | undefined; helpText?: string | undefined; placeholder?: string | undefined; multiline?: boolean | undefined; lines?: number | undefined; minLength?: number | undefined; maxLength?: number | undefined; }, string>; /** * Requests a boolean value. * * **Usage:** * * ```typescript * const shouldSubscribe = await io.input.boolean("Subscribe to our newsletter?"); * ``` */ boolean: InputIOComponentFunction<"INPUT_BOOLEAN", { defaultValue?: boolean | null | undefined; disabled?: boolean | undefined; helpText?: string | undefined; }, boolean>; /** * Requests a numeric value. * * **Usage:** * * ```typescript * const amount = await io.input.number("Amount", { * helpText: "Enter a number between one and ten.", * min: 1, * max: 10, * }); * ``` */ number: InputIOComponentFunction<"INPUT_NUMBER", { defaultValue?: number | null | undefined; disabled?: boolean | undefined; helpText?: string | undefined; placeholder?: string | undefined; min?: number | undefined; max?: number | undefined; prepend?: string | undefined; decimals?: number | undefined; currency?: "USD" | "CAD" | "EUR" | "GBP" | "AUD" | "CNY" | "JPY" | undefined; }, number>; /** * Requests a numeric value within a range using a slider input. * * **Usage:** * * ```typescript * const amount = await io.input.range("Amount", { * helpText: "Select a number between one and ten.", * min: 1, * max: 10, * }); */ slider: InputIOComponentFunction<"INPUT_SLIDER", { defaultValue?: number | null | undefined; disabled?: boolean | undefined; helpText?: string | undefined; step?: number | undefined; min: number; max: number; }, number>; /** * Requests an email address. * * **Usage:** * * ```typescript * const email = await io.input.email("Email address", { * helpText: "Please provide your work email.", * placeholder: "you@example.com", * }); * ``` */ email: InputIOComponentFunction<"INPUT_EMAIL", { defaultValue?: string | null | undefined; disabled?: boolean | undefined; helpText?: string | undefined; placeholder?: string | undefined; }, string>; /** * Requests rich text input and returns a string of HTML. * * **Usage:** * * ```typescript * const body = await io.input.richText("Email body", { * helpText: "Please include user activation information.", * }); * ``` */ richText: InputIOComponentFunction<"INPUT_RICH_TEXT", { defaultValue?: string | null | undefined; disabled?: boolean | undefined; helpText?: string | undefined; placeholder?: string | undefined; }, string>; /** * Requests a URL. * * The URL is validated and an error is shown if the provided value is not a URL. You can perform additional URL validation by using the validation API with `.validate()`. * * **Usage:** * * ```typescript * const redirectUrl = await io.input.url("Redirect URL", { * helpText: "Please provide a URL for the redirect.", * placeholder: "https://example.com", * allowedProtocols: ["https"], * }); * * return redirectUrl.href; * ``` */ url: InputIOComponentFunction<"INPUT_URL", { defaultValue?: string | null | undefined; disabled?: boolean | undefined; helpText?: string | undefined; placeholder?: string | undefined; allowedProtocols?: string[] | undefined; }, URL>; /** * Requests a date. * * **Usage:** * * ```typescript * const date = await io.input.date("Date"); * ``` */ date: InputIOComponentFunction<"INPUT_DATE", Omit<{ defaultValue?: { year: number; month: number; day: number; } | null | undefined; disabled?: boolean | undefined; helpText?: string | undefined; min?: { year: number; month: number; day: number; } | undefined; max?: { year: number; month: number; day: number; } | undefined; }, "defaultValue" | "min" | "max"> & { defaultValue?: Date | { year: number; month: number; day: number; } | undefined; min?: Date | { year: number; month: number; day: number; } | undefined; max?: Date | { year: number; month: number; day: number; } | undefined; }, { jsDate: Date; year: number; month: number; day: number; }>; /** * Requests a time. * * **Usage:** * * ```typescript * const time = await io.input.time("Time"); * ``` */ time: InputIOComponentFunction<"INPUT_TIME", { defaultValue?: { hour: number; minute: number; } | null | undefined; disabled?: boolean | undefined; helpText?: string | undefined; min?: { hour: number; minute: number; } | undefined; max?: { hour: number; minute: number; } | undefined; }, { hour: number; minute: number; }>; /** * Requests a date & time. * * **Usage:** * * ```typescript * const datetime = await io.input.datetime("Date & time"); * ``` */ datetime: InputIOComponentFunction<"INPUT_DATETIME", Omit<{ defaultValue?: { year: number; month: number; day: number; hour: number; minute: number; } | null | undefined; disabled?: boolean | undefined; helpText?: string | undefined; min?: { year: number; month: number; day: number; hour: number; minute: number; } | undefined; max?: { year: number; month: number; day: number; hour: number; minute: number; } | undefined; }, "defaultValue" | "min" | "max"> & { defaultValue?: Date | { year: number; month: number; day: number; hour: number; minute: number; } | undefined; min?: Date | { year: number; month: number; day: number; hour: number; minute: number; } | undefined; max?: Date | { year: number; month: number; day: number; hour: number; minute: number; } | undefined; }, { jsDate: Date; year: number; month: number; day: number; hour: number; minute: number; }>; /** * Prompts the app user to select and upload a file. * * The resulting object points to a temporary file that expires after the action finishes running. You can access its contents in your action and optionally persist the file elsewhere if it should live longer. * * You may upload the file directly to your own S3-compatible API by providing custom presigned upload and download URLs via the `generatePresignedUrls` property. * * **Usage:** * * ```typescript * const datetime = await io.input.datetime("Date & time"); * ``` */ file: MultipleableInputIOComponentFunction<"UPLOAD_FILE", { disabled?: boolean | undefined; helpText?: string | undefined; allowedExtensions?: string[] | undefined; uploadUrl?: string | null | undefined; downloadUrl?: string | null | undefined; fileUrls?: { uploadUrl: string; downloadUrl: string; }[] | null | undefined; } & { generatePresignedUrls?: ((state: { type: string; name: string; }) => Promise<{ uploadUrl: string; downloadUrl: string; }>) | undefined; }, { lastModified: Date; extension: string; url(): Promise; text(): Promise; json(): Promise; buffer(): Promise; type: string; size: number; name: string; }>; }; /** * The namespace for methods which allow users to select items from a predefined list. */ select: { /** * Prompts the app user to select a single value from a set of provided values. * * **Usage:** * * ```typescript * const currency = await io.select.single("Currency", { * options: [ * { label: "US Dollar", value: "USD" }, * { label: "Canadian Dollar", value: "CAD" }, * { label: "Euro", value: "EUR" }, * ], * defaultValue: "USD", * helpText: "Currency for this transaction", * }); * * const currencyCode = currency.value; * ``` */ single: