Code Monkey home page Code Monkey logo

delivery-sdk-js's People

Contributors

christopherjennings avatar dependabot[bot] avatar dusekdan avatar ematipico avatar enngage avatar ivankiral avatar jancerman avatar jankalfus avatar jaredtbates avatar jj-plane avatar juraju-kentico avatar kentico-anthonym avatar kentico-ericd avatar kontent-ai-bot avatar makma avatar martinafarkasova avatar nickm615 avatar padresvk avatar petrsvihlik avatar simply007 avatar suyalcinkaya avatar suzii avatar terence1988 avatar tomasvorel2 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

Watchers

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

delivery-sdk-js's Issues

Create base abstract service

It would be nice to have a base abstract service that users can easily inherit and have type service ready to be used without additional coding.

Unclear error message while not providing modular content data

When I use the code from javascript penultimate code snippets from documentation:
https://developer.kenticocloud.com/docs/get-titles-and-images-of-5-latest-articles

const KenticoCloud = require('kentico-cloud-delivery-typescript-sdk');
class Article extends KenticoCloud.ContentItem {
    constructor() {
        super();
    }
}
const config = new KenticoCloud.DeliveryClientConfig('975bf280-fd91-488c-994c-2f04416e5ee3', 
    [ new KenticoCloud.TypeResolver('article', () => new Article()) 
]);
const deliveryClient = new KenticoCloud.DeliveryClient(config);
deliveryClient.items()
    .type('article')
    .orderParameter('elements.post_date', KenticoCloud.SortOrder.desc)
    .limitParameter(5)
    .get()
    .subscribe(response => console.log(response));

I got en error (thce the same):

dist/services/query.service.js:49 Error: Cannot map fields because item is not defined
    at FieldMapService.mapFields (dist/services/field-map.service.js:32)
    at dist/services/field-map.service.js:117
    at Array.forEach (<anonymous>)
    at FieldMapService.mapRichTextField (dist/services/field-map.service.js:115)
    at FieldMapService.mapField (dist/services/field-map.service.js:93)
    at dist/services/field-map.service.js:69
    at Array.forEach (<anonymous>)
    at FieldMapService.mapFields (dist/services/field-map.service.js:54)
    at dist/services/field-map.service.js:182
    at Array.forEach (<anonymous>)

It is because loaded article is using modular content in the field body_copy and the data for modular content are not in the returned data (default value of the depth parameter is 1).
Error is not clear about what really happens - I was force to debug the sdk to find the real cause. I am pretty OK with the error (maybe warning), but the message must me more specific.

Are we OK, that the code snippet in documentations leads to error, or we should add i.e. .depthParameter(2) to the query specification to prevent the error?

Critical dependency due to parse5 dependency

We are seeing a 'Critical dependency' warning being logged in console when building the app (i.e. react, angular..). We should resolve this in some way or use different html parser that works in all environments (node.js, browser...)

Issue raised with parse5 with no resolution so far

Rxjs treeshaking

Importing from rxjs such as like:

import { Observable } from 'rxjs/Rx'

might cause the library to be unnecessary large. We should find out how treeshaking works in this case and if we can make it better.

Feature: Support Node.js

Use case

Using SDK in a Nodejs/Express application

I am working on a REST API developed with Nodejs and Express. Requirement is to read data from Kentico Cloud, execute some treatment on it and then returned the processed data.

I have setup a simple node server with express to deliver the content. I have set up my models as per the
KenticoCloudSampleJavascriptApp.

Error

When executing the following code:

var config = new kc.DeliveryClientConfig(projectId, typeResolvers); 
var deliveryClient = new kc.DeliveryClient(config); 

deliveryClient.item('home') 
  .depthParameter(3) 
  .get() 
  .subscribe(response => res.json(response)); 

This exception is thrown:

Error: XMLHttpRequest is not supported by your browser
    at getXMLHttpRequest (D:\_\sample-tool\node_modules\rxjs\observable\dom\AjaxObs
ervable.js:45:19)
    at Object.createXHR (D:\_\sample-tool\node_modules\rxjs\observable\dom\AjaxObse
rvable.js:93:71)
    at Object.tryCatcher (D:\_\sample-tool\node_modules\rxjs\util\tryCatch.js:6:31)
    at AjaxSubscriber.send (D:\_\sample-tool\node_modules\rxjs\observable\dom\AjaxO
bservable.js:191:50)
    at new AjaxSubscriber (D:\_\sample-tool\node_modules\rxjs\observable\dom\AjaxOb
servable.js:180:14)
    at AjaxObservable._subscribe (D:\_\sample-tool\node_modules\rxjs\observable\dom
\AjaxObservable.js:115:16)
    at AjaxObservable.Observable._trySubscribe (D:\_\sample-tool\node_modules\rxjs\
Observable.js:171:25)
    at AjaxObservable.Observable.subscribe (D:\_\sample-tool\node_modules\rxjs\Obse
rvable.js:159:65)
    at MapOperator.call (D:\_\sample-tool\node_modules\rxjs\operator\map.js:54:23)
    at Observable.subscribe (D:\_\sample-tool\node_modules\rxjs\Observable.js:156:2
2)

The dependencies of the SDK require the code to work on a browser. It would be great to have the ability to work on a nodejs app.

Versions

  • node: 8.5.0
  • kentico-cloud-delivery-typescript-sdk: 1.6.0
  • express: 4.15.4

Resolving of links in modular content no longer works due to changed response

