From 23a35d1b91d3232435bdc5f15353955d65e6456d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 9 Apr 2026 16:36:00 +0200 Subject: [PATCH] frontend-plugin-api: widen config schema constraint to accept Standard Schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Widens the TConfigSchema generic constraint in createExtension, createExtensionBlueprint, and their override/makeWithOverrides methods to accept both the existing zod factory form and direct Standard Schema instances via the new ConfigFieldSchema union type. Existing consumers are unaffected — the factory form continues to infer concrete types through z.infer>. Direct Standard Schema values are accepted but infer as any in the current iteration. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .../frontend-plugin-api/report-alpha.api.md | 24 ++-- packages/frontend-plugin-api/report.api.md | 135 +++++++++++++++--- .../src/schema/createPortableSchema.ts | 111 +++++++++----- .../frontend-plugin-api/src/schema/index.ts | 5 + .../src/wiring/createExtension.ts | 41 ++++-- .../src/wiring/createExtensionBlueprint.ts | 37 +++-- 6 files changed, 262 insertions(+), 91 deletions(-) diff --git a/packages/frontend-plugin-api/report-alpha.api.md b/packages/frontend-plugin-api/report-alpha.api.md index c27ba1b814..82d9da2627 100644 --- a/packages/frontend-plugin-api/report-alpha.api.md +++ b/packages/frontend-plugin-api/report-alpha.api.md @@ -14,7 +14,8 @@ import { FilterPredicate } from '@backstage/filter-predicates'; import { JsonObject } from '@backstage/types'; import { JSX as JSX_2 } from 'react'; import { ReactNode } from 'react'; -import type { z } from 'zod/v3'; +import { z } from 'zod/v3'; +import { ZodType } from 'zod/v3'; // @public export type AnyRouteRefParams = @@ -160,10 +161,11 @@ export interface ExtensionBlueprint< inputs: T['inputs']; params: T['params']; }>; + // Warning: (ae-forgotten-export) The symbol "ConfigFieldSchema" needs to be exported by the entry point alpha.d.ts makeWithOverrides< TName extends string | undefined, TExtensionConfigSchema extends { - [key in string]: (zImpl: typeof z) => z.ZodType; + [key in string]: ConfigFieldSchema; }, UFactoryOutput extends ExtensionDataValue, UNewOutput extends ExtensionDataRef, @@ -212,7 +214,7 @@ export interface ExtensionBlueprint< apis: ApiHolder; config: T['config'] & { [key in keyof TExtensionConfigSchema]: z.infer< - ReturnType + ReturnType<((...args: any[]) => any) & TExtensionConfigSchema[key]> >; }; inputs: Expand>; @@ -230,7 +232,9 @@ export interface ExtensionBlueprint< ? {} : { [key in keyof TExtensionConfigSchema]: z.infer< - ReturnType + ReturnType< + ((...args: any[]) => any) & TExtensionConfigSchema[key] + > >; }) & T['config'] @@ -241,7 +245,7 @@ export interface ExtensionBlueprint< : z.input< z.ZodObject<{ [key in keyof TExtensionConfigSchema]: ReturnType< - TExtensionConfigSchema[key] + ((...args: any[]) => any) & TExtensionConfigSchema[key] >; }> >) & @@ -473,7 +477,7 @@ export interface OverridableExtensionDefinition< // (undocumented) override< TExtensionConfigSchema extends { - [key in string]: (zImpl: typeof z) => z.ZodType; + [key in string]: ConfigFieldSchema; }, UFactoryOutput extends ExtensionDataValue, UNewOutput extends ExtensionDataRef, @@ -531,7 +535,9 @@ export interface OverridableExtensionDefinition< apis: ApiHolder; config: T['config'] & { [key in keyof TExtensionConfigSchema]: z.infer< - ReturnType + ReturnType< + ((...args: any[]) => any) & TExtensionConfigSchema[key] + > >; }; inputs: Expand>; @@ -560,14 +566,14 @@ export interface OverridableExtensionDefinition< inputs: T['inputs'] & TExtraInputs; config: T['config'] & { [key in keyof TExtensionConfigSchema]: z.infer< - ReturnType + ReturnType<((...args: any[]) => any) & TExtensionConfigSchema[key]> >; }; configInput: T['configInput'] & z.input< z.ZodObject<{ [key in keyof TExtensionConfigSchema]: ReturnType< - TExtensionConfigSchema[key] + ((...args: any[]) => any) & TExtensionConfigSchema[key] >; }> >; diff --git a/packages/frontend-plugin-api/report.api.md b/packages/frontend-plugin-api/report.api.md index 9752eaa6c8..54023e5b08 100644 --- a/packages/frontend-plugin-api/report.api.md +++ b/packages/frontend-plugin-api/report.api.md @@ -23,7 +23,8 @@ import { Observable } from '@backstage/types'; import { PropsWithChildren } from 'react'; import { ReactNode } from 'react'; import { SwappableComponentRef as SwappableComponentRef_2 } from '@backstage/frontend-plugin-api'; -import type { z } from 'zod/v3'; +import { z } from 'zod/v3'; +import { ZodType } from 'zod/v3'; // @public @deprecated export type AlertApi = { @@ -388,6 +389,16 @@ export const configApiRef: ApiRef_2 & { readonly $$type: '@backstage/ApiRef'; }; +// @public +export type ConfigFieldSchema = + | StandardSchemaV1 + | ((zImpl: typeof z) => ZodType); + +// @public +export type ConfigSchemaRecord = { + [key: string]: ConfigFieldSchema; +}; + // @public (undocumented) export interface ConfigurableExtensionDataRef< TData, @@ -464,7 +475,7 @@ export function createExtension< [inputName in string]: ExtensionInput; }, TConfigSchema extends { - [key: string]: (zImpl: typeof z) => z.ZodType; + [key: string]: ConfigFieldSchema; }, UFactoryOutput extends ExtensionDataValue, const TKind extends string | undefined = undefined, @@ -484,13 +495,17 @@ export function createExtension< config: string extends keyof TConfigSchema ? {} : { - [key in keyof TConfigSchema]: z.infer>; + [key in keyof TConfigSchema]: z.infer< + ReturnType<((...args: any[]) => any) & TConfigSchema[key]> + >; }; configInput: string extends keyof TConfigSchema ? {} : z.input< z.ZodObject<{ - [key in keyof TConfigSchema]: ReturnType; + [key in keyof TConfigSchema]: ReturnType< + ((...args: any[]) => any) & TConfigSchema[key] + >; }> >; output: UOutput extends ExtensionDataRef< @@ -514,7 +529,7 @@ export function createExtensionBlueprint< [inputName in string]: ExtensionInput; }, TConfigSchema extends { - [key in string]: (zImpl: typeof z) => z.ZodType; + [key in string]: ConfigFieldSchema; }, UFactoryOutput extends ExtensionDataValue, TKind extends string, @@ -547,13 +562,17 @@ export function createExtensionBlueprint< config: string extends keyof TConfigSchema ? {} : { - [key in keyof TConfigSchema]: z.infer>; + [key in keyof TConfigSchema]: z.infer< + ReturnType<((...args: any[]) => any) & TConfigSchema[key]> + >; }; configInput: string extends keyof TConfigSchema ? {} : z.input< z.ZodObject<{ - [key in keyof TConfigSchema]: ReturnType; + [key in keyof TConfigSchema]: ReturnType< + ((...args: any[]) => any) & TConfigSchema[key] + >; }> >; dataRefs: TDataRefs; @@ -568,7 +587,7 @@ export type CreateExtensionBlueprintOptions< [inputName in string]: ExtensionInput; }, TConfigSchema extends { - [key in string]: (zImpl: typeof z) => z.ZodType; + [key in string]: ConfigFieldSchema; }, UFactoryOutput extends ExtensionDataValue, TDataRefs extends { @@ -597,7 +616,9 @@ export type CreateExtensionBlueprintOptions< node: AppNode; apis: ApiHolder; config: { - [key in keyof TConfigSchema]: z.infer>; + [key in keyof TConfigSchema]: z.infer< + ReturnType<((...args: any[]) => any) & TConfigSchema[key]> + >; }; inputs: Expand>; }, @@ -657,7 +678,7 @@ export type CreateExtensionOptions< [inputName in string]: ExtensionInput; }, TConfigSchema extends { - [key: string]: (zImpl: typeof z) => z.ZodType; + [key: string]: ConfigFieldSchema; }, UFactoryOutput extends ExtensionDataValue, UParentInputs extends ExtensionDataRef, @@ -677,7 +698,9 @@ export type CreateExtensionOptions< node: AppNode; apis: ApiHolder; config: { - [key in keyof TConfigSchema]: z.infer>; + [key in keyof TConfigSchema]: z.infer< + ReturnType<((...args: any[]) => any) & TConfigSchema[key]> + >; }; inputs: Expand>; }): Iterable; @@ -1042,7 +1065,7 @@ export interface ExtensionBlueprint< makeWithOverrides< TName extends string | undefined, TExtensionConfigSchema extends { - [key in string]: (zImpl: typeof z) => z.ZodType; + [key in string]: ConfigFieldSchema; }, UFactoryOutput extends ExtensionDataValue, UNewOutput extends ExtensionDataRef, @@ -1091,7 +1114,7 @@ export interface ExtensionBlueprint< apis: ApiHolder; config: T['config'] & { [key in keyof TExtensionConfigSchema]: z.infer< - ReturnType + ReturnType<((...args: any[]) => any) & TExtensionConfigSchema[key]> >; }; inputs: Expand>; @@ -1109,7 +1132,9 @@ export interface ExtensionBlueprint< ? {} : { [key in keyof TExtensionConfigSchema]: z.infer< - ReturnType + ReturnType< + ((...args: any[]) => any) & TExtensionConfigSchema[key] + > >; }) & T['config'] @@ -1120,7 +1145,7 @@ export interface ExtensionBlueprint< : z.input< z.ZodObject<{ [key in keyof TExtensionConfigSchema]: ReturnType< - TExtensionConfigSchema[key] + ((...args: any[]) => any) & TExtensionConfigSchema[key] >; }> >) & @@ -1682,7 +1707,7 @@ export interface OverridableExtensionDefinition< // (undocumented) override< TExtensionConfigSchema extends { - [key in string]: (zImpl: typeof z) => z.ZodType; + [key in string]: ConfigFieldSchema; }, UFactoryOutput extends ExtensionDataValue, UNewOutput extends ExtensionDataRef, @@ -1740,7 +1765,9 @@ export interface OverridableExtensionDefinition< apis: ApiHolder; config: T['config'] & { [key in keyof TExtensionConfigSchema]: z.infer< - ReturnType + ReturnType< + ((...args: any[]) => any) & TExtensionConfigSchema[key] + > >; }; inputs: Expand>; @@ -1769,14 +1796,14 @@ export interface OverridableExtensionDefinition< inputs: T['inputs'] & TExtraInputs; config: T['config'] & { [key in keyof TExtensionConfigSchema]: z.infer< - ReturnType + ReturnType<((...args: any[]) => any) & TExtensionConfigSchema[key]> >; }; configInput: T['configInput'] & z.input< z.ZodObject<{ [key in keyof TExtensionConfigSchema]: ReturnType< - TExtensionConfigSchema[key] + ((...args: any[]) => any) & TExtensionConfigSchema[key] >; }> >; @@ -2119,6 +2146,76 @@ export namespace SessionState { export type SignedOut = typeof SessionState.SignedOut; } +// @public +export interface StandardSchemaV1 { + // (undocumented) + readonly '~standard': StandardSchemaV1.Props; +} + +// @public (undocumented) +export namespace StandardSchemaV1 { + // (undocumented) + export interface FailureResult { + // (undocumented) + readonly issues: ReadonlyArray; + } + // (undocumented) + export type InferInput = NonNullable< + Schema['~standard']['types'] + >['input']; + // (undocumented) + export type InferOutput = NonNullable< + Schema['~standard']['types'] + >['output']; + // (undocumented) + export interface Issue { + // (undocumented) + readonly message: string; + // (undocumented) + readonly path?: ReadonlyArray | undefined; + } + // (undocumented) + export interface Options { + // (undocumented) + readonly libraryOptions?: Record | undefined; + } + // (undocumented) + export interface PathSegment { + // (undocumented) + readonly key: PropertyKey; + } + // (undocumented) + export interface Props { + // (undocumented) + readonly types?: Types | undefined; + // (undocumented) + readonly validate: ( + value: unknown, + options?: Options | undefined, + ) => Result | Promise>; + // (undocumented) + readonly vendor: string; + // (undocumented) + readonly version: 1; + } + // (undocumented) + export type Result = SuccessResult | FailureResult; + // (undocumented) + export interface SuccessResult { + // (undocumented) + readonly issues?: undefined; + // (undocumented) + readonly value: Output; + } + // (undocumented) + export interface Types { + // (undocumented) + readonly input: Input; + // (undocumented) + readonly output: Output; + } +} + // @public export interface StorageApi { forBucket(name: string): StorageApi; diff --git a/packages/frontend-plugin-api/src/schema/createPortableSchema.ts b/packages/frontend-plugin-api/src/schema/createPortableSchema.ts index 877cbd2ef1..6e83ceef97 100644 --- a/packages/frontend-plugin-api/src/schema/createPortableSchema.ts +++ b/packages/frontend-plugin-api/src/schema/createPortableSchema.ts @@ -44,13 +44,19 @@ import { PortableSchema } from './types'; // See: https://github.com/standard-schema/standard-schema // --------------------------------------------------------------------------- -/** The Standard Schema interface. */ -interface StandardSchemaV1 { +/** + * The Standard Schema interface. + * @public + */ +export interface StandardSchemaV1 { readonly '~standard': StandardSchemaV1.Props; } +/** + * @public + */ // eslint-disable-next-line @typescript-eslint/no-namespace -namespace StandardSchemaV1 { +export namespace StandardSchemaV1 { export interface Props { readonly version: 1; readonly vendor: string; @@ -106,38 +112,82 @@ namespace StandardSchemaV1 { /** * A single config field schema. Accepts any Standard Schema implementation, * or the legacy factory form for backward compat and zod-based composition. + * @public */ -type ConfigFieldSchema = StandardSchemaV1 | ((zImpl: typeof zodV3) => ZodType); +export type ConfigFieldSchema = + | StandardSchemaV1 + | ((zImpl: typeof zodV3) => ZodType); -/** A record of per-field config schemas. */ -type ConfigSchemaRecord = { [key: string]: ConfigFieldSchema }; - -/** Resolves a field entry to its StandardSchemaV1 form for type inference. */ -type ResolveField = T extends ( - ...args: any[] -) => infer R - ? R extends StandardSchemaV1 - ? R - : never - : T extends StandardSchemaV1 - ? T - : never; +/** + * A record of per-field config schemas. + * @public + */ +export type ConfigSchemaRecord = { [key: string]: ConfigFieldSchema }; /** * Infers the parsed output type of a config schema record. * Replaces: `{ [key in keyof T]: z.infer> }` + * + * Split into two mapped types joined by intersection to avoid conditional + * types in the value position, which TypeScript defers in declaration emit. + * Factory-form fields use `ReturnType<...>['_output']` (eagerly evaluated), + * Standard Schema fields use `['~standard']['types']['output']`. + * @ignore */ type InferConfigOutput = { - [K in keyof T]: StandardSchemaV1.InferOutput>; + [K in keyof T as T[K] extends (...args: any[]) => any + ? K + : never]: ReturnType any)>['_output']; +} & { + [K in keyof T as T[K] extends (...args: any[]) => any + ? never + : K]: NonNullable< + (T[K] & StandardSchemaV1)['~standard']['types'] + >['output']; }; /** * Infers the raw input type (before defaults/transforms) of a config * schema record. * Replaces: `z.input>` + * + * Fields whose input type includes `undefined` are made optional keys, + * matching the behavior of `z.input>` for ZodDefault + * and ZodOptional fields. + * @ignore */ -type InferConfigInput = { - [K in keyof T]: StandardSchemaV1.InferInput>; +type InferConfigInput = _RequiredInput & + _OptionalInput; + +type _FactoryInput any> = ReturnType['_input']; +type _SchemaInput = NonNullable< + T['~standard']['types'] +>['input']; + +/** @ignore */ +type _RequiredInput = { + [K in keyof T as T[K] extends (...args: any[]) => any + ? undefined extends _FactoryInput any)> + ? never + : K + : undefined extends _SchemaInput + ? never + : K]: T[K] extends (...args: any[]) => any + ? _FactoryInput any)> + : _SchemaInput; +}; + +/** @ignore */ +type _OptionalInput = { + [K in keyof T as T[K] extends (...args: any[]) => any + ? undefined extends _FactoryInput any)> + ? K + : never + : undefined extends _SchemaInput + ? K + : never]?: T[K] extends (...args: any[]) => any + ? _FactoryInput any)> + : _SchemaInput; }; // --------------------------------------------------------------------------- @@ -161,7 +211,7 @@ interface FieldValidator { * public PortableSchema surface. The brand field is used to detect whether * a PortableSchema came from this utility (and thus supports merging). */ -interface MergeablePortableSchema +export interface MergeablePortableSchema extends PortableSchema { /** @internal */ readonly _fields: Record; @@ -171,7 +221,7 @@ interface MergeablePortableSchema // createPortableSchema — builds from a field record // --------------------------------------------------------------------------- -function createPortableSchema( +export function createPortableSchema( fields: T, ): MergeablePortableSchema, InferConfigInput> { const fieldValidators: Record = {}; @@ -193,7 +243,7 @@ function createPortableSchema( // no need to mix schema types within a single validator. // --------------------------------------------------------------------------- -function mergePortableSchemas( +export function mergePortableSchemas( a: MergeablePortableSchema | undefined, b: MergeablePortableSchema | undefined, ): MergeablePortableSchema | undefined { @@ -437,18 +487,3 @@ function formatStandardIssue( : fieldKey; return `${message} at '${path}'`; } - -// --------------------------------------------------------------------------- -// Exports -// --------------------------------------------------------------------------- - -export { - createPortableSchema, - mergePortableSchemas, - type MergeablePortableSchema, - type ConfigFieldSchema, - type ConfigSchemaRecord, - type InferConfigOutput, - type InferConfigInput, - type StandardSchemaV1, -}; diff --git a/packages/frontend-plugin-api/src/schema/index.ts b/packages/frontend-plugin-api/src/schema/index.ts index a8f92a37f4..3297c09ce3 100644 --- a/packages/frontend-plugin-api/src/schema/index.ts +++ b/packages/frontend-plugin-api/src/schema/index.ts @@ -15,3 +15,8 @@ */ export { type PortableSchema } from './types'; +export { + type StandardSchemaV1, + type ConfigFieldSchema, + type ConfigSchemaRecord, +} from './createPortableSchema'; diff --git a/packages/frontend-plugin-api/src/wiring/createExtension.ts b/packages/frontend-plugin-api/src/wiring/createExtension.ts index 1b5869460a..735438cdd7 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtension.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtension.ts @@ -28,6 +28,7 @@ import { ExtensionDataRef, ExtensionDataValue } from './createExtensionDataRef'; import { ExtensionInput } from './createExtensionInput'; import type { z } from 'zod/v3'; import { createSchemaFromZod } from '../schema/createSchemaFromZod'; +import type { ConfigFieldSchema } from '../schema/createPortableSchema'; import { OpaqueExtensionDefinition } from '@internal/frontend'; import { ExtensionDataContainer } from './types'; import { @@ -166,7 +167,7 @@ export type CreateExtensionOptions< TName extends string | undefined, UOutput extends ExtensionDataRef, TInputs extends { [inputName in string]: ExtensionInput }, - TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType }, + TConfigSchema extends { [key: string]: ConfigFieldSchema }, UFactoryOutput extends ExtensionDataValue, UParentInputs extends ExtensionDataRef, > = { @@ -185,7 +186,9 @@ export type CreateExtensionOptions< node: AppNode; apis: ApiHolder; config: { - [key in keyof TConfigSchema]: z.infer>; + [key in keyof TConfigSchema]: z.infer< + ReturnType<((...args: any[]) => any) & TConfigSchema[key]> + >; }; inputs: Expand>; }): Iterable; @@ -239,7 +242,7 @@ export interface OverridableExtensionDefinition< override< TExtensionConfigSchema extends { - [key in string]: (zImpl: typeof z) => z.ZodType; + [key in string]: ConfigFieldSchema; }, UFactoryOutput extends ExtensionDataValue, UNewOutput extends ExtensionDataRef, @@ -295,7 +298,9 @@ export interface OverridableExtensionDefinition< apis: ApiHolder; config: T['config'] & { [key in keyof TExtensionConfigSchema]: z.infer< - ReturnType + ReturnType< + ((...args: any[]) => any) & TExtensionConfigSchema[key] + > >; }; inputs: Expand>; @@ -324,14 +329,14 @@ export interface OverridableExtensionDefinition< inputs: T['inputs'] & TExtraInputs; config: T['config'] & { [key in keyof TExtensionConfigSchema]: z.infer< - ReturnType + ReturnType<((...args: any[]) => any) & TExtensionConfigSchema[key]> >; }; configInput: T['configInput'] & z.input< z.ZodObject<{ [key in keyof TExtensionConfigSchema]: ReturnType< - TExtensionConfigSchema[key] + ((...args: any[]) => any) & TExtensionConfigSchema[key] >; }> >; @@ -400,7 +405,7 @@ function bindInputs( export function createExtension< UOutput extends ExtensionDataRef, TInputs extends { [inputName in string]: ExtensionInput }, - TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType }, + TConfigSchema extends { [key: string]: ConfigFieldSchema }, UFactoryOutput extends ExtensionDataValue, const TKind extends string | undefined = undefined, const TName extends string | undefined = undefined, @@ -419,16 +424,19 @@ export function createExtension< config: string extends keyof TConfigSchema ? {} : { - [key in keyof TConfigSchema]: z.infer>; + [key in keyof TConfigSchema]: z.infer< + ReturnType<((...args: any[]) => any) & TConfigSchema[key]> + >; }; configInput: string extends keyof TConfigSchema ? {} : z.input< z.ZodObject<{ - [key in keyof TConfigSchema]: ReturnType; + [key in keyof TConfigSchema]: ReturnType< + ((...args: any[]) => any) & TConfigSchema[key] + >; }> >; - // This inference and remapping back to ExtensionDataRef eliminates any occurrences ConfigurationExtensionDataRef output: UOutput extends ExtensionDataRef< infer IData, infer IId, @@ -447,8 +455,11 @@ export function createExtension< createSchemaFromZod(innerZ => innerZ.object( Object.fromEntries( - Object.entries(schemaDeclaration).map(([k, v]) => [k, v(innerZ)]), - ), + Object.entries(schemaDeclaration).map(([k, v]) => [ + k, + typeof v === 'function' ? v(innerZ) : v, + ]), + ) as Record, ), ); @@ -458,14 +469,16 @@ export function createExtension< ? {} : { [key in keyof TConfigSchema]: z.infer< - ReturnType + ReturnType<((...args: any[]) => any) & TConfigSchema[key]> >; }; configInput: string extends keyof TConfigSchema ? {} : z.input< z.ZodObject<{ - [key in keyof TConfigSchema]: ReturnType; + [key in keyof TConfigSchema]: ReturnType< + ((...args: any[]) => any) & TConfigSchema[key] + >; }> >; output: UOutput; diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts index cd593f3c93..80c78ea24a 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts @@ -28,6 +28,7 @@ import { } from './createExtension'; import type { z } from 'zod/v3'; import { ExtensionInput } from './createExtensionInput'; +import type { ConfigFieldSchema } from '../schema/createPortableSchema'; import { ExtensionDataRef, ExtensionDataValue } from './createExtensionDataRef'; import { createExtensionDataContainer } from '@internal/frontend'; import { @@ -106,7 +107,7 @@ export type CreateExtensionBlueprintOptions< TParams extends object | ExtensionBlueprintDefineParams, UOutput extends ExtensionDataRef, TInputs extends { [inputName in string]: ExtensionInput }, - TConfigSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType }, + TConfigSchema extends { [key in string]: ConfigFieldSchema }, UFactoryOutput extends ExtensionDataValue, TDataRefs extends { [name in string]: ExtensionDataRef }, UParentInputs extends ExtensionDataRef, @@ -170,7 +171,9 @@ export type CreateExtensionBlueprintOptions< node: AppNode; apis: ApiHolder; config: { - [key in keyof TConfigSchema]: z.infer>; + [key in keyof TConfigSchema]: z.infer< + ReturnType<((...args: any[]) => any) & TConfigSchema[key]> + >; }; inputs: Expand>; }, @@ -248,7 +251,7 @@ export interface ExtensionBlueprint< makeWithOverrides< TName extends string | undefined, TExtensionConfigSchema extends { - [key in string]: (zImpl: typeof z) => z.ZodType; + [key in string]: ConfigFieldSchema; }, UFactoryOutput extends ExtensionDataValue, UNewOutput extends ExtensionDataRef, @@ -295,7 +298,7 @@ export interface ExtensionBlueprint< apis: ApiHolder; config: T['config'] & { [key in keyof TExtensionConfigSchema]: z.infer< - ReturnType + ReturnType<((...args: any[]) => any) & TExtensionConfigSchema[key]> >; }; inputs: Expand>; @@ -313,7 +316,9 @@ export interface ExtensionBlueprint< ? {} : { [key in keyof TExtensionConfigSchema]: z.infer< - ReturnType + ReturnType< + ((...args: any[]) => any) & TExtensionConfigSchema[key] + > >; }) & T['config'] @@ -324,7 +329,7 @@ export interface ExtensionBlueprint< : z.input< z.ZodObject<{ [key in keyof TExtensionConfigSchema]: ReturnType< - TExtensionConfigSchema[key] + ((...args: any[]) => any) & TExtensionConfigSchema[key] >; }> >) & @@ -461,7 +466,7 @@ export function createExtensionBlueprint< TParams extends object | ExtensionBlueprintDefineParams, UOutput extends ExtensionDataRef, TInputs extends { [inputName in string]: ExtensionInput }, - TConfigSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType }, + TConfigSchema extends { [key in string]: ConfigFieldSchema }, UFactoryOutput extends ExtensionDataValue, TKind extends string, UParentInputs extends ExtensionDataRef, @@ -491,12 +496,18 @@ export function createExtensionBlueprint< inputs: string extends keyof TInputs ? {} : TInputs; config: string extends keyof TConfigSchema ? {} - : { [key in keyof TConfigSchema]: z.infer> }; + : { + [key in keyof TConfigSchema]: z.infer< + ReturnType<((...args: any[]) => any) & TConfigSchema[key]> + >; + }; configInput: string extends keyof TConfigSchema ? {} : z.input< z.ZodObject<{ - [key in keyof TConfigSchema]: ReturnType; + [key in keyof TConfigSchema]: ReturnType< + ((...args: any[]) => any) & TConfigSchema[key] + >; }> >; dataRefs: TDataRefs; @@ -592,13 +603,17 @@ export function createExtensionBlueprint< config: string extends keyof TConfigSchema ? {} : { - [key in keyof TConfigSchema]: z.infer>; + [key in keyof TConfigSchema]: z.infer< + ReturnType<((...args: any[]) => any) & TConfigSchema[key]> + >; }; configInput: string extends keyof TConfigSchema ? {} : z.input< z.ZodObject<{ - [key in keyof TConfigSchema]: ReturnType; + [key in keyof TConfigSchema]: ReturnType< + ((...args: any[]) => any) & TConfigSchema[key] + >; }> >; dataRefs: TDataRefs;