UNPKG

@halospv3/hce.shared-config

Version:

Automate commit message quality, changelogs, and CI/CD releases. Its `main` entry point is a Semantic Release config. Functions and classes are exposed for customization. An ESLint config, a Commitlint config, and addl. resources for .NET projects are als

86 lines (80 loc) 3.78 kB
/* eslint-disable jsdoc/no-defaults */ import type { TupleIndices } from '../miscTypes.ts'; import { getPrototypeOf } from './getPrototypeOf.ts'; import { baseClassProto as baseClassPrototype, type BaseClassProto as BaseClassPrototype, type ClassLike, type ConstructorConstraint, type ProtoChainOfClass as PrototypeChainOfClass, type ProtoChainOfClassInstance as PrototypeChainOfClassInstance, type SuperClassLike, type WithProto as WithPrototype, } from './inheritance.ts'; import { isConstructor } from './isConstructor.ts'; type PrototypeChain< Class extends ClassLike<ConstructorConstraint<Class> & WithPrototype<SuperClassLike | BaseClassPrototype>>, ClassesOrInstances extends 'classes' | 'classInstances', > = [ClassesOrInstances] extends ['classInstances'] ? PrototypeChainOfClassInstance<Class> : [ClassesOrInstances] extends ['classes'] ? PrototypeChainOfClass<Class> : never; /** * Iterate through the class and its base/super classes until an anonymous function is reached. This is the default superclass all classes extend. * @template Class Any {@link ClassLike} type. * @template ClassesOrInstances 'classes' or 'classInstances' * @param classDefinition Any class type satisfying {@link Class}. This class (or its instance type) is included in the return value. * @param [returnType='classes'] Determines return type. If 'classInstances', the return type is an array of the classes' `.prototype`. Else, the classes themselves are returned. * @since 3.0.0 * @returns * `returnType extends 'classInstances' ? ClassLike<T>[] : ClassLike<T>[].map(c => c.prototype)` * Excludes default superclasses e.g. anonymous functions, native code. */ export function getPrototypesChainOf< Class extends ClassLike<ConstructorConstraint<Class> & WithPrototype<SuperClassLike | BaseClassPrototype>>, ClassesOrInstances extends 'classes' | 'classInstances', >( classDefinition: Class, returnType: ClassesOrInstances, ): PrototypeChain<Class, ClassesOrInstances> { // class definitions or their respective .prototype; exclude default superclasses. let current: PrototypeChainOfClass<Class>[TupleIndices<PrototypeChainOfClass<Class>>] = classDefinition as PrototypeChainOfClass<Class>[0 extends TupleIndices<PrototypeChainOfClass<Class>> ? 0 : never]; const returnValue = [] as unknown as PrototypeChain<Class, ClassesOrInstances>; let index: TupleIndices<typeof returnValue> = 0 as TupleIndices<typeof returnValue>; while (baseClassPrototype !== current) { const parent: typeof current & WithPrototype<SuperClassLike | BaseClassPrototype> | object = getPrototypeOf(current); // current is a Class symbol/constructor. Object.getOwnPropertyDescriptors on current will include static properties. if (!isConstructor(current)) break; if (returnType === 'classInstances') { const instanceOfCurrent = current.prototype as InstanceType<typeof current>; returnValue[index] = instanceOfCurrent as typeof returnValue[typeof index]; } else { returnValue[index] = current as typeof returnValue[typeof index]; } /** * Assign the super class to current. * If the argument is a class, Reflect.getPrototypeOf method returns the * superclass. */ if ( isConstructor(parent) && 'name' in parent && typeof parent.name === 'string' && '' !== parent.name // it's possible for a Function/Constructor to be anonymous... ) { current = parent as PrototypeChainOfClass<Class>[TupleIndices<PrototypeChainOfClass<Class>>]; } else { break; } index++; } return returnValue; /* assuming current is NugetProjectProperties... Reflect.getPrototypeOf(current).name is 'MSBuildProjectProperties' */ }