Code Monkey home page Code Monkey logo

swiftphoenixclient's Introduction

Swift Phoenix Client

Swift Version License Platform Carthage compatible Open Source Helpers

About

SwiftPhoenixClient is a Swift port of phoenix.js, allowing your swift projects to connect to a Phoenix Websocket backend.

We try out best to keep the library up to date with phoenix.js but if there is something that is missing, please create an issue or, even better, a PR to address the change.

Sample Projects

You can view the example of how to use SwiftPhoenixClient in the Example/ dir. There are two primary classes, BasicViewController and ChatRoomViewController. The BasicViewController is designed to test against a local chat server where as ChatRoomViewController is a more "complete" example which targets dwyl's phoenix-chat-example Heroku app.

SwiftPhoenixClient

The core module which provides the Phoenix Channels and Presence logic. It also uses URLSession's default WebSocket implementation which has a minimum iOS target of 13.0.

Installation

CocoaPods

You can install SwiftPhoenix Client via CocoaPods by adding the following to your Podfile. Keep in mind that in order to use Swift Phoenix Client, the minimum iOS target must be '9.0'

pod "SwiftPhoenixClient", '~> 5.3'

and running pod install. From there you will need to add import SwiftPhoenixClient in any class you want it to be used.

Carthage

If you use Carthage to manage your dependencies, simply add SwiftPhoenixClient to your Cartfile:

github "davidstump/SwiftPhoenixClient" ~> 5.3

Then run carthage update.

If this is your first time using Carthage in the project, you'll need to go through some additional steps as explained over at Carthage.

SwiftPackageManager

Note: Instructions below are for using SwiftPM without the Xcode UI. It's the easiest to go to your Project Settings -> Swift Packages and add SwiftPhoenixClient from there.

To integrate using Apple's Swift package manager, without Xcode integration, add the following as a dependency to your Package.swift:

.package(url: "https://github.com/davidstump/SwiftPhoenixClient.git", .upToNextMajor(from: "5.2.2"))

and then specify "SwiftPhoenixClient" as a dependency of the Target in which you wish to use SwiftPhoenixClient.

Usage

Using the Swift Phoenix Client is extremely easy (and familiar if you have used the phoenix.js client).

See the Usage Guide for details instructions. You can also check out the documentation

Example

Check out the ViewController in this repo for a brief example of a simple iOS chat application using the Phoenix Chat Example

Also check out both the Swift and Elixir channels on IRC.

Development

Check out the wiki page for getting started

Thanks

Many many thanks to Daniel Rees for his many contributions and continued maintenance of this project!

License

SwiftPhoenixClient is available under the MIT license. See the LICENSE file for more info.

swiftphoenixclient's People

Contributors

aaa70 avatar andrewsb avatar aquageek avatar bcardarella avatar codetriage-readme-bot avatar danielgarbien avatar darrenclark avatar davidstump avatar dsrees avatar ejensen avatar gerardogtn avatar jklp avatar joesus avatar laiso avatar lucasvandongen avatar marshalgeazipp avatar morgz avatar msandel6 avatar mudphone avatar murphb52 avatar nilslattek avatar optikfluffel avatar peteranny avatar richard-ash avatar ruslandoga avatar sjrmanning avatar tapi avatar wilson-micah avatar yangjian avatar zhyu 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swiftphoenixclient's Issues

Add to Cocoapods

Would be ideal to allow people to pull this in via Cocoapods.

Swift 3 Support

Hey there!

Just wanted to have a place to discuss Swift 3 issues.

I've started working on a migration now that Starscream has a branch supporting it. Any chance you could make a new branch here to push to?

Cheers.

More robust Unit Tests

There are some basic Unit tests set up around creating a Socket, but I would love to see a more robust test which sets up a mock server and actually "sends" and "receives" messages back and forth

labeling this as easy for now if anyone wants to take up the task.

No rejoin when loosing network connection

