Code Monkey home page Code Monkey logo

strongly-typed-events-for-typescript's Introduction

Strongly Typed Events

Add the power of events to your projects. We even have 3 flavors for you.

Build Status npm version License: MIT

Event types

This project gives you the following event types:

  • Events - styled after the way .Net implements events. With each event you'll get a sender and an argument object. If you use typescript, you can implement them using generics.
    npm install ste-events or npm install ste-promise-events for event handlers that support Promise.
  • Simple events - basically the same thing, with only an argument.
    npm install ste-simple-events or npm install ste-promise-simple-events for event handlers that support Promise.
  • Signals - for when no data is needed, just the firing of the event is enough.
    npm install ste-signals or npm install ste-promise-signals for event handlers that support Promise.
  • You want them all? Just use
    npm install strongly-typed-events.

Subscription made easy

An example says more than a 1000 words. Imagine if you have events like this on your class:

let clock = new Clock("Smu", 1000);

//log the ticks to the console - this is a signal event
clock.onTick.subscribe(() => console.log("Tick!"));

//log the sequence parameter to the console - this is a simple event
clock.onSequenceTick.subscribe(s => console.log(`Sequence: ${s}`));

//log the name of the clock and the tick argument to the console - this is an event
clock.onClockTick.subscribe((c, n) =>
  console.log(`${c.name} ticked ${n} times.`)
);

Events made easy

So let's look at the implementation from a TypeScript perspective. (Do you program NodeJs without typescript? Check this.)

import { SignalDispatcher, SimpleEventDispatcher, EventDispatcher } from "strongly-typed-events";

class Clock {
  private _onTick = new SignalDispatcher();
  private _onSequenceTick = new SimpleEventDispatcher<number>();
  private _onClockTick = new EventDispatcher<Clock, number>();
  private _ticks: number = 0;

  constructor(public name: string, timeout: number) {
    setInterval(() => {
      this._ticks += 1;
      this._onTick.dispatch();
      this._onSequenceTick.dispatch(this._ticks);
      this._onClockTick.dispatch(this, this._ticks);
    }, timeout);
  }

  public get onTick() {
    return this._onTick.asEvent();
  }

  public get onSequenceTick() {
    return this._onSequenceTick.asEvent();
  }

  public get onClockTick() {
    return this._onClockTick.asEvent();
  }
}

Stopping events

You can stop events from being propagated.

let dispatcher = new SignalDispatcher();

  let a = 0;
  dispatcher.sub(ev => {
    a++;
    if (a > 2) {
      ev.stopPropagation();
    }
  });

  let b = 0;
  dispatcher.sub(() => { b++; });

  dispatcher.dispatch();
  dispatcher.dispatch();
  dispatcher.dispatch();
  dispatcher.dispatch();

  // a should be 4, because 4 dispatches are done.");
  // b should be 2, because events after the 2nd dispatch are stopped."

Check the documentation or the examples for more information.

Documentation

This project will help you to add events, event handling en event dispatching to your classes. To get you started, check:

History

Click here for more history...

Packages

Want a smaller package? Check out on of these:

Package Description
ste-core Package that contains all the building blocks for the creation of events. The dispatcher implementation is its main hero.
ste-events or ste-promise-events Events that are modeled after .Net with a sender and argument. If you use typescript, you can leverage the support for generics and get strongly typed code.
ste-simple-events or ste-promise-simple-events A simpler version of the ste-event-event. No sender, just an argument.
ste-signals or ste-promise-signals A signal is even simpler, it is just a callback for when you need to be alerted without any scope.
strongly-typed-events This package includes everything.
ste-browser Helps to host events in the browser.

Maintenance

This project is maintained by Kees C. Bakker.

strongly-typed-events-for-typescript's People

Contributors

dependabot-preview[bot] avatar dependabot[bot] avatar exusaltimus avatar jjordan-dff avatar keescbakker avatar kraciasty avatar silveredgold avatar tjenkinson avatar x3rax avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

