@open-condo/miniapp-utils
Version:
A set of helper functions / components / hooks used to build new condo apps fast
92 lines (89 loc) • 4.39 kB
text/typescript
import { IncomingMessage, ServerResponse } from 'http';
import { Context } from 'react';
declare const SSR_COOKIES_DEFAULT_PROP_NAME = "__SSR_COOKIES__";
type SSRCookiesContextValues<CookiesList extends ReadonlyArray<string>> = Record<CookiesList[number], string | null>;
type Optional<T> = T | undefined;
type SSRProps<PropsType extends Record<string, unknown>> = {
props?: PropsType;
};
type SSRPropsWithCookies<PropsType extends Record<string, unknown>, CookiesList extends ReadonlyArray<string>, CookiesPropName extends string = typeof SSR_COOKIES_DEFAULT_PROP_NAME> = {
props: PropsType & {
[K in CookiesPropName]?: SSRCookiesContextValues<CookiesList>;
};
};
type UseSSRCookiesExtractor<CookiesList extends ReadonlyArray<string>, CookiesPropName extends string = typeof SSR_COOKIES_DEFAULT_PROP_NAME> = <PropsType extends Record<string, unknown>>(pageParams: SSRPropsWithCookies<PropsType, CookiesList, CookiesPropName>['props']) => SSRCookiesContextValues<CookiesList>;
type UseSSRCookies<CookiesList extends ReadonlyArray<string>> = () => SSRCookiesContextValues<CookiesList>;
/**
* Helper that allows you to pass cookies from the request directly to the SSR,
* thus avoiding layout shifts and loading states.
*
* NOTE: You should not use this tool to pass secure http-only cookies to the client,
* that's why each application must define the list of allowed cookies itself.
*
* @example Init helper and export utils for app
* import { SSRCookiesHelper } from '@open-condo/miniapp-utils/helpers/cookies'
* import type { SSRCookiesContextValues } from '@open-condo/miniapp-utils/helpers/cookies'
*
* import type { Context } from 'react'
*
* // NOTE: put here only cookies needed in SRR (hydration), does not put http-only cookies here
* const VITAL_COOKIES = ['residentId', 'isLayoutMinified'] as const
*
* const cookieHelper = new SSRCookiesHelper(VITAL_COOKIES)
*
* export const extractSSRCookies = cookieHelper.extractSSRCookies
* export const useSSRCookiesExtractor = cookieHelper.generateUseSSRCookiesExtractorHook()
* export const useSSRCookies = cookieHelper.generateUseSSRCookiesHook()
* export const SSRCookiesContext = cookieHelper.getContext() as Context<SSRCookiesContextValues<typeof VITAL_COOKIES>>
*
* @example Extract cookies in getServerSideProps / getInitialProps
* import { extractSSRCookies } from '@/domains/common/utils/ssr'
*
* export const getServerSideProps = async ({ req, res }) => {
* return extractSSRCookies(req, res, {
* props: { ... }
* })
* }
*
* @example Pass extracted cookies to React context in your _app.ts
* import { SSRCookiesContext } from '@/domains/common/utils/ssr'
*
* export default function App ({ Component, pageProps }: AppProps): ReactNode {
* const ssrCookies = useSSRCookiesExtractor(pageProps)
*
* return (
* <SSRCookiesContext.Provider value={ssrCookies}>
* <Component {...pageProps} />
* </SSRCookiesContext.Provider>
* )
* }
*
* @example Use extracted cookies anywhere in your app.
* // /domains/common/components/Layout.tsx
* import { useState } from 'react'
* import { useSSRCookies } from '@/domains/common/utils/ssr'
*
* import type { FC } from 'react'
*
* export const Layout: FC = () => {
* const { isLayoutMinified } = useSSRCookies()
*
* const [layoutMinified, setLayoutMinified] = useState(isLayoutMinified === 'true')
*
* return {
* // ...
* }
* }
*/
declare class SSRCookiesHelper<CookiesList extends ReadonlyArray<string>, CookiesPropName extends string = typeof SSR_COOKIES_DEFAULT_PROP_NAME> {
allowedCookies: CookiesList;
propName: CookiesPropName;
private readonly context;
private readonly defaultValues;
constructor(allowedCookies: CookiesList, propName?: CookiesPropName);
getContext(): Context<SSRCookiesContextValues<CookiesList>>;
generateUseSSRCookiesExtractorHook(): UseSSRCookiesExtractor<CookiesList, CookiesPropName>;
generateUseSSRCookiesHook(): UseSSRCookies<CookiesList>;
extractSSRCookies<PropsType extends Record<string, unknown>>(req: Optional<IncomingMessage>, res: Optional<ServerResponse>, pageParams: SSRProps<PropsType>): SSRPropsWithCookies<PropsType, CookiesList, CookiesPropName>;
}
export { type SSRCookiesContextValues, SSRCookiesHelper, type UseSSRCookies, type UseSSRCookiesExtractor };