{"action":"created","comment":{"url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/pulls/comments/48617665","id":48617665,"diff_hunk":"@@ -0,0 +1,380 @@\n+# Meta\n+\n+ - RFC Name: SubDocument API for clients\n+ - RFC ID: 0002\n+ - Start Date: 2015-11-11\n+ - Owner: Mark Nunberg\n+ - Current Status: Draft\n+\n+# Summary\n+\n+This RFC proposes a client-side API for the Sub-Document operations which will\n+be released in a future server version.\n+\n+# Motivation\n+\n+Expose the high performance subdocument API to developers\n+\n+# General Design\n+\n+## Terminology\n+\n+* Document: A document or item in the Memcached sense.\n+* Path: A specific location in a JSON document. A path uses the path syntax\n+  described in the server-side API.\n+* Sub-Document: A section of a document, specified by the path.\n+* Top-level: Document-level operations, for example `upsert`.\n+\n+## Overview\n+\n+The Sub-Document API exposes CRUD-like methods which operate on paths _within_\n+documents. In these respects it is identical to CRUD methods except that it\n+treats each path as its own \"sub-document\" (hence the name).\n+\n+Subdocument operations come in two flavors. One is the simple single-operation\n+form which takes a single document ID and a single path. Another is a\n+_multi-path_ form which retrieves or mutates _several_ paths within a document.\n+\n+Single-path methods are slightly more efficient and require less processing\n+overhead than their multi-path equivalents (that is, even if you pass a single\n+path to a multipath method, some additional processing overhead may be involved).\n+\n+Note that both 'multi-path' and 'single-path' APIs operate on the same\n+document, and correspond to a single binary operation. This should not be\n+confused with 'multi' operations in some SDKs which pipeline multiple binary\n+requests in the network.\n+\n+## Objects\n+\n+### Document/Item\n+\n+This class, used in top-level KV operations, is also employed by the sub-document\n+API to return values or indicate status.\n+\n+[The `Document` _may_ be subclassed into `DocumentFragment` to signal that the\n+value contained therein is only _part_ of the document (a fragment).\n+\n+This subclass contains the same fields as the `Document`, except the `value`\n+(or `contents`) is replaced by the `fragment` field. This is to avoid confusion\n+regarding whether the value \"truly\" contains the entire document value, or\n+merely a subdoc.\n+\n+The `Document` object itself is the return value from normal KV operations\n+which contain the value, cas, mutation token, etc.\n+\n+This object is used as an example, some SDKs may wish to either use the\n+'value' or 'document' field of the existing `Document` return value, or\n+subclass it, replacing value with 'fragment'.\n+\n+## Path\n+\n+From the perspective of the SDK, the path is a simple string used to specify\n+a location within the document. The path uses N1QL syntax to specify locations\n+within a document, thus a valid path may be:\n+\n+    foo.bar.baz\n+\n+or\n+\n+    `foo`.`bar`.`baz`\n+\n+or\n+\n+    `foo.some_array[0]`\n+\n+or\n+\n+    `foo.some_array[-1]`\n+\n+As in N1QL, special path characters may be escaped via a backtick (`` ` ``).\n+\n+Some operations (notably, those taking a path to an array) may accept the\n+_empty path_ (i.e. an empty string)\n+which refers to the entire document. This is valid if the document is a bare\n+JSON array.\n+\n+Each path component must be valid JSON (without the enclosing quotes). This\n+means that things like tabs, quotes, and backslashes must be escaped. To think\n+of it another way, the path matching algorithm in the server works via simple\n+string comparison, so a JSON key `\"bs\\\\ and \\t tabs are here\" would be matched\n+by a path component of `\"bs\\\\ and \\t tabs are here\"`.\n+\n+The SDK MUST verify that a path is non-empty for operations which do not\n+support empty paths. All other forms of path verification is done on the server\n+(but an empty path for unsupported operations will return a memcached `EINVAL`\n+which isn't really helpful).\n+\n+## Single-path Methods\n+\n+Methods are named exactly like their top-level counterparts, and should also\n+exist at the top level as well.\n+\n+Error codes are common to most operations.\n+\n+### `get_in(docid, path)`\n+Gets a single path from the document. Returns a `Document`\n+(or `DocumentFragment`) containing the path value.\n+\n+* `docid`: Document ID\n+* `path`: The sub-document path\n+\n+### `exists_in(docid, path)`\n+\n+Like `get_in`, but does not return the value (only checks if it exists)`. If the\n+item does not exist, the error code is suitably set in the result (or whatever\n+the appropriate error delivery mechanism is for the SDK).\n+\n+### `upsert_in(docid, path, value, create_parents, cas, ttl, persist_to, replicate_to)`\n+Unconditionally places the specified value in the provided path.\n+\n+* `docid`: Document ID\n+* `path`: the sub-document path\n+* `value`: the sub-document value. This should be anything JSON-serializable.\n+  JSON primitives such as true, false, null, strings and numbers are accepted\n+  too.\n+* `create_parents`: Boolean parameter indicating whether the full parent tree\n+  should be created. By default, only the _last_ path element is created if\n+  it does not exist.\n+* `cas`: Exactly the same meaning as it has in top-level CRUD operations.\n+* `ttl`: Expiration time. This has the same meaning as it does in the CRUD\n+  operations. The TTL can be set for _all_ mutation methods.\n+* `persist_to`, `replicate_to`: Durability requirements. Functions exactly as in CRUD\n+\n+> *NOTE*: This (And the other sub-document APIs) will never create or remove documents\n+> on the server. This means that if the document does not exist, a `KEY_ENOENT`\n+> is returned from the server. The document is never created, even if `create_parents`\n+> is true\n+\n+### `insert_in(docid, path, value, create_parents, cas, ttl, persist_to, replicate_to)`\n+Exactly like `upsert_in`, except the path must not already exist.\n+If it does, `PathExists` is thrown.\n+\n+### `replace_in(docid, path, value, cas, ttl, persist_to, replicate_to)`\n+Exactly like `upsert_in`, except the penultimate path must exist. If it \n+not exist, `PathNotFound` is thrown. Unlike `insert_in` and `upsert_in`,\n+`replace_in` can work on both dictionary and array values\n+\n+### `extend_in(docid, path, value_or_values, direction, create_parents, cas, ttl, persist_to, replicate_to)`\n+Add an element to the back or front of an array.\n+\n+* `value_or_values`: Can be a single JSON value, or a list of multiple\n+  JSON values. The list should be of a special type (MultiValue) so the\n+  SDK should not serialize the list itself as JSON.\n+* `direction`: `FRONT` or `BACK` depending on whether the item is to be\n+  added to the beginning or end of the array\n+* `create_parents`: Create the enclosing array and any intermediate elements.\n+  If this is not set, then the immediate array must exist.\n+\n+### `arrayinsert_in(docid, path, value_or_values, cas, ttl, persist_to, replicate_to)`\n+Insert an element(s) at a given position in the array. The path should indicate\n+the desired position at which to insert the new element(s).\n+\n+**FIXME:** This should really be `insert_in`, but we are already using that for\n+the object-based insert.\n+\n+### `addunique_in(docid, path, value, create_parents, ttl, persist_to, replicate_to)`\n+Adds a 'unique' element into an array (at which end is not defined or specified).\n+Functions exactly like `extend_in`. There are some server-side constraints into\n+which values can be used for unique operations - currently it is restricted to\n+JSON primitives (so no compound items).\n+\n+* Throws `PathExists` if the unique element already exists\n+* Throws `CantInsertValue` if the value is not a JSON primitive.\n+* Throws `PathMismatch` if the array already contains non-primitive elements\n+\n+> Because there is too much variation in semantics between `add_unique_in` and\n+> `extend_in`, they are separate methods rather than a single unified one.\n+\n+### `counter_in(docid, path, delta, create_parents, cas, ttl, persist_to, replicate_to)`\n+Performs an atomic counter operation on a given path.\n+\n+* `delta`: The numeric delta, this is simply added (`+`) to the existing value.\n+  This value may be signed to 'decrement' or unsigned to 'increment' the existing\n+  value.\n+\n+See \"Numeric Errors\" below for a list of errors thrown by this operation.\n+This method also returns the current value as a `DocumentFragment`\n+\n+### `remove_in(docid, path, cas, ttl, persist_to, replicate_to)`\n+Removes a path from the document\n+\n+## Multi-Path methods\n+\n+These methods take a document ID and a list of _specifications_ to perform. There are\n+only two methods (`mutate_in` and `lookup_in`).\n+\n+The specification of each method is highly language specific, to use pseudo code, we will\n+pretend there are two static helper classes which generate appropriate specs:\n+\n+### `LookupSpec`\n+Creates lookup specifications. There are two 'static methods'\n+\n+* `LookupSpec.get(docid)` (takes the same arguments as `get_in`\n+* `LookupSpec.exists(docid)` (takes the same arguments as `exists_in`)\n+\n+Both these objects should return a spec suitable for consumption by the `lookup_in`\n+method.\n+\n+### `MutationSpec`\n+Creates mutation specifications. There are several 'static methods' which may be used.\n+These all function exactly like their single-path counterparts except that the document\n+ID and cas are not provided (these are passed directly into `mutate_in`).\n+\n+* `MutationSpec.replace(path, value)`: See `replace_in`\n+* `MutationSpec.upsert(path, value, create_parents)`. See `upsert_in`\n+* `MutationSpec.insert(path, value, create_parents)`. See `insert_in`\n+* `MutationSpec.extend(path, value_or_values, direction, create_parents)`. See `extend_in`\n+* `MutationSpec.arrayinsert(path, value_or_values)`. See `arrayinsert_in`\n+* `MutationSpec.addunique(path, value)`. See `addunique_in`\n+* `MutationSpec.counter(path, delta)`. See `counter_in`\n+* `MutationSpec.remove(path)`. See `remove_in`\n+\n+### `LookupResultSpec`\n+This object represents a result for a single path when using `lookup_in`.\n+It contains two fields:\n+\n+* `status`: The error code for the operation. If the path exists, this should\n+  contain an object or value which indicates \"Success\" (this can be a NULL or\n+  empty value to indicate no error)\n+* `value`: The value for the path. This is always empty when using `exists`.\n+\n+\n+### `lookup_in(docid, lookup_specs...)`\n+\n+Retrieve (or check the existence of) multiple paths.\n+\n+Returns a list of MetaDocFragment objects. Individual objects may also","path":"draft/0002-subdocapi.md","position":246,"original_position":246,"commit_id":"2ad71302928365c4506c58ce894dceb00c91af6d","original_commit_id":"2ad71302928365c4506c58ce894dceb00c91af6d","user":{"login":"mnunberg","id":436049,"avatar_url":"https://avatars.githubusercontent.com/u/436049?v=3","gravatar_id":"","url":"https://api.github.com/users/mnunberg","html_url":"https://github.com/mnunberg","followers_url":"https://api.github.com/users/mnunberg/followers","following_url":"https://api.github.com/users/mnunberg/following{/other_user}","gists_url":"https://api.github.com/users/mnunberg/gists{/gist_id}","starred_url":"https://api.github.com/users/mnunberg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mnunberg/subscriptions","organizations_url":"https://api.github.com/users/mnunberg/orgs","repos_url":"https://api.github.com/users/mnunberg/repos","events_url":"https://api.github.com/users/mnunberg/events{/privacy}","received_events_url":"https://api.github.com/users/mnunberg/received_events","type":"User","site_admin":false},"body":"This is an errror, which I believe I fixed? it shouldn’t return a list of fragments\n> On Dec 30, 2015, at 2:03 AM, Michael Nitschinger <notifications@github.com> wrote:\n> \n> In draft/0002-subdocapi.md <https://github.com/couchbaselabs/sdk-rfcs/pull/2#discussion_r48596041>:\n> \n> > +\n> > +### `LookupResultSpec`\n> > +This object represents a result for a single path when using `lookup_in`.\n> > +It contains two fields:\n> > +\n> > +* `status`: The error code for the operation. If the path exists, this should\n> > +  contain an object or value which indicates \"Success\" (this can be a NULL or\n> > +  empty value to indicate no error)\n> > +* `value`: The value for the path. This is always empty when using `exists`.\n> > +\n> > +\n> > +### `lookup_in(docid, lookup_specs...)`\n> > +\n> > +Retrieve (or check the existence of) multiple paths.\n> > +\n> > +Returns a list of MetaDocFragment objects. Individual objects may also\n> if we dont put the path into the fragment, wouldn't then then actually be one DocumentFragment with a list of actual fragments inside? Of course if we put the path into the fragment its ambiguous...\n> \n> I'm asking since most of the stuff is duplicated (like the id(), cas().. and so on)..\n> \n> —\n> Reply to this email directly or view it on GitHub <https://github.com/couchbaselabs/sdk-rfcs/pull/2/files#r48596041>.\n> \n\n","created_at":"2015-12-30T17:25:28Z","updated_at":"2015-12-30T17:25:28Z","html_url":"https://github.com/couchbaselabs/sdk-rfcs/pull/2#discussion_r48617665","pull_request_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/pulls/2","_links":{"self":{"href":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/pulls/comments/48617665"},"html":{"href":"https://github.com/couchbaselabs/sdk-rfcs/pull/2#discussion_r48617665"},"pull_request":{"href":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/pulls/2"}}},"pull_request":{"url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/pulls/2","id":50453840,"html_url":"https://github.com/couchbaselabs/sdk-rfcs/pull/2","diff_url":"https://github.com/couchbaselabs/sdk-rfcs/pull/2.diff","patch_url":"https://github.com/couchbaselabs/sdk-rfcs/pull/2.patch","issue_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/issues/2","number":2,"state":"open","locked":false,"title":"0002-subdocapi","user":{"login":"mnunberg","id":436049,"avatar_url":"https://avatars.githubusercontent.com/u/436049?v=3","gravatar_id":"","url":"https://api.github.com/users/mnunberg","html_url":"https://github.com/mnunberg","followers_url":"https://api.github.com/users/mnunberg/followers","following_url":"https://api.github.com/users/mnunberg/following{/other_user}","gists_url":"https://api.github.com/users/mnunberg/gists{/gist_id}","starred_url":"https://api.github.com/users/mnunberg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mnunberg/subscriptions","organizations_url":"https://api.github.com/users/mnunberg/orgs","repos_url":"https://api.github.com/users/mnunberg/repos","events_url":"https://api.github.com/users/mnunberg/events{/privacy}","received_events_url":"https://api.github.com/users/mnunberg/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-11-11T23:51:48Z","updated_at":"2015-12-30T17:25:28Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b43c468a9a5b7f5b940dc8be07395c5845ea285c","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/pulls/2/commits","review_comments_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/pulls/2/comments","review_comment_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/pulls/comments{/number}","comments_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/issues/2/comments","statuses_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/statuses/2ad71302928365c4506c58ce894dceb00c91af6d","head":{"label":"mnunberg:0002-subdoc","ref":"0002-subdoc","sha":"2ad71302928365c4506c58ce894dceb00c91af6d","user":{"login":"mnunberg","id":436049,"avatar_url":"https://avatars.githubusercontent.com/u/436049?v=3","gravatar_id":"","url":"https://api.github.com/users/mnunberg","html_url":"https://github.com/mnunberg","followers_url":"https://api.github.com/users/mnunberg/followers","following_url":"https://api.github.com/users/mnunberg/following{/other_user}","gists_url":"https://api.github.com/users/mnunberg/gists{/gist_id}","starred_url":"https://api.github.com/users/mnunberg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mnunberg/subscriptions","organizations_url":"https://api.github.com/users/mnunberg/orgs","repos_url":"https://api.github.com/users/mnunberg/repos","events_url":"https://api.github.com/users/mnunberg/events{/privacy}","received_events_url":"https://api.github.com/users/mnunberg/received_events","type":"User","site_admin":false},"repo":{"id":46017504,"name":"sdk-rfcs","full_name":"mnunberg/sdk-rfcs","owner":{"login":"mnunberg","id":436049,"avatar_url":"https://avatars.githubusercontent.com/u/436049?v=3","gravatar_id":"","url":"https://api.github.com/users/mnunberg","html_url":"https://github.com/mnunberg","followers_url":"https://api.github.com/users/mnunberg/followers","following_url":"https://api.github.com/users/mnunberg/following{/other_user}","gists_url":"https://api.github.com/users/mnunberg/gists{/gist_id}","starred_url":"https://api.github.com/users/mnunberg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mnunberg/subscriptions","organizations_url":"https://api.github.com/users/mnunberg/orgs","repos_url":"https://api.github.com/users/mnunberg/repos","events_url":"https://api.github.com/users/mnunberg/events{/privacy}","received_events_url":"https://api.github.com/users/mnunberg/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mnunberg/sdk-rfcs","description":"SDK RFCs","fork":true,"url":"https://api.github.com/repos/mnunberg/sdk-rfcs","forks_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/forks","keys_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/teams","hooks_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/hooks","issue_events_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/issues/events{/number}","events_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/events","assignees_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/assignees{/user}","branches_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/branches{/branch}","tags_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/tags","blobs_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/git/refs{/sha}","trees_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/statuses/{sha}","languages_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/languages","stargazers_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/stargazers","contributors_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/contributors","subscribers_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/subscribers","subscription_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/subscription","commits_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/commits{/sha}","git_commits_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/git/commits{/sha}","comments_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/comments{/number}","issue_comment_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/issues/comments{/number}","contents_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/contents/{+path}","compare_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/merges","archive_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/downloads","issues_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/issues{/number}","pulls_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/pulls{/number}","milestones_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/milestones{/number}","notifications_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/labels{/name}","releases_url":"https://api.github.com/repos/mnunberg/sdk-rfcs/releases{/id}","created_at":"2015-11-11T23:50:52Z","updated_at":"2015-10-23T07:26:18Z","pushed_at":"2015-12-29T17:38:30Z","git_url":"git://github.com/mnunberg/sdk-rfcs.git","ssh_url":"git@github.com:mnunberg/sdk-rfcs.git","clone_url":"https://github.com/mnunberg/sdk-rfcs.git","svn_url":"https://github.com/mnunberg/sdk-rfcs","homepage":null,"size":9,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"couchbaselabs:master","ref":"master","sha":"1f52b573de725142f3a1e3dcff27ed25abdaa191","user":{"login":"couchbaselabs","id":636956,"avatar_url":"https://avatars.githubusercontent.com/u/636956?v=3","gravatar_id":"","url":"https://api.github.com/users/couchbaselabs","html_url":"https://github.com/couchbaselabs","followers_url":"https://api.github.com/users/couchbaselabs/followers","following_url":"https://api.github.com/users/couchbaselabs/following{/other_user}","gists_url":"https://api.github.com/users/couchbaselabs/gists{/gist_id}","starred_url":"https://api.github.com/users/couchbaselabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/couchbaselabs/subscriptions","organizations_url":"https://api.github.com/users/couchbaselabs/orgs","repos_url":"https://api.github.com/users/couchbaselabs/repos","events_url":"https://api.github.com/users/couchbaselabs/events{/privacy}","received_events_url":"https://api.github.com/users/couchbaselabs/received_events","type":"Organization","site_admin":false},"repo":{"id":44797604,"name":"sdk-rfcs","full_name":"couchbaselabs/sdk-rfcs","owner":{"login":"couchbaselabs","id":636956,"avatar_url":"https://avatars.githubusercontent.com/u/636956?v=3","gravatar_id":"","url":"https://api.github.com/users/couchbaselabs","html_url":"https://github.com/couchbaselabs","followers_url":"https://api.github.com/users/couchbaselabs/followers","following_url":"https://api.github.com/users/couchbaselabs/following{/other_user}","gists_url":"https://api.github.com/users/couchbaselabs/gists{/gist_id}","starred_url":"https://api.github.com/users/couchbaselabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/couchbaselabs/subscriptions","organizations_url":"https://api.github.com/users/couchbaselabs/orgs","repos_url":"https://api.github.com/users/couchbaselabs/repos","events_url":"https://api.github.com/users/couchbaselabs/events{/privacy}","received_events_url":"https://api.github.com/users/couchbaselabs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/couchbaselabs/sdk-rfcs","description":"SDK RFCs","fork":false,"url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs","forks_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/forks","keys_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/teams","hooks_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/hooks","issue_events_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/issues/events{/number}","events_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/events","assignees_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/assignees{/user}","branches_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/branches{/branch}","tags_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/tags","blobs_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/git/refs{/sha}","trees_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/statuses/{sha}","languages_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/languages","stargazers_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/stargazers","contributors_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/contributors","subscribers_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/subscribers","subscription_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/subscription","commits_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/commits{/sha}","git_commits_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/git/commits{/sha}","comments_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/comments{/number}","issue_comment_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/issues/comments{/number}","contents_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/contents/{+path}","compare_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/merges","archive_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/downloads","issues_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/issues{/number}","pulls_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/pulls{/number}","milestones_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/milestones{/number}","notifications_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/labels{/name}","releases_url":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/releases{/id}","created_at":"2015-10-23T07:26:18Z","updated_at":"2015-10-23T07:26:18Z","pushed_at":"2015-12-29T17:38:30Z","git_url":"git://github.com/couchbaselabs/sdk-rfcs.git","ssh_url":"git@github.com:couchbaselabs/sdk-rfcs.git","clone_url":"https://github.com/couchbaselabs/sdk-rfcs.git","svn_url":"https://github.com/couchbaselabs/sdk-rfcs","homepage":null,"size":22,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2,"mirror_url":null,"open_issues_count":7,"forks":2,"open_issues":7,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/pulls/2"},"html":{"href":"https://github.com/couchbaselabs/sdk-rfcs/pull/2"},"issue":{"href":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/issues/2"},"comments":{"href":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/issues/2/comments"},"review_comments":{"href":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/pulls/2/comments"},"review_comment":{"href":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/pulls/2/commits"},"statuses":{"href":"https://api.github.com/repos/couchbaselabs/sdk-rfcs/statuses/2ad71302928365c4506c58ce894dceb00c91af6d"}}}}