core-plugin-api: Remove deprecated get method from StorageApi

Signed-off-by: Johan Haals <johan.haals@gmail.com>
This commit is contained in:
Johan Haals
2022-03-01 09:28:50 +01:00
parent 2638cd044c
commit bb2bb36651
14 changed files with 60 additions and 95 deletions
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/core-app-api': minor
'@backstage/core-plugin-api': minor
'@backstage/test-utils': minor
---
**BREAKING**: Removed the deprecated `get` method from `StorageAPI` and its implementations, this method has been replaced by the `snapshot` method. The return value from snapshot no longer includes `newValue` which has been replaced by `value`. For getting notified when a value changes, use `observe$`.
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/core-components': patch
'@backstage/plugin-catalog-react': patch
---
Updated usage of `StorageApi` to use `snapshot` method instead of `get`
@@ -33,12 +33,11 @@ describe('WebStorage Storage API', () => {
it('should return undefined for values which are unset', async () => {
const storage = createWebStorage();
expect(storage.get('myfakekey')).toBeUndefined();
expect(storage.snapshot('myfakekey').value).toBeUndefined();
expect(storage.snapshot('myfakekey')).toEqual({
key: 'myfakekey',
presence: 'absent',
value: undefined,
newValue: undefined,
});
});
@@ -48,26 +47,23 @@ describe('WebStorage Storage API', () => {
await storage.set('myfakekey', 'helloimastring');
await storage.set('mysecondfakekey', 1234);
await storage.set('mythirdfakekey', true);
expect(storage.get('myfakekey')).toBe('helloimastring');
expect(storage.get('mysecondfakekey')).toBe(1234);
expect(storage.get('mythirdfakekey')).toBe(true);
expect(storage.snapshot('myfakekey').value).toBe('helloimastring');
expect(storage.snapshot('mysecondfakekey').value).toBe(1234);
expect(storage.snapshot('mythirdfakekey').value).toBe(true);
expect(storage.snapshot('myfakekey')).toEqual({
key: 'myfakekey',
presence: 'present',
value: 'helloimastring',
newValue: 'helloimastring',
});
expect(storage.snapshot('mysecondfakekey')).toEqual({
key: 'mysecondfakekey',
presence: 'present',
value: 1234,
newValue: 1234,
});
expect(storage.snapshot('mythirdfakekey')).toEqual({
key: 'mythirdfakekey',
presence: 'present',
value: true,
newValue: true,
});
});
@@ -81,12 +77,11 @@ describe('WebStorage Storage API', () => {
await storage.set('myfakekey', mockData);
expect(storage.get('myfakekey')).toEqual(mockData);
expect(storage.snapshot('myfakekey').value).toEqual(mockData);
expect(storage.snapshot('myfakekey')).toEqual({
key: 'myfakekey',
presence: 'present',
value: mockData,
newValue: mockData,
});
});
@@ -118,7 +113,6 @@ describe('WebStorage Storage API', () => {
key: 'correctKey',
presence: 'present',
value: mockData,
newValue: mockData,
});
});
@@ -152,7 +146,6 @@ describe('WebStorage Storage API', () => {
key: 'correctKey',
presence: 'absent',
value: undefined,
newValue: undefined,
});
});
@@ -166,9 +159,11 @@ describe('WebStorage Storage API', () => {
await firstStorage.set(keyName, 'boop');
await secondStorage.set(keyName, 'deerp');
expect(firstStorage.get(keyName)).not.toBe(secondStorage.get(keyName));
expect(firstStorage.get(keyName)).toBe('boop');
expect(secondStorage.get(keyName)).toBe('deerp');
expect(firstStorage.snapshot(keyName)).not.toBe(
secondStorage.snapshot(keyName),
);
expect(firstStorage.snapshot(keyName).value).toBe('boop');
expect(secondStorage.snapshot(keyName).value).toBe('deerp');
expect(firstStorage.snapshot(keyName)).not.toEqual(
secondStorage.snapshot(keyName),
);
@@ -176,13 +171,11 @@ describe('WebStorage Storage API', () => {
key: keyName,
presence: 'present',
value: 'boop',
newValue: 'boop',
});
expect(secondStorage.snapshot(keyName)).toEqual({
key: keyName,
presence: 'present',
value: 'deerp',
newValue: 'deerp',
});
});
@@ -217,7 +210,6 @@ describe('WebStorage Storage API', () => {
key: 'key',
presence: 'absent',
value: undefined,
newValue: undefined,
});
expect(mockErrorApi.post).toHaveBeenCalledWith(expect.any(Error));
expect(mockErrorApi.post).toHaveBeenCalledWith(
@@ -65,7 +65,7 @@ export class WebStorage implements StorageApi {
new Error(`Error when parsing JSON config from storage for: ${key}`),
);
}
return { key, value, newValue: value, presence };
return { key, value, presence };
}
forBucket(name: string): WebStorage {
@@ -75,7 +75,7 @@ describe('<DismissableBanner />', () => {
);
fireEvent.click(button);
const dismissedBanners =
notifications?.get<string[]>('dismissedBanners') ?? [];
notifications?.snapshot<string[]>('dismissedBanners').value ?? [];
expect(
dismissedBanners.includes('catalog_page_welcome_banner'),
).toBeTruthy();
@@ -101,7 +101,7 @@ export const DismissableBanner = (props: Props) => {
const storageApi = useApi(storageApiRef);
const notificationsStore = storageApi.forBucket('notifications');
const rawDismissedBanners =
notificationsStore.get<string[]>('dismissedBanners') ?? [];
notificationsStore.snapshot<string[]>('dismissedBanners').value ?? [];
const [dismissedBanners, setDismissedBanners] = useState(
new Set(rawDismissedBanners),
@@ -112,11 +112,11 @@ export const DismissableBanner = (props: Props) => {
);
useEffect(() => {
if (observedItems?.newValue) {
const currentValue = observedItems?.newValue ?? [];
if (observedItems?.value) {
const currentValue = observedItems?.value ?? [];
setDismissedBanners(new Set(currentValue));
}
}, [observedItems?.newValue]);
}, [observedItems?.value]);
const handleClick = () => {
notificationsStore.set('dismissedBanners', [...dismissedBanners, id]);
-8
View File
@@ -678,8 +678,6 @@ export type SignInPageProps = {
// @public
export interface StorageApi {
forBucket(name: string): StorageApi;
// @deprecated
get<T extends JsonValue>(key: string): T | undefined;
observe$<T extends JsonValue>(
key: string,
): Observable<StorageValueSnapshot<T>>;
@@ -691,23 +689,17 @@ export interface StorageApi {
// @public
export const storageApiRef: ApiRef<StorageApi>;
// @public @deprecated (undocumented)
export type StorageValueChange<TValue extends JsonValue> =
StorageValueSnapshot<TValue>;
// @public
export type StorageValueSnapshot<TValue extends JsonValue> =
| {
key: string;
presence: 'unknown' | 'absent';
value?: undefined;
newValue?: undefined;
}
| {
key: string;
presence: 'present';
value: TValue;
newValue?: TValue;
};
// @public
@@ -27,24 +27,13 @@ export type StorageValueSnapshot<TValue extends JsonValue> =
key: string;
presence: 'unknown' | 'absent';
value?: undefined;
/** @deprecated Use `value` instead */
newValue?: undefined;
}
| {
key: string;
presence: 'present';
value: TValue;
/** @deprecated Use `value` instead */
newValue?: TValue;
};
/**
* @public
* @deprecated Use StorageValueSnapshot instead
*/
export type StorageValueChange<TValue extends JsonValue> =
StorageValueSnapshot<TValue>;
/**
* Provides a key-value persistence API.
*
@@ -59,14 +48,6 @@ export interface StorageApi {
*/
forBucket(name: string): StorageApi;
/**
* Get the current value for persistent data, use observe$ to be notified of updates.
*
* @deprecated Use `snapshot` instead.
* @param key - Unique key associated with the data.
*/
get<T extends JsonValue>(key: string): T | undefined;
/**
* Remove persistent data.
*
-2
View File
@@ -164,8 +164,6 @@ export class MockStorageApi implements StorageApi {
// (undocumented)
forBucket(name: string): StorageApi;
// (undocumented)
get<T>(key: string): T | undefined;
// (undocumented)
observe$<T>(key: string): Observable<StorageValueSnapshot<T>>;
// (undocumented)
remove(key: string): Promise<void>;
@@ -24,7 +24,7 @@ describe('WebStorage Storage API', () => {
it('should return undefined for values which are unset', async () => {
const storage = createMockStorage();
expect(storage.get('myfakekey')).toBeUndefined();
expect(storage.snapshot('myfakekey').value).toBeUndefined();
expect(storage.snapshot('myfakekey')).toEqual({
key: 'myfakekey',
presence: 'absent',
@@ -33,32 +33,29 @@ describe('WebStorage Storage API', () => {
});
});
it('should allow the setting and getting of the simple data structures', async () => {
it('should allow the setting and snapshotting of the simple data structures', async () => {
const storage = createMockStorage();
await storage.set('myfakekey', 'helloimastring');
await storage.set('mysecondfakekey', 1234);
await storage.set('mythirdfakekey', true);
expect(storage.get('myfakekey')).toBe('helloimastring');
expect(storage.get('mysecondfakekey')).toBe(1234);
expect(storage.get('mythirdfakekey')).toBe(true);
expect(storage.snapshot('myfakekey').value).toBe('helloimastring');
expect(storage.snapshot('mysecondfakekey').value).toBe(1234);
expect(storage.snapshot('mythirdfakekey').value).toBe(true);
expect(storage.snapshot('myfakekey')).toEqual({
key: 'myfakekey',
presence: 'present',
value: 'helloimastring',
newValue: 'helloimastring',
});
expect(storage.snapshot('mysecondfakekey')).toEqual({
key: 'mysecondfakekey',
presence: 'present',
value: 1234,
newValue: 1234,
});
expect(storage.snapshot('mythirdfakekey')).toEqual({
key: 'mythirdfakekey',
presence: 'present',
value: true,
newValue: true,
});
});
@@ -72,12 +69,11 @@ describe('WebStorage Storage API', () => {
await storage.set('myfakekey', mockData);
expect(storage.get('myfakekey')).toEqual(mockData);
expect(storage.snapshot('myfakekey').value).toEqual(mockData);
expect(storage.snapshot('myfakekey')).toEqual({
key: 'myfakekey',
presence: 'present',
value: mockData,
newValue: mockData,
});
});
@@ -107,7 +103,6 @@ describe('WebStorage Storage API', () => {
key: 'correctKey',
presence: 'present',
value: mockData,
newValue: mockData,
});
});
@@ -153,9 +148,11 @@ describe('WebStorage Storage API', () => {
await firstStorage.set(keyName, 'boop');
await secondStorage.set(keyName, 'deerp');
expect(firstStorage.get(keyName)).not.toBe(secondStorage.get(keyName));
expect(firstStorage.get(keyName)).toBe('boop');
expect(secondStorage.get(keyName)).toBe('deerp');
expect(firstStorage.snapshot(keyName)).not.toBe(
secondStorage.snapshot(keyName),
);
expect(firstStorage.snapshot(keyName).value).toBe('boop');
expect(secondStorage.snapshot(keyName).value).toBe('deerp');
expect(firstStorage.snapshot(keyName)).not.toEqual(
secondStorage.snapshot(keyName),
);
@@ -163,13 +160,11 @@ describe('WebStorage Storage API', () => {
key: keyName,
presence: 'present',
value: 'boop',
newValue: 'boop',
});
expect(secondStorage.snapshot(keyName)).toEqual({
key: keyName,
presence: 'present',
value: 'deerp',
newValue: 'deerp',
});
});
@@ -186,7 +181,7 @@ describe('WebStorage Storage API', () => {
await firstStorage.set('test2', { error: true });
expect(secondStorage.get('deep/test2')).toBe(undefined);
expect(secondStorage.snapshot('deep/test2').value).toBe(undefined);
expect(secondStorage.snapshot('deep/test2')).toMatchObject({
presence: 'absent',
});
@@ -201,19 +196,17 @@ describe('WebStorage Storage API', () => {
await firstStorage.set('test2', true);
expect(firstStorage.get('test2')).toBe(true);
expect(secondStorage.get('test2')).toBe(undefined);
expect(firstStorage.snapshot('test2').value).toBe(true);
expect(secondStorage.snapshot('test2').value).toBe(undefined);
expect(firstStorage.snapshot('test2')).toEqual({
key: 'test2',
presence: 'present',
value: true,
newValue: true,
});
expect(secondStorage.snapshot('test2')).toEqual({
key: 'test2',
presence: 'absent',
value: undefined,
newValue: undefined,
});
});
@@ -61,10 +61,6 @@ export class MockStorageApi implements StorageApi {
return this.bucketStorageApis.get(name)!;
}
get<T>(key: string): T | undefined {
return this.snapshot(key).value as T | undefined;
}
snapshot<T extends JsonValue>(key: string): StorageValueSnapshot<T> {
if (this.data.hasOwnProperty(this.getKeyName(key))) {
const data = this.data[this.getKeyName(key)];
@@ -72,14 +68,12 @@ export class MockStorageApi implements StorageApi {
key,
presence: 'present',
value: data,
newValue: data,
};
}
return {
key,
presence: 'absent',
value: undefined,
newValue: undefined,
};
}
@@ -95,7 +89,6 @@ export class MockStorageApi implements StorageApi {
key,
presence: 'present',
value: serialized,
newValue: serialized,
});
}
@@ -105,7 +98,6 @@ export class MockStorageApi implements StorageApi {
key,
presence: 'absent',
value: undefined,
newValue: undefined,
});
}
@@ -36,12 +36,12 @@ export class DefaultStarredEntitiesApi implements StarredEntitiesApi {
this.settingsStore = opts.storageApi.forBucket('starredEntities');
this.starredEntities = new Set(
this.settingsStore.get<string[]>('entityRefs') ?? [],
this.settingsStore.snapshot<string[]>('entityRefs').value ?? [],
);
this.settingsStore.observe$<string[]>('entityRefs').subscribe({
next: next => {
this.starredEntities = new Set(next.newValue ?? []);
this.starredEntities = new Set(next.value ?? []);
this.notifyChanges();
},
});
@@ -41,19 +41,19 @@ describe('performMigrationToTheNewBucket', () => {
'entity:Component:default:a',
'entity:template:custom:b',
]);
expect(oldBucket.get('starredEntities')).not.toBeUndefined();
expect(oldBucket.snapshot('starredEntities').value).not.toBeUndefined();
await performMigrationToTheNewBucket({ storageApi: mockStorage });
// read NEW bucket
expect(await newBucket.get('entityRefs')).toEqual([
expect(await newBucket.snapshot('entityRefs').value).toEqual([
'component:default/c',
'component:default/a',
'template:custom/b',
]);
// OLD bucket should be removed
expect(oldBucket.get('starredEntities')).toBeUndefined();
expect(oldBucket.snapshot('starredEntities').value).toBeUndefined();
});
it('should ignore invalid entries', async () => {
@@ -67,15 +67,17 @@ describe('performMigrationToTheNewBucket', () => {
'entity:Component:a',
'invalid',
]);
expect(oldBucket.get('starredEntities')).not.toBeUndefined();
expect(oldBucket.snapshot('starredEntities')).not.toBeUndefined();
await performMigrationToTheNewBucket({ storageApi: mockStorage });
// read NEW bucket
expect(await newBucket.get('entityRefs')).toEqual(['component:default/a']);
expect(await newBucket.snapshot('entityRefs').value).toEqual([
'component:default/a',
]);
// OLD bucket should be removed
expect(oldBucket.get('starredEntities')).toBeUndefined();
expect(oldBucket.snapshot('starredEntities').value).toBeUndefined();
});
it('should skip migration without old starred entities', async () => {
@@ -88,7 +90,7 @@ describe('performMigrationToTheNewBucket', () => {
await performMigrationToTheNewBucket({ storageApi: mockStorage });
// read NEW bucket
expect(newBucket.get('entityRefs')).toEqual(expectedEntries);
expect(newBucket.snapshot('entityRefs').value).toEqual(expectedEntries);
});
it('should skip migration with non-array old starred entities', async () => {
@@ -105,9 +107,9 @@ describe('performMigrationToTheNewBucket', () => {
await performMigrationToTheNewBucket({ storageApi: mockStorage });
// read NEW bucket
expect(newBucket.get('entityRefs')).toEqual(expectedEntries);
expect(newBucket.snapshot('entityRefs').value).toEqual(expectedEntries);
// OLD bucket should be unchanged
expect(oldBucket.get('starredEntities')).toBe('invalid');
expect(oldBucket.snapshot('starredEntities').value).toBe('invalid');
});
});
@@ -35,13 +35,15 @@ export async function performMigrationToTheNewBucket({
const source = storageApi.forBucket('settings');
const target = storageApi.forBucket('starredEntities');
const oldStarredEntities = source.get('starredEntities');
const oldStarredEntities = source.snapshot('starredEntities').value;
if (!isArray(oldStarredEntities)) {
// nothing to do
return;
}
const targetEntities = new Set(target.get<string[]>('entityRefs') ?? []);
const targetEntities = new Set(
target.snapshot<string[]>('entityRefs').value ?? [],
);
oldStarredEntities
.filter(isString)