Git Product home page Git Product logo

deepsignal's People

Contributors

adanperez avatar aralroca avatar billybimbob avatar codyjasonbennett avatar darerodz avatar developit avatar dhananjay-jsr avatar eddyw avatar elliotwaite avatar evansd avatar filiptammergard avatar github-actions[bot] avatar jhuleatt avatar jmeistrich avatar jossmac avatar jovidecroock avatar jviide avatar keichinger avatar kim3er avatar luisherranz avatar marvinhagemeister avatar melnikov-s avatar nazimamin avatar nichoth avatar obahareth avatar pauan avatar rschristian avatar skvale avatar sun0day avatar tjenkinson 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

deepsignal's Issues

"export 'effect' was not found in 'deepsignal'

Hi,
I am new to deepsignals.
I face this issue when using effect as the example in Readme.md:

effect(() => {
console.log(state.counter);
});

Could you pls help to let me know where effect should i import from? Do i need to use effect from Signals along with Deepsignals?

Stop deepSignal from proxying certain properties or classes

Problem

Currently shouldProxy omits functions and builtins from proxying https://github.com/luisherranz/deepsignal/blob/main/packages/deepsignal/core/src/index.ts#L137-L144, however in the project I'm working on currently we have other classes that are being stored in a deepsignal that we need to omit from proxying (in this case because they are already proxies and double-proxying causes issues).

Current Workaround

I was able to work around the problem for now by adding the constructor to globalThis so that deepsignal thinks it's a builtin, but this isn't ideal. It seems quite likely to me that there will be other use cases that will have classes that want to be stored in deepsignal but not have them proxied from one reason or another.

Proposed Solutions

I can see a few ways this might be solved:

  • a helper function
import { deepSignal, omit } from 'deepsignal';

deepSignal({ a: { b: 1 }, c: omit({ d: 2 }) })
  • a second argument for options
import { deepSignal, omit } from 'deepsignal';

deepSignal({ a: { b: 1 }, c: { d: 1 } }, { omit: ['c'] })
  • expose a list of constructors should proxy omits (less flexible but only needs to be specified once per constructor)
import { deepSignal, omit } from 'deepsignal';

omit(SomeConstructor);
deepSignal({ a: { b: 1}, c: new SomeConstructor({ d: 1 }) });

I think this functionality could be added without adding too much to size bundle. If you're open to this functionality being added but don't have time to add it, let me know what your preferred path would be and I'd be happy to send you a PR.

[Enhancement] implement "defineProperty" trap as well

Object.defineProperty is a commonly used approach to define new object properties - internally, Reflect.set(...) will invoke Object.defineProperty anyway whenever a new property is to be set.

For that reason, it is a good idea to implement the "defineProperty" trap in order to catch all situations, where new properties are defined.

The required changes should be trivial (see my own fork of your repository)

[Enhancement] allow object properties named "$"

$ is a common name for object properties, particularly in browser environments (the best-known example should be jQuery)

While it is a nice idea to access object property signals using $name or array element signals using $[index], it should remain possible to use $ by itself as the name of an object (not an array) property - and $$ as the name for its related signal.

The required changes should be trivial (see my own fork of your repository)

Enhancement: get informed about insertion/removal of properties

First of all: thank you very much for your marvellous work!

It looks brilliant - but lacks a feature I currently need: I want to get informed whenever a new property is added to an observed object.

