Merge pull request #25765 from backstage/blam/output-types

NFS: Added config input type to the Extensions
This commit is contained in:
Patrik Oldsberg
2024-07-24 15:37:23 +02:00
committed by GitHub
27 changed files with 321 additions and 117 deletions
+14
View File
@@ -0,0 +1,14 @@
---
'@backstage/frontend-plugin-api': patch
'@backstage/frontend-test-utils': patch
'@backstage/frontend-app-api': patch
'@backstage/core-compat-api': patch
'@backstage/plugin-catalog-react': patch
'@backstage/plugin-user-settings': patch
'@backstage/plugin-search-react': patch
'@backstage/plugin-techdocs': patch
'@backstage/plugin-catalog': patch
'@backstage/plugin-search': patch
---
Added config input type to the extensions
@@ -101,7 +101,7 @@ function visitRouteChildren(options: {
parentExtensionId: string;
context: {
pluginId: string;
extensions: ExtensionDefinition<unknown>[];
extensions: ExtensionDefinition<any, any>[];
getUniqueName: () => string;
discoverPlugin: (plugin: LegacyBackstagePlugin) => void;
};
@@ -154,7 +154,7 @@ export function collectLegacyRoutes(
): BackstagePlugin[] {
const pluginExtensions = new Map<
LegacyBackstagePlugin,
ExtensionDefinition<unknown>[]
ExtensionDefinition<any, any>[]
>();
const getUniqueName = (() => {
@@ -70,7 +70,7 @@ function createTestExtension(options: {
});
}
function routeInfoFromExtensions(extensions: ExtensionDefinition<unknown>[]) {
function routeInfoFromExtensions(extensions: ExtensionDefinition<any, any>[]) {
const plugin = createPlugin({
id: 'test',
extensions,
@@ -25,7 +25,7 @@ import { instantiateAppNodeTree } from './instantiateAppNodeTree';
/** @internal */
export interface CreateAppTreeOptions {
features: FrontendFeature[];
builtinExtensions: Extension<unknown>[];
builtinExtensions: Extension<any, any>[];
config: Config;
}
@@ -59,22 +59,22 @@ const simpleExtension = resolveExtensionDefinition(
}),
);
function makeSpec<TConfig>(
extension: Extension<TConfig>,
function makeSpec<TConfig, TConfigInput>(
extension: Extension<TConfig, TConfigInput>,
spec?: Partial<AppNodeSpec>,
): AppNodeSpec {
return {
id: extension.id,
attachTo: extension.attachTo,
disabled: extension.disabled,
extension,
extension: extension as Extension<unknown, unknown>,
source: undefined,
...spec,
};
}
function makeNode<TConfig>(
extension: Extension<TConfig>,
function makeNode<TConfig, TConfigInput>(
extension: Extension<TConfig, TConfigInput>,
spec?: Partial<AppNodeSpec>,
): AppNode {
return {
@@ -85,8 +85,8 @@ function makeNode<TConfig>(
};
}
function makeInstanceWithId<TConfig>(
extension: Extension<TConfig>,
function makeInstanceWithId<TConfig, TConfigInput>(
extension: Extension<TConfig, TConfigInput>,
config?: TConfig,
): AppNode {
const node = makeNode(extension, { config });
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import { createExtension } from '@backstage/frontend-plugin-api';
import { createExtension, Extension } from '@backstage/frontend-plugin-api';
import { resolveAppTree } from './resolveAppTree';
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import { resolveExtensionDefinition } from '../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition';
@@ -26,7 +26,7 @@ const extension = resolveExtensionDefinition(
output: {},
factory: () => ({}),
}),
);
) as Extension<unknown, unknown>;
const baseSpec = {
extension,
+84 -26
View File
@@ -230,7 +230,7 @@ export interface AppNodeSpec {
// (undocumented)
readonly disabled: boolean;
// (undocumented)
readonly extension: Extension<unknown>;
readonly extension: Extension<unknown, unknown>;
// (undocumented)
readonly id: string;
// (undocumented)
@@ -391,7 +391,7 @@ export function createApiExtension<
configSchema?: PortableSchema<TConfig>;
inputs?: TInputs;
},
): ExtensionDefinition<TConfig>;
): ExtensionDefinition<TConfig & {}, TConfig & {}>;
// @public (undocumented)
export namespace createApiExtension {
@@ -487,7 +487,7 @@ export function createComponentExtension<
inputs: Expand<ResolvedExtensionInputs<TInputs>>;
}) => ComponentType<TProps>;
};
}): ExtensionDefinition<TConfig>;
}): ExtensionDefinition<TConfig & {}, TConfig & {}>;
// @public (undocumented)
export namespace createComponentExtension {
@@ -512,12 +512,34 @@ export function createExtension<
TOutput extends AnyExtensionDataMap,
TInputs extends AnyExtensionInputMap,
TConfig,
TConfigInput,
TConfigSchema extends {
[key: string]: (zImpl: typeof z) => z.ZodType;
},
>(
options: CreateExtensionOptions<TOutput, TInputs, TConfig, TConfigSchema>,
): ExtensionDefinition<TConfig>;
options: CreateExtensionOptions<
TOutput,
TInputs,
TConfig,
TConfigInput,
TConfigSchema
>,
): ExtensionDefinition<
TConfig &
(string extends keyof TConfigSchema
? {}
: {
[key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;
}),
TConfigInput &
(string extends keyof TConfigSchema
? {}
: z.input<
z.ZodObject<{
[key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;
}>
>)
>;
// @public
export function createExtensionBlueprint<
@@ -545,6 +567,13 @@ export function createExtensionBlueprint<
: {
[key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;
},
string extends keyof TConfigSchema
? {}
: z.input<
z.ZodObject<{
[key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;
}>
>,
TDataRefs
>;
@@ -627,6 +656,7 @@ export interface CreateExtensionOptions<
TOutput extends AnyExtensionDataMap,
TInputs extends AnyExtensionInputMap,
TConfig,
TConfigInput,
TConfigSchema extends {
[key: string]: (zImpl: typeof z) => z.ZodType;
},
@@ -641,15 +671,20 @@ export interface CreateExtensionOptions<
schema: TConfigSchema;
};
// @deprecated (undocumented)
configSchema?: PortableSchema<TConfig>;
configSchema?: PortableSchema<TConfig, TConfigInput>;
// (undocumented)
disabled?: boolean;
// (undocumented)
factory(context: {
node: AppNode;
config: TConfig & {
[key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;
};
config: TConfig &
(string extends keyof TConfigSchema
? {}
: {
[key in keyof TConfigSchema]: z.infer<
ReturnType<TConfigSchema[key]>
>;
});
inputs: Expand<ResolvedExtensionInputs<TInputs>>;
}): Expand<ExtensionDataValues<TOutput>>;
// (undocumented)
@@ -702,9 +737,14 @@ export function createNavItemExtension(options: {
routeRef: RouteRef<undefined>;
title: string;
icon: IconComponent_2;
}): ExtensionDefinition<{
title: string;
}>;
}): ExtensionDefinition<
{
title: string;
},
{
title?: string | undefined;
}
>;
// @public (undocumented)
export namespace createNavItemExtension {
@@ -726,7 +766,7 @@ export function createNavLogoExtension(options: {
namespace?: string;
logoIcon: JSX.Element;
logoFull: JSX.Element;
}): ExtensionDefinition<unknown>;
}): ExtensionDefinition<{}, {}>;
// @public (undocumented)
export namespace createNavLogoExtension {
@@ -837,7 +877,7 @@ export namespace createRouterExtension {
// @public @deprecated (undocumented)
export function createSchemaFromZod<TOutput, TInput>(
schemaCreator: (zImpl: typeof z) => ZodSchema<TOutput, ZodTypeDef, TInput>,
): PortableSchema<TOutput>;
): PortableSchema<TOutput, TInput>;
// @public (undocumented)
export function createSignInPageExtension<
@@ -881,7 +921,7 @@ export function createSubRouteRef<
// @public (undocumented)
export function createThemeExtension(
theme: AppTheme,
): ExtensionDefinition<unknown>;
): ExtensionDefinition<{}, {}>;
// @public (undocumented)
export namespace createThemeExtension {
@@ -897,7 +937,7 @@ export namespace createThemeExtension {
export function createTranslationExtension(options: {
name?: string;
resource: TranslationResource | TranslationMessages;
}): ExtensionDefinition<unknown>;
}): ExtensionDefinition<{}, {}>;
// @public (undocumented)
export namespace createTranslationExtension {
@@ -935,7 +975,7 @@ export { ErrorApiErrorContext };
export { errorApiRef };
// @public (undocumented)
export interface Extension<TConfig> {
export interface Extension<TConfig, TConfigInput = TConfig> {
// (undocumented)
$$type: '@backstage/Extension';
// (undocumented)
@@ -944,7 +984,7 @@ export interface Extension<TConfig> {
input: string;
};
// (undocumented)
readonly configSchema?: PortableSchema<TConfig>;
readonly configSchema?: PortableSchema<TConfig, TConfigInput>;
// (undocumented)
readonly disabled: boolean;
// (undocumented)
@@ -959,6 +999,9 @@ export interface ExtensionBlueprint<
TConfig extends {
[key in string]: unknown;
},
TConfigInput extends {
[key in string]: unknown;
},
TDataRefs extends AnyExtensionDataMap,
> {
// (undocumented)
@@ -1014,7 +1057,15 @@ export interface ExtensionBlueprint<
[key in keyof TExtensionConfigSchema]: z.infer<
ReturnType<TExtensionConfigSchema[key]>
>;
} & TConfig
} & TConfig,
z.input<
z.ZodObject<{
[key in keyof TExtensionConfigSchema]: ReturnType<
TExtensionConfigSchema[key]
>;
}>
> &
TConfigInput
>;
}
@@ -1062,7 +1113,7 @@ export type ExtensionDataValues<TExtensionData extends AnyExtensionDataMap> = {
};
// @public (undocumented)
export interface ExtensionDefinition<TConfig> {
export interface ExtensionDefinition<TConfig, TConfigInput = TConfig> {
// (undocumented)
$$type: '@backstage/ExtensionDefinition';
// (undocumented)
@@ -1071,7 +1122,7 @@ export interface ExtensionDefinition<TConfig> {
input: string;
};
// (undocumented)
readonly configSchema?: PortableSchema<TConfig>;
readonly configSchema?: PortableSchema<TConfig, TConfigInput>;
// (undocumented)
readonly disabled: boolean;
// (undocumented)
@@ -1107,7 +1158,7 @@ export interface ExtensionOverrides {
// @public (undocumented)
export interface ExtensionOverridesOptions {
// (undocumented)
extensions: ExtensionDefinition<unknown>[];
extensions: ExtensionDefinition<any, any>[];
// (undocumented)
featureFlags?: FeatureFlagConfig[];
}
@@ -1170,7 +1221,14 @@ export const IconBundleBlueprint: ExtensionBlueprint<
{}
>;
},
{},
{
icons: string;
test: string;
},
{
test: string;
icons?: string | undefined;
},
{
icons: ConfigurableExtensionDataRef<
'core.icons',
@@ -1235,7 +1293,7 @@ export interface PluginOptions<
ExternalRoutes extends AnyExternalRoutes,
> {
// (undocumented)
extensions?: ExtensionDefinition<unknown>[];
extensions?: ExtensionDefinition<any, any>[];
// (undocumented)
externalRoutes?: ExternalRoutes;
// (undocumented)
@@ -1247,8 +1305,8 @@ export interface PluginOptions<
}
// @public (undocumented)
export type PortableSchema<TOutput> = {
parse: (input: unknown) => TOutput;
export type PortableSchema<TOutput, TInput = TOutput> = {
parse: (input: TInput) => TOutput;
schema: JsonObject;
};
@@ -29,7 +29,7 @@ import { BackstagePlugin, Extension, ExtensionDataRef } from '../../wiring';
export interface AppNodeSpec {
readonly id: string;
readonly attachTo: { id: string; input: string };
readonly extension: Extension<unknown>;
readonly extension: Extension<unknown, unknown>;
readonly disabled: boolean;
readonly config?: unknown;
readonly source?: BackstagePlugin;
@@ -28,6 +28,12 @@ export const IconBundleBlueprint = createExtensionBlueprint({
output: {
icons: iconsDataRef,
},
config: {
schema: {
icons: z => z.string().default('blob'),
test: z => z.string(),
},
},
factory: (params: { icons: { [key in string]: IconComponent } }) => params,
dataRefs: {
icons: iconsDataRef,
@@ -25,10 +25,19 @@ describe('createSchemaFromZod', () => {
}),
);
expect(() => parse({ derp: { bar: 'derp' } })).toThrow(
expect(() => {
// @ts-expect-error
return parse({ derp: { bar: 'derp' } });
}).toThrow(
`Missing required value at 'foo'; Expected number, received string at 'derp.bar'`,
);
expect(() => parse(undefined)).toThrow(`Missing required value`);
expect(() => parse('derp')).toThrow(`Expected object, received string`);
expect(() => {
// @ts-expect-error
return parse(undefined);
}).toThrow(`Missing required value`);
expect(() => {
// @ts-expect-error
return parse('derp');
}).toThrow(`Expected object, received string`);
});
});
@@ -25,7 +25,7 @@ import { PortableSchema } from './types';
*/
export function createSchemaFromZod<TOutput, TInput>(
schemaCreator: (zImpl: typeof z) => ZodSchema<TOutput, ZodTypeDef, TInput>,
): PortableSchema<TOutput> {
): PortableSchema<TOutput, TInput> {
const schema = schemaCreator(z);
return {
// TODO: Types allow z.array etc here but it will break stuff
@@ -17,7 +17,7 @@
import { JsonObject } from '@backstage/types';
/** @public */
export type PortableSchema<TOutput> = {
parse: (input: unknown) => TOutput;
export type PortableSchema<TOutput, TInput = TOutput> = {
parse: (input: TInput) => TOutput;
schema: JsonObject;
};
@@ -334,6 +334,7 @@ describe('createExtension', () => {
foo: 'x',
bar: 'y',
baz: 'z',
// @ts-expect-error
qux: 'w',
}),
).toEqual({
@@ -349,8 +350,9 @@ describe('createExtension', () => {
foo: 'x',
bar: 'bar',
});
expect(() => extension.configSchema?.parse({})).toThrow(
"Missing required value at 'foo'",
);
expect(() => {
// @ts-expect-error
return extension.configSchema?.parse({});
}).toThrow("Missing required value at 'foo'");
});
});
@@ -82,6 +82,7 @@ export interface CreateExtensionOptions<
TOutput extends AnyExtensionDataMap,
TInputs extends AnyExtensionInputMap,
TConfig,
TConfigInput,
TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType },
> {
kind?: string;
@@ -92,33 +93,38 @@ export interface CreateExtensionOptions<
inputs?: TInputs;
output: TOutput;
/** @deprecated - use `config.schema` instead */
configSchema?: PortableSchema<TConfig>;
configSchema?: PortableSchema<TConfig, TConfigInput>;
config?: {
schema: TConfigSchema;
};
factory(context: {
node: AppNode;
config: TConfig & {
[key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;
};
config: TConfig &
(string extends keyof TConfigSchema
? {}
: {
[key in keyof TConfigSchema]: z.infer<
ReturnType<TConfigSchema[key]>
>;
});
inputs: Expand<ResolvedExtensionInputs<TInputs>>;
}): Expand<ExtensionDataValues<TOutput>>;
}
/** @public */
export interface ExtensionDefinition<TConfig> {
export interface ExtensionDefinition<TConfig, TConfigInput = TConfig> {
$$type: '@backstage/ExtensionDefinition';
readonly kind?: string;
readonly namespace?: string;
readonly name?: string;
readonly attachTo: { id: string; input: string };
readonly disabled: boolean;
readonly configSchema?: PortableSchema<TConfig>;
readonly configSchema?: PortableSchema<TConfig, TConfigInput>;
}
/** @internal */
export interface InternalExtensionDefinition<TConfig>
extends ExtensionDefinition<TConfig> {
export interface InternalExtensionDefinition<TConfig, TConfigInput>
extends ExtensionDefinition<TConfig, TConfigInput> {
readonly version: 'v1';
readonly inputs: AnyExtensionInputMap;
readonly output: AnyExtensionDataMap;
@@ -130,10 +136,13 @@ export interface InternalExtensionDefinition<TConfig>
}
/** @internal */
export function toInternalExtensionDefinition<TConfig>(
overrides: ExtensionDefinition<TConfig>,
): InternalExtensionDefinition<TConfig> {
const internal = overrides as InternalExtensionDefinition<TConfig>;
export function toInternalExtensionDefinition<TConfig, TConfigInput>(
overrides: ExtensionDefinition<TConfig, TConfigInput>,
): InternalExtensionDefinition<TConfig, TConfigInput> {
const internal = overrides as InternalExtensionDefinition<
TConfig,
TConfigInput
>;
if (internal.$$type !== '@backstage/ExtensionDefinition') {
throw new Error(
`Invalid extension definition instance, bad type '${internal.$$type}'`,
@@ -152,10 +161,32 @@ export function createExtension<
TOutput extends AnyExtensionDataMap,
TInputs extends AnyExtensionInputMap,
TConfig,
TConfigInput,
TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType },
>(
options: CreateExtensionOptions<TOutput, TInputs, TConfig, TConfigSchema>,
): ExtensionDefinition<TConfig> {
options: CreateExtensionOptions<
TOutput,
TInputs,
TConfig,
TConfigInput,
TConfigSchema
>,
): ExtensionDefinition<
TConfig &
(string extends keyof TConfigSchema
? {}
: {
[key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;
}),
TConfigInput &
(string extends keyof TConfigSchema
? {}
: z.input<
z.ZodObject<{
[key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;
}>
>)
> {
const newConfigSchema = options.config?.schema;
if (newConfigSchema && options.configSchema) {
throw new Error(`Cannot provide both configSchema and config.schema`);
@@ -205,5 +236,22 @@ export function createExtension<
parts.push(`attachTo=${options.attachTo.id}@${options.attachTo.input}`);
return `ExtensionDefinition{${parts.join(',')}}`;
},
} as InternalExtensionDefinition<TConfig>;
} as InternalExtensionDefinition<
TConfig &
(string extends keyof TConfigSchema
? {}
: {
[key in keyof TConfigSchema]: z.infer<
ReturnType<TConfigSchema[key]>
>;
}),
TConfigInput &
(string extends keyof TConfigSchema
? {}
: z.input<
z.ZodObject<{
[key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;
}>
>)
>;
}
@@ -67,6 +67,7 @@ export interface ExtensionBlueprint<
TInputs extends AnyExtensionInputMap,
TOutput extends AnyExtensionDataMap,
TConfig extends { [key in string]: unknown },
TConfigInput extends { [key in string]: unknown },
TDataRefs extends AnyExtensionDataMap,
> {
dataRefs: TDataRefs;
@@ -125,7 +126,15 @@ export interface ExtensionBlueprint<
[key in keyof TExtensionConfigSchema]: z.infer<
ReturnType<TExtensionConfigSchema[key]>
>;
} & TConfig
} & TConfig,
z.input<
z.ZodObject<{
[key in keyof TExtensionConfigSchema]: ReturnType<
TExtensionConfigSchema[key]
>;
}>
> &
TConfigInput
>;
}
@@ -199,7 +208,18 @@ class ExtensionBlueprintImpl<
>;
} & {
[key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;
}
},
z.input<
z.ZodObject<
{
[key in keyof TExtensionConfigSchema]: ReturnType<
TExtensionConfigSchema[key]
>;
} & {
[key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;
}
>
>
> {
const schema = {
...this.options.config?.schema,
@@ -279,6 +299,13 @@ export function createExtensionBlueprint<
string extends keyof TConfigSchema
? {}
: { [key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>> },
string extends keyof TConfigSchema
? {}
: z.input<
z.ZodObject<{
[key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;
}>
>,
TDataRefs
> {
return new ExtensionBlueprintImpl(options) as ExtensionBlueprint<
@@ -290,6 +317,13 @@ export function createExtensionBlueprint<
: {
[key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;
},
string extends keyof TConfigSchema
? {}
: z.input<
z.ZodObject<{
[key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;
}>
>,
TDataRefs
>;
}
@@ -23,7 +23,7 @@ import { ExtensionOverrides, FeatureFlagConfig } from './types';
/** @public */
export interface ExtensionOverridesOptions {
extensions: ExtensionDefinition<unknown>[];
extensions: ExtensionDefinition<any, any>[];
featureFlags?: FeatureFlagConfig[];
}
@@ -34,7 +34,7 @@ export interface PluginOptions<
id: string;
routes?: Routes;
externalRoutes?: ExternalRoutes;
extensions?: ExtensionDefinition<unknown>[];
extensions?: ExtensionDefinition<any, any>[];
featureFlags?: FeatureFlagConfig[];
}
@@ -26,16 +26,17 @@ import {
import { PortableSchema } from '../schema';
/** @public */
export interface Extension<TConfig> {
export interface Extension<TConfig, TConfigInput = TConfig> {
$$type: '@backstage/Extension';
readonly id: string;
readonly attachTo: { id: string; input: string };
readonly disabled: boolean;
readonly configSchema?: PortableSchema<TConfig>;
readonly configSchema?: PortableSchema<TConfig, TConfigInput>;
}
/** @internal */
export interface InternalExtension<TConfig> extends Extension<TConfig> {
export interface InternalExtension<TConfig, TConfigInput>
extends Extension<TConfig, TConfigInput> {
readonly version: 'v1';
readonly inputs: AnyExtensionInputMap;
readonly output: AnyExtensionDataMap;
@@ -47,10 +48,10 @@ export interface InternalExtension<TConfig> extends Extension<TConfig> {
}
/** @internal */
export function toInternalExtension<TConfig>(
overrides: Extension<TConfig>,
): InternalExtension<TConfig> {
const internal = overrides as InternalExtension<TConfig>;
export function toInternalExtension<TConfig, TConfigInput>(
overrides: Extension<TConfig, TConfigInput>,
): InternalExtension<TConfig, TConfigInput> {
const internal = overrides as InternalExtension<TConfig, TConfigInput>;
if (internal.$$type !== '@backstage/Extension') {
throw new Error(
`Invalid extension instance, bad type '${internal.$$type}'`,
@@ -65,10 +66,10 @@ export function toInternalExtension<TConfig>(
}
/** @internal */
export function resolveExtensionDefinition<TConfig>(
definition: ExtensionDefinition<TConfig>,
export function resolveExtensionDefinition<TConfig, TConfigInput>(
definition: ExtensionDefinition<TConfig, TConfigInput>,
context?: { namespace?: string },
): Extension<TConfig> {
): Extension<TConfig, TConfigInput> {
const internalDefinition = toInternalExtensionDefinition(definition);
const { name, kind, namespace: _, ...rest } = internalDefinition;
const namespace = internalDefinition.namespace ?? context?.namespace;
@@ -91,5 +92,5 @@ export function resolveExtensionDefinition<TConfig>(
toString() {
return `Extension{id=${id}}`;
},
} as Extension<TConfig>;
} as Extension<TConfig, TConfigInput>;
}
+3 -3
View File
@@ -39,10 +39,10 @@ export { ErrorWithContext };
// @public (undocumented)
export class ExtensionTester {
// (undocumented)
add<TConfig>(
extension: ExtensionDefinition<TConfig>,
add<TConfig, TConfigInput>(
extension: ExtensionDefinition<TConfig, TConfigInput>,
options?: {
config?: TConfig;
config?: TConfigInput;
},
): ExtensionTester;
// (undocumented)
@@ -88,9 +88,9 @@ const TestAppNavExtension = createExtension({
/** @public */
export class ExtensionTester {
/** @internal */
static forSubject<TConfig>(
subject: ExtensionDefinition<TConfig>,
options?: { config?: TConfig },
static forSubject<TConfig, TConfigInput>(
subject: ExtensionDefinition<TConfig, TConfigInput>,
options?: { config?: TConfigInput },
): ExtensionTester {
const tester = new ExtensionTester();
const { output, factory, ...rest } = toInternalExtensionDefinition(subject);
@@ -107,7 +107,7 @@ export class ExtensionTester {
path: '/',
}),
});
tester.add(extension, options);
tester.add(extension, options as TConfigInput & {});
return tester;
}
@@ -117,9 +117,9 @@ export class ExtensionTester {
config?: JsonValue;
}>();
add<TConfig>(
extension: ExtensionDefinition<TConfig>,
options?: { config?: TConfig },
add<TConfig, TConfigInput>(
extension: ExtensionDefinition<TConfig, TConfigInput>,
options?: { config?: TConfigInput },
): ExtensionTester {
const { name, namespace } = extension;
+13 -6
View File
@@ -115,7 +115,7 @@ export function createEntityCardExtension<
config: TConfig;
inputs: Expand<ResolvedExtensionInputs<TInputs>>;
}) => Promise<JSX.Element>;
}): ExtensionDefinition<TConfig>;
}): ExtensionDefinition<TConfig & {}, TConfig & {}>;
// @alpha (undocumented)
export function createEntityContentExtension<
@@ -138,11 +138,18 @@ export function createEntityContentExtension<
loader: (options: {
inputs: Expand<ResolvedExtensionInputs<TInputs>>;
}) => Promise<JSX.Element>;
}): ExtensionDefinition<{
title: string;
path: string;
filter?: string | undefined;
}>;
}): ExtensionDefinition<
{
title: string;
path: string;
filter?: string | undefined;
},
{
filter?: string | undefined;
title?: string | undefined;
path?: string | undefined;
}
>;
// @alpha
export function isOwnerOf(owner: Entity, entity: Entity): boolean;
+2 -2
View File
@@ -99,14 +99,14 @@ export const catalogTranslationRef: TranslationRef<
// @alpha (undocumented)
export function createCatalogFilterExtension<
TInputs extends AnyExtensionInputMap,
TConfig = never,
TConfig,
>(options: {
namespace?: string;
name?: string;
inputs?: TInputs;
configSchema?: PortableSchema<TConfig>;
loader: (options: { config: TConfig }) => Promise<JSX.Element>;
}): ExtensionDefinition<TConfig>;
}): ExtensionDefinition<TConfig & {}, TConfig & {}>;
// @alpha (undocumented)
const _default: BackstagePlugin<
@@ -26,7 +26,7 @@ import {
/** @alpha */
export function createCatalogFilterExtension<
TInputs extends AnyExtensionInputMap,
TConfig = never,
TConfig,
>(options: {
namespace?: string;
name?: string;
+1 -1
View File
@@ -25,7 +25,7 @@ export function createSearchResultListItemExtension<
},
>(
options: SearchResultItemExtensionOptions<TConfig>,
): ExtensionDefinition<TConfig>;
): ExtensionDefinition<TConfig & {}, TConfig & {}>;
// @alpha (undocumented)
export namespace createSearchResultListItemExtension {
+19 -8
View File
@@ -17,18 +17,29 @@ const _default: BackstagePlugin<
export default _default;
// @alpha (undocumented)
export const searchApi: ExtensionDefinition<{}>;
export const searchApi: ExtensionDefinition<{}, {}>;
// @alpha (undocumented)
export const searchNavItem: ExtensionDefinition<{
title: string;
}>;
export const searchNavItem: ExtensionDefinition<
{
title: string;
},
{
title?: string | undefined;
}
>;
// @alpha (undocumented)
export const searchPage: ExtensionDefinition<{
path: string;
noTrack: boolean;
}>;
export const searchPage: ExtensionDefinition<
{
path: string;
noTrack: boolean;
},
{
path: string;
noTrack: boolean;
}
>;
// (No @packageDocumentation comment for this package)
```
+16 -7
View File
@@ -23,13 +23,22 @@ const _default: BackstagePlugin<
export default _default;
// @alpha (undocumented)
export const techDocsSearchResultListItemExtension: ExtensionDefinition<{
lineClamp: number;
noTrack: boolean;
asListItem: boolean;
asLink: boolean;
title?: string | undefined;
}>;
export const techDocsSearchResultListItemExtension: ExtensionDefinition<
{
lineClamp: number;
noTrack: boolean;
asListItem: boolean;
asLink: boolean;
title?: string | undefined;
},
{
lineClamp: number;
noTrack: boolean;
asListItem: boolean;
asLink: boolean;
title?: string | undefined;
}
>;
// (No @packageDocumentation comment for this package)
```
+8 -3
View File
@@ -18,9 +18,14 @@ const _default: BackstagePlugin<
export default _default;
// @alpha (undocumented)
export const settingsNavItem: ExtensionDefinition<{
title: string;
}>;
export const settingsNavItem: ExtensionDefinition<
{
title: string;
},
{
title?: string | undefined;
}
>;
// @alpha (undocumented)
export const userSettingsTranslationRef: TranslationRef<