From 73a752ff4f1767fc00f4119c749475dd7219130f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 10 Sep 2021 17:53:13 +0200 Subject: [PATCH] core-app-api: switch to using version-bridge Signed-off-by: Patrik Oldsberg --- packages/core-app-api/package.json | 1 + .../src/apis/system/ApiProvider.test.tsx | 3 +- .../src/apis/system/ApiProvider.tsx | 4 +- .../core-app-api/src/app/AppContext.test.tsx | 3 +- packages/core-app-api/src/app/AppContext.tsx | 4 +- .../core-app-api/src/lib/globalObject.test.ts | 90 ------------------- packages/core-app-api/src/lib/globalObject.ts | 73 --------------- .../src/lib/versionedValues.test.ts | 40 --------- .../core-app-api/src/lib/versionedValues.ts | 40 --------- .../src/routing/RoutingProvider.test.tsx | 3 +- .../src/routing/RoutingProvider.tsx | 6 +- packages/core-app-api/src/routing/types.ts | 2 +- 12 files changed, 12 insertions(+), 257 deletions(-) delete mode 100644 packages/core-app-api/src/lib/globalObject.test.ts delete mode 100644 packages/core-app-api/src/lib/globalObject.ts delete mode 100644 packages/core-app-api/src/lib/versionedValues.test.ts delete mode 100644 packages/core-app-api/src/lib/versionedValues.ts diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index 5223d2b27e..790b1e29fb 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -33,6 +33,7 @@ "@backstage/config": "^0.1.9", "@backstage/core-plugin-api": "^0.1.7", "@backstage/theme": "^0.2.10", + "@backstage/version-bridge": "^0.1.0", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@types/react": "*", diff --git a/packages/core-app-api/src/apis/system/ApiProvider.test.tsx b/packages/core-app-api/src/apis/system/ApiProvider.test.tsx index b94aea6b67..c80b0c117f 100644 --- a/packages/core-app-api/src/apis/system/ApiProvider.test.tsx +++ b/packages/core-app-api/src/apis/system/ApiProvider.test.tsx @@ -26,8 +26,7 @@ import { ApiProvider } from './ApiProvider'; import { ApiRegistry } from './ApiRegistry'; import { render } from '@testing-library/react'; import { withLogCollector } from '@backstage/test-utils-core'; -import { getGlobalSingleton } from '../../lib/globalObject'; -import { VersionedValue } from '../../lib/versionedValues'; +import { getGlobalSingleton, VersionedValue } from '@backstage/version-bridge'; describe('ApiProvider', () => { type Api = () => string; diff --git a/packages/core-app-api/src/apis/system/ApiProvider.tsx b/packages/core-app-api/src/apis/system/ApiProvider.tsx index ce6c388087..bffb9986c7 100644 --- a/packages/core-app-api/src/apis/system/ApiProvider.tsx +++ b/packages/core-app-api/src/apis/system/ApiProvider.tsx @@ -23,11 +23,11 @@ import React, { import PropTypes from 'prop-types'; import { ApiHolder } from '@backstage/core-plugin-api'; import { ApiAggregator } from './ApiAggregator'; -import { getOrCreateGlobalSingleton } from '../../lib/globalObject'; import { VersionedValue, createVersionedValueMap, -} from '../../lib/versionedValues'; + getOrCreateGlobalSingleton, +} from '@backstage/version-bridge'; type ApiProviderProps = { apis: ApiHolder; diff --git a/packages/core-app-api/src/app/AppContext.test.tsx b/packages/core-app-api/src/app/AppContext.test.tsx index 6ce164b9f0..3397eb4620 100644 --- a/packages/core-app-api/src/app/AppContext.test.tsx +++ b/packages/core-app-api/src/app/AppContext.test.tsx @@ -16,8 +16,7 @@ import React, { useContext, Context } from 'react'; import { renderHook } from '@testing-library/react-hooks'; -import { VersionedValue } from '../lib/versionedValues'; -import { getGlobalSingleton } from '../lib/globalObject'; +import { getGlobalSingleton, VersionedValue } from '@backstage/version-bridge'; import { AppContext as AppContextV1 } from './types'; import { AppContextProvider } from './AppContext'; diff --git a/packages/core-app-api/src/app/AppContext.tsx b/packages/core-app-api/src/app/AppContext.tsx index c583478ec2..640d814da0 100644 --- a/packages/core-app-api/src/app/AppContext.tsx +++ b/packages/core-app-api/src/app/AppContext.tsx @@ -18,8 +18,8 @@ import React, { createContext, PropsWithChildren } from 'react'; import { VersionedValue, createVersionedValueMap, -} from '../lib/versionedValues'; -import { getOrCreateGlobalSingleton } from '../lib/globalObject'; + getOrCreateGlobalSingleton, +} from '@backstage/version-bridge'; import { AppContext as AppContextV1 } from './types'; type AppContextType = VersionedValue<{ 1: AppContextV1 }> | undefined; diff --git a/packages/core-app-api/src/lib/globalObject.test.ts b/packages/core-app-api/src/lib/globalObject.test.ts deleted file mode 100644 index a658b253a6..0000000000 --- a/packages/core-app-api/src/lib/globalObject.test.ts +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2021 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 { - getGlobalSingleton, - getOrCreateGlobalSingleton, - setGlobalSingleton, -} from './globalObject'; - -const anyGlobal = global as any; - -describe('getGlobalSingleton', () => { - beforeEach(() => { - delete anyGlobal['__@backstage/my-thing__']; - }); - - it('should return an existing value', () => { - const myThing = {}; - const myOtherThing = {}; - - anyGlobal['__@backstage/my-thing__'] = myThing; - expect(getGlobalSingleton('my-thing')).toBe(myThing); - expect(getGlobalSingleton('my-thing')).toBe(myThing); - anyGlobal['__@backstage/my-thing__'] = myOtherThing; - expect(getGlobalSingleton('my-thing')).toBe(myOtherThing); - }); - - it('should throw if the value is not set', () => { - expect(() => getGlobalSingleton('my-thing')).toThrow( - 'Global my-thing is not set', - ); - }); -}); - -describe('getOrCreateGlobalSingleton', () => { - beforeEach(() => { - delete anyGlobal['__@backstage/my-thing__']; - }); - - it('should return an existing value', () => { - const myThing = {}; - anyGlobal['__@backstage/my-thing__'] = myThing; - - expect(getOrCreateGlobalSingleton('my-thing', () => ({}))).toBe(myThing); - expect(getOrCreateGlobalSingleton('my-thing', () => ({}))).toBe(myThing); - }); - - it('should should create a new value', () => { - const myNewThing = {}; - - expect(anyGlobal['__@backstage/my-thing__']).toBe(undefined); - expect(getOrCreateGlobalSingleton('my-thing', () => myNewThing)).toBe( - myNewThing, - ); - expect(anyGlobal['__@backstage/my-thing__']).toBe(myNewThing); - expect(getOrCreateGlobalSingleton('my-thing', () => ({}))).toBe(myNewThing); - }); -}); - -describe('setGlobalSingleton', () => { - beforeEach(() => { - delete anyGlobal['__@backstage/my-thing__']; - }); - - it('should set a global value', () => { - setGlobalSingleton('my-thing', 'global value'); - - expect(anyGlobal['__@backstage/my-thing__']).toBe('global value'); - }); - - it('should throw if global value is set', () => { - anyGlobal['__@backstage/my-thing__'] = 'already defined'; - expect(() => setGlobalSingleton('my-thing', () => 'global value')).toThrow( - 'Global my-thing is already se', - ); - }); -}); diff --git a/packages/core-app-api/src/lib/globalObject.ts b/packages/core-app-api/src/lib/globalObject.ts deleted file mode 100644 index ad70a61110..0000000000 --- a/packages/core-app-api/src/lib/globalObject.ts +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2021 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. - */ - -// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 -function getGlobalObject() { - if (typeof window !== 'undefined' && window.Math === Math) { - return window; - } - if (typeof self !== 'undefined' && self.Math === Math) { - return self; - } - // eslint-disable-next-line no-new-func - return Function('return this')(); -} - -const globalObject = getGlobalObject(); - -const makeKey = (id: string) => `__@backstage/${id}__`; - -/** - * Used to provide a global singleton value, failing if it is already set. - */ -export function setGlobalSingleton(id: string, value: unknown): void { - const key = makeKey(id); - if (key in globalObject) { - throw new Error(`Global ${id} is already set`); // TODO some sort of special build err - } - globalObject[key] = value; -} - -/** - * Used to access a global singleton value, failing if it is not already set. - */ -export function getGlobalSingleton(id: string): T { - const key = makeKey(id); - if (!(key in globalObject)) { - throw new Error(`Global ${id} is not set`); // TODO some sort of special build err - } - - return globalObject[key]; -} - -/** - * Serializes access to a global singleton value, with the first caller creating the value. - */ -export function getOrCreateGlobalSingleton( - id: string, - supplier: () => T, -): T { - const key = makeKey(id); - - let value = globalObject[key]; - if (value) { - return value; - } - - value = supplier(); - globalObject[key] = value; - return value; -} diff --git a/packages/core-app-api/src/lib/versionedValues.test.ts b/packages/core-app-api/src/lib/versionedValues.test.ts deleted file mode 100644 index 19f9c8f349..0000000000 --- a/packages/core-app-api/src/lib/versionedValues.test.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2021 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 { createVersionedValueMap } from './versionedValues'; - -describe('createVersionedValueMap', () => { - it('should be empty', () => { - const map = createVersionedValueMap({}); - - // @ts-expect-error - expect(map.atVersion(1 as any)).toBe(undefined); - }); - - it('should access values by version', () => { - const map = createVersionedValueMap({ 1: 'v1', 2: 'v2' }); - - expect(map.atVersion(1)).toBe('v1'); - expect(map.atVersion(2)).toBe('v2'); - - // @ts-expect-error - expect(map.atVersion(0)).toBe(undefined); - // @ts-expect-error - expect(map.atVersion(NaN)).toBe(undefined); - // @ts-expect-error - expect(map.atVersion(Infinity)).toBe(undefined); - }); -}); diff --git a/packages/core-app-api/src/lib/versionedValues.ts b/packages/core-app-api/src/lib/versionedValues.ts deleted file mode 100644 index 3b3064fc7e..0000000000 --- a/packages/core-app-api/src/lib/versionedValues.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2021 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. - */ - -/** - * The versioned value interface is a container for a set of values that - * can be looked up by version. It is intended to be used as a container - * for values that can be versioned independently of package versions. - */ -export type VersionedValue = { - atVersion( - version: Version, - ): Versions[Version] | undefined; -}; - -/** - * Creates a container for a map of versioned values that implements VersionedValue. - */ -export function createVersionedValueMap< - Versions extends { [version: number]: any }, ->(versions: Versions): VersionedValue { - Object.freeze(versions); - return { - atVersion(version) { - return versions[version]; - }, - }; -} diff --git a/packages/core-app-api/src/routing/RoutingProvider.test.tsx b/packages/core-app-api/src/routing/RoutingProvider.test.tsx index 47f9c87c96..bf6d06aaf7 100644 --- a/packages/core-app-api/src/routing/RoutingProvider.test.tsx +++ b/packages/core-app-api/src/routing/RoutingProvider.test.tsx @@ -23,8 +23,7 @@ import React, { import { MemoryRouter, Routes } from 'react-router-dom'; import { render } from '@testing-library/react'; import { renderHook } from '@testing-library/react-hooks'; -import { VersionedValue } from '../lib/versionedValues'; -import { getGlobalSingleton } from '../lib/globalObject'; +import { VersionedValue, getGlobalSingleton } from '@backstage/version-bridge'; import { childDiscoverer, routeElementDiscoverer, diff --git a/packages/core-app-api/src/routing/RoutingProvider.tsx b/packages/core-app-api/src/routing/RoutingProvider.tsx index 2192f5df26..b2aaf3df3b 100644 --- a/packages/core-app-api/src/routing/RoutingProvider.tsx +++ b/packages/core-app-api/src/routing/RoutingProvider.tsx @@ -20,11 +20,11 @@ import { RouteRef, SubRouteRef, } from '@backstage/core-plugin-api'; -import { getOrCreateGlobalSingleton } from '../lib/globalObject'; import { - createVersionedValueMap, VersionedValue, -} from '../lib/versionedValues'; + createVersionedValueMap, + getOrCreateGlobalSingleton, +} from '@backstage/version-bridge'; import { RouteResolver } from './RouteResolver'; import { BackstageRouteObject } from './types'; diff --git a/packages/core-app-api/src/routing/types.ts b/packages/core-app-api/src/routing/types.ts index a12e914aba..12bf0d1a0f 100644 --- a/packages/core-app-api/src/routing/types.ts +++ b/packages/core-app-api/src/routing/types.ts @@ -19,7 +19,7 @@ import { SubRouteRef, ExternalRouteRef, } from '@backstage/core-plugin-api'; -import { getOrCreateGlobalSingleton } from '../lib/globalObject'; +import { getOrCreateGlobalSingleton } from '@backstage/version-bridge'; type RouteRefType = Exclude< keyof RouteRef,