Hello,
I am using SwiftPhoenixClient in my Mac OS application.

I've just updated to 0.8.1, the previous version was 0.6.0.

0.8.1 does not rejoin.
My code:
`socket = Socket(url: "ws://...")

    socket.onOpen = { 
        print("onOpen")
    }
    socket.onClose = { 
        print("onClose")
    }
    socket.onError = { error in
        print("onError")
    }
    socket.connect()
    
    channel = self.socket?.channel("mychannel")                
    
    channel.onError {
        (payload) in print("Error: ", payload)
    }
    
   channel.onClose {
        (payload) in print("Channel Closed")            
    }
    
   channel.join().receive("ok") { (payload) in
        print("Channel Joined", payload)
        }.receive("error"){ (payload) in
            print("Failed to join", payload)
        }.receive("timeout") { (payload) in
            print("Networking issue...", payload)
    }`

So when I'm online it connects successfully, and prints "onOpen"->"Channel Joined"
Then I turn off my network and receive "onError".
Next step is to turn on it again - no actions. This method is not called:
open func stream(_ aStream: Stream, handle eventCode: Stream.Event)
But if I do the same for 0.6.0 - it works perfectly.

I wouldn't like to use 0.6.0 because new APIs look much better.
Could you help me with this please?

Update Documentation

CocoaPods is now all setup and pushed to trunk. Need to update documentation to reference installation and usage via CocoaPods.

Handle error when sending data

I use Swift Phoenix Client in my app to sending & receive data with Phoenix sockets. If I use the traditional way with channel.on to receive data on events, I use also your specific way to send data with method socket.send. But I doesn't really understand how I can handle errors at this moment, in others words, how can I verifiy if the connection is always established, if my message was send correctly etc.

Params not sent when joining a Channel

It looks to me like #85 forgot about /// The params sent when joining the channel.

When I try to:

let channel = socket.channel("room:secret", params: ["token": "Super Secret Room Token"])

channel.join()
    .receive("ok") { payload in print("Channel Joined", payload) }
    .receive("error") { payload in print("Failed to join", payload) }
    .receive("timeout") { payload in print("Networking issue...", payload) }

I never seem to receive the token server side.

Auth token example for Swift library

I've just finished reading great book "Programming Phoenix". The sample to create video annotation identifies a user through window-token which is part of DOM itself. What is the approach for the client library?. What is best approach I can apply to keep my channel specific for a user and safe.
Phoenix <3 !

Background disconnect / reconnect strategy

I have a connection that basically should exist whenever the app is running. iOS will not allow you to run sockets in the background unless you're a VoIP app and basically we're not really doing that. What is the strategy to follow to disconnect and reconnect? We sometimes run into problems with the StarScream layer giving a -1000 protocol layer error when we disconnect when going into background an reconnect again coming to the foreground

Swift 3 errors

Hi,

I installed SwiftPhoenixClient using cocoapods on an empty project, but when I try to open the xcworkspace, Xcode8 says that I need to choose to convert the code to either Swift3 or Swift2.3

After choosing Swift3 and letting XCode convert the code, I ended up with >30 errors, about 20 of which were due to StarScream and about 10 of which were because of SwiftPhoenixClient.

Do I need to install StarScream manually (not via the SwiftPhoenixClient cocoapods dependency), since it appears to be the cause of the errors?

Thanks,
Jake
xcode_errors

#join message argument does nothing...?

Howdy,

This could very well be a case of me missing the point, or just being an idiot, but from what I can tell and how I'd like to use this, setting a join message does nothing. Join calls rejoin, and correctly connects to the channel, but rejoin uses it's own hard coded message and payload.

E.g.

