{"action":"created","comment":{"url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/pulls/comments/234378793","pull_request_review_id":176019975,"id":234378793,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIzNDM3ODc5Mw==","diff_hunk":"@@ -0,0 +1,758 @@\n+/*!\n+ * Copyright 2017-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n+ * Licensed under the Amazon Software License (the \"License\"). You may not use this file except in compliance with the License. A copy of\n+ * the License is located at\n+ *     http://aws.amazon.com/asl/\n+ * or in the \"license\" file accompanying this file. This file is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n+ * KIND, express or implied. See the License for the specific language governing permissions and limitations under the License.\n+ */\n+import { OfflineAction } from \"@redux-offline/redux-offline/lib/types\";\n+import { NormalizedCacheObject, readQueryFromStore, defaultNormalizedCacheFactory } from \"apollo-cache-inmemory\";\n+import { Store, AnyAction } from \"redux\";\n+import { OfflineCache, AppSyncMetadataState, METADATA_KEY } from \"./cache/offline-cache\";\n+import AWSAppSyncClient, { OfflineCallback, SubscribeWithSyncOptions, QuerySyncOptions } from \"./client\";\n+import { OfflineEffectConfig } from \"./store\";\n+import { tryFunctionOrLogError, graphQLResultHasError, getMainDefinition, addTypenameToDocument } from \"apollo-utilities\";\n+import { OperationVariables, MutationUpdaterFn } from \"apollo-client\";\n+import { hash, getOperationFieldName } from \"./utils\";\n+import { Observable, FetchResult } from \"apollo-link\";\n+import { Subscription } from \"apollo-client/util/Observable\";\n+import { DataProxy } from \"apollo-cache\";\n+import debug from 'debug';\n+import { SKIP_RETRY_KEY } from \"./link/retry-link\";\n+import { DocumentNode, print, OperationDefinitionNode, FieldNode, ExecutionResult } from \"graphql\";\n+import { getOpTypeFromOperationName, CacheOperationTypes, getUpdater, QueryWithVariables } from \"./helpers/offline\";\n+import { boundSaveSnapshot, replaceUsingMap, EnqueuedMutationEffect, offlineEffectConfig as mutationsConfig } from \"./link/offline-link\";\n+import { CONTROL_EVENTS_KEY } from \"./link/subscription-handshake-link\";\n+\n+const logger = debug('aws-appsync:deltasync');\n+\n+//#region Types\n+type DeltaSyncUpdateLastSyncAction = AnyAction & {\n+    payload: {\n+        hash: string,\n+        lastSyncTimestamp: number,\n+        baseLastSyncTimestamp: number,\n+    }\n+};\n+\n+type SubscribeWithSyncEffectOptions<T, TVariables = OperationVariables> = SubscribeWithSyncOptions<T, TVariables> & {\n+    lastSyncTimestamp?: number,\n+    baseLastSyncTimestamp?: number,\n+};\n+\n+export type DeltaSyncEffect<T> = {\n+    options: SubscribeWithSyncEffectOptions<any, any>,\n+    observer: ZenObservable.SubscriptionObserver<T>,\n+    callback: (Subscription) => void,\n+};\n+\n+export const DELTASYNC_KEY = 'deltaSync';\n+export type DeltaSyncState = {\n+    metadata: {\n+        [key: string]: DeltaSyncStateMetadata\n+    }\n+};\n+export type DeltaSyncStateMetadata = {\n+    baseLastSyncTimestamp: number\n+    lastSyncTimestamp: number\n+};\n+\n+type SubscriptionMessagesProcessorCreator = (proxy: DataProxy, updateFunction: MutationUpdaterFn) => SubscriptionMessagesProcessor;\n+type SubscriptionMessagesProcessor = {\n+    enqueue: (x: any) => void,\n+    ready: () => void,\n+    close: () => void,\n+}\n+\n+type DeltaSyncReducer = () => (state: AppSyncMetadataState, action: AnyAction) => AppSyncMetadataState;\n+//#endregion\n+\n+//#region Constants\n+const actions = {\n+    ENQUEUE: 'DELTASYNC_ENQUEUE_RECONNECT',\n+    UPDATE_LASTSYNC: 'DELTASYNC_UPDATE_LASTSYNC',\n+};\n+const DEFAULT_UPPER_BOUND_TIME_MS = 24 * 60 * 60 * 1000;\n+const MIN_UPPER_BOUND_TIME_MS = 2 * 1000;\n+const BUFFER_MILLISECONDS = 2000;\n+//#endregion\n+\n+//#region helpers\n+const subscriptionMessagesProcessorCreator: SubscriptionMessagesProcessorCreator = (proxy, updateFunction) => {\n+    let buffer = [];\n+    let ready = false;\n+\n+    const wrappedUpdateFunction: MutationUpdaterFn = (proxy, record) => tryFunctionOrLogError(() => updateFunction(proxy, record))\n+\n+    const processor: SubscriptionMessagesProcessor = {\n+        enqueue: record => {\n+            if (ready) {\n+                wrappedUpdateFunction(proxy, record);\n+\n+                return;\n+            }\n+\n+            buffer.push(record);\n+        },\n+        ready: () => {\n+            if (ready) {\n+                return;\n+            }\n+\n+            buffer.forEach(record => wrappedUpdateFunction(proxy, record));\n+            buffer = [];\n+\n+            ready = true;\n+        },\n+        close: () => {\n+            buffer = [];\n+            ready = true;\n+        }\n+    };\n+\n+    return processor;\n+};\n+\n+export const hashForOptions = (options: SubscribeWithSyncOptions<any>) => {\n+    const {\n+        baseQuery: {\n+            query: baseQueryQuery = null,\n+            variables: baseQueryVariables = {},\n+        } = {},\n+        subscriptionQuery: {\n+            query: subscriptionQueryQuery = null,\n+            variables: subscriptionQueryVariables = {},\n+        } = {},\n+        deltaQuery: {\n+            query: deltaQueryQuery = null,\n+            variables: deltaQueryVariables = {},\n+        } = {},\n+    } = options;\n+\n+    const baseQuery = baseQueryQuery ? {\n+        query: print(baseQueryQuery),\n+        variables: baseQueryVariables,\n+    } : {};\n+    const subscriptionQuery = subscriptionQueryQuery ? {\n+        query: print(subscriptionQueryQuery),\n+        variables: subscriptionQueryVariables,\n+    } : {};\n+    const deltaQuery = deltaQueryQuery ? {\n+        query: print(deltaQueryQuery),\n+        variables: deltaQueryVariables,\n+    } : {};\n+\n+    return hash(JSON.stringify({\n+        baseQuery,\n+        subscriptionQuery,\n+        deltaQuery,\n+    }));\n+}\n+//#endregion\n+\n+//#region Redux\n+const effect = async <TCache extends NormalizedCacheObject>(\n+    store: Store<OfflineCache>,\n+    client: AWSAppSyncClient<TCache>,\n+    effect: DeltaSyncEffect<any>,\n+    _action: OfflineAction,\n+    _offlineCallback: OfflineCallback,\n+    offlineStatusChangeObservable: Observable<any>\n+): Promise<void> => {\n+    const { options, options: {\n+        baseQuery,\n+        subscriptionQuery,\n+        deltaQuery,\n+    }, observer, callback = () => { } } = effect;\n+\n+    if (!observer || typeof observer.next !== 'function' || observer.closed) {\n+        return;\n+    }\n+\n+    let upperBoundTimeMS = DEFAULT_UPPER_BOUND_TIME_MS;\n+\n+    let { lastSyncTimestamp, baseLastSyncTimestamp } = options;\n+    const hash = hashForOptions(options);\n+    const itemInHash = store.getState()[METADATA_KEY][DELTASYNC_KEY].metadata[hash];\n+\n+    let networkStatusSubscription: Subscription;\n+    let subscription: Subscription;\n+    let baseQueryTimeoutId: number;\n+    let subscriptionProcessor: SubscriptionMessagesProcessor;\n+    const unsubscribeAll = () => {\n+        logger('Unsubscribing');\n+\n+        if (networkStatusSubscription) networkStatusSubscription.unsubscribe();\n+\n+        if (subscription) subscription.unsubscribe();\n+\n+        if (baseQueryTimeoutId) clearTimeout(baseQueryTimeoutId);\n+\n+        if (subscriptionProcessor) subscriptionProcessor.close();\n+    };\n+\n+    const enqueueAgain = () => {\n+        unsubscribeAll();\n+\n+        logger('Re-queuing', { baseLastSyncTimestamp, lastSyncTimestamp });\n+        boundEnqueueDeltaSync(store, { ...options, lastSyncTimestamp, baseLastSyncTimestamp }, observer, callback);\n+    };\n+\n+    if (typeof callback === 'function') {\n+        let handle = new Observable(() => () => unsubscribeAll()).subscribe({ next: () => { } });\n+        callback(handle);\n+    }\n+\n+    networkStatusSubscription = new Observable(obs => {\n+        const handle = offlineStatusChangeObservable.subscribe({\n+            next: ({ online }) => {\n+                if (!online) {\n+                    obs.next(null);\n+                    obs.complete();\n+                }\n+            },\n+            complete: () => obs.complete(),\n+        });\n+\n+        return () => handle.unsubscribe();\n+    }).subscribe({\n+        next: () => {\n+            enqueueAgain();\n+        }\n+    });\n+\n+    const STOP_CACHE_RECORDING = Symbol('lawea');\n+    let recorderCacheWrites = [];\n+\n+    const cacheProxy = new Proxy(client.cache, {\n+        get: (target, name, receiver) => {\n+            switch (name) {\n+                case 'write':\n+                    return (options) => {\n+                        if (!receiver[STOP_CACHE_RECORDING]) {\n+                            recorderCacheWrites.push(options);\n+                        }\n+\n+                        return target[name](options);\n+                    }\n+            }\n+\n+            return target[name];\n+        }\n+    });\n+\n+    subscriptionProcessor = subscriptionMessagesProcessorCreator(cacheProxy, (proxy, record) => {\n+        const { update } = options.subscriptionQuery;\n+\n+        if (typeof update === 'function') {\n+            update(proxy, record);\n+\n+            client.queryManager.broadcastQueries();\n+        }\n+    });\n+\n+    try {\n+        let error;\n+\n+        const {\n+            [METADATA_KEY]: { idsMap, snapshot: { cache: cacheSnapshot } },\n+            offline: { outbox: enquededMutations }\n+        } = store.getState();\n+\n+        //#region Subscription\n+        const subsControlLogger = logger.extend('subsc-control');\n+\n+        await new Promise(resolve => {\n+            if (subscriptionQuery && subscriptionQuery.query) {\n+                const { query, variables } = subscriptionQuery;\n+                const waitForConnect = true;\n+\n+                subscription = client.subscribe<FetchResult, any>({\n+                    query: query,\n+                    variables: {\n+                        ...variables,\n+                        [SKIP_RETRY_KEY]: true,\n+                        ...(waitForConnect ? { [CONTROL_EVENTS_KEY]: true } : null),\n+                    },\n+                }).filter(data => {\n+                    const { extensions: { msgType = undefined, info = undefined } = {} } = data;\n+                    const isControlMsg = typeof msgType !== 'undefined';\n+\n+                    if (msgType) {\n+                        subsControlLogger(msgType, info);\n+\n+                        if (msgType === 'CONNECTED') {\n+                            resolve();\n+                        }\n+                    }\n+\n+                    return !isControlMsg;\n+                }).subscribe({\n+                    next: data => {\n+                        resolve();\n+\n+                        subscriptionProcessor.enqueue(data);\n+                    },\n+                    error: (err) => {\n+                        resolve();\n+\n+                        error = err;\n+                        unsubscribeAll();\n+\n+                        if (graphQLResultHasError(err) || err.graphQLErrors) {\n+                            // send error to observable, unsubscribe all, do not enqueue\n+                            observer.error(err);\n+                            return;\n+                        }\n+\n+                        enqueueAgain();\n+                    }\n+                });\n+\n+                if (!waitForConnect) {\n+                    resolve();\n+                }\n+            } else {\n+                resolve();\n+            }\n+        });\n+        //#endregion\n+\n+        const { refreshIntervalInSeconds } = baseQuery;\n+        upperBoundTimeMS = refreshIntervalInSeconds ? refreshIntervalInSeconds * 1000 : DEFAULT_UPPER_BOUND_TIME_MS;\n+\n+        const skipBaseQuery = !(baseQuery && baseQuery.query) || (baseLastSyncTimestamp\n+            ? Date.now() - baseLastSyncTimestamp < upperBoundTimeMS\n+            : itemInHash.baseLastSyncTimestamp && Date.now() - itemInHash.baseLastSyncTimestamp < upperBoundTimeMS);\n+\n+        //#region Base query\n+        if (baseQuery && baseQuery.query) {\n+            const { query, update, variables } = baseQuery;\n+\n+            logger(`${skipBaseQuery ? 'Skipping' : 'Running'} base query`, { baseLastSyncTimestamp, itemInHash });\n+            if (!skipBaseQuery) {\n+                const result = await client.query({\n+                    fetchPolicy: 'network-only',\n+                    query,\n+                    variables,\n+                });\n+                cacheProxy.writeQuery({ query, data: result.data });\n+\n+                if (typeof update === 'function') {\n+                    tryFunctionOrLogError(() => {\n+                        update(cacheProxy, result);\n+                    });\n+                }\n+\n+                baseLastSyncTimestamp = new Date().getTime() - BUFFER_MILLISECONDS;\n+                boundUpdateLastSync(store, { hash, baseLastSyncTimestamp });\n+            } else {\n+                const data = readQueryFromStore({","path":"packages/aws-appsync/src/deltaSync.ts","position":351,"original_position":351,"commit_id":"8fe7419086d450ccf3bf96062a55e267cf18449e","original_commit_id":"8fe7419086d450ccf3bf96062a55e267cf18449e","user":{"login":"manueliglesias","id":6154160,"node_id":"MDQ6VXNlcjYxNTQxNjA=","avatar_url":"https://avatars2.githubusercontent.com/u/6154160?v=4","gravatar_id":"","url":"https://api.github.com/users/manueliglesias","html_url":"https://github.com/manueliglesias","followers_url":"https://api.github.com/users/manueliglesias/followers","following_url":"https://api.github.com/users/manueliglesias/following{/other_user}","gists_url":"https://api.github.com/users/manueliglesias/gists{/gist_id}","starred_url":"https://api.github.com/users/manueliglesias/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/manueliglesias/subscriptions","organizations_url":"https://api.github.com/users/manueliglesias/orgs","repos_url":"https://api.github.com/users/manueliglesias/repos","events_url":"https://api.github.com/users/manueliglesias/events{/privacy}","received_events_url":"https://api.github.com/users/manueliglesias/received_events","type":"User","site_admin":false},"body":"It shouldn't fail, but I've added a try/catch block for this piece in case the baseQuery is not in the snapshot.","created_at":"2018-11-16T23:39:38Z","updated_at":"2018-11-16T23:39:39Z","html_url":"https://github.com/awslabs/aws-mobile-appsync-sdk-js/pull/293#discussion_r234378793","pull_request_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/pulls/293","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/pulls/comments/234378793"},"html":{"href":"https://github.com/awslabs/aws-mobile-appsync-sdk-js/pull/293#discussion_r234378793"},"pull_request":{"href":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/pulls/293"}},"in_reply_to_id":234358602},"pull_request":{"url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/pulls/293","id":231380281,"node_id":"MDExOlB1bGxSZXF1ZXN0MjMxMzgwMjgx","html_url":"https://github.com/awslabs/aws-mobile-appsync-sdk-js/pull/293","diff_url":"https://github.com/awslabs/aws-mobile-appsync-sdk-js/pull/293.diff","patch_url":"https://github.com/awslabs/aws-mobile-appsync-sdk-js/pull/293.patch","issue_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/issues/293","number":293,"state":"open","locked":false,"title":"feat(delta-sync): Add DeltaSync support","user":{"login":"manueliglesias","id":6154160,"node_id":"MDQ6VXNlcjYxNTQxNjA=","avatar_url":"https://avatars2.githubusercontent.com/u/6154160?v=4","gravatar_id":"","url":"https://api.github.com/users/manueliglesias","html_url":"https://github.com/manueliglesias","followers_url":"https://api.github.com/users/manueliglesias/followers","following_url":"https://api.github.com/users/manueliglesias/following{/other_user}","gists_url":"https://api.github.com/users/manueliglesias/gists{/gist_id}","starred_url":"https://api.github.com/users/manueliglesias/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/manueliglesias/subscriptions","organizations_url":"https://api.github.com/users/manueliglesias/orgs","repos_url":"https://api.github.com/users/manueliglesias/repos","events_url":"https://api.github.com/users/manueliglesias/events{/privacy}","received_events_url":"https://api.github.com/users/manueliglesias/received_events","type":"User","site_admin":false},"body":"*Issue #, if available:*\r\n\r\n*Description of changes:*\r\n\r\n\r\nBy submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.\r\n","created_at":"2018-11-16T00:33:16Z","updated_at":"2018-11-16T23:39:39Z","closed_at":null,"merged_at":null,"merge_commit_sha":"61e71fc6b800e895dcecd08d831d3746f3f77d93","assignee":null,"assignees":[],"requested_reviewers":[{"login":"undefobj","id":4294295,"node_id":"MDQ6VXNlcjQyOTQyOTU=","avatar_url":"https://avatars0.githubusercontent.com/u/4294295?v=4","gravatar_id":"","url":"https://api.github.com/users/undefobj","html_url":"https://github.com/undefobj","followers_url":"https://api.github.com/users/undefobj/followers","following_url":"https://api.github.com/users/undefobj/following{/other_user}","gists_url":"https://api.github.com/users/undefobj/gists{/gist_id}","starred_url":"https://api.github.com/users/undefobj/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/undefobj/subscriptions","organizations_url":"https://api.github.com/users/undefobj/orgs","repos_url":"https://api.github.com/users/undefobj/repos","events_url":"https://api.github.com/users/undefobj/events{/privacy}","received_events_url":"https://api.github.com/users/undefobj/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/pulls/293/commits","review_comments_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/pulls/293/comments","review_comment_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/pulls/comments{/number}","comments_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/issues/293/comments","statuses_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/statuses/8fe7419086d450ccf3bf96062a55e267cf18449e","head":{"label":"manueliglesias:feature/delta-sync","ref":"feature/delta-sync","sha":"8fe7419086d450ccf3bf96062a55e267cf18449e","user":{"login":"manueliglesias","id":6154160,"node_id":"MDQ6VXNlcjYxNTQxNjA=","avatar_url":"https://avatars2.githubusercontent.com/u/6154160?v=4","gravatar_id":"","url":"https://api.github.com/users/manueliglesias","html_url":"https://github.com/manueliglesias","followers_url":"https://api.github.com/users/manueliglesias/followers","following_url":"https://api.github.com/users/manueliglesias/following{/other_user}","gists_url":"https://api.github.com/users/manueliglesias/gists{/gist_id}","starred_url":"https://api.github.com/users/manueliglesias/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/manueliglesias/subscriptions","organizations_url":"https://api.github.com/users/manueliglesias/orgs","repos_url":"https://api.github.com/users/manueliglesias/repos","events_url":"https://api.github.com/users/manueliglesias/events{/privacy}","received_events_url":"https://api.github.com/users/manueliglesias/received_events","type":"User","site_admin":false},"repo":{"id":117590475,"node_id":"MDEwOlJlcG9zaXRvcnkxMTc1OTA0NzU=","name":"aws-mobile-appsync-sdk-js","full_name":"manueliglesias/aws-mobile-appsync-sdk-js","private":false,"owner":{"login":"manueliglesias","id":6154160,"node_id":"MDQ6VXNlcjYxNTQxNjA=","avatar_url":"https://avatars2.githubusercontent.com/u/6154160?v=4","gravatar_id":"","url":"https://api.github.com/users/manueliglesias","html_url":"https://github.com/manueliglesias","followers_url":"https://api.github.com/users/manueliglesias/followers","following_url":"https://api.github.com/users/manueliglesias/following{/other_user}","gists_url":"https://api.github.com/users/manueliglesias/gists{/gist_id}","starred_url":"https://api.github.com/users/manueliglesias/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/manueliglesias/subscriptions","organizations_url":"https://api.github.com/users/manueliglesias/orgs","repos_url":"https://api.github.com/users/manueliglesias/repos","events_url":"https://api.github.com/users/manueliglesias/events{/privacy}","received_events_url":"https://api.github.com/users/manueliglesias/received_events","type":"User","site_admin":false},"html_url":"https://github.com/manueliglesias/aws-mobile-appsync-sdk-js","description":"JavaScript library files for Offline, Sync, Sigv4. includes support for React Native","fork":true,"url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js","forks_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/forks","keys_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/keys{/key_id}","collaborators_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/teams","hooks_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/hooks","issue_events_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/issues/events{/number}","events_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/events","assignees_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/assignees{/user}","branches_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/branches{/branch}","tags_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/tags","blobs_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/git/refs{/sha}","trees_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/git/trees{/sha}","statuses_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/statuses/{sha}","languages_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/languages","stargazers_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/stargazers","contributors_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/contributors","subscribers_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/subscribers","subscription_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/subscription","commits_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/commits{/sha}","git_commits_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/git/commits{/sha}","comments_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/comments{/number}","issue_comment_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/issues/comments{/number}","contents_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/contents/{+path}","compare_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/compare/{base}...{head}","merges_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/merges","archive_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/downloads","issues_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/issues{/number}","pulls_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/pulls{/number}","milestones_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/milestones{/number}","notifications_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/labels{/name}","releases_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/releases{/id}","deployments_url":"https://api.github.com/repos/manueliglesias/aws-mobile-appsync-sdk-js/deployments","created_at":"2018-01-15T20:09:58Z","updated_at":"2018-08-20T20:43:26Z","pushed_at":"2018-11-15T22:08:43Z","git_url":"git://github.com/manueliglesias/aws-mobile-appsync-sdk-js.git","ssh_url":"git@github.com:manueliglesias/aws-mobile-appsync-sdk-js.git","clone_url":"https://github.com/manueliglesias/aws-mobile-appsync-sdk-js.git","svn_url":"https://github.com/manueliglesias/aws-mobile-appsync-sdk-js","homepage":null,"size":664,"stargazers_count":0,"watchers_count":0,"language":"TypeScript","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":1,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"awslabs:master","ref":"master","sha":"c4cfe8f1578bc2c29dd601141107a54cd823f0f7","user":{"login":"awslabs","id":3299148,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMyOTkxNDg=","avatar_url":"https://avatars0.githubusercontent.com/u/3299148?v=4","gravatar_id":"","url":"https://api.github.com/users/awslabs","html_url":"https://github.com/awslabs","followers_url":"https://api.github.com/users/awslabs/followers","following_url":"https://api.github.com/users/awslabs/following{/other_user}","gists_url":"https://api.github.com/users/awslabs/gists{/gist_id}","starred_url":"https://api.github.com/users/awslabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/awslabs/subscriptions","organizations_url":"https://api.github.com/users/awslabs/orgs","repos_url":"https://api.github.com/users/awslabs/repos","events_url":"https://api.github.com/users/awslabs/events{/privacy}","received_events_url":"https://api.github.com/users/awslabs/received_events","type":"Organization","site_admin":false},"repo":{"id":108162421,"node_id":"MDEwOlJlcG9zaXRvcnkxMDgxNjI0MjE=","name":"aws-mobile-appsync-sdk-js","full_name":"awslabs/aws-mobile-appsync-sdk-js","private":false,"owner":{"login":"awslabs","id":3299148,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMyOTkxNDg=","avatar_url":"https://avatars0.githubusercontent.com/u/3299148?v=4","gravatar_id":"","url":"https://api.github.com/users/awslabs","html_url":"https://github.com/awslabs","followers_url":"https://api.github.com/users/awslabs/followers","following_url":"https://api.github.com/users/awslabs/following{/other_user}","gists_url":"https://api.github.com/users/awslabs/gists{/gist_id}","starred_url":"https://api.github.com/users/awslabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/awslabs/subscriptions","organizations_url":"https://api.github.com/users/awslabs/orgs","repos_url":"https://api.github.com/users/awslabs/repos","events_url":"https://api.github.com/users/awslabs/events{/privacy}","received_events_url":"https://api.github.com/users/awslabs/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/awslabs/aws-mobile-appsync-sdk-js","description":"JavaScript library files for Offline, Sync, Sigv4. includes support for React Native","fork":false,"url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js","forks_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/forks","keys_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/keys{/key_id}","collaborators_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/teams","hooks_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/hooks","issue_events_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/issues/events{/number}","events_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/events","assignees_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/assignees{/user}","branches_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/branches{/branch}","tags_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/tags","blobs_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/git/refs{/sha}","trees_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/git/trees{/sha}","statuses_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/statuses/{sha}","languages_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/languages","stargazers_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/stargazers","contributors_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/contributors","subscribers_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/subscribers","subscription_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/subscription","commits_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/commits{/sha}","git_commits_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/git/commits{/sha}","comments_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/comments{/number}","issue_comment_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/issues/comments{/number}","contents_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/contents/{+path}","compare_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/compare/{base}...{head}","merges_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/merges","archive_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/downloads","issues_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/issues{/number}","pulls_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/pulls{/number}","milestones_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/milestones{/number}","notifications_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/labels{/name}","releases_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/releases{/id}","deployments_url":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/deployments","created_at":"2017-10-24T17:42:46Z","updated_at":"2018-11-16T19:32:25Z","pushed_at":"2018-11-16T18:32:11Z","git_url":"git://github.com/awslabs/aws-mobile-appsync-sdk-js.git","ssh_url":"git@github.com:awslabs/aws-mobile-appsync-sdk-js.git","clone_url":"https://github.com/awslabs/aws-mobile-appsync-sdk-js.git","svn_url":"https://github.com/awslabs/aws-mobile-appsync-sdk-js","homepage":null,"size":593,"stargazers_count":420,"watchers_count":420,"language":"TypeScript","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":89,"mirror_url":null,"archived":false,"open_issues_count":50,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":89,"open_issues":50,"watchers":420,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/pulls/293"},"html":{"href":"https://github.com/awslabs/aws-mobile-appsync-sdk-js/pull/293"},"issue":{"href":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/issues/293"},"comments":{"href":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/issues/293/comments"},"review_comments":{"href":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/pulls/293/comments"},"review_comment":{"href":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/pulls/293/commits"},"statuses":{"href":"https://api.github.com/repos/awslabs/aws-mobile-appsync-sdk-js/statuses/8fe7419086d450ccf3bf96062a55e267cf18449e"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"manueliglesias"}}