apollo-client
Advanced tools
Comparing version 0.4.5 to 0.4.6
"use strict"; | ||
var isArray = require('lodash.isarray'); | ||
var isNull = require('lodash.isnull'); | ||
var isString = require('lodash.isstring'); | ||
var has = require('lodash.has'); | ||
var assign = require('lodash.assign'); | ||
var storeUtils_1 = require('./storeUtils'); | ||
var store_1 = require('./store'); | ||
var getFromAST_1 = require('../queries/getFromAST'); | ||
@@ -149,5 +149,12 @@ var directives_1 = require('../queries/directives'); | ||
if (!field.selectionSet) { | ||
return { | ||
result: storeValue, | ||
}; | ||
if (store_1.isJsonValue(storeValue)) { | ||
return { | ||
result: storeValue.json, | ||
}; | ||
} | ||
else { | ||
return { | ||
result: storeValue, | ||
}; | ||
} | ||
} | ||
@@ -183,7 +190,8 @@ if (isNull(storeValue)) { | ||
} | ||
if (isString(storeValue)) { | ||
if (store_1.isIdValue(storeValue)) { | ||
var unescapedId = storeValue.id; | ||
return diffSelectionSetAgainstStore({ | ||
store: store, | ||
throwOnMissingField: throwOnMissingField, | ||
rootId: storeValue, | ||
rootId: unescapedId, | ||
selectionSet: field.selectionSet, | ||
@@ -194,4 +202,4 @@ variables: variables, | ||
} | ||
throw new Error('Unexpected number value in the store where the query had a subselection.'); | ||
throw new Error('Unexpected value in the store where the query had a subselection.'); | ||
} | ||
//# sourceMappingURL=diffAgainstStore.js.map |
@@ -12,3 +12,14 @@ import { ApolloAction } from '../actions'; | ||
} | ||
export declare type StoreValue = number | string | string[]; | ||
export interface IdValue { | ||
type: "id"; | ||
id: string; | ||
generated: boolean; | ||
} | ||
export interface JsonValue { | ||
type: "json"; | ||
json: any; | ||
} | ||
export declare type StoreValue = number | string | string[] | IdValue | JsonValue; | ||
export declare function isIdValue(idObject: StoreValue): idObject is IdValue; | ||
export declare function isJsonValue(jsonObject: StoreValue): jsonObject is JsonValue; | ||
export declare function data(previousState: NormalizedCache, action: ApolloAction, queries: QueryStore, mutations: MutationStore, config: ApolloReducerConfig): NormalizedCache; |
@@ -5,4 +5,13 @@ "use strict"; | ||
var assign = require('lodash.assign'); | ||
var isObject = require('lodash.isobject'); | ||
var storeUtils_1 = require('./storeUtils'); | ||
var mutationResults_1 = require('./mutationResults'); | ||
function isIdValue(idObject) { | ||
return (isObject(idObject) && idObject.type === 'id'); | ||
} | ||
exports.isIdValue = isIdValue; | ||
function isJsonValue(jsonObject) { | ||
return (isObject(jsonObject) && jsonObject.type === 'json'); | ||
} | ||
exports.isJsonValue = isJsonValue; | ||
function data(previousState, action, queries, mutations, config) { | ||
@@ -9,0 +18,0 @@ if (previousState === void 0) { previousState = {}; } |
@@ -5,6 +5,9 @@ "use strict"; | ||
var isUndefined = require('lodash.isundefined'); | ||
var isObject = require('lodash.isobject'); | ||
var assign = require('lodash.assign'); | ||
var getFromAST_1 = require('../queries/getFromAST'); | ||
var storeUtils_1 = require('./storeUtils'); | ||
var store_1 = require('./store'); | ||
var directives_1 = require('../queries/directives'); | ||
var errors_1 = require('../errors'); | ||
function writeFragmentToStore(_a) { | ||
@@ -101,2 +104,20 @@ var result = _a.result, fragment = _a.fragment, _b = _a.store, store = _b === void 0 ? {} : _b, variables = _a.variables, _c = _a.dataIdFromObject, dataIdFromObject = _c === void 0 ? null : _c; | ||
exports.writeSelectionSetToStore = writeSelectionSetToStore; | ||
function isGeneratedId(id) { | ||
return (id[0] === '$'); | ||
} | ||
function mergeWithGenerated(generatedKey, realKey, cache) { | ||
var generated = cache[generatedKey]; | ||
var real = cache[realKey]; | ||
Object.keys(generated).forEach(function (key) { | ||
var value = generated[key]; | ||
var realValue = real[key]; | ||
if (store_1.isIdValue(value) | ||
&& isGeneratedId(value.id) | ||
&& store_1.isIdValue(realValue)) { | ||
mergeWithGenerated(value.id, realValue.id, cache); | ||
} | ||
delete cache[generatedKey]; | ||
cache[realKey] = assign({}, generated, real); | ||
}); | ||
} | ||
function writeFieldToStore(_a) { | ||
@@ -106,5 +127,13 @@ var field = _a.field, value = _a.value, variables = _a.variables, store = _a.store, dataId = _a.dataId, dataIdFromObject = _a.dataIdFromObject, fragmentMap = _a.fragmentMap; | ||
var storeFieldName = storeUtils_1.storeKeyNameFromField(field, variables); | ||
if (!field.selectionSet || isNull(value)) { | ||
var shouldMerge = false; | ||
var generatedKey; | ||
if ((!field.selectionSet || isNull(value)) && !isObject(value)) { | ||
storeValue = value; | ||
} | ||
else if ((!field.selectionSet || isNull(value)) && isObject(value)) { | ||
storeValue = { | ||
type: 'json', | ||
json: value, | ||
}; | ||
} | ||
else if (isArray(value)) { | ||
@@ -140,6 +169,14 @@ var thisIdList_1 = []; | ||
var valueDataId = dataId + "." + storeFieldName; | ||
var generated = true; | ||
if (!isGeneratedId(valueDataId)) { | ||
valueDataId = '$' + valueDataId; | ||
} | ||
if (dataIdFromObject) { | ||
var semanticId = dataIdFromObject(value); | ||
if (semanticId && isGeneratedId(semanticId)) { | ||
throw new Error('IDs returned by dataIdFromObject cannot begin with the "$" character.'); | ||
} | ||
if (semanticId) { | ||
valueDataId = semanticId; | ||
generated = false; | ||
} | ||
@@ -156,3 +193,21 @@ } | ||
}); | ||
storeValue = valueDataId; | ||
storeValue = { | ||
type: 'id', | ||
id: valueDataId, | ||
generated: generated, | ||
}; | ||
if (store[dataId] && store[dataId][storeFieldName] !== storeValue) { | ||
var escapedId = store[dataId][storeFieldName]; | ||
if (store_1.isIdValue(storeValue) && storeValue.generated | ||
&& store_1.isIdValue(escapedId) && !escapedId.generated) { | ||
throw new errors_1.ApolloError({ | ||
errorMessage: "Store error: the application attempted to write an object with no provided id" + | ||
(" but the store already contains an id of " + escapedId.id + " for this object."), | ||
}); | ||
} | ||
if (store_1.isIdValue(escapedId) && escapedId.generated) { | ||
generatedKey = escapedId.id; | ||
shouldMerge = true; | ||
} | ||
} | ||
} | ||
@@ -163,2 +218,5 @@ var newStoreObj = assign({}, store[dataId], (_b = {}, | ||
)); | ||
if (shouldMerge) { | ||
mergeWithGenerated(generatedKey, storeValue.id, store); | ||
} | ||
if (!store[dataId] || storeValue !== store[dataId][storeFieldName]) { | ||
@@ -165,0 +223,0 @@ store[dataId] = newStoreObj; |
@@ -6,4 +6,4 @@ import { NetworkInterface, createNetworkInterface, addQueryMerging } from './networkInterface'; | ||
import { QueryManager } from './QueryManager'; | ||
import { ObservableQuery } from '../src/ObservableQuery'; | ||
import { WatchQueryOptions } from '../src/watchQueryOptions'; | ||
import { ObservableQuery } from './ObservableQuery'; | ||
import { WatchQueryOptions } from './watchQueryOptions'; | ||
import { readQueryFromStore, readFragmentFromStore } from './data/readFromStore'; | ||
@@ -10,0 +10,0 @@ import { writeQueryToStore, writeFragmentToStore } from './data/writeToStore'; |
@@ -0,5 +1,5 @@ | ||
import { WatchQueryOptions } from './watchQueryOptions'; | ||
import { Observable } from './util/Observable'; | ||
import { QueryScheduler } from './scheduler'; | ||
import { ApolloQueryResult } from './index'; | ||
import { WatchQueryOptions } from './watchQueryOptions'; | ||
import { QueryManager } from './QueryManager'; | ||
export declare class ObservableQuery extends Observable<ApolloQueryResult> { | ||
@@ -10,6 +10,7 @@ refetch: (variables?: any) => Promise<ApolloQueryResult>; | ||
options: WatchQueryOptions; | ||
queryManager: QueryManager; | ||
queryId: string; | ||
constructor({queryManager, options, shouldSubscribe}: { | ||
queryManager: QueryManager; | ||
private queryId; | ||
private scheduler; | ||
private queryManager; | ||
constructor({scheduler, options, shouldSubscribe}: { | ||
scheduler: QueryScheduler; | ||
options: WatchQueryOptions; | ||
@@ -16,0 +17,0 @@ shouldSubscribe?: boolean; |
@@ -7,4 +7,4 @@ "use strict"; | ||
}; | ||
var Observable_1 = require('./util/Observable'); | ||
var assign = require('lodash.assign'); | ||
var Observable_1 = require('./util/Observable'); | ||
var ObservableQuery = (function (_super) { | ||
@@ -14,7 +14,12 @@ __extends(ObservableQuery, _super); | ||
var _this = this; | ||
var queryManager = _a.queryManager, options = _a.options, _b = _a.shouldSubscribe, shouldSubscribe = _b === void 0 ? true : _b; | ||
var scheduler = _a.scheduler, options = _a.options, _b = _a.shouldSubscribe, shouldSubscribe = _b === void 0 ? true : _b; | ||
var queryManager = scheduler.queryManager; | ||
var queryId = queryManager.generateQueryId(); | ||
var isPollingQuery = !!options.pollInterval; | ||
var subscriberFunction = function (observer) { | ||
var retQuerySubscription = { | ||
unsubscribe: function () { | ||
if (isPollingQuery) { | ||
scheduler.stopPollingQuery(queryId); | ||
} | ||
queryManager.stopQuery(queryId); | ||
@@ -27,2 +32,8 @@ }, | ||
} | ||
if (isPollingQuery) { | ||
if (options.noFetch) { | ||
throw new Error('noFetch option should not use query polling.'); | ||
} | ||
_this.scheduler.startPollingQuery(options, queryId); | ||
} | ||
queryManager.startQuery(queryId, options, queryManager.queryListenerForObserver(queryId, options, observer)); | ||
@@ -33,2 +44,3 @@ return retQuerySubscription; | ||
this.options = options; | ||
this.scheduler = scheduler; | ||
this.queryManager = queryManager; | ||
@@ -47,4 +59,5 @@ this.queryId = queryId; | ||
this.stopPolling = function () { | ||
if (_this.queryManager.pollingTimers[_this.queryId]) { | ||
clearInterval(_this.queryManager.pollingTimers[_this.queryId]); | ||
_this.queryManager.stopQuery(_this.queryId); | ||
if (isPollingQuery) { | ||
_this.scheduler.stopPollingQuery(_this.queryId); | ||
} | ||
@@ -56,7 +69,7 @@ }; | ||
} | ||
_this.queryManager.pollingTimers[_this.queryId] = setInterval(function () { | ||
var pollingOptions = assign({}, _this.options); | ||
pollingOptions.forceFetch = true; | ||
_this.queryManager.fetchQuery(_this.queryId, pollingOptions); | ||
}, pollInterval); | ||
if (isPollingQuery) { | ||
_this.scheduler.stopPollingQuery(_this.queryId); | ||
} | ||
options.pollInterval = pollInterval; | ||
_this.scheduler.startPollingQuery(_this.options, _this.queryId, false); | ||
}; | ||
@@ -63,0 +76,0 @@ } |
{ | ||
"name": "apollo-client", | ||
"version": "0.4.5", | ||
"version": "0.4.6", | ||
"description": "A simple yet functional GraphQL client.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -8,2 +8,3 @@ import { NetworkInterface } from './networkInterface'; | ||
import { MutationBehavior, MutationQueryReducersMap } from './data/mutationResults'; | ||
import { QueryScheduler } from './scheduler'; | ||
import { ApolloQueryResult } from './index'; | ||
@@ -18,2 +19,3 @@ import { Observer, Subscription } from './util/Observable'; | ||
}; | ||
scheduler: QueryScheduler; | ||
private networkInterface; | ||
@@ -26,3 +28,2 @@ private store; | ||
private idCounter; | ||
private scheduler; | ||
private batcher; | ||
@@ -29,0 +30,0 @@ private batchInterval; |
"use strict"; | ||
var forOwn = require('lodash.forown'); | ||
var assign = require('lodash.assign'); | ||
var isEqual = require('lodash.isequal'); | ||
@@ -126,18 +125,25 @@ var store_1 = require('./store'); | ||
else { | ||
var resultFromStore = { | ||
data: readFromStore_1.readSelectionSetFromStore({ | ||
store: _this.getDataWithOptimisticResults(), | ||
rootId: queryStoreValue.query.id, | ||
selectionSet: queryStoreValue.query.selectionSet, | ||
variables: queryStoreValue.variables, | ||
returnPartialData: options.returnPartialData || options.noFetch, | ||
fragmentMap: queryStoreValue.fragmentMap, | ||
}), | ||
}; | ||
if (observer.next) { | ||
if (_this.isDifferentResult(queryId, resultFromStore)) { | ||
_this.queryResults[queryId] = resultFromStore; | ||
observer.next(resultFromStore); | ||
try { | ||
var resultFromStore = { | ||
data: readFromStore_1.readSelectionSetFromStore({ | ||
store: _this.getDataWithOptimisticResults(), | ||
rootId: queryStoreValue.query.id, | ||
selectionSet: queryStoreValue.query.selectionSet, | ||
variables: queryStoreValue.variables, | ||
returnPartialData: options.returnPartialData || options.noFetch, | ||
fragmentMap: queryStoreValue.fragmentMap, | ||
}), | ||
}; | ||
if (observer.next) { | ||
if (_this.isDifferentResult(queryId, resultFromStore)) { | ||
_this.queryResults[queryId] = resultFromStore; | ||
observer.next(resultFromStore); | ||
} | ||
} | ||
} | ||
catch (error) { | ||
if (observer.error) { | ||
observer.error(error); | ||
} | ||
} | ||
} | ||
@@ -151,3 +157,3 @@ } | ||
var observableQuery = new ObservableQuery_1.ObservableQuery({ | ||
queryManager: this, | ||
scheduler: this.scheduler, | ||
options: options, | ||
@@ -247,14 +253,5 @@ shouldSubscribe: shouldSubscribe, | ||
QueryManager.prototype.startQuery = function (queryId, options, listener) { | ||
var _this = this; | ||
this.queryListeners[queryId] = listener; | ||
this.fetchQuery(queryId, options); | ||
if (options.pollInterval) { | ||
if (options.noFetch) { | ||
throw new Error('noFetch option should not use query polling.'); | ||
} | ||
this.pollingTimers[queryId] = setInterval(function () { | ||
var pollingOptions = assign({}, options); | ||
pollingOptions.forceFetch = true; | ||
_this.fetchQuery(queryId, pollingOptions); | ||
}, options.pollInterval); | ||
if (!options.pollInterval) { | ||
this.fetchQuery(queryId, options); | ||
} | ||
@@ -265,9 +262,3 @@ return queryId; | ||
delete this.queryListeners[queryId]; | ||
if (this.pollingTimers[queryId]) { | ||
clearInterval(this.pollingTimers[queryId]); | ||
} | ||
this.store.dispatch({ | ||
type: 'APOLLO_QUERY_STOP', | ||
queryId: queryId, | ||
}); | ||
this.stopQueryInStore(queryId); | ||
}; | ||
@@ -274,0 +265,0 @@ QueryManager.prototype.collectResultBehaviorsFromUpdateQueries = function (updateQueries, mutationResult, isOptimistic) { |
@@ -8,3 +8,9 @@ import { QueryManager, QueryListener } from './QueryManager'; | ||
}; | ||
private queryManager; | ||
registeredQueries: { | ||
[queryId: string]: WatchQueryOptions; | ||
}; | ||
intervalQueries: { | ||
[interval: number]: string[]; | ||
}; | ||
queryManager: QueryManager; | ||
private pollingTimers; | ||
@@ -16,7 +22,9 @@ constructor({queryManager}: { | ||
fetchQuery(queryId: string, options: WatchQueryOptions): Promise<{}>; | ||
startPollingQuery(options: WatchQueryOptions, listener: QueryListener, queryId?: string): string; | ||
startPollingQuery(options: WatchQueryOptions, queryId?: string, firstFetch?: boolean, listener?: QueryListener): string; | ||
stopPollingQuery(queryId: string): void; | ||
registerPollingQuery(options: WatchQueryOptions): ObservableQuery; | ||
fetchQueriesOnInterval(interval: number): void; | ||
addQueryOnInterval(queryId: string, queryOptions: WatchQueryOptions): void; | ||
registerPollingQuery(queryOptions: WatchQueryOptions): ObservableQuery; | ||
private addInFlight(queryId, options); | ||
private removeInFlight(queryId); | ||
} |
@@ -10,2 +10,4 @@ "use strict"; | ||
this.inFlightQueries = {}; | ||
this.registeredQueries = {}; | ||
this.intervalQueries = {}; | ||
} | ||
@@ -28,32 +30,59 @@ QueryScheduler.prototype.checkInFlight = function (queryId) { | ||
}; | ||
QueryScheduler.prototype.startPollingQuery = function (options, listener, queryId) { | ||
var _this = this; | ||
if (!queryId) { | ||
queryId = this.queryManager.generateQueryId(); | ||
QueryScheduler.prototype.startPollingQuery = function (options, queryId, firstFetch, listener) { | ||
if (firstFetch === void 0) { firstFetch = true; } | ||
if (!options.pollInterval) { | ||
throw new Error('Attempted to start a polling query without a polling interval.'); | ||
} | ||
this.fetchQuery(queryId, options); | ||
this.queryManager.addQueryListener(queryId, listener); | ||
this.pollingTimers[queryId] = setInterval(function () { | ||
var pollingOptions = assign({}, options); | ||
pollingOptions.forceFetch = true; | ||
if (!_this.checkInFlight(queryId)) { | ||
_this.fetchQuery(queryId, pollingOptions); | ||
} | ||
}, options.pollInterval); | ||
this.registeredQueries[queryId] = options; | ||
if (firstFetch) { | ||
this.fetchQuery(queryId, options); | ||
} | ||
if (listener) { | ||
this.queryManager.addQueryListener(queryId, listener); | ||
} | ||
this.addQueryOnInterval(queryId, options); | ||
return queryId; | ||
}; | ||
QueryScheduler.prototype.stopPollingQuery = function (queryId) { | ||
this.queryManager.removeQueryListener(queryId); | ||
if (this.pollingTimers[queryId]) { | ||
clearInterval(this.pollingTimers[queryId]); | ||
delete this.registeredQueries[queryId]; | ||
}; | ||
QueryScheduler.prototype.fetchQueriesOnInterval = function (interval) { | ||
var _this = this; | ||
this.intervalQueries[interval] = this.intervalQueries[interval].filter(function (queryId) { | ||
if (!_this.registeredQueries.hasOwnProperty(queryId)) { | ||
return false; | ||
} | ||
if (_this.checkInFlight(queryId)) { | ||
return true; | ||
} | ||
var queryOptions = _this.registeredQueries[queryId]; | ||
var pollingOptions = assign({}, queryOptions); | ||
pollingOptions.forceFetch = true; | ||
_this.fetchQuery(queryId, pollingOptions); | ||
return true; | ||
}); | ||
if (this.intervalQueries[interval].length === 0) { | ||
clearInterval(this.pollingTimers[interval]); | ||
} | ||
this.queryManager.stopQueryInStore(queryId); | ||
}; | ||
QueryScheduler.prototype.registerPollingQuery = function (options) { | ||
if (!options.pollInterval) { | ||
throw new Error('Tried to register a non-polling query with the scheduler.'); | ||
QueryScheduler.prototype.addQueryOnInterval = function (queryId, queryOptions) { | ||
var _this = this; | ||
var interval = queryOptions.pollInterval; | ||
if (this.intervalQueries.hasOwnProperty(interval.toString())) { | ||
this.intervalQueries[interval].push(queryId); | ||
} | ||
else { | ||
this.intervalQueries[interval] = [queryId]; | ||
this.pollingTimers[interval] = setInterval(function () { | ||
_this.fetchQueriesOnInterval(interval); | ||
}, interval); | ||
} | ||
}; | ||
QueryScheduler.prototype.registerPollingQuery = function (queryOptions) { | ||
if (!queryOptions.pollInterval) { | ||
throw new Error('Attempted to register a non-polling query with the scheduler.'); | ||
} | ||
return new ObservableQuery_1.ObservableQuery({ | ||
queryManager: this.queryManager, | ||
options: options, | ||
scheduler: this, | ||
options: queryOptions, | ||
}); | ||
@@ -60,0 +89,0 @@ }; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
235914
3466