Initial work on the backend/next setup for the catalog

Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: blam <ben@blam.sh>
Co-authored-by: Johan Haals <johan.haals@gmail.com>
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
Fredrik Adelöw
2022-06-15 14:27:23 +02:00
committed by Patrik Oldsberg
parent 4ad817262c
commit 39b24c78fe
19 changed files with 697 additions and 34 deletions
+15
View File
@@ -0,0 +1,15 @@
## API Report File for "@backstage/backend-app-api"
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
import { AnyServiceFactory } from '@backstage/backend-plugin-api';
import { BackendRegistrable } from '@backstage/backend-plugin-api';
// Warning: (ae-forgotten-export) The symbol "CreateBackendOptions" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "Backend" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "createBackend" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function createBackend(options?: CreateBackendOptions): Backend;
```
+3 -1
View File
@@ -33,7 +33,9 @@
"clean": "backstage-cli package clean",
"start": "backstage-cli package start"
},
"dependencies": {},
"dependencies": {
"@backstage/backend-plugin-api": "^0.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.17.2-next.0"
},
+1 -1
View File
@@ -20,4 +20,4 @@
* @packageDocumentation
*/
export {};
export { createBackend } from './wiring/types';
@@ -0,0 +1,153 @@
/*
* Copyright 2022 The Backstage Authors
*
* 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 { BackendRegistrable, ServiceRef } from '@backstage/backend-plugin-api';
import { BackendRegisterInit, ApiHolder } from './types';
export class BackendInitializer {
#started = false;
#extensions = new Map<BackendRegistrable, unknown>();
// #stops = [];
#registerInits = new Array<BackendRegisterInit>();
#apis = new Map<ServiceRef<unknown>, unknown>();
#apiHolder: ApiHolder;
constructor(apiHolder: ApiHolder) {
this.#apiHolder = apiHolder;
}
async #getInitDeps(
deps: { [name: string]: ServiceRef<unknown> },
pluginId: string,
) {
return Object.fromEntries(
await Promise.all(
Object.entries(deps).map(async ([name, apiRef]) => [
name,
this.#apis.get(apiRef) ||
(await this.#apiHolder.get(apiRef)!(pluginId)),
]),
),
);
}
add<TOptions>(extension: BackendRegistrable, options?: TOptions) {
if (this.#started) {
throw new Error(
'extension can not be added after the backend has started',
);
}
this.#extensions.set(extension, options);
}
async start(): Promise<void> {
console.log(`Starting backend`);
if (this.#started) {
throw new Error('Backend has already started');
}
this.#started = true;
for (const [extension] of this.#extensions) {
const provides = new Set<ServiceRef<unknown>>();
let registerInit: BackendRegisterInit | undefined = undefined;
console.log('Registering', extension.id);
extension.register({
registerExtensionPoint: (api, impl) => {
if (registerInit) {
throw new Error('registerInitApi called after registerInit');
}
if (this.#apis.has(api)) {
throw new Error(`API ${api.id} already registered`);
}
this.#apis.set(api, impl);
provides.add(api);
},
registerInit: registerOptions => {
if (registerInit) {
throw new Error('registerInit must only be called once');
}
registerInit = {
id: extension.id,
provides,
consumes: new Set(Object.values(registerOptions.deps)),
deps: registerOptions.deps,
init: registerOptions.init as BackendRegisterInit['init'],
};
},
});
if (!registerInit) {
throw new Error(
`registerInit was not called by register in ${extension.id}`,
);
}
this.#registerInits.push(registerInit);
}
this.validateSetup();
const orderedRegisterResults = this.#resolveInitOrder(this.#registerInits);
for (const registerInit of orderedRegisterResults) {
// TODO: DI
const deps = await this.#getInitDeps(registerInit.deps, registerInit.id);
await registerInit.init(deps);
// Maybe return stop? or lifecycle API
// this.#stops.push();
}
}
// async stop(): Promise<void> {
// for (const stop of this.#stops) {
// await stop.stop();
// }
// }
private validateSetup() {}
#resolveInitOrder(registerInits: Array<BackendRegisterInit>) {
let registerInitsToOrder = registerInits.slice();
const orderedRegisterInits = new Array<BackendRegisterInit>();
// TODO: Validate duplicates
while (registerInitsToOrder.length > 0) {
const toRemove = new Set<unknown>();
for (const registerInit of registerInitsToOrder) {
const unInitializedDependents = Array.from(
registerInit.provides,
// eslint-disable-next-line no-loop-func
).filter(r =>
registerInitsToOrder.some(
init => init !== registerInit && init.consumes.has(r),
),
);
if (unInitializedDependents.length === 0) {
orderedRegisterInits.push(registerInit);
toRemove.add(registerInit);
}
}
registerInitsToOrder = registerInitsToOrder.filter(r => !toRemove.has(r));
}
return orderedRegisterInits;
}
}
@@ -0,0 +1,44 @@
/*
* Copyright 2022 The Backstage Authors
*
* 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 {
BackendRegistrable,
AnyServiceFactory,
} from '@backstage/backend-plugin-api';
import { BackendInitializer } from './BackendInitializer';
import { CoreApiRegistry } from './CoreApiRegistry';
import { Backend } from './types';
export class BackstageBackend implements Backend {
#coreApis: CoreApiRegistry;
#initializer: BackendInitializer;
constructor(apiFactories: AnyServiceFactory[]) {
this.#coreApis = new CoreApiRegistry(apiFactories);
this.#initializer = new BackendInitializer(this.#coreApis);
}
add(extension: BackendRegistrable): void {
this.#initializer.add(extension);
}
async start(): Promise<void> {
await this.#initializer.start();
}
// async stop(): Promise<void> {
// await this.#initializer.stop();
// }
}
@@ -0,0 +1,65 @@
/*
* Copyright 2022 The Backstage Authors
*
* 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 {
AnyServiceFactory,
ServiceRef,
FactoryFunc,
} from '@backstage/backend-plugin-api';
export class CoreApiRegistry {
readonly #implementations: Map<string, Map<string, unknown>>;
readonly #factories: Map<string, AnyServiceFactory>;
constructor(factories: AnyServiceFactory[]) {
this.#factories = new Map(factories.map(f => [f.service.id, f]));
this.#implementations = new Map();
}
get<T>(ref: ServiceRef<T>): FactoryFunc<T> | undefined {
const factory = this.#factories.get(ref.id);
if (!factory) {
return undefined;
}
return async (pluginId: string): Promise<T> => {
if (this.#implementations.has(ref.id)) {
if (this.#implementations.get(ref.id)!.has(pluginId)) {
return this.#implementations.get(ref.id)!.get(pluginId) as T;
}
this.#implementations.set(ref.id, new Map<string, unknown>());
} else {
this.#implementations.set(ref.id, new Map());
}
const factoryDeps = Object.fromEntries(
Object.entries(factory.deps).map(([name, apiRef]) => [
name,
this.get(apiRef)!, // TODO: throw
]),
);
const factoryFunc = await factory.factory(factoryDeps);
const implementation = await factoryFunc(pluginId);
this.#implementations.set(
ref.id,
this.#implementations.get(ref.id)!.set(pluginId, implementation),
);
return implementation as T;
};
}
}
+23 -2
View File
@@ -14,14 +14,35 @@
* limitations under the License.
*/
export interface BackendApp {
add(registrable: BackendRegistrable): void;
import {
BackendRegistrable,
AnyServiceFactory,
ServiceRef,
FactoryFunc,
} from '@backstage/backend-plugin-api';
import { BackstageBackend } from './BackstageBackend';
export interface Backend {
add(extension: BackendRegistrable): void;
start(): Promise<void>;
}
export interface BackendRegisterInit {
id: string;
consumes: Set<ServiceRef<unknown>>;
provides: Set<ServiceRef<unknown>>;
deps: { [name: string]: ServiceRef<unknown> };
init: (deps: { [name: string]: unknown }) => Promise<void>;
}
interface CreateBackendOptions {
apis: AnyServiceFactory[];
}
export type ApiHolder = {
get<T>(api: ServiceRef<T>): FactoryFunc<T> | undefined;
};
export function createBackend(options?: CreateBackendOptions): Backend {
return new BackstageBackend(options?.apis ?? []);
}
+3 -1
View File
@@ -33,7 +33,9 @@
"clean": "backstage-cli package clean",
"start": "backstage-cli package start"
},
"dependencies": {},
"dependencies": {
"@backstage/config": "^1.0.1"
},
"devDependencies": {
"@backstage/cli": "^0.17.2-next.0"
},
+2
View File
@@ -21,3 +21,5 @@
*/
export * from './wiring';
export * from './services/system/types';
export * from './services/definitions';
@@ -0,0 +1,22 @@
/*
* Copyright 2022 The Backstage Authors
*
* 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 { Config } from '@backstage/config';
import { createServiceRef } from '../system/types';
export const configApiRef = createServiceRef<Config>({
id: 'core.config',
});
@@ -0,0 +1,25 @@
/*
* Copyright 2022 The Backstage Authors
*
* 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 { createServiceRef } from '../system/types';
export interface HttpRouterApi {
get(path: string): void;
}
export const httpRouterApiRef = createServiceRef<HttpRouterApi>({
id: 'core.httpRouter',
});
@@ -14,31 +14,6 @@
* limitations under the License.
*/
interface Logger {
log(message: string): void;
child(fields: { [name: string]: string }): Logger;
}
interface ConfigApi {
getString(key: string): string;
}
interface HttpRouterApi {
get(path: string): void;
}
export const loggerApiRef = createServiceRef<Logger>({
id: 'core.logger',
});
export const configApiRef = createServiceRef<ConfigApi>({
id: 'core.config',
});
export const httpRouterApiRef = createServiceRef<HttpRouterApi>({
id: 'core.apiRouter',
});
// export type PluginEnvironment = {
// logger: Logger;
// cache: PluginCacheManager;
@@ -50,3 +25,9 @@ export const httpRouterApiRef = createServiceRef<HttpRouterApi>({
// permissions: PermissionEvaluator | PermissionAuthorizer;
// scheduler: PluginTaskScheduler;
// };
export { configApiRef } from './configApiRef';
export { httpRouterApiRef } from './httpRouterApiRef';
export type { HttpRouterApi } from './httpRouterApiRef';
export { loggerApiRef } from './loggerApiRef';
export type { Logger } from './loggerApiRef';
@@ -0,0 +1,26 @@
/*
* Copyright 2022 The Backstage Authors
*
* 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 { createServiceRef } from '../system/types';
export interface Logger {
log(message: string): void;
child(fields: { [name: string]: string }): Logger;
}
export const loggerApiRef = createServiceRef<Logger>({
id: 'core.logger',
});
@@ -14,17 +14,56 @@
* limitations under the License.
*/
/**
* TODO
*
* @public
*/
export interface ServiceRef<T> {
id: string;
/**
* Utility for getting the type of the service, using `typeof serviceRef.T`.
* Attempting to actually read this value will result in an exception.
*/
T: T;
toString(): string;
$$ref: 'service';
}
type TypesToServiceRef<T> = { [key in keyof T]: ServiceRef<T[key]> };
type DepsToDepFactories<T> = {
[key in keyof T]: (pluginId: string) => Promise<T[key]>;
};
export type FactoryFunc<Impl> = (pluginId: string) => Promise<Impl>;
export type ServiceFactory<
TApi,
TImpl extends TApi,
TDeps extends { [name in string]: unknown },
> = {
service: ServiceRef<TApi>;
deps: TypesToServiceRef<TDeps>;
factory(deps: DepsToDepFactories<TDeps>): Promise<FactoryFunc<TImpl>>;
};
export type AnyServiceFactory = ServiceFactory<
unknown,
unknown,
{ [key in string]: unknown }
>;
export function createServiceRef<T>(options: { id: string }): ServiceRef<T> {
return {
id: options.id,
get T(): T {
throw Error('NO T');
throw new Error(`tried to read ServiceRef.T of ${this}`);
},
toString() {
return `serviceRef{${options.id}}`;
},
$$ref: 'service', // TODO: declare
};
@@ -14,4 +14,5 @@
* limitations under the License.
*/
export { BackendRegistrable } from './types';
export type { BackendRegistrable } from './types';
export * from './types';
@@ -14,9 +14,25 @@
* limitations under the License.
*/
import { ServiceRef } from '../services/system/types';
/**
* TODO
*
* @public
*/
export interface ExtensionPoint<T> {
id: string;
/**
* Utility for getting the type of the extension point, using `typeof
* extensionPoint.T`. Attempting to actually read this value will result in an
* exception.
*/
T: T;
toString(): string;
$$ref: 'extension-point';
}
@@ -26,7 +42,10 @@ export function createExtensionPoint<T>(options: {
return {
id: options.id,
get T(): T {
throw Error('NO T');
throw new Error(`tried to read ExtensionPoint.T of ${this}`);
},
toString() {
return `extensionPoint{${options.id}}`;
},
$$ref: 'extension-point', // TODO: declare
};
+2
View File
@@ -26,6 +26,8 @@
"build-image": "docker build ../.. -f Dockerfile --tag example-backend"
},
"dependencies": {
"@backstage/backend-plugin-api": "^0.0.0",
"@backstage/backend-app-api": "^0.0.0",
"@backstage/backend-common": "^0.14.1-next.2",
"@backstage/backend-tasks": "^0.3.3-next.2",
"@backstage/catalog-client": "^1.0.4-next.1",
+100
View File
@@ -0,0 +1,100 @@
/*
* Copyright 2022 The Backstage Authors
*
* 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 { createBackend } from '@backstage/backend-app-api';
import {
createBackendModule,
createBackendPlugin,
createServiceRef,
} from '@backstage/backend-plugin-api';
// import { catalogPlugin } from '@backstage/plugin-catalog-backend';
// import { scaffolderPlugin } from '@backstage/plugin-scaffolder-backend';
interface CatalogProcessor {
process(): void;
}
interface CatalogProcessingInitApi {
addProcessor(processor: CatalogProcessor): void;
}
export const catalogProcessingInitApiRef =
createServiceRef<CatalogProcessingInitApi>({
id: 'catalog.processing',
});
class CatalogExtensionPointImpl implements CatalogProcessingInitApi {
#processors = new Array<CatalogProcessor>();
addProcessor(processor: CatalogProcessor): void {
this.#processors.push(processor);
}
get processors() {
return this.#processors;
}
}
export const catalogPlugin = createBackendPlugin({
id: 'catalog',
register(env) {
const processingExtensions = new CatalogExtensionPointImpl();
// plugins depending on this API will be initialized before this plugins init method is executed.
env.registerExtensionPoint(
catalogProcessingInitApiRef,
processingExtensions,
);
env.registerInit({
deps: {
// logger: loggerApiRef,
},
async init() {
console.log('I HAZ', processingExtensions.processors[0].process());
console.log('I AM le CATALOG!');
// logger.log('HELLO!');
},
});
},
});
export const scaffolderCatalogExtension = createBackendModule({
moduleId: 'boop',
pluginId: 'catalog',
register(env) {
env.registerInit({
deps: {
catalogProcessingInitApi: catalogProcessingInitApiRef,
},
async init({ catalogProcessingInitApi }) {
catalogProcessingInitApi.addProcessor({
process() {
console.log('Running scaffolder processor');
},
});
},
});
},
});
const backend = createBackend({
apis: [],
});
// backend.add(scaffolderPlugin());
backend.add(catalogPlugin({}));
backend.add(scaffolderCatalogExtension({}));
backend.start();
+145 -1
View File
@@ -1557,6 +1557,126 @@
lodash "^4.17.21"
uuid "^8.0.0"
"@backstage/cli@^0.17.2-next.0":
version "0.17.2"
resolved "https://registry.npmjs.org/@backstage/cli/-/cli-0.17.2.tgz#2387b8d24d8af4828b84baaa62e6b444ec4330e6"
integrity sha512-stRJWmokD7SXnclZ1dsVfA1stUP4PQPkbi3GkwY1zM84y4M20dU+YHde7MrTILMPnhMY+16WdTdfbeqLfXOJrw==
dependencies:
"@backstage/cli-common" "^0.1.9"
"@backstage/config" "^1.0.1"
"@backstage/config-loader" "^1.1.2"
"@backstage/errors" "^1.0.0"
"@backstage/release-manifests" "^0.0.4"
"@backstage/types" "^1.0.0"
"@hot-loader/react-dom-v16" "npm:@hot-loader/react-dom@^16.0.2"
"@hot-loader/react-dom-v17" "npm:@hot-loader/react-dom@^17.0.2"
"@manypkg/get-packages" "^1.1.3"
"@octokit/request" "^5.4.12"
"@rollup/plugin-commonjs" "^22.0.0"
"@rollup/plugin-json" "^4.1.0"
"@rollup/plugin-node-resolve" "^13.0.0"
"@rollup/plugin-yaml" "^3.1.0"
"@spotify/eslint-config-base" "^13.0.0"
"@spotify/eslint-config-react" "^13.0.0"
"@spotify/eslint-config-typescript" "^13.0.0"
"@sucrase/jest-plugin" "^2.1.1"
"@sucrase/webpack-loader" "^2.0.0"
"@svgr/plugin-jsx" "6.2.x"
"@svgr/plugin-svgo" "6.2.x"
"@svgr/rollup" "6.2.x"
"@svgr/webpack" "6.2.x"
"@types/webpack-env" "^1.15.2"
"@typescript-eslint/eslint-plugin" "^5.9.0"
"@typescript-eslint/parser" "^5.9.0"
"@yarnpkg/lockfile" "^1.1.0"
"@yarnpkg/parsers" "^3.0.0-rc.4"
bfj "^7.0.2"
buffer "^6.0.3"
chalk "^4.0.0"
chokidar "^3.3.1"
commander "^9.1.0"
css-loader "^6.5.1"
diff "^5.0.0"
esbuild "^0.14.10"
esbuild-loader "^2.18.0"
eslint "^8.6.0"
eslint-config-prettier "^8.3.0"
eslint-formatter-friendly "^7.0.0"
eslint-plugin-deprecation "^1.3.2"
eslint-plugin-import "^2.25.4"
eslint-plugin-jest "^26.1.2"
eslint-plugin-jsx-a11y "^6.5.1"
eslint-plugin-monorepo "^0.3.2"
eslint-plugin-react "^7.28.0"
eslint-plugin-react-hooks "^4.3.0"
eslint-webpack-plugin "^3.1.1"
express "^4.17.1"
fork-ts-checker-webpack-plugin "^7.0.0-alpha.8"
fs-extra "10.1.0"
glob "^7.1.7"
global-agent "^3.0.0"
handlebars "^4.7.3"
html-webpack-plugin "^5.3.1"
inquirer "^8.2.0"
jest "^27.5.1"
jest-css-modules "^2.1.0"
jest-runtime "^27.5.1"
jest-transform-yaml "^1.0.0"
json-schema "^0.4.0"
lodash "^4.17.21"
mini-css-extract-plugin "^2.4.2"
minimatch "5.1.0"
node-fetch "^2.6.7"
node-libs-browser "^2.2.1"
npm-packlist "^5.0.0"
ora "^5.3.0"
postcss "^8.1.0"
process "^0.11.10"
react-dev-utils "^12.0.0-next.60"
react-hot-loader "^4.13.0"
recursive-readdir "^2.2.2"
replace-in-file "^6.0.0"
rollup "^2.60.2"
rollup-plugin-dts "^4.0.1"
rollup-plugin-esbuild "^4.7.2"
rollup-plugin-postcss "^4.0.0"
rollup-pluginutils "^2.8.2"
run-script-webpack-plugin "^0.0.14"
semver "^7.3.2"
style-loader "^3.3.1"
sucrase "^3.20.2"
tar "^6.1.2"
terser-webpack-plugin "^5.1.3"
util "^0.12.3"
webpack "^5.66.0"
webpack-dev-server "^4.7.3"
webpack-node-externals "^3.0.0"
yaml "^1.10.0"
yml-loader "^2.1.0"
yn "^4.0.0"
zod "^3.11.6"
"@backstage/config-loader@^1.1.2":
version "1.1.2"
resolved "https://registry.npmjs.org/@backstage/config-loader/-/config-loader-1.1.2.tgz#72cb0d7b2647f5a646bb279360bc34732e06521f"
integrity sha512-c5ZO7xDJn609DBIsYAWGE5kgh+7SPYUmG2ADtVX9SbXaql3VCafGlhc2hAZQa/O12W04qi3GgwGg0bqSFmx5uw==
dependencies:
"@backstage/cli-common" "^0.1.9"
"@backstage/config" "^1.0.1"
"@backstage/errors" "^1.0.0"
"@backstage/types" "^1.0.0"
"@types/json-schema" "^7.0.6"
ajv "^8.10.0"
chokidar "^3.5.2"
fs-extra "10.1.0"
json-schema "^0.4.0"
json-schema-merge-allof "^0.8.1"
json-schema-traverse "^1.0.0"
node-fetch "^2.6.7"
typescript-json-schema "^0.53.0"
yaml "^1.9.2"
yup "^0.32.9"
"@backstage/core-components@^0.9.0", "@backstage/core-components@^0.9.5":
version "0.9.5"
resolved "https://registry.npmjs.org/@backstage/core-components/-/core-components-0.9.5.tgz#5a0b34867aaee0549bfa67b39a69c09588fa3c7a"
@@ -5555,7 +5675,7 @@
dependencies:
"@rollup/pluginutils" "^3.0.8"
"@rollup/plugin-node-resolve@^13.0.6":
"@rollup/plugin-node-resolve@^13.0.0", "@rollup/plugin-node-resolve@^13.0.6":
version "13.3.0"
resolved "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.3.0.tgz#da1c5c5ce8316cef96a2f823d111c1e4e498801c"
integrity sha512-Lus8rbUo1eEcnS4yTFKLZrVumLPY+YayBdWXgFSHYhTT2iJbMhoaaBL3xl5NCdeRytErGr8tZ0L71BMRmnlwSw==
@@ -20504,6 +20624,11 @@ path-case@^3.0.4:
dot-case "^3.0.4"
tslib "^2.0.3"
path-equal@1.1.2:
version "1.1.2"
resolved "https://registry.npmjs.org/path-equal/-/path-equal-1.1.2.tgz#260e7c449c4c2022f68cc5fa6e617e892858250d"
integrity sha512-p5kxPPwCdbf5AdXzT1bUBJomhgBlEjRBavYNr1XUpMFIE4Hnf2roueCMXudZK5tnaAu1tTmp3GPzqwJK45IHEA==
path-equal@^1.1.2:
version "1.2.2"
resolved "https://registry.npmjs.org/path-equal/-/path-equal-1.2.2.tgz#fa2997f0a829de22ec8f5f86461ca5590d49b832"
@@ -23028,6 +23153,11 @@ run-parallel@^1.1.9:
resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679"
integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==
run-script-webpack-plugin@^0.0.14:
version "0.0.14"
resolved "https://registry.npmjs.org/run-script-webpack-plugin/-/run-script-webpack-plugin-0.0.14.tgz#fe2362b32c1dab7a8af7a6f1246fc043690cedd7"
integrity sha512-DXe6lzzEVXjBr/74zd4m4yOfmz5P6GMjzhQxDDsViOmwG7cap8UCE6RgD5rT7zf4wM83a+ToHnpB3v4efUv5IA==
run-script-webpack-plugin@^0.1.0:
version "0.1.1"
resolved "https://registry.npmjs.org/run-script-webpack-plugin/-/run-script-webpack-plugin-0.1.1.tgz#dad3114be32eb864d2160306e4d9c52a2c1cfd59"
@@ -25311,6 +25441,20 @@ typedarray@^0.0.6:
resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
typescript-json-schema@^0.53.0:
version "0.53.1"
resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.53.1.tgz#9204547f3e145169b40928998366ff6d28b81d32"
integrity sha512-Hg+RnOKUd38MOzC0rDft03a8xvwO+gCcj1F77smw2tCoZYQpFoLtrXWBGdvCX+REliko5WYel2kux17HPFqjLQ==
dependencies:
"@types/json-schema" "^7.0.9"
"@types/node" "^16.9.2"
glob "^7.1.7"
path-equal "1.1.2"
safe-stable-stringify "^2.2.0"
ts-node "^10.2.1"
typescript "~4.6.0"
yargs "^17.1.1"
typescript-json-schema@^0.54.0:
version "0.54.0"
resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.54.0.tgz#b3fc42ad90df6a0f6ab57571ebc8b4d41125df4f"