diff --git a/harmony-proxy/harmony-proxy-tests.ts b/harmony-proxy/harmony-proxy-tests.ts new file mode 100644 index 000000000..4c011d5fd --- /dev/null +++ b/harmony-proxy/harmony-proxy-tests.ts @@ -0,0 +1,27 @@ +/// + +import * as Proxy from "harmony-proxy"; + +interface IKatana { + use: () => void; +} + +class Katana implements IKatana { + public use() { + console.log("Used Katana!"); + } +} + +let handler = { + apply: function(target: any, thisArg: any, argArray: any) { + console.log(`Starting: ${performance.now()}`); + let result = target.apply(thisArg, argArray); + console.log(`Finished: ${performance.now()}`); + return result; + } +}; + +let katana = new Katana(); + +let katanaProxy = new Proxy(katana, handler); +katanaProxy.use(); diff --git a/harmony-proxy/harmony-proxy.d.ts b/harmony-proxy/harmony-proxy.d.ts new file mode 100644 index 000000000..dba832c14 --- /dev/null +++ b/harmony-proxy/harmony-proxy.d.ts @@ -0,0 +1,35 @@ +// Type definitions for harmony-proxy 1.0.0 +// Project: https://www.npmjs.com/package/harmony-proxy +// Definitions by: Remo Jansen +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +declare module harmonyProxy { + type PropertyKey = string | number | symbol; + + interface ProxyHandler { + getPrototypeOf? (target: T): any; + setPrototypeOf? (target: T, v: any): boolean; + isExtensible? (target: T): boolean; + preventExtensions? (target: T): boolean; + getOwnPropertyDescriptor? (target: T, p: PropertyKey): PropertyDescriptor; + has? (target: T, p: PropertyKey): boolean; + get? (target: T, p: PropertyKey, receiver: any): any; + set? (target: T, p: PropertyKey, value: any, receiver: any): boolean; + deleteProperty? (target: T, p: PropertyKey): boolean; + defineProperty? (target: T, p: PropertyKey, attributes: PropertyDescriptor): boolean; + enumerate? (target: T): PropertyKey[]; + ownKeys? (target: T): PropertyKey[]; + apply? (target: T, thisArg: any, argArray?: any): any; + construct? (target: T, thisArg: any, argArray?: any): any; + } + + interface ProxyConstructor { + revocable(target: T, handler: ProxyHandler): { proxy: T; revoke: () => void; }; + new (target: T, handler: ProxyHandler): T + } +} + +declare module "harmony-proxy" { + let _Proxy: harmonyProxy.ProxyConstructor; + export = _Proxy; +} diff --git a/inversify/inversify-global-tests.ts b/inversify/inversify-global-tests.ts new file mode 100644 index 000000000..ab1ac4b11 --- /dev/null +++ b/inversify/inversify-global-tests.ts @@ -0,0 +1,193 @@ +/// + +module global_module_test { + + interface INinja { + fight(): string; + sneak(): string; + } + + interface IKatana { + hit(): string; + } + + interface IShuriken { + throw(): string; + } + + class Katana implements IKatana { + public hit() { + return "cut!"; + } + } + + class Shuriken implements IShuriken { + public throw() { + return "hit!"; + } + } + + @inversify.inject("IKatana", "IShuriken") + class Ninja implements INinja { + + private _katana: IKatana; + private _shuriken: IShuriken; + + public constructor(katana: IKatana, shuriken: IShuriken) { + this._katana = katana; + this._shuriken = shuriken; + } + + public fight() { return this._katana.hit(); }; + public sneak() { return this._shuriken.throw(); }; + + } + + let kernel = new inversify.Kernel(); + kernel.bind("INinja").to(Ninja); + kernel.bind("IKatana").to(Katana); + kernel.bind("IShuriken").to(Shuriken).inSingletonScope(); + + let ninja = kernel.get("INinja"); + console.log(ninja); + + // Unbind + kernel.unbind("INinja"); + kernel.unbindAll(); + + // Kernel modules + let module: inversify.IKernelModule = (k: inversify.IKernel) => { + k.bind("INinja").to(Ninja); + k.bind("IKatana").to(Katana).inTransientScope(); + k.bind("IShuriken").to(Shuriken).inSingletonScope(); + }; + + let options: inversify.IKernelOptions = { + middleware: [], + modules: [module] + }; + + kernel = new inversify.Kernel(options); + let ninja2 = kernel.get("INinja"); + console.log(ninja2); + + // binding types + kernel.bind("IKatana").to(Katana); + kernel.bind("IKatana").toValue(new Katana()); + + kernel.bind>("IKatana").toConstructor(Katana); + + kernel.bind>("IKatana").toFactory((context) => { + return () => { + return kernel.get("IKatana"); + }; + }); + + kernel.bind>("IKatana").toAutoFactory(); + + kernel.bind>("IKatana").toProvider((context) => { + return () => { + return new Promise((resolve) => { + let katana = kernel.get("IKatana"); + resolve(katana); + }); + }; + }); + + kernel.bind("IKatana").to(Katana).proxy((katanaToBeInjected: IKatana) => { + // BLOCK http://stackoverflow.com/questions/35906938/how-to-enable-harmony-proxies-in-gulp-mocha + /* + let handler = { + apply: function(target, thisArgument, argumentsList) { + console.log(`Starting: ${performance.now()}`); + let result = target.apply(thisArgument, argumentsList); + console.log(`Finished: ${performance.now()}`); + return result; + } + }; + return new Proxy(katanaToBeInjected, handler); + */ + return katanaToBeInjected; + }); + + interface IWeapon {} + interface ISamurai { + katana: IWeapon; + shuriken: IWeapon; + } + + @inversify.inject("IWeapon", "IWeapon") + class Samurai implements ISamurai { + public katana: IWeapon; + public shuriken: IWeapon; + public constructor( + @inversify.tagged("canThrow", false) katana: IWeapon, + @inversify.tagged("canThrow", true) shuriken: IWeapon + ) { + this.katana = katana; + this.shuriken = shuriken; + } + } + + kernel.bind("Samurai").to(Samurai); + kernel.bind("IWeapon").to(Katana).whenTargetTagged("canThrow", false); + kernel.bind("IWeapon").to(Shuriken).whenTargetTagged("canThrow", true); + + let throwable = inversify.tagged("canThrow", true); + let notThrowable = inversify.tagged("canThrow", false); + + @inversify.inject("IWeapon", "IWeapon") + class Samurai2 implements ISamurai { + public katana: IWeapon; + public shuriken: IWeapon; + public constructor( + @throwable("canThrow", false) katana: IWeapon, + @notThrowable("canThrow", true) shuriken: IWeapon + ) { + this.katana = katana; + this.shuriken = shuriken; + } + } + + @inversify.inject("IWeapon", "IWeapon") + class Samurai3 implements ISamurai { + public katana: IWeapon; + public shuriken: IWeapon; + public constructor( + @inversify.named("strong") katana: IWeapon, + @inversify.named("weak") shuriken: IWeapon + ) { + this.katana = katana; + this.shuriken = shuriken; + } + } + + kernel.bind("ISamurai").to(Samurai3); + kernel.bind("IWeapon").to(Katana).whenTargetNamed("strong"); + kernel.bind("IWeapon").to(Shuriken).whenTargetNamed("weak"); + + @inversify.inject("IWeapon", "IWeapon") + @inversify.paramNames("katana", "shuriken") + class Samurai4 implements ISamurai { + public katana: IWeapon; + public shuriken: IWeapon; + public constructor( + katana: IWeapon, + shuriken: IWeapon + ) { + this.katana = katana; + this.shuriken = shuriken; + } + } + + kernel.bind("ISamurai").to(Samurai4); + + kernel.bind("IWeapon").to(Katana).when((request: inversify.IRequest) => { + return request.target.name.equals("katana"); + }); + + kernel.bind("IWeapon").to(Shuriken).when((request: inversify.IRequest) => { + return request.target.name.equals("shuriken"); + }); + +} diff --git a/inversify/inversify-tests.ts b/inversify/inversify-tests.ts index 46b5cab97..8d2d99d5c 100644 --- a/inversify/inversify-tests.ts +++ b/inversify/inversify-tests.ts @@ -1,75 +1,200 @@ /// -interface FooInterface { - name : string; - greet() : string; +import { + Kernel, + inject, tagged, named, paramNames, + IKernel, IKernelOptions, INewable, + IKernelModule, IFactory, IProvider, IRequest +} from "inversify"; + +module external_module_test { + + interface INinja { + fight(): string; + sneak(): string; + } + + interface IKatana { + hit(): string; + } + + interface IShuriken { + throw(): string; + } + + class Katana implements IKatana { + public hit() { + return "cut!"; + } + } + + class Shuriken implements IShuriken { + public throw() { + return "hit!"; + } + } + + @inject("IKatana", "IShuriken") + class Ninja implements INinja { + + private _katana: IKatana; + private _shuriken: IShuriken; + + public constructor(katana: IKatana, shuriken: IShuriken) { + this._katana = katana; + this._shuriken = shuriken; + } + + public fight() { return this._katana.hit(); }; + public sneak() { return this._shuriken.throw(); }; + + } + + let kernel = new Kernel(); + kernel.bind("INinja").to(Ninja); + kernel.bind("IKatana").to(Katana); + kernel.bind("IShuriken").to(Shuriken).inSingletonScope(); + + let ninja = kernel.get("INinja"); + console.log(ninja); + + // Unbind + kernel.unbind("INinja"); + kernel.unbindAll(); + + // Kernel modules + let module: IKernelModule = (k: IKernel) => { + k.bind("INinja").to(Ninja); + k.bind("IKatana").to(Katana).inTransientScope(); + k.bind("IShuriken").to(Shuriken).inSingletonScope(); + }; + + let options: IKernelOptions = { + middleware: [], + modules: [module] + }; + + kernel = new Kernel(options); + let ninja2 = kernel.get("INinja"); + console.log(ninja2); + + // binding types + kernel.bind("IKatana").to(Katana); + kernel.bind("IKatana").toValue(new Katana()); + + kernel.bind>("IKatana").toConstructor(Katana); + + kernel.bind>("IKatana").toFactory((context) => { + return () => { + return kernel.get("IKatana"); + }; + }); + + kernel.bind>("IKatana").toAutoFactory(); + + kernel.bind>("IKatana").toProvider((context) => { + return () => { + return new Promise((resolve) => { + let katana = kernel.get("IKatana"); + resolve(katana); + }); + }; + }); + + kernel.bind("IKatana").to(Katana).proxy((katanaToBeInjected: IKatana) => { + // BLOCK http://stackoverflow.com/questions/35906938/how-to-enable-harmony-proxies-in-gulp-mocha + /* + let handler = { + apply: function(target, thisArgument, argumentsList) { + console.log(`Starting: ${performance.now()}`); + let result = target.apply(thisArgument, argumentsList); + console.log(`Finished: ${performance.now()}`); + return result; + } + }; + return new Proxy(katanaToBeInjected, handler); + */ + return katanaToBeInjected; + }); + + interface IWeapon {} + interface ISamurai { + katana: IWeapon; + shuriken: IWeapon; + } + + @inject("IWeapon", "IWeapon") + class Samurai implements ISamurai { + public katana: IWeapon; + public shuriken: IWeapon; + public constructor( + @tagged("canThrow", false) katana: IWeapon, + @tagged("canThrow", true) shuriken: IWeapon + ) { + this.katana = katana; + this.shuriken = shuriken; + } + } + + kernel.bind("Samurai").to(Samurai); + kernel.bind("IWeapon").to(Katana).whenTargetTagged("canThrow", false); + kernel.bind("IWeapon").to(Shuriken).whenTargetTagged("canThrow", true); + + let throwable = tagged("canThrow", true); + let notThrowable = tagged("canThrow", false); + + @inject("IWeapon", "IWeapon") + class Samurai2 implements ISamurai { + public katana: IWeapon; + public shuriken: IWeapon; + public constructor( + @throwable("canThrow", false) katana: IWeapon, + @notThrowable("canThrow", true) shuriken: IWeapon + ) { + this.katana = katana; + this.shuriken = shuriken; + } + } + + @inject("IWeapon", "IWeapon") + class Samurai3 implements ISamurai { + public katana: IWeapon; + public shuriken: IWeapon; + public constructor( + @named("strong") katana: IWeapon, + @named("weak") shuriken: IWeapon + ) { + this.katana = katana; + this.shuriken = shuriken; + } + } + + kernel.bind("ISamurai").to(Samurai3); + kernel.bind("IWeapon").to(Katana).whenTargetNamed("strong"); + kernel.bind("IWeapon").to(Shuriken).whenTargetNamed("weak"); + + @inject("IWeapon", "IWeapon") + @paramNames("katana", "shuriken") + class Samurai4 implements ISamurai { + public katana: IWeapon; + public shuriken: IWeapon; + public constructor( + katana: IWeapon, + shuriken: IWeapon + ) { + this.katana = katana; + this.shuriken = shuriken; + } + } + + kernel.bind("ISamurai").to(Samurai4); + + kernel.bind("IWeapon").to(Katana).when((request: IRequest) => { + return request.target.name.equals("katana"); + }); + + kernel.bind("IWeapon").to(Shuriken).when((request: IRequest) => { + return request.target.name.equals("shuriken"); + }); + } - -interface BarInterface { - name : string; - greet() : string; -} - -interface FooBarInterface { - foo : FooInterface; - bar : BarInterface; - greet() : string; -} - -class Foo implements FooInterface { - public name : string; - constructor() { - this.name = "foo"; - } - public greet() : string { - return this.name; - } -} - -class Bar implements BarInterface { - public name : string; - constructor() { - this.name = "bar"; - } - public greet() : string { - return this.name; - } -} - -class FooBar implements FooBarInterface { - public foo : FooInterface; - public bar : BarInterface; - constructor(FooInterface : FooInterface, BarInterface : BarInterface) { - this.foo = FooInterface; - this.bar = BarInterface; - } - public greet() : string{ - return this.foo.greet() + this.bar.greet(); - } -} - -// Kernel -var kernel = new inversify.Kernel(); - -// Identifiers -var fooRuntimeIdentifier = "FooInterface"; -var barRuntimeIdentifier = "BarInterface"; -var fooBarRuntimeIdentifier = "FooBarInterface"; - -// Bindings -var fooBinding = new inversify.TypeBinding(fooRuntimeIdentifier, Foo); -var barBinding = new inversify.TypeBinding(barRuntimeIdentifier, Bar); -var fooBarBinding = new inversify.TypeBinding(fooBarRuntimeIdentifier, FooBar); - -kernel.bind(fooBinding); -kernel.bind(barBinding); -kernel.bind(fooBarBinding); - -// Resolve -var foo = kernel.resolve(fooRuntimeIdentifier); -var bar = kernel.resolve(barRuntimeIdentifier); -var fooBar = kernel.resolve(fooBarRuntimeIdentifier); - -// Unbind -kernel.unbind(fooRuntimeIdentifier); -kernel.unbindAll(); diff --git a/inversify/inversify.d.ts b/inversify/inversify.d.ts index f3c924e82..fe2e3c1f7 100644 --- a/inversify/inversify.d.ts +++ b/inversify/inversify.d.ts @@ -1,51 +1,143 @@ -// Type definitions for inversify 1.0.0 +// Type definitions for inversify 2.0.0-alpha.3 // Project: https://github.com/inversify/InversifyJS // Definitions by: inversify // Definitions: https://github.com/borisyankov/DefinitelyTyped -declare module inversify { - - interface TypeBindingInterface { - runtimeIdentifier : string; - implementationType : { new(): TServiceType ;}; - cache : TServiceType; - scope : number; // TypeBindingScopeEnum - } +/// - interface KernelInterface { - bind(typeBinding : TypeBindingInterface) : void; - unbind(runtimeIdentifier : string) : void; - unbindAll() : void; - resolve(runtimeIdentifier : string) : TImplementationType; - } +declare namespace inversify { - enum TypeBindingScopeEnum { - Transient = 0, - Singleton = 1, - } + interface IKernelConstructor { + new(options?: IKernelOptions): IKernel; + } - class TypeBinding implements TypeBindingInterface { - runtimeIdentifier: string; - implementationType: { - new (): TServiceType; - }; - cache: TServiceType; - scope: TypeBindingScopeEnum; - constructor(runtimeIdentifier: string, implementationType: { - new (...args: any[]): TServiceType; - }, scopeType?: TypeBindingScopeEnum); - } + export interface IKernel { + bind(runtimeIdentifier: string): IBindingToSyntax; + unbind(runtimeIdentifier: string): void; + unbindAll(): void; + get(runtimeIdentifier: string): T; + getAll(runtimeIdentifier: string): T[]; + } - class Kernel implements KernelInterface { - private _bindings; - bind(typeBinding: TypeBindingInterface): void; - unbind(runtimeIdentifier: string): void; - unbindAll(): void; - resolve(runtimeIdentifier: string): TImplementationType; - private _validateBinding(typeBinding); - private _getConstructorArguments(func); - private _injectDependencies(func); - private _construct(constr, args); - constructor(); - } + export interface IKernelOptions { + middleware?: IMiddleware[]; + modules?: IKernelModule[]; + } + + interface IMiddleware extends Function { + (...args: any[]): any; + } + + export interface IKernelModule extends Function { + (kernel: IKernel): void; + } + + interface IBindingToSyntax { + to(constructor: { new(...args: any[]): T; }): IBindingInWhenProxySyntax; + toValue(value: T): IBindingInWhenProxySyntax; + toConstructor(constructor: INewable): IBindingInWhenProxySyntax; + toFactory(factory: IFactoryCreator): IBindingInWhenProxySyntax; + toAutoFactory(): IBindingInWhenProxySyntax; + toProvider(provider: IProviderCreator): IBindingInWhenProxySyntax; + } + + interface IBindingInWhenProxySyntax { + inTransientScope(): IBindingInWhenProxySyntax; + inSingletonScope(): IBindingInWhenProxySyntax; + when(constraint: (request: IRequest) => boolean): IBindingInWhenProxySyntax; + whenTargetNamed(name: string): IBindingInWhenProxySyntax; + whenTargetTagged(tag: string, value: any): IBindingInWhenProxySyntax; + proxy(fn: (injectable: T) => T): IBindingInWhenProxySyntax; + } + + export interface IFactory extends Function { + (): T; + } + + interface IFactoryCreator extends Function { + (context: IContext): IFactory; + } + + export interface INewable { + new(...args: any[]): T; + } + + export interface IProvider extends Function { + (): Promise; + } + + interface IProviderCreator extends Function { + (context: IContext): IProvider; + } + + export interface IContext { + kernel: IKernel; + plan: IPlan; + addPlan(plan: IPlan): void; + } + + export interface IPlan { + parentContext: IContext; + rootRequest: IRequest; + } + + export interface IRequest { + service: string; + parentContext: IContext; + parentRequest: IRequest; + childRequests: IRequest[]; + target: ITarget; + bindings: IBinding[]; + addChildRequest( + service: string, + bindings: (IBinding|IBinding[]), + target: ITarget): IRequest; + } + + export interface IBinding { + runtimeIdentifier: string; + implementationType: INewable; + factory: IFactoryCreator; + provider: IProviderCreator; + constraint: (request: IRequest) => boolean; + proxyMaker: (injectable: T) => T; + cache: T; + scope: number; // BindingScope + type: number; // BindingType + } + + export interface ITarget { + service: IQueryableString; + name: IQueryableString; + metadata: Array; + isArray(): boolean; + isNamed(): boolean; + isTagged(): boolean; + matchesName(name: string): boolean; + matchesTag(name: IMetadata): boolean; + } + + export interface IQueryableString { + startsWith(searchString: string): boolean; + endsWith(searchString: string): boolean; + contains(searchString: string): boolean; + equals(compareString: string): boolean; + value(): string; + } + + export interface IMetadata { + key: string; + value: any; + } + + export var Kernel: IKernelConstructor; + export var decorate: any; + export function inject(...typeIdentifiers: string[]): (typeConstructor: any) => void; + export var tagged: any; + export var named: any; + export var paramNames: any; +} + +declare module "inversify" { + export = inversify; }