Giter VIP home page Giter VIP logo

seam's Introduction

seamlogo

Pod Version Carthage Compatible Platform License

Seam allows you to sync your CoreData Stores with CloudKit.

Topics

Features

  • Automatic mapping of CoreData Models to CloudKit Private Databases
  • Supports Assets
  • Background Sync
  • Conflict Resolution

Requirements

  • iOS 8.0+ / Mac OS X 10.10+
  • Xcode 7.1+

Communication

Please read the Contributing Guidelines before doing any of above.

Installation

Cocoapods

CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:

$ gem install cocoapods

To integrate Seam into your Xcode project using CocoaPods, specify it in your Podfile:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!

pod 'Seam', '~> 0.6'

Then, run the following command:

$ pod install

Carthage

Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.

You can install Carthage with Homebrew using the following command:

$ brew update
$ brew install carthage

To integrate Seam into your Xcode project using Carthage, specify it in your Cartfile:

github "Seam/Seam" ~> 0.6

Run carthage update to build the framework and drag the built Seam.framework into your Xcode project.

Usage

Add a Store type of SeamStoreType to a NSPersistentStoreCoordinator in your CoreData stack:

let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: yourModel)
let seamStore = try persistentStoreCoordinator.addPersistentStoreWithType(SeamStoreType, 
                                                                          configuration: nil, 
                                                                          URL: url, options: nil) as? Store

Observe the following two Notifications to know when the Sync Operation starts and finishes:

NSNotificationCenter.defaultCenter().addObserver(self, selector: "didStartSyncing:",
                                                name: SMStoreDidStartSyncingNotification,
                                                object: seamStore)

NSNotificationCenter.defaultCenter().addObserver(self, selector: "didFinishSyncing:",
                                                name: SMStoreDidFinishSyncingNotification,
                                                object: seamStore)                                               

func didStartSyncing(notification: NSNotification) {
  // Prepare for new data before syncing completes
}
  
func didFinishSyncing(notification: NSNotification) {
  // Merge Changes into your context after syncing completes
  mainContext.mergeChangesFromStoreDidFinishSyncingNotification(notification)
}
  

Finally call sync whenever and wherever you want:

seamStore.sync(nil)

To trigger sync whenever a change happens on the CloudKit Servers. Subscribe the store to receive Push Notifications from the CloudKit Servers.

seamStore.subscribeToPushNotifications({ successful in
    guard successful else { return }
    // Ensured that subscription was created successfully
})

// In your AppDelegate

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
    seamStore.sync(nil)
}

Attributes

All CloudKit Attributes are mapped automatically to your CoreData attributes with the exception of CKAsset and CLLocation.

CKAsset and CLLocation can be used by setting the corresponding attribute as Transformable in your CoreData Model.

CloudKit CoreData
NSDate NSDate
NSData NSData
NSString NSString
NSNumber NSNumber
CKReference NSManagedObject
CKAsset Transformable
CLLocation Transformable

Transformable Attributes

CKAsset and CLLocation can be used in your CoreData model as Transformable attributes.

  1. To use CKAsset set Transformable as AttributeType and CKAssetTransformer as value transformer name for the attribute.

  1. To use CLLocation set Transformable as AttributeType and CLLocationTransformer as value transformer name for the attribute.

Relationships

CoreData Relationship Translation on CloudKit
To - one To one relationships are translated as CKReferences on the CloudKit Servers.
To - many To many relationships are not explicitly created. Seam only creates and manages to-one relationships on the CloudKit Servers.
Example -> If an Employee has a to-one relationship to Department and Department has a to-many relationship to Employee than Seam will only create the former on the CloudKit Servers. It will fullfil the later by using the to-one relationship. If all employees of a department are accessed Seam will fulfil it by fetching all the employees that belong to that particular department.

Note : You must create inverse relationships in your app's CoreData Model or Seam wouldn't be able to translate CoreData Models in to CloudKit Records. Unexpected errors and curroption of data can possibly occur.

Getting Started

Download the demo project. Run it and see the magic as it happens.

FAQ

tvOS Support ?

tvOS provides no persistent local storage. Seam uses SQLITE file to keep a local copy of your database which is not possible with tvOS.

Apps

A list of Apps which are using Seam.

Author

Seam is owned and maintained by Nofel Mahmood.

You can follow him on Twitter and Medium

License

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

seam's People

Contributors

nofelmahmood 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

seam's Issues

Taking CoreData operations off main thread

Hello guys!

