import { Constructor } from "type-fest"; import { AllowedNames, ConstructorOf } from "../types"; import { Decorator20223 } from "./types"; type Stage3Decorator = Decorator20223; type LegacyDecorator = >(target: any, property: string | symbol | number, descriptor?: PropertyDescriptor) => void; export interface WithoutOther { (..._: Parameters>): ReturnType (..._: Parameters): ReturnType> } export interface WithOther extends WithoutOther { (..._: OtherParams): OtherReturn } export function decorator_compatibility>({ stage3, legacy }: { stage3?: D3, legacy?: DL, }) { function combo_decorator(..._: Parameters
) function combo_decorator(..._: Parameters) function combo_decorator(...args): any { if (args[1] && args[1].kind) { // @ts-ignore return stage3(...args); } else if (typeof args[1] == 'string' && typeof args[0] == 'object' && (args.length == 2 || args.length == 3)) { // @ts-ignore return legacy(...args); } else { // @ts-ignore return otherwise(...args); } } return combo_decorator; } function areDecoratorArgs(args: any[]) { // Legacy Decorator if (typeof args[1] == 'string' && typeof args[0] == 'object' && (args.length == 2 || args.length == 3)) { return true; } // Stage3 Decorator if (typeof args[1] == 'object' && args[1].kind) { return true; } return false; } export function optional_config_decorator any)>(defaults: T, f: (...params: T) => Dec): { (...params: T): Dec (...params: Parameters): ReturnType } { return (...args) => { if (areDecoratorArgs(args)) { const dec = f(...defaults); // @ts-ignore return dec(...args) as any; } else { // @ts-ignore return f(...args); } } } export function createDefaultSetter(key) { return function set(newValue) { Object.defineProperty(this, key, { configurable: true, writable: true, // IS enumerable when reassigned by the outside word enumerable: true, value: newValue }); return newValue; }; } /** @deprecated Legacy Decorators */ export function wrappedDecorate(target, key, descriptor, wrapper: (f: T) => R) { //: TypedPropertyDescriptor { const { configurable, enumerable, writable } = descriptor; const originalGet = descriptor.get; const originalSet = descriptor.set; const originalValue = descriptor.value; const isGetter = !!originalGet; return { configurable, enumerable, get() { const fn = isGetter ? originalGet.call(this) : originalValue; const value = wrapper.call(this, fn); if (isGetter) { return value; } else { const desc: any = { configurable, enumerable }; desc.value = value; desc.writable = writable; Object.defineProperty(this, key, desc); return value; } }, set: isGetter ? originalSet : createDefaultSetter(key) }; } export const WrappingDec = (f: (inner: T) => R) => { return decorator_compatibility({ legacy(target, key, descriptor) { return wrappedDecorate(target, key, descriptor, f); }, stage3(value, context) { return f.call(value); }, }) }