├── .gitignore ├── test ├── CQRSTest.d.ts ├── mocha.d.ts ├── should.d.ts ├── CQRSTest.ts └── CQRSTest.js ├── package.json ├── Gruntfile.js ├── README.md └── lib ├── cqrs-typescript.d.ts ├── async.d.ts ├── node_redis.d.ts ├── cqrs-typescript.ts ├── cqrs-typescript.js └── node.d.ts /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /test/CQRSTest.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cqrs-typescript", 3 | "version": "0.0.9", 4 | "description": "A Typescript friendly library for writing event sourcing or CQRS apps.", 5 | "main": "lib/cqrs-typescript.js", 6 | "keywords" : [ 7 | "CQRS", 8 | "Event sourcing", 9 | "Typescript" 10 | ], 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/andrewwebber/cqrs-typescript" 14 | }, 15 | "scripts": { 16 | "test": "node-debug ./node_modules/grunt-cli/bin/grunt test" 17 | }, 18 | "directories" : { 19 | "lib" : "lib", 20 | "test" : "test" 21 | }, 22 | "author": "@MrPanigale", 23 | "license": "ISC", 24 | "devDependencies": { 25 | "grunt": "^0.4.5", 26 | "grunt-contrib-jshint": "^0.10.0", 27 | "grunt-contrib-nodeunit": "^0.4.1", 28 | "grunt-contrib-watch": "^0.6.1", 29 | "grunt-mocha-test": "^0.11.0", 30 | "grunt-typescript": "^0.3.7", 31 | "should": "^4.0.4", 32 | "grunt-cli": "~0.1.13" 33 | }, 34 | "dependencies": { 35 | "redis": "~0.10.3", 36 | "async": "~0.9.0" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | 'use strict'; 3 | // Project configuration 4 | grunt.initConfig({ 5 | // Metadata 6 | pkg: grunt.file.readJSON('package.json'), 7 | banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + 8 | '<%= grunt.template.today("yyyy-mm-dd") %>\n' + 9 | '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' + 10 | '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + 11 | ' Licensed <%= props.license %> */\n', 12 | // Task configuration 13 | jshint: { 14 | options: { 15 | node: true, 16 | curly: true, 17 | eqeqeq: true, 18 | immed: true, 19 | latedef: true, 20 | newcap: true, 21 | noarg: true, 22 | sub: true, 23 | undef: true, 24 | unused: true, 25 | eqnull: true, 26 | boss: true 27 | }, 28 | gruntfile: { 29 | src: 'gruntfile.js' 30 | }, 31 | lib_test: { 32 | src: ['lib/**/*.js'] 33 | } 34 | }, 35 | nodeunit: { 36 | files: ['test/**/*_test.js'] 37 | }, 38 | watch: { 39 | gruntfile: { 40 | files: '<%= jshint.gruntfile.src %>', 41 | tasks: ['jshint:gruntfile'] 42 | }, 43 | lib_test: { 44 | files: '<%= jshint.lib_test.src %>', 45 | tasks: ['jshint:lib_test', 'nodeunit'] 46 | } 47 | }, 48 | typescript : { 49 | development: { 50 | src: ['lib/*.ts', 'test/*.ts'], 51 | options: { 52 | module: 'commonjs', 53 | watch:true, 54 | declaration: true 55 | } 56 | }, 57 | test: { 58 | src: ['lib/*.ts', 'test/*.ts'], 59 | options: { 60 | module: 'commonjs', 61 | watch:false, 62 | declaration: true, 63 | comments:true 64 | } 65 | } 66 | }, 67 | mochaTest: { 68 | test: { 69 | options: { 70 | reporter: 'spec' 71 | }, 72 | src: ['test/**/*.js'] 73 | } 74 | } 75 | }); 76 | 77 | // These plugins provide necessary tasks 78 | grunt.loadNpmTasks('grunt-contrib-nodeunit'); 79 | grunt.loadNpmTasks('grunt-contrib-jshint'); 80 | grunt.loadNpmTasks('grunt-contrib-watch'); 81 | grunt.loadNpmTasks('grunt-typescript'); 82 | grunt.loadNpmTasks('grunt-mocha-test'); 83 | 84 | // Default task 85 | grunt.registerTask('default', ['typescript:development']); 86 | grunt.registerTask('ts', ['typescript:development']); 87 | grunt.registerTask('test', ['typescript:test', 'mochaTest']); 88 | }; 89 | -------------------------------------------------------------------------------- /test/mocha.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for mocha 1.17.1 2 | // Project: http://visionmedia.github.io/mocha/ 3 | // Definitions by: Kazi Manzur Rashid , otiai10 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | interface Mocha { 7 | // Setup mocha with the given setting options. 8 | setup(options: MochaSetupOptions): Mocha; 9 | 10 | //Run tests and invoke `fn()` when complete. 11 | run(callback?: () => void): void; 12 | 13 | // Set reporter as function 14 | reporter(reporter: () => void): Mocha; 15 | 16 | // Set reporter, defaults to "dot" 17 | reporter(reporter: string): Mocha; 18 | 19 | // Enable growl support. 20 | growl(): Mocha 21 | } 22 | 23 | interface MochaSetupOptions { 24 | //milliseconds to wait before considering a test slow 25 | slow?: number; 26 | 27 | // timeout in milliseconds 28 | timeout?: number; 29 | 30 | // ui name "bdd", "tdd", "exports" etc 31 | ui?: string; 32 | 33 | //array of accepted globals 34 | globals?: any[]; 35 | 36 | // reporter instance (function or string), defaults to `mocha.reporters.Dot` 37 | reporter?: any; 38 | 39 | // bail on the first test failure 40 | bail?: Boolean; 41 | 42 | // ignore global leaks 43 | ignoreLeaks?: Boolean; 44 | 45 | // grep string or regexp to filter tests with 46 | grep?: any; 47 | } 48 | 49 | interface MochaDone { 50 | (error?: Error): void; 51 | } 52 | 53 | declare var mocha: Mocha; 54 | 55 | declare var describe : { 56 | (description: string, spec: () => void): void; 57 | only(description: string, spec: () => void): void; 58 | skip(description: string, spec: () => void): void; 59 | timeout(ms: number): void; 60 | } 61 | 62 | // alias for `describe` 63 | declare var context : { 64 | (contextTitle: string, spec: () => void): void; 65 | only(contextTitle: string, spec: () => void): void; 66 | skip(contextTitle: string, spec: () => void): void; 67 | timeout(ms: number): void; 68 | } 69 | 70 | declare var it: { 71 | (expectation: string, assertion?: () => void): void; 72 | (expectation: string, assertion?: (done: MochaDone) => void): void; 73 | only(expectation: string, assertion?: () => void): void; 74 | only(expectation: string, assertion?: (done: MochaDone) => void): void; 75 | skip(expectation: string, assertion?: () => void): void; 76 | skip(expectation: string, assertion?: (done: MochaDone) => void): void; 77 | timeout(ms: number): void; 78 | }; 79 | 80 | declare function before(action: () => void): void; 81 | 82 | declare function before(action: (done: MochaDone) => void): void; 83 | 84 | declare function setup(action: () => void): void; 85 | 86 | declare function setup(action: (done: MochaDone) => void): void; 87 | 88 | declare function after(action: () => void): void; 89 | 90 | declare function after(action: (done: MochaDone) => void): void; 91 | 92 | declare function teardown(action: () => void): void; 93 | 94 | declare function teardown(action: (done: MochaDone) => void): void; 95 | 96 | declare function beforeEach(action: () => void): void; 97 | 98 | declare function beforeEach(action: (done: MochaDone) => void): void; 99 | 100 | declare function suiteSetup(action: () => void): void; 101 | 102 | declare function suiteSetup(action: (done: MochaDone) => void): void; 103 | 104 | declare function afterEach(action: () => void): void; 105 | 106 | declare function afterEach(action: (done: MochaDone) => void): void; 107 | 108 | declare function suiteTeardown(action: () => void): void; 109 | 110 | declare function suiteTeardown(action: (done: MochaDone) => void): void; 111 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | cqrs-typescript 2 | =============== 3 | 4 | ###CQRS implementation in typescript. 5 | 6 | 7 | 8 | Components avaliable: 9 | - Event Sourcing 10 | - Interfaces for creating versioned events 11 | - Base classes for creating an event sourced aggregates and raising versioned events 12 | - Command processing 13 | - Interfaces for creating commands 14 | - Command bus for sending events 15 | - Redis based command bus using ['rpoplpush'](http://redis.io/commands/rpoplpush) 16 | - Command handling registry for signing up for command types 17 | - Event processing 18 | - Interfaces for creating events 19 | - Event bus for sending events 20 | - Redis based event bus using ['rpoplpush'](http://redis.io/commands/rpoplpush) 21 | - Event handling registry for signing up for command types 22 | 23 | View the tests for more examples on usage. 24 | 25 | ####Event Sourcing 26 | 27 | ```ts 28 | /// 29 | /// 30 | 31 | import CQRS = require('cqrs-typescript'); 32 | import should = require('should'); 33 | should.equal('actual', 'actual'); 34 | 35 | interface ICreditAccountEvent extends CQRS.IVersionedEvent{ 36 | amount:number 37 | } 38 | 39 | interface IDebitAccountEvent extends CQRS.IVersionedEvent{ 40 | amount:number 41 | } 42 | 43 | class BankAccount extends CQRS.EventSourced{ 44 | constructor(id :string){ 45 | super(id); 46 | this.balance = 0; 47 | } 48 | 49 | balance : number; 50 | 51 | credit(amount:number) : void { 52 | this.update({ 53 | name: 'CreditAccount', 54 | amount: amount, 55 | version: -1, 56 | sourceId: '' 57 | }); 58 | } 59 | 60 | debit(amount:number) : void{ 61 | this.update({ 62 | name: 'DebitAccount', 63 | amount: amount, 64 | version: -1, 65 | sourceId: '' 66 | }); 67 | } 68 | 69 | private onCreditAccount(e : ICreditAccountEvent):void{ 70 | this.balance += e.amount; 71 | } 72 | 73 | private onDebitAccount(e : IDebitAccountEvent):void{ 74 | this.balance -= e.amount; 75 | } 76 | } 77 | 78 | var account : BankAccount; 79 | 80 | describe('extending from "EventSourced" to create a "bank account"', function() { 81 | it('should be ok to create one once supplying an id ', function() { 82 | account = new BankAccount('1'); 83 | }); 84 | 85 | it('should be ok to credit the account to 100 by raising an event',function(){ 86 | account.credit(100); 87 | account.balance.should.be.exactly(100); 88 | account.getEvents().length.should.be.exactly(1); 89 | account.getVersion().should.be.exactly(1); 90 | }); 91 | 92 | it('should be ok to credit the account to 150 by raising an event',function(){ 93 | account.credit(50); 94 | account.balance.should.be.exactly(150); 95 | account.getEvents().length.should.be.exactly(2); 96 | account.getVersion().should.be.exactly(2); 97 | }); 98 | 99 | it('should be ok to debit the account by 100 by raising an event',function(){ 100 | account.debit(100); 101 | account.balance.should.be.exactly(50); 102 | account.getEvents().length.should.be.exactly(3); 103 | account.getVersion().should.be.exactly(3); 104 | }); 105 | 106 | it('should be ok to load a bank account from an event stream',function(){ 107 | var accountFromEvents = new BankAccount('1'); 108 | var events = account.getEvents(); 109 | accountFromEvents.loadFromEvents(events); 110 | accountFromEvents.balance.should.be.exactly(account.balance); 111 | accountFromEvents.getVersion().should.be.exactly(account.getVersion()); 112 | }); 113 | }); 114 | ``` 115 | 116 | ####Redis based event sourcing repository 117 | ```ts 118 | var account = new BankAccount('2'); 119 | account.credit(100); 120 | account.credit(100); 121 | account.debit(50); 122 | account.credit(100); 123 | account.debit(200); 124 | account.balance.should.be.exactly(50); 125 | 126 | var provider = new CQRS.RedisEventSourcedRepository({ host: "127.0.0.1", port:6379}); 127 | it('should connect to a specified Redis server',function(done){ 128 | provider.connect((error)=>{ 129 | should.equal(error, null); 130 | done(); 131 | }); 132 | }); 133 | 134 | it('should be able to persist an event stream for an given aggregate id',function(done){ 135 | var events = account.getEvents(); 136 | events.length.should.be.exactly(5); 137 | provider.saveEventsByAggregateId(account.getId(),events, (error)=>{ 138 | should.equal(error, null); 139 | done(); 140 | }); 141 | }); 142 | 143 | it('should be able to retrieve an event stream by aggregate id and recreate an aggregate instance',function(done){ 144 | provider.getEventsByAggregateId(account.getId(),(error, events)=>{ 145 | should.equal(error, null); 146 | events.length.should.be.exactly(5); 147 | 148 | var accountFromEvents = new BankAccount(account.getId()); 149 | accountFromEvents.loadFromEvents(events); 150 | accountFromEvents.balance.should.be.exactly(account.balance); 151 | done(); 152 | }); 153 | }); 154 | ``` 155 | -------------------------------------------------------------------------------- /lib/cqrs-typescript.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | import Redis = require('redis'); 5 | export interface IEnvelope { 6 | body: T; 7 | correlationId: string; 8 | messageId: string; 9 | TTL?: number; 10 | } 11 | export interface ICommand { 12 | id: string; 13 | name: string; 14 | } 15 | export interface ICommandHandler { 16 | handleCommand(commandToHandle: IEnvelope, callback: (error: any) => void): void; 17 | } 18 | export interface IEvent { 19 | sourceId: string; 20 | name: string; 21 | } 22 | export interface IEventHandler { 23 | handleEvent(eventToHandle: IEnvelope, callback: (error: any) => void): void; 24 | } 25 | export declare class HandlerRegistry implements ICommandHandler, IEventHandler { 26 | constructor(); 27 | public commandsRegistry: any; 28 | public eventsRegistry: any; 29 | public registerCommandHandler(commandName: string, commandHandler: ICommandHandler): void; 30 | public registerEventHandler(eventName: string, eventHandler: IEventHandler): void; 31 | public handleCommand(commandToHandle: IEnvelope, callback: (error: any) => void): void; 32 | public handleEvent(eventToHandle: IEnvelope, callback: (error: any) => void): void; 33 | } 34 | export interface IVersionedEvent extends IEvent { 35 | version: number; 36 | } 37 | export interface IEventSourced { 38 | getId(): string; 39 | getVersion(): number; 40 | getEvents(): IVersionedEvent[]; 41 | } 42 | export declare class EventSourced implements IEventSourced { 43 | private id; 44 | private version; 45 | private events; 46 | constructor(id: string); 47 | public getId(): string; 48 | public getVersion(): number; 49 | public getEvents(): IVersionedEvent[]; 50 | public loadFromEvents(events: IVersionedEvent[]): void; 51 | public update(versionedEvent: IVersionedEvent): void; 52 | } 53 | export declare class RedisResource { 54 | private client; 55 | constructor(options: IRedisConnectionOptions); 56 | public options: IRedisConnectionOptions; 57 | public getClient(): Redis.RedisClient; 58 | public connect(callback: (error: any) => void): void; 59 | } 60 | export declare class RedisCommandReceiver extends RedisResource { 61 | constructor(options: IRedisConnectionOptions, commandReceiver: ICommandHandler); 62 | public commandReceiver: ICommandHandler; 63 | public paused: boolean; 64 | public onConnected(): void; 65 | } 66 | export declare class RedisEventReceiver extends RedisResource { 67 | constructor(options: IRedisConnectionOptions, eventReceiver: IEventHandler); 68 | public eventReceiver: IEventHandler; 69 | public paused: boolean; 70 | public onConnected(): void; 71 | } 72 | export declare class RedisCommandBus extends RedisResource implements ICommandHandler { 73 | constructor(options: IRedisConnectionOptions); 74 | public handleCommand(commandToHandle: IEnvelope, callback: (error: any) => void): void; 75 | } 76 | export declare class RedisEventBus extends RedisResource implements IEventHandler { 77 | constructor(options: IRedisConnectionOptions); 78 | public handleEvent(eventToHandle: IEnvelope, callback: (error: any) => void): void; 79 | } 80 | export interface IEventSourcedRepository { 81 | getEventsByAggregateId(id: string, callback: (error: any, events: IVersionedEvent[]) => void): any; 82 | saveEventsByAggregateId(id: string, events: IVersionedEvent[], callback: (error: any) => void): any; 83 | } 84 | export declare class InMemoryEventSourcedRepository implements IEventSourcedRepository { 85 | private db; 86 | constructor(); 87 | public getEventsByAggregateId(id: string, callback: (error: any, events: IVersionedEvent[]) => void): void; 88 | public saveEventsByAggregateId(id: string, events: IVersionedEvent[], callback: (error: any) => void): void; 89 | } 90 | export interface IRedisConnectionOptions { 91 | host: string; 92 | port: number; 93 | } 94 | export declare class EventSourceRepositoryWithNotifications implements IEventSourcedRepository { 95 | constructor(repository: IEventSourcedRepository, onSaveCallback: (id: string, events: IVersionedEvent[]) => void); 96 | public repository: IEventSourcedRepository; 97 | public onSaveCallback: (id: string, events: IVersionedEvent[]) => void; 98 | public getEventsByAggregateId(id: string, callback: (error: any, events: IVersionedEvent[]) => void): void; 99 | public saveEventsByAggregateId(id: string, events: IVersionedEvent[], callback: (error: any) => void): void; 100 | } 101 | export declare class RedisEventSourcedRepository extends RedisResource implements IEventSourcedRepository { 102 | constructor(options: IRedisConnectionOptions); 103 | public getEventsByAggregateId(id: string, callback: (error: any, events: IVersionedEvent[]) => void): void; 104 | public saveEventsByAggregateId(id: string, events: IVersionedEvent[], callback: (error: any) => void): void; 105 | private constructResultsResponse(error, results, callback); 106 | } 107 | -------------------------------------------------------------------------------- /test/should.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for should.js 3.1.2 2 | // Project: https://github.com/visionmedia/should.js 3 | // Definitions by: Alex Varju , Maxime LUCE 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | interface Object { 7 | should: ShouldAssertion; 8 | } 9 | 10 | interface ShouldAssertion { 11 | // basic grammar 12 | a: ShouldAssertion; 13 | an: ShouldAssertion; 14 | and: ShouldAssertion; 15 | be: ShouldAssertion; 16 | have: ShouldAssertion; 17 | with: ShouldAssertion; 18 | of: ShouldAssertion; 19 | not: ShouldAssertion; 20 | 21 | // validators 22 | arguments: ShouldAssertion; 23 | empty: ShouldAssertion; 24 | ok: ShouldAssertion; 25 | true: ShouldAssertion; 26 | false: ShouldAssertion; 27 | NaN: ShouldAssertion; 28 | Infinity: ShouldAssertion; 29 | Array: ShouldAssertion; 30 | Object: ShouldAssertion; 31 | String: ShouldAssertion; 32 | Boolean: ShouldAssertion; 33 | Number: ShouldAssertion; 34 | Error: ShouldAssertion; 35 | Function: ShouldAssertion; 36 | eql(expected: any, description?: string): ShouldAssertion; 37 | equal(expected: any, description?: string): ShouldAssertion; 38 | within(start: number, finish: number, description?: string): ShouldAssertion; 39 | approximately(value: number, delta: number, description?: string): ShouldAssertion; 40 | type(expected: any, description?: string): ShouldAssertion; 41 | instanceof(constructor: Function, description?: string): ShouldAssertion; 42 | above(n: number, description?: string): ShouldAssertion; 43 | below(n: number, description?: string): ShouldAssertion; 44 | match(other: {}, description?: string): ShouldAssertion; 45 | match(other: (val: any) => any, description?: string): ShouldAssertion; 46 | match(regexp: RegExp, description?: string): ShouldAssertion; 47 | match(other: any, description?: string): ShouldAssertion; 48 | matchEach(other: {}, description?: string): ShouldAssertion; 49 | matchEach(other: (val: any) => any, description?: string): ShouldAssertion; 50 | matchEach(regexp: RegExp, description?: string): ShouldAssertion; 51 | matchEach(other: any, description?: string): ShouldAssertion; 52 | length(n: number, description?: string): ShouldAssertion; 53 | property(name: string, description?: string): ShouldAssertion; 54 | property(name: string, val: any, description?: string): ShouldAssertion; 55 | properties(names: string[]): ShouldAssertion; 56 | properties(name: string): ShouldAssertion; 57 | properties(descriptor: any): ShouldAssertion; 58 | properties(...properties: string[]): ShouldAssertion; 59 | ownProperty(name: string, description?: string): ShouldAssertion; 60 | contain(obj: any): ShouldAssertion; 61 | containEql(obj: any): ShouldAssertion; 62 | containDeep(obj: any): ShouldAssertion; 63 | keys(...allKeys: string[]): ShouldAssertion; 64 | keys(allKeys: string[]): ShouldAssertion; 65 | header(field: string, val?: string): ShouldAssertion; 66 | status(code: number): ShouldAssertion; 67 | json: ShouldAssertion; 68 | html: ShouldAssertion; 69 | startWith(expected: string, message?: any): ShouldAssertion; 70 | endWith(expected: string, message?: any): ShouldAssertion; 71 | throw(message?: any): ShouldAssertion; 72 | 73 | // deprecated 74 | include(obj: any, description?: string): ShouldAssertion; 75 | includeEql(obj: any[], description?: string): ShouldAssertion; 76 | 77 | // aliases 78 | exactly(expected: any, description?: string): ShouldAssertion; 79 | instanceOf(constructor: Function, description?: string): ShouldAssertion; 80 | throwError(message?: any): ShouldAssertion; 81 | lengthOf(n: number, description?: string): ShouldAssertion; 82 | key(key: string): ShouldAssertion; 83 | haveOwnProperty(name: string, description?: string): ShouldAssertion; 84 | greaterThan(n: number, description?: string): ShouldAssertion; 85 | lessThan(n: number, description?: string): ShouldAssertion; 86 | } 87 | 88 | interface ShouldInternal { 89 | // should.js's extras 90 | exist(actual: any): void; 91 | exists(actual: any): void; 92 | not: ShouldInternal; 93 | } 94 | 95 | interface Internal extends ShouldInternal { 96 | (obj: any): ShouldAssertion; 97 | 98 | // node.js's assert functions 99 | fail(actual: any, expected: any, message: string, operator: string): void; 100 | assert(value: any, message: string): void; 101 | ok(value: any, message?: string): void; 102 | equal(actual: any, expected: any, message?: string): void; 103 | notEqual(actual: any, expected: any, message?: string): void; 104 | deepEqual(actual: any, expected: any, message?: string): void; 105 | notDeepEqual(actual: any, expected: any, message?: string): void; 106 | strictEqual(actual: any, expected: any, message?: string): void; 107 | notStrictEqual(actual: any, expected: any, message?: string): void; 108 | throws(block: any, error?: any, message?: string): void; 109 | doesNotThrow(block: any, message?: string): void; 110 | ifError(value: any): void; 111 | inspect(value: any, obj: any): any; 112 | } 113 | 114 | declare var should: Internal; 115 | 116 | declare module "should" { 117 | export = should; 118 | } 119 | -------------------------------------------------------------------------------- /lib/async.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Async 0.1.23 2 | // Project: https://github.com/caolan/async 3 | // Definitions by: Boris Yankov 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | interface AsyncMultipleResultsCallback { (err: Error, results: T[]): any; } 7 | interface AsyncSingleResultCallback { (err: Error, result: T): void; } 8 | interface AsyncTimesCallback { (n: number, callback: AsyncMultipleResultsCallback): void; } 9 | 10 | interface AsyncIterator { (item: T, callback: AsyncSingleResultCallback): void; } 11 | interface AsyncMemoIterator { (memo: R, item: T, callback: AsyncSingleResultCallback): void; } 12 | 13 | interface AsyncWorker { (task: T, callback: Function): void; } 14 | 15 | interface AsyncQueue { 16 | length(): number; 17 | concurrency: number; 18 | push(task: T, callback?: AsyncMultipleResultsCallback): void; 19 | push(task: T[], callback?: AsyncMultipleResultsCallback): void; 20 | saturated: AsyncMultipleResultsCallback; 21 | empty: AsyncMultipleResultsCallback; 22 | drain: AsyncMultipleResultsCallback; 23 | } 24 | 25 | interface Async { 26 | 27 | // Collections 28 | forEach(arr: T[], iterator: AsyncIterator, callback: AsyncMultipleResultsCallback): void; 29 | forEachSeries(arr: T[], iterator: AsyncIterator, callback: AsyncMultipleResultsCallback): void; 30 | forEachLimit(arr: T[], limit: number, iterator: AsyncIterator, callback: AsyncMultipleResultsCallback): void; 31 | map(arr: T[], iterator: AsyncIterator, callback: AsyncMultipleResultsCallback): any; 32 | mapSeries(arr: T[], iterator: AsyncIterator, callback: AsyncMultipleResultsCallback): any; 33 | filter(arr: T[], iterator: AsyncIterator, callback: AsyncMultipleResultsCallback): any; 34 | select(arr: T[], iterator: AsyncIterator, callback: AsyncMultipleResultsCallback): any; 35 | filterSeries(arr: T[], iterator: AsyncIterator, callback: AsyncMultipleResultsCallback): any; 36 | selectSeries(arr: T[], iterator: AsyncIterator, callback: AsyncMultipleResultsCallback): any; 37 | reject(arr: T[], iterator: AsyncIterator, callback: AsyncMultipleResultsCallback): any; 38 | rejectSeries(arr: T[], iterator: AsyncIterator, callback: AsyncMultipleResultsCallback): any; 39 | reduce(arr: T[], memo: R, iterator: AsyncMemoIterator, callback: AsyncSingleResultCallback): any; 40 | inject(arr: T[], memo: R, iterator: AsyncMemoIterator, callback: AsyncSingleResultCallback): any; 41 | foldl(arr: T[], memo: R, iterator: AsyncMemoIterator, callback: AsyncSingleResultCallback): any; 42 | reduceRight(arr: T[], memo: R, iterator: AsyncMemoIterator, callback: AsyncSingleResultCallback): any; 43 | foldr(arr: T[], memo: R, iterator: AsyncMemoIterator, callback: AsyncSingleResultCallback): any; 44 | detect(arr: T[], iterator: AsyncIterator, callback: AsyncMultipleResultsCallback): any; 45 | detectSeries(arr: T[], iterator: AsyncIterator, callback: AsyncMultipleResultsCallback): any; 46 | sortBy(arr: T[], iterator: AsyncIterator, callback: AsyncMultipleResultsCallback): any; 47 | some(arr: T[], iterator: AsyncIterator, callback: AsyncMultipleResultsCallback): any; 48 | any(arr: T[], iterator: AsyncIterator, callback: AsyncMultipleResultsCallback): any; 49 | every(arr: T[], iterator: AsyncIterator, callback: (result: boolean) => any): any; 50 | all(arr: T[], iterator: AsyncIterator, callback: (result: boolean) => any): any; 51 | concat(arr: T[], iterator: AsyncIterator, callback: AsyncMultipleResultsCallback): any; 52 | concatSeries(arr: T[], iterator: AsyncIterator, callback: AsyncMultipleResultsCallback): any; 53 | 54 | // Control Flow 55 | series(tasks: T[], callback?: AsyncMultipleResultsCallback): void; 56 | series(tasks: T, callback?: AsyncMultipleResultsCallback): void; 57 | parallel(tasks: T[], callback?: AsyncMultipleResultsCallback): void; 58 | parallel(tasks: T, callback?: AsyncMultipleResultsCallback): void; 59 | parallelLimit(tasks: T[], limit: number, callback?: AsyncMultipleResultsCallback): void; 60 | parallelLimit(tasks: T, limit: number, callback?: AsyncMultipleResultsCallback): void; 61 | whilst(test: Function, fn: Function, callback: Function): void; 62 | until(test: Function, fn: Function, callback: Function): void; 63 | waterfall(tasks: T[], callback?: AsyncMultipleResultsCallback): void; 64 | waterfall(tasks: T, callback?: AsyncMultipleResultsCallback): void; 65 | queue(worker: AsyncWorker, concurrency: number): AsyncQueue; 66 | // auto(tasks: any[], callback?: AsyncMultipleResultsCallback): void; 67 | auto(tasks: any, callback?: AsyncMultipleResultsCallback): void; 68 | iterator(tasks: Function[]): Function; 69 | apply(fn: Function, ...arguments: any[]): void; 70 | nextTick(callback: Function): void; 71 | 72 | times (n: number, callback: AsyncTimesCallback): void; 73 | timesSeries (n: number, callback: AsyncTimesCallback): void; 74 | 75 | // Utils 76 | memoize(fn: Function, hasher?: Function): Function; 77 | unmemoize(fn: Function): Function; 78 | log(fn: Function, ...arguments: any[]): void; 79 | dir(fn: Function, ...arguments: any[]): void; 80 | noConflict(): Async; 81 | } 82 | 83 | declare var async: Async; 84 | 85 | declare module "async" { 86 | export = async; 87 | } 88 | -------------------------------------------------------------------------------- /lib/node_redis.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for node_redis 0.8 2 | // Project: https://github.com/mranney/node_redis 3 | // Definitions by: Boris Yankov 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | 7 | declare module 'redis' { 8 | export var debug_mode: boolean; 9 | export function createClient(): RedisClient; 10 | export function createClient(port: number, host: string, options?: RedisOptions): RedisClient; 11 | export function print(err: string, reply?: string); 12 | 13 | interface RedisOptions { 14 | parser?: string; 15 | return_buffers?: boolean; 16 | detect_buffers?: boolean; 17 | socket_nodelay?: boolean; 18 | no_ready_check?: boolean; 19 | enable_offline_queue?: boolean; 20 | } 21 | 22 | interface Command { 23 | (...args: any[]): any; 24 | } 25 | 26 | interface Commands { 27 | 28 | get: Command; 29 | set: Command; 30 | setnx: Command; 31 | setex: Command; 32 | append: Command; 33 | strlen: Command; 34 | del: Command; 35 | exists: Command; 36 | setbit: Command; 37 | getbit: Command; 38 | setrange: Command; 39 | getrange: Command; 40 | substr: Command; 41 | incr: Command; 42 | decr: Command; 43 | mget: Command; 44 | 45 | rpush: Command; 46 | lpush: Command; 47 | rpushx: Command; 48 | lpushx: Command; 49 | linsert: Command; 50 | rpop: Command; 51 | lpop: Command; 52 | brpop: Command; 53 | brpoplpush: Command; 54 | blpop: Command; 55 | llen: Command; 56 | lindex: Command; 57 | lset: Command; 58 | lrange: Command; 59 | ltrim: Command; 60 | lrem: Command; 61 | rpoplpush: Command; 62 | 63 | sadd: Command; 64 | srem: Command; 65 | smove: Command; 66 | sismember: Command; 67 | scard: Command; 68 | spop: Command; 69 | srandmember: Command; 70 | sinter: Command; 71 | sinterstore: Command; 72 | sunion: Command; 73 | sunionstore: Command; 74 | sdiff: Command; 75 | sdiffstore: Command; 76 | smembers: Command; 77 | 78 | zadd: Command; 79 | zincrby: Command; 80 | zrem: Command; 81 | zremrangebyscore: Command; 82 | zremrangebyrank: Command; 83 | zunionstore: Command; 84 | zinterstore: Command; 85 | zrange: Command; 86 | zrangebyscore: Command; 87 | zrevrangebyscore: Command; 88 | zcount: Command; 89 | zrevrange: Command; 90 | zcard: Command; 91 | zscore: Command; 92 | zrank: Command; 93 | zrevrank: Command; 94 | 95 | hset: Command; 96 | hsetnx: Command; 97 | hget: Command; 98 | hmset: Command; 99 | hmget: Command; 100 | hincrby: Command; 101 | hdel: Command; 102 | hlen: Command; 103 | hkeys: Command; 104 | hvals: Command; 105 | hgetall: Command; 106 | hexists: Command; 107 | 108 | incrby: Command; 109 | decrby: Command; 110 | getset: Command; 111 | mset: Command; 112 | msetnx: Command; 113 | randomkey: Command; 114 | select: Command; 115 | move: Command; 116 | rename: Command; 117 | renamenx: Command; 118 | expire: Command; 119 | expireat: Command; 120 | keys: Command; 121 | dbsize: Command; 122 | auth: Command; 123 | ping: Command; 124 | echo: Command; 125 | save: Command; 126 | bgsave: Command; 127 | bgrewriteaof: Command; 128 | shutdown: Command; 129 | lastsave: Command; 130 | type: Command; 131 | multi: Command; 132 | exec: Command; 133 | discard: Command; 134 | sync: Command; 135 | flushdb: Command; 136 | flushall: Command; 137 | sort: Command; 138 | info: Command; 139 | monitor: Command; 140 | ttl: Command; 141 | persist: Command; 142 | slaveof: Command; 143 | debug: Command; 144 | config: Command; 145 | subscribe: Command; 146 | unsubscribe: Command; 147 | psubscribe: Command; 148 | punsubscribe: Command; 149 | publish: Command; 150 | watch: Command; 151 | unwatch: Command; 152 | cluster: Command; 153 | restore: Command; 154 | migrate: Command; 155 | dump: Command; 156 | object: Command; 157 | client: Command; 158 | eval: Command; 159 | evalsha: Command; 160 | 161 | quit: Command; 162 | 163 | ///////////////// 164 | 165 | GET: Command; 166 | SET: Command; 167 | SETNX: Command; 168 | SETEX: Command; 169 | APPEND: Command; 170 | STRLEN: Command; 171 | DEL: Command; 172 | EXISTS: Command; 173 | SETBIT: Command; 174 | GETBIT: Command; 175 | SETRANGE: Command; 176 | GETRANGE: Command; 177 | SUBSTR: Command; 178 | INCR: Command; 179 | DECR: Command; 180 | MGET: Command; 181 | 182 | RPUSH: Command; 183 | LPUSH: Command; 184 | RPUSHX: Command; 185 | LPUSHX: Command; 186 | LINSERT: Command; 187 | RPOP: Command; 188 | LPOP: Command; 189 | BRPOP: Command; 190 | BRPOPLPUSH: Command; 191 | BLPOP: Command; 192 | LLEN: Command; 193 | LINDEX: Command; 194 | LSET: Command; 195 | LRANGE: Command; 196 | LTRIM: Command; 197 | LREM: Command; 198 | RPOPLPUSH: Command; 199 | 200 | SADD: Command; 201 | SREM: Command; 202 | SMOVE: Command; 203 | SISMEMBER: Command; 204 | SCARD: Command; 205 | SPOP: Command; 206 | SRANDMEMBER: Command; 207 | SINTER: Command; 208 | SINTERSTORE: Command; 209 | SUNION: Command; 210 | SUNIONSTORE: Command; 211 | SDIFF: Command; 212 | SDIFFSTORE: Command; 213 | SMEMBERS: Command; 214 | 215 | ZADD: Command; 216 | ZINCRBY: Command; 217 | ZREM: Command; 218 | ZREMRANGEBYSCORE: Command; 219 | ZREMRANGEBYRANK: Command; 220 | ZUNIONSTORE: Command; 221 | ZINTERSTORE: Command; 222 | ZRANGE: Command; 223 | ZRANGEBYSCORE: Command; 224 | ZREVRANGEBYSCORE: Command; 225 | ZCOUNT: Command; 226 | ZREVRANGE: Command; 227 | ZCARD: Command; 228 | ZSCORE: Command; 229 | ZRANK: Command; 230 | ZREVRANK: Command; 231 | 232 | HSET: Command; 233 | HSETNX: Command; 234 | HGET: Command; 235 | HMSET: Command; 236 | HMGET: Command; 237 | HINCRBY: Command; 238 | HDEL: Command; 239 | HLEN: Command; 240 | HKEYS: Command; 241 | HVALS: Command; 242 | HGETALL: Command; 243 | HEXISTS: Command; 244 | 245 | INCRBY: Command; 246 | DECRBY: Command; 247 | GETSET: Command; 248 | MSET: Command; 249 | MSETNX: Command; 250 | RANDOMKEY: Command; 251 | SELECT: Command; 252 | MOVE: Command; 253 | RENAME: Command; 254 | RENAMENX: Command; 255 | EXPIRE: Command; 256 | EXPIREAT: Command; 257 | KEYS: Command; 258 | DBSIZE: Command; 259 | AUTH: Command; 260 | PING: Command; 261 | ECHO: Command; 262 | SAVE: Command; 263 | BGSAVE: Command; 264 | BGREWRITEAOF: Command; 265 | SHUTDOWN: Command; 266 | LASTSAVE: Command; 267 | TYPE: Command; 268 | MULTI: Command; 269 | EXEC: Command; 270 | DISCARD: Command; 271 | SYNC: Command; 272 | FLUSHDB: Command; 273 | FLUSHALL: Command; 274 | SORT: Command; 275 | INFO: Command; 276 | MONITOR: Command; 277 | TTL: Command; 278 | PERSIST: Command; 279 | SLAVEOF: Command; 280 | DEBUG: Command; 281 | CONFIG: Command; 282 | SUBSCRIBE: Command; 283 | UNSUBSCRIBE: Command; 284 | PSUBSCRIBE: Command; 285 | PUNSUBSCRIBE: Command; 286 | PUBLISH: Command; 287 | WATCH: Command; 288 | UNWATCH: Command; 289 | CLUSTER: Command; 290 | RESTORE: Command; 291 | MIGRATE: Command; 292 | DUMP: Command; 293 | OBJECT: Command; 294 | CLIENT: Command; 295 | EVAL: Command; 296 | EVALSHA: Command; 297 | 298 | QUIT: Command; 299 | } 300 | 301 | interface Multi extends Commands { 302 | } 303 | 304 | interface RedisClient extends Commands { 305 | 306 | initialize_retry_vars(): void; 307 | flush_and_error(message: string): void; 308 | on_error(message: string): void; 309 | do_auth(): void; 310 | on_connect(): void; 311 | init_parser(): void; 312 | on_ready(): void; 313 | on_info_cmd(err, res): void; 314 | ready_check(): void; 315 | send_offline_queue(): void; 316 | connection_gone(why: string): void; 317 | on_data(data): void; 318 | return_error(err): void; 319 | return_reply(reply): void; 320 | send_command(command: string, args: any[], callback?: Function); 321 | send_command(command: string, ...args: any[]); 322 | pub_sub_command(command: { command: string; args: any[]; }); 323 | 324 | port: number; 325 | host: string; 326 | reply_parser; 327 | stream; 328 | 329 | server_info; 330 | connected: boolean; 331 | command_queue: any[]; 332 | offline_queue: any[]; 333 | retry_delay : number; 334 | retry_backoff: number; 335 | 336 | auth(password?: string, callback?: Function): void; 337 | AUTH(password?: string, callback?: Function): void; 338 | 339 | end(): RedisClient; 340 | 341 | on(eventName: string, callback: Function): void; 342 | once(eventName: string, callback: Function): void; 343 | removeListener(eventName: string, callback: Function): void; 344 | 345 | multi(commands?: any[]): Multi; 346 | MULTI(): Multi; 347 | } 348 | } -------------------------------------------------------------------------------- /lib/cqrs-typescript.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | import Redis = require('redis'); 5 | import Async = require('async'); 6 | 7 | export interface IEnvelope{ 8 | body : T; 9 | correlationId: string; 10 | messageId: string; 11 | TTL? : number; 12 | } 13 | 14 | export interface ICommand{ 15 | id: string; 16 | name : string 17 | } 18 | 19 | export interface ICommandHandler{ 20 | handleCommand(commandToHandle : IEnvelope, callback: (error)=>void): void; 21 | } 22 | 23 | export interface IEvent{ 24 | sourceId : string; 25 | name : string; 26 | } 27 | 28 | export interface IEventHandler{ 29 | handleEvent(eventToHandle : IEnvelope, callback: (error)=>void): void; 30 | } 31 | 32 | export class HandlerRegistry implements ICommandHandler, IEventHandler{ 33 | constructor(){ 34 | this.commandsRegistry = {}; 35 | this.eventsRegistry = {}; 36 | } 37 | 38 | commandsRegistry : any; 39 | eventsRegistry : any; 40 | 41 | registerCommandHandler(commandName: string, commandHandler : ICommandHandler){ 42 | var handlers = this.commandsRegistry[commandName]; 43 | if(!handlers){ 44 | handlers = []; 45 | } 46 | 47 | handlers.push(commandHandler); 48 | this.commandsRegistry[commandName] = handlers; 49 | } 50 | 51 | registerEventHandler(eventName: string, eventHandler : IEventHandler){ 52 | var handlers = this.eventsRegistry[eventName]; 53 | if(!handlers){ 54 | handlers = []; 55 | } 56 | 57 | handlers.push(eventHandler); 58 | this.eventsRegistry[eventName] = handlers; 59 | } 60 | 61 | handleCommand(commandToHandle : IEnvelope, callback: (error)=>void){ 62 | var handlers = this.commandsRegistry[commandToHandle.body.name]; 63 | if(!handlers) return callback(null); 64 | 65 | Async.forEach(handlers,function(handler : ICommandHandler, callback : (error:any)=>void){ 66 | handler.handleCommand(commandToHandle,callback); 67 | },callback); 68 | } 69 | 70 | handleEvent(eventToHandle : IEnvelope, callback: (error)=>void){ 71 | var handlers = this.eventsRegistry[eventToHandle.body.name]; 72 | if(!handlers) return callback(null); 73 | 74 | Async.forEach(handlers,function(handler : IEventHandler, callback : (error:any)=>void){ 75 | handler.handleEvent(eventToHandle,callback); 76 | },callback); 77 | } 78 | } 79 | 80 | export interface IVersionedEvent extends IEvent{ 81 | version : number; 82 | } 83 | 84 | export interface IEventSourced{ 85 | getId() : string; 86 | getVersion() : number; 87 | getEvents() : Array; 88 | } 89 | 90 | export class EventSourced implements IEventSourced { 91 | private id: string; 92 | private version : number; 93 | private events : Array; 94 | 95 | constructor(id : string){ 96 | this.id = id; 97 | this.events = new Array(); 98 | this.version = 0; 99 | } 100 | 101 | getId() : string{ 102 | return this.id; 103 | } 104 | 105 | getVersion() : number{ 106 | return this.version; 107 | } 108 | 109 | getEvents() : Array{ 110 | return this.events; 111 | } 112 | 113 | loadFromEvents(events : Array) : void{ 114 | var self = this; 115 | events.forEach(function(item){ 116 | self["on" + item.name](item); 117 | self.version = item.version; 118 | }); 119 | } 120 | 121 | update(versionedEvent : IVersionedEvent) : void{ 122 | versionedEvent.sourceId = this.id; 123 | versionedEvent.version = this.version + 1; 124 | this["on" + versionedEvent.name](versionedEvent); 125 | this.version = versionedEvent.version; 126 | this.events.push(versionedEvent); 127 | } 128 | } 129 | 130 | export class RedisResource { 131 | private client : Redis.RedisClient; 132 | 133 | constructor(options : IRedisConnectionOptions){ 134 | this.options = options; 135 | } 136 | 137 | options : IRedisConnectionOptions; 138 | 139 | getClient() : Redis.RedisClient{ 140 | return this.client; 141 | } 142 | 143 | connect(callback : (error)=>void ):void{ 144 | this.client = Redis.createClient(this.options.port, this.options.host); 145 | 146 | this.client.on('error', function(errorMessage){ 147 | if (errorMessage.indexOf && errorMessage.indexOf('connect') >= 0) { 148 | callback(errorMessage); 149 | } 150 | }); 151 | 152 | var self = this; 153 | this.client.on('ready', ()=>{ 154 | if(self['onConnected']){ 155 | self['onConnected'](); 156 | } 157 | 158 | callback(null); 159 | }); 160 | } 161 | } 162 | 163 | export class RedisCommandReceiver extends RedisResource{ 164 | constructor(options: IRedisConnectionOptions, commandReceiver : ICommandHandler){ 165 | super(options); 166 | this.commandReceiver = commandReceiver; 167 | } 168 | 169 | commandReceiver : ICommandHandler; 170 | paused : boolean; 171 | 172 | onConnected(){ 173 | var self = this; 174 | var receiveLoop = function(){ 175 | if(self.paused) return setTimeout(receiveLoop, 500); 176 | 177 | self.getClient().rpoplpush('messaging.queuedcommands','messaging.activecommands',function(error, result){ 178 | if(result){ 179 | var command = JSON.parse(result); 180 | return self.commandReceiver.handleCommand(command, (error)=>{ 181 | self.getClient().lrem('messaging.activecommands', 0, result,function(error, count){ 182 | if(count !== 1)throw "invalid count " + count; 183 | receiveLoop(); 184 | }); 185 | }); 186 | } 187 | 188 | setTimeout(receiveLoop, 500); 189 | }); 190 | }; 191 | 192 | receiveLoop(); 193 | } 194 | } 195 | 196 | export class RedisEventReceiver extends RedisResource{ 197 | constructor(options: IRedisConnectionOptions, eventReceiver : IEventHandler){ 198 | super(options); 199 | this.eventReceiver = eventReceiver; 200 | } 201 | 202 | eventReceiver : IEventHandler; 203 | paused : boolean; 204 | 205 | onConnected(){ 206 | var self = this; 207 | var receiveLoop = function(){ 208 | if(self.paused) return setTimeout(receiveLoop, 500); 209 | 210 | self.getClient().rpoplpush('messaging.queuedevents','messaging.activeevents',function(error, result){ 211 | if(result){ 212 | var _event = JSON.parse(result); 213 | return self.eventReceiver.handleEvent(_event, (error)=>{ 214 | self.getClient().lrem('messaging.activeevents', 0, result,function(error, count){ 215 | if(count !== 1) throw 'invalid "messaging.activeevents" count ' + count; 216 | receiveLoop(); 217 | }); 218 | }); 219 | } 220 | 221 | setTimeout(receiveLoop, 500); 222 | }); 223 | }; 224 | 225 | receiveLoop(); 226 | } 227 | } 228 | 229 | export class RedisCommandBus extends RedisResource implements ICommandHandler{ 230 | constructor(options : IRedisConnectionOptions){ 231 | super(options); 232 | } 233 | 234 | handleCommand(commandToHandle : IEnvelope, callback: (error)=>void): void{ 235 | var commandSerialized = JSON.stringify(commandToHandle); 236 | this.getClient().rpush('messaging.queuedcommands', commandSerialized, callback); 237 | } 238 | } 239 | 240 | export class RedisEventBus extends RedisResource implements IEventHandler{ 241 | constructor(options : IRedisConnectionOptions){ 242 | super(options); 243 | } 244 | 245 | handleEvent(eventToHandle : IEnvelope, callback: (error)=>void): void{ 246 | var eventSerialized = JSON.stringify(eventToHandle); 247 | this.getClient().rpush('messaging.queuedevents', eventSerialized, callback); 248 | } 249 | } 250 | 251 | export interface IEventSourcedRepository { 252 | getEventsByAggregateId(id : string, callback : (error : any, events : Array) => void); 253 | saveEventsByAggregateId(id : string, events : Array, callback: (error: any) => void); 254 | } 255 | 256 | export class InMemoryEventSourcedRepository implements IEventSourcedRepository{ 257 | private db : any; 258 | 259 | constructor(){ 260 | this.db = {}; 261 | } 262 | 263 | getEventsByAggregateId(id : string, callback : (error : any, events : Array) => void){ 264 | if(!this.db[id]) return callback(null,[]); 265 | 266 | var aggregateEvents = this.db[id]; 267 | callback(null,aggregateEvents); 268 | } 269 | 270 | saveEventsByAggregateId(id : string, events : Array, callback: (error: any) => void){ 271 | var aggregateEvents = this.db[id]; 272 | if(!aggregateEvents) aggregateEvents = []; 273 | aggregateEvents = aggregateEvents.concat(events); 274 | this.db[id] = aggregateEvents; 275 | callback(null); 276 | } 277 | } 278 | 279 | export interface IRedisConnectionOptions{ 280 | host:string; 281 | port:number; 282 | } 283 | 284 | export class EventSourceRepositoryWithNotifications implements IEventSourcedRepository{ 285 | constructor(repository: IEventSourcedRepository, onSaveCallback: (id : string, events : Array)=>void){ 286 | this.repository = repository; 287 | this.onSaveCallback = onSaveCallback; 288 | } 289 | 290 | repository : IEventSourcedRepository; 291 | onSaveCallback: (id : string, events : Array)=>void; 292 | 293 | getEventsByAggregateId(id : string, callback : (error : any, events : Array) => void){ 294 | this.repository.getEventsByAggregateId(id,callback); 295 | } 296 | 297 | saveEventsByAggregateId(id : string, events : Array, callback: (error: any) => void){ 298 | var self = this; 299 | this.repository.saveEventsByAggregateId(id,events,(error)=>{ 300 | if(!error){ 301 | self.onSaveCallback(id,events); 302 | } 303 | 304 | callback(error); 305 | }); 306 | } 307 | } 308 | 309 | export class RedisEventSourcedRepository extends RedisResource implements IEventSourcedRepository{ 310 | constructor(options : IRedisConnectionOptions){ 311 | super(options); 312 | } 313 | 314 | getEventsByAggregateId(id : string, callback : (error : any, events : Array) => void){ 315 | var self = this; 316 | this.getClient().lrange('eventsourcing.aggregate:' + id,0,-1, function(error, results){ 317 | self.constructResultsResponse(error, results, callback); 318 | }); 319 | } 320 | 321 | saveEventsByAggregateId(id : string, events : Array, callback: (error: any) => void){ 322 | if (!events || events.length === 0) { 323 | callback(null); 324 | return; 325 | } 326 | 327 | var self = this; 328 | Async.forEachSeries(events, function(versionedEvent : IVersionedEvent, callback : (error:any)=>void){ 329 | var serializedEvent = JSON.stringify(versionedEvent); 330 | self.getClient().rpush('eventsourcing.aggregate:' + versionedEvent.sourceId, serializedEvent, function(error){ 331 | if(error) return callback(error); 332 | callback(null); 333 | }); 334 | },callback); 335 | } 336 | 337 | private constructResultsResponse(error : any, results : Array, callback : (error: any, results: Array)=>void){ 338 | if(error) return callback(error,null); 339 | 340 | if (results && results.length > 0) { 341 | var arr = []; 342 | 343 | results.forEach(function(item) { 344 | arr.push(JSON.parse(item)); 345 | }); 346 | 347 | return callback(null, arr); 348 | } 349 | 350 | callback(null, []); 351 | } 352 | } 353 | -------------------------------------------------------------------------------- /lib/cqrs-typescript.js: -------------------------------------------------------------------------------- 1 | var __extends = this.__extends || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | __.prototype = b.prototype; 5 | d.prototype = new __(); 6 | }; 7 | /// 8 | /// 9 | /// 10 | var Redis = require('redis'); 11 | var Async = require('async'); 12 | 13 | var HandlerRegistry = (function () { 14 | function HandlerRegistry() { 15 | this.commandsRegistry = {}; 16 | this.eventsRegistry = {}; 17 | } 18 | HandlerRegistry.prototype.registerCommandHandler = function (commandName, commandHandler) { 19 | var handlers = this.commandsRegistry[commandName]; 20 | if (!handlers) { 21 | handlers = []; 22 | } 23 | 24 | handlers.push(commandHandler); 25 | this.commandsRegistry[commandName] = handlers; 26 | }; 27 | 28 | HandlerRegistry.prototype.registerEventHandler = function (eventName, eventHandler) { 29 | var handlers = this.eventsRegistry[eventName]; 30 | if (!handlers) { 31 | handlers = []; 32 | } 33 | 34 | handlers.push(eventHandler); 35 | this.eventsRegistry[eventName] = handlers; 36 | }; 37 | 38 | HandlerRegistry.prototype.handleCommand = function (commandToHandle, callback) { 39 | var handlers = this.commandsRegistry[commandToHandle.body.name]; 40 | if (!handlers) 41 | return callback(null); 42 | 43 | Async.forEach(handlers, function (handler, callback) { 44 | handler.handleCommand(commandToHandle, callback); 45 | }, callback); 46 | }; 47 | 48 | HandlerRegistry.prototype.handleEvent = function (eventToHandle, callback) { 49 | var handlers = this.eventsRegistry[eventToHandle.body.name]; 50 | if (!handlers) 51 | return callback(null); 52 | 53 | Async.forEach(handlers, function (handler, callback) { 54 | handler.handleEvent(eventToHandle, callback); 55 | }, callback); 56 | }; 57 | return HandlerRegistry; 58 | })(); 59 | exports.HandlerRegistry = HandlerRegistry; 60 | 61 | var EventSourced = (function () { 62 | function EventSourced(id) { 63 | this.id = id; 64 | this.events = new Array(); 65 | this.version = 0; 66 | } 67 | EventSourced.prototype.getId = function () { 68 | return this.id; 69 | }; 70 | 71 | EventSourced.prototype.getVersion = function () { 72 | return this.version; 73 | }; 74 | 75 | EventSourced.prototype.getEvents = function () { 76 | return this.events; 77 | }; 78 | 79 | EventSourced.prototype.loadFromEvents = function (events) { 80 | var self = this; 81 | events.forEach(function (item) { 82 | self["on" + item.name](item); 83 | self.version = item.version; 84 | }); 85 | }; 86 | 87 | EventSourced.prototype.update = function (versionedEvent) { 88 | versionedEvent.sourceId = this.id; 89 | versionedEvent.version = this.version + 1; 90 | this["on" + versionedEvent.name](versionedEvent); 91 | this.version = versionedEvent.version; 92 | this.events.push(versionedEvent); 93 | }; 94 | return EventSourced; 95 | })(); 96 | exports.EventSourced = EventSourced; 97 | 98 | var RedisResource = (function () { 99 | function RedisResource(options) { 100 | this.options = options; 101 | } 102 | RedisResource.prototype.getClient = function () { 103 | return this.client; 104 | }; 105 | 106 | RedisResource.prototype.connect = function (callback) { 107 | this.client = Redis.createClient(this.options.port, this.options.host); 108 | 109 | this.client.on('error', function (errorMessage) { 110 | if (errorMessage.indexOf && errorMessage.indexOf('connect') >= 0) { 111 | callback(errorMessage); 112 | } 113 | }); 114 | 115 | var self = this; 116 | this.client.on('ready', function () { 117 | if (self['onConnected']) { 118 | self['onConnected'](); 119 | } 120 | 121 | callback(null); 122 | }); 123 | }; 124 | return RedisResource; 125 | })(); 126 | exports.RedisResource = RedisResource; 127 | 128 | var RedisCommandReceiver = (function (_super) { 129 | __extends(RedisCommandReceiver, _super); 130 | function RedisCommandReceiver(options, commandReceiver) { 131 | _super.call(this, options); 132 | this.commandReceiver = commandReceiver; 133 | } 134 | RedisCommandReceiver.prototype.onConnected = function () { 135 | var self = this; 136 | var receiveLoop = function () { 137 | if (self.paused) 138 | return setTimeout(receiveLoop, 500); 139 | 140 | self.getClient().rpoplpush('messaging.queuedcommands', 'messaging.activecommands', function (error, result) { 141 | if (result) { 142 | var command = JSON.parse(result); 143 | return self.commandReceiver.handleCommand(command, function (error) { 144 | self.getClient().lrem('messaging.activecommands', 0, result, function (error, count) { 145 | if (count !== 1) 146 | throw "invalid count " + count; 147 | receiveLoop(); 148 | }); 149 | }); 150 | } 151 | 152 | setTimeout(receiveLoop, 500); 153 | }); 154 | }; 155 | 156 | receiveLoop(); 157 | }; 158 | return RedisCommandReceiver; 159 | })(RedisResource); 160 | exports.RedisCommandReceiver = RedisCommandReceiver; 161 | 162 | var RedisEventReceiver = (function (_super) { 163 | __extends(RedisEventReceiver, _super); 164 | function RedisEventReceiver(options, eventReceiver) { 165 | _super.call(this, options); 166 | this.eventReceiver = eventReceiver; 167 | } 168 | RedisEventReceiver.prototype.onConnected = function () { 169 | var self = this; 170 | var receiveLoop = function () { 171 | if (self.paused) 172 | return setTimeout(receiveLoop, 500); 173 | 174 | self.getClient().rpoplpush('messaging.queuedevents', 'messaging.activeevents', function (error, result) { 175 | if (result) { 176 | var _event = JSON.parse(result); 177 | return self.eventReceiver.handleEvent(_event, function (error) { 178 | self.getClient().lrem('messaging.activeevents', 0, result, function (error, count) { 179 | if (count !== 1) 180 | throw 'invalid "messaging.activeevents" count ' + count; 181 | receiveLoop(); 182 | }); 183 | }); 184 | } 185 | 186 | setTimeout(receiveLoop, 500); 187 | }); 188 | }; 189 | 190 | receiveLoop(); 191 | }; 192 | return RedisEventReceiver; 193 | })(RedisResource); 194 | exports.RedisEventReceiver = RedisEventReceiver; 195 | 196 | var RedisCommandBus = (function (_super) { 197 | __extends(RedisCommandBus, _super); 198 | function RedisCommandBus(options) { 199 | _super.call(this, options); 200 | } 201 | RedisCommandBus.prototype.handleCommand = function (commandToHandle, callback) { 202 | var commandSerialized = JSON.stringify(commandToHandle); 203 | this.getClient().rpush('messaging.queuedcommands', commandSerialized, callback); 204 | }; 205 | return RedisCommandBus; 206 | })(RedisResource); 207 | exports.RedisCommandBus = RedisCommandBus; 208 | 209 | var RedisEventBus = (function (_super) { 210 | __extends(RedisEventBus, _super); 211 | function RedisEventBus(options) { 212 | _super.call(this, options); 213 | } 214 | RedisEventBus.prototype.handleEvent = function (eventToHandle, callback) { 215 | var eventSerialized = JSON.stringify(eventToHandle); 216 | this.getClient().rpush('messaging.queuedevents', eventSerialized, callback); 217 | }; 218 | return RedisEventBus; 219 | })(RedisResource); 220 | exports.RedisEventBus = RedisEventBus; 221 | 222 | var InMemoryEventSourcedRepository = (function () { 223 | function InMemoryEventSourcedRepository() { 224 | this.db = {}; 225 | } 226 | InMemoryEventSourcedRepository.prototype.getEventsByAggregateId = function (id, callback) { 227 | if (!this.db[id]) 228 | return callback(null, []); 229 | 230 | var aggregateEvents = this.db[id]; 231 | callback(null, aggregateEvents); 232 | }; 233 | 234 | InMemoryEventSourcedRepository.prototype.saveEventsByAggregateId = function (id, events, callback) { 235 | var aggregateEvents = this.db[id]; 236 | if (!aggregateEvents) 237 | aggregateEvents = []; 238 | aggregateEvents = aggregateEvents.concat(events); 239 | this.db[id] = aggregateEvents; 240 | callback(null); 241 | }; 242 | return InMemoryEventSourcedRepository; 243 | })(); 244 | exports.InMemoryEventSourcedRepository = InMemoryEventSourcedRepository; 245 | 246 | var EventSourceRepositoryWithNotifications = (function () { 247 | function EventSourceRepositoryWithNotifications(repository, onSaveCallback) { 248 | this.repository = repository; 249 | this.onSaveCallback = onSaveCallback; 250 | } 251 | EventSourceRepositoryWithNotifications.prototype.getEventsByAggregateId = function (id, callback) { 252 | this.repository.getEventsByAggregateId(id, callback); 253 | }; 254 | 255 | EventSourceRepositoryWithNotifications.prototype.saveEventsByAggregateId = function (id, events, callback) { 256 | var self = this; 257 | this.repository.saveEventsByAggregateId(id, events, function (error) { 258 | if (!error) { 259 | self.onSaveCallback(id, events); 260 | } 261 | 262 | callback(error); 263 | }); 264 | }; 265 | return EventSourceRepositoryWithNotifications; 266 | })(); 267 | exports.EventSourceRepositoryWithNotifications = EventSourceRepositoryWithNotifications; 268 | 269 | var RedisEventSourcedRepository = (function (_super) { 270 | __extends(RedisEventSourcedRepository, _super); 271 | function RedisEventSourcedRepository(options) { 272 | _super.call(this, options); 273 | } 274 | RedisEventSourcedRepository.prototype.getEventsByAggregateId = function (id, callback) { 275 | var self = this; 276 | this.getClient().lrange('eventsourcing.aggregate:' + id, 0, -1, function (error, results) { 277 | self.constructResultsResponse(error, results, callback); 278 | }); 279 | }; 280 | 281 | RedisEventSourcedRepository.prototype.saveEventsByAggregateId = function (id, events, callback) { 282 | if (!events || events.length === 0) { 283 | callback(null); 284 | return; 285 | } 286 | 287 | var self = this; 288 | Async.forEachSeries(events, function (versionedEvent, callback) { 289 | var serializedEvent = JSON.stringify(versionedEvent); 290 | self.getClient().rpush('eventsourcing.aggregate:' + versionedEvent.sourceId, serializedEvent, function (error) { 291 | if (error) 292 | return callback(error); 293 | callback(null); 294 | }); 295 | }, callback); 296 | }; 297 | 298 | RedisEventSourcedRepository.prototype.constructResultsResponse = function (error, results, callback) { 299 | if (error) 300 | return callback(error, null); 301 | 302 | if (results && results.length > 0) { 303 | var arr = []; 304 | 305 | results.forEach(function (item) { 306 | arr.push(JSON.parse(item)); 307 | }); 308 | 309 | return callback(null, arr); 310 | } 311 | 312 | callback(null, []); 313 | }; 314 | return RedisEventSourcedRepository; 315 | })(RedisResource); 316 | exports.RedisEventSourcedRepository = RedisEventSourcedRepository; 317 | -------------------------------------------------------------------------------- /test/CQRSTest.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | /*global describe, it, import */ 5 | /*jslint node: true */ 6 | import CQRS = require('../lib/cqrs-typescript'); 7 | import should = require('should'); 8 | should.equal('actual', 'actual'); 9 | 10 | interface ICreditAccountEvent extends CQRS.IVersionedEvent{ 11 | amount:number 12 | } 13 | 14 | interface IDebitAccountEvent extends CQRS.IVersionedEvent{ 15 | amount:number 16 | } 17 | 18 | class BankAccount extends CQRS.EventSourced{ 19 | constructor(id :string){ 20 | super(id); 21 | this.balance = 0; 22 | } 23 | 24 | balance : number; 25 | 26 | credit(amount:number) : void { 27 | this.update({ 28 | name: 'CreditAccount', 29 | amount: amount, 30 | version: -1, 31 | sourceId: '' 32 | }); 33 | } 34 | 35 | debit(amount:number) : void{ 36 | this.update({ 37 | name: 'DebitAccount', 38 | amount: amount, 39 | version: -1, 40 | sourceId: '' 41 | }); 42 | } 43 | 44 | private onCreditAccount(e : ICreditAccountEvent):void{ 45 | this.balance += e.amount; 46 | } 47 | 48 | private onDebitAccount(e : IDebitAccountEvent):void{ 49 | this.balance -= e.amount; 50 | } 51 | } 52 | 53 | class TestCommand implements CQRS.ICommand{ 54 | constructor(message: string){ 55 | this.name = 'TestCommand'; 56 | this.message = message; 57 | } 58 | 59 | id :string; 60 | name: string; 61 | message : string; 62 | } 63 | 64 | class TestCommandHandler implements CQRS.ICommandHandler{ 65 | handleCommand(commandToHandle : CQRS.IEnvelope, callback: (error)=>void): void{ 66 | commandToHandle.body.name.should.be.exactly('TestCommand'); 67 | commandToHandle.body.message.should.be.exactly('hello world'); 68 | callback(null); 69 | } 70 | }; 71 | 72 | class RedisCommandReceiverTestHandler implements CQRS.ICommandHandler{ 73 | constructor(done){ 74 | this.done = done; 75 | this.callCount = 0; 76 | } 77 | 78 | done : ()=>void; 79 | callCount : number; 80 | handleCommand(commandToHandle : CQRS.IEnvelope, callback: (error)=>void): void{ 81 | callback(null); 82 | this.done(); 83 | } 84 | } 85 | 86 | class RedisEventReceiverTestHandler implements CQRS.IEventHandler{ 87 | constructor(done, expectedMessage){ 88 | this.done = done; 89 | this.callCount = 0; 90 | this.expectedMessage = expectedMessage; 91 | } 92 | 93 | expectedMessage : string; 94 | done : ()=>void; 95 | callCount : number; 96 | handleEvent(eventToHandle : CQRS.IEnvelope, callback: (error)=>void): void{ 97 | eventToHandle.body.message.should.be.exactly(this.expectedMessage); 98 | callback(null); 99 | this.done(); 100 | } 101 | } 102 | 103 | class TestEventMessageReceived implements CQRS.IEvent{ 104 | constructor(message: string){ 105 | this.name = 'TestEventMessageReceived'; 106 | this.message = message; 107 | } 108 | 109 | sourceId :string; 110 | name: string; 111 | message : string; 112 | } 113 | 114 | class TestEventMessageReceivedHandler implements CQRS.IEventHandler{ 115 | handleEvent(eventToHandle : CQRS.IEnvelope, callback: (error)=>void): void{ 116 | eventToHandle.body.name.should.be.exactly('TestEventMessageReceived'); 117 | eventToHandle.body.message.should.be.exactly('hello world'); 118 | callback(null); 119 | } 120 | }; 121 | 122 | describe('CQRS Tests', function() { 123 | describe('Core Tests', function(){ 124 | var account :BankAccount; 125 | 126 | describe('extending from "EventSourced" to create a "bank account"',function(){ 127 | it('should be ok to create one once supplying an id ', function() { 128 | account = new BankAccount('1'); 129 | }); 130 | 131 | it('should be ok to credit the account to 100 by raising an event',function(){ 132 | account.credit(100); 133 | account.balance.should.be.exactly(100); 134 | account.getEvents().length.should.be.exactly(1); 135 | account.getVersion().should.be.exactly(1); 136 | }); 137 | 138 | it('should be ok to credit the account to 150 by raising an event',function(){ 139 | account.credit(50); 140 | account.balance.should.be.exactly(150); 141 | account.getEvents().length.should.be.exactly(2); 142 | account.getVersion().should.be.exactly(2); 143 | }); 144 | 145 | it('should be ok to debit the account by 100 by raising an event',function(){ 146 | account.debit(100); 147 | account.balance.should.be.exactly(50); 148 | account.getEvents().length.should.be.exactly(3); 149 | account.getVersion().should.be.exactly(3); 150 | }); 151 | 152 | it('should be ok to load a bank account from an event stream',function(){ 153 | var accountFromEvents = new BankAccount('1'); 154 | var events = account.getEvents(); 155 | accountFromEvents.loadFromEvents(events); 156 | accountFromEvents.balance.should.be.exactly(account.balance); 157 | accountFromEvents.getVersion().should.be.exactly(account.getVersion()); 158 | }); 159 | }); 160 | 161 | describe('using an in memory "event sourced" repository',function(){ 162 | var provider = new CQRS.InMemoryEventSourcedRepository(); 163 | 164 | it('should be able to save events in memory',function(done){ 165 | provider.saveEventsByAggregateId(account.getId(), account.getEvents(), (error)=>{ 166 | should.equal(error,null); 167 | done(); 168 | }); 169 | }); 170 | 171 | it('should be able to load events previously saved',function(done){ 172 | provider.getEventsByAggregateId(account.getId(), (error, events)=>{ 173 | events.should.be.an.Array; 174 | events.length.should.be.exactly(account.getEvents().length); 175 | done(); 176 | }); 177 | }); 178 | 179 | it('should be possible to load a bank account from events loaded from the repository',function(done){ 180 | provider.getEventsByAggregateId(account.getId(), (error, events)=>{ 181 | should.equal(error, null); 182 | var accountFromEvents = new BankAccount(account.getId()); 183 | accountFromEvents.loadFromEvents(events); 184 | accountFromEvents.balance.should.be.exactly(account.balance); 185 | done(); 186 | }); 187 | }); 188 | }); 189 | 190 | describe('Handler registry', function(){ 191 | var registry = new CQRS.HandlerRegistry(); 192 | 193 | describe('command registration',function(){ 194 | var testCommandHandler = new TestCommandHandler(); 195 | var commandName = 'TestCommand'; 196 | 197 | it('should be possible to register a command handler', function(){ 198 | registry.registerCommandHandler(commandName, testCommandHandler); 199 | var handlers = registry.commandsRegistry[commandName]; 200 | handlers.length.should.be.exactly(1); 201 | }); 202 | 203 | it('should be possible to execute a command handler having sending a command through the "HandlerRegistry"',function(done){ 204 | var testCommand = new TestCommand('hello world'); 205 | testCommand.id = "1"; 206 | registry.handleCommand({ 207 | messageId : "1", 208 | correlationId : "1", 209 | body: testCommand 210 | },(error)=>{ 211 | should.equal(error, null); 212 | done(); 213 | }); 214 | }); 215 | }); 216 | 217 | describe('event registration',function(){ 218 | var testEventHandler = new TestEventMessageReceivedHandler(); 219 | var eventName = 'TestEventMessageReceived'; 220 | 221 | it('should be possible to register an event handler', function(){ 222 | registry.registerEventHandler(eventName, testEventHandler); 223 | var handlers = registry.eventsRegistry[eventName]; 224 | handlers.length.should.be.exactly(1); 225 | }); 226 | 227 | it('should be possible to execute an event handler having sending an event through the "HandlerRegistry"',function(done){ 228 | var testEvent = new TestEventMessageReceived('hello world'); 229 | testEvent.sourceId = "1"; 230 | registry.handleEvent({ 231 | messageId : "1", 232 | correlationId : "1", 233 | body: testEvent 234 | },(error)=>{ 235 | should.equal(error, null); 236 | done(); 237 | }); 238 | }); 239 | }); 240 | }); 241 | }); 242 | 243 | describe('Infrastructure tests',function(){ 244 | describe('Redis event sourced repository',function(){ 245 | var account = new BankAccount('2'); 246 | account.credit(100); 247 | account.credit(100); 248 | account.debit(50); 249 | account.credit(100); 250 | account.debit(200); 251 | account.balance.should.be.exactly(50); 252 | 253 | var provider = new CQRS.RedisEventSourcedRepository({ host: "127.0.0.1", port:6379}); 254 | it('should connect to a specified Redis server',function(done){ 255 | provider.connect((error)=>{ 256 | should.equal(error, null); 257 | done(); 258 | }); 259 | }); 260 | 261 | it('should be able to persist an event stream for an given aggregate id',function(done){ 262 | var events = account.getEvents(); 263 | events.length.should.be.exactly(5); 264 | provider.saveEventsByAggregateId(account.getId(),events, (error)=>{ 265 | should.equal(error, null); 266 | done(); 267 | }); 268 | }); 269 | 270 | it('should be able to retrieve an event stream by aggregate id and recreate an aggregate instance',function(done){ 271 | provider.getEventsByAggregateId(account.getId(),(error, events)=>{ 272 | should.equal(error, null); 273 | events.length.should.be.exactly(5); 274 | 275 | var accountFromEvents = new BankAccount(account.getId()); 276 | accountFromEvents.loadFromEvents(events); 277 | accountFromEvents.balance.should.be.exactly(account.balance); 278 | accountFromEvents.getEvents().length.should.be.exactly(0); 279 | done(); 280 | }); 281 | }); 282 | 283 | describe('using an "EventSourceRepositoryWithNotifications"',function(){ 284 | it('should be able to persist an event can get notified via a callback',function(done){ 285 | var eventSourceRepositoryWithNotifications = new CQRS.EventSourceRepositoryWithNotifications( 286 | provider, (id:string, events : Array)=>{ 287 | id.should.be.exactly('2'); 288 | events.length.should.be.exactly(2); 289 | events[1].amount.should.be.exactly(70); 290 | done(); 291 | } 292 | ); 293 | 294 | var accountFromEvents = new BankAccount(account.getId()); 295 | accountFromEvents.loadFromEvents(account.getEvents()); 296 | accountFromEvents.balance.should.be.exactly(account.balance); 297 | accountFromEvents.getEvents().length.should.be.exactly(0); 298 | 299 | accountFromEvents.credit(230); 300 | accountFromEvents.credit(70); 301 | accountFromEvents.getEvents().length.should.be.exactly(2); 302 | 303 | eventSourceRepositoryWithNotifications.saveEventsByAggregateId(accountFromEvents.getId(),accountFromEvents.getEvents(), (error)=>{ 304 | should.equal(error, null); 305 | }); 306 | }); 307 | }); 308 | 309 | after(function(done){ 310 | provider.getClient().del('eventsourcing.aggregate:' + account.getId(),(error)=>{ 311 | should.equal(error, null); 312 | done(); 313 | }); 314 | }); 315 | }); 316 | 317 | describe('Redis command bus',function(){ 318 | var redisCommandBus = new CQRS.RedisCommandBus({ host: "127.0.0.1", port:6379}); 319 | it('should connect to a specified Redis server',function(done){ 320 | redisCommandBus.connect((error)=>{ 321 | should.equal(error, null); 322 | done(); 323 | }); 324 | }); 325 | 326 | it('should be possible to persist a command into Redis in the pending commands list',function(done){ 327 | var testCommand = new TestCommand('hello world'); 328 | testCommand.id = "1"; 329 | redisCommandBus.handleCommand({ 330 | messageId : "1", 331 | correlationId : "1", 332 | body: testCommand 333 | },(error)=>{ 334 | should.equal(error, null); 335 | 336 | redisCommandBus.getClient().lrange('messaging.queuedcommands', 0, -1, function(error, results){ 337 | should.equal(error, null); 338 | results.length.should.be.exactly(1); 339 | var commandSerialized = results[0]; 340 | var command = JSON.parse(commandSerialized); 341 | command.body.message.should.be.exactly(testCommand.message); 342 | done(); 343 | }); 344 | }); 345 | }); 346 | 347 | it('should be possible to persist another command into Redis in the pending commands list',function(done){ 348 | var testCommand = new TestCommand('hello world2'); 349 | testCommand.id = "1"; 350 | redisCommandBus.handleCommand({ 351 | messageId : "1", 352 | correlationId : "1", 353 | body: testCommand 354 | },(error)=>{ 355 | should.equal(error, null); 356 | 357 | redisCommandBus.getClient().lrange('messaging.queuedcommands', 0, -1, function(error, results){ 358 | should.equal(error, null); 359 | results.length.should.be.exactly(2); 360 | var commandSerialized = results[1]; 361 | var command = JSON.parse(commandSerialized); 362 | command.body.message.should.be.exactly(testCommand.message); 363 | done(); 364 | }); 365 | }); 366 | }); 367 | 368 | describe('using the "RedisCommandReceiver"',function(){ 369 | it('should be possible to receive pending commands using the "RedisCommandReceiver"',function(done){ 370 | var redisCommandReceiverTestHandler = new RedisCommandReceiverTestHandler(()=>{ 371 | redisCommandReceiverTestHandler.callCount +=1; 372 | if(redisCommandReceiverTestHandler.callCount == 2) return done(); 373 | }); 374 | 375 | var redisCommandReceiver = new CQRS.RedisCommandReceiver( 376 | { host: "127.0.0.1", port:6379}, 377 | redisCommandReceiverTestHandler); 378 | 379 | redisCommandReceiver.connect((error)=>{ 380 | should.equal(error, null); 381 | }); 382 | }); 383 | }); 384 | 385 | after(function(done){ 386 | redisCommandBus.getClient().del('messaging.queuedcommands',(error)=>{ 387 | should.equal(error, null); 388 | done(); 389 | }); 390 | }); 391 | }); 392 | 393 | 394 | describe('Redis event bus',function(){ 395 | var redisEventBus = new CQRS.RedisEventBus({ host: "127.0.0.1", port:6379}); 396 | it('should connect to a specified Redis server',function(done){ 397 | redisEventBus.connect((error)=>{ 398 | should.equal(error, null); 399 | done(); 400 | }); 401 | }); 402 | 403 | it('should be possible to persist an event into Redis in the pending commands list',function(done){ 404 | var testEvent = new TestEventMessageReceived('hello world'); 405 | testEvent.sourceId = "1"; 406 | redisEventBus.handleEvent({ 407 | messageId : "1", 408 | correlationId : "1", 409 | body: testEvent 410 | },(error)=>{ 411 | should.equal(error, null); 412 | 413 | redisEventBus.getClient().lrange('messaging.queuedevents', 0, -1, function(error, results){ 414 | should.equal(error, null); 415 | results.length.should.be.exactly(1); 416 | var eventSerialized = results[0]; 417 | var _event = JSON.parse(eventSerialized); 418 | _event.body.message.should.be.exactly(testEvent.message); 419 | done(); 420 | }); 421 | }); 422 | }); 423 | 424 | it('should be possible to persist another event into Redis in the pending commands list',function(done){ 425 | var testEvent = new TestEventMessageReceived('hello world'); 426 | testEvent.sourceId = "1"; 427 | redisEventBus.handleEvent({ 428 | messageId : "1", 429 | correlationId : "1", 430 | body: testEvent 431 | },(error)=>{ 432 | should.equal(error, null); 433 | 434 | redisEventBus.getClient().lrange('messaging.queuedevents', 0, -1, function(error, results){ 435 | should.equal(error, null); 436 | results.length.should.be.exactly(2); 437 | var eventSerialized = results[0]; 438 | var _event = JSON.parse(eventSerialized); 439 | _event.body.message.should.be.exactly(testEvent.message); 440 | done(); 441 | }); 442 | }); 443 | }); 444 | 445 | describe('using the "RedisEventReceiver"',function(){ 446 | it('should be possible to receive pending events using the "RedisEventReceiver"',function(done){ 447 | var redisEventReceiverTestHandler = new RedisEventReceiverTestHandler(()=>{ 448 | redisEventReceiverTestHandler.callCount +=1; 449 | if(redisEventReceiverTestHandler.callCount == 2) return done(); 450 | },'hello world'); 451 | 452 | var redisEventReceiver = new CQRS.RedisEventReceiver( 453 | { host: "127.0.0.1", port:6379}, 454 | redisEventReceiverTestHandler); 455 | 456 | redisEventReceiver.connect((error)=>{ 457 | should.equal(error, null); 458 | }); 459 | }); 460 | }); 461 | 462 | after(function(done){ 463 | redisEventBus.getClient().del('messaging.queuedevents',(error)=>{ 464 | should.equal(error, null); 465 | done(); 466 | }); 467 | }); 468 | }); 469 | }); 470 | }); 471 | -------------------------------------------------------------------------------- /test/CQRSTest.js: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | var __extends = this.__extends || function (d, b) { 4 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 5 | function __() { this.constructor = d; } 6 | __.prototype = b.prototype; 7 | d.prototype = new __(); 8 | }; 9 | /*global describe, it, import */ 10 | /*jslint node: true */ 11 | var CQRS = require('../lib/cqrs-typescript'); 12 | var should = require('should'); 13 | should.equal('actual', 'actual'); 14 | 15 | var BankAccount = (function (_super) { 16 | __extends(BankAccount, _super); 17 | function BankAccount(id) { 18 | _super.call(this, id); 19 | this.balance = 0; 20 | } 21 | BankAccount.prototype.credit = function (amount) { 22 | this.update({ 23 | name: 'CreditAccount', 24 | amount: amount, 25 | version: -1, 26 | sourceId: '' 27 | }); 28 | }; 29 | 30 | BankAccount.prototype.debit = function (amount) { 31 | this.update({ 32 | name: 'DebitAccount', 33 | amount: amount, 34 | version: -1, 35 | sourceId: '' 36 | }); 37 | }; 38 | 39 | BankAccount.prototype.onCreditAccount = function (e) { 40 | this.balance += e.amount; 41 | }; 42 | 43 | BankAccount.prototype.onDebitAccount = function (e) { 44 | this.balance -= e.amount; 45 | }; 46 | return BankAccount; 47 | })(CQRS.EventSourced); 48 | 49 | var TestCommand = (function () { 50 | function TestCommand(message) { 51 | this.name = 'TestCommand'; 52 | this.message = message; 53 | } 54 | return TestCommand; 55 | })(); 56 | 57 | var TestCommandHandler = (function () { 58 | function TestCommandHandler() { 59 | } 60 | TestCommandHandler.prototype.handleCommand = function (commandToHandle, callback) { 61 | commandToHandle.body.name.should.be.exactly('TestCommand'); 62 | commandToHandle.body.message.should.be.exactly('hello world'); 63 | callback(null); 64 | }; 65 | return TestCommandHandler; 66 | })(); 67 | ; 68 | 69 | var RedisCommandReceiverTestHandler = (function () { 70 | function RedisCommandReceiverTestHandler(done) { 71 | this.done = done; 72 | this.callCount = 0; 73 | } 74 | RedisCommandReceiverTestHandler.prototype.handleCommand = function (commandToHandle, callback) { 75 | callback(null); 76 | this.done(); 77 | }; 78 | return RedisCommandReceiverTestHandler; 79 | })(); 80 | 81 | var RedisEventReceiverTestHandler = (function () { 82 | function RedisEventReceiverTestHandler(done, expectedMessage) { 83 | this.done = done; 84 | this.callCount = 0; 85 | this.expectedMessage = expectedMessage; 86 | } 87 | RedisEventReceiverTestHandler.prototype.handleEvent = function (eventToHandle, callback) { 88 | eventToHandle.body.message.should.be.exactly(this.expectedMessage); 89 | callback(null); 90 | this.done(); 91 | }; 92 | return RedisEventReceiverTestHandler; 93 | })(); 94 | 95 | var TestEventMessageReceived = (function () { 96 | function TestEventMessageReceived(message) { 97 | this.name = 'TestEventMessageReceived'; 98 | this.message = message; 99 | } 100 | return TestEventMessageReceived; 101 | })(); 102 | 103 | var TestEventMessageReceivedHandler = (function () { 104 | function TestEventMessageReceivedHandler() { 105 | } 106 | TestEventMessageReceivedHandler.prototype.handleEvent = function (eventToHandle, callback) { 107 | eventToHandle.body.name.should.be.exactly('TestEventMessageReceived'); 108 | eventToHandle.body.message.should.be.exactly('hello world'); 109 | callback(null); 110 | }; 111 | return TestEventMessageReceivedHandler; 112 | })(); 113 | ; 114 | 115 | describe('CQRS Tests', function () { 116 | describe('Core Tests', function () { 117 | var account; 118 | 119 | describe('extending from "EventSourced" to create a "bank account"', function () { 120 | it('should be ok to create one once supplying an id ', function () { 121 | account = new BankAccount('1'); 122 | }); 123 | 124 | it('should be ok to credit the account to 100 by raising an event', function () { 125 | account.credit(100); 126 | account.balance.should.be.exactly(100); 127 | account.getEvents().length.should.be.exactly(1); 128 | account.getVersion().should.be.exactly(1); 129 | }); 130 | 131 | it('should be ok to credit the account to 150 by raising an event', function () { 132 | account.credit(50); 133 | account.balance.should.be.exactly(150); 134 | account.getEvents().length.should.be.exactly(2); 135 | account.getVersion().should.be.exactly(2); 136 | }); 137 | 138 | it('should be ok to debit the account by 100 by raising an event', function () { 139 | account.debit(100); 140 | account.balance.should.be.exactly(50); 141 | account.getEvents().length.should.be.exactly(3); 142 | account.getVersion().should.be.exactly(3); 143 | }); 144 | 145 | it('should be ok to load a bank account from an event stream', function () { 146 | var accountFromEvents = new BankAccount('1'); 147 | var events = account.getEvents(); 148 | accountFromEvents.loadFromEvents(events); 149 | accountFromEvents.balance.should.be.exactly(account.balance); 150 | accountFromEvents.getVersion().should.be.exactly(account.getVersion()); 151 | }); 152 | }); 153 | 154 | describe('using an in memory "event sourced" repository', function () { 155 | var provider = new CQRS.InMemoryEventSourcedRepository(); 156 | 157 | it('should be able to save events in memory', function (done) { 158 | provider.saveEventsByAggregateId(account.getId(), account.getEvents(), function (error) { 159 | should.equal(error, null); 160 | done(); 161 | }); 162 | }); 163 | 164 | it('should be able to load events previously saved', function (done) { 165 | provider.getEventsByAggregateId(account.getId(), function (error, events) { 166 | events.should.be.an.Array; 167 | events.length.should.be.exactly(account.getEvents().length); 168 | done(); 169 | }); 170 | }); 171 | 172 | it('should be possible to load a bank account from events loaded from the repository', function (done) { 173 | provider.getEventsByAggregateId(account.getId(), function (error, events) { 174 | should.equal(error, null); 175 | var accountFromEvents = new BankAccount(account.getId()); 176 | accountFromEvents.loadFromEvents(events); 177 | accountFromEvents.balance.should.be.exactly(account.balance); 178 | done(); 179 | }); 180 | }); 181 | }); 182 | 183 | describe('Handler registry', function () { 184 | var registry = new CQRS.HandlerRegistry(); 185 | 186 | describe('command registration', function () { 187 | var testCommandHandler = new TestCommandHandler(); 188 | var commandName = 'TestCommand'; 189 | 190 | it('should be possible to register a command handler', function () { 191 | registry.registerCommandHandler(commandName, testCommandHandler); 192 | var handlers = registry.commandsRegistry[commandName]; 193 | handlers.length.should.be.exactly(1); 194 | }); 195 | 196 | it('should be possible to execute a command handler having sending a command through the "HandlerRegistry"', function (done) { 197 | var testCommand = new TestCommand('hello world'); 198 | testCommand.id = "1"; 199 | registry.handleCommand({ 200 | messageId: "1", 201 | correlationId: "1", 202 | body: testCommand 203 | }, function (error) { 204 | should.equal(error, null); 205 | done(); 206 | }); 207 | }); 208 | }); 209 | 210 | describe('event registration', function () { 211 | var testEventHandler = new TestEventMessageReceivedHandler(); 212 | var eventName = 'TestEventMessageReceived'; 213 | 214 | it('should be possible to register an event handler', function () { 215 | registry.registerEventHandler(eventName, testEventHandler); 216 | var handlers = registry.eventsRegistry[eventName]; 217 | handlers.length.should.be.exactly(1); 218 | }); 219 | 220 | it('should be possible to execute an event handler having sending an event through the "HandlerRegistry"', function (done) { 221 | var testEvent = new TestEventMessageReceived('hello world'); 222 | testEvent.sourceId = "1"; 223 | registry.handleEvent({ 224 | messageId: "1", 225 | correlationId: "1", 226 | body: testEvent 227 | }, function (error) { 228 | should.equal(error, null); 229 | done(); 230 | }); 231 | }); 232 | }); 233 | }); 234 | }); 235 | 236 | describe('Infrastructure tests', function () { 237 | describe('Redis event sourced repository', function () { 238 | var account = new BankAccount('2'); 239 | account.credit(100); 240 | account.credit(100); 241 | account.debit(50); 242 | account.credit(100); 243 | account.debit(200); 244 | account.balance.should.be.exactly(50); 245 | 246 | var provider = new CQRS.RedisEventSourcedRepository({ host: "127.0.0.1", port: 6379 }); 247 | it('should connect to a specified Redis server', function (done) { 248 | provider.connect(function (error) { 249 | should.equal(error, null); 250 | done(); 251 | }); 252 | }); 253 | 254 | it('should be able to persist an event stream for an given aggregate id', function (done) { 255 | var events = account.getEvents(); 256 | events.length.should.be.exactly(5); 257 | provider.saveEventsByAggregateId(account.getId(), events, function (error) { 258 | should.equal(error, null); 259 | done(); 260 | }); 261 | }); 262 | 263 | it('should be able to retrieve an event stream by aggregate id and recreate an aggregate instance', function (done) { 264 | provider.getEventsByAggregateId(account.getId(), function (error, events) { 265 | should.equal(error, null); 266 | events.length.should.be.exactly(5); 267 | 268 | var accountFromEvents = new BankAccount(account.getId()); 269 | accountFromEvents.loadFromEvents(events); 270 | accountFromEvents.balance.should.be.exactly(account.balance); 271 | accountFromEvents.getEvents().length.should.be.exactly(0); 272 | done(); 273 | }); 274 | }); 275 | 276 | describe('using an "EventSourceRepositoryWithNotifications"', function () { 277 | it('should be able to persist an event can get notified via a callback', function (done) { 278 | var eventSourceRepositoryWithNotifications = new CQRS.EventSourceRepositoryWithNotifications(provider, function (id, events) { 279 | id.should.be.exactly('2'); 280 | events.length.should.be.exactly(2); 281 | events[1].amount.should.be.exactly(70); 282 | done(); 283 | }); 284 | 285 | var accountFromEvents = new BankAccount(account.getId()); 286 | accountFromEvents.loadFromEvents(account.getEvents()); 287 | accountFromEvents.balance.should.be.exactly(account.balance); 288 | accountFromEvents.getEvents().length.should.be.exactly(0); 289 | 290 | accountFromEvents.credit(230); 291 | accountFromEvents.credit(70); 292 | accountFromEvents.getEvents().length.should.be.exactly(2); 293 | 294 | eventSourceRepositoryWithNotifications.saveEventsByAggregateId(accountFromEvents.getId(), accountFromEvents.getEvents(), function (error) { 295 | should.equal(error, null); 296 | }); 297 | }); 298 | }); 299 | 300 | after(function (done) { 301 | provider.getClient().del('eventsourcing.aggregate:' + account.getId(), function (error) { 302 | should.equal(error, null); 303 | done(); 304 | }); 305 | }); 306 | }); 307 | 308 | describe('Redis command bus', function () { 309 | var redisCommandBus = new CQRS.RedisCommandBus({ host: "127.0.0.1", port: 6379 }); 310 | it('should connect to a specified Redis server', function (done) { 311 | redisCommandBus.connect(function (error) { 312 | should.equal(error, null); 313 | done(); 314 | }); 315 | }); 316 | 317 | it('should be possible to persist a command into Redis in the pending commands list', function (done) { 318 | var testCommand = new TestCommand('hello world'); 319 | testCommand.id = "1"; 320 | redisCommandBus.handleCommand({ 321 | messageId: "1", 322 | correlationId: "1", 323 | body: testCommand 324 | }, function (error) { 325 | should.equal(error, null); 326 | 327 | redisCommandBus.getClient().lrange('messaging.queuedcommands', 0, -1, function (error, results) { 328 | should.equal(error, null); 329 | results.length.should.be.exactly(1); 330 | var commandSerialized = results[0]; 331 | var command = JSON.parse(commandSerialized); 332 | command.body.message.should.be.exactly(testCommand.message); 333 | done(); 334 | }); 335 | }); 336 | }); 337 | 338 | it('should be possible to persist another command into Redis in the pending commands list', function (done) { 339 | var testCommand = new TestCommand('hello world2'); 340 | testCommand.id = "1"; 341 | redisCommandBus.handleCommand({ 342 | messageId: "1", 343 | correlationId: "1", 344 | body: testCommand 345 | }, function (error) { 346 | should.equal(error, null); 347 | 348 | redisCommandBus.getClient().lrange('messaging.queuedcommands', 0, -1, function (error, results) { 349 | should.equal(error, null); 350 | results.length.should.be.exactly(2); 351 | var commandSerialized = results[1]; 352 | var command = JSON.parse(commandSerialized); 353 | command.body.message.should.be.exactly(testCommand.message); 354 | done(); 355 | }); 356 | }); 357 | }); 358 | 359 | describe('using the "RedisCommandReceiver"', function () { 360 | it('should be possible to receive pending commands using the "RedisCommandReceiver"', function (done) { 361 | var redisCommandReceiverTestHandler = new RedisCommandReceiverTestHandler(function () { 362 | redisCommandReceiverTestHandler.callCount += 1; 363 | if (redisCommandReceiverTestHandler.callCount == 2) 364 | return done(); 365 | }); 366 | 367 | var redisCommandReceiver = new CQRS.RedisCommandReceiver({ host: "127.0.0.1", port: 6379 }, redisCommandReceiverTestHandler); 368 | 369 | redisCommandReceiver.connect(function (error) { 370 | should.equal(error, null); 371 | }); 372 | }); 373 | }); 374 | 375 | after(function (done) { 376 | redisCommandBus.getClient().del('messaging.queuedcommands', function (error) { 377 | should.equal(error, null); 378 | done(); 379 | }); 380 | }); 381 | }); 382 | 383 | describe('Redis event bus', function () { 384 | var redisEventBus = new CQRS.RedisEventBus({ host: "127.0.0.1", port: 6379 }); 385 | it('should connect to a specified Redis server', function (done) { 386 | redisEventBus.connect(function (error) { 387 | should.equal(error, null); 388 | done(); 389 | }); 390 | }); 391 | 392 | it('should be possible to persist an event into Redis in the pending commands list', function (done) { 393 | var testEvent = new TestEventMessageReceived('hello world'); 394 | testEvent.sourceId = "1"; 395 | redisEventBus.handleEvent({ 396 | messageId: "1", 397 | correlationId: "1", 398 | body: testEvent 399 | }, function (error) { 400 | should.equal(error, null); 401 | 402 | redisEventBus.getClient().lrange('messaging.queuedevents', 0, -1, function (error, results) { 403 | should.equal(error, null); 404 | results.length.should.be.exactly(1); 405 | var eventSerialized = results[0]; 406 | var _event = JSON.parse(eventSerialized); 407 | _event.body.message.should.be.exactly(testEvent.message); 408 | done(); 409 | }); 410 | }); 411 | }); 412 | 413 | it('should be possible to persist another event into Redis in the pending commands list', function (done) { 414 | var testEvent = new TestEventMessageReceived('hello world'); 415 | testEvent.sourceId = "1"; 416 | redisEventBus.handleEvent({ 417 | messageId: "1", 418 | correlationId: "1", 419 | body: testEvent 420 | }, function (error) { 421 | should.equal(error, null); 422 | 423 | redisEventBus.getClient().lrange('messaging.queuedevents', 0, -1, function (error, results) { 424 | should.equal(error, null); 425 | results.length.should.be.exactly(2); 426 | var eventSerialized = results[0]; 427 | var _event = JSON.parse(eventSerialized); 428 | _event.body.message.should.be.exactly(testEvent.message); 429 | done(); 430 | }); 431 | }); 432 | }); 433 | 434 | describe('using the "RedisEventReceiver"', function () { 435 | it('should be possible to receive pending events using the "RedisEventReceiver"', function (done) { 436 | var redisEventReceiverTestHandler = new RedisEventReceiverTestHandler(function () { 437 | redisEventReceiverTestHandler.callCount += 1; 438 | if (redisEventReceiverTestHandler.callCount == 2) 439 | return done(); 440 | }, 'hello world'); 441 | 442 | var redisEventReceiver = new CQRS.RedisEventReceiver({ host: "127.0.0.1", port: 6379 }, redisEventReceiverTestHandler); 443 | 444 | redisEventReceiver.connect(function (error) { 445 | should.equal(error, null); 446 | }); 447 | }); 448 | }); 449 | 450 | after(function (done) { 451 | redisEventBus.getClient().del('messaging.queuedevents', function (error) { 452 | should.equal(error, null); 453 | done(); 454 | }); 455 | }); 456 | }); 457 | }); 458 | }); 459 | -------------------------------------------------------------------------------- /lib/node.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Node.js v0.10.1 2 | // Project: http://nodejs.org/ 3 | // Definitions by: Microsoft TypeScript , DefinitelyTyped 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | /************************************************ 7 | * * 8 | * Node.js v0.10.1 API * 9 | * * 10 | ************************************************/ 11 | 12 | /************************************************ 13 | * * 14 | * GLOBAL * 15 | * * 16 | ************************************************/ 17 | declare var process: NodeJS.Process; 18 | declare var global: any; 19 | 20 | declare var __filename: string; 21 | declare var __dirname: string; 22 | 23 | declare function setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; 24 | declare function clearTimeout(timeoutId: NodeJS.Timer): void; 25 | declare function setInterval(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer; 26 | declare function clearInterval(intervalId: NodeJS.Timer): void; 27 | declare function setImmediate(callback: (...args: any[]) => void, ...args: any[]): any; 28 | declare function clearImmediate(immediateId: any): void; 29 | 30 | declare var require: { 31 | (id: string): any; 32 | resolve(id:string): string; 33 | cache: any; 34 | extensions: any; 35 | main: any; 36 | }; 37 | 38 | declare var module: { 39 | exports: any; 40 | require(id: string): any; 41 | id: string; 42 | filename: string; 43 | loaded: boolean; 44 | parent: any; 45 | children: any[]; 46 | }; 47 | 48 | // Same as module.exports 49 | declare var exports: any; 50 | declare var SlowBuffer: { 51 | new (str: string, encoding?: string): Buffer; 52 | new (size: number): Buffer; 53 | new (array: any[]): Buffer; 54 | prototype: Buffer; 55 | isBuffer(obj: any): boolean; 56 | byteLength(string: string, encoding?: string): number; 57 | concat(list: Buffer[], totalLength?: number): Buffer; 58 | }; 59 | 60 | 61 | // Buffer class 62 | interface Buffer extends NodeBuffer {} 63 | declare var Buffer: { 64 | new (str: string, encoding?: string): Buffer; 65 | new (size: number): Buffer; 66 | new (array: any[]): Buffer; 67 | prototype: Buffer; 68 | isBuffer(obj: any): boolean; 69 | byteLength(string: string, encoding?: string): number; 70 | concat(list: Buffer[], totalLength?: number): Buffer; 71 | }; 72 | 73 | /************************************************ 74 | * * 75 | * GLOBAL INTERFACES * 76 | * * 77 | ************************************************/ 78 | declare module NodeJS { 79 | export interface ErrnoException extends Error { 80 | errno?: any; 81 | code?: string; 82 | path?: string; 83 | syscall?: string; 84 | } 85 | 86 | export interface EventEmitter { 87 | addListener(event: string, listener: Function): EventEmitter; 88 | on(event: string, listener: Function): EventEmitter; 89 | once(event: string, listener: Function): EventEmitter; 90 | removeListener(event: string, listener: Function): EventEmitter; 91 | removeAllListeners(event?: string): EventEmitter; 92 | setMaxListeners(n: number): void; 93 | listeners(event: string): Function[]; 94 | emit(event: string, ...args: any[]): boolean; 95 | } 96 | 97 | export interface ReadableStream extends EventEmitter { 98 | readable: boolean; 99 | read(size?: number): any; 100 | setEncoding(encoding: string): void; 101 | pause(): void; 102 | resume(): void; 103 | pipe(destination: T, options?: { end?: boolean; }): T; 104 | unpipe(destination?: T): void; 105 | unshift(chunk: string): void; 106 | unshift(chunk: Buffer): void; 107 | wrap(oldStream: ReadableStream): ReadableStream; 108 | } 109 | 110 | export interface WritableStream extends EventEmitter { 111 | writable: boolean; 112 | write(buffer: Buffer, cb?: Function): boolean; 113 | write(str: string, cb?: Function): boolean; 114 | write(str: string, encoding?: string, cb?: Function): boolean; 115 | end(): void; 116 | end(buffer: Buffer, cb?: Function): void; 117 | end(str: string, cb?: Function): void; 118 | end(str: string, encoding?: string, cb?: Function): void; 119 | } 120 | 121 | export interface ReadWriteStream extends ReadableStream, WritableStream {} 122 | 123 | export interface Process extends EventEmitter { 124 | stdout: WritableStream; 125 | stderr: WritableStream; 126 | stdin: ReadableStream; 127 | argv: string[]; 128 | execPath: string; 129 | abort(): void; 130 | chdir(directory: string): void; 131 | cwd(): string; 132 | env: any; 133 | exit(code?: number): void; 134 | getgid(): number; 135 | setgid(id: number): void; 136 | setgid(id: string): void; 137 | getuid(): number; 138 | setuid(id: number): void; 139 | setuid(id: string): void; 140 | version: string; 141 | versions: { 142 | http_parser: string; 143 | node: string; 144 | v8: string; 145 | ares: string; 146 | uv: string; 147 | zlib: string; 148 | openssl: string; 149 | }; 150 | config: { 151 | target_defaults: { 152 | cflags: any[]; 153 | default_configuration: string; 154 | defines: string[]; 155 | include_dirs: string[]; 156 | libraries: string[]; 157 | }; 158 | variables: { 159 | clang: number; 160 | host_arch: string; 161 | node_install_npm: boolean; 162 | node_install_waf: boolean; 163 | node_prefix: string; 164 | node_shared_openssl: boolean; 165 | node_shared_v8: boolean; 166 | node_shared_zlib: boolean; 167 | node_use_dtrace: boolean; 168 | node_use_etw: boolean; 169 | node_use_openssl: boolean; 170 | target_arch: string; 171 | v8_no_strict_aliasing: number; 172 | v8_use_snapshot: boolean; 173 | visibility: string; 174 | }; 175 | }; 176 | kill(pid: number, signal?: string): void; 177 | pid: number; 178 | title: string; 179 | arch: string; 180 | platform: string; 181 | memoryUsage(): { rss: number; heapTotal: number; heapUsed: number; }; 182 | nextTick(callback: Function): void; 183 | umask(mask?: number): number; 184 | uptime(): number; 185 | hrtime(time?:number[]): number[]; 186 | 187 | // Worker 188 | send?(message: any, sendHandle?: any): void; 189 | } 190 | 191 | export interface Timer { 192 | ref() : void; 193 | unref() : void; 194 | } 195 | } 196 | 197 | /** 198 | * @deprecated 199 | */ 200 | interface NodeBuffer { 201 | [index: number]: number; 202 | write(string: string, offset?: number, length?: number, encoding?: string): number; 203 | toString(encoding?: string, start?: number, end?: number): string; 204 | toJSON(): any; 205 | length: number; 206 | copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number; 207 | slice(start?: number, end?: number): Buffer; 208 | readUInt8(offset: number, noAsset?: boolean): number; 209 | readUInt16LE(offset: number, noAssert?: boolean): number; 210 | readUInt16BE(offset: number, noAssert?: boolean): number; 211 | readUInt32LE(offset: number, noAssert?: boolean): number; 212 | readUInt32BE(offset: number, noAssert?: boolean): number; 213 | readInt8(offset: number, noAssert?: boolean): number; 214 | readInt16LE(offset: number, noAssert?: boolean): number; 215 | readInt16BE(offset: number, noAssert?: boolean): number; 216 | readInt32LE(offset: number, noAssert?: boolean): number; 217 | readInt32BE(offset: number, noAssert?: boolean): number; 218 | readFloatLE(offset: number, noAssert?: boolean): number; 219 | readFloatBE(offset: number, noAssert?: boolean): number; 220 | readDoubleLE(offset: number, noAssert?: boolean): number; 221 | readDoubleBE(offset: number, noAssert?: boolean): number; 222 | writeUInt8(value: number, offset: number, noAssert?: boolean): void; 223 | writeUInt16LE(value: number, offset: number, noAssert?: boolean): void; 224 | writeUInt16BE(value: number, offset: number, noAssert?: boolean): void; 225 | writeUInt32LE(value: number, offset: number, noAssert?: boolean): void; 226 | writeUInt32BE(value: number, offset: number, noAssert?: boolean): void; 227 | writeInt8(value: number, offset: number, noAssert?: boolean): void; 228 | writeInt16LE(value: number, offset: number, noAssert?: boolean): void; 229 | writeInt16BE(value: number, offset: number, noAssert?: boolean): void; 230 | writeInt32LE(value: number, offset: number, noAssert?: boolean): void; 231 | writeInt32BE(value: number, offset: number, noAssert?: boolean): void; 232 | writeFloatLE(value: number, offset: number, noAssert?: boolean): void; 233 | writeFloatBE(value: number, offset: number, noAssert?: boolean): void; 234 | writeDoubleLE(value: number, offset: number, noAssert?: boolean): void; 235 | writeDoubleBE(value: number, offset: number, noAssert?: boolean): void; 236 | fill(value: any, offset?: number, end?: number): void; 237 | } 238 | 239 | /************************************************ 240 | * * 241 | * MODULES * 242 | * * 243 | ************************************************/ 244 | declare module "buffer" { 245 | export var INSPECT_MAX_BYTES: number; 246 | } 247 | 248 | declare module "querystring" { 249 | export function stringify(obj: any, sep?: string, eq?: string): string; 250 | export function parse(str: string, sep?: string, eq?: string, options?: { maxKeys?: number; }): any; 251 | export function escape(): any; 252 | export function unescape(): any; 253 | } 254 | 255 | declare module "events" { 256 | export class EventEmitter implements NodeJS.EventEmitter { 257 | static listenerCount(emitter: EventEmitter, event: string): number; 258 | 259 | addListener(event: string, listener: Function): EventEmitter; 260 | on(event: string, listener: Function): EventEmitter; 261 | once(event: string, listener: Function): EventEmitter; 262 | removeListener(event: string, listener: Function): EventEmitter; 263 | removeAllListeners(event?: string): EventEmitter; 264 | setMaxListeners(n: number): void; 265 | listeners(event: string): Function[]; 266 | emit(event: string, ...args: any[]): boolean; 267 | } 268 | } 269 | 270 | declare module "http" { 271 | import events = require("events"); 272 | import net = require("net"); 273 | import stream = require("stream"); 274 | 275 | export interface Server extends events.EventEmitter { 276 | listen(port: number, hostname?: string, backlog?: number, callback?: Function): Server; 277 | listen(path: string, callback?: Function): Server; 278 | listen(handle: any, listeningListener?: Function): Server; 279 | close(cb?: any): Server; 280 | address(): { port: number; family: string; address: string; }; 281 | maxHeadersCount: number; 282 | } 283 | export interface ServerRequest extends events.EventEmitter, stream.Readable { 284 | method: string; 285 | url: string; 286 | headers: any; 287 | trailers: string; 288 | httpVersion: string; 289 | setEncoding(encoding?: string): void; 290 | pause(): void; 291 | resume(): void; 292 | connection: net.Socket; 293 | } 294 | export interface ServerResponse extends events.EventEmitter, stream.Writable { 295 | // Extended base methods 296 | write(buffer: Buffer): boolean; 297 | write(buffer: Buffer, cb?: Function): boolean; 298 | write(str: string, cb?: Function): boolean; 299 | write(str: string, encoding?: string, cb?: Function): boolean; 300 | write(str: string, encoding?: string, fd?: string): boolean; 301 | 302 | writeContinue(): void; 303 | writeHead(statusCode: number, reasonPhrase?: string, headers?: any): void; 304 | writeHead(statusCode: number, headers?: any): void; 305 | statusCode: number; 306 | setHeader(name: string, value: string): void; 307 | sendDate: boolean; 308 | getHeader(name: string): string; 309 | removeHeader(name: string): void; 310 | write(chunk: any, encoding?: string): any; 311 | addTrailers(headers: any): void; 312 | 313 | // Extended base methods 314 | end(): void; 315 | end(buffer: Buffer, cb?: Function): void; 316 | end(str: string, cb?: Function): void; 317 | end(str: string, encoding?: string, cb?: Function): void; 318 | end(data?: any, encoding?: string): void; 319 | } 320 | export interface ClientRequest extends events.EventEmitter, stream.Writable { 321 | // Extended base methods 322 | write(buffer: Buffer): boolean; 323 | write(buffer: Buffer, cb?: Function): boolean; 324 | write(str: string, cb?: Function): boolean; 325 | write(str: string, encoding?: string, cb?: Function): boolean; 326 | write(str: string, encoding?: string, fd?: string): boolean; 327 | 328 | write(chunk: any, encoding?: string): void; 329 | abort(): void; 330 | setTimeout(timeout: number, callback?: Function): void; 331 | setNoDelay(noDelay?: boolean): void; 332 | setSocketKeepAlive(enable?: boolean, initialDelay?: number): void; 333 | 334 | // Extended base methods 335 | end(): void; 336 | end(buffer: Buffer, cb?: Function): void; 337 | end(str: string, cb?: Function): void; 338 | end(str: string, encoding?: string, cb?: Function): void; 339 | end(data?: any, encoding?: string): void; 340 | } 341 | export interface ClientResponse extends events.EventEmitter, stream.Readable { 342 | statusCode: number; 343 | httpVersion: string; 344 | headers: any; 345 | trailers: any; 346 | setEncoding(encoding?: string): void; 347 | pause(): void; 348 | resume(): void; 349 | } 350 | export interface Agent { maxSockets: number; sockets: any; requests: any; } 351 | 352 | export var STATUS_CODES: { 353 | [errorCode: number]: string; 354 | [errorCode: string]: string; 355 | }; 356 | export function createServer(requestListener?: (request: ServerRequest, response: ServerResponse) =>void ): Server; 357 | export function createClient(port?: number, host?: string): any; 358 | export function request(options: any, callback?: Function): ClientRequest; 359 | export function get(options: any, callback?: Function): ClientRequest; 360 | export var globalAgent: Agent; 361 | } 362 | 363 | declare module "cluster" { 364 | import child = require("child_process"); 365 | import events = require("events"); 366 | 367 | export interface ClusterSettings { 368 | exec?: string; 369 | args?: string[]; 370 | silent?: boolean; 371 | } 372 | 373 | export class Worker extends events.EventEmitter { 374 | id: string; 375 | process: child.ChildProcess; 376 | suicide: boolean; 377 | send(message: any, sendHandle?: any): void; 378 | kill(signal?: string): void; 379 | destroy(signal?: string): void; 380 | disconnect(): void; 381 | } 382 | 383 | export var settings: ClusterSettings; 384 | export var isMaster: boolean; 385 | export var isWorker: boolean; 386 | export function setupMaster(settings?: ClusterSettings): void; 387 | export function fork(env?: any): Worker; 388 | export function disconnect(callback?: Function): void; 389 | export var worker: Worker; 390 | export var workers: Worker[]; 391 | 392 | // Event emitter 393 | export function addListener(event: string, listener: Function): void; 394 | export function on(event: string, listener: Function): any; 395 | export function once(event: string, listener: Function): void; 396 | export function removeListener(event: string, listener: Function): void; 397 | export function removeAllListeners(event?: string): void; 398 | export function setMaxListeners(n: number): void; 399 | export function listeners(event: string): Function[]; 400 | export function emit(event: string, ...args: any[]): boolean; 401 | } 402 | 403 | declare module "zlib" { 404 | import stream = require("stream"); 405 | export interface ZlibOptions { chunkSize?: number; windowBits?: number; level?: number; memLevel?: number; strategy?: number; dictionary?: any; } 406 | 407 | export interface Gzip extends stream.Transform { } 408 | export interface Gunzip extends stream.Transform { } 409 | export interface Deflate extends stream.Transform { } 410 | export interface Inflate extends stream.Transform { } 411 | export interface DeflateRaw extends stream.Transform { } 412 | export interface InflateRaw extends stream.Transform { } 413 | export interface Unzip extends stream.Transform { } 414 | 415 | export function createGzip(options?: ZlibOptions): Gzip; 416 | export function createGunzip(options?: ZlibOptions): Gunzip; 417 | export function createDeflate(options?: ZlibOptions): Deflate; 418 | export function createInflate(options?: ZlibOptions): Inflate; 419 | export function createDeflateRaw(options?: ZlibOptions): DeflateRaw; 420 | export function createInflateRaw(options?: ZlibOptions): InflateRaw; 421 | export function createUnzip(options?: ZlibOptions): Unzip; 422 | 423 | export function deflate(buf: Buffer, callback: (error: Error, result: any) =>void ): void; 424 | export function deflateRaw(buf: Buffer, callback: (error: Error, result: any) =>void ): void; 425 | export function gzip(buf: Buffer, callback: (error: Error, result: any) =>void ): void; 426 | export function gunzip(buf: Buffer, callback: (error: Error, result: any) =>void ): void; 427 | export function inflate(buf: Buffer, callback: (error: Error, result: any) =>void ): void; 428 | export function inflateRaw(buf: Buffer, callback: (error: Error, result: any) =>void ): void; 429 | export function unzip(buf: Buffer, callback: (error: Error, result: any) =>void ): void; 430 | 431 | // Constants 432 | export var Z_NO_FLUSH: number; 433 | export var Z_PARTIAL_FLUSH: number; 434 | export var Z_SYNC_FLUSH: number; 435 | export var Z_FULL_FLUSH: number; 436 | export var Z_FINISH: number; 437 | export var Z_BLOCK: number; 438 | export var Z_TREES: number; 439 | export var Z_OK: number; 440 | export var Z_STREAM_END: number; 441 | export var Z_NEED_DICT: number; 442 | export var Z_ERRNO: number; 443 | export var Z_STREAM_ERROR: number; 444 | export var Z_DATA_ERROR: number; 445 | export var Z_MEM_ERROR: number; 446 | export var Z_BUF_ERROR: number; 447 | export var Z_VERSION_ERROR: number; 448 | export var Z_NO_COMPRESSION: number; 449 | export var Z_BEST_SPEED: number; 450 | export var Z_BEST_COMPRESSION: number; 451 | export var Z_DEFAULT_COMPRESSION: number; 452 | export var Z_FILTERED: number; 453 | export var Z_HUFFMAN_ONLY: number; 454 | export var Z_RLE: number; 455 | export var Z_FIXED: number; 456 | export var Z_DEFAULT_STRATEGY: number; 457 | export var Z_BINARY: number; 458 | export var Z_TEXT: number; 459 | export var Z_ASCII: number; 460 | export var Z_UNKNOWN: number; 461 | export var Z_DEFLATED: number; 462 | export var Z_NULL: number; 463 | } 464 | 465 | declare module "os" { 466 | export function tmpDir(): string; 467 | export function hostname(): string; 468 | export function type(): string; 469 | export function platform(): string; 470 | export function arch(): string; 471 | export function release(): string; 472 | export function uptime(): number; 473 | export function loadavg(): number[]; 474 | export function totalmem(): number; 475 | export function freemem(): number; 476 | export function cpus(): { model: string; speed: number; times: { user: number; nice: number; sys: number; idle: number; irq: number; }; }[]; 477 | export function networkInterfaces(): any; 478 | export var EOL: string; 479 | } 480 | 481 | declare module "https" { 482 | import tls = require("tls"); 483 | import events = require("events"); 484 | import http = require("http"); 485 | 486 | export interface ServerOptions { 487 | pfx?: any; 488 | key?: any; 489 | passphrase?: string; 490 | cert?: any; 491 | ca?: any; 492 | crl?: any; 493 | ciphers?: string; 494 | honorCipherOrder?: boolean; 495 | requestCert?: boolean; 496 | rejectUnauthorized?: boolean; 497 | NPNProtocols?: any; 498 | SNICallback?: (servername: string) => any; 499 | } 500 | 501 | export interface RequestOptions { 502 | host?: string; 503 | hostname?: string; 504 | port?: number; 505 | path?: string; 506 | method?: string; 507 | headers?: any; 508 | auth?: string; 509 | agent?: any; 510 | pfx?: any; 511 | key?: any; 512 | passphrase?: string; 513 | cert?: any; 514 | ca?: any; 515 | ciphers?: string; 516 | rejectUnauthorized?: boolean; 517 | } 518 | 519 | export interface Agent { 520 | maxSockets: number; 521 | sockets: any; 522 | requests: any; 523 | } 524 | export var Agent: { 525 | new (options?: RequestOptions): Agent; 526 | }; 527 | export interface Server extends tls.Server { } 528 | export function createServer(options: ServerOptions, requestListener?: Function): Server; 529 | export function request(options: RequestOptions, callback?: (res: events.EventEmitter) =>void ): http.ClientRequest; 530 | export function get(options: RequestOptions, callback?: (res: events.EventEmitter) =>void ): http.ClientRequest; 531 | export var globalAgent: Agent; 532 | } 533 | 534 | declare module "punycode" { 535 | export function decode(string: string): string; 536 | export function encode(string: string): string; 537 | export function toUnicode(domain: string): string; 538 | export function toASCII(domain: string): string; 539 | export var ucs2: ucs2; 540 | interface ucs2 { 541 | decode(string: string): string; 542 | encode(codePoints: number[]): string; 543 | } 544 | export var version: any; 545 | } 546 | 547 | declare module "repl" { 548 | import stream = require("stream"); 549 | import events = require("events"); 550 | 551 | export interface ReplOptions { 552 | prompt?: string; 553 | input?: NodeJS.ReadableStream; 554 | output?: NodeJS.WritableStream; 555 | terminal?: boolean; 556 | eval?: Function; 557 | useColors?: boolean; 558 | useGlobal?: boolean; 559 | ignoreUndefined?: boolean; 560 | writer?: Function; 561 | } 562 | export function start(options: ReplOptions): events.EventEmitter; 563 | } 564 | 565 | declare module "readline" { 566 | import events = require("events"); 567 | import stream = require("stream"); 568 | 569 | export interface ReadLine extends events.EventEmitter { 570 | setPrompt(prompt: string, length: number): void; 571 | prompt(preserveCursor?: boolean): void; 572 | question(query: string, callback: Function): void; 573 | pause(): void; 574 | resume(): void; 575 | close(): void; 576 | write(data: any, key?: any): void; 577 | } 578 | export interface ReadLineOptions { 579 | input: NodeJS.ReadableStream; 580 | output: NodeJS.WritableStream; 581 | completer?: Function; 582 | terminal?: boolean; 583 | } 584 | export function createInterface(options: ReadLineOptions): ReadLine; 585 | } 586 | 587 | declare module "vm" { 588 | export interface Context { } 589 | export interface Script { 590 | runInThisContext(): void; 591 | runInNewContext(sandbox?: Context): void; 592 | } 593 | export function runInThisContext(code: string, filename?: string): void; 594 | export function runInNewContext(code: string, sandbox?: Context, filename?: string): void; 595 | export function runInContext(code: string, context: Context, filename?: string): void; 596 | export function createContext(initSandbox?: Context): Context; 597 | export function createScript(code: string, filename?: string): Script; 598 | } 599 | 600 | declare module "child_process" { 601 | import events = require("events"); 602 | import stream = require("stream"); 603 | 604 | export interface ChildProcess extends events.EventEmitter { 605 | stdin: stream.Writable; 606 | stdout: stream.Readable; 607 | stderr: stream.Readable; 608 | pid: number; 609 | kill(signal?: string): void; 610 | send(message: any, sendHandle: any): void; 611 | disconnect(): void; 612 | } 613 | 614 | export function spawn(command: string, args?: string[], options?: { 615 | cwd?: string; 616 | stdio?: any; 617 | custom?: any; 618 | env?: any; 619 | detached?: boolean; 620 | }): ChildProcess; 621 | export function exec(command: string, options: { 622 | cwd?: string; 623 | stdio?: any; 624 | customFds?: any; 625 | env?: any; 626 | encoding?: string; 627 | timeout?: number; 628 | maxBuffer?: number; 629 | killSignal?: string; 630 | }, callback: (error: Error, stdout: Buffer, stderr: Buffer) =>void ): ChildProcess; 631 | export function exec(command: string, callback: (error: Error, stdout: Buffer, stderr: Buffer) =>void ): ChildProcess; 632 | export function execFile(file: string, args: string[], options: { 633 | cwd?: string; 634 | stdio?: any; 635 | customFds?: any; 636 | env?: any; 637 | encoding?: string; 638 | timeout?: number; 639 | maxBuffer?: string; 640 | killSignal?: string; 641 | }, callback: (error: Error, stdout: Buffer, stderr: Buffer) =>void ): ChildProcess; 642 | export function fork(modulePath: string, args?: string[], options?: { 643 | cwd?: string; 644 | env?: any; 645 | encoding?: string; 646 | }): ChildProcess; 647 | } 648 | 649 | declare module "url" { 650 | export interface Url { 651 | href: string; 652 | protocol: string; 653 | auth: string; 654 | hostname: string; 655 | port: string; 656 | host: string; 657 | pathname: string; 658 | search: string; 659 | query: string; 660 | slashes: boolean; 661 | hash?: string; 662 | path?: string; 663 | } 664 | 665 | export interface UrlOptions { 666 | protocol?: string; 667 | auth?: string; 668 | hostname?: string; 669 | port?: string; 670 | host?: string; 671 | pathname?: string; 672 | search?: string; 673 | query?: any; 674 | hash?: string; 675 | path?: string; 676 | } 677 | 678 | export function parse(urlStr: string, parseQueryString?: boolean , slashesDenoteHost?: boolean ): Url; 679 | export function format(url: UrlOptions): string; 680 | export function resolve(from: string, to: string): string; 681 | } 682 | 683 | declare module "dns" { 684 | export function lookup(domain: string, family: number, callback: (err: Error, address: string, family: number) =>void ): string; 685 | export function lookup(domain: string, callback: (err: Error, address: string, family: number) =>void ): string; 686 | export function resolve(domain: string, rrtype: string, callback: (err: Error, addresses: string[]) =>void ): string[]; 687 | export function resolve(domain: string, callback: (err: Error, addresses: string[]) =>void ): string[]; 688 | export function resolve4(domain: string, callback: (err: Error, addresses: string[]) =>void ): string[]; 689 | export function resolve6(domain: string, callback: (err: Error, addresses: string[]) =>void ): string[]; 690 | export function resolveMx(domain: string, callback: (err: Error, addresses: string[]) =>void ): string[]; 691 | export function resolveTxt(domain: string, callback: (err: Error, addresses: string[]) =>void ): string[]; 692 | export function resolveSrv(domain: string, callback: (err: Error, addresses: string[]) =>void ): string[]; 693 | export function resolveNs(domain: string, callback: (err: Error, addresses: string[]) =>void ): string[]; 694 | export function resolveCname(domain: string, callback: (err: Error, addresses: string[]) =>void ): string[]; 695 | export function reverse(ip: string, callback: (err: Error, domains: string[]) =>void ): string[]; 696 | } 697 | 698 | declare module "net" { 699 | import stream = require("stream"); 700 | 701 | export interface Socket extends stream.Duplex { 702 | // Extended base methods 703 | write(buffer: Buffer): boolean; 704 | write(buffer: Buffer, cb?: Function): boolean; 705 | write(str: string, cb?: Function): boolean; 706 | write(str: string, encoding?: string, cb?: Function): boolean; 707 | write(str: string, encoding?: string, fd?: string): boolean; 708 | 709 | connect(port: number, host?: string, connectionListener?: Function): void; 710 | connect(path: string, connectionListener?: Function): void; 711 | bufferSize: number; 712 | setEncoding(encoding?: string): void; 713 | write(data: any, encoding?: string, callback?: Function): void; 714 | destroy(): void; 715 | pause(): void; 716 | resume(): void; 717 | setTimeout(timeout: number, callback?: Function): void; 718 | setNoDelay(noDelay?: boolean): void; 719 | setKeepAlive(enable?: boolean, initialDelay?: number): void; 720 | address(): { port: number; family: string; address: string; }; 721 | remoteAddress: string; 722 | remotePort: number; 723 | bytesRead: number; 724 | bytesWritten: number; 725 | 726 | // Extended base methods 727 | end(): void; 728 | end(buffer: Buffer, cb?: Function): void; 729 | end(str: string, cb?: Function): void; 730 | end(str: string, encoding?: string, cb?: Function): void; 731 | end(data?: any, encoding?: string): void; 732 | } 733 | 734 | export var Socket: { 735 | new (options?: { fd?: string; type?: string; allowHalfOpen?: boolean; }): Socket; 736 | }; 737 | 738 | export interface Server extends Socket { 739 | listen(port: number, host?: string, backlog?: number, listeningListener?: Function): Server; 740 | listen(path: string, listeningListener?: Function): Server; 741 | listen(handle: any, listeningListener?: Function): Server; 742 | close(callback?: Function): Server; 743 | address(): { port: number; family: string; address: string; }; 744 | maxConnections: number; 745 | connections: number; 746 | } 747 | export function createServer(connectionListener?: (socket: Socket) =>void ): Server; 748 | export function createServer(options?: { allowHalfOpen?: boolean; }, connectionListener?: (socket: Socket) =>void ): Server; 749 | export function connect(options: { allowHalfOpen?: boolean; }, connectionListener?: Function): Socket; 750 | export function connect(port: number, host?: string, connectionListener?: Function): Socket; 751 | export function connect(path: string, connectionListener?: Function): Socket; 752 | export function createConnection(options: { allowHalfOpen?: boolean; }, connectionListener?: Function): Socket; 753 | export function createConnection(port: number, host?: string, connectionListener?: Function): Socket; 754 | export function createConnection(path: string, connectionListener?: Function): Socket; 755 | export function isIP(input: string): number; 756 | export function isIPv4(input: string): boolean; 757 | export function isIPv6(input: string): boolean; 758 | } 759 | 760 | declare module "dgram" { 761 | import events = require("events"); 762 | 763 | export function createSocket(type: string, callback?: Function): Socket; 764 | 765 | interface Socket extends events.EventEmitter { 766 | send(buf: Buffer, offset: number, length: number, port: number, address: string, callback?: (error: Error, bytes: number) => void): void; 767 | bind(port: number, address?: string, callback?: () => void): void; 768 | close(): void; 769 | address: { address: string; family: string; port: number; }; 770 | setBroadcast(flag: boolean): void; 771 | setMulticastTTL(ttl: number): void; 772 | setMulticastLoopback(flag: boolean): void; 773 | addMembership(multicastAddress: string, multicastInterface?: string): void; 774 | dropMembership(multicastAddress: string, multicastInterface?: string): void; 775 | } 776 | } 777 | 778 | declare module "fs" { 779 | import stream = require("stream"); 780 | import events = require("events"); 781 | 782 | interface Stats { 783 | isFile(): boolean; 784 | isDirectory(): boolean; 785 | isBlockDevice(): boolean; 786 | isCharacterDevice(): boolean; 787 | isSymbolicLink(): boolean; 788 | isFIFO(): boolean; 789 | isSocket(): boolean; 790 | dev: number; 791 | ino: number; 792 | mode: number; 793 | nlink: number; 794 | uid: number; 795 | gid: number; 796 | rdev: number; 797 | size: number; 798 | blksize: number; 799 | blocks: number; 800 | atime: Date; 801 | mtime: Date; 802 | ctime: Date; 803 | } 804 | 805 | interface FSWatcher extends events.EventEmitter { 806 | close(): void; 807 | } 808 | 809 | export interface ReadStream extends stream.Readable {} 810 | export interface WriteStream extends stream.Writable {} 811 | 812 | export function rename(oldPath: string, newPath: string, callback?: (err?: NodeJS.ErrnoException) => void): void; 813 | export function renameSync(oldPath: string, newPath: string): void; 814 | export function truncate(path: string, callback?: (err?: NodeJS.ErrnoException) => void): void; 815 | export function truncate(path: string, len: number, callback?: (err?: NodeJS.ErrnoException) => void): void; 816 | export function truncateSync(path: string, len?: number): void; 817 | export function ftruncate(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; 818 | export function ftruncate(fd: number, len: number, callback?: (err?: NodeJS.ErrnoException) => void): void; 819 | export function ftruncateSync(fd: number, len?: number): void; 820 | export function chown(path: string, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; 821 | export function chownSync(path: string, uid: number, gid: number): void; 822 | export function fchown(fd: number, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; 823 | export function fchownSync(fd: number, uid: number, gid: number): void; 824 | export function lchown(path: string, uid: number, gid: number, callback?: (err?: NodeJS.ErrnoException) => void): void; 825 | export function lchownSync(path: string, uid: number, gid: number): void; 826 | export function chmod(path: string, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; 827 | export function chmod(path: string, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; 828 | export function chmodSync(path: string, mode: number): void; 829 | export function chmodSync(path: string, mode: string): void; 830 | export function fchmod(fd: number, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; 831 | export function fchmod(fd: number, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; 832 | export function fchmodSync(fd: number, mode: number): void; 833 | export function fchmodSync(fd: number, mode: string): void; 834 | export function lchmod(path: string, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; 835 | export function lchmod(path: string, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; 836 | export function lchmodSync(path: string, mode: number): void; 837 | export function lchmodSync(path: string, mode: string): void; 838 | export function stat(path: string, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; 839 | export function lstat(path: string, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; 840 | export function fstat(fd: number, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; 841 | export function statSync(path: string): Stats; 842 | export function lstatSync(path: string): Stats; 843 | export function fstatSync(fd: number): Stats; 844 | export function link(srcpath: string, dstpath: string, callback?: (err?: NodeJS.ErrnoException) => void): void; 845 | export function linkSync(srcpath: string, dstpath: string): void; 846 | export function symlink(srcpath: string, dstpath: string, type?: string, callback?: (err?: NodeJS.ErrnoException) => void): void; 847 | export function symlinkSync(srcpath: string, dstpath: string, type?: string): void; 848 | export function readlink(path: string, callback?: (err: NodeJS.ErrnoException, linkString: string) => any): void; 849 | export function readlinkSync(path: string): string; 850 | export function realpath(path: string, callback?: (err: NodeJS.ErrnoException, resolvedPath: string) => any): void; 851 | export function realpath(path: string, cache: {[path: string]: string}, callback: (err: NodeJS.ErrnoException, resolvedPath: string) =>any): void; 852 | export function realpathSync(path: string, cache?: {[path: string]: string}): string; 853 | export function unlink(path: string, callback?: (err?: NodeJS.ErrnoException) => void): void; 854 | export function unlinkSync(path: string): void; 855 | export function rmdir(path: string, callback?: (err?: NodeJS.ErrnoException) => void): void; 856 | export function rmdirSync(path: string): void; 857 | export function mkdir(path: string, callback?: (err?: NodeJS.ErrnoException) => void): void; 858 | export function mkdir(path: string, mode: number, callback?: (err?: NodeJS.ErrnoException) => void): void; 859 | export function mkdir(path: string, mode: string, callback?: (err?: NodeJS.ErrnoException) => void): void; 860 | export function mkdirSync(path: string, mode?: number): void; 861 | export function mkdirSync(path: string, mode?: string): void; 862 | export function readdir(path: string, callback?: (err: NodeJS.ErrnoException, files: string[]) => void): void; 863 | export function readdirSync(path: string): string[]; 864 | export function close(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; 865 | export function closeSync(fd: number): void; 866 | export function open(path: string, flags: string, callback?: (err: NodeJS.ErrnoException, fd: number) => any): void; 867 | export function open(path: string, flags: string, mode: number, callback?: (err: NodeJS.ErrnoException, fd: number) => any): void; 868 | export function open(path: string, flags: string, mode: string, callback?: (err: NodeJS.ErrnoException, fd: number) => any): void; 869 | export function openSync(path: string, flags: string, mode?: number): number; 870 | export function openSync(path: string, flags: string, mode?: string): number; 871 | export function utimes(path: string, atime: number, mtime: number, callback?: (err?: NodeJS.ErrnoException) => void): void; 872 | export function utimes(path: string, atime: Date, mtime: Date, callback?: (err?: NodeJS.ErrnoException) => void): void; 873 | export function utimesSync(path: string, atime: number, mtime: number): void; 874 | export function utimesSync(path: string, atime: Date, mtime: Date): void; 875 | export function futimes(fd: number, atime: number, mtime: number, callback?: (err?: NodeJS.ErrnoException) => void): void; 876 | export function futimes(fd: number, atime: Date, mtime: Date, callback?: (err?: NodeJS.ErrnoException) => void): void; 877 | export function futimesSync(fd: number, atime: number, mtime: number): void; 878 | export function futimesSync(fd: number, atime: Date, mtime: Date): void; 879 | export function fsync(fd: number, callback?: (err?: NodeJS.ErrnoException) => void): void; 880 | export function fsyncSync(fd: number): void; 881 | export function write(fd: number, buffer: Buffer, offset: number, length: number, position: number, callback?: (err: NodeJS.ErrnoException, written: number, buffer: Buffer) => void): void; 882 | export function writeSync(fd: number, buffer: Buffer, offset: number, length: number, position: number): number; 883 | export function read(fd: number, buffer: Buffer, offset: number, length: number, position: number, callback?: (err: NodeJS.ErrnoException, bytesRead: number, buffer: Buffer) => void): void; 884 | export function readSync(fd: number, buffer: Buffer, offset: number, length: number, position: number): number; 885 | export function readFile(filename: string, encoding: string, callback: (err: NodeJS.ErrnoException, data: string) => void): void; 886 | export function readFile(filename: string, options: { encoding: string; flag?: string; }, callback: (err: NodeJS.ErrnoException, data: string) => void): void; 887 | export function readFile(filename: string, options: { flag?: string; }, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; 888 | export function readFile(filename: string, callback: (err: NodeJS.ErrnoException, data: Buffer) => void ): void; 889 | export function readFileSync(filename: string, encoding: string): string; 890 | export function readFileSync(filename: string, options: { encoding: string; flag?: string; }): string; 891 | export function readFileSync(filename: string, options?: { flag?: string; }): Buffer; 892 | export function writeFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void; 893 | export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; 894 | export function writeFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; 895 | export function writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void; 896 | export function writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: string; flag?: string; }): void; 897 | export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; 898 | export function appendFile(filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void): void; 899 | export function appendFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void; 900 | export function appendFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void; 901 | export function appendFileSync(filename: string, data: any, options?: { encoding?: string; mode?: string; flag?: string; }): void; 902 | export function watchFile(filename: string, listener: (curr: Stats, prev: Stats) => void): void; 903 | export function watchFile(filename: string, options: { persistent?: boolean; interval?: number; }, listener: (curr: Stats, prev: Stats) => void): void; 904 | export function unwatchFile(filename: string, listener?: (curr: Stats, prev: Stats) => void): void; 905 | export function watch(filename: string, listener?: (event: string, filename: string) => any): FSWatcher; 906 | export function watch(filename: string, options: { persistent?: boolean; }, listener?: (event: string, filename: string) => any): FSWatcher; 907 | export function exists(path: string, callback?: (exists: boolean) => void): void; 908 | export function existsSync(path: string): boolean; 909 | export function createReadStream(path: string, options?: { 910 | flags?: string; 911 | encoding?: string; 912 | fd?: string; 913 | mode?: number; 914 | bufferSize?: number; 915 | }): ReadStream; 916 | export function createReadStream(path: string, options?: { 917 | flags?: string; 918 | encoding?: string; 919 | fd?: string; 920 | mode?: string; 921 | bufferSize?: number; 922 | }): ReadStream; 923 | export function createWriteStream(path: string, options?: { 924 | flags?: string; 925 | encoding?: string; 926 | string?: string; 927 | }): WriteStream; 928 | } 929 | 930 | declare module "path" { 931 | export function normalize(p: string): string; 932 | export function join(...paths: any[]): string; 933 | export function resolve(...pathSegments: any[]): string; 934 | export function relative(from: string, to: string): string; 935 | export function dirname(p: string): string; 936 | export function basename(p: string, ext?: string): string; 937 | export function extname(p: string): string; 938 | export var sep: string; 939 | } 940 | 941 | declare module "string_decoder" { 942 | export interface NodeStringDecoder { 943 | write(buffer: Buffer): string; 944 | detectIncompleteChar(buffer: Buffer): number; 945 | } 946 | export var StringDecoder: { 947 | new (encoding: string): NodeStringDecoder; 948 | }; 949 | } 950 | 951 | declare module "tls" { 952 | import crypto = require("crypto"); 953 | import net = require("net"); 954 | import stream = require("stream"); 955 | 956 | var CLIENT_RENEG_LIMIT: number; 957 | var CLIENT_RENEG_WINDOW: number; 958 | 959 | export interface TlsOptions { 960 | pfx?: any; //string or buffer 961 | key?: any; //string or buffer 962 | passphrase?: string; 963 | cert?: any; 964 | ca?: any; //string or buffer 965 | crl?: any; //string or string array 966 | ciphers?: string; 967 | honorCipherOrder?: any; 968 | requestCert?: boolean; 969 | rejectUnauthorized?: boolean; 970 | NPNProtocols?: any; //array or Buffer; 971 | SNICallback?: (servername: string) => any; 972 | } 973 | 974 | export interface ConnectionOptions { 975 | host?: string; 976 | port?: number; 977 | socket?: net.Socket; 978 | pfx?: any; //string | Buffer 979 | key?: any; //string | Buffer 980 | passphrase?: string; 981 | cert?: any; //string | Buffer 982 | ca?: any; //Array of string | Buffer 983 | rejectUnauthorized?: boolean; 984 | NPNProtocols?: any; //Array of string | Buffer 985 | servername?: string; 986 | } 987 | 988 | export interface Server extends net.Server { 989 | // Extended base methods 990 | listen(port: number, host?: string, backlog?: number, listeningListener?: Function): Server; 991 | listen(path: string, listeningListener?: Function): Server; 992 | listen(handle: any, listeningListener?: Function): Server; 993 | 994 | listen(port: number, host?: string, callback?: Function): Server; 995 | close(): Server; 996 | address(): { port: number; family: string; address: string; }; 997 | addContext(hostName: string, credentials: { 998 | key: string; 999 | cert: string; 1000 | ca: string; 1001 | }): void; 1002 | maxConnections: number; 1003 | connections: number; 1004 | } 1005 | 1006 | export interface ClearTextStream extends stream.Duplex { 1007 | authorized: boolean; 1008 | authorizationError: Error; 1009 | getPeerCertificate(): any; 1010 | getCipher: { 1011 | name: string; 1012 | version: string; 1013 | }; 1014 | address: { 1015 | port: number; 1016 | family: string; 1017 | address: string; 1018 | }; 1019 | remoteAddress: string; 1020 | remotePort: number; 1021 | } 1022 | 1023 | export interface SecurePair { 1024 | encrypted: any; 1025 | cleartext: any; 1026 | } 1027 | 1028 | export function createServer(options: TlsOptions, secureConnectionListener?: (cleartextStream: ClearTextStream) =>void ): Server; 1029 | export function connect(options: TlsOptions, secureConnectionListener?: () =>void ): ClearTextStream; 1030 | export function connect(port: number, host?: string, options?: ConnectionOptions, secureConnectListener?: () =>void ): ClearTextStream; 1031 | export function connect(port: number, options?: ConnectionOptions, secureConnectListener?: () =>void ): ClearTextStream; 1032 | export function createSecurePair(credentials?: crypto.Credentials, isServer?: boolean, requestCert?: boolean, rejectUnauthorized?: boolean): SecurePair; 1033 | } 1034 | 1035 | declare module "crypto" { 1036 | export interface CredentialDetails { 1037 | pfx: string; 1038 | key: string; 1039 | passphrase: string; 1040 | cert: string; 1041 | ca: any; //string | string array 1042 | crl: any; //string | string array 1043 | ciphers: string; 1044 | } 1045 | export interface Credentials { context?: any; } 1046 | export function createCredentials(details: CredentialDetails): Credentials; 1047 | export function createHash(algorithm: string): Hash; 1048 | export function createHmac(algorithm: string, key: string): Hmac; 1049 | interface Hash { 1050 | update(data: any, input_encoding?: string): Hash; 1051 | digest(encoding?: string): string; 1052 | } 1053 | interface Hmac { 1054 | update(data: any, input_encoding?: string): Hmac; 1055 | digest(encoding?: string): string; 1056 | } 1057 | export function createCipher(algorithm: string, password: any): Cipher; 1058 | export function createCipheriv(algorithm: string, key: any, iv: any): Cipher; 1059 | interface Cipher { 1060 | update(data: any, input_encoding?: string, output_encoding?: string): string; 1061 | final(output_encoding?: string): string; 1062 | setAutoPadding(auto_padding: boolean): void; 1063 | createDecipher(algorithm: string, password: any): Decipher; 1064 | createDecipheriv(algorithm: string, key: any, iv: any): Decipher; 1065 | } 1066 | interface Decipher { 1067 | update(data: any, input_encoding?: string, output_encoding?: string): void; 1068 | final(output_encoding?: string): string; 1069 | setAutoPadding(auto_padding: boolean): void; 1070 | } 1071 | export function createSign(algorithm: string): Signer; 1072 | interface Signer { 1073 | update(data: any): void; 1074 | sign(private_key: string, output_format: string): string; 1075 | } 1076 | export function createVerify(algorith: string): Verify; 1077 | interface Verify { 1078 | update(data: any): void; 1079 | verify(object: string, signature: string, signature_format?: string): boolean; 1080 | } 1081 | export function createDiffieHellman(prime_length: number): DiffieHellman; 1082 | export function createDiffieHellman(prime: number, encoding?: string): DiffieHellman; 1083 | interface DiffieHellman { 1084 | generateKeys(encoding?: string): string; 1085 | computeSecret(other_public_key: string, input_encoding?: string, output_encoding?: string): string; 1086 | getPrime(encoding?: string): string; 1087 | getGenerator(encoding: string): string; 1088 | getPublicKey(encoding?: string): string; 1089 | getPrivateKey(encoding?: string): string; 1090 | setPublicKey(public_key: string, encoding?: string): void; 1091 | setPrivateKey(public_key: string, encoding?: string): void; 1092 | } 1093 | export function getDiffieHellman(group_name: string): DiffieHellman; 1094 | export function pbkdf2(password: string, salt: string, iterations: number, keylen: number, callback: (err: Error, derivedKey: string) => any): void; 1095 | export function pbkdf2Sync(password: string, salt: string, iterations: number, keylen: number) : Buffer; 1096 | export function randomBytes(size: number): Buffer; 1097 | export function randomBytes(size: number, callback: (err: Error, buf: Buffer) =>void ): void; 1098 | export function pseudoRandomBytes(size: number): Buffer; 1099 | export function pseudoRandomBytes(size: number, callback: (err: Error, buf: Buffer) =>void ): void; 1100 | } 1101 | 1102 | declare module "stream" { 1103 | import events = require("events"); 1104 | 1105 | export interface ReadableOptions { 1106 | highWaterMark?: number; 1107 | encoding?: string; 1108 | objectMode?: boolean; 1109 | } 1110 | 1111 | export class Readable extends events.EventEmitter implements NodeJS.ReadableStream { 1112 | readable: boolean; 1113 | constructor(opts?: ReadableOptions); 1114 | _read(size: number): void; 1115 | read(size?: number): any; 1116 | setEncoding(encoding: string): void; 1117 | pause(): void; 1118 | resume(): void; 1119 | pipe(destination: T, options?: { end?: boolean; }): T; 1120 | unpipe(destination?: T): void; 1121 | unshift(chunk: string): void; 1122 | unshift(chunk: Buffer): void; 1123 | wrap(oldStream: NodeJS.ReadableStream): NodeJS.ReadableStream; 1124 | push(chunk: any, encoding?: string): boolean; 1125 | } 1126 | 1127 | export interface WritableOptions { 1128 | highWaterMark?: number; 1129 | decodeStrings?: boolean; 1130 | } 1131 | 1132 | export class Writable extends events.EventEmitter implements NodeJS.WritableStream { 1133 | writable: boolean; 1134 | constructor(opts?: WritableOptions); 1135 | _write(data: Buffer, encoding: string, callback: Function): void; 1136 | _write(data: string, encoding: string, callback: Function): void; 1137 | write(buffer: Buffer, cb?: Function): boolean; 1138 | write(str: string, cb?: Function): boolean; 1139 | write(str: string, encoding?: string, cb?: Function): boolean; 1140 | end(): void; 1141 | end(buffer: Buffer, cb?: Function): void; 1142 | end(str: string, cb?: Function): void; 1143 | end(str: string, encoding?: string, cb?: Function): void; 1144 | } 1145 | 1146 | export interface DuplexOptions extends ReadableOptions, WritableOptions { 1147 | allowHalfOpen?: boolean; 1148 | } 1149 | 1150 | // Note: Duplex extends both Readable and Writable. 1151 | export class Duplex extends Readable implements NodeJS.ReadWriteStream { 1152 | writable: boolean; 1153 | constructor(opts?: DuplexOptions); 1154 | _write(data: Buffer, encoding: string, callback: Function): void; 1155 | _write(data: string, encoding: string, callback: Function): void; 1156 | write(buffer: Buffer, cb?: Function): boolean; 1157 | write(str: string, cb?: Function): boolean; 1158 | write(str: string, encoding?: string, cb?: Function): boolean; 1159 | end(): void; 1160 | end(buffer: Buffer, cb?: Function): void; 1161 | end(str: string, cb?: Function): void; 1162 | end(str: string, encoding?: string, cb?: Function): void; 1163 | } 1164 | 1165 | export interface TransformOptions extends ReadableOptions, WritableOptions {} 1166 | 1167 | // Note: Transform lacks the _read and _write methods of Readable/Writable. 1168 | export class Transform extends events.EventEmitter implements NodeJS.ReadWriteStream { 1169 | readable: boolean; 1170 | writable: boolean; 1171 | constructor(opts?: TransformOptions); 1172 | _transform(chunk: Buffer, encoding: string, callback: Function): void; 1173 | _transform(chunk: string, encoding: string, callback: Function): void; 1174 | _flush(callback: Function): void; 1175 | read(size?: number): any; 1176 | setEncoding(encoding: string): void; 1177 | pause(): void; 1178 | resume(): void; 1179 | pipe(destination: T, options?: { end?: boolean; }): T; 1180 | unpipe(destination?: T): void; 1181 | unshift(chunk: string): void; 1182 | unshift(chunk: Buffer): void; 1183 | wrap(oldStream: NodeJS.ReadableStream): NodeJS.ReadableStream; 1184 | push(chunk: any, encoding?: string): boolean; 1185 | write(buffer: Buffer, cb?: Function): boolean; 1186 | write(str: string, cb?: Function): boolean; 1187 | write(str: string, encoding?: string, cb?: Function): boolean; 1188 | end(): void; 1189 | end(buffer: Buffer, cb?: Function): void; 1190 | end(str: string, cb?: Function): void; 1191 | end(str: string, encoding?: string, cb?: Function): void; 1192 | } 1193 | 1194 | export class PassThrough extends Transform {} 1195 | } 1196 | 1197 | declare module "util" { 1198 | export interface InspectOptions { 1199 | showHidden?: boolean; 1200 | depth?: number; 1201 | colors?: boolean; 1202 | customInspect?: boolean; 1203 | } 1204 | 1205 | export function format(format: any, ...param: any[]): string; 1206 | export function debug(string: string): void; 1207 | export function error(...param: any[]): void; 1208 | export function puts(...param: any[]): void; 1209 | export function print(...param: any[]): void; 1210 | export function log(string: string): void; 1211 | export function inspect(object: any, showHidden?: boolean, depth?: number, color?: boolean): string; 1212 | export function inspect(object: any, options: InspectOptions): string; 1213 | export function isArray(object: any): boolean; 1214 | export function isRegExp(object: any): boolean; 1215 | export function isDate(object: any): boolean; 1216 | export function isError(object: any): boolean; 1217 | export function inherits(constructor: any, superConstructor: any): void; 1218 | } 1219 | 1220 | declare module "assert" { 1221 | function internal (value: any, message?: string): void; 1222 | module internal { 1223 | export class AssertionError implements Error { 1224 | name: string; 1225 | message: string; 1226 | actual: any; 1227 | expected: any; 1228 | operator: string; 1229 | generatedMessage: boolean; 1230 | 1231 | constructor(options?: {message?: string; actual?: any; expected?: any; 1232 | operator?: string; stackStartFunction?: Function}); 1233 | } 1234 | 1235 | export function fail(actual?: any, expected?: any, message?: string, operator?: string): void; 1236 | export function ok(value: any, message?: string): void; 1237 | export function equal(actual: any, expected: any, message?: string): void; 1238 | export function notEqual(actual: any, expected: any, message?: string): void; 1239 | export function deepEqual(actual: any, expected: any, message?: string): void; 1240 | export function notDeepEqual(acutal: any, expected: any, message?: string): void; 1241 | export function strictEqual(actual: any, expected: any, message?: string): void; 1242 | export function notStrictEqual(actual: any, expected: any, message?: string): void; 1243 | export var throws: { 1244 | (block: Function, message?: string): void; 1245 | (block: Function, error: Function, message?: string): void; 1246 | (block: Function, error: RegExp, message?: string): void; 1247 | (block: Function, error: (err: any) => boolean, message?: string): void; 1248 | }; 1249 | 1250 | export var doesNotThrow: { 1251 | (block: Function, message?: string): void; 1252 | (block: Function, error: Function, message?: string): void; 1253 | (block: Function, error: RegExp, message?: string): void; 1254 | (block: Function, error: (err: any) => boolean, message?: string): void; 1255 | }; 1256 | 1257 | export function ifError(value: any): void; 1258 | } 1259 | 1260 | export = internal; 1261 | } 1262 | 1263 | declare module "tty" { 1264 | import net = require("net"); 1265 | 1266 | export function isatty(fd: number): boolean; 1267 | export interface ReadStream extends net.Socket { 1268 | isRaw: boolean; 1269 | setRawMode(mode: boolean): void; 1270 | } 1271 | export interface WriteStream extends net.Socket { 1272 | columns: number; 1273 | rows: number; 1274 | } 1275 | } 1276 | 1277 | declare module "domain" { 1278 | import events = require("events"); 1279 | 1280 | export class Domain extends events.EventEmitter { 1281 | run(fn: Function): void; 1282 | add(emitter: events.EventEmitter): void; 1283 | remove(emitter: events.EventEmitter): void; 1284 | bind(cb: (err: Error, data: any) => any): any; 1285 | intercept(cb: (data: any) => any): any; 1286 | dispose(): void; 1287 | 1288 | addListener(event: string, listener: Function): Domain; 1289 | on(event: string, listener: Function): Domain; 1290 | once(event: string, listener: Function): Domain; 1291 | removeListener(event: string, listener: Function): Domain; 1292 | removeAllListeners(event?: string): Domain; 1293 | } 1294 | 1295 | export function create(): Domain; 1296 | } 1297 | --------------------------------------------------------------------------------