According to best practices, it is better to do Coredata related operations in the background, not to cause any possible performance drops, or UI blocks.

I feel like you are doing some database access in the main thread:

Class:StoreRelationshipTests function:testAddingTagToAlreadyAddedTask is calling deleteAll which is doing database operations.

Don't you think it would be better to take these operations off the main thread?

SeamDemo infinite loop

SeamDemo runs in an infinite loop, consumes more and more memory, until it finally crashes.

Steps to reproduce:

  1. Download the current master branch.
  2. Change the Bundle Identifier in the SeamDemo project to something unique.
  3. Add a custom iCloud container and select it as the only one to use.
  4. Run the app either in the simulator or on an device.

I expect the app to normally run, and not to sync anything until I create a first record. I use the latest iOS 9, OS X 10.11 & Xcode 7 betas. Currently I just get the following output until the demo app crashes:

Sync Started
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
More Coming
…

On inspecting ~/Library/Mobile Documents/ I don’t see the corresponding subfolder created by Apple’s frameworks which is normally present when you use Core Data + iCloud and I don’t see any data in the CloudKit Dashboard.

Getting NSInternalInconsistencyException

Hi Nofel

I seem to have everything setup but when I launch my app I am getting the following exception:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Entity already contains a property named sm_LocalStore_RecordID.'

It looks like it is happening in:

func addExtraBackingStoreAttributes(toEntity entity: NSEntityDescription)

line:

 entity.properties.append(recordIDAttribute)

Have you any ideas why this may be happening?

Just a little bit more background as my setup wasn't too straightforward.

I'm using the framework in an Objective C app - and struggled to get it to link using CocoaPods. So for now I've just copied in your Swift code files and accessing the Swift via #import "ProjectName-Swift.h"

This is how I am adding the Store Type.

 smStore = [coordinator addPersistentStoreWithType:SMStore.type configuration:nil URL:storeUrl options:nil error:nil];

(I had to use SMStore.type directly as I couldn't get at SeamStoreType)

Any help or pointers would be much appreciated.
Thank you

WatchOS2 support!

With the current implementation there is no way to sync with the Apple watch app. It would be great if we found a way to do it. As off WatchOS2, there are two stores now, so this library would be in great demand if it works with the watch app

Many-to-many relations

Are many-to-many relationships supported as well? Or only one-to-many?

Example:

  • A user can be in many groups
  • A group can hold many users

or

  • An item has many tags and
  • A tag has many items

Would that be a problem?

How does Seam handle migration?

This library looks awesome. :) I had a few questions:

  • How does Seam handle two different model versions on two different devices, both trying to use the same records/keys?
  • How does Seam handle the user downloading the app, sending data to the cloud, then downloading a newer version of the app at a later date, with an updated model version?

Object not saved correctly

Object not saved correctly.

My steps:
First I create a client it works fine.
Then I create a project but the project is not saved correctly, it appears until I close and open the app. Then its gone.
The project is not synced to the cloud kit either. Thats an fail I haven’t seen before. It works local with coredata and it doesn't give me any error.
So It can be hard to debug :(

CloudKit Public database support

Personally I don't really see the need for private database support since we already have iCloud Core Data storage which does the same thing. Public on the other hand introduces many opportunities. Can't you use queries for higher change tag or modified time to enable you to do the sync without the requirement for custom zones and change requests?

Manual attaching of CKAssets to a record

It is best practice to store big blobs of data (such as images) on the filesystem. An interface to add CKAssets to records would be desirable.

Since the CKSRecordContext is holding all records, the user could manually attach CKAssets to records before calling save() on it. Maybe even an automated option might be possible (e.g. if there is a file path stored in an attribute, a CKAsset could be created)?

unexpectedly found nil while unwrapping an Optional value

This code works the first time though when I run it a second time on the line:

  • result.name = "(result.name! ) ClientChange" I get the error
    (unexpectedly found nil while unwrapping an Optional value)

let moc = CoreDataStack.defaultStack.managedObjectContext

    let task: Task = NSEntityDescription.insertNewObjectForEntityForName("Task", inManagedObjectContext: moc) as! Task
    task.name = "HElaLuia"

    let cycling: Task = NSEntityDescription.insertNewObjectForEntityForName("Task", inManagedObjectContext: moc) as! Task
    cycling.name = "Foolish"

    let biking: Task = NSEntityDescription.insertNewObjectForEntityForName("Task", inManagedObjectContext: moc) as! Task
    biking.name = "Acting"

    let outdoorTasksTag = NSEntityDescription.insertNewObjectForEntityForName("Tag", inManagedObjectContext: moc) as! Tag
    outdoorTasksTag.name = "AnotherTag"

    let newTasksTag = NSEntityDescription.insertNewObjectForEntityForName("Tag", inManagedObjectContext: moc) as! Tag
    newTasksTag.name = "Just Another Tag"
    newTasksTag.task = biking

    outdoorTasksTag.task = cycling


    if moc.hasChanges
    {
        do
        {
            try moc.save()
        }
        catch let error as NSError?
        {
            print("Error Occured \(error!)", terminator: "\n")
        }
    }
    CoreDataStack.defaultStack.seamStore!.triggerSync()



            do
            {
                try moc.save()
            }
            catch
            {
                print("Error thrown baby", terminator: "\n")
            }



            let fetchRequest: NSFetchRequest = NSFetchRequest(entityName: "Task")
            do
            {
                let results = try moc.executeFetchRequest(fetchRequest)
                for result in results as! [Task]
                {


                    result.name = "\(result.name! ) ClientChange"
                    NSLog ("result.name  %@ \n",result);
                }
                try moc.save()
            }
            catch
            {

            }

Also can you give a demo of how to use the cloudKit functionality.
Thank you in Advance. :)

