@backstage/frontend-plugin-api
Advanced tools
Comparing version 0.1.0-next.0 to 0.1.0
# @backstage/frontend-plugin-api | ||
## 0.1.0 | ||
### Minor Changes | ||
- 628ca7e458e4: Initial release | ||
### Patch Changes | ||
- Updated dependencies | ||
- @backstage/core-plugin-api@1.6.0 | ||
- @backstage/types@1.1.1 | ||
## 0.1.0-next.0 | ||
@@ -4,0 +16,0 @@ |
/// <reference types="react" /> | ||
import React, { ComponentType, ReactNode } from 'react'; | ||
import React, { JSX as JSX$1, ReactNode } from 'react'; | ||
import { JsonObject } from '@backstage/types'; | ||
import { AnyApiFactory, RouteRef, AnyApiRef } from '@backstage/core-plugin-api'; | ||
import { IconComponent, RouteRef, AnyApiFactory, AnyApiRef } from '@backstage/core-plugin-api'; | ||
import { z, ZodSchema, ZodTypeDef } from 'zod'; | ||
@@ -28,7 +28,14 @@ | ||
/** @public */ | ||
type NavTarget = { | ||
title: string; | ||
icon: IconComponent; | ||
routeRef: RouteRef<{}>; | ||
}; | ||
/** @public */ | ||
declare const coreExtensionData: { | ||
reactComponent: ConfigurableExtensionDataRef<ComponentType<{}>, {}>; | ||
reactElement: ConfigurableExtensionDataRef<JSX$1.Element, {}>; | ||
routePath: ConfigurableExtensionDataRef<string, {}>; | ||
apiFactory: ConfigurableExtensionDataRef<AnyApiFactory, {}>; | ||
routeRef: ConfigurableExtensionDataRef<RouteRef<any>, {}>; | ||
routeRef: ConfigurableExtensionDataRef<RouteRef, {}>; | ||
navTarget: ConfigurableExtensionDataRef<NavTarget, {}>; | ||
}; | ||
@@ -46,23 +53,18 @@ | ||
/** @public */ | ||
type AnyExtensionDataMap = { | ||
[name in string]: ExtensionDataRef<any, any>; | ||
}; | ||
interface ExtensionInput<TExtensionData extends AnyExtensionDataMap, TConfig extends { | ||
singleton: boolean; | ||
optional: boolean; | ||
}> { | ||
$$type: '@backstage/ExtensionInput'; | ||
extensionData: TExtensionData; | ||
config: TConfig; | ||
} | ||
/** @public */ | ||
interface Extension<TConfig> { | ||
$$type: '@backstage/Extension'; | ||
id: string; | ||
at: string; | ||
disabled: boolean; | ||
inputs: Record<string, { | ||
extensionData: AnyExtensionDataMap; | ||
}>; | ||
output: AnyExtensionDataMap; | ||
configSchema?: PortableSchema<TConfig>; | ||
factory(options: { | ||
source?: BackstagePlugin; | ||
bind: ExtensionDataBind<AnyExtensionDataMap>; | ||
config: TConfig; | ||
inputs: Record<string, Array<Record<string, unknown>>>; | ||
}): void; | ||
} | ||
declare function createExtensionInput<TExtensionData extends AnyExtensionDataMap, TConfig extends { | ||
singleton?: boolean; | ||
optional?: boolean; | ||
}>(extensionData: TExtensionData, config?: TConfig): ExtensionInput<TExtensionData, { | ||
singleton: TConfig['singleton'] extends true ? true : false; | ||
optional: TConfig['optional'] extends true ? true : false; | ||
}>; | ||
@@ -84,31 +86,45 @@ /** @public */ | ||
/** @public */ | ||
type ExtensionDataInputValues<TInputs extends { | ||
[name in string]: { | ||
extensionData: AnyExtensionDataMap; | ||
}; | ||
}> = { | ||
[InputName in keyof TInputs]: Array<{ | ||
[DataName in keyof TInputs[InputName]['extensionData'] as TInputs[InputName]['extensionData'][DataName]['config'] extends { | ||
optional: true; | ||
} ? never : DataName]: TInputs[InputName]['extensionData'][DataName]['T']; | ||
} & { | ||
[DataName in keyof TInputs[InputName]['extensionData'] as TInputs[InputName]['extensionData'][DataName]['config'] extends { | ||
optional: true; | ||
} ? DataName : never]?: TInputs[InputName]['extensionData'][DataName]['T']; | ||
type AnyExtensionDataMap = { | ||
[name in string]: ExtensionDataRef<unknown, { | ||
optional?: true; | ||
}>; | ||
}; | ||
/** @public */ | ||
type ExtensionDataBind<TMap extends AnyExtensionDataMap> = (values: { | ||
[DataName in keyof TMap as TMap[DataName]['config'] extends { | ||
type AnyExtensionInputMap = { | ||
[inputName in string]: ExtensionInput<AnyExtensionDataMap, { | ||
optional: boolean; | ||
singleton: boolean; | ||
}>; | ||
}; | ||
/** | ||
* Utility type to expand type aliases into their equivalent type. | ||
* @ignore | ||
*/ | ||
type Expand<T> = T extends infer O ? { | ||
[K in keyof O]: O[K]; | ||
} : never; | ||
/** | ||
* Converts an extension data map into the matching concrete data values type. | ||
* @public | ||
*/ | ||
type ExtensionDataValues<TExtensionData extends AnyExtensionDataMap> = { | ||
[DataName in keyof TExtensionData as TExtensionData[DataName]['config'] extends { | ||
optional: true; | ||
} ? never : DataName]: TMap[DataName]['T']; | ||
} ? never : DataName]: TExtensionData[DataName]['T']; | ||
} & { | ||
[DataName in keyof TMap as TMap[DataName]['config'] extends { | ||
[DataName in keyof TExtensionData as TExtensionData[DataName]['config'] extends { | ||
optional: true; | ||
} ? DataName : never]?: TMap[DataName]['T']; | ||
}) => void; | ||
} ? DataName : never]?: TExtensionData[DataName]['T']; | ||
}; | ||
/** | ||
* Converts an extension input map into the matching concrete input values type. | ||
* @public | ||
*/ | ||
type ExtensionInputValues<TInputs extends { | ||
[name in string]: ExtensionInput<any, any>; | ||
}> = { | ||
[InputName in keyof TInputs]: false extends TInputs[InputName]['config']['singleton'] ? Array<Expand<ExtensionDataValues<TInputs[InputName]['extensionData']>>> : false extends TInputs[InputName]['config']['optional'] ? Expand<ExtensionDataValues<TInputs[InputName]['extensionData']>> : Expand<ExtensionDataValues<TInputs[InputName]['extensionData']> | undefined>; | ||
}; | ||
/** @public */ | ||
interface CreateExtensionOptions<TOutput extends AnyExtensionDataMap, TInputs extends Record<string, { | ||
extensionData: AnyExtensionDataMap; | ||
}>, TConfig> { | ||
interface CreateExtensionOptions<TOutput extends AnyExtensionDataMap, TInputs extends AnyExtensionInputMap, TConfig> { | ||
id: string; | ||
@@ -122,11 +138,25 @@ at: string; | ||
source?: BackstagePlugin; | ||
bind: ExtensionDataBind<TOutput>; | ||
bind(values: Expand<ExtensionDataValues<TOutput>>): void; | ||
config: TConfig; | ||
inputs: ExtensionDataInputValues<TInputs>; | ||
inputs: Expand<ExtensionInputValues<TInputs>>; | ||
}): void; | ||
} | ||
/** @public */ | ||
declare function createExtension<TOutput extends AnyExtensionDataMap, TInputs extends Record<string, { | ||
extensionData: AnyExtensionDataMap; | ||
}>, TConfig = never>(options: CreateExtensionOptions<TOutput, TInputs, TConfig>): Extension<TConfig>; | ||
interface Extension<TConfig> { | ||
$$type: '@backstage/Extension'; | ||
id: string; | ||
at: string; | ||
disabled: boolean; | ||
inputs: AnyExtensionInputMap; | ||
output: AnyExtensionDataMap; | ||
configSchema?: PortableSchema<TConfig>; | ||
factory(options: { | ||
source?: BackstagePlugin; | ||
bind(values: ExtensionInputValues<any>): void; | ||
config: TConfig; | ||
inputs: Record<string, undefined | Record<string, unknown> | Array<Record<string, unknown>>>; | ||
}): void; | ||
} | ||
/** @public */ | ||
declare function createExtension<TOutput extends AnyExtensionDataMap, TInputs extends AnyExtensionInputMap, TConfig = never>(options: CreateExtensionOptions<TOutput, TInputs, TConfig>): Extension<TConfig>; | ||
@@ -142,9 +172,7 @@ /** @public */ | ||
/** @public */ | ||
declare function createApiExtension<TConfig extends {}, TInputs extends Record<string, { | ||
extensionData: AnyExtensionDataMap; | ||
}>>(options: ({ | ||
declare function createApiExtension<TConfig extends {}, TInputs extends AnyExtensionInputMap>(options: ({ | ||
api: AnyApiRef; | ||
factory: (options: { | ||
config: TConfig; | ||
inputs: ExtensionDataInputValues<TInputs>; | ||
inputs: Expand<ExtensionInputValues<TInputs>>; | ||
}) => AnyApiFactory; | ||
@@ -165,5 +193,3 @@ } | { | ||
path: string; | ||
}, TInputs extends Record<string, { | ||
extensionData: AnyExtensionDataMap; | ||
}>>(options: ({ | ||
}, TInputs extends AnyExtensionInputMap>(options: ({ | ||
defaultPath: string; | ||
@@ -178,11 +204,24 @@ } | { | ||
routeRef?: RouteRef; | ||
component: (props: { | ||
loader: (options: { | ||
config: TConfig; | ||
inputs: ExtensionDataInputValues<TInputs>; | ||
inputs: Expand<ExtensionInputValues<TInputs>>; | ||
}) => Promise<JSX.Element>; | ||
}): Extension<TConfig>; | ||
/** | ||
* Helper for creating extensions for a nav item. | ||
* @public | ||
*/ | ||
declare function createNavItemExtension(options: { | ||
id: string; | ||
routeRef: RouteRef; | ||
title: string; | ||
icon: IconComponent; | ||
}): Extension<{ | ||
title: string; | ||
}>; | ||
/** @public */ | ||
declare function useRouteRef(routeRef: RouteRef<any>): () => string; | ||
export { AnyExtensionDataMap, BackstagePlugin, ConfigurableExtensionDataRef, CreateExtensionOptions, Extension, ExtensionBoundary, ExtensionBoundaryProps, ExtensionDataBind, ExtensionDataInputValues, ExtensionDataRef, PluginOptions, PortableSchema, coreExtensionData, createApiExtension, createExtension, createExtensionDataRef, createPageExtension, createPlugin, createSchemaFromZod, useRouteRef }; | ||
export { AnyExtensionDataMap, AnyExtensionInputMap, BackstagePlugin, ConfigurableExtensionDataRef, CreateExtensionOptions, Extension, ExtensionBoundary, ExtensionBoundaryProps, ExtensionDataRef, ExtensionDataValues, ExtensionInput, ExtensionInputValues, NavTarget, PluginOptions, PortableSchema, coreExtensionData, createApiExtension, createExtension, createExtensionDataRef, createExtensionInput, createNavItemExtension, createPageExtension, createPlugin, createSchemaFromZod, useRouteRef }; |
@@ -23,6 +23,7 @@ import React, { useContext, useMemo } from 'react'; | ||
const coreExtensionData = { | ||
reactComponent: createExtensionDataRef("core.reactComponent"), | ||
reactElement: createExtensionDataRef("core.reactElement"), | ||
routePath: createExtensionDataRef("core.routing.path"), | ||
apiFactory: createExtensionDataRef("core.api.factory"), | ||
routeRef: createExtensionDataRef("core.routing.ref") | ||
routeRef: createExtensionDataRef("core.routing.ref"), | ||
navTarget: createExtensionDataRef("core.nav.target") | ||
}; | ||
@@ -47,2 +48,13 @@ | ||
function createExtensionInput(extensionData, config) { | ||
return { | ||
$$type: "@backstage/ExtensionInput", | ||
extensionData, | ||
config: { | ||
singleton: Boolean(config == null ? void 0 : config.singleton), | ||
optional: Boolean(config == null ? void 0 : config.optional) | ||
} | ||
}; | ||
} | ||
function createPlugin(options) { | ||
@@ -117,3 +129,3 @@ var _a; | ||
output: { | ||
component: coreExtensionData.reactComponent, | ||
element: coreExtensionData.reactElement, | ||
path: coreExtensionData.routePath, | ||
@@ -126,7 +138,7 @@ routeRef: coreExtensionData.routeRef.optional() | ||
const LazyComponent = React.lazy( | ||
() => options.component({ config, inputs }).then((element) => ({ default: () => element })) | ||
() => options.loader({ config, inputs }).then((element) => ({ default: () => element })) | ||
); | ||
bind({ | ||
path: config.path, | ||
component: () => /* @__PURE__ */ React.createElement(ExtensionBoundary, { source }, /* @__PURE__ */ React.createElement(React.Suspense, { fallback: "..." }, /* @__PURE__ */ React.createElement(LazyComponent, null))), | ||
element: /* @__PURE__ */ React.createElement(ExtensionBoundary, { source }, /* @__PURE__ */ React.createElement(React.Suspense, { fallback: "..." }, /* @__PURE__ */ React.createElement(LazyComponent, null))), | ||
routeRef: options.routeRef | ||
@@ -138,2 +150,27 @@ }); | ||
function createNavItemExtension(options) { | ||
const { id, routeRef, title, icon } = options; | ||
return createExtension({ | ||
id, | ||
at: "core.nav/items", | ||
configSchema: createSchemaFromZod( | ||
(z) => z.object({ | ||
title: z.string().default(title) | ||
}) | ||
), | ||
output: { | ||
navTarget: coreExtensionData.navTarget | ||
}, | ||
factory: ({ bind, config }) => { | ||
bind({ | ||
navTarget: { | ||
title: config.title, | ||
icon, | ||
routeRef | ||
} | ||
}); | ||
} | ||
}); | ||
} | ||
function useRouteRef(routeRef) { | ||
@@ -152,3 +189,3 @@ const { pathname } = useLocation(); | ||
export { ExtensionBoundary, coreExtensionData, createApiExtension, createExtension, createExtensionDataRef, createPageExtension, createPlugin, createSchemaFromZod, useRouteRef }; | ||
export { ExtensionBoundary, coreExtensionData, createApiExtension, createExtension, createExtensionDataRef, createExtensionInput, createNavItemExtension, createPageExtension, createPlugin, createSchemaFromZod, useRouteRef }; | ||
//# sourceMappingURL=index.esm.js.map |
{ | ||
"name": "@backstage/frontend-plugin-api", | ||
"version": "0.1.0-next.0", | ||
"version": "0.1.0", | ||
"main": "dist/index.esm.js", | ||
@@ -26,5 +26,5 @@ "types": "dist/index.d.ts", | ||
"devDependencies": { | ||
"@backstage/cli": "^0.22.13-next.3", | ||
"@backstage/frontend-app-api": "^0.1.0-next.0", | ||
"@backstage/test-utils": "^1.4.3-next.3", | ||
"@backstage/cli": "^0.22.13", | ||
"@backstage/frontend-app-api": "^0.1.0", | ||
"@backstage/test-utils": "^1.4.3", | ||
"@testing-library/jest-dom": "^5.10.1", | ||
@@ -41,4 +41,4 @@ "@testing-library/react": "^12.1.3" | ||
"dependencies": { | ||
"@backstage/core-plugin-api": "^1.6.0-next.3", | ||
"@backstage/types": "^1.1.1-next.0", | ||
"@backstage/core-plugin-api": "^1.6.0", | ||
"@backstage/types": "^1.1.1", | ||
"@types/react": "^16.13.1 || ^17.0.0", | ||
@@ -45,0 +45,0 @@ "lodash": "^4.17.21", |
Sorry, the diff of this file is not supported yet
41331
382
Updated@backstage/types@^1.1.1