Files
Lauren Tan db240980a3 [playground] Decouple playground from compiler
Currently the playground is setup as a linked workspace for the
compiler which complicates our yarn workspace setup and means that snap
can sometimes pull in a different version of react than was otherwise
specified.

There's no real reason to have these workspaces combined so let's split
them up.

ghstack-source-id: 56ab064b2f
Pull Request resolved: https://github.com/facebook/react/pull/31081
2024-09-27 15:25:07 -04:00

70 lines
1.9 KiB
TypeScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import invariant from 'invariant';
import {
compressToEncodedURIComponent,
decompressFromEncodedURIComponent,
} from 'lz-string';
import {defaultStore} from '../defaultStore';
/**
* Global Store for Playground
*/
export interface Store {
source: string;
}
export function encodeStore(store: Store): string {
return compressToEncodedURIComponent(JSON.stringify(store));
}
export function decodeStore(hash: string): Store {
return JSON.parse(decompressFromEncodedURIComponent(hash));
}
/**
* Serialize, encode, and save @param store to localStorage and update URL.
*/
export function saveStore(store: Store): void {
const hash = encodeStore(store);
localStorage.setItem('playgroundStore', hash);
history.replaceState({}, '', `#${hash}`);
}
/**
* Check if @param raw is a valid Store by if
* - it has a `source` property and is a string
*/
function isValidStore(raw: unknown): raw is Store {
return (
raw != null &&
typeof raw == 'object' &&
'source' in raw &&
typeof raw['source'] === 'string'
);
}
/**
* Deserialize, decode, and initialize @param store from URL and then
* localStorage. Throw an error if Store is malformed.
*/
export function initStoreFromUrlOrLocalStorage(): Store {
const encodedSourceFromUrl = location.hash.slice(1);
const encodedSourceFromLocal = localStorage.getItem('playgroundStore');
const encodedSource = encodedSourceFromUrl || encodedSourceFromLocal;
/**
* No data in the URL and no data in the localStorage to fallback to.
* Initialize with the default store.
*/
if (!encodedSource) return defaultStore;
const raw = decodeStore(encodedSource);
invariant(isValidStore(raw), 'Invalid Store');
return raw;
}