'Cannot retrieve referenceObject from an objectID that was not created by this store’ error

I have an object called Client, which have a NSSet of Projects and the Project object have a Client reference.

I can create a client and edit it as long as it dosen’t have any projects.
But when I create a project and give the project a client. I can’t edit the client anymore.
Is gives me this error: 'Cannot retrieve referenceObject from an objectID that was not created by this store’

                managedContext.refreshObject(client, mergeChanges: false)
                for pro in client.projects {
                    managedContext.refreshObject(pro as! Project, mergeChanges: false)
                }

If I call the refresh method show above I dont get the earlier error but this:

Error Domain=NSCocoaErrorDomain Code=1550 "The operation couldn’t be completed. (Cocoa error 1550.)" UserInfo=0x1740ec100 {NSValidationErrorObject=<TimeTarget.Client: 0x1700bbfc0> (entity: Client; id: 0x170424720 x-coredata://EC349C9D-E6A5-4297-9B96-778618D88B0E-7984-000002915A9F1799/Client/pBA63AEE6-5C27-47A3-86B0-57FD57A8A1EE ; data: {
billable = 0;
color = 0;
defaultHourRate = 0;
name = Huhu4;
projects = (
"0xd000000000040002 x-coredata://8B9AF010-A46F-4A5B-872B-A87B38C291C5/Project/p1"
);
}), NSValidationErrorValue=Relationship 'projects' on managed object (0x1700bbfc0) <TimeTarget.Client: 0x1700bbfc0> (entity: Client; id: 0x170424720 x-coredata://EC349C9D-E6A5-4297-9B96-778618D88B0E-7984-000002915A9F1799/Client/pBA63AEE6-5C27-47A3-86B0-57FD57A8A1EE ; data: {
billable = 0;
color = 0;
defaultHourRate = 0;
name = Huhu4;
projects = (
"0xd000000000040002 x-coredata://8B9AF010-A46F-4A5B-872B-A87B38C291C5/Project/p1"
);
}) with objects {(
<TimeTarget.Project: 0x1700de060> (entity: Project; id: 0xd000000000040002 x-coredata://8B9AF010-A46F-4A5B-872B-A87B38C291C5/Project/p1 ; data: {
billable = nil;
"cks_LocalStore_Attribute_ChangeType" = 0;
"cks_LocalStore_Attribute_EncodedValues" = <62706c69 73743030 d4010203 04050649 4a582476 65727369 6f6e5824 6f626a65 63747359 24617263 68697665 72542474 6f70>;
"cks_LocalStore_Attribute_RecordID" = "5C8A7045-6398-441F-B3D1-46A30523C4D7";
client = "0xd000000000040000 x-coredata://8B9AF010-A46F-4A5B-872B-A87B38C291C5/Client/p1";
color = 0;
defaultHourRate = 0;
name = Nu;
})
)}, NSValidationErrorKey=projects, NSLocalizedDescription=The operation couldn’t be completed. (Cocoa error 1550.)}

Everything works if I dont use CKSIncrementalStore and only core data local on iPhone.

My core data model:
screen shot 2015-07-19 at 00 31 52