After looking into your code, I quickly hacked the required changes in a way I can live with - but these changes are neither properly tested nor completely free of side effects (I'm currently using a "helper property" with a literal key rather than a JavaScript symbol - I did that in order not to touch too many parts of your code)

If you are interested, just have a look into my fork - perhaps, you'll come up with a better (or more professional) solution?

Unproxy an array

In my code, I need to get the "raw" array from my deepsignal state, and I thought the RevertDeepSignal type might help me get there, but while I can get a clean array back - all of the 20,000 items in that array are Proxy objects. When I pass the array to a function that has no concept of signals, it treats the array as if it were empty.

Please take a look at the demonstrate() function below to see how I was hoping to get the raw array value back.

Note: in my particular case, I don't need the items in the arrays to be "deepsignaled", and those item's properties, and those item's properties... Just the array itself.

I'm not sure if that is an option?

interface WorkbookState {
  loadingState: WorkbookLoadingState;
  attributes: Attribute[];
  categories: Category[];
  hierarchies: Hierarchy[];
  hierarchy: Hierarchy | null;
  hierarchyNodes: HierarchyNode[];
  lrsSegments: Segment[];
  segments: Segment[];
  trees: ExplicitDataSource<PlanningTreeData> | null;
  workbook: Workbook | null;
}

const initialState: WorkbookState = {
  attributes: [],
  categories: [],
  hierarchy: null,
  hierarchyNodes: [],
  hierarchies: [],
  loadingState: WorkbookLoadingState.Initial,
  lrsSegments: [],
  segments: [],
  trees: null,
  workbook: null,
};

const store: WorkbookStore = {
  state: deepSignal<WorkbookState>(initialState),

  closeWorkbook,
  openWorkbook,
  setHierarchy,
};

const demonstrate = () => {
    const attributes: Attribute[] = Object.values<Attribute>(
      store.state.attributes as RevertDeepSignal<typeof store.state.attributes>,
    );

    // while the attributes array is properly types, attributes[n] are Proxy objects.

    // when I pass them to my AttributeLookup class, they do not work because the elements are Proxy objects
    const attributeLookup = new AttributeLookup(attributes);

    // my current work around is to do a deep copy of property to eliminate proxies
    const attributes: Attribute[] = toRaw(store.state.attributes);
}

function toRaw(val: any): any {
  if (val instanceof Array) return val.map((val) => toRaw(val));
  if (val instanceof Object)
    return Object.fromEntries(
      Object.entries(Object.assign({}, val)).map(([k, v]) => [k, toRaw(v)]),
    );
  return val;
}

Type errors with nested object types

Hi @luisherranz

I'd like to start off by saying I think the API you've written here is absolutely excellent. I've rewritten around 1000 lines of old contexts to deep signals, and everything is way easier to reason with.

I have run into one issue so far, and this might be entirely down to user error. I've narrowed things down to the minimal reproduction below

import { deepSignal } from "deepsignal";

type Example = {
  testKey: Record<string, string | boolean>;
};

const initialState: Example = {
  testKey: { testValue: false },
};

const state = deepSignal<Example>(initialState);

const testKey: Example["testKey"] = { testValue: true };

state.testKey = testKey;

I get the following error:

Type 'Record<string, string | boolean>' is not assignable to type 'DeepSignalObject<Record<string, string | boolean>>'.
  Type 'Record<string, string | boolean>' is not assignable to type '{ [x: `$${string}`]: Signal<string | boolean> | undefined; }'.
    'string' and '`$${string}`' index signatures are incompatible.
      Type 'string | boolean' is not assignable to type 'Signal<string | boolean> | undefined'.
        Type 'string' is not assignable to type 'Signal<string | boolean>'.ts(2322)

I see a similar error with

type Example = {
  testKey: { [key: string]: string | boolean };
};

however if I change the string into a literal,

type Example = {
  testKey: Record<"someLiteral", string | boolean>;
};

or

type Example = {
  testKey: { ["someLiteral"]: string | boolean};
};

I no longer get the error. I have tried various permutations of using optional values / undefined unions, but to no real avail.

Do you see anything here that I'm doing incorrectly here?

Thanks very much!

Getters make the component re-renders when using signals

Hi there ! Thank you for this lib, it makes a perfect combo with preact/signals.

When I use the counter example in React from the docs :

import { deepSignal } from "deepsignal";

const state = deepSignal({
	count: 0,
	get double() {
		return state.count * 2;
	},
});

function Counter() {
	return (
		<button onClick={() => (state.count += 1)}>
			{state.$count} x 2 = {state.$double}
		</button>
	);
}

the component is re-rendered when I use {state.$double}.

The same computed value doesn't make a re-render when I use it with preact directly: const double = computed(() => count.value*2).

If I use the same principe with deepsignal, it doesn't make a re-render :

get double() {
		return computed(() => state.count * 2);
},

In the docs, you wrote : deepsignal will convert getters to computed values instead of signal instances underneath.

So I am not sure what's happening here. Is it the behaviour we should expect when using the signal state.$double ?

Thanks a lot for your help !

overwrapping proxies

Hi luisherranz

First of all thank u for the nice library.
Is the smoothest state management dx in react imo. Dangerously smooth!

I came across a bit of an unpleasantry in dx with what looks like stale state, caused by unwanted nesting of the proxy-state.

Say I have the following store

const store = deepsignal({ renderedNode: undefined, nodes:  [{id: 1, x: 0, y: 0}, ...])

if I would do

store.renderedNode = store.nodes[0];

store.renderedNode would become a nested proxy.
accessing and mutating this proxy would cause inconsistent state, I assume because the outer-proxy consumes all the mutations.

It is possible to prevent this bug by doing

store.$renderedNode.value = store.nodes[0];

But I wonder if it would be possible to prevent this overwrapping/unwanted nesting automatically, p.ex by checking for a symbol on the proxy.

I think solidjs does something similar with their createStore.

Missing React peer dependency

Hey @luisherranz! I've been working on incorporating @wordpress/ package updates into Calypso. The published packages has a peer dependency violation:

deepsignal@npm:1.3.4 [411e6] doesnt provide react (p9b425), requested by @preact/signals-react

yarn explain peer-requirements p9b425
➤ YN0000: deepsignal@npm:1.3.4 [411e6] doesnt provide react, breaking the following requirements:

➤ YN0000: @preact/signals-react@npm:1.3.4 [ed871]   → ^16.14.0 || 17.x || 18.x      ✘
➤ YN0000: use-sync-external-store@npm:1.2.0 [23689] → ^16.8.0 || ^17.0.0 || ^18.0.0 ✘

➤ YN0000: Note: these requirements start with @preact/signals-react@npm:1.3.4 [ed871]

While I've just ignored the error on our side, I think this warning will show up in most dependency tools when installing deepsignal.

Support setters

Sorry for bothering you, but I must be completely blind right now...

Consider the following code

  import { deepSignal } from 'https://unpkg.com/[email protected]/dist/deepsignal.module.js'

  let Test = deepSignal({
    _x:0,
    get x () { return this._x },
    set x (newX) {
      if (newX !== this.x) { this._x = newX }
    }
  })

  console.log('Test.x is defined as',Object.getOwnPropertyDescriptor(Test,'x'))

  console.log('\ntrying to set "Test.x" to 1\n')
  Test.x = 1

This code crashes with:

Test.x is defined as {enumerable: true, configurable: true, get: ƒ, set: ƒ}
  configurable: true
  enumerable: true
  get: ƒ x()
  set: ƒ x(newX)
  [[Prototype]]: Object

trying to set "Test.x" to 1

index.ts:103 Uncaught TypeError: Cannot set property value of [object Object] which has only a getter
    at Object.set (index.ts:103:30)
    at VM6069 about:srcdoc:28:10

Do you have any idea why my code fails? I had the impression, that deepSignal would support getters and setters...

Support for @preact/signals-react with DeepSignals

I am using @preact/signals-react with react-native and it works but in many places I have a deeply nested object, to which I need to listen to property changes and re-render accordingly.
DeepSignals with @preact/signals-react would be the ideal solution.

Error computed side-effects error when accessing getter

When attempting to write a getter which consolidates a nested object, signals throws an error.

Reproduction:

const state = deepSignal({
  x: {
    a: 1,
    b: 2,
  },
  get y() {
    return Object.values((state.x as RevertDeepSignal<typeof state.x>) ?? {});
  },
});

console.log(state.y);

Error:

Error: Computed cannot have side-effects
      at mutationDetected (node_modules/.pnpm/@[email protected]/node_modules/@preact/signals-core/src/index.ts:5:8)
      at value (node_modules/.pnpm/@[email protected]/node_modules/@preact/signals-core/src/index.ts:314:4)
      at Object.values [as ownKeys] (node_modules/.pnpm/[email protected][email protected]/node_modules/deepsignal/core/src/index.ts:120:29)
      at Function.values (<anonymous>)

[Bug?] an array nested in an object added to an observed object is not properly observed

It took me quite a while to figure out, but when trying the following code

  let hugo = deepSignal({ })
  let anna = hugo.anna = {
    _list:[1,2,3],
    get list () { return this._list.slice() }
  }

  effect(() => { console.log('> anna.list',anna.list) })

  console.log('assign')
    anna._list = anna._list.slice(0,2).concat(2.5,anna._list.slice(2))
    anna._list = anna._list.slice(0,2).concat(anna._list.slice(3))

you will see that changes to anna.list will not be recognized.

There is, however, a simple workaround: just observe anna itself

  let anna = hugo.anna = deepSignal({
    _list:[1,2,3],
    get list () { return this._list.slice() }
  })

and everything works as intended

Shouldn't type DeepSignalObject be exported?

I'm attempting to create a store using deepsignal in TypeScript.

I'm having a problem when I attempt to type my store, and in particular my Store's state object. Don't I need to declare state as a type of DeepSignalObject? But that type is not exported from the library.

interface AuthState {
  auth: boolean;
}

interface AuthActions {
  isAuthenticated: () => boolean;
  setIsAuthenticated: (isAuthenticated: boolean) => void;
  signOut: () => void;
}

interface DeepAuthState {
  state: DeepSignalObject<AuthState>;
}

type AuthStore = DeepAuthState & AuthActions;

export const authStore: AuthStore = {
  state: deepSignal<AuthState>({
    auth: false,
  }),

  isAuthenticated() {
    return this.state.auth;
  },

  setIsAuthenticated(isAuthenticated: boolean): void {
    this.state.auth.value = isAuthenticated;
  },

  signOut(): void {
    setIsAuthenticated(false);
  },
};

Support Maps.

Cannot proxy a Map.
I get,

Uncaught Error: This object can't be observed.

Feature request: computed

I like the DX of using the signal.value by default and accessing the underlying signal with the $ prefix, but context switching when using computed values is awkward. It would be nice to provide computed with the same functionality as Preact's computed, only returning a proxy object instead for the improved DX

Unable to update input field values

import * as React from "react";
import Box from "@mui/material/Box";
import TextField from "@mui/material/TextField";
import { useSignal } from "@preact/signals-react";
import { useDeepSignal } from "deepsignal/react";

export default function BasicTextFields() {
  const state = useDeepSignal({
    textField1: "",
    textField2: "",
    textField3: ""
  });

  const onHandleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const { name, value } = event.target;
    state[name] = value;
  };

  return (
    <Box
      component="form"
      sx={{
        "& > :not(style)": { m: 1, width: "25ch" }
      }}
      noValidate
      autoComplete="off"
    >
      <TextField
        name="textField1"
        id="outlined-basic"
        label="Outlined"
        variant="outlined"
        onChange={onHandleChange}
        value={state.$textField1.value}
      />
      <TextField
        name="textField2"
        id="filled-basic"
        label="Filled"
        variant="filled"
        onChange={onHandleChange}
        value={state.$textField2.value}
      />
      <TextField
        name="textField3"
        id="standard-basic"
        label="Standard"
        variant="standard"
        onChange={onHandleChange}
        value={state.$textField3.value}
      />
    </Box>
  );
}

Why am I not able to update the textField values? I want to have a common changeHandler. Thanks.

This is my stackblitz: https://codesandbox.io/s/affectionate-worker-tkgfqv?file=/demo.tsx:0-1303

deleting a key does not trigger effects

example:

const sign = deepSignal<{ key?: string }>({  });

setTimeout(() => {
  sign.key = 'value';
}, 1000);

setTimeout(() => {
  delete sign.key;
}, 2000);

effect(() => {
  console.log('sign', sign.key);
});

expected behavior:

  1. log undefined
  2. after 1 second log value
  3. after 2 seconds log undefined

current behavior:

  1. log undefined
  2. after 1 second log value

see for an example with solid's createMutable

Support for classes

Consider the following code:

  import { deepSignal }  from 'https://unpkg.com/[email protected]/dist/deepsignal.module.js'

  class TestClass {
    _Prop = 0

    get Prop () { return this._Prop }
    set Prop (newValue) {
      this._Prop = newValue
      this.logIt()
    }

    logIt () {
      console.log('internal report: Prop was just set to',this.Prop)
    }
  }

  let Test = deepSignal(new TestClass())

/**** now run some tests ****/

  console.log('observe "Test.Prop"')
  effect(() => {
    console.log('>>>> external effect: current "Prop" is now',Test.Prop)
  })

  console.log('\nsetting Test.Prop to 1\n\n')
  Test.Prop = 1

  console.log('\nsetting Test.Prop to 2\n\n')
  Test.Prop = 2

(mind the import statement which imports your published module without any of my modifications!)

This code produces the following output:

observe "Test.Prop"
>>>> external effect: current "Prop" is now 0
 
setting Test.Prop to 1

>>>> external effect: current "Prop" is now 0
internal report: Prop was just set to 0
>>>> external effect: current "Prop" is now 1

setting Test.Prop to 2

>>>> external effect: current "Prop" is now 1
internal report: Prop was just set to 1
>>>> external effect: current "Prop" is now 2

I don't really worry about the useless effect callback invocations for already set values (although they are a bit ugly), but I worry about getter invocations following a set operation which still deliver an old value!

Do you have any idea?

Update effect after change to any property of any element in array

Hi,

Thanks for the excellent library.

I think I'm missing something fundamental but is it possible to define an effect that will update after any change to an array of objects, and not just a specific property of one of the objects?

Here's an example of what I mean:

const state = deepSignal({
  myArray: [
    {
      count: 0,
    },
    {
      count: 0,
    },
  ],
});

const IncrementArray = () => {
  return (
    <Button onClick={() => state.myArray[0].count++}>Increment</Button>
  );
};

// Updates after increment
effect(() => {
  if (state.myArray[0].count) {
    console.log("state.myArray[0].count has changed");
  }
});

// Doesn't update after increment
effect(() => {
  if (state.myArray[0]) {
    console.log("state.myArray[0] has changed");
  }
});

// Also doesn't update after increment
effect(() => {
  if (state.myArray) {
    console.log("state.myArray has changed");
  }
});

Is there any way to write either of those last two effects so that they will trigger when any property changes for any element in the array?

I know I can get the second effect working by incrementing the count like this instead:

 <Button
        onClick={() =>
          (stateTest.myArray[0] = {
            ...stateTest.myArray[0],
            count: stateTest.myArray[0].count + 1,
          })
        }
      >
        Increment
      </Button>

But I am really loving the ability to modify the property directly that this library provides.

Thanks!

[Bug] intermediate "effect" invocations during array changes with wrong values

Consider the following code:

  import { effect } from '@preact/signals-core'
  import { deepSignal } from 'deepsignal'

  let hugo = deepSignal({
    list:[1,2,3]
  })

  effect(() => { console.log('> hugo.list',JSON.stringify(hugo.list)) })

  console.log('push');    hugo.list.push(4)                 // works as intended
  console.log('pop');     hugo.list.pop()          // -> [1,2,3,null] -> [1,2,3]
  console.log('shift');   hugo.list.shift() // [2,2,3] > [2,3,3] > [2,3,null] > [2,3]
  console.log('unshift'); hugo.list.unshift(1)    // [2,3,3] > [2,2,3] > [1,2,3]
  console.log('insert');  hugo.list.splice(2,0,2.5)   // [1,2,3,3] > [1,2,2.5,3]
  console.log('delete');  hugo.list.splice(2,1) // [1,2,3,3] > [1,2,3,null] > [1,2,3]

  console.log('assign')
    hugo.list = hugo.list.slice(0,2).concat(2.5,hugo.list.slice(2)) // reacts 2x

This code produces the following output:

> hugo.list [1,2,3]
push
> hugo.list [1,2,3,4]
pop
> hugo.list [1,2,3,null]
> hugo.list [1,2,3]
shift
> hugo.list [2,2,3]
> hugo.list [2,3,3]
> hugo.list [2,3,null]
> hugo.list [2,3]
unshift
> hugo.list [2,3,3]
> hugo.list [2,2,3]
> hugo.list [1,2,3]
insert
> hugo.list [1,2,3,3]
> hugo.list [1,2,2.5,3]
delete
> hugo.list [1,2,3,3]
> hugo.list [1,2,3,null]
> hugo.list [1,2,3]
assign
> hugo.list [1,2,2.5,3]
> hugo.list [1,2,2.5,3]

As you can see, the effect callback is invoked far too often - and the intermediate calls often log wrong lists (at least "wrong" from a functional point of view, what we see here might reveal some unwanted implementation details)

Resetting the initial state of a deepSignal

I didn't see in the unit tests or the documentation an example on how one might set the entire state object.

I assume if I can extract the values using RevertDeepSignal, there might be a mechanism to set the values?

Take the following example. I assume that closeWorkbook2() will work as expected, but is there a simpler approach that works more like closeWorkbook1?

enum WorkbookLoadingState {
  Initial,
  Loading,
  Success,
  Error,
}

interface WorkbookState {
  loadingState: WorkbookLoadingState;
  attributes: Attribute[];
  categories: Category[];
  hierarchies: Hierarchy[];
  hierarchy: Hierarchy | null;
  hierarchyNodes: HierarchyNode[];
  lrsSegments: Segment[];
  segments: Segment[];
  trees: ExplicitDataSource<PlanningTreeData> | null;
  workbook: Workbook | null;
}

interface WorkbookActions {
  loadWorkbook: (workbookId: string) => void;
  closeWorkbook: () => void;
  setHierarchy: (hierarchy: Hierarchy) => void;
}

type WorkbookStore = WorkbookActions & {
  state: DeepSignal<WorkbookState>;
};

const initialState:WorkbookState = {
  attributes: [],
  categories: [],
  hierarchy: null,
  hierarchyNodes: [],
  hierarchies: [],
  loadingState: WorkbookLoadingState.Initial,
  lrsSegments: [],
  segments: [],
  trees: null,
  workbook: null,
};

// Not typesafe
const closeWorkbook1 = () => {
    store.state = initialState;
}

const closeWorkbook2 = () => {
  batch(() => {
    store.state.attributes = [];
    store.state.categories = [];
    store.state.hierarchy = null;
    store.state.hierarchyNodes = [];
    store.state.hierarchies = [];
    store.state.loadingState = WorkbookLoadingState.Initial;
    store.state.lrsSegments = [];
    store.state.segments = [];
    store.state.trees = null;
    store.state.workbook = null;
  });
}

const store: WorkbookStore = {
  state: deepSignal<WorkbookState>(initialState),

  closeWorkbook1,
};

@preact/signals-react v2.0.0 integration

Preact was just upgraded fixing a bunch of issues we were having, upgrading @preact/signals-react seems to break deepsignal proxy observers and mutations on proxy don't trigger react render.

I don't have specific logs, there aren't any to show, it is simply not working with the latest upgrade, understandably.

Do you have plans to upgrade to the latest @preact/signals-react usage? If so, let us know what the timeframe might be.

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.