Merge pull request #4725 from backstage/rugvip/globocon
core-api: new internal utility for accessing global singletons
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import { ComponentType, ReactNode } from 'react';
|
||||
import { globalObject } from '../lib/globalObject';
|
||||
import { getGlobalSingleton } from '../lib/globalObject';
|
||||
|
||||
// TODO(Rugvip): Access via symbol is deprecated, remove once on 0.3.x
|
||||
const DATA_KEY = Symbol('backstage-component-data');
|
||||
@@ -32,22 +32,10 @@ type MaybeComponentNode = ReactNode & {
|
||||
type?: ComponentType<any> & { [DATA_KEY]?: DataContainer };
|
||||
};
|
||||
|
||||
const GLOBAL_KEY = '__@backstage/component-data-store__';
|
||||
|
||||
// The store is bridged across versions using the global object
|
||||
function getStore() {
|
||||
let storeObj = globalObject[GLOBAL_KEY] as
|
||||
| { store: WeakMap<ComponentType<any>, DataContainer> }
|
||||
| undefined;
|
||||
if (!storeObj) {
|
||||
const store = new WeakMap<ComponentType<any>, DataContainer>();
|
||||
storeObj = { store };
|
||||
globalObject[GLOBAL_KEY] = storeObj;
|
||||
}
|
||||
return storeObj.store;
|
||||
}
|
||||
|
||||
const store = getStore();
|
||||
const { store } = getGlobalSingleton('component-data-store', () => ({
|
||||
store: new WeakMap<ComponentType<any>, DataContainer>(),
|
||||
}));
|
||||
|
||||
export function attachComponentData<P>(
|
||||
component: ComponentType<P>,
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2021 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 { getGlobalSingleton } from './globalObject';
|
||||
|
||||
const anyGlobal = global as any;
|
||||
|
||||
describe('getGlobalSingleton', () => {
|
||||
beforeEach(() => {
|
||||
delete anyGlobal['__@backstage/my-thing__'];
|
||||
});
|
||||
|
||||
it('should return an existing value', () => {
|
||||
const myThing = {};
|
||||
anyGlobal['__@backstage/my-thing__'] = myThing;
|
||||
|
||||
expect(getGlobalSingleton('my-thing', () => ({}))).toBe(myThing);
|
||||
expect(getGlobalSingleton('my-thing', () => ({}))).toBe(myThing);
|
||||
});
|
||||
|
||||
it('should should create a new value', () => {
|
||||
const myNewThing = {};
|
||||
|
||||
expect(anyGlobal['__@backstage/my-thing__']).toBe(undefined);
|
||||
expect(getGlobalSingleton('my-thing', () => myNewThing)).toBe(myNewThing);
|
||||
expect(anyGlobal['__@backstage/my-thing__']).toBe(myNewThing);
|
||||
expect(getGlobalSingleton('my-thing', () => ({}))).toBe(myNewThing);
|
||||
});
|
||||
});
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
|
||||
function getGlobal() {
|
||||
function getGlobalObject() {
|
||||
if (typeof window !== 'undefined' && window.Math === Math) {
|
||||
return window;
|
||||
}
|
||||
@@ -26,4 +26,17 @@ function getGlobal() {
|
||||
return Function('return this')();
|
||||
}
|
||||
|
||||
export const globalObject = getGlobal();
|
||||
export const globalObject = getGlobalObject();
|
||||
|
||||
export function getGlobalSingleton<T>(id: string, supplier: () => T): T {
|
||||
const key = `__@backstage/${id}__`;
|
||||
|
||||
let value = globalObject[key];
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
value = supplier();
|
||||
globalObject[key] = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user