Link objects in rich text field were part of the modular content response in the past, but now it has been replaced with something like this:

 "body_copy": {
          "type": "rich_text",
          "name": "Body Copy",
          "images": {},
          "links": {
            "80c7074b-3da1-4e1d-882b-c5716ebb4d25": {
              "codename": "kenya_gakuyuni_aa",
              "type": "coffee",
              "url_slug": "kenya-gakuyuni-aa"
            },
            "0c9a11bb-6fc3-409c-b3cb-f0b797e15489": {
              "codename": "brazil_natural_barra_grande",
              "type": "coffee",
              "url_slug": "brazil-natural-barra-grande"
            }
          },

Sample response

Field map service may return outdated content

Hi, I have this use case in which I believe the FieldMapService returns old data. It only happens with modular content and the scenario is as follows:

  1. I get an item with modular content via DeliveryClient.item().get().
  2. I go to app.kenticocloud.com and update one of item's modular items.
  3. I get the same item with modular content again.
  4. The raw response (response.debug.rawResponse.xhr.responseText) contains fresh data, however the processed item returned from the SDK is of an old version.

IMHO, the problem lies in the fact, that same instance of DeliveryClient is used for both requests, which has same instance of QueryService and somewhere inside same instance of FieldMapService caches/memoizes its processed items without clearing the cache in between consecutive requests.

To be precise, the item root item is always recomputed aside from being added to processedItems. However, the modular content is taken from (possibly outdated) cache, which results in outdated data being returned.

I am not 100% sure I have investigated this correctly, could you please have a look?

Angular 6.0.0 Compatability

I get the following error when trying to build an Angular 6 project which contains the delivery sdk.

ERROR in ./node_modules/kentico-cloud-delivery/node_modules/parse5/lib/parser/parser_stream.js
Module not found: Error: Can't resolve 'stream' in '/Users/martya/…/node_modules/parse5/lib/parser'
ERROR in ./node_modules/kentico-cloud-delivery/node_modules/parse5/lib/sax/index.js
Module not found: Error: Can't resolve 'stream' in '/Users/martya/…/node_modules/kentico-cloud-delivery/node_modules/parse5/lib/sax'
ERROR in ./node_modules/kentico-cloud-delivery/node_modules/parse5/lib/sax/dev_null_stream.js
Module not found: Error: Can't resolve 'stream' in '/Users/martya/…/node_modules/kentico-cloud-delivery/node_modules/parse5/lib/sax'
ERROR in ./node_modules/kentico-cloud-delivery/node_modules/parse5/lib/serializer/serializer_stream.js
Module not found: Error: Can't resolve 'stream' in '/Users/martya/…/node_modules/kentico-cloud-delivery/node_modules/parse5/lib/serializer'

In my research into the issue I noticed that @Enngage has lodged a ticket about this on the official angular project. It seems like it's an underlying issue with Angular, however it's worth lodging an issue here so other's can see what's going on.

The only workaround which I've found is to install the stream package separately via npm npm install stream. This solves the issue for now but it would good if there's a better way.

No support for resolving links in rich text?

Am I missing something, or is there no way to specify how links in rich text fields will be resolved? I imagine it would be very similar to how modular content is resolved, but looking for a tags with data-item-id attributes and no href attribute value.

Pagination for Taxonomies

Listing taxonomy groups supports pagination. We need to reflect that in the SDK.

{
  "taxonomies": [
    {
      "system": {
        "id": "f30c7f72-e9ab-8832-2a57-62944a038809",
        "name": "Personas",
        "codename": "personas",
        "last_modified": "2016-10-20T13:24:00.3200182Z"
      },
      "terms": [
        {
          "name": "Coffee expert",
          "codename": "coffee_expert",
          "terms": [
            {
              "name": "Barista",
              "codename": "barista",
              "terms": []
            },
            {
              "name": "Cafe owner",
              "codename": "cafe_owner",
              "terms": []
            }
          ]
        },
        {
          "name": "Coffee enthusiast",
          "codename": "coffee_enthusiast",
          "terms": [
            {
              "name": "Coffee lover",
              "codename": "coffee_lover",
              "terms": []
            },
            {
              "name": "Coffee blogger",
              "codename": "coffee_blogger",
              "terms": []
            }
          ]
        }
      ]
    },
    {
      "system": {
        "id": "d351400e-0290-87b2-1413-6c411d8ae5a4",
        "name": "Processing type",
        "codename": "processing_type",
        "last_modified": "2017-09-04T12:50:20.7857817Z"
      },
      "terms": [
        {
          "name": "Wet (Washed)",
          "codename": "wet__washed_",
          "terms": []
        },
        {
          "name": "Dry (Natural)",
          "codename": "dry__natural_",
          "terms": []
        },
        {
          "name": "Semi-dry",
          "codename": "semi_dry",
          "terms": []
        }
      ]
    },
    {
      "system": {
        "id": "79b1c5b6-30bc-d076-a236-d9ec9f1ff01b",
        "name": "Product status",
        "codename": "product_status",
        "last_modified": "2016-09-15T10:53:25.2233101Z"
      },
      "terms": [
        {
          "name": "On sale",
          "codename": "on_sale",
          "terms": []
        },
        {
          "name": "Bestseller",
          "codename": "bestseller",
          "terms": []
        }
      ]
    }
  ],
  "pagination": {
    "skip": 0,
    "limit": 3,
    "count": 3,
    "next_page": ""
  }
}

SDK tracking header

Motivation:
We'd like to start sending a header for identifying SDKs + their versions with each request from all SDKs. The header would be then tracked by App Insights and should provide us with information valuable for multiple departments in Kentico. App Insights already gather information about the user agent, but that is not always usable or present (there are some screenshots below).

In the future, the tracking should help us:

  • identify trends and make decisions regarding future SDK development like:
    • avoid breaking changes (in APIs that are highly used)
    • identify new SDK opportunities (e.g. we may see that users are making plain calls from a certain platform while not using any SDK)
    • new functionality opportunities (similarly to SDK opportunities, we may discovery that certain part of the API is not covered by SDK)
  • discover misbehavior of certain SDK versions
    • see whether users are using the latest version or if they are stuck
  • send out targeted messages about an SDK version being deprecated
  • save round-trips to customer asking about platform they're using and the SDK version (Support)

Specification:
Send the following header with each request to the Kentico Cloud Delivery API.

  • Header name: X-KC-SDKID
  • Header format: ;;
    • PackageRepositoryHost - HOST part of the package repository URI. The value can be hardcoded.
    • SDKPackageID - ID specific for the package repository. In other words, the identifier that's used when specifying the package as a dependency of the resulting application (typically in a json or xml file - package.json, *.csproj, composer.json, etc.) Sometimes the ID can consist of a vendor name and package name. The value can be hardcoded.
    • SDKVersion - version of the package (typically in a semantic version format). This information needs to be either retrieved programmatically during the runtime or hardcoded and manually updated with every release.

Examples:

X-KC-SDKID: nuget.org;KenticoCloud.Delivery;4.12.0
X-KC-SDKID: packagist.org;kentico-cloud/delivery-sdk-php;0.9.1
X-KC-SDKID: maven.org;com.kenticocloud:delivery-sdk-java;1.0.5
X-KC-SDKID: npmjs.com;kentico-cloud-delivery-typescript-sdk;2.2.2

Uncaught ReferenceError: exports is not defined

Getting an error Uncaught ReferenceError: exports is not defined

at line

Object.defineProperty(exports, "__esModule", { value: true }); var kentico_cloud_delivery_typescript_sdk_1 = require("kentico-cloud-delivery-typescript-sdk");

Improve pagination in the DeliveryItemListingResponse

As part of the DeliveryItemListingResponse object, the Pagination.NextPageUrl property provides a reference to getting the next page data.

The Delivery client (the "items" method) should be able to get the next page data, either using the NextPageUrl, or something more appropriate.

Make get() return a Promise.

The get() method of the SingleItemQuery<...> and MultipleItemQuery<...> returns an Observable<...>.
I mean, ... how many times is the subscribed callback intended to be called?
I suppose the request is resolved once. That, I think, leaves Promise as a more suitable option especially in the light or the recently introduced async/await which is perfectly backwards compatible with Promises. Because they transpile to Promises basically.

Property decorator - Resolving field

While working with the SDK, I found tedious to create translators for field names.
I would like to propose the following approach to resolve property names: Use Typescript Decorators to set the codename at the property level

Example:

export class Article extends ContentItem {
  @codeName('teaser_image')
  public teaserImage: Fields.AssetsField;
  public title: Fields.TextField;
  public summary: Fields.TextField;

  constructor() {
    super()
  }
}

Advantages

  • SDK being built with Typescript, we can use its Decorator feature
  • Easy to read
  • no need to create an map object of the code names
  • can use constants @codeName(ContentTypes.Article.fields.teaserImage)

Work

I have started working on this here
It is currently working as is and would require some refactoring - I don't really like having to path the instance in the decorator.

What I did was to:

  • Create a property decorator that defines the code name of KC field
  • in the model class inheriting from ContentItem - override propertyResolver method, retrieve a property by decorator.

I believe the last one could be moved to the ContentItem class itself and therefore, we wouldn't to override propertyResolver method anymore.

Please, let me know what do you think.

Thanks.

Add support for secured access to published (production) content

In coming weeks, the Delivery API will start supporting authenticated access.

In the first version of this feature, content will be secured using an API key. The developer will be able to turn the authenticated access on and off for the whole project. There will be one authentication key for the project, not multiple ones (for various user roles, for example).

Implement support for submitting the key in the form of the "Authorization" request header. The key should be sent via the Bearer scheme (with a "Bearer " prefix).

We'll provide more information once they become available. https://kenticocloud.com/roadmap#secured-delivery-api

Set up CI + Code Coverage

I think it would be great if there was an indication of the project being buildable and of the % of code covered by automatic tests.

Would you consider setting up CI (e.g. Travis) + export code coverage (to codeclimate/codecov/coveralls..)

I came across several how-tos for TypeScript (most of them are mentioning istanbul and mocha), so it should be doable.

If you need some inspiration regarding yml files, look at the Kentico repos, e.g.:

Add support for image optimization

We need to get up to speed with the .NET SDK regarding image optimization.

Here's the code: https://github.com/Kentico/delivery-sdk-net/pull/113/files

Example

Scale
image.jpg?mode=scale&width=300
image.jpg?mode=scale&height=150
image.jpg?mode=fit&height=150&width=300

DPR
image.jpg?mode=scale&width=300&dpr=2.0

Specification

If a developer provides a parameter with invalid value or omits a parameter that is required for desired optimization, the Asset API will either ignore this parameter, or return the original asset without any optimizations.

Also, to keep our sanity, we will transform each image optimization parameter independently from others. Yes, this approach might sometimes produce surprising results. However, both Fastly and imgix are designed to handle a set of parameters that do not make sense and we are not making the situation worse.

Regarding requests to the Asset API, the idea is to go through all parameters, transform the supported ones and get rid of everything else.

To get a grasp of the image optimization You can experiment with two identical images:

rect=x,y,w,h (incompatible with crop)

- -
x is not float Nothing
x < 0.0 Nothing
y is not float Nothing
y < 0.0 Nothing
w is not float Nothing
w <= 0.0 Nothing
h is not float Nothing
h <= 0.0 Nothing
h <= 0.0 Nothing
otherwise crop={w},{h},x{x},y{y}

If the rect parameter is malformed, just ignore it.

fit=crop&crop=focalpoint&fp-x=x&fp-y=y&fp-z=z (incompatible with rect)

- -
x is not float set x as 0.5
y is not float set y as 0.5
z is not float Nothing
z <= 1.0 Nothing
1 / z < 1.0 Nothing
otherwise crop={1 / z},{1 / z},offset-x{(x * z - 0.5) / (z - 1)},offset-y{(y * z - 0.5) / (z - 1) * 100}

Both offset-x and offset-y must be clamped into range from 0 to 100.

imgix supports crop by both rectangle and focal point. Unfortunately, it is not so easy to calculate Fastly parameters. Therefore, let's declare the rect parameter more important. So, if both crop by rectangle and focal point are specified, choose the first.

fm=x

- -
x = gif format=gif
x = png format=png
x = png8 format=png8
x = jpg format=jpg
x = pjpg format=pjpg
x = webp format=webp
otherwise Nothing

fm=webp&lossless=x

- -
x = 1 format=webpll
x = true format=webpll
x = 0 format=webply
x = false format=webply
otherwise format=webp

q=x

- -
x is not float Nothing
otherwise quality={x}\

auto=x

- -
x = format auto=webp
otherwise Nothing

Local variables and related functions will be required to transform parameters.

SPIKE: Automatic generation for the changelog.md

Validate possibilities for an automatic generation for changelog.md.

Mind that this is a monorep repository. Provide the best practice to apply discovered approach for all the repositories (at least all our SDKs).

Create content management API

Create another SDK package, that allows using Content Management API in javascript.

Implementation should be as similar as possible with already implemented .net conent management sdk.

High-level feature set Implementation could be split:

  • Importing content items
    • Adding a content item
    • Viewing a content item
    • Listing content items
    • Listing content items
    • Deleting a content item
    • Upserting a content item by external ID
    • Adding language variants
      • Upserting a language variant
      • Viewing a language variant
      • Listing language variants
      • Deleting a language variant
  • Importing assets
    • Uploading a file
    • Upserting an asset using external ID
    • Uploading an asset from a file system in a single step
    • Viewing an asset
    • Listing assets
    • Deleting an asset
  • Importing Modular and linked content
  • Strongly-typed models support
  • Getting an edit link for a content item
  • Getting an edit link for a specific content element
  • Getting an edit link for multiple content elements

Formal requirements

Additional resources:

Response from types call returns only name and types codename

I have used delivery client to load content type definition.
I have needed to get all possible options from the multiple choice field.

I have used the code defined in:
https://github.com/Enngage/KenticoCloudDeliveryTypeScriptSDK#working-with-content-types

Response does not contain possible options to the multi choice field:
multiplechoice

There is also no raw response that could be used to get the option values.

Note it would be also good to extend type calling by specifik what elements to load, but it does not block me :-)
https://developer.kenticocloud.com/v1/reference#view-a-content-type-element

