Skip to content

Commit

Permalink
Merge pull request #2 from abraham/files
Browse files Browse the repository at this point in the history
Move methods to index
  • Loading branch information
abraham authored Jul 23, 2018
2 parents afcbc43 + e6edde2 commit 5667385
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 105 deletions.
101 changes: 98 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,104 @@
import { decorate, defineMetadata, getMetadata, hasOwnMetadata, metadata } from './methods';

export const Reflection = Object.assign(Reflect, {
export const Reflection = Object.assign({}, Reflect, {
decorate,
defineMetadata,
getMetadata,
hasOwnMetadata,
metadata,
});

export type Decorator = ClassDecorator | MemberDecorator;
export type MemberDecorator = <T>(target: Target, propertyKey: PropertyKey, descriptor?: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
export type MetadataKey = string;
export type MetadataValue = Function;
export type PropertyKey = string | symbol;
export type Target = object | Function;

const Metadata = new WeakMap();

export function defineMetadata(metadataKey: MetadataKey, metadataValue: MetadataValue, target: Target, propertyKey?: PropertyKey) {
return ordinaryDefineOwnMetadata(metadataKey, metadataValue, target, propertyKey);
}

export function decorate(decorators: ClassDecorator[], target: Function): Function
export function decorate(decorators: MemberDecorator[], target: object, propertyKey?: PropertyKey, attributes?: PropertyDescriptor): PropertyDescriptor | undefined
export function decorate(decorators: Decorator[], target: Target, propertyKey?: PropertyKey, attributes?: PropertyDescriptor): Function | PropertyDescriptor | undefined {
if (decorators.length === 0) throw new TypeError();

if (typeof target === 'function') {
return decorateConstructor(decorators as ClassDecorator[], target);
} else if (propertyKey !== undefined) {
return decorateProperty(decorators as MemberDecorator[], target, propertyKey, attributes);
}
return;
}

export function metadata(metadataKey: MetadataKey, metadataValue: MetadataValue) {
return function decorator(target: Function, propertyKey?: PropertyKey) {
ordinaryDefineOwnMetadata(metadataKey, metadataValue, target, propertyKey);
};
}

export function getMetadata(metadataKey: MetadataKey, target: Target, propertyKey?: PropertyKey) {
return ordinaryGetMetadata(metadataKey, target, propertyKey);
}

export function hasOwnMetadata(metadataKey: MetadataKey, target: Target, propertyKey?: PropertyKey): boolean {
return ordinaryHasOwnMetadata(metadataKey, target, propertyKey);
}

function decorateConstructor(decorators: ClassDecorator[], target: Function): Function {
decorators.reverse().forEach((decorator: ClassDecorator) => {
const decorated = decorator(target);
if (decorated) {
target = decorated;
}
});
return target;
}

function decorateProperty(decorators: MemberDecorator[], target: Target, propertyKey: PropertyKey, descriptor?: PropertyDescriptor): PropertyDescriptor | undefined {
decorators.reverse().forEach((decorator: MemberDecorator) => {
const decorated = decorator(target, propertyKey, descriptor);
if (decorated) {
descriptor = decorated;
}
});
return descriptor;
}

function ordinaryDefineOwnMetadata(metadataKey: MetadataKey, metadataValue: MetadataValue, target: Target, propertyKey?: PropertyKey): void {
if (propertyKey && !['string', 'symbol'].includes(typeof propertyKey)) throw new TypeError();

createMetadataMap(target, propertyKey)
.set(metadataKey, metadataValue);
}

function ordinaryGetMetadata(metadataKey: MetadataKey, target: Target, propertyKey?: PropertyKey): Function | undefined {
return ordinaryHasOwnMetadata(metadataKey, target, propertyKey)
? ordinaryGetOwnMetadata(metadataKey, target, propertyKey)
: Object.getPrototypeOf(target)
? ordinaryGetMetadata(metadataKey, Object.getPrototypeOf(target), propertyKey)
: undefined;
}

function ordinaryHasOwnMetadata(metadataKey: MetadataKey, target: Target, propertyKey?: PropertyKey): boolean {
const metadataMap = getMetadataMap(target, propertyKey);
return !!metadataMap && !!metadataMap.has(metadataKey);
}

function ordinaryGetOwnMetadata(metadataKey: MetadataKey, target: Target, propertyKey?: PropertyKey): Function | undefined {
const metadataMap = getMetadataMap(target, propertyKey);
return metadataMap && metadataMap.get(metadataKey);
}

function getMetadataMap(target: Target, propertyKey?: PropertyKey): Map<MetadataKey, MetadataValue> | undefined {
return Metadata.get(target) && Metadata.get(target).get(propertyKey);
}

export function createMetadataMap(target: Target, propertyKey?: PropertyKey): Map<MetadataKey, MetadataValue> {
const targetMetadata = new Map<PropertyKey | undefined, Map<MetadataKey, MetadataValue>>();
Metadata.set(target, targetMetadata);
const metadataMap = new Map<MetadataKey, MetadataValue>();
targetMetadata.set(propertyKey, metadataMap);
return metadataMap;
}
96 changes: 0 additions & 96 deletions src/methods.ts

This file was deleted.

8 changes: 2 additions & 6 deletions src/reflect.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { decorate, defineMetadata, getMetadata, hasOwnMetadata, metadata } from './methods';
import { Reflection } from './index';

// TODO: Is there a better way to do this?
declare global {
Expand All @@ -7,8 +7,4 @@ declare global {
}
}

window.Reflect.decorate = decorate;
window.Reflect.defineMetadata = defineMetadata;
window.Reflect.getMetadata = getMetadata;
window.Reflect.hasOwnMetadata = hasOwnMetadata;
window.Reflect.metadata = metadata;
window.Reflect = Reflection;

0 comments on commit 5667385

Please sign in to comment.