Push configuration

I am trying to figure out whether app should register for remote notifications or implementing didReceiveRemoteNotification should be sufficient enough.

To be fair I am not much familiar with CloudKit, and looking at both README and demo app I see inconsistencies.

Demo app does not register for remote notifications nor handles remote notifications. Is this somehow intentional?

How does one configure Seam to receive live updates from CloudKit?

SeamStoreType undeclared identifier

I have added Seam to my ObjectiveC project using CocoaPods, and successfully declared a property for the store:

@property (nonatomic, readonly) SMStore *seamStore;

I then use the following code to add it to my NSPersistentStoreCoordinator:

_store = [_coordinator addPersistentStoreWithType: SeamStoreType configuration: nil URL: storeURL options: options error: &error];

Which gives me an undeclared identifier error for SeamStoreType.

What do I need to do for my code to recognize SeamStoreType?

Demo App Crashes

When you run the app I receive an error in the CKIncrementalStore.swift for function triggerSync() on below line:

'''
...
if error == nil
{
print("Sync Performed Successfully")
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in

// CRASHES ON THIS LINE EVERY TIME NSNotificationCenter.defaultCenter().postNotificationName(CKSIncrementalStoreDidFinishSyncOperationNotification, object: self)

            })
        }

...
'''

When I comment that line out the app does not crash but syncing stops.

I also needed to add to the TableView a cell otherwise code crashes.

Thank you.

Crash because of NSMutableOrderedSet

Hello,

When using this library I get the following error message:
Could not cast value of type '_NSFaultingMutableOrderedSet' (0x19fe9c2e8) to 'NSSet' (0x19fe879e8).
It occurs in SMStore.swift - setRelationshipValuesForBackingObject: because of this line:

let relationshipValue: Set<NSObject> = sourceObject.valueForKey(relationship.name) as! Set<NSObject>

I can't find my mistake since I already got the inverse relations set up as you are describing in the README. I hope you can give me a hint why this does not work.

Here is my xcdatamodeld setup :
bildschirmfoto 2015-12-28 um 18 32 51
bildschirmfoto 2015-12-28 um 18 32 29
bildschirmfoto 2015-12-28 um 18 32 40
bildschirmfoto 2015-12-28 um 18 32 15

Zone.swift: Operations created, but not added to NSOperationQueue

In Zone.swift::subscriptionExistsOnServer an CKFetchSubscriptionsOperation operation is created, but never added to NSOperationQueue!