strongly-typed-events-for-typescript's Issues

Transpiling issue with latest versions

image

I updated the version from 1.0.1 to the latest, and faced this issue while running some unit tests.
Looks like the issue is with transpiling :

Object.defineProperty(exports, "__esModule", { value: true });
**const** subscription_1 = __webpack_require__(4);
/**
* Base class for implementation of the dispatcher. It facilitates the subscribe
* and unsubscribe methods based on generic handlers. The TEventType specifies
* the type of event that should be exposed. Use the asEvent to expose the
* dispatcher as event.
*/
class DispatcherBase {
constructor() {
this._wrap = new DispatcherWrapper(this);
this._subscriptions = new Array();
}

My guess is something has changed with release version v1.1.3.
I am happy to use v1.0.1, but would be great if there is a fix for the problem I am facing with the latest versions, so I can switch to these anytime I want.

NOTE- If there is something that I need to fix on my end, just let me know!

Links in README as rendered by npmjs.com broken

Expected Behavior

If I click “Check this” at the npmjs page, I should see this page.

Current Behavior

When I click “Check this” at the npmjs page, I see this 404 page.

Possible Solution

It is possible this is an npmjs issue and needs to be raised with them. I believe they attempt to render README.md in a GitHub-compatible way, and this may be failing. It is also possible that the package’s README.md could be changed to be compatible with how npmjs renders them.

It might be a discrepancy between where the README.md is located in the GitHub tree compared to when it is distributed in the npmjs package. The README.md may be in a subdirectory of the GitHub repo, but when distributed in the npmjs package, it is treated as if it is as the root of the repo.

Steps to Reproduce

  1. https://www.npmjs.com/package/ste-signals
  2. Click “Check this” or “documentation” or “examples”.

Non-Uniform EventList and SimpleEventList using TArgsMap

Update (08/06): Revised the issue to focus on the issue rather than the proposed solution.

Background

The EvenList and SimpleEventList classes are unable to assist with non uniform event arg types. If I were to create an EventList for dispatching events with different event arguments types (lets say string and number), I would need to do this:

const myEvents = new SimpleEventList<number | string>();

events.get('event-two').subscribe((args: number | string) => {
  // Do type guard checks
});

events.get('event-one').subscribe((args: number | string) => {
  // Do type guard checks
});

This has several weaknesses.

  1. There is no declaration which event names are associated with which event argument type.
  2. When using get() to retrieve an EventDispatcher, there is no constraint of available event names (how do I know "event-one" is a valid event, but not "event-foo"?).

This makes EvenList and SimpleEventList not very useful for non-uniform event argument types. If we want to use EventList for non-uniform event types, we'll need to resort to a union or any type, giving us more work with type guards. It also is unclear what valid event names can be passed to get().

Proposed structure

Removed

Use Cases

I think some simple examples will help explain the use cases. Let's imagine we could supply a type map to SimpleEventList that would tell the SimpleEventList which event argument types correspond to which event names.

type MyEventsMap = {
  ['event-one']: string;
  ['event-two']: number;
};

const myEvents = new NonUniformSimpleEventList<MyEventsMap>();

events.get('event-two').subscribe((args: number) => {
  // args is definitely a number!
});

events.get('event-one').subscribe((args: string) => {
  // args is definitely a string!
});

events.get('event-one').dispatch({foo: 'bar'}) // <-- Type check error, argument {foo: 'bar'} is not compatible with string

events.get('wrong-event') // <-- Type check error, 'wrong-event' is not a key from MyEventsMap

Under the hood, event dispatching works exactly the same. But this interface allows us to manage a non-uniform list of dispatchers and constrain event names.

Proposal

I'd like to get input on a couple things:

  • Does this enhancement conflict with core design decisions of EventList/SimpleEventList?
  • Does this feature belong in new classes, or should it replace the interface for EventList and SimpleEventList?

If this addition makes sense, I'd like to prepare a pull request. I have a few approaches I've put together that work.

Thanks for taking the time to look over this!

Npm module not found by typescript "node" resolution strategy

Currently npm package is named "strongly-typed-events", but the definitions file in it is named "StronglyTypedEvents.d.ts". As a result typescript (version 1.8.10) cannot find the module after "npm install strongly-typed-events":
Error TS2307: Cannot find module 'strongly-typed-events
According to node resolution strategy described here, this is expected behavior of typescript.

I see two ways of fixing it:

  1. Rename StronglyTypedEvents.ts to strongly-typed-events.ts (and do the same for generated files).
  2. Add "typings": "StronglyTypedEvents.d.ts" line to package.json of npm module.

Handlers use implicit any type

When building using the library with definition files in a project, the following can occur:

ERROR in [at-loader] ./node_modules/strongly-typed-events/strongly-typed-events.ts:18:5
    TS7020: Call signature, which lacks return-type annotation, implicitly has an 'any' return type.

ERROR in [at-loader] ./node_modules/strongly-typed-events/strongly-typed-events.ts:28:5
    TS7020: Call signature, which lacks return-type annotation, implicitly has an 'any' return type.

ERROR in [at-loader] ./node_modules/strongly-typed-events/strongly-typed-events.ts:35:5
    TS7020: Call signature, which lacks return-type annotation, implicitly has an 'any' return type.

strongly-typed-events.ts needs to define the return type for such cases.

Unsubbing bound method doesn't work

Trying to unsub a bound method from a SignalDispatcher. No unsubbing is finding the place.

Expected Behavior

I tried subscribing to an event with a bound method to access a class like this:

let onUpdate = new SignalDispatcher = new SignalDispatcher();
let component = new Component();
onUpdate.sub(component.Update.bind(component));

void Update(){
 this.onUpdate.dispatch();
}

class Component {
 public Update(){
  //do stuff
 }
}

Current Behavior

However, when I try to unsubscribe from the event with the same method, It won't subscribe. Removing the bind works however but then I can't access 'this' in the component.

Context (Environment)

I'm trying to create an entity-component-based Engine. For the main loops, I want to use this event system.

Cannot load module: does not provide an export named 'SimpleEventDispatcher'

Hi all!

I've got a problem when loading the package in my Typescript application. I've installed the package using yarn:
yarn add strongly-typed-events.

When i run my application i get the following error in the console of the browser.

Uncaught SyntaxError: The requested module './../../../node_modules/strongly-typed-events/dist/index.js' does not provide an export named 'SimpleEventDispatcher'

I think it has something to do with the way Typescripts loads the libraries? (i've got limit knowledge on ts.)

I've got the following tsconfig.json:

{
  "compilerOptions": {
    "target": "es2018",
    "module": "esnext",
    "moduleResolution": "node",
    "noEmitOnError": true,
    "lib": ["es2017", "dom"],
    "strict": true,
    "esModuleInterop": false,
    "outDir": "out-tsc",
    "rootDir": "./",
    "experimentalDecorators": true,
    "resolveJsonModule": true,
    "allowSyntheticDefaultImports": true
  },
  "include": ["./src/**/*.ts"]
}

in my application i load the SimpleEventDispatcher by importing the library:

import { SimpleEventDispatcher } from 'strongly-typed-events';

The Typescript compiler does not complain about this, it's only when i run the application in the browser i get the message.

What am i missing?

Handle event in Stencil app

I have a Stencil app with several pages. One page shall be notified and reload if something happens on another page. How can I listen for signal event on another page?

Add dispose method

Hi,

could you add dispose/clear method to clear all subscriptions?

It will be useful for scenarios where objects are created and destroyed frequently.

Thanks

Feature request: Make events cancellable

Sometimes a "third-party" developer wants to cancel some task. Imagine an event of a data change where developer wants to abort the change. He should be able to call eventManagement.cancel() where the dispatch function at event should return boolean if event was cancelled.

Of-course this should be possible only in "pre-events" or developer makes undo action when event.isCancelled().

Possible Solution

1.) Change dispatch's return type to boolean
2.) Add cancel() and isCancelled() to IEventManagement or add ability to set custom EventManagement and link it inside events.

