import React from 'react'; class DigigovError extends Error { constructor(message) { super(message); // (1) this.name = 'DigigovError'; // (2) } } const loggedDeprecations: string[] = []; export interface ErrorWarning { /** * Will log a warning if true. */ warning?: string | true; error?: string | true; } export interface PropValueDeprecations { values?: Record; } export type Deprecations = { name: string; rename?: string; props?: Record; } & ErrorWarning; const warnOnce = (name, message) => { if (loggedDeprecations.includes(name)) { return; } else { loggedDeprecations.push(name); } console.warn(message); }; const handleErrorWarning = ( componentName, name: string, { error, warning }: (PropValueDeprecations & ErrorWarning) | ErrorWarning, type ) => { if (warning === true) { warnOnce( componentName, `⚠️ ${componentName}: ${name} ${type} will be deprecated.` ); } else if (typeof warning === 'string') { warnOnce(componentName, warning); } if (error === true) { throw new DigigovError( `${componentName}: !! ${name} ${type} is deprecated.` ); } else if (typeof error === 'string') { throw new DigigovError( `Component \`${componentName}\` with \`${name}\` prop: ${error}` ); } }; export default function withDeprecation( Component: Type, deprecations: Deprecations ): Type { const componentName = // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore deprecations.name || Component.name || Component?.render?.name; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore return function withDeprecationComponent(props) { if (deprecations.rename) { warnOnce( componentName, `♻️ ${componentName} is renamed to ${deprecations.rename}\n` ); } handleErrorWarning(componentName, componentName, deprecations, 'component'); if (deprecations.props) { Object.keys(deprecations.props).forEach((propName) => { const value = props[propName]; if (!value) { return; } const propDeprecation = deprecations?.props?.[propName]; if (propDeprecation?.values?.[value]) { return handleErrorWarning( componentName, `${propName} ${value}`, propDeprecation?.values?.[value], 'property value' ); } if (propDeprecation?.error || propDeprecation?.warning) { return handleErrorWarning( componentName, propName, propDeprecation, 'property' ); } }); } // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore return ; }; }