Support handling of transient faults

Add a capability of dealing with transient network outages via the following retry policy:

  • Let the client code define a maximum amount of retry attempts, preferably via the DeliveryClientConfig class.
  • If not specified in the config, the retry policy should be disabled by default.
  • If specified, the Delivery client should retry in exponential retry intervals.
  • The interval, in milliseconds, is always calculated as a power of the number 2. The exponent is the ordinal number of the next attempt. The result is then multiplied by 100. The order is one-based. For instance, the first retry attempt interval equals to (22 * 100), the second equals to (23 * 100), etc.
  • When all retry attempts fail, the SDK should notify the client code about it, preferable via an exception.

Angular AOT build fails when using the Typescript SDK

We are trying to use the Kentico Typescript SDK in an Angular application.
Angular version: 5.2.0
Typescript version: 2.5.3
Kentico version: 2.3.3

The SDK works fine in local development mode and a normal Angular build. However if you try to run an AOT build it fails with a module reference error. I am not certain but this could be due to how the module is defined.

You can find a reproduction at this repo https://github.com/dewang/kentico-test.git. This is an absolutely basic app created using Angular CLI, with the addition of referencing the Kentico SDK.

Running ng build --aot fails with the following error

ERROR in ./src/app/app.module.ngfactory.js
Module not found: Error: Can't resolve 'kentico-cloud-delivery-typescript-sdk/definitions/client/delivery-client' in '/home/code/src/kentico-test/src/app'
resolve 'kentico-cloud-delivery-typescript-sdk/definitions/client/delivery-client' in '/home/code/src/kentico-test/src/app'
  Parsed request is a module
  using description file: /home/code/src/kentico-test/package.json (relative path: ./src/app)
    Field 'browser' doesn't contain a valid alias configuration
  after using description file: /home/code/src/kentico-test/package.json (relative path: ./src/app)
    resolve as module
      /home/code/src/kentico-test/src/app/node_modules doesn't exist or is not a directory
      /home/code/src/kentico-test/src/node_modules doesn't exist or is not a directory
      /home/code/src/node_modules doesn't exist or is not a directory
      /home/dewang/code/akoni/node_modules doesn't exist or is not a directory
      /home/dewang/code/node_modules doesn't exist or is not a directory
      /home/dewang/node_modules doesn't exist or is not a directory
      /home/node_modules doesn't exist or is not a directory
      /node_modules doesn't exist or is not a directory
      looking for modules in /home/code/src/kentico-test/node_modules
        using description file: /home/code/src/kentico-test/package.json (relative path: ./node_modules)
          Field 'browser' doesn't contain a valid alias configuration
        after using description file: /home/code/src/kentico-test/package.json (relative path: ./node_modules)
          using description file: /home/code/src/kentico-test/node_modules/kentico-cloud-delivery-typescript-sdk/package.json (relative path: ./definitions/client/delivery-client)
            no extension
              Field 'browser' doesn't contain a valid alias configuration
              /home/code/src/kentico-test/node_modules/kentico-cloud-delivery-typescript-sdk/definitions/client/delivery-client doesn't exist
            .ts
              Field 'browser' doesn't contain a valid alias configuration
              /home/code/src/kentico-test/node_modules/kentico-cloud-delivery-typescript-sdk/definitions/client/delivery-client.ts doesn't exist
            .js
              Field 'browser' doesn't contain a valid alias configuration
              /home/code/src/kentico-test/node_modules/kentico-cloud-delivery-typescript-sdk/definitions/client/delivery-client.js doesn't exist
            as directory
              /home/code/src/kentico-test/node_modules/kentico-cloud-delivery-typescript-sdk/definitions/client/delivery-client doesn't exist

We get a slightly different error in our actual app which does not use Angular CLI, but uses a custom Webpack 3 build.

This dependency was not found:

* kentico-cloud-delivery-typescript-sdk/definitions/client/delivery-client in ./src/app/app.module.ngfactory.js, ./src/app/modules/home/home.component.ngfactory.js and 1 other

However the base issue is that it cannot resolve the referenced classes from the module.

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.