Use interface and not implementation in ApiRef<T>
Closes #4404 Signed-off-by: Oliver Sand <oliver.sand@sda-se.com>
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
---
|
||||
'@backstage/plugin-techdocs': patch
|
||||
---
|
||||
|
||||
Make `techdocsStorageApiRef` and `techdocsApiRef` use interfaces instead of the
|
||||
actual implementation classes.
|
||||
|
||||
This renames the classes `TechDocsApi` to `TechDocsClient` and `TechDocsStorageApi`
|
||||
to `TechDocsStorageClient` and renames the interfaces `TechDocs` to `TechDocsApi`
|
||||
and `TechDocsStorage` to `TechDocsStorageApi` to comply the pattern elsewhere in
|
||||
the project. This also fixes the types returned by some methods on those
|
||||
interfaces.
|
||||
@@ -13,13 +13,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { DiscoveryApi, IdentityApi } from '@backstage/core';
|
||||
import { Config } from '@backstage/config';
|
||||
import { EntityName } from '@backstage/catalog-model';
|
||||
import { TechDocsStorage } from '../src/api';
|
||||
import { Config } from '@backstage/config';
|
||||
import { DiscoveryApi, IdentityApi } from '@backstage/core';
|
||||
import { NotFoundError } from '@backstage/errors';
|
||||
import { TechDocsStorageApi } from '../src/api';
|
||||
|
||||
export class TechDocsDevStorageApi implements TechDocsStorage {
|
||||
export class TechDocsDevStorageApi implements TechDocsStorageApi {
|
||||
public configApi: Config;
|
||||
public discoveryApi: DiscoveryApi;
|
||||
public identityApi: IdentityApi;
|
||||
|
||||
+9
-227
@@ -14,11 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createApiRef, DiscoveryApi, IdentityApi } from '@backstage/core';
|
||||
import { Config } from '@backstage/config';
|
||||
import { EntityName } from '@backstage/catalog-model';
|
||||
import { TechDocsMetadata } from './types';
|
||||
import { NotFoundError } from '@backstage/errors';
|
||||
import { createApiRef } from '@backstage/core';
|
||||
import { TechDocsEntityMetadata, TechDocsMetadata } from './types';
|
||||
|
||||
export const techdocsStorageApiRef = createApiRef<TechDocsStorageApi>({
|
||||
id: 'plugin.techdocs.storageservice',
|
||||
@@ -30,7 +28,10 @@ export const techdocsApiRef = createApiRef<TechDocsApi>({
|
||||
description: 'Used to make requests towards techdocs API',
|
||||
});
|
||||
|
||||
export interface TechDocsStorage {
|
||||
export interface TechDocsStorageApi {
|
||||
getApiOrigin(): Promise<string>;
|
||||
getStorageUrl(): Promise<string>;
|
||||
getBuilder(): Promise<string>;
|
||||
getEntityDocs(entityId: EntityName, path: string): Promise<string>;
|
||||
syncEntityDocs(entityId: EntityName): Promise<boolean>;
|
||||
getBaseUrl(
|
||||
@@ -40,227 +41,8 @@ export interface TechDocsStorage {
|
||||
): Promise<string>;
|
||||
}
|
||||
|
||||
export interface TechDocs {
|
||||
export interface TechDocsApi {
|
||||
getApiOrigin(): Promise<string>;
|
||||
getTechDocsMetadata(entityId: EntityName): Promise<TechDocsMetadata>;
|
||||
getEntityMetadata(entityId: EntityName): Promise<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* API to talk to techdocs-backend.
|
||||
*
|
||||
* @property {string} apiOrigin Set to techdocs.requestUrl as the URL for techdocs-backend API
|
||||
*/
|
||||
export class TechDocsApi implements TechDocs {
|
||||
public configApi: Config;
|
||||
public discoveryApi: DiscoveryApi;
|
||||
public identityApi: IdentityApi;
|
||||
|
||||
constructor({
|
||||
configApi,
|
||||
discoveryApi,
|
||||
identityApi,
|
||||
}: {
|
||||
configApi: Config;
|
||||
discoveryApi: DiscoveryApi;
|
||||
identityApi: IdentityApi;
|
||||
}) {
|
||||
this.configApi = configApi;
|
||||
this.discoveryApi = discoveryApi;
|
||||
this.identityApi = identityApi;
|
||||
}
|
||||
|
||||
async getApiOrigin() {
|
||||
return (
|
||||
this.configApi.getOptionalString('techdocs.requestUrl') ??
|
||||
(await this.discoveryApi.getBaseUrl('techdocs'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve TechDocs metadata.
|
||||
*
|
||||
* When docs are built, we generate a techdocs_metadata.json and store it along with the generated
|
||||
* static files. It includes necessary data about the docs site. This method requests techdocs-backend
|
||||
* which retrieves the TechDocs metadata.
|
||||
*
|
||||
* @param {EntityName} entityId Object containing entity data like name, namespace, etc.
|
||||
*/
|
||||
async getTechDocsMetadata(entityId: EntityName) {
|
||||
const { kind, namespace, name } = entityId;
|
||||
|
||||
const apiOrigin = await this.getApiOrigin();
|
||||
const requestUrl = `${apiOrigin}/metadata/techdocs/${namespace}/${kind}/${name}`;
|
||||
const token = await this.identityApi.getIdToken();
|
||||
|
||||
const request = await fetch(`${requestUrl}`, {
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
||||
});
|
||||
const res = await request.json();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve metadata about an entity.
|
||||
*
|
||||
* This method requests techdocs-backend which uses the catalog APIs to respond with filtered
|
||||
* information required here.
|
||||
*
|
||||
* @param {EntityName} entityId Object containing entity data like name, namespace, etc.
|
||||
*/
|
||||
async getEntityMetadata(entityId: EntityName) {
|
||||
const { kind, namespace, name } = entityId;
|
||||
|
||||
const apiOrigin = await this.getApiOrigin();
|
||||
const requestUrl = `${apiOrigin}/metadata/entity/${namespace}/${kind}/${name}`;
|
||||
const token = await this.identityApi.getIdToken();
|
||||
|
||||
const request = await fetch(`${requestUrl}`, {
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
||||
});
|
||||
const res = await request.json();
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* API which talks to TechDocs storage to fetch files to render.
|
||||
*
|
||||
* @property {string} apiOrigin Set to techdocs.requestUrl as the URL for techdocs-backend API
|
||||
*/
|
||||
export class TechDocsStorageApi implements TechDocsStorage {
|
||||
public configApi: Config;
|
||||
public discoveryApi: DiscoveryApi;
|
||||
public identityApi: IdentityApi;
|
||||
|
||||
constructor({
|
||||
configApi,
|
||||
discoveryApi,
|
||||
identityApi,
|
||||
}: {
|
||||
configApi: Config;
|
||||
discoveryApi: DiscoveryApi;
|
||||
identityApi: IdentityApi;
|
||||
}) {
|
||||
this.configApi = configApi;
|
||||
this.discoveryApi = discoveryApi;
|
||||
this.identityApi = identityApi;
|
||||
}
|
||||
|
||||
async getApiOrigin() {
|
||||
return (
|
||||
this.configApi.getOptionalString('techdocs.requestUrl') ??
|
||||
(await this.discoveryApi.getBaseUrl('techdocs'))
|
||||
);
|
||||
}
|
||||
|
||||
async getStorageUrl() {
|
||||
return (
|
||||
this.configApi.getOptionalString('techdocs.storageUrl') ??
|
||||
`${await this.discoveryApi.getBaseUrl('techdocs')}/static/docs`
|
||||
);
|
||||
}
|
||||
|
||||
async getBuilder() {
|
||||
return this.configApi.getString('techdocs.builder');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch HTML content as text for an individual docs page in an entity's docs site.
|
||||
*
|
||||
* @param {EntityName} entityId Object containing entity data like name, namespace, etc.
|
||||
* @param {string} path The unique path to an individual docs page e.g. overview/what-is-new
|
||||
* @returns {string} HTML content of the docs page as string
|
||||
* @throws {Error} Throws error when the page is not found.
|
||||
*/
|
||||
async getEntityDocs(entityId: EntityName, path: string) {
|
||||
const { kind, namespace, name } = entityId;
|
||||
|
||||
const storageUrl = await this.getStorageUrl();
|
||||
const url = `${storageUrl}/${namespace}/${kind}/${name}/${path}`;
|
||||
const token = await this.identityApi.getIdToken();
|
||||
|
||||
const request = await fetch(
|
||||
`${url.endsWith('/') ? url : `${url}/`}index.html`,
|
||||
{
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
||||
},
|
||||
);
|
||||
|
||||
let errorMessage = '';
|
||||
switch (request.status) {
|
||||
case 404:
|
||||
errorMessage = 'Page not found. ';
|
||||
// path is empty for the home page of an entity's docs site
|
||||
if (!path) {
|
||||
errorMessage +=
|
||||
'This could be because there is no index.md file in the root of the docs directory of this repository.';
|
||||
}
|
||||
throw new NotFoundError(errorMessage);
|
||||
case 500:
|
||||
errorMessage =
|
||||
'Could not generate documentation or an error in the TechDocs backend. ';
|
||||
throw new Error(errorMessage);
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
return request.text();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if docs are on the latest version and trigger rebuild if not
|
||||
*
|
||||
* @param {EntityName} entityId Object containing entity data like name, namespace, etc.
|
||||
* @returns {boolean} Whether documents are currently synchronized to newest version
|
||||
* @throws {Error} Throws error on error from sync endpoint in Techdocs Backend
|
||||
*/
|
||||
async syncEntityDocs(entityId: EntityName) {
|
||||
const { kind, namespace, name } = entityId;
|
||||
|
||||
const apiOrigin = await this.getApiOrigin();
|
||||
const url = `${apiOrigin}/sync/${namespace}/${kind}/${name}`;
|
||||
const token = await this.identityApi.getIdToken();
|
||||
let request;
|
||||
let attempts: number = 0;
|
||||
// retry if request times out, up to 5 times
|
||||
// can happen due to docs taking too long to generate
|
||||
while (!request || (request.status === 408 && attempts < 5)) {
|
||||
attempts++;
|
||||
request = await fetch(url, {
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
||||
});
|
||||
}
|
||||
|
||||
switch (request.status) {
|
||||
case 404:
|
||||
throw new NotFoundError((await request.json()).error);
|
||||
case 200:
|
||||
case 201:
|
||||
case 304:
|
||||
return true;
|
||||
// for timeout and misc errors, handle without error to allow viewing older docs
|
||||
// if older docs not available,
|
||||
// Reader will show 404 error coming from getEntityDocs
|
||||
case 408:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async getBaseUrl(
|
||||
oldBaseUrl: string,
|
||||
entityId: EntityName,
|
||||
path: string,
|
||||
): Promise<string> {
|
||||
const { kind, namespace, name } = entityId;
|
||||
|
||||
const apiOrigin = await this.getApiOrigin();
|
||||
return new URL(
|
||||
oldBaseUrl,
|
||||
`${apiOrigin}/static/docs/${namespace}/${kind}/${name}/${path}`,
|
||||
).toString();
|
||||
}
|
||||
getEntityMetadata(entityId: EntityName): Promise<TechDocsEntityMetadata>;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
import { Config } from '@backstage/config';
|
||||
import { UrlPatternDiscovery } from '@backstage/core';
|
||||
import { TechDocsStorageApi } from './api';
|
||||
import { TechDocsStorageClient } from './client';
|
||||
|
||||
const mockEntity = {
|
||||
kind: 'Component',
|
||||
@@ -23,7 +23,7 @@ const mockEntity = {
|
||||
name: 'test-component',
|
||||
};
|
||||
|
||||
describe('TechDocsStorageApi', () => {
|
||||
describe('TechDocsStorageClient', () => {
|
||||
const mockBaseUrl = 'http://backstage:9191/api/techdocs';
|
||||
const configApi = {
|
||||
getOptionalString: () => 'http://backstage:9191/api/techdocs',
|
||||
@@ -32,7 +32,7 @@ describe('TechDocsStorageApi', () => {
|
||||
|
||||
it('should return correct base url based on defined storage', async () => {
|
||||
// @ts-ignore Partial<Config> not assignable to Config.
|
||||
const storageApi = new TechDocsStorageApi({ configApi, discoveryApi });
|
||||
const storageApi = new TechDocsStorageClient({ configApi, discoveryApi });
|
||||
|
||||
await expect(
|
||||
storageApi.getBaseUrl('test.js', mockEntity, ''),
|
||||
@@ -43,7 +43,7 @@ describe('TechDocsStorageApi', () => {
|
||||
|
||||
it('should return base url with correct entity structure', async () => {
|
||||
// @ts-ignore Partial<Config> not assignable to Config.
|
||||
const storageApi = new TechDocsStorageApi({ configApi, discoveryApi });
|
||||
const storageApi = new TechDocsStorageClient({ configApi, discoveryApi });
|
||||
|
||||
await expect(
|
||||
storageApi.getBaseUrl('test/', mockEntity, ''),
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { EntityName } from '@backstage/catalog-model';
|
||||
import { Config } from '@backstage/config';
|
||||
import { DiscoveryApi, IdentityApi } from '@backstage/core';
|
||||
import { NotFoundError } from '@backstage/errors';
|
||||
import { TechDocsApi, TechDocsStorageApi } from './api';
|
||||
import { TechDocsEntityMetadata, TechDocsMetadata } from './types';
|
||||
|
||||
/**
|
||||
* API to talk to techdocs-backend.
|
||||
*
|
||||
* @property {string} apiOrigin Set to techdocs.requestUrl as the URL for techdocs-backend API
|
||||
*/
|
||||
export class TechDocsClient implements TechDocsApi {
|
||||
public configApi: Config;
|
||||
public discoveryApi: DiscoveryApi;
|
||||
public identityApi: IdentityApi;
|
||||
|
||||
constructor({
|
||||
configApi,
|
||||
discoveryApi,
|
||||
identityApi,
|
||||
}: {
|
||||
configApi: Config;
|
||||
discoveryApi: DiscoveryApi;
|
||||
identityApi: IdentityApi;
|
||||
}) {
|
||||
this.configApi = configApi;
|
||||
this.discoveryApi = discoveryApi;
|
||||
this.identityApi = identityApi;
|
||||
}
|
||||
|
||||
async getApiOrigin(): Promise<string> {
|
||||
return (
|
||||
this.configApi.getOptionalString('techdocs.requestUrl') ??
|
||||
(await this.discoveryApi.getBaseUrl('techdocs'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve TechDocs metadata.
|
||||
*
|
||||
* When docs are built, we generate a techdocs_metadata.json and store it along with the generated
|
||||
* static files. It includes necessary data about the docs site. This method requests techdocs-backend
|
||||
* which retrieves the TechDocs metadata.
|
||||
*
|
||||
* @param {EntityName} entityId Object containing entity data like name, namespace, etc.
|
||||
*/
|
||||
async getTechDocsMetadata(entityId: EntityName): Promise<TechDocsMetadata> {
|
||||
const { kind, namespace, name } = entityId;
|
||||
|
||||
const apiOrigin = await this.getApiOrigin();
|
||||
const requestUrl = `${apiOrigin}/metadata/techdocs/${namespace}/${kind}/${name}`;
|
||||
const token = await this.identityApi.getIdToken();
|
||||
|
||||
const request = await fetch(`${requestUrl}`, {
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
||||
});
|
||||
const res = await request.json();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve metadata about an entity.
|
||||
*
|
||||
* This method requests techdocs-backend which uses the catalog APIs to respond with filtered
|
||||
* information required here.
|
||||
*
|
||||
* @param {EntityName} entityId Object containing entity data like name, namespace, etc.
|
||||
*/
|
||||
async getEntityMetadata(
|
||||
entityId: EntityName,
|
||||
): Promise<TechDocsEntityMetadata> {
|
||||
const { kind, namespace, name } = entityId;
|
||||
|
||||
const apiOrigin = await this.getApiOrigin();
|
||||
const requestUrl = `${apiOrigin}/metadata/entity/${namespace}/${kind}/${name}`;
|
||||
const token = await this.identityApi.getIdToken();
|
||||
|
||||
const request = await fetch(`${requestUrl}`, {
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
||||
});
|
||||
const res = await request.json();
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* API which talks to TechDocs storage to fetch files to render.
|
||||
*
|
||||
* @property {string} apiOrigin Set to techdocs.requestUrl as the URL for techdocs-backend API
|
||||
*/
|
||||
export class TechDocsStorageClient implements TechDocsStorageApi {
|
||||
public configApi: Config;
|
||||
public discoveryApi: DiscoveryApi;
|
||||
public identityApi: IdentityApi;
|
||||
|
||||
constructor({
|
||||
configApi,
|
||||
discoveryApi,
|
||||
identityApi,
|
||||
}: {
|
||||
configApi: Config;
|
||||
discoveryApi: DiscoveryApi;
|
||||
identityApi: IdentityApi;
|
||||
}) {
|
||||
this.configApi = configApi;
|
||||
this.discoveryApi = discoveryApi;
|
||||
this.identityApi = identityApi;
|
||||
}
|
||||
|
||||
async getApiOrigin(): Promise<string> {
|
||||
return (
|
||||
this.configApi.getOptionalString('techdocs.requestUrl') ??
|
||||
(await this.discoveryApi.getBaseUrl('techdocs'))
|
||||
);
|
||||
}
|
||||
|
||||
async getStorageUrl(): Promise<string> {
|
||||
return (
|
||||
this.configApi.getOptionalString('techdocs.storageUrl') ??
|
||||
`${await this.discoveryApi.getBaseUrl('techdocs')}/static/docs`
|
||||
);
|
||||
}
|
||||
|
||||
async getBuilder(): Promise<string> {
|
||||
return this.configApi.getString('techdocs.builder');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch HTML content as text for an individual docs page in an entity's docs site.
|
||||
*
|
||||
* @param {EntityName} entityId Object containing entity data like name, namespace, etc.
|
||||
* @param {string} path The unique path to an individual docs page e.g. overview/what-is-new
|
||||
* @returns {string} HTML content of the docs page as string
|
||||
* @throws {Error} Throws error when the page is not found.
|
||||
*/
|
||||
async getEntityDocs(entityId: EntityName, path: string): Promise<string> {
|
||||
const { kind, namespace, name } = entityId;
|
||||
|
||||
const storageUrl = await this.getStorageUrl();
|
||||
const url = `${storageUrl}/${namespace}/${kind}/${name}/${path}`;
|
||||
const token = await this.identityApi.getIdToken();
|
||||
|
||||
const request = await fetch(
|
||||
`${url.endsWith('/') ? url : `${url}/`}index.html`,
|
||||
{
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
||||
},
|
||||
);
|
||||
|
||||
let errorMessage = '';
|
||||
switch (request.status) {
|
||||
case 404:
|
||||
errorMessage = 'Page not found. ';
|
||||
// path is empty for the home page of an entity's docs site
|
||||
if (!path) {
|
||||
errorMessage +=
|
||||
'This could be because there is no index.md file in the root of the docs directory of this repository.';
|
||||
}
|
||||
throw new NotFoundError(errorMessage);
|
||||
case 500:
|
||||
errorMessage =
|
||||
'Could not generate documentation or an error in the TechDocs backend. ';
|
||||
throw new Error(errorMessage);
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
return request.text();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if docs are on the latest version and trigger rebuild if not
|
||||
*
|
||||
* @param {EntityName} entityId Object containing entity data like name, namespace, etc.
|
||||
* @returns {boolean} Whether documents are currently synchronized to newest version
|
||||
* @throws {Error} Throws error on error from sync endpoint in Techdocs Backend
|
||||
*/
|
||||
async syncEntityDocs(entityId: EntityName): Promise<boolean> {
|
||||
const { kind, namespace, name } = entityId;
|
||||
|
||||
const apiOrigin = await this.getApiOrigin();
|
||||
const url = `${apiOrigin}/sync/${namespace}/${kind}/${name}`;
|
||||
const token = await this.identityApi.getIdToken();
|
||||
let request;
|
||||
let attempts: number = 0;
|
||||
// retry if request times out, up to 5 times
|
||||
// can happen due to docs taking too long to generate
|
||||
while (!request || (request.status === 408 && attempts < 5)) {
|
||||
attempts++;
|
||||
request = await fetch(url, {
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
||||
});
|
||||
}
|
||||
|
||||
switch (request.status) {
|
||||
case 404:
|
||||
throw new NotFoundError((await request.json()).error);
|
||||
case 200:
|
||||
case 201:
|
||||
case 304:
|
||||
return true;
|
||||
// for timeout and misc errors, handle without error to allow viewing older docs
|
||||
// if older docs not available,
|
||||
// Reader will show 404 error coming from getEntityDocs
|
||||
case 408:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async getBaseUrl(
|
||||
oldBaseUrl: string,
|
||||
entityId: EntityName,
|
||||
path: string,
|
||||
): Promise<string> {
|
||||
const { kind, namespace, name } = entityId;
|
||||
|
||||
const apiOrigin = await this.getApiOrigin();
|
||||
return new URL(
|
||||
oldBaseUrl,
|
||||
`${apiOrigin}/static/docs/${namespace}/${kind}/${name}/${path}`,
|
||||
).toString();
|
||||
}
|
||||
}
|
||||
@@ -14,17 +14,20 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './api';
|
||||
export { techdocsApiRef, techdocsStorageApiRef } from './api';
|
||||
export type { TechDocsApi, TechDocsStorageApi } from './api';
|
||||
export { TechDocsClient, TechDocsStorageClient } from './client';
|
||||
export type { PanelType } from './home/components/TechDocsCustomHome';
|
||||
export {
|
||||
techdocsPlugin,
|
||||
techdocsPlugin as plugin,
|
||||
TechdocsPage,
|
||||
EntityTechdocsContent,
|
||||
DocsCardGrid,
|
||||
DocsTable,
|
||||
EntityTechdocsContent,
|
||||
TechDocsCustomHome,
|
||||
TechdocsPage,
|
||||
techdocsPlugin as plugin,
|
||||
techdocsPlugin,
|
||||
TechDocsReaderPage,
|
||||
} from './plugin';
|
||||
export { Router, EmbeddedDocsRouter } from './Router';
|
||||
export * from './reader';
|
||||
export * from './api';
|
||||
export type { PanelType } from './home/components/TechDocsCustomHome';
|
||||
export { EmbeddedDocsRouter, Router } from './Router';
|
||||
|
||||
@@ -30,21 +30,17 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
createPlugin,
|
||||
createRouteRef,
|
||||
createApiFactory,
|
||||
configApiRef,
|
||||
createApiFactory,
|
||||
createComponentExtension,
|
||||
createPlugin,
|
||||
createRoutableExtension,
|
||||
createRouteRef,
|
||||
discoveryApiRef,
|
||||
identityApiRef,
|
||||
createRoutableExtension,
|
||||
createComponentExtension,
|
||||
} from '@backstage/core';
|
||||
import {
|
||||
techdocsStorageApiRef,
|
||||
TechDocsStorageApi,
|
||||
techdocsApiRef,
|
||||
TechDocsApi,
|
||||
} from './api';
|
||||
import { techdocsApiRef, techdocsStorageApiRef } from './api';
|
||||
import { TechDocsClient, TechDocsStorageClient } from './client';
|
||||
|
||||
export const rootRouteRef = createRouteRef({
|
||||
path: '',
|
||||
@@ -72,7 +68,7 @@ export const techdocsPlugin = createPlugin({
|
||||
identityApi: identityApiRef,
|
||||
},
|
||||
factory: ({ configApi, discoveryApi, identityApi }) =>
|
||||
new TechDocsStorageApi({
|
||||
new TechDocsStorageClient({
|
||||
configApi,
|
||||
discoveryApi,
|
||||
identityApi,
|
||||
@@ -86,7 +82,7 @@ export const techdocsPlugin = createPlugin({
|
||||
identityApi: identityApiRef,
|
||||
},
|
||||
factory: ({ configApi, discoveryApi, identityApi }) =>
|
||||
new TechDocsApi({
|
||||
new TechDocsClient({
|
||||
configApi,
|
||||
discoveryApi,
|
||||
identityApi,
|
||||
|
||||
@@ -14,7 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Entity, Location } from '@backstage/catalog-model';
|
||||
|
||||
export type TechDocsMetadata = {
|
||||
site_name: string;
|
||||
site_description: string;
|
||||
};
|
||||
|
||||
export type TechDocsEntityMetadata = Entity & { locationMetadata?: Location };
|
||||
|
||||
Reference in New Issue
Block a user