And also in Zone.swift::createSubscription(completionBlock: the CKFetchSubscriptionsOperation operation is created, but never added to the NSOperationQueue!

Is this intended behaviour?

Default data

Is it possible to start an application with some default data? I know how to do it with a sql based coredata app but no idea how to do it with a cloudkit based coredata.

TVOS support

Support for TVOS framework would be great, especially because on TVOS Core Data is not guaranteed to be persistent.

Crash in executeInResponseToFetchRequest

I see crash in executeInResponseToFetchRequest where it expects NSManagedObject but it gets NSManagedObjectID instead...

I am bridging MagicalRecord with Seam so I assume this may be the cause of me doing something wrong... or maybe not.

This is my current implementation which is simply uses Seam store, everything else is left intact:

https://gist.github.com/pronebird/1a6db53e6f75e7baf109

Log:

Not coming
Sync Performed
Sync Performed Successfully
Could not cast value of type '_NSCoreDataTaggedObjectID' (0x10784df60) to 'NSManagedObject' (0x10784e9b0).

Therefore in this context we get crash:

    // MARK : Fetch Request
    func executeInResponseToFetchRequest(fetchRequest:NSFetchRequest,context:NSManagedObjectContext) throws ->NSArray {
        let resultsFromLocalStore = try self.backingMOC.executeFetchRequest(fetchRequest)
        if resultsFromLocalStore.count > 0 {
            return resultsFromLocalStore.map({(result)->NSManagedObject in
                let result = result as! NSManagedObject <-- CRASH

Unacceptable type of value for to-one relationship

When I try to edit and TimeEntry i get this error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for to-one relationship: property = "project"; desired type = TimeTarget.Project; given type = TimeTarget.Project; value = (entity: Project; id: 0x174426160 x-coredata://6B81EA38-15B7-4C85-ADB5-6640EE31DF5D-9088-000002BEECC9720D/Project/p254230CF-A9CD-4CAD-B47F-19DFBA054081 ; data: {
billable = 0;
"cks_LocalStore_Attribute_ChangeType" = nil;
"cks_LocalStore_Attribute_EncodedValues" = nil;
"cks_LocalStore_Attribute_RecordID" = nil;
client = "0x174239480 x-coredata://6B81EA38-15B7-4C85-ADB5-6640EE31DF5D-9088-000002BEECC9720D/Client/p686DBB54-ACC5-4313-8369-2DF9B8003E4B";
color = 0;
defaultHourRate = 0;
name = Kk;
timeEntries = "";
}).'

And same when I try an edit an Project:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for to-one relationship: property = "client"; desired type = TimeTarget.Client; given type = TimeTarget.Client; value = (entity: Client; id: 0x174621ac0 x-coredata://17D56827-FF19-4DDD-8161-E4C930BC4398-9102-000002BF85C10C71/Client/p686DBB54-ACC5-4313-8369-2DF9B8003E4B ; data: {
billable = 0;
color = 0;
defaultHourRate = 0;
name = Klkj;
projects = (
"0x170432e00 x-coredata://17D56827-FF19-4DDD-8161-E4C930BC4398-9102-000002BF85C10C71/Project/p9E6EA418-FF51-492C-84ED-575A76659490",
"0x170432e20 x-coredata://17D56827-FF19-4DDD-8161-E4C930BC4398-9102-000002BF85C10C71/Project/p254230CF-A9CD-4CAD-B47F-19DFBA054081"
);
}).'

The client I can edit / save without problem. It first happens when I have closed the app and reopened the app again.

Model:
1f1e4122-2db4-11e5-9773-68432c8cc9c9

NSData Attribute Sync Crash

I've got my nsmanagedobject subclass which has also an nsdata attribute to store an image. That's not always needed and so when i set it to nil Seam Crashes.
Look at the screenshot below..
Hope in a fix..
Best regards
schermata 2015-08-26 alle 12 01 55

Package Seam as a Carthage Framework

I was wondering if it would be possible to have Seam set up as a Carthage framework, in addition to CocoaPods. I'm not sure what the process for doing so is, so I'm not sure if this is a monumental undertaking or not, but it would be a nice addition (and, for me, match the rest of my dependancies).

I'm excited to try Seam out, in place of my own super-hacky CoreData to CloudKit sync solution.

Swift 3.0 / App crashing

I have forked this project to my Bitbucket account, and have successfully got it compiling in Xcode 8, beta 6. The only problem is that the demo app is crashing on startup (I have the iCloud configurations set up on Apple's side).

Here is the crash: (SMStore.swift)

screen shot 2016-09-04 at 4 30 03 pm

I am not familiar enough with the codebase to fully understand what is going on. I could submit a pull request with my Swift 3.0 code, if that would help?

Thank you in advance for any assistance. I would really like to use this library in my application.

Works in iOS 8.1, requires 9.0

I have currently tested seam in iOS 8.1 and it seems to be working fine, but the minimum deployment target is iOS 9.0 which messes up my cocoapods setup. For the sake of compatibility I'm requesting the deployment target be changed to ios 8.1 at minimum (or iOS if it is tested as working). Thanks

Need to read from Notification Collection

When a push notification is received indicating changes have occurred it is necessary to read from the Notification Collection see if any notifications were dropped. Since push is "best effort" delivery and only the last notification is delivered while offline it is possible for notifications to be missed. This was covered in one of the videos from WWDC 2014. I'm not sure what the API call is for doing this.

Tutorial request

There is too much going on in the app.

I tried to recreate the app from scratch but its not working. I think I have missed to add something.

If you could post tutorial on medium then it would be great.

Thanks either way for this project.

Need to handle iCloud account changes

If the user switches iCloud accounts their local data will no longer match the server's data. In that case you would need initiate a complete two-way sync of all records stored both locally and on the server. In iOS 9 there is a notification you can subscribe to so you know when the account change happens, but in iOS 8 I believe the only option is to record the user's iCloud ID and poll it for changes periodically (like at startup?). Alternatively, providing a button to manually initiate a complete sync might be acceptable.

Repo status and CKContainer question

Is this repo still being updated? I see the branch Improve-Store (and forks) have been updated recently, but these branches are quite different from the latest release. 0.6 had some major errors for me, so I had to use Improve-Store. My issue is that I cannot define a custom CKContainer with an id different from the bundle_id. I've looked through the entire codebase for a while now and can't figure out how to change from the default container. Any help would be appreciated, 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.