https://github.com/davidstump/SwiftPhoenixClient/blob/master/Pod/Classes/Phoenix.swift#L201-L216

    func rejoin(chan: Phoenix.Channel) {
      chan.reset()
      let joinMessage = Phoenix.Message(subject: "status", body: "joining")
      let payload = Phoenix.Payload(topic: chan.topic!, event: "phx_join", message: joinMessage)
      send(payload)
      chan.callback(chan)
    }

    public func join(topic  topic: String, message: Phoenix.Message, callback: (AnyObject -> Void)) {
      let chan = Phoenix.Channel(topic: topic, message: message, callback: callback, socket: self)
      channels.append(chan)
      if isConnected() {
        print("joining")
        rejoin(chan)
      }
    }

Is there something I'm missing from the guides that makes this behavior required or a reason why the message argument is even provided?

Nothing happens when joining

I'm using a simple Phoenix instance, and have a simple channel join event working in js. I'm using the following on iOS:

    let socket = Socket(domainAndPort: "localhost:4000", path: "socket", transport: "websocket")
    socket.join(topic: "room:lobby", message: Message(subject: "status", body: "joining")) { channel in
        let channel = channel as! Channel
        print("join")
    }

But nothing is logged on the server. I'm watching the traffic going through the server's port 4000 and am seeing some packets flow every time I trigger the above code.

Not sure if I should post this in the Phoenix Framework project as well.

Support receive hooks

The phoenix js sdk allows to receive the reply to a pushed message:

// from the phoenix.js file
channel.push("new_msg", {body: e.target.val}, 10000)
.receive("ok", (msg) => console.log("created message", msg) )
.receive("error", (reasons) => console.log("create failed", reasons) )
.receive("timeout", () => console.log("Networking issue...") );

The receive("ok") callback will be called with the response_payload returned in the channel:

def handle_in("ping", payload, socket) do
  response_payload = %{"some_result" => 123}
  {:reply, {:ok, response_payload, socket}
end

This allows for an easier message -> reply style of programming when using channels. At the moment we do not have this functionality in the iOS SDK. The implementation in JS just listens for a phx_reply event and compares the ref ids.
I might look into that issue soon, but I guess it would require a little bit more work or refactoring. Also since it requires parsing json please first have a look at #49.

Create a new 0.2.0 release tag, so we an push to CocoaPods

I think we have an old (unnecessary) release tag for 0.2.0. Can you create a new one so that we can push to CocoaPods?

I'm assuming that you have to create the release tags, since I don't think that they come across in my pull requests. Once the tag is created, I can push to CocoaPods (test out my ability to do so), if you'd like.

FYI: I'm preparing to create a Swift 2.0 branch, to support tvOS. I tried to use the existing code with a tvOS app and it barfed on syntax changes. So, I'd just like to wrap up the current version (as a pod release) before starting on Swift 2.0 things.

How to disable console log..?

Hi, Thanks for the great framework.
how can I disable and enable console log for this frame work...?

{"topic":"phoenix","ref":"165","payload":{"status":"ok","response":{}},"join_ref":null,"event":"phx_reply"}
json: {"event":"heartbeat","topic":"phoenix","ref":"166","payload":{"body":"Pong"}}
socket message: {"topic":"phoenix","ref":"166","payload":{"status":"ok","response":{}},"join_ref":null,"event":"phx_reply"}

Token Authorization

Hi there,

Thank you for the awesome pod!

I'm building a chat app using this, but I want to check user authentication when socket joining.
It's related phoenixframework/phoenix#699 .

Do you have a plan to pass not only Phoenix.Message but something?

Best,

Non Working Usage Example

When trying this example, from the bottom of the Channels and Events section in the Usage Guide:

/// Called before the `.on(event:, callback:)` hook is called for all events. Allows you to
/// hook in an manipulate or spy on the incoming payload before it is sent out to it's
/// bound handler. You must return the payload, modified or unmodified
channel.onMessage { (event, payload, ref) -> Payload in 
    payload["modified"] = true
    return payload 
}

XCode tells me for the payload["modified"] = true part that it

🛑 Cannot assign through subscript: 'payload' is a 'let' constant

Channel `onClose` is never called

A Channel's onClose closure is never called.

It could potentially be hooked into the leave method.
Possible fix is to call the closure after channel has been given the ok after a leave event

Current:

public func leave(timeout: Int? = nil) -> Push {
return socket.push(topic: topic, event: PhoenixEvent.leave)
}

Proposed:

    public func leave(timeout: Int? = nil) -> Push {
        return socket.push(topic: topic, event: PhoenixEvent.leave)
            .receive("ok") { payload in
                self.onClose?(payload)
            }
    }

Long polling support?

Is Long polling supported? From what I can see the WebSocket implementation is highly coupled with the socket implementation. Do you have any plans to de-couple these and add support for other transport layers?

leave function on Socket is private

I cannot find a way to close a socket connection, other than the method as seen in the leave() function in the Socket class:

let leavingMessage = Phoenix.Message(subject: "status", body: "leaving")
let payload = Phoenix.Payload(topic: topic, event: "leave", message: leavingMessage)
socket.send(payload)

Why not make the leave() function public in the Socket class?

Alternative client

Hello, wanted to let you know that I've built alternative client on Swift, while I've used many places of this project for ideas, it was total overhaul, so I though making it separate project would be better than PR.

I wouldn't write here about that, but looking at your README looks like you don't have much time for maintenance, and I thought it would be a good idea to let developers know about alternatives, and I don't have any intentions to insult you here.

Basically it supports iOS 8 (#28), Carthage (#10), token authorisation (#9). Otherwise it's almost the same, except that it allows you to pass callbacks for messages to which server :replyes (the feature I've needed, and the reason I've built it).

Link to it: https://github.com/almassapargali/PhoenixWebSocket
Thanks, anyway!

Can't keep connection up, seemingly different errors every now and then

Connections dies at random times after initially connecting, most often with the error right here. If I try to reconnect, it does not do anything and usually end up with a new error (will edit and update once I get it the next time).

I have a separate WebSocket connection also using StarScream that is connected to another server, and it seems to be running fine, so I suppose the error could be in this layer (SwiftPhoenixClient) and not below.

This however, when connected to either my local phoenix app or the remote deployed one keeps disconnecting and it takes a reboot of the app to get it up again. I'll dump more data as I get it.

EventManager.121: Socket log string: SwiftPhoenixClient: transport, Connected to ws://192.168.127.92:4000/events/websocket?token=Bearer%20THIS%20IS%20A%20TOKEN&terminal=951654322
EventManager.121: Socket log string: SwiftPhoenixClient: push, Sending {"event":"phx_join","topic":"terminal:123123123123","payload":{"status":"joining"},"ref":"1","join_ref":"1"}
EventManager.121: Socket log string: SwiftPhoenixClient: push, Sending {"event":"phx_join","topic":"place:123123123123","payload":{"status":"joining"},"ref":"2","join_ref":"2"}
EventManager.110: Connected to the event server.
EventManager.121: Socket log string: SwiftPhoenixClient: receive , {"topic":"terminal:123123123123","ref":"1","payload":{"status":"ok","response":{}},"event":"phx_reply"}
Join channel Optional("terminal:123123123123")
Phoenix reply @ terminal:123123123123: SwiftPhoenixClient.Message
EventManager.121: Socket log string: SwiftPhoenixClient: receive , {"topic":"place:123123123123","ref":"2","payload":{"status":"ok","response":{}},"event":"phx_reply"}
Join channel Optional("place:123123123123")
Phoenix reply @ place:123123123123: SwiftPhoenixClient.Message
EventManager.121: Socket log string: SwiftPhoenixClient: push, Sending {"event":"heartbeat","topic":"phoenix","payload":{},"ref":"3"}
EventManager.121: Socket log string: SwiftPhoenixClient: transport, WSError(type: Starscream.ErrorType.protocolError, message: "", code: 1000)
EventManager.117: Connection error: WSError(type: Starscream.ErrorType.protocolError, message: "", code: 1000)
EventManager.121: Socket log string: SwiftPhoenixClient: channel, error terminal:123123123123
EventManager.121: Socket log string: SwiftPhoenixClient: channel, error place:123123123123
2018-07-16 13:10:01.789333+0200 APP[4346:1817409] SocketStream read error [0x1c4362f40]: 1 54

Support installation via Carthage

Carthage is a simplified dependency manager for iOS/OS-X. I know that you already have a Podspec (which I plan on using for now) but Carthage might be another great place to publish the client... and hopefully, allow you to do so with minimal hassle.

Better Name?

@mudphone Any thoughts on the repo name? The current name was just a quick filler when I started playing with channels. Thanks :)

Stabilize 0.7.0

This is a list of things to investigate/change before making 0.7.0 a finalized release

Things to change

  • Change .close(reset:) to default to true instead of false
  • Investigate issue with using wss://hostname.com causing:
socket closed: The operation couldn’t be completed. (Starscream.WSError error 1.)
Error: WSError(type: Starscream.ErrorType.upgradeError, message: "Invalid HTTP upgrade", code: 403)

Potentially future release

  • Improve error handling when opening a socket
  • Allow disable sending heartbeat

Update cocoapods

As I mentioned in #32 there was an issue where the phoenix websocket server was killing the connection after 30 seconds or so. I ran into this issue while running the a project where the dependency was installed via from the cocoapods repo, when running with the dependency locally, I have had no issues.

If you have the time, could you please update the version hosted on cocoapods to be current with master?

Thanks!

CFNetwork SSLHandshake failed (-9807)

Getting this error while connecting to HTTP socket?

2017-04-19 12:52:57.445851+0530 WebRTCConnection[2396:344111] CFNetwork SSLHandshake failed (-9807)

Does this library allow setting something like

NSExceptionAllowsInsecureHTTPLoads

Channel Presence

Phoenix 1.2 introduced Presence.

Was wondering if this library will be supporting it.

Thanks!

It is not possible to dealloc a socket instance.

When I am storing my socket in a property like

var socket: Phoenix.Socket?

and lets say I want to close the connection when the user performs a logout:

socket = nil

The socket is never deallocated because it has up to three NSTimers which hold a strong reference to the socket. (reconnect, hearbeat, sendBufferTimer).
A solution would be to expose a disconnect method which stops all timers and leaves all channels. The channels hold also a strong reference, which can be solved by #37 or automatically leaving all channels on disconnect.

Update README/Docs

Update README to walk a user through the new changes from @mudphone making everything compatible with the newest versions of Swift and Phoenix.

socket closed: Optional("connection closed by server")

Hi, thanks for awesome pod!
I tried socket.join and send message.
but, 40sec after joining, connection closed automatically.

(10sec later)socket message: {"topic":"phoenix","ref":null,"payload":{},"event":"heartbeat"}
(20sec later)socket message: {"topic":"phoenix","ref":null,"payload":{},"event":"heartbeat"}
(40sec later)socket closed: Optional("connection closed by server")

so I added timeout value to phoenix_server/web/channels/user_socket.ex

defmodule PhoenixServer.UserSocket do
  use Phoenix.Socket

  ## Channels
  channel "rooms:*", PhoenixServer.RoomChannel

  ## Transports
  transport :websocket, Phoenix.Transports.WebSocket,
    timeout: :infinity

  def connect(_params, socket) do
    {:ok, socket}
  end

  def id(_socket), do: nil
end

but, it doesn't work...

What should I do to keep socket connection?

onError event

I'm new to swift, so I may be misreading the source code on this, but it doesn't look like there is a way to know about an error event? I would really like to be able to listen for errors and respond to error events.

iOS 8

Is it possible to make version 2 work with iOS 8 rather than 9 only?

Setup socket

Hello,

Is possible to initialize socket within viewDidLoad method it's important to pass some special parameters like token for example the scenario is user login get the token and after construct socket object in my example doesn't seems to work any ideas?

Enhancement or bridge to Objective-C

Hey!

I would love to help, just some thoughts;

There's a existing Objective-C library, I have opened a issue to see if it's still maintained. By the looks of it, I think its abandoned.

I'm still learning Elixir and playing around with Phoenix. I am comfortable in Objective-C and have some experience with Swift. What I can do is, either help out with some of the issues labeled as enhancements or write the bridging header to Objective-C.

Any enhancements that should be prioritised?

Cheers 😄

Leave not public and has wrong event

I've avoided creating a pull request for this as I'm hanging out for #17 to get pulled in, and my fork currently conflicts with that as it also fixes the same issue.

The leave methods on Phoenix.Socket and Phoenix.Channel aren't public, and the leave method that is there isn't using the right phx_leave event in the message. You can see my commit here for the fix: sjrmanning@8f652ad

JSON parsing

May I ask why you used an external JSON parsing library? It causes some troubles with my messages. Two examples:
JSON:

{
    "someString": "with value",
    "data": [{
        "title": "Hello",
        "nested": [{
            "subtitle": "One level deep",
            "id": 1
        }]
    }]
}

It does not parse nested JSON:

let json = "{\"someString\":\"with value\",\"data\":[{\"title\":\"Hello\",\"nested\":[{\"subtitle\":\"One level deep\",\"id\":1}]}]}"
// parsing json as in Phoenix.swift
let parsed = JSON.parse(json)
let msg: [String: AnyObject] = parsed.asDictionary!
// msg is then stored in Phoenix.Message

// For comparison the ios native way
let data = json.dataUsingEncoding(NSUTF8StringEncoding)!
let iosMsg = try! NSJSONSerialization.JSONObjectWithData(data, options: [])

// in the debugger you can see that it did not parse the nested elements:
po msg
 2 elements
   [0] : 2 elements
    - .0 : "data"
     .1 : [{"title":"Hello","nested":[{"subtitle":"One level deep","id":1}]}]
   [1] : 2 elements
    - .0 : "someString"
     .1 : with value

// the native ios solution however parses it correctly:
po iosMsg
 2 elements
   [0] : 2 elements
    - .0 : someString
    - .1 : with value
   [1] : 2 elements
    - .0 : data
     .1 : 1 elements
       [0] : 2 elements
         [0] : 2 elements
          - .0 : title
          - .1 : Hello
         [1] : 2 elements
          - .0 : nested
           .1 : 1 elements
             [0] : 2 elements
               [0] : 2 elements
                - .0 : subtitle
                - .1 : One level deep
               [1] : 2 elements
                - .0 : id

Type casting is a problem / not working:

// again with the parsed json from above, I try to cast the AnyObject to a Swift String:
// msg["someString"]
// ▿ Optional<AnyObject>
//   ▿ Some : with value

msg["someString"] as! String
// Could not cast value of type 'SwiftPhoenixClient.JSON' (0x10fec19e8) to 'NSString' (0x111031b48).
// error: Execution was interrupted, reason: signal SIGABRT.
// The process has been returned to the state before expression evaluation.

// which fails, in the chat app example the solution is the following, which looks quite ugly:
"\(msg["someString"])"
// also this solution gets worse when parsing integers:
Int64("\(msg["id"]!)")

// native ios solution:
iosMsg["someString"] as! String
// => "with value" a real String

Maybe we should provide a way to access the raw String or NSData inside the Phoenix.Message coming from the websocket? Then it would be possible to choose a different parser.

"Invalid HTTP upgrade"

Hey,

I am testing the iOS client with the phoenix chat example. Everything works fine locally. When I deploy to heroku, I can't connect through web socket via the iOS client ( js client works fine). I get this error:
socket closed: Optional("Invalid HTTP upgrade").
Can you help me understanding what's wrong? and how to fix it?

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.