Context (Environment)

I'm developing WYSIWYG editor and I want to make it flexible as is it possible. In my project I'm using strongly-typed-events everywhere but this is the last puzzle what I am missing to have great result. If you are not able to modify existing functions then could you add something like: dispatchCancellable?

Possible Implementation

An example on Car class

class Car {
  private health: number = 10;
  private _onCarDestroy: EventDispatcher<Car, any> = new EventDispatcher<Car, any>();

  onCarDestroy(): IEvent<Car, any> { return this._onCarDestroy.asEvent() }

  destroyCar(): void {
    const result = this._onCarDestroy.dispatch(this) // or this._onCarDestroy.dispatchCancellable(this)

    // with "EventStatus" enum
    if(result === EventStatus.OK) {
      this.health = 0;
    }

    // with boolean solution
   if(result) {
      this.health = 0;
   }
  }
}

const car = new Car();
car.onCarDestroy.subsribe((car, _, eventManagement) => {
  if(car.isAdmin()) { // or any other variable not related to car instance
    eventManagement.cancel(); // makes `result` above "false" or "EventStatus.Cancelled"
  }
})

Sure I can do something like:

const eventArgs = {_cancelled: false, cancel() => {...})
event.dispatch(eventArgs);
if(eventArgs._cancelled) ....

but why developer should find "unsub" and "stopPropagation" in different argument than cancel function. It will make the project a little bit messy.

Having an ability to adjust EventManagement instance will be enough.

Unsubscribe during dispatching Events

Hi, I faced problem during dispatching events. I have few objects, that are subscribed for target object update. When the target object is updated the dispatcher is going through the array of subscribers and runs their reactiong routines. But my app logic in those reaction routines could decide to unsubscribe. The unsubscription goes well, but it is directly affecting the subscription array during the dispatching events to other subscribers.
For example I have 2 subscribers. First is informed and his reaction routine unsubscribe it from the subscription array. Then there should be second round for dispatcher to inform second subscriber, but the length of the subscription array is suddenly only 1 and because of that the FOR routine in dispatcher will never try to reach the second subscriber.
I have resolved this with copying the subscription array and dispatching events from copy, which is not affected from original which is changed via unsubscribing by listener. Like this:

protected _dispatch(executeAsync: boolean, scope: any, args: IArguments): void {
            let copy = new Array<Subscription<TEventHandler>>();
            copy = this._subscriptions.slice();
            for (let i = 0; i < copy.length; i++) {
                let sub = copy[i];
             ...

Another solution could be, to set some lock for the subscription array, and let the unsubscribing routine to wait, until the lock will be set off.

I hope it is understandable, because it is quite complicated to explain even in my mother language :)

How to use STE with namespace project?

I am relatively new to TypeScript, so excuse me if that is a dumb question.

My web project is build with namespaces (https://www.typescriptlang.org/docs/handbook/namespaces.html) instead of modules. I use the latest version of STE, so I updated my package.json like so and did an npm install (all fine):

    "ste-core": "^1.4.3",
    "ste-events": "^1.4.3",
    "ste-signals": "^1.4.3",
    "ste-simple-events": "^1.4.3",
     "strongly-typed-events": "^1.4.3"

Now, with namespaces I do not use import statements, if I understand it correctly (when I try it it breaks my code). So normally I just write var ttt = new SimpleEventDispatcher<number>();. But the compiler tells me that it cannot find name SimpleEventDispatcher and so on.

One possibility is to declare a reference path like ///<reference path="..\node_modules\ste-simple-events\dist\index.d.ts"/>. But this leads this error:
node_modules/ste-simple-events/dist/definitions.d.ts(1,69): error TS2307: Cannot find module 'ste-core'.

I tried a test project using no namespaces but import statements and this does work. So the question is, is there a way to use it with namespace style and/or do I something wrong? Thanks a lot!

Error when using Webpack UglifyJsPlugin mangle=true

When I have this config in webpack.config.js:

config.plugins.push( new webpack.optimize.UglifyJsPlugin({
      mangle: true,
 }));

resulted:
i.default.createEventDispatcher is not a function.
Tested in Node and browser.

I made some hack in the source code, and it worked:
(Not sure if it's the correct way)

(function () {
    var exportables = [
        EventDispatcher, SimpleEventDispatcher, SignalDispatcher,
        EventList, SimpleEventList, SignalList,
        EventHandlingBase, SimpleEventHandlingBase, SignalHandlingBase,
        createEventDispatcher, createSimpleEventDispatcher, createSignalDispatcher,
        createEventList, createSimpleEventList, createSignalList
    ];
   var exportable_names = [
        'EventDispatcher', 'SimpleEventDispatcher', 'SignalDispatcher',
        'EventList', 'SimpleEventList', 'SignalList',
        'EventHandlingBase', 'SimpleEventHandlingBase', 'SignalHandlingBase',
        'createEventDispatcher', 'createSimpleEventDispatcher', 'createSignalDispatcher',
        'createEventList', 'createSimpleEventList', 'createSignalList'
    ];
    // Node: Export function
    if (typeof module !== "undefined" && module.exports) {
        exportables.forEach(function (exp,i) { return module.exports[exportable_names[i]] = exp; });
    }

Webpack Build Errors: An accessor cannot be declared in an ambient context

Expected Behavior

Project builds with webpack through Vue UI.

Current Behavior

It does not, it throws errors.

Steps to Reproduce

  1. Start a webpack/Vue Project
  2. Add this library
  3. Try to build

(Not sure if this is reproducible that way?)

Enviornment

TypeScript 3.5.3

 error  in [RedactedPath]/ClientApp/node_modules/ste-core/dist/dispatching.d.ts

ERROR in [RedactedPath]/ClientApp/node_modules/ste-core/dist/dispatching.d.ts
19:9 An accessor cannot be declared in an ambient context.
    17 |      * @memberOf DispatcherBase
    18 |      */
  > 19 |     get count(): number;
       |         ^
    20 |     /**
    21 |      * Subscribe to the event dispatcher.
    22 |      * @param fn The event handler that is called when the event is dispatched.

 error  in [RedactedPath]/ClientApp/node_modules/ste-core/dist/dispatching.d.ts

ERROR in [RedactedPath]/ClientApp/node_modules/ste-core/dist/dispatching.d.ts
119:9 An accessor cannot be declared in an ambient context.
    117 |      * @memberOf DispatcherWrapper
    118 |      */
  > 119 |     get count(): number;
        |         ^
    120 |     /**
    121 |      * Subscribe to the event dispatcher.
    122 |      * @param fn The event handler that is called when the event is dispatched.

 error  in [RedactedPath]/ClientApp/node_modules/ste-events/dist/events.d.ts

ERROR in [RedactedPath]/ClientApp/node_modules/ste-events/dist/events.d.ts
74:19 An accessor cannot be declared in an ambient context.
    72 |      * Gets the list with all the event dispatchers.
    73 |      */
  > 74 |     protected get events(): EventList<TSender, TArgs>;
       |                   ^
    75 |     /**
    76 |      * Subscribes to the event with the specified name.
    77 |      * @param name The name of the event.

 error  in [RedactedPath]/ClientApp/node_modules/ste-signals/dist/signals.d.ts

ERROR in [RedactedPath]/ClientApp/node_modules/ste-signals/dist/signals.d.ts
45:19 An accessor cannot be declared in an ambient context.
    43 | export declare abstract class SignalHandlingBase implements ISignalHandling {
    44 |     private _events;
  > 45 |     protected get events(): SignalList;
       |                   ^
    46 |     /**
    47 |      * Subscribes once to the event with the specified name.
    48 |      * @param name The name of the event.

 error  in [RedactedPath]/ClientApp/node_modules/ste-simple-events/dist/simple-events.d.ts

ERROR in [RedactedPath]/ClientApp/node_modules/ste-simple-events/dist/simple-events.d.ts
69:19 An accessor cannot be declared in an ambient context.
    67 | export declare abstract class SimpleEventHandlingBase<TArgs> implements ISimpleEventHandling<TArgs> {
    68 |     private _events;
  > 69 |     protected get events(): SimpleEventList<TArgs>;
       |                   ^
    70 |     /**
    71 |      * Subscribes to the event with the specified name.
    72 |      * @param name The name of the event.

Library bundle for easier consumption across modules

In our application we have various projects that are bundle independently and we would like to be able to use this library across all of them.

But the npm package does not come with a UMD bundle that we could set as an external in webpack.

Exported external package typings file is not a module

I have installed npm package, and now I try to use it in typescript 1.8.10:
import events from 'strongly-typed-events';
This gives me the following error (given that module resolution is fixed, of course):

Error TS2306: File 'node_modules/strongly-typed-events/StronglyTypedEvents.d.ts' is not a module.
Error TS2656: Exported external package typings file 'node_modules/strongly-typed-events/StronglyTypedEvents.d.ts' is not a module. Please contact the package author to update the package definition.

It seems that currently the module is not easily usable.

Angular warning

Hi!

I just started using this tool and I really love it, kudos for the work :D

I am using it on a Game I am making using Angular, so that classes can talk to each other with events, and when I build the Angular project using ng build --prod I get this warning:

Warning: .../play-player.class.ts depends on 'strongly-typed-events'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies

Expected Behavior

The expected behavior would be to see no warning.

Current Behavior

There is no problem, it's just a warning and everything works as expected, but I'm opening this issue in case it really is causing any optimization problem I'm just not aware of.

Possible Solution

Sorry, can help on how to fix it.

Steps to Reproduce

  1. Download repo https://github.com/igorosabel/Game
  2. npm install
  3. ng build --prod
  4. See the warning

Context (Environment)

This warning shows on macOS as on Windows.
Also shows both on Angular 10 (where I started using it) as on Angular 11 (which was just released yesterday).

Thanks!

@Types ?

HI,
I am using a Webpack based Project which uses @types.
What is the best way to integrate Strongly-Typed-Events-for-TypeScript in such a project please?

Add support for `thisArg`

Due to the nature of JavaScript, method contexts (i.e., this reference) could change depending on the way of invocation. In STE, using subscribe or sub without binding the listener method to the calling context would result in unexpected results.

For example:

import { ISimpleEvent, SimpleEventDispatcher } from "ste-simple-events";

const event = new SimpleEventDispatcher();
const foo = new Foo();
event.subscribe(foo.bar); // Dynamic-context subscription.
event.subscribe(foo.bar.bind(foo)); // Static-context subscription.
event.dispatch();

class Foo {
  dummy = 1;
  bar() { console.log(this.dummy); }
}

Here, the first subscription results in unexpected behavior due to its dynamic context, however, this is not totally unexpected due to the nature of the language.

Currently I'm using the binding method (second subscription), but it would be better for STE to take another argument as thisArg to hold the context and do the binding behind the scene, which complies with the current well-known conventions in the JS/TS community. Obviously, the argument is meant to be optional.

Cannot read property 'DispatcherBase' of undefined

I'm trying to use ste-browser package, but by writing this html i get the error in the title:

<!DOCTYPE html>
<html>
    <head>
        <script src="https://cdn.jsdelivr.net/npm/ste-browser/dist/ste-simple-events.js"></script>
    </head>
    <body>
        aaa
    </body>
</html>

maybe i'm missing something or the documentation needs